[PATCH 15/18] include: add blocking notifier aliases

2023-11-10 Thread Ahmad Fatoum
All notifiers are blocking in barebox, but to avoid needless mechanical
fixups during porting, just provide the stubs in a new
 header. While at it, also provide NOTIFY_DONE and
NOTIFY_DONE for use in the notifier callbacks.

Signed-off-by: Ahmad Fatoum 
---
 include/linux/notifier.h | 16 
 include/notifier.h   |  3 +++
 2 files changed, 19 insertions(+)
 create mode 100644 include/linux/notifier.h

diff --git a/include/linux/notifier.h b/include/linux/notifier.h
new file mode 100644
index ..25f4921a3e80
--- /dev/null
+++ b/include/linux/notifier.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __LINUX_NOTIFIER_H
+#define __LINUX_NOTIFIER_H
+
+#include 
+
+#define BLOCKING_NOTIFIER_HEAD NOTIFIER_HEAD
+
+#define blocking_notifier_call_chain   notifier_call_chain
+
+#define blocking_notifier_head notifier_head
+
+#define blocking_notifier_chain_register   notifier_chain_register
+#define blocking_notifier_chain_unregister notifier_chain_unregister
+
+#endif
diff --git a/include/notifier.h b/include/notifier.h
index 432b66c4ca5a..093fedb0e8e4 100644
--- a/include/notifier.h
+++ b/include/notifier.h
@@ -35,4 +35,7 @@ int clock_notifier_call_chain(void);
.blocks = LIST_HEAD_INIT((name).blocks),\
};
 
+#define NOTIFY_DONE0x  /* Don't care */
+#define NOTIFY_OK  0x0001  /* Suits me */
+
 #endif /* __NOTIFIER_H */
-- 
2.39.2




[PATCH 14/18] include: implement dev_warn_once and friends

2023-11-10 Thread Ahmad Fatoum
We already have pr_once, so duplicate it for dev_warn and friends as
well.

Signed-off-by: Ahmad Fatoum 
---
 drivers/firmware/arm_scmi/driver.c |  4 ++--
 include/linux/printk.h | 29 -
 2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/firmware/arm_scmi/driver.c 
b/drivers/firmware/arm_scmi/driver.c
index c3536d6e9fbd..98f672746527 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -988,7 +988,7 @@ static void scmi_create_protocol_devices(struct device_node 
*np,
  */
 int scmi_protocol_device_request(const struct scmi_device_id *id_table)
 {
-   int ret = 0;
+   int id, ret = 0;
struct list_head *phead = NULL;
struct scmi_requested_dev *rdev;
struct scmi_info *info;
@@ -1001,7 +1001,7 @@ int scmi_protocol_device_request(const struct 
scmi_device_id *id_table)
 * Search for the matching protocol rdev list and then search
 * of any existent equally named device...fails if any duplicate found.
 */
-   idr_for_each_entry(_requested_devices, idr) {
+   idr_for_each_entry(_requested_devices, idr, id) {
struct list_head *head = idr->ptr;
if (!phead) {
/* A list found registered in the IDR is never empty */
diff --git a/include/linux/printk.h b/include/linux/printk.h
index cd4c3cb68edb..0e9604bbe967 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -57,7 +57,15 @@ static inline int pr_print(int level, const char *format, 
...)
(level) <= LOGLEVEL ? dev_printf((level), (dev), (format), 
##args) : 0; \
 })
 
-
+#define __dev_printf_once(level, dev, format, args...) do {\
+   static bool __print_once;   \
+   \
+   if (!__print_once && (level) <= LOGLEVEL) { \
+   __print_once = true;\
+   dev_printf((level), (dev), (format), ##args);   \
+   }   \
+} while (0)
+ 
 #define dev_emerg(dev, format, arg...) \
__dev_printf(0, (dev) , format , ## arg)
 #define dev_alert(dev, format, arg...) \
@@ -77,6 +85,25 @@ static inline int pr_print(int level, const char *format, 
...)
 #define dev_vdbg(dev, format, arg...)  \
__dev_printf(8, (dev) , format , ## arg)
 
+#define dev_emerg_once(dev, format, arg...)\
+   __dev_printf_once(0, (dev) , format , ## arg)
+#define dev_alert_once(dev, format, arg...)\
+   __dev_printf_once(1, (dev) , format , ## arg)
+#define dev_crit_once(dev, format, arg...) \
+   __dev_printf_once(2, (dev) , format , ## arg)
+#define dev_err_once(dev, format, arg...)  \
+   __dev_prin_oncetf(3, (dev) , format , ## arg)
+#define dev_warn_once(dev, format, arg...) \
+   __dev_printf_once(4, (dev) , format , ## arg)
+#define dev_notice_once(dev, format, arg...)   \
+   __dev_printf(_once5, (dev) , format , ## arg)
+#define dev_info_once(dev, format, arg...) \
+   __dev_printf_once(6, (dev) , format , ## arg)
+#define dev_dbg_once(dev, format, arg...)  \
+   __dev_prin_oncetf(7, (dev) , format , ## arg)
+#define dev_vdbg_once(dev, format, arg...) \
+   __dev_printf_once(8, (dev) , format , ## arg)
+
 #if LOGLEVEL >= MSG_ERR
 int dev_err_probe(struct device *dev, int err, const char *fmt, ...)
__attribute__ ((format(__printf__, 3, 4)));
-- 
2.39.2




[PATCH 16/18] include: add Linux ktime API

2023-11-10 Thread Ahmad Fatoum
With get_time_ns(), we already have a monotonically increasing nanosecond
counter, so let's define ktime_get() as an alias for it and import the
Linux helpers for doing arithmetic with this ktime_t type.

There is a slight mismatch here as get_time_ns() returns a u64, while
ktime_t is signed, but U64_MAX is > 580 years and half of that is still
a fair bit longer than the expected life time of a device idling with
100% CPU in the barebox shell after an aborted boot.

Signed-off-by: Ahmad Fatoum 
---
 include/linux/ktime.h | 212 ++
 1 file changed, 212 insertions(+)
 create mode 100644 include/linux/ktime.h

diff --git a/include/linux/ktime.h b/include/linux/ktime.h
new file mode 100644
index ..ea368b8802e7
--- /dev/null
+++ b/include/linux/ktime.h
@@ -0,0 +1,212 @@
+/*
+ *  include/linux/ktime.h
+ *
+ *  ktime_t - nanosecond-resolution time format.
+ *
+ *   Copyright(C) 2005, Thomas Gleixner 
+ *   Copyright(C) 2005, Red Hat, Inc., Ingo Molnar
+ *
+ *  data type definitions, declarations, prototypes and macros.
+ *
+ *  Started by: Thomas Gleixner and Ingo Molnar
+ *
+ *  Credits:
+ *
+ * Roman Zippel provided the ideas and primary code snippets of
+ * the ktime_t union and further simplifications of the original
+ * code.
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+#ifndef _LINUX_KTIME_H
+#define _LINUX_KTIME_H
+
+#include 
+#include 
+#include 
+
+#define KTIME_MAX  ((s64)~((u64)1 << 63))
+#define KTIME_MIN  (-KTIME_MAX - 1)
+#define KTIME_SEC_MAX  (KTIME_MAX / NSEC_PER_SEC)
+#define KTIME_SEC_MIN  (KTIME_MIN / NSEC_PER_SEC)
+
+/* Nanosecond scalar representation for kernel time values */
+typedef s64ktime_t;
+
+/**
+ * ktime_set - Set a ktime_t variable from a seconds/nanoseconds value
+ * @secs:  seconds to set
+ * @nsecs: nanoseconds to set
+ *
+ * Return: The ktime_t representation of the value.
+ */
+static inline ktime_t ktime_set(const s64 secs, const unsigned long nsecs)
+{
+   if (unlikely(secs >= KTIME_SEC_MAX))
+   return KTIME_MAX;
+
+   return secs * NSEC_PER_SEC + (s64)nsecs;
+}
+
+/* Subtract two ktime_t variables. rem = lhs -rhs: */
+#define ktime_sub(lhs, rhs)((lhs) - (rhs))
+
+/* Add two ktime_t variables. res = lhs + rhs: */
+#define ktime_add(lhs, rhs)((lhs) + (rhs))
+
+/*
+ * Same as ktime_add(), but avoids undefined behaviour on overflow; however,
+ * this means that you must check the result for overflow yourself.
+ */
+#define ktime_add_unsafe(lhs, rhs) ((u64) (lhs) + (rhs))
+
+/*
+ * Add a ktime_t variable and a scalar nanosecond value.
+ * res = kt + nsval:
+ */
+#define ktime_add_ns(kt, nsval)((kt) + (nsval))
+
+/*
+ * Subtract a scalar nanosecod from a ktime_t variable
+ * res = kt - nsval:
+ */
+#define ktime_sub_ns(kt, nsval)((kt) - (nsval))
+
+/* Convert ktime_t to nanoseconds */
+static inline s64 ktime_to_ns(const ktime_t kt)
+{
+   return kt;
+}
+
+/**
+ * ktime_compare - Compares two ktime_t variables for less, greater or equal
+ * @cmp1:  comparable1
+ * @cmp2:  comparable2
+ *
+ * Return: ...
+ *   cmp1  < cmp2: return <0
+ *   cmp1 == cmp2: return 0
+ *   cmp1  > cmp2: return >0
+ */
+static inline int ktime_compare(const ktime_t cmp1, const ktime_t cmp2)
+{
+   if (cmp1 < cmp2)
+   return -1;
+   if (cmp1 > cmp2)
+   return 1;
+   return 0;
+}
+
+/**
+ * ktime_after - Compare if a ktime_t value is bigger than another one.
+ * @cmp1:  comparable1
+ * @cmp2:  comparable2
+ *
+ * Return: true if cmp1 happened after cmp2.
+ */
+static inline bool ktime_after(const ktime_t cmp1, const ktime_t cmp2)
+{
+   return ktime_compare(cmp1, cmp2) > 0;
+}
+
+/**
+ * ktime_before - Compare if a ktime_t value is smaller than another one.
+ * @cmp1:  comparable1
+ * @cmp2:  comparable2
+ *
+ * Return: true if cmp1 happened before cmp2.
+ */
+static inline bool ktime_before(const ktime_t cmp1, const ktime_t cmp2)
+{
+   return ktime_compare(cmp1, cmp2) < 0;
+}
+
+#if BITS_PER_LONG < 64
+extern s64 __ktime_divns(const ktime_t kt, s64 div);
+static inline s64 ktime_divns(const ktime_t kt, s64 div)
+{
+   /*
+* Negative divisors could cause an inf loop,
+* so bug out here.
+*/
+   BUG_ON(div < 0);
+   if (__builtin_constant_p(div) && !(div >> 32)) {
+   s64 ns = kt;
+   u64 tmp = ns < 0 ? -ns : ns;
+
+   do_div(tmp, div);
+   return ns < 0 ? -tmp : tmp;
+   } else {
+   return __ktime_divns(kt, div);
+   }
+}
+#else /* BITS_PER_LONG < 64 */
+static inline s64 ktime_divns(const ktime_t kt, s64 div)
+{
+   /*
+* 32-bit implementation cannot handle negative divisors,
+* so catch them on 64bit as well.
+*/
+   WARN_ON(div < 0);
+   return kt / div;
+}

[PATCH 13/18] include: linux/idr.h: implement more Linux API

2023-11-10 Thread Ahmad Fatoum
Upcoming sync of SCMI with the kernel will start using IDR API, which we
lack in barebox, so let's retrofit it.

Signed-off-by: Ahmad Fatoum 
---
 drivers/firmware/arm_scmi/driver.c |  2 +-
 include/linux/idr.h| 69 ++
 2 files changed, 61 insertions(+), 10 deletions(-)

diff --git a/drivers/firmware/arm_scmi/driver.c 
b/drivers/firmware/arm_scmi/driver.c
index dcd15528f394..c3536d6e9fbd 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -1001,7 +1001,7 @@ int scmi_protocol_device_request(const struct 
scmi_device_id *id_table)
 * Search for the matching protocol rdev list and then search
 * of any existent equally named device...fails if any duplicate found.
 */
-   __idr_for_each_entry(_requested_devices, idr) {
+   idr_for_each_entry(_requested_devices, idr) {
struct list_head *head = idr->ptr;
if (!phead) {
/* A list found registered in the IDR is never empty */
diff --git a/include/linux/idr.h b/include/linux/idr.h
index 12494b1f01cb..de1d5d78f546 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -24,21 +24,66 @@ struct idr {
 #define DEFINE_IDR(name)   \
struct idr name = { .list = LIST_HEAD_INIT((name).list) }
 
-#define __idr_for_each_entry(head, idr) \
-   list_for_each_entry((idr), &(head)->list, list)
+/**
+ * idr_for_each_entry() - Iterate over an IDR's elements of a given type.
+ * @_idr: IDR handle.
+ * @_entry: The type * to use as cursor
+ * @_id: Entry ID.
+ *
+ * @_entry and @_id do not need to be initialized before the loop, and
+ * after normal termination @_entry is left with the value NULL.  This
+ * is convenient for a "not found" value.
+ */
+#define idr_for_each_entry(_idr, _entry, _id)  \
+   for (struct idr *iter = (_idr); \
+>list != &((_idr)->list) || (_entry = NULL); \
+iter = list_next_entry(iter, list))\
+   if ((_entry = iter->ptr, _id = iter->id, true))
 
-static inline struct idr *__idr_find(struct idr *head, int id)
+static inline struct idr *__idr_find(struct idr *head, int lookup_id)
 {
-   struct idr *idr;
+   struct idr *cursor;
 
-   __idr_for_each_entry(head, idr) {
-   if (idr->id == id)
-   return idr;
+   list_for_each_entry(cursor, >list, list) {
+   if (cursor->id == lookup_id)
+   return cursor;
}
 
return NULL;
 }
 
+/**
+ * idr_for_each() - Iterate through all stored pointers.
+ * @idr: IDR handle.
+ * @fn: Function to be called for each pointer.
+ * @data: Data passed to callback function.
+ *
+ * The callback function will be called for each entry in @idr, passing
+ * the ID, the entry and @data.
+ *
+ * If @fn returns anything other than %0, the iteration stops and that
+ * value is returned from this function.
+ */
+static inline int idr_for_each(const struct idr *idr,
+  int (*fn)(int id, void *p, void *data), void 
*data)
+{
+   const struct idr *pos, *tmp;
+   int ret;
+
+   list_for_each_entry_safe(pos, tmp, >list, list) {
+   ret = fn(pos->id, pos->ptr, data);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
+}
+
+static inline int idr_is_empty(const struct idr *idr)
+{
+   return list_empty(>list);
+}
+
 static inline void *idr_find(struct idr *head, int id)
 {
struct idr *idr = __idr_find(head, id);
@@ -70,12 +115,18 @@ static inline void idr_init(struct idr *idr)
INIT_LIST_HEAD(>list);
 }
 
-static inline void idr_remove(struct idr *head, int id)
+static inline void idr_destroy(struct idr *idr)
 {
-   struct idr *idr = __idr_find(head, id);
+   if (!idr)
+   return;
 
list_del(>list);
free(idr);
 }
 
+static inline void idr_remove(struct idr *head, int id)
+{
+   idr_destroy(__idr_find(head, id));
+}
+
 #endif /* __IDR_H__ */
-- 
2.39.2




[PATCH 11/18] include: asm-generic/atomic.h: define atomic_cmpxchg

2023-11-10 Thread Ahmad Fatoum
We already define a generic cmpxchg implementation, so add one that
operates on atomic_t as well.

Signed-off-by: Ahmad Fatoum 
---
 include/asm-generic/atomic.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h
index 27b0f73b487b..74429e1c373f 100644
--- a/include/asm-generic/atomic.h
+++ b/include/asm-generic/atomic.h
@@ -116,6 +116,8 @@ static inline void atomic_clear_mask(unsigned long mask, 
unsigned long *addr)
*addr &= ~mask;
 }
 
+#define atomic_cmpxchg(v, o, n)cmpxchg(&((v)->counter), o, n)
+
 /* Atomic operations are already serializing on ARM */
 #define smp_mb__before_atomic_dec()barrier()
 #define smp_mb__after_atomic_dec() barrier()
-- 
2.39.2




[PATCH 18/18] include: add linux/device.h wrapper around driver.h

2023-11-10 Thread Ahmad Fatoum
We don't have device-scoped resource control and in practice memory
allocated in device functions is only freed when barebox terminates, so
let's accept the fact that most code is leaky and implement devm_
as literal leaky abstractions.

While at it provide some macros to translate Linux API into equivalent
barebox API.

Signed-off-by: Ahmad Fatoum 
---
 include/linux/device.h | 66 ++
 1 file changed, 66 insertions(+)
 create mode 100644 include/linux/device.h

diff --git a/include/linux/device.h b/include/linux/device.h
new file mode 100644
index ..0bd61154ac30
--- /dev/null
+++ b/include/linux/device.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef LINUX_DRIVER_H_
+#define LINUX_DRIVER_H_
+
+#include 
+#include 
+#include 
+#include 
+
+#define device_driver driver
+
+#define __devm_wrapper(fn, dev, ...) ({ BUG_ON(!dev); fn(__VA_ARGS__); })
+
+#define devm_kmalloc(...)  __devm_wrapper(kmalloc, __VA_ARGS__)
+#define devm_krealloc(...) __devm_wrapper(krealloc, __VA_ARGS__)
+#define devm_kvasprintf(...)   __devm_wrapper(kvasprintf, __VA_ARGS__)
+#define devm_kasprintf(...)__devm_wrapper(kasprintf, __VA_ARGS__)
+#define devm_kzalloc(...)  __devm_wrapper(kzalloc, __VA_ARGS__)
+#define devm_kmalloc_array(...)__devm_wrapper(kmalloc_array, 
__VA_ARGS__)
+#define devm_kcalloc(...)  __devm_wrapper(kcalloc, __VA_ARGS__)
+#define devm_krealloc_array(...)   __devm_wrapper(krealloc_array, 
__VA_ARGS__)
+#define devm_kfree(...)__devm_wrapper(kfree, 
__VA_ARGS__)
+#define devm_kstrdup(...)  __devm_wrapper(kstrdup, __VA_ARGS__)
+#define devm_kstrdup_const(...)__devm_wrapper(kstrdup_const, 
__VA_ARGS__)
+#define devm_kmemdup(...)  __devm_wrapper(kmemdup, __VA_ARGS__)
+#define devm_bitmap_zalloc(dev, nbits, gfp)\
+   __devm_wrapper(bitmap_zalloc, dev, nbits)
+
+#define device_register register_device
+#define device_unregister unregister_device
+
+#define driver_register register_driver
+#define driver_unregister unregister_driver
+
+static inline void __iomem *devm_ioremap(struct device *dev,
+resource_size_t start,
+resource_size_t size)
+{
+   if (start)
+   remap_range((void *)start, size, MAP_UNCACHED);
+
+   return IOMEM(start);
+}
+
+static inline int bus_for_each_dev(const struct bus_type *bus, struct device 
*start, void *data,
+  int (*fn)(struct device *dev, void *data))
+{
+   struct device *dev;
+   int ret;
+
+   bus_for_each_device(bus, dev) {
+   if (start) {
+   if (dev == start)
+   start = NULL;
+   continue;
+   }
+
+   ret = fn(dev, data);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
+}
+
+#endif
-- 
2.39.2




[PATCH 10/18] of: add CONFIG_OF for Linux compatibility

2023-11-10 Thread Ahmad Fatoum
barebox has CONFIG_OFTREE and CONFIG_OFDEVICE as separate definitions
for good reason, because configurations parsing device trees, while not
using them are possible. In Linux, there is no such distinction and
CONFIG_OF is used as single option for this. Provide the same option in
barebox as hidden symbol and select it from CONFIG_OFDEVICE to make
porting a tiny bit easier.

Signed-off-by: Ahmad Fatoum 
---
 drivers/of/Kconfig | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 4dc40b27f442..816aff0063b0 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -11,8 +11,12 @@ config OFTREE_MEM_GENERIC
 config DTC
bool
 
+config OF
+   bool
+
 config OFDEVICE
select OFTREE
+   select OF
select DTC
bool "Enable probing of devices from the devicetree"
 
-- 
2.39.2




[PATCH 12/18] kbuild: build barebox for -std=gnu11

2023-11-10 Thread Ahmad Fatoum
Linux has been configured with -std=gnu11 since v5.18 to benefit from
being able to declare variables in for loops init statements.

This is handy for barebox as well and should we adopt
__attribute__((cleanup)) to simplify resource management, it will become
required anyway, because define __attribute((cleanup)) variables much
earlier than they are used is needlessly cumbersome.

So let's do the switch.

Signed-off-by: Ahmad Fatoum 
---
 Makefile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index dc22ea546428..85bc6515d462 100644
--- a/Makefile
+++ b/Makefile
@@ -387,7 +387,7 @@ HOSTCC   = gcc
 HOSTCXX  = g++
 
 KBUILD_USERHOSTCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes \
- -O2 -fomit-frame-pointer -std=gnu89
+ -O2 -fomit-frame-pointer -std=gnu11
 KBUILD_USERCFLAGS  := $(KBUILD_USERHOSTCFLAGS) $(USERCFLAGS)
 KBUILD_USERLDFLAGS := $(USERLDFLAGS)
 
@@ -452,7 +452,7 @@ KBUILD_CPPFLAGS:= -D__KERNEL__ -D__BAREBOX__ 
$(LINUXINCLUDE) -fno-builti
 KBUILD_CFLAGS   := -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs \
   -fno-strict-aliasing -fno-common -fshort-wchar \
-Werror=implicit-function-declaration -Werror=implicit-int \
-   -Os -pipe -Wmissing-prototypes -std=gnu89
+   -Os -pipe -Wmissing-prototypes -std=gnu11
 KBUILD_AFLAGS  := -D__ASSEMBLY__
 KBUILD_AFLAGS_KERNEL :=
 KBUILD_CFLAGS_KERNEL :=
-- 
2.39.2




[PATCH 17/18] of: define of_devices_ensure_probed_by_compatible

2023-11-10 Thread Ahmad Fatoum
We will need to ensure probe of OP-TEE from SCMI code in a follow-up
commit, so add a small helper to facilitate this.

Signed-off-by: Ahmad Fatoum 
---
 include/of.h | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/include/of.h b/include/of.h
index a7a1ce125fc0..7ebf1f02cc68 100644
--- a/include/of.h
+++ b/include/of.h
@@ -1220,6 +1220,16 @@ int of_device_disable(struct device_node *node);
 int of_device_disable_path(const char *path);
 int of_device_disable_by_alias(const char *alias);
 
+static inline int of_devices_ensure_probed_by_compatible(char *compatible)
+{
+   struct of_device_id match_id[] = {
+   { .compatible = compatible, },
+   { /* sentinel */ },
+   };
+
+   return of_devices_ensure_probed_by_dev_id(match_id);
+}
+
 phandle of_get_tree_max_phandle(struct device_node *root);
 phandle of_node_create_phandle(struct device_node *node);
 int of_set_property_to_child_phandle(struct device_node *node, char 
*prop_name);
-- 
2.39.2




[PATCH 02/18] include: add linux/refcount.h

2023-11-10 Thread Ahmad Fatoum
For complex interactions, especially in communication protocols, it can
be beneficial to keep the reference counts used in the Linux drivers as
is to avoid resource leaks or use-after-frees.

Provide a simplified kref and refcount API to facilitate this.

Signed-off-by: Ahmad Fatoum 
---
 include/asm-generic/cmpxchg-local.h |  64 +++
 include/asm-generic/cmpxchg.h   |  26 +++
 include/linux/atomic.h  |  63 +++
 include/linux/kref.h|  90 +
 include/linux/refcount.h| 271 
 lib/Makefile|   1 +
 lib/refcount.c  |  34 
 7 files changed, 549 insertions(+)
 create mode 100644 include/asm-generic/cmpxchg-local.h
 create mode 100644 include/asm-generic/cmpxchg.h
 create mode 100644 include/linux/kref.h
 create mode 100644 include/linux/refcount.h
 create mode 100644 lib/refcount.c

diff --git a/include/asm-generic/cmpxchg-local.h 
b/include/asm-generic/cmpxchg-local.h
new file mode 100644
index ..d93b103d5ca2
--- /dev/null
+++ b/include/asm-generic/cmpxchg-local.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_GENERIC_CMPXCHG_LOCAL_H
+#define __ASM_GENERIC_CMPXCHG_LOCAL_H
+
+#include 
+#include 
+
+extern unsigned long wrong_size_cmpxchg(volatile void *ptr)
+   __noreturn;
+
+/*
+ * Generic version of __cmpxchg_local (disables interrupts). Takes an unsigned
+ * long parameter, supporting various types of architectures.
+ */
+static inline unsigned long __generic_cmpxchg_local(volatile void *ptr,
+   unsigned long old, unsigned long new, int size)
+{
+   unsigned long prev;
+
+   /*
+* Sanity checking, compile-time.
+*/
+   if (size == 8 && sizeof(unsigned long) != 8)
+   wrong_size_cmpxchg(ptr);
+
+   switch (size) {
+   case 1: prev = *(u8 *)ptr;
+   if (prev == old)
+   *(u8 *)ptr = (u8)new;
+   break;
+   case 2: prev = *(u16 *)ptr;
+   if (prev == old)
+   *(u16 *)ptr = (u16)new;
+   break;
+   case 4: prev = *(u32 *)ptr;
+   if (prev == old)
+   *(u32 *)ptr = (u32)new;
+   break;
+   case 8: prev = *(u64 *)ptr;
+   if (prev == old)
+   *(u64 *)ptr = (u64)new;
+   break;
+   default:
+   wrong_size_cmpxchg(ptr);
+   }
+   return prev;
+}
+
+/*
+ * Generic version of __cmpxchg64_local. Takes an u64 parameter.
+ */
+static inline u64 __generic_cmpxchg64_local(volatile void *ptr,
+   u64 old, u64 new)
+{
+   u64 prev;
+
+   prev = *(u64 *)ptr;
+   if (prev == old)
+   *(u64 *)ptr = new;
+
+   return prev;
+}
+
+#endif
diff --git a/include/asm-generic/cmpxchg.h b/include/asm-generic/cmpxchg.h
new file mode 100644
index ..b90524135efe
--- /dev/null
+++ b/include/asm-generic/cmpxchg.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Generic non-atomic cmpxchg for porting kernel code.
+ */
+
+#ifndef __ASM_GENERIC_CMPXCHG_H
+#define __ASM_GENERIC_CMPXCHG_H
+
+#ifdef CONFIG_SMP
+#error "Cannot use generic cmpxchg on SMP"
+#endif
+
+#include 
+
+#define generic_cmpxchg_local(ptr, o, n) ({
\
+   ((__typeof__(*(ptr)))__generic_cmpxchg_local((ptr), (unsigned long)(o), 
\
+   (unsigned long)(n), sizeof(*(ptr;   
\
+})
+
+#define generic_cmpxchg64_local(ptr, o, n) \
+   __generic_cmpxchg64_local((ptr), (o), (n))
+
+#define cmpxchggeneric_cmpxchg_local
+#define cmpxchg64  generic_cmpxchg64_local
+
+#endif
diff --git a/include/linux/atomic.h b/include/linux/atomic.h
index 9304ab4a34ba..c7bdf5857ce8 100644
--- a/include/linux/atomic.h
+++ b/include/linux/atomic.h
@@ -3,5 +3,68 @@
 #define LINUX_ATOMIC_H_
 
 #include 
+#include 
+#include 
+
+#define raw_cmpxchg_relaxed cmpxchg
+
+/**
+ * raw_atomic_cmpxchg_relaxed() - atomic compare and exchange with relaxed 
ordering
+ * @v: pointer to atomic_t
+ * @old: int value to compare with
+ * @new: int value to assign
+ *
+ * If (@v == @old), atomically updates @v to @new with relaxed ordering.
+ *
+ * Safe to use in noinstr code; prefer atomic_cmpxchg_relaxed() elsewhere.
+ *
+ * Return: The original value of @v.
+ */
+static __always_inline int
+raw_atomic_cmpxchg_relaxed(atomic_t *v, int old, int new)
+{
+   return raw_cmpxchg_relaxed(>counter, old, new);
+}
+
+/**
+ * atomic_try_cmpxchg_relaxed() - atomic compare and exchange with relaxed 
ordering
+ * @v: pointer to atomic_t
+ * @old: pointer to int value to compare with
+ * @new: int value to assign
+ *
+ * If (@v == @old), atomically updates @v to @new with relaxed ordering.
+ * Otherwise, updates @old to the current value of @v.
+ *
+ * Return: @true if the exchange occured, @false otherwise.
+ */
+static 

[PATCH 04/18] include: import

2023-11-10 Thread Ahmad Fatoum
This header provides definitions for getting the instruction pointer and
the return address in a portable manner, which can be useful for
trace outputs where dump_stack would be overkill.

Signed-off-by: Ahmad Fatoum 
---
 include/linux/instruction_pointer.h | 11 +++
 include/linux/kernel.h  |  3 +--
 2 files changed, 12 insertions(+), 2 deletions(-)
 create mode 100644 include/linux/instruction_pointer.h

diff --git a/include/linux/instruction_pointer.h 
b/include/linux/instruction_pointer.h
new file mode 100644
index ..6564127a31ba
--- /dev/null
+++ b/include/linux/instruction_pointer.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_INSTRUCTION_POINTER_H
+#define _LINUX_INSTRUCTION_POINTER_H
+
+#define _RET_IP_   (unsigned long)__builtin_return_address(0)
+
+#ifndef _THIS_IP_
+#define _THIS_IP_  ({ __label__ __here; __here: (unsigned long)&&__here; })
+#endif
+
+#endif /* _LINUX_INSTRUCTION_POINTER_H */
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 0e4ba243915b..da6121888ebd 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #define ALIGN(x, a)__ALIGN_MASK(x, (typeof(x))(a) - 1)
@@ -117,8 +118,6 @@ extern long long simple_strtoll(const char *,char 
**,unsigned int);
 }  \
 )
 
-#define _RET_IP_ (unsigned long)__builtin_return_address(0)
-
 extern const char hex_asc[];
 #define hex_asc_lo(x)  hex_asc[((x) & 0x0f)]
 #define hex_asc_hi(x)  hex_asc[((x) & 0xf0) >> 4]
-- 
2.39.2




[PATCH 05/18] asm-generic: split off typeconfused readl and friends

2023-11-10 Thread Ahmad Fatoum
The MMIO accessors in barebox like readl have the error prone
peculiarity of accepting integer arguments to pointers automatically,
which makes it easy to confuse address and data.

We will add an alternative less error-probe way for new code, so first
split off the typeconfused code into a separate file.

Signed-off-by: Ahmad Fatoum 
---
 include/asm-generic/io-typeconfused.h | 75 +++
 include/asm-generic/io.h  | 57 +---
 2 files changed, 76 insertions(+), 56 deletions(-)
 create mode 100644 include/asm-generic/io-typeconfused.h

diff --git a/include/asm-generic/io-typeconfused.h 
b/include/asm-generic/io-typeconfused.h
new file mode 100644
index ..d25ed7db2473
--- /dev/null
+++ b/include/asm-generic/io-typeconfused.h
@@ -0,0 +1,75 @@
+/* Generic I/O port emulation, based on MN10300 code
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef __ASM_GENERIC_IO_TYPECONFUSED_H
+#define __ASM_GENERIC_IO_TYPECONFUSED_H
+
+#include  /* for memset() and memcpy() */
+#include 
+#include 
+#include 
+
+/*/
+/*
+ * Unlike the definitions in , these macros don't complain
+ * about integer arguments and just silently cast them to pointers. This is
+ * a common cause of bugs, but lots of existing code depends on this, so
+ * this header is provided as a transitory measure.
+ */
+
+#ifndef __raw_readb
+#define __raw_readb(a) (__chk_io_ptr(a), *(volatile unsigned char 
__force  *)(a))
+#endif
+
+#ifndef __raw_readw
+#define __raw_readw(a) (__chk_io_ptr(a), *(volatile unsigned short 
__force *)(a))
+#endif
+
+#ifndef __raw_readl
+#define __raw_readl(a) (__chk_io_ptr(a), *(volatile unsigned int 
__force   *)(a))
+#endif
+
+#ifndef readb
+#define readb __raw_readb
+#endif
+
+#ifndef readw
+#define readw(addr) __le16_to_cpu(__raw_readw(addr))
+#endif
+
+#ifndef readl
+#define readl(addr) __le32_to_cpu(__raw_readl(addr))
+#endif
+
+#ifndef __raw_writeb
+#define __raw_writeb(v,a)  (__chk_io_ptr(a), *(volatile unsigned char 
__force  *)(a) = (v))
+#endif
+
+#ifndef __raw_writew
+#define __raw_writew(v,a)  (__chk_io_ptr(a), *(volatile unsigned short 
__force *)(a) = (v))
+#endif
+
+#ifndef __raw_writel
+#define __raw_writel(v,a)  (__chk_io_ptr(a), *(volatile unsigned int 
__force   *)(a) = (v))
+#endif
+
+#ifndef writeb
+#define writeb __raw_writeb
+#endif
+
+#ifndef writew
+#define writew(b,addr) __raw_writew(__cpu_to_le16(b),addr)
+#endif
+
+#ifndef writel
+#define writel(b,addr) __raw_writel(__cpu_to_le32(b),addr)
+#endif
+
+#endif /* __ASM_GENERIC_IO_TYPECONFUSED_H */
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index ab439026928a..6383d71746f1 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -15,62 +15,7 @@
 #include 
 #include 
 #include 
-
-/*/
-/*
- * readX/writeX() are used to access memory mapped devices. On some
- * architectures the memory mapped IO stuff needs to be accessed
- * differently. On the simple architectures, we just read/write the
- * memory location directly.
- */
-
-#ifndef __raw_readb
-#define __raw_readb(a) (__chk_io_ptr(a), *(volatile unsigned char 
__force  *)(a))
-#endif
-
-#ifndef __raw_readw
-#define __raw_readw(a) (__chk_io_ptr(a), *(volatile unsigned short 
__force *)(a))
-#endif
-
-#ifndef __raw_readl
-#define __raw_readl(a) (__chk_io_ptr(a), *(volatile unsigned int 
__force   *)(a))
-#endif
-
-#ifndef readb
-#define readb __raw_readb
-#endif
-
-#ifndef readw
-#define readw(addr) __le16_to_cpu(__raw_readw(addr))
-#endif
-
-#ifndef readl
-#define readl(addr) __le32_to_cpu(__raw_readl(addr))
-#endif
-
-#ifndef __raw_writeb
-#define __raw_writeb(v,a)  (__chk_io_ptr(a), *(volatile unsigned char 
__force  *)(a) = (v))
-#endif
-
-#ifndef __raw_writew
-#define __raw_writew(v,a)  (__chk_io_ptr(a), *(volatile unsigned short 
__force *)(a) = (v))
-#endif
-
-#ifndef __raw_writel
-#define __raw_writel(v,a)  (__chk_io_ptr(a), *(volatile unsigned int 
__force   *)(a) = (v))
-#endif
-
-#ifndef writeb
-#define writeb __raw_writeb
-#endif
-
-#ifndef writew
-#define writew(b,addr) __raw_writew(__cpu_to_le16(b),addr)
-#endif
-
-#ifndef writel
-#define writel(b,addr) __raw_writel(__cpu_to_le32(b),addr)
-#endif
+#include 
 
 #ifdef CONFIG_64BIT
 static inline u64 __raw_readq(const volatile void __iomem *addr)
-- 
2.39.2




[PATCH 08/18] include: import Linux word-at-a-time.h

2023-11-10 Thread Ahmad Fatoum
The Linux  interface is used to optimize
searching for bytes in strings by doing word-size comparisons. This will
be used in the implementation of strscpy in a follow-up commit, so
import the generic version here.

A good overview on the interface is available at LWN[1]. Note that
it discuss Linux v3.5. The asm-generic version imported here works
also on little-endian and not only big-endian[2].

[1]: https://lwn.net/Articles/501492/
[2]: Linux kernel commit a6e2f029ae34 ("Make asm/word-at-a-time.h
 available on all architectures").

Signed-off-by: Ahmad Fatoum 
---
 arch/arm/include/asm/word-at-a-time.h  |  59 
 arch/kvx/include/asm/word-at-a-time.h  |   2 +
 arch/mips/include/asm/word-at-a-time.h |   2 +
 arch/openrisc/include/asm/word-at-a-time.h |   2 +
 arch/powerpc/include/asm/word-at-a-time.h  | 156 +
 arch/riscv/include/asm/word-at-a-time.h|  48 +++
 arch/sandbox/include/asm/word-at-a-time.h  |   2 +
 arch/x86/include/asm/word-at-a-time.h  |  73 ++
 include/asm-generic/word-at-a-time.h   | 121 
 include/linux/kernel.h |   8 ++
 10 files changed, 473 insertions(+)
 create mode 100644 arch/arm/include/asm/word-at-a-time.h
 create mode 100644 arch/kvx/include/asm/word-at-a-time.h
 create mode 100644 arch/mips/include/asm/word-at-a-time.h
 create mode 100644 arch/openrisc/include/asm/word-at-a-time.h
 create mode 100644 arch/powerpc/include/asm/word-at-a-time.h
 create mode 100644 arch/riscv/include/asm/word-at-a-time.h
 create mode 100644 arch/sandbox/include/asm/word-at-a-time.h
 create mode 100644 arch/x86/include/asm/word-at-a-time.h
 create mode 100644 include/asm-generic/word-at-a-time.h

diff --git a/arch/arm/include/asm/word-at-a-time.h 
b/arch/arm/include/asm/word-at-a-time.h
new file mode 100644
index ..f22198a66be3
--- /dev/null
+++ b/arch/arm/include/asm/word-at-a-time.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2013 ARM Ltd.
+ */
+#ifndef __ASM_WORD_AT_A_TIME_H
+#define __ASM_WORD_AT_A_TIME_H
+
+#if !defined(__AARCH64EB__) && !defined(__ARMEB__)
+
+#include 
+
+struct word_at_a_time {
+   const unsigned long one_bits, high_bits;
+};
+
+#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) }
+
+static inline unsigned long has_zero(unsigned long a, unsigned long *bits,
+const struct word_at_a_time *c)
+{
+   unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits;
+   *bits = mask;
+   return mask;
+}
+
+#define prep_zero_mask(a, bits, c) (bits)
+
+static inline unsigned long create_zero_mask(unsigned long bits)
+{
+   bits = (bits - 1) & ~bits;
+   return bits >> 7;
+}
+
+static inline unsigned long find_zero(unsigned long mask)
+{
+   unsigned long ret;
+
+#if __LINUX_ARM_ARCH__ >= 8
+   ret = fls64(mask) >> 3;
+#elif __LINUX_ARM_ARCH__ >= 5
+   /* We have clz available. */
+   ret = fls(mask) >> 3;
+#else
+   /* (00 ff 00 ff) -> ( 1 1 2 3 ) */
+   ret = (0x0ff0001 + mask) >> 23;
+   /* Fix the 1 for 00 case */
+   ret &= mask;
+#endif
+
+   return ret;
+}
+
+#define zero_bytemask(mask) (mask)
+
+#else  /* __AARCH64EB__ || __ARMEB__ */
+#include 
+#endif
+
+#endif /* __ASM_WORD_AT_A_TIME_H */
diff --git a/arch/kvx/include/asm/word-at-a-time.h 
b/arch/kvx/include/asm/word-at-a-time.h
new file mode 100644
index ..f6306fb896a1
--- /dev/null
+++ b/arch/kvx/include/asm/word-at-a-time.h
@@ -0,0 +1,2 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#include 
diff --git a/arch/mips/include/asm/word-at-a-time.h 
b/arch/mips/include/asm/word-at-a-time.h
new file mode 100644
index ..f6306fb896a1
--- /dev/null
+++ b/arch/mips/include/asm/word-at-a-time.h
@@ -0,0 +1,2 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#include 
diff --git a/arch/openrisc/include/asm/word-at-a-time.h 
b/arch/openrisc/include/asm/word-at-a-time.h
new file mode 100644
index ..f6306fb896a1
--- /dev/null
+++ b/arch/openrisc/include/asm/word-at-a-time.h
@@ -0,0 +1,2 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#include 
diff --git a/arch/powerpc/include/asm/word-at-a-time.h 
b/arch/powerpc/include/asm/word-at-a-time.h
new file mode 100644
index ..1de46fbd2e15
--- /dev/null
+++ b/arch/powerpc/include/asm/word-at-a-time.h
@@ -0,0 +1,156 @@
+#ifndef _ASM_WORD_AT_A_TIME_H
+#define _ASM_WORD_AT_A_TIME_H
+
+/*
+ * Word-at-a-time interfaces for PowerPC.
+ */
+
+#include 
+
+#ifdef __BIG_ENDIAN__
+
+struct word_at_a_time {
+   const unsigned long high_bits, low_bits;
+};
+
+#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0xfe) + 1, REPEAT_BYTE(0x7f) }
+
+/* Bit set in the bytes that have a zero */
+static inline long prep_zero_mask(unsigned long val, unsigned long rhs, const 
struct word_at_a_time *c)
+{
+   unsigned long mask = (val & c->low_bits) + c->low_bits;
+   return ~(mask | 

[PATCH 07/18] include: add linux/io.h with strict prototypes

2023-11-10 Thread Ahmad Fatoum
Kernel code uses  instead of , which defines readl and
friends as functions with type checks instead of macros that just cast
everything to pointers. Let's provide  to ease porting as
well and have it have the same semantics.

Eventually, we should be able to get switch  to include
 once all in-tree users are migrated.

Signed-off-by: Ahmad Fatoum 
---
 include/asm-generic/io.h | 217 +--
 include/linux/io.h   |   9 ++
 2 files changed, 218 insertions(+), 8 deletions(-)
 create mode 100644 include/linux/io.h

diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index b118979ed1df..123ad5488ffc 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -13,23 +13,224 @@
 
 #include  /* for memset() and memcpy() */
 #include 
+#include 
 #include 
 #include 
+
+#ifndef __LINUX_IO_STRICT_PROTOTYPES__
 #include 
+#endif
+
+#define __io_br()  barrier()
+#define __io_ar(v)  barrier()
+#define __io_bw()  barrier()
+#define __io_pbw() __io_bw()
+#define __io_paw() __io_aw()
+#define __io_aw()  do { } while (0)
+#define __io_pbr() __io_br()
+#define __io_par(v) __io_ar(v)
+
+static inline void log_write_mmio(u64 val, u8 width, volatile void __iomem 
*addr,
+ unsigned long caller_addr, unsigned long 
caller_addr0) {}
+static inline void log_post_write_mmio(u64 val, u8 width, volatile void 
__iomem *addr,
+  unsigned long caller_addr, unsigned long 
caller_addr0) {}
+static inline void log_read_mmio(u8 width, const volatile void __iomem *addr,
+unsigned long caller_addr, unsigned long 
caller_addr0) {}
+static inline void log_post_read_mmio(u64 val, u8 width, const volatile void 
__iomem *addr,
+ unsigned long caller_addr, unsigned long 
caller_addr0) {}
+
+/*
+ * __raw_{read,write}{b,w,l,q}() access memory in native endianness.
+ *
+ * On some architectures memory mapped IO needs to be accessed differently.
+ * On the simple architectures, we just read/write the memory location
+ * directly.
+ */
+
+#ifndef __raw_readb
+#define __raw_readb __raw_readb
+static inline u8 __raw_readb(const volatile void __iomem *addr)
+{
+   return *(const volatile u8 __force *)addr;
+}
+#endif
+
+#ifndef __raw_readw
+#define __raw_readw __raw_readw
+static inline u16 __raw_readw(const volatile void __iomem *addr)
+{
+   return *(const volatile u16 __force *)addr;
+}
+#endif
+
+#ifndef __raw_readl
+#define __raw_readl __raw_readl
+static inline u32 __raw_readl(const volatile void __iomem *addr)
+{
+   return *(const volatile u32 __force *)addr;
+}
+#endif
 
 #ifdef CONFIG_64BIT
+#ifndef __raw_readq
+#define __raw_readq __raw_readq
 static inline u64 __raw_readq(const volatile void __iomem *addr)
 {
-   return *(const volatile u64 __force *) addr;
+   return *(const volatile u64 __force *)addr;
 }
-#define readq(addr) __le64_to_cpu(__raw_readq(addr))
-
-static inline void __raw_writeq(u64 b, volatile void __iomem *addr)
-{
-   *(volatile u64 __force *) addr = b;
-}
-#define writeq(b,addr) __raw_writeq(__cpu_to_le64(b),addr)
 #endif
+#endif /* CONFIG_64BIT */
+
+#ifndef __raw_writeb
+#define __raw_writeb __raw_writeb
+static inline void __raw_writeb(u8 value, volatile void __iomem *addr)
+{
+   *(volatile u8 __force *)addr = value;
+}
+#endif
+
+#ifndef __raw_writew
+#define __raw_writew __raw_writew
+static inline void __raw_writew(u16 value, volatile void __iomem *addr)
+{
+   *(volatile u16 __force *)addr = value;
+}
+#endif
+
+#ifndef __raw_writel
+#define __raw_writel __raw_writel
+static inline void __raw_writel(u32 value, volatile void __iomem *addr)
+{
+   *(volatile u32 __force *)addr = value;
+}
+#endif
+
+#ifdef CONFIG_64BIT
+#ifndef __raw_writeq
+#define __raw_writeq __raw_writeq
+static inline void __raw_writeq(u64 value, volatile void __iomem *addr)
+{
+   *(volatile u64 __force *)addr = value;
+}
+#endif
+#endif /* CONFIG_64BIT */
+
+/*
+ * {read,write}{b,w,l,q}() access little endian memory and return result in
+ * native endianness.
+ */
+
+#ifndef readb
+#define readb readb
+static inline u8 readb(const volatile void __iomem *addr)
+{
+   u8 val;
+
+   log_read_mmio(8, addr, _THIS_IP_, _RET_IP_);
+   __io_br();
+   val = __raw_readb(addr);
+   __io_ar(val);
+   log_post_read_mmio(val, 8, addr, _THIS_IP_, _RET_IP_);
+   return val;
+}
+#endif
+
+#ifndef readw
+#define readw readw
+static inline u16 readw(const volatile void __iomem *addr)
+{
+   u16 val;
+
+   log_read_mmio(16, addr, _THIS_IP_, _RET_IP_);
+   __io_br();
+   val = __le16_to_cpu((__le16 __force)__raw_readw(addr));
+   __io_ar(val);
+   log_post_read_mmio(val, 16, addr, _THIS_IP_, _RET_IP_);
+   return val;
+}
+#endif
+
+#ifndef readl
+#define readl readl
+static inline u32 readl(const volatile void __iomem *addr)
+{
+   u32 val;

[PATCH 00/18] prepare for porting OP-TEE communication support

2023-11-10 Thread Ahmad Fatoum
So far, barebox support for OP-TEE was restricted to loading it either
early in PBL or via bootm and to not step over it when allocating
memory. This was guarded behind CONFIG_HAVE_OPTEE.

To prepare porting the Linux driver behind CONFIG_OPTEE, which
brings actual bidirectional communication with OP-TEE to barebox,
let's import some of the headers and APIs used by the v6.6 Linux
driver.

Ahmad Fatoum (18):
  include: provide linux/errno.h
  include: add linux/refcount.h
  bitops: split off linux/bits.h
  include: import 
  asm-generic: split off typeconfused readl and friends
  asm-generic: migrate relaxed helpers into asm-generic/io.h
  include: add linux/io.h with strict prototypes
  include: import Linux word-at-a-time.h
  string: implement strscpy
  of: add CONFIG_OF for Linux compatibility
  include: asm-generic/atomic.h: define atomic_cmpxchg
  kbuild: build barebox for -std=gnu11
  include: linux/idr.h: implement more Linux API
  include: implement dev_warn_once and friends
  include: add blocking notifier aliases
  include: add Linux ktime API
  of: define of_devices_ensure_probed_by_compatible
  include: add linux/device.h wrapper around driver.h

 Makefile   |   4 +-
 arch/arm/include/asm/word-at-a-time.h  |  59 +
 arch/kvx/include/asm/word-at-a-time.h  |   2 +
 arch/mips/include/asm/word-at-a-time.h |   2 +
 arch/openrisc/include/asm/word-at-a-time.h |   2 +
 arch/powerpc/include/asm/word-at-a-time.h  | 156 +++
 arch/powerpc/lib/misc.S|   2 +-
 arch/powerpc/lib/ppcstring.S   |   2 +-
 arch/riscv/include/asm/word-at-a-time.h|  48 
 arch/sandbox/include/asm/word-at-a-time.h  |   2 +
 arch/x86/include/asm/word-at-a-time.h  |  73 ++
 common/optee.c |   2 +-
 drivers/firmware/arm_scmi/driver.c |   4 +-
 drivers/of/Kconfig |   4 +
 include/asm-generic/atomic.h   |   2 +
 include/asm-generic/cmpxchg-local.h|  64 +
 include/asm-generic/cmpxchg.h  |  26 ++
 include/asm-generic/errno.h|  11 -
 include/asm-generic/io-typeconfused.h  |  75 ++
 include/asm-generic/io.h   | 284 +
 include/asm-generic/word-at-a-time.h   | 121 +
 include/bbu.h  |   2 +-
 include/errno.h|   2 +-
 include/io.h   |  34 ---
 include/linux/atomic.h |  63 +
 include/linux/bitops.h |  21 +-
 include/linux/bits.h   |  30 +++
 include/linux/device.h |  66 +
 include/linux/err.h|   2 +-
 include/linux/errno.h  |  36 +++
 include/linux/idr.h|  69 -
 include/linux/instruction_pointer.h|  11 +
 include/linux/io.h |   9 +
 include/linux/kernel.h |  11 +-
 include/linux/kref.h   |  90 +++
 include/linux/ktime.h  | 212 +++
 include/linux/notifier.h   |  16 ++
 include/linux/printk.h |  29 ++-
 include/linux/pstore.h |   2 +-
 include/linux/refcount.h   | 271 
 include/linux/string.h |   3 +
 include/mach/at91/iomux.h  |   2 +-
 include/notifier.h |   3 +
 include/of.h   |  10 +
 include/tee/optee.h|   2 +-
 lib/Makefile   |   1 +
 lib/reed_solomon/reed_solomon.c|   2 +-
 lib/refcount.c |  34 +++
 lib/string.c   |  71 ++
 49 files changed, 1906 insertions(+), 143 deletions(-)
 create mode 100644 arch/arm/include/asm/word-at-a-time.h
 create mode 100644 arch/kvx/include/asm/word-at-a-time.h
 create mode 100644 arch/mips/include/asm/word-at-a-time.h
 create mode 100644 arch/openrisc/include/asm/word-at-a-time.h
 create mode 100644 arch/powerpc/include/asm/word-at-a-time.h
 create mode 100644 arch/riscv/include/asm/word-at-a-time.h
 create mode 100644 arch/sandbox/include/asm/word-at-a-time.h
 create mode 100644 arch/x86/include/asm/word-at-a-time.h
 create mode 100644 include/asm-generic/cmpxchg-local.h
 create mode 100644 include/asm-generic/cmpxchg.h
 create mode 100644 include/asm-generic/io-typeconfused.h
 create mode 100644 include/asm-generic/word-at-a-time.h
 create mode 100644 include/linux/bits.h
 create mode 100644 include/linux/device.h
 create mode 100644 include/linux/errno.h
 create mode 100644 include/linux/instruction_pointer.h
 create mode 100644 include/linux/io.h
 create mode 100644 include/linux/kref.h
 create mode 100644 include/linux/ktime.h
 create mode 100644 include/linux/notifier.h
 create mode 100644 

[PATCH 06/18] asm-generic: migrate relaxed helpers into asm-generic/io.h

2023-11-10 Thread Ahmad Fatoum
In preparation for having  be the include file for type confused
MMIO accessors and  for typechecked accessors, let's move out
of  everything that's not directly related to the type confusion.

Signed-off-by: Ahmad Fatoum 
---
 include/asm-generic/io.h | 34 ++
 include/io.h | 34 --
 2 files changed, 34 insertions(+), 34 deletions(-)

diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index 6383d71746f1..b118979ed1df 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -792,4 +792,38 @@ static inline void memcpy_toio(volatile void __iomem 
*addr, const void *buffer,
 
 #include 
 
+#define IOMEM_ERR_PTR(err) (__force void __iomem *)ERR_PTR(err)
+
+#ifndef readq_relaxed
+#define readq_relaxed(addr) readq(addr)
+#endif
+
+#ifndef readl_relaxed
+#define readl_relaxed(addr) readl(addr)
+#endif
+
+#ifndef readw_relaxed
+#define readw_relaxed(addr) readw(addr)
+#endif
+
+#ifndef readb_relaxed
+#define readb_relaxed(addr) readb(addr)
+#endif
+
+#ifndef writeq_relaxed
+#define writeq_relaxed(val, addr) writeq((val), (addr))
+#endif
+
+#ifndef writel_relaxed
+#define writel_relaxed(val, addr) writel((val), (addr))
+#endif
+
+#ifndef writew_relaxed
+#define writew_relaxed(val, addr) writew((val), (addr))
+#endif
+
+#ifndef writeb_relaxed
+#define writeb_relaxed(val, addr) writeb((val), (addr))
+#endif
+
 #endif /* __ASM_GENERIC_IO_H */
diff --git a/include/io.h b/include/io.h
index 6a74246ea777..913002072240 100644
--- a/include/io.h
+++ b/include/io.h
@@ -4,38 +4,4 @@
 
 #include 
 
-#define IOMEM_ERR_PTR(err) (__force void __iomem *)ERR_PTR(err)
-
-#ifndef readq_relaxed
-#define readq_relaxed(addr) readq(addr)
-#endif
-
-#ifndef readl_relaxed
-#define readl_relaxed(addr) readl(addr)
-#endif
-
-#ifndef readw_relaxed
-#define readw_relaxed(addr) readw(addr)
-#endif
-
-#ifndef readb_relaxed
-#define readb_relaxed(addr) readb(addr)
-#endif
-
-#ifndef writeq_relaxed
-#define writeq_relaxed(val, addr) writeq((val), (addr))
-#endif
-
-#ifndef writel_relaxed
-#define writel_relaxed(val, addr) writel((val), (addr))
-#endif
-
-#ifndef writew_relaxed
-#define writew_relaxed(val, addr) writew((val), (addr))
-#endif
-
-#ifndef writeb_relaxed
-#define writeb_relaxed(val, addr) writeb((val), (addr))
-#endif
-
 #endif /* __IO_H */
-- 
2.39.2




[PATCH 03/18] bitops: split off linux/bits.h

2023-11-10 Thread Ahmad Fatoum
The bit definitions are split off in Linux into , which
is included by  and extended with bit operations.

Follow through in barebox to simplify porting kernel code and in future
to speed up the build a bit by avoiding pulling in the whole bitops.h,
when only needing macros like BIT().

Signed-off-by: Ahmad Fatoum 
---
 include/linux/bitops.h | 21 +
 include/linux/bits.h   | 30 ++
 2 files changed, 31 insertions(+), 20 deletions(-)
 create mode 100644 include/linux/bits.h

diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index a5f6ac6545ee..65061946130c 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -5,15 +5,9 @@
 
 #include 
 #include 
+#include 
 
 #ifdef __KERNEL__
-#define BIT(nr)(UL(1) << (nr))
-#define BIT_ULL(nr)(ULL(1) << (nr))
-#define BIT_MASK(nr)   (UL(1) << ((nr) % BITS_PER_LONG))
-#define BIT_WORD(nr)   ((nr) / BITS_PER_LONG)
-#define BIT_ULL_MASK(nr)   (ULL(1) << ((nr) % BITS_PER_LONG_LONG))
-#define BIT_ULL_WORD(nr)   ((nr) / BITS_PER_LONG_LONG)
-#define BITS_PER_BYTE  8
 #define BITS_PER_TYPE(type)(sizeof(type) * BITS_PER_BYTE)
 #define BITS_TO_LONGS(nr)  DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
 #define BITS_TO_U64(nr)DIV_ROUND_UP(nr, BITS_PER_TYPE(u64))
@@ -21,19 +15,6 @@
 #define BITS_TO_BYTES(nr)  DIV_ROUND_UP(nr, BITS_PER_TYPE(char))
 #endif
 
-/*
- * Create a contiguous bitmask starting at bit position @l and ending at
- * position @h. For example
- * GENMASK_ULL(39, 21) gives us the 64bit vector 0x00e0.
- */
-#define GENMASK(h, l) \
-   (((~UL(0)) - (UL(1) << (l)) + 1) & \
-(~UL(0) >> (BITS_PER_LONG - 1 - (h
-
-#define GENMASK_ULL(h, l) \
-   (((~ULL(0)) - (ULL(1) << (l)) + 1) & \
-(~ULL(0) >> (BITS_PER_LONG_LONG - 1 - (h
-
 #ifndef __ASSEMBLY__
 /*
  * Include this here because some architectures need generic_ffs/fls in
diff --git a/include/linux/bits.h b/include/linux/bits.h
new file mode 100644
index ..ea5dfa120102
--- /dev/null
+++ b/include/linux/bits.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_BITS_H
+#define __LINUX_BITS_H
+
+#include 
+#include 
+#include 
+
+#define BIT(nr)(UL(1) << (nr))
+#define BIT_ULL(nr)(ULL(1) << (nr))
+#define BIT_MASK(nr)   (UL(1) << ((nr) % BITS_PER_LONG))
+#define BIT_WORD(nr)   ((nr) / BITS_PER_LONG)
+#define BIT_ULL_MASK(nr)   (ULL(1) << ((nr) % BITS_PER_LONG_LONG))
+#define BIT_ULL_WORD(nr)   ((nr) / BITS_PER_LONG_LONG)
+#define BITS_PER_BYTE  8
+
+/*
+ * Create a contiguous bitmask starting at bit position @l and ending at
+ * position @h. For example
+ * GENMASK_ULL(39, 21) gives us the 64bit vector 0x00e0.
+ */
+#define GENMASK(h, l) \
+   (((~UL(0)) - (UL(1) << (l)) + 1) & \
+(~UL(0) >> (BITS_PER_LONG - 1 - (h
+
+#define GENMASK_ULL(h, l) \
+   (((~ULL(0)) - (ULL(1) << (l)) + 1) & \
+(~ULL(0) >> (BITS_PER_LONG_LONG - 1 - (h
+
+#endif /* __LINUX_BITS_H */
-- 
2.39.2




[PATCH 01/18] include: provide linux/errno.h

2023-11-10 Thread Ahmad Fatoum
We don't have the historic baggage of having to support different errno
definitions depending on architecture. We thus have only
asm-generic/errno.h and include that from errno.h and elsewhere
directly.

Kernel code however includes , so let's provide that file
as well and define there the Linux-specific errno's and include
 for all other errnos.

Signed-off-by: Ahmad Fatoum 
---
 arch/powerpc/lib/misc.S |  2 +-
 arch/powerpc/lib/ppcstring.S|  2 +-
 common/optee.c  |  2 +-
 include/asm-generic/errno.h | 11 --
 include/bbu.h   |  2 +-
 include/errno.h |  2 +-
 include/linux/err.h |  2 +-
 include/linux/errno.h   | 36 +
 include/linux/pstore.h  |  2 +-
 include/mach/at91/iomux.h   |  2 +-
 include/tee/optee.h |  2 +-
 lib/reed_solomon/reed_solomon.c |  2 +-
 12 files changed, 46 insertions(+), 21 deletions(-)
 create mode 100644 include/linux/errno.h

diff --git a/arch/powerpc/lib/misc.S b/arch/powerpc/lib/misc.S
index c45f02ba3af0..024d26ed58e9 100644
--- a/arch/powerpc/lib/misc.S
+++ b/arch/powerpc/lib/misc.S
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 
 #include 
-#include 
+#include 
 
.globl  __ashrdi3
 __ashrdi3:
diff --git a/arch/powerpc/lib/ppcstring.S b/arch/powerpc/lib/ppcstring.S
index cce85e3252a8..55f96cc9a448 100644
--- a/arch/powerpc/lib/ppcstring.S
+++ b/arch/powerpc/lib/ppcstring.S
@@ -9,7 +9,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 #include 
-#include 
+#include 
 
.globl  strcpy
 strcpy:
diff --git a/common/optee.c b/common/optee.c
index b460fbcd0161..32a6c0a15b94 100644
--- a/common/optee.c
+++ b/common/optee.c
@@ -4,7 +4,7 @@
 
 #include 
 #include 
-#include 
+#include 
 
 int optee_verify_header(struct optee_header *hdr)
 {
diff --git a/include/asm-generic/errno.h b/include/asm-generic/errno.h
index a96f8864dfd4..7629d5c8dd58 100644
--- a/include/asm-generic/errno.h
+++ b/include/asm-generic/errno.h
@@ -134,15 +134,4 @@
 #defineEKEYREVOKED 128 /* Key has been revoked */
 #defineEKEYREJECTED129 /* Key was rejected by service */
 
-/* Should never be seen by user programs */
-#define ERESTARTSYS512
-#define ERESTARTNOINTR 513
-#define ERESTARTNOHAND 514 /* restart if no handler.. */
-#define ENOIOCTLCMD515 /* No ioctl command */
-#define EPROBE_DEFER   517 /* Driver requests probe retry */
-
-#define ENOTSUPP   524 /* Operation is not supported */
-
-#define _LAST_ERRNO524
-
 #endif
diff --git a/include/bbu.h b/include/bbu.h
index cec7e22d4d90..0a4f324ade5b 100644
--- a/include/bbu.h
+++ b/include/bbu.h
@@ -2,7 +2,7 @@
 #ifndef __INCLUDE_BBU_H
 #define __INCLUDE_BBU_H
 
-#include 
+#include 
 #include 
 #include 
 #include 
diff --git a/include/errno.h b/include/errno.h
index 164426596604..6ec7af4d7e9f 100644
--- a/include/errno.h
+++ b/include/errno.h
@@ -2,7 +2,7 @@
 #ifndef __ERRNO_H
 #define __ERRNO_H
 
-#include 
+#include 
 #include 
 
 extern int errno;
diff --git a/include/linux/err.h b/include/linux/err.h
index db7ad6cc5bfa..d743b4d0928a 100644
--- a/include/linux/err.h
+++ b/include/linux/err.h
@@ -5,7 +5,7 @@
 
 #include 
 
-#include 
+#include 
 
 /*
  * Kernel pointers have redundant information, so we can use a
diff --git a/include/linux/errno.h b/include/linux/errno.h
new file mode 100644
index ..b3bf44d24936
--- /dev/null
+++ b/include/linux/errno.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_ERRNO_H
+#define _LINUX_ERRNO_H
+
+#include 
+
+
+/*
+ * These should never be seen by user programs.  To return one of ERESTART*
+ * codes, signal_pending() MUST be set.  Note that ptrace can observe these
+ * at syscall exit tracing, but they will never be left for the debugged user
+ * process to see.
+ */
+#define ERESTARTSYS512
+#define ERESTARTNOINTR 513
+#define ERESTARTNOHAND 514 /* restart if no handler.. */
+#define ENOIOCTLCMD515 /* No ioctl command */
+#define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
+#define EPROBE_DEFER   517 /* Driver requests probe retry */
+#define EOPENSTALE 518 /* open found a stale dentry */
+#define ENOPARAM   519 /* Parameter not supported */
+
+/* Defined for the NFSv3 protocol */
+#define EBADHANDLE 521 /* Illegal NFS file handle */
+#define ENOTSYNC   522 /* Update synchronization mismatch */
+#define EBADCOOKIE 523 /* Cookie is stale */
+#define ENOTSUPP   524 /* Operation is not supported */
+#define ETOOSMALL  525 /* Buffer or request is too small */
+#define ESERVERFAULT   526 /* An untranslatable error occurred */
+#define EBADTYPE   527 /* Type not supported by server */
+#define EJUKEBOX   528 /* Request initiated, but will not complete 
before timeout */
+#define EIOCBQUEUED529 /* iocb 

[PATCH 09/18] string: implement strscpy

2023-11-10 Thread Ahmad Fatoum
strscpy is meant to be a safer alternative to strscpy, which always
terminates the destination string and returns an error code if
truncation happens. To enable porting kernel code using it, import the
definition.

Signed-off-by: Ahmad Fatoum 
---
 include/linux/string.h |  3 ++
 lib/string.c   | 71 ++
 2 files changed, 74 insertions(+)

diff --git a/include/linux/string.h b/include/linux/string.h
index 75c8cf818b39..32ce56939699 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -46,6 +46,9 @@ extern char * strncpy(char *,const char *, __kernel_size_t);
 #ifndef __HAVE_ARCH_STRLCPY
 size_t strlcpy(char *, const char *, size_t);
 #endif
+#ifndef __HAVE_ARCH_STRSCPY
+ssize_t strscpy(char *, const char *, size_t);
+#endif
 #ifndef __HAVE_ARCH_STRCAT
 extern char * strcat(char *, const char *);
 #endif
diff --git a/lib/string.c b/lib/string.c
index 166ef190d6aa..bf0f0455ab3f 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #ifndef __HAVE_ARCH_STRCASECMP
@@ -87,6 +88,76 @@ char * strcpy(char * dest,const char *src)
 #endif
 EXPORT_SYMBOL(strcpy);
 
+#ifndef __HAVE_ARCH_STRSCPY
+ssize_t strscpy(char *dest, const char *src, size_t count)
+{
+   const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
+   size_t max = count;
+   long res = 0;
+
+   if (count == 0 || WARN_ON_ONCE(count > INT_MAX))
+   return -E2BIG;
+
+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+   /*
+* If src is unaligned, don't cross a page boundary,
+* since we don't know if the next page is mapped.
+*/
+   if ((long)src & (sizeof(long) - 1)) {
+   size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1));
+   if (limit < max)
+   max = limit;
+   }
+#else
+   /* If src or dest is unaligned, don't do word-at-a-time. */
+   if (((long) dest | (long) src) & (sizeof(long) - 1))
+   max = 0;
+#endif
+
+   /*
+* read_word_at_a_time() below may read uninitialized bytes after the
+* trailing zero and use them in comparisons. Disable this optimization
+* under KMSAN to prevent false positive reports.
+*/
+   if (IS_ENABLED(CONFIG_KMSAN))
+   max = 0;
+
+   while (max >= sizeof(unsigned long)) {
+   unsigned long c, data;
+
+   c = read_word_at_a_time(src+res);
+   if (has_zero(c, , )) {
+   data = prep_zero_mask(c, data, );
+   data = create_zero_mask(data);
+   *(unsigned long *)(dest+res) = c & zero_bytemask(data);
+   return res + find_zero(data);
+   }
+   *(unsigned long *)(dest+res) = c;
+   res += sizeof(unsigned long);
+   count -= sizeof(unsigned long);
+   max -= sizeof(unsigned long);
+   }
+
+   while (count) {
+   char c;
+
+   c = src[res];
+   dest[res] = c;
+   if (!c)
+   return res;
+   res++;
+   count--;
+   }
+
+   /* Hit buffer length without finding a NUL; force NUL-termination. */
+   if (res)
+   dest[res-1] = '\0';
+
+   return -E2BIG;
+}
+EXPORT_SYMBOL(strscpy);
+#endif
+
 /**
  * stpcpy - Copy a %NUL terminated string, but return pointer to %NUL
  * @dest: Where to copy the string to
-- 
2.39.2




Re: [PATCH master] resource: align memory reservation to page boundaries

2023-11-10 Thread Sascha Hauer
On Thu, Nov 09, 2023 at 12:30:12PM +0100, Ahmad Fatoum wrote:
> barebox remaps all reserved entries as uncached to avoid speculative
> access into the described regions using remap_range.
> 
> The ARM implementation requires buffers to be page aligned, which we
> can't assume unconditionally. For this reason, reserve_sdram_region
> will align region start and size before mapping uncached.
> 
> __mmu_init called later on, will remap everything outside the reserved
> entries cached, e.g. to cache additional DRAM not known at PBL time.
> No realignment will happen then though triggering the BUG(!IS_ALIGNED)
> in ARM's arch_remap_range.
> 
> By moving the realignment before __request_sdram_region(), we ensure
> that no misaligned memory regions will be passed to arch_remap_range by
> core code.
> 
> This fixes chainloading barebox from an older barebox[1] that reserves
> the FDT prior to relocation.
> 
> [1]: anything prior to 0b6b146a5508 ("fdt: Do not reserve device tree blob")
> 
> Reported-by: Uwe Kleine-König 
> Signed-off-by: Ahmad Fatoum 
> ---
>  common/memory.c | 8 
>  1 file changed, 4 insertions(+), 4 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/common/memory.c b/common/memory.c
> index d560d444b0a8..300320f85344 100644
> --- a/common/memory.c
> +++ b/common/memory.c
> @@ -218,10 +218,6 @@ struct resource *reserve_sdram_region(const char *name, 
> resource_size_t start,
>  {
>   struct resource *res;
>  
> - res = __request_sdram_region(name, IORESOURCE_BUSY, start, size);
> - if (IS_ERR(res))
> - return ERR_CAST(res);
> -
>   if (!IS_ALIGNED(start, PAGE_SIZE)) {
>   pr_err("%s: %s start is not page aligned\n", __func__, name);
>   start = ALIGN_DOWN(start, PAGE_SIZE);
> @@ -232,6 +228,10 @@ struct resource *reserve_sdram_region(const char *name, 
> resource_size_t start,
>   size = ALIGN(size, PAGE_SIZE);
>   }
>  
> + res = __request_sdram_region(name, IORESOURCE_BUSY, start, size);
> + if (IS_ERR(res))
> + return ERR_CAST(res);
> +
>   remap_range((void *)start, size, MAP_UNCACHED);
>  
>   return res;
> -- 
> 2.39.2
> 
> 
> 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |



Re: [PATCH] x86: efi: add IMD data to the EFI binary

2023-11-10 Thread Sascha Hauer
On Fri, Nov 03, 2023 at 04:58:31PM +0100, Michael Olbrich wrote:
> It it currently missing so the imd command and the bareboximd tool do
> not work.
> 
> Add the .barebox_imd section to the linker script and copy it to the EFI
> binary.
> 
> Signed-off-by: Michael Olbrich 
> ---
>  arch/x86/Makefile  | 2 +-
>  arch/x86/mach-efi/elf_x86_64_efi.lds.S | 2 ++
>  2 files changed, 3 insertions(+), 1 deletion(-)

Applied, thanks

Sascha

> 
> diff --git a/arch/x86/Makefile b/arch/x86/Makefile
> index a0ce8c17f181..019c1adb7781 100644
> --- a/arch/x86/Makefile
> +++ b/arch/x86/Makefile
> @@ -60,7 +60,7 @@ KBUILD_LDFLAGS := --no-undefined
>  
>  OBJCOPYFLAGS_barebox.efi = \
>   -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela \
> - -j .reloc -j .bbenv.* -j .bblogo.* --target=$(TARGET)
> + -j .reloc -j .bbenv.* -j .bblogo.* -j .barebox_imd --target=$(TARGET)
>  
>  barebox.efi: $(KBUILD_BINARY) FORCE
>   $(call if_changed,objcopy)
> diff --git a/arch/x86/mach-efi/elf_x86_64_efi.lds.S 
> b/arch/x86/mach-efi/elf_x86_64_efi.lds.S
> index ab4a9e815c00..52a0d3db2d6c 100644
> --- a/arch/x86/mach-efi/elf_x86_64_efi.lds.S
> +++ b/arch/x86/mach-efi/elf_x86_64_efi.lds.S
> @@ -56,6 +56,8 @@ SECTIONS
>   }
>   _edata = .;
>  
> + .barebox_imd : { BAREBOX_IMD }
> +
>   . = ALIGN(4096);
>   .dynamic : { *(.dynamic) }
>   . = ALIGN(4096);
> -- 
> 2.39.2
> 
> 
> 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |



Re: [PATCH] test: self: mmu: skip false positive test fail when no RAM at address 0

2023-11-10 Thread Sascha Hauer
On Thu, Nov 09, 2023 at 04:29:46PM +0100, Ahmad Fatoum wrote:
> Testing zero_page_access only makes sense if we actually have RAM at
> address 0 that we may read from. If it happens to I/O memory, the SoC
> may hang or a data abort may be raised, which would make the test fail.
> 
> Avoid this by explicitly checking for that case and skipping the test
> without running.
> 
> Signed-off-by: Ahmad Fatoum 
> ---
>  test/self/mmu.c | 33 ++---
>  1 file changed, 30 insertions(+), 3 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/test/self/mmu.c b/test/self/mmu.c
> index ca58d718ffb3..58961daaab95 100644
> --- a/test/self/mmu.c
> +++ b/test/self/mmu.c
> @@ -9,6 +9,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #define TEST_BUFFER_SIZE SZ_1M
>  #define TEST_BUFFER_ALIGNSZ_4K
> @@ -171,6 +172,34 @@ static void test_remap(void)
>   free(mirror);
>  }
>  
> +static bool zero_page_access_ok(void)
> +{
> + struct memory_bank *bank;
> + const char *reason;
> + struct resource null_res = {
> + .name = "null",
> + .flags = IORESOURCE_MEM,
> + .start = 0,
> + .end = sizeof(int) - 1,
> + };
> +
> + if (!IS_ENABLED(CONFIG_ARCH_HAS_ZERO_PAGE)) {
> + reason = "CONFIG_ARCH_HAS_ZERO_PAGE=n";
> + goto not_ok;
> + }
> +
> + for_each_memory_bank(bank) {
> + if (resource_contains(bank->res, _res))
> + return true;
> + }
> +
> + reason = "no memory at address zero";
> +
> +not_ok:
> + pr_info("skipping rest of zero page tests because %s\n", reason);
> + return false;
> +}
> +
>  static void test_zero_page(void)
>  {
>   void __iomem *null = NULL;
> @@ -197,9 +226,7 @@ static void test_zero_page(void)
>   failed_tests++;
>   }
>  
> - if (!IS_ENABLED(CONFIG_ARCH_HAS_ZERO_PAGE)) {
> - pr_info("skipping %s because %s=n\n",
> - "CONFIG_ARCH_HAS_ZERO_PAGE", __func__);
> + if (!zero_page_access_ok()) {
>   skipped_tests += 2;
>   return;
>   }
> -- 
> 2.39.2
> 
> 
> 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |



Re: [PATCH] test: self: malloc: hide allocation size from compiler

2023-11-10 Thread Sascha Hauer
On Thu, Nov 09, 2023 at 02:38:12PM +0100, Ahmad Fatoum wrote:
> Once we start annotating malloc with __attribute((alloc_size)), GCC will
> detect that we intentionally buffers that are too big.
> 
> Avoid the warning by hiding the size using the RELOC_HIDE macro.
> 
> Signed-off-by: Ahmad Fatoum 
> ---
>  test/self/malloc.c | 8 
>  1 file changed, 4 insertions(+), 4 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/test/self/malloc.c b/test/self/malloc.c
> index 47c225ac6a10..0feec810185f 100644
> --- a/test/self/malloc.c
> +++ b/test/self/malloc.c
> @@ -85,11 +85,11 @@ static void test_malloc(void)
>   free(p);
>  
>   if (mem_malloc_size) {
> - tmp = expect_alloc_fail(malloc(SIZE_MAX));
> + tmp = expect_alloc_fail(malloc(RELOC_HIDE(SIZE_MAX, 0)));
>   free(tmp);
>  
>   if (0xf000 > mem_malloc_size) {
> - tmp = expect_alloc_fail(malloc(0xf000));
> + tmp = expect_alloc_fail(malloc(RELOC_HIDE(0xf000, 
> 0)));
>   free(tmp);
>   }
>   } else {
> @@ -111,11 +111,11 @@ static void test_malloc(void)
>   free(tmp);
>  
>   if (0xf000 > mem_malloc_size) {
> - tmp = expect_alloc_fail(realloc(p, 0xf000));
> + tmp = expect_alloc_fail(realloc(p, 
> RELOC_HIDE(0xf000, 0)));
>   free(tmp);
>   }
>  
> - tmp = expect_alloc_fail(realloc(p, SIZE_MAX));
> + tmp = expect_alloc_fail(realloc(p, RELOC_HIDE(SIZE_MAX, 0)));
>   free(tmp);
>  
>   } else {
> -- 
> 2.39.2
> 
> 
> 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |



Re: [PATCH] ARM: stm32mp: fix typo in STM32MP135-DK prompt

2023-11-10 Thread Sascha Hauer
On Thu, Nov 09, 2023 at 02:02:53PM +0100, Ahmad Fatoum wrote:
> The board is called STM32MP135 and there is currently no STM32MP137.
> The typo was likely caused by copy-pasting from the STM32MP15x, which
> has STM32MP157.
> 
> Signed-off-by: Ahmad Fatoum 
> ---
>  arch/arm/mach-stm32mp/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied, thanks

Sascha

> 
> diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig
> index bc0a48d64c82..524d282a1db8 100644
> --- a/arch/arm/mach-stm32mp/Kconfig
> +++ b/arch/arm/mach-stm32mp/Kconfig
> @@ -16,7 +16,7 @@ config ARCH_STM32MP157
>  
>  config MACH_STM32MP13XX_DK
>   select ARCH_STM32MP13
> - bool "STM32MP137F DK board"
> + bool "STM32MP135F DK board"
>  
>  config MACH_STM32MP15XX_DKX
>   select ARCH_STM32MP157
> -- 
> 2.39.2
> 
> 
> 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |



Re: [PATCH] include: spinlock.h: mark DEFINE_SPINLOCK with __always_unused

2023-11-10 Thread Sascha Hauer
On Thu, Nov 09, 2023 at 01:29:45PM +0100, Ahmad Fatoum wrote:
> The spinlock stubs don't actually do anything with the spinlock_t.
> To avoid the compiler warning about it add an __always_unused annotation
> to the spinlock.
> 
> Signed-off-by: Ahmad Fatoum 
> ---
>  include/linux/spinlock.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied, thanks

Sascha

> 
> diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
> index a604e0fd090f..6f90fb1cad43 100644
> --- a/include/linux/spinlock.h
> +++ b/include/linux/spinlock.h
> @@ -12,6 +12,6 @@ typedef int   spinlock_t;
>  #define spin_lock_irqsave(lock, flags) do { flags = 0; } while (0)
>  #define spin_unlock_irqrestore(lock, flags) do { flags = flags; } while (0)
>  
> -#define DEFINE_SPINLOCK(lock) spinlock_t lock
> +#define DEFINE_SPINLOCK(lock) spinlock_t __always_unused lock
>  
>  #endif /* __LINUX_SPINLOCK_H */
> -- 
> 2.39.2
> 
> 
> 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |



Re: [PATCH master] scripts: setlocalversion: sync with Linux

2023-11-10 Thread Sascha Hauer
On Thu, Nov 09, 2023 at 12:38:35PM +0100, Ahmad Fatoum wrote:
> We are using an older version of setlocalversion that sources the
> config. This is wrong as there's no guarantee that it's ok to source the
> config, e.g.:
> 
>   CONFIG_DEFAULT_ENVIRONMENT_PATH="$(objtree)/.ptxdist-defaultenv"
> 
> when sourced will lead to:
> 
>   scripts/setlocalversion: 15: include/config/auto.conf: objtree: not found
> 
> Fix this by grepping the file instead.
> 
> Signed-off-by: Ahmad Fatoum 
> ---
>  scripts/setlocalversion | 11 ++-
>  1 file changed, 6 insertions(+), 5 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/scripts/setlocalversion b/scripts/setlocalversion
> index 6b54e46a0f12..cbd3883df9ae 100755
> --- a/scripts/setlocalversion
> +++ b/scripts/setlocalversion
> @@ -111,13 +111,14 @@ if $scm_only; then
>   exit
>  fi
>  
> -if test -e include/config/auto.conf; then
> - . include/config/auto.conf
> -else
> +if ! test -e include/config/auto.conf; then
>   echo "Error: kernelrelease not valid - run 'make prepare' to update it" 
> >&2
>   exit 1
>  fi
>  
> +# version string from CONFIG_LOCALVERSION
> +config_localversion=$(sed -n 's/^CONFIG_LOCALVERSION=\(.*\)$/\1/p' 
> include/config/auto.conf)
> +
>  # localversion* files in the build and source directory
>  res="$(collect_files localversion*)"
>  if test ! "$srctree" -ef .; then
> @@ -125,10 +126,10 @@ if test ! "$srctree" -ef .; then
>  fi
>  
>  # CONFIG_LOCALVERSION and LOCALVERSION (if set)
> -res="${res}${CONFIG_LOCALVERSION}${LOCALVERSION}"
> +res="${res}${config_localversion}${LOCALVERSION}"
>  
>  # scm version string if not at a tagged commit
> -if test "$CONFIG_LOCALVERSION_AUTO" = "y"; then
> +if grep -q "^CONFIG_LOCALVERSION_AUTO=y$" include/config/auto.conf; then
>   # full scm version string
>   res="$res$(scm_version)"
>  elif [ "${LOCALVERSION+set}" != "set" ]; then
> -- 
> 2.39.2
> 
> 
> 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |



Re: [PATCH] include: pm_domain.h: make header self-contained

2023-11-10 Thread Sascha Hauer
On Thu, Nov 09, 2023 at 01:11:08PM +0100, Ahmad Fatoum wrote:
> pm_domain.h so far included no headers and only worked, because it was
> included in a "correct" order in other files. Fix this by including the
> header it depends on.
> 
> Signed-off-by: Ahmad Fatoum 
> ---
>  include/pm_domain.h | 3 +++
>  1 file changed, 3 insertions(+)

Applied, thanks

Sascha

> 
> diff --git a/include/pm_domain.h b/include/pm_domain.h
> index a7e46c86b9cb..ac0ec477b6b1 100644
> --- a/include/pm_domain.h
> +++ b/include/pm_domain.h
> @@ -3,6 +3,9 @@
>  #ifndef _PM_DOMAIN_H
>  #define _PM_DOMAIN_H
>  
> +#include 
> +#include 
> +
>  enum gpd_status {
>   GPD_STATE_ACTIVE = 0,   /* PM domain is active */
>   GPD_STATE_POWER_OFF,/* PM domain is off */
> -- 
> 2.39.2
> 
> 
> 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |



Re: [PATCH master] phy: stm32-usbphyc: fix unbalanced phy exit

2023-11-10 Thread Sascha Hauer
On Thu, Nov 09, 2023 at 01:10:12PM +0100, Ahmad Fatoum wrote:
> On the STM32MP1, shutting down barebox can result in a
> 
>   ERROR: phy1: phy exit failed --> -22
> 
> message printed to the console. This is because the regulator is disabled
> more often than it was enabled, because stm32_usbphyc_pll_disable
> is called twice:
> 
>   - Once from stm32_usbphyc_remove calling stm32_usbphyc_phy_exit
>   - Once from dwc2_remove calling phy_exit -> stm32_usbphyc_phy_exit
> 
> The code is taken from Linux and likely causes no issues there, because
> devices are removed in reverse probe order, which barebox doesn't
> enforce. Properly solving this would be a larger endeavour, so for now
> just fix the stm32-usbphyc driver to ignore reference count dropping
> below zero and only call __stm32_usbphyc_pll_disable once.
> 
> Signed-off-by: Ahmad Fatoum 
> ---
>  drivers/phy/phy-stm32-usbphyc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c
> index ac82b019f44c..91f4e7f7e08d 100644
> --- a/drivers/phy/phy-stm32-usbphyc.c
> +++ b/drivers/phy/phy-stm32-usbphyc.c
> @@ -277,7 +277,7 @@ static int __stm32_usbphyc_pll_disable(struct 
> stm32_usbphyc *usbphyc)
>  static int stm32_usbphyc_pll_disable(struct stm32_usbphyc *usbphyc)
>  {
>   /* Check if a phy port is still active or clk48 in use */
> - if (atomic_dec_return(>n_pll_cons) > 0)
> + if (atomic_dec_return(>n_pll_cons) != 1)
>   return 0;
>  
>   return __stm32_usbphyc_pll_disable(usbphyc);
> -- 
> 2.39.2
> 
> 
> 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |



Re: [PATCH] barebox-wrapper: define stub for MODULE_VERSION

2023-11-10 Thread Sascha Hauer
On Thu, Nov 09, 2023 at 01:00:45PM +0100, Ahmad Fatoum wrote:
> We already stub out a number of MODULE_* macros to save porters the
> hassle of deleting them. Let's add MODULE_VERSION to the list as well.
> 
> Signed-off-by: Ahmad Fatoum 
> ---
>  include/linux/barebox-wrapper.h | 1 +
>  1 file changed, 1 insertion(+)

Applied, thanks

Sascha

> 
> diff --git a/include/linux/barebox-wrapper.h b/include/linux/barebox-wrapper.h
> index ed237877fc75..5d311e1d70f4 100644
> --- a/include/linux/barebox-wrapper.h
> +++ b/include/linux/barebox-wrapper.h
> @@ -19,6 +19,7 @@ static inline void vfree(const void *addr)
>  #define MODULE_AUTHOR(x)
>  #define MODULE_DESCRIPTION(x)
>  #define MODULE_LICENSE(x)
> +#define MODULE_VERSION(x)
>  #define MODULE_ALIAS(x)
>  #define MODULE_DEVICE_TABLE(bus, table)
>  #define MODULE_ALIAS_DSA_TAG_DRIVER(drv)
> -- 
> 2.39.2
> 
> 
> 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |



Re: [PATCH master] efi: acpi: fix printf format specifier mismatch

2023-11-10 Thread Sascha Hauer
On Thu, Nov 09, 2023 at 12:59:54PM +0100, Ahmad Fatoum wrote:
> entry_count has type size_t and not long as the format string wrongly
> suggested.
> 
> Signed-off-by: Ahmad Fatoum 
> ---
>  drivers/bus/acpi.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/bus/acpi.c b/drivers/bus/acpi.c
> index f69789200633..ac034cce4569 100644
> --- a/drivers/bus/acpi.c
> +++ b/drivers/bus/acpi.c
> @@ -186,7 +186,7 @@ static int acpi_register_devices(struct bus_type *bus)
>   return -EIO;
>   }
>  
> - dev_info(bus->dev, "Found %s (OEM: %.8s) with %lu entries\n",
> + dev_info(bus->dev, "Found %s (OEM: %.8s) with %zu entries\n",
>   sig, root->sdt.oem_id, entry_count);
>  
>   for (i = 0; i < entry_count; i++) {
> -- 
> 2.39.2
> 
> 
> 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |



Re: [PATCH master] mfd: syscon: don't register clocked syscon if geting clock fails

2023-11-10 Thread Sascha Hauer
On Thu, Nov 09, 2023 at 12:55:22PM +0100, Ahmad Fatoum wrote:
> When of_syscon_register is called with check_clk=true, it will attempt
> to attach the clock. If that fails, the newly allocated syscon is freed,
> but a dangling pointer remained in the syscon_list.
> 
> Fix this by only registering the syscon in the successful case.
> 
> Fixes: b36b7b727192 ("mfd: syscon: clock peripheral if specified in device 
> tree")
> Signed-off-by: Ahmad Fatoum 
> ---
>  drivers/mfd/syscon.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
> index 3e12123b572e..3c2e1241fdff 100644
> --- a/drivers/mfd/syscon.c
> +++ b/drivers/mfd/syscon.c
> @@ -74,8 +74,6 @@ static struct syscon *of_syscon_register(struct device_node 
> *np, bool check_clk)
>   syscon_config.val_bits = reg_io_width * 8;
>   syscon_config.max_register = resource_size() - reg_io_width;
>  
> - list_add_tail(>list, _list);
> -
>   syscon->regmap = regmap_init_mmio_clk(NULL, NULL, syscon->base,
> _config);
>  
> @@ -93,6 +91,8 @@ static struct syscon *of_syscon_register(struct device_node 
> *np, bool check_clk)
>   }
>   }
>  
> + list_add_tail(>list, _list);
> +
>   return syscon;
>  
>  err_map:
> -- 
> 2.39.2
> 
> 
> 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |



Re: Rockchip rk3328 support?

2023-11-10 Thread Konstantin Kletschke
Hi Sascha,

On Fri, Nov 10, 2023 at 01:42:06PM +0100, Sascha Hauer wrote:

> The rk3328 is not yet supported. We have support for rk3568 and rk3288
> though, so the ground work for generally supporting Rockchip SoCs has

Ok

> been done. I don't know how similar the rk3328 is to the supported SoCs,
> you could have a look at the Kernel or U-Boot to see how close they are.

Actually I am fighting with u-boot. There are Dusun SDKs with all
sources available but what they are using are ancient 2017.09 u-boot
version which are forked in mirrors rooting to a rockchip github tree.

Now I am fighting with a Dusun SDK using a rather vanilla 2022 u-boot
which is not the same, I just managed to get a working SDRAM setup. Now
reading MMC gives mmc block read error probably yielding to DT setup
issues.

Then we will investigate what has to be done among the common stuff
to put this into barebox.

Kind Regards
Konstantin





Re: [PATCH] usb: dwc2: use linux/spinlock.h for stubs

2023-11-10 Thread Sascha Hauer
On Thu, Nov 09, 2023 at 12:48:38PM +0100, Ahmad Fatoum wrote:
> We already have dummy definitions for common spin lock operations,
> so reuse them instead of defining them in the driver.
> 
> Signed-off-by: Ahmad Fatoum 
> ---
>  drivers/usb/dwc2/gadget.c | 5 +
>  1 file changed, 1 insertion(+), 4 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
> index 00323d2d9029..3c06c438b65d 100644
> --- a/drivers/usb/dwc2/gadget.c
> +++ b/drivers/usb/dwc2/gadget.c
> @@ -1,18 +1,15 @@
>  // SPDX-License-Identifier: GPL-2.0-or-later
>  #include 
>  #include 
> +#include 
>  #include "dwc2.h"
>  
>  #define to_dwc2 gadget_to_dwc2
>  #define dwc2_set_bit(d, r, b)dwc2_writel(d, (b) | dwc2_readl(d, r), 
> r)
>  #define dwc2_clear_bit(d, r, b)  dwc2_writel(d, ~(b) & dwc2_readl(d, r), 
> r)
>  
> -#define spin_lock(lock)
> -#define spin_unlock(lock)
>  #define local_irq_save(flags)(void)(flags)
>  #define local_irq_restore(flags) (void)(flags)
> -#define spin_lock_irqsave(lock, flags) (void)(flags)
> -#define spin_unlock_irqrestore(lock, flags) (void)(flags)
>  
>  static void kill_all_requests(struct dwc2 *, struct dwc2_ep *, int);
>  
> -- 
> 2.39.2
> 
> 
> 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |



Re: [PATCH 1/2] KASan: test_kasan: hide buggy accesses from compiler

2023-11-10 Thread Sascha Hauer
On Thu, Nov 09, 2023 at 12:38:06PM +0100, Ahmad Fatoum wrote:
> Once we add __alloc_size attributes to allocations, GCC will complain
> about violation of memory safety in test_kasan.c.
> 
> That memory violation is intended though as test_kasan is meant to
> trigger kasan at runtime to verify correct operation.
> 
> Silence the warnings by hiding the origin of ptr, so the compiler loses
> context about the size of the allocation.
> 
> Signed-off-by: Ahmad Fatoum 
> ---
>  lib/kasan/test_kasan.c | 11 +++
>  1 file changed, 11 insertions(+)

Applied, thanks

Sascha

> 
> diff --git a/lib/kasan/test_kasan.c b/lib/kasan/test_kasan.c
> index 14511cdb80bd..a74251a6d9ad 100644
> --- a/lib/kasan/test_kasan.c
> +++ b/lib/kasan/test_kasan.c
> @@ -38,6 +38,8 @@ static noinline void malloc_oob_right(void)
>   return;
>   }
>  
> + OPTIMIZER_HIDE_VAR(ptr);
> +
>   ptr[size] = 'x';
>  
>   free(ptr);
> @@ -55,6 +57,8 @@ static noinline void malloc_oob_left(void)
>   return;
>   }
>  
> + OPTIMIZER_HIDE_VAR(ptr);
> +
>   *ptr = *(ptr - 1);
>   free(ptr);
>  }
> @@ -75,6 +79,8 @@ static noinline void malloc_oob_realloc_more(void)
>   return;
>   }
>  
> + OPTIMIZER_HIDE_VAR(ptr2);
> +
>   ptr2[size2] = 'x';
>  
>   free(ptr2);
> @@ -95,6 +101,8 @@ static noinline void malloc_oob_realloc_less(void)
>   return;
>   }
>  
> + OPTIMIZER_HIDE_VAR(ptr2);
> +
>   ptr2[size2] = 'x';
>  
>   free(ptr2);
> @@ -115,6 +123,9 @@ static noinline void malloc_oob_16(void)
>   free(ptr2);
>   return;
>   }
> +
> + OPTIMIZER_HIDE_VAR(ptr1);
> +
>   *ptr1 = *ptr2;
>   free(ptr1);
>   free(ptr2);
> -- 
> 2.39.2
> 
> 
> 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |



[PATCH 2/2] mfd: pca9450: Add init callback

2023-11-10 Thread Sascha Hauer
We currently do not have regulator support for the pca945x chips,
so provide a init callback for board code to do the basic setup.

Signed-off-by: Sascha Hauer 
---
 drivers/mfd/pca9450.c | 21 +
 include/mfd/pca9450.h | 14 ++
 2 files changed, 35 insertions(+)

diff --git a/drivers/mfd/pca9450.c b/drivers/mfd/pca9450.c
index 20f6b016fa..8fa5363f8a 100644
--- a/drivers/mfd/pca9450.c
+++ b/drivers/mfd/pca9450.c
@@ -61,6 +61,23 @@ static int pca9450_get_reset_source(struct device *dev, 
struct regmap *map)
return 0;
 };
 
+static struct regmap *pca9450_map;
+
+static void (*pca9450_init_callback)(struct regmap *map);
+
+int pca9450_register_init_callback(void(*callback)(struct regmap *map))
+{
+   if (pca9450_init_callback)
+   return -EBUSY;
+
+   pca9450_init_callback = callback;
+
+   if (pca9450_map)
+   pca9450_init_callback(pca9450_map);
+
+   return 0;
+}
+
 static int __init pca9450_probe(struct device *dev)
 {
struct regmap *regmap;
@@ -84,6 +101,10 @@ static int __init pca9450_probe(struct device *dev)
/* Chip ID defined in bits [7:4] */
dev_info(dev, "PMIC Chip ID: 0x%x\n", (reg >> 4));
 
+   if (pca9450_init_callback)
+   pca9450_init_callback(regmap);
+   pca9450_map = regmap;
+
pca9450_get_reset_source(dev,regmap);
 
return of_platform_populate(dev->of_node, NULL, dev);
diff --git a/include/mfd/pca9450.h b/include/mfd/pca9450.h
index 256f661911..7071c3a9da 100644
--- a/include/mfd/pca9450.h
+++ b/include/mfd/pca9450.h
@@ -6,6 +6,8 @@
 #ifndef PCA9450_H_
 #define PCA9450_H_
 
+#include 
+
 enum {
PCA9450_REG_DEV_ID  = 0x00,
PCA9450_INT1= 0x01,
@@ -52,4 +54,16 @@ enum {
PCA9450_REG_NUM,
 };
 
+#ifdef CONFIG_MFD_PCA9450
+
+int pca9450_register_init_callback(void(*callback)(struct regmap *map));
+
+#else
+
+static inline int pca9450_register_init_callback(void(*callback)(struct regmap 
*map))
+{
+   return -ENODEV;
+}
+#endif
+
 #endif
-- 
2.39.2




[PATCH 1/2] mfd: pca9450: Add support for pca9451a

2023-11-10 Thread Sascha Hauer
Add support for the pca9451a chip variant. This is not compatible
with the other variants, but as we currently only provide a regmap
this is fine.

Signed-off-by: Sascha Hauer 
---
 drivers/mfd/pca9450.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mfd/pca9450.c b/drivers/mfd/pca9450.c
index cf0efab16f..20f6b016fa 100644
--- a/drivers/mfd/pca9450.c
+++ b/drivers/mfd/pca9450.c
@@ -92,6 +92,7 @@ static int __init pca9450_probe(struct device *dev)
 static __maybe_unused struct of_device_id pca9450_dt_ids[] = {
{ .compatible = "nxp,pca9450a" },
{ .compatible = "nxp,pca9450c" },
+   { .compatible = "nxp,pca9451a" },
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, pca9450_dt_ids);
-- 
2.39.2




[PATCH] mtd: spi-nor: add support for Winbond w25q512nwq

2023-11-10 Thread Sascha Hauer
Add entry for the Winbond w25q512nwq.

Signed-off-by: Sascha Hauer 
---
 drivers/mtd/spi-nor/spi-nor.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index ab61e7824c..5ad95ff50d 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -867,6 +867,7 @@ static const struct spi_device_id spi_nor_ids[] = {
{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
{ "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
{ "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128, SECT_4K) },
+   { "w25q512nwq", INFO(0xef6020, 0, 512 * 1024, 128, SECT_4K) },
{ "w25q80", INFO(0xef5014, 0, 64 * 1024,  16, SECT_4K) },
{ "w25q80bl", INFO(0xef4014, 0, 64 * 1024,  16, SECT_4K) },
{ "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
-- 
2.39.2




[PATCH] usb: gadget: i.MX: Move PBL USB gadget driver to arch/

2023-11-10 Thread Sascha Hauer
The i.MX PBL USB gadget driver is currently selected by architecture
Kconfig options. When USB gadget support is disabled then the build
system doesn't descend into the directory where the driver is, leading
to undefined references. We could change that and descend into the
directory unconditionally, but as the driver doesn't have any
dependencies to the USB gadget framework we can also move the driver
to arch/arm/mach-imx/ to solve this problem.

Signed-off-by: Sascha Hauer 
---
 arch/arm/mach-imx/Kconfig  | 3 +++
 arch/arm/mach-imx/Makefile | 1 +
 .../gadget/udc/fsl_udc_pbl.c => arch/arm/mach-imx/imx-udc.c| 0
 drivers/usb/gadget/Kconfig | 3 ---
 drivers/usb/gadget/udc/Makefile| 1 -
 5 files changed, 4 insertions(+), 4 deletions(-)
 rename drivers/usb/gadget/udc/fsl_udc_pbl.c => arch/arm/mach-imx/imx-udc.c 
(100%)

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 6a7d90e2c8..13d914cdb6 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -27,6 +27,9 @@ config BAREBOX_UPDATE_IMX_EXTERNAL_NAND
depends on MTD_WRITE
default y
 
+config USB_GADGET_DRIVER_ARC_PBL
+   bool
+
 config RESET_IMX_SRC
def_bool y
depends on ARCH_IMX6 || ARCH_IMX50 || ARCH_IMX51 || ARCH_IMX53
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index f49bbea2b4..9e8cb5eeb7 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_CMD_BOOTROM) += bootrom-cmd.o
 obj-pbl-y += esdctl.o boot.o
 obj-$(CONFIG_BAREBOX_UPDATE) += imx-bbu-internal.o
 obj-$(CONFIG_BAREBOX_UPDATE_IMX_EXTERNAL_NAND) += imx-bbu-external-nand.o
+pbl-$(CONFIG_USB_GADGET_DRIVER_ARC_PBL) += imx-udc.o
 obj-$(CONFIG_RESET_IMX_SRC) += src.o
 lwl-y += cpu_init.o
 pbl-y += xload-spi.o xload-common.o xload-imx-nand.o xload-gpmi-nand.o
diff --git a/drivers/usb/gadget/udc/fsl_udc_pbl.c b/arch/arm/mach-imx/imx-udc.c
similarity index 100%
rename from drivers/usb/gadget/udc/fsl_udc_pbl.c
rename to arch/arm/mach-imx/imx-udc.c
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index ffaf355936..517255f477 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -5,9 +5,6 @@ menuconfig USB_GADGET
select NLS
bool "USB gadget support"
 
-config USB_GADGET_DRIVER_ARC_PBL
-   bool
-
 if USB_GADGET
 
 config USB_GADGET_DUALSPEED
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile
index f52660fcf5..6e79e80cfa 100644
--- a/drivers/usb/gadget/udc/Makefile
+++ b/drivers/usb/gadget/udc/Makefile
@@ -3,6 +3,5 @@
 obj-$(CONFIG_USB_GADGET) += core.o
 
 obj-$(CONFIG_USB_GADGET_DRIVER_ARC) += fsl_udc.o
-pbl-$(CONFIG_USB_GADGET_DRIVER_ARC_PBL) += fsl_udc_pbl.o
 obj-$(CONFIG_USB_GADGET_DRIVER_AT91) += at91_udc.o
 obj-$(CONFIG_USB_GADGET_DRIVER_PXA27X) += pxa27x_udc.o
-- 
2.39.2




[PATCH 1/3] net: eqos: rename i.MX8 driver glue code to i.MX

2023-11-10 Thread Sascha Hauer
The i.MX8 glue code for the designware ethernet driver will be used by
i.MX9 as well. Rename the file accordingly.

Signed-off-by: Sascha Hauer 
---
 arch/arm/configs/imx_v8_defconfig |  2 +-
 arch/arm/configs/multi_v8_defconfig   |  2 +-
 drivers/net/Kconfig   |  6 +-
 drivers/net/Makefile  |  2 +-
 .../{designware_imx8.c => designware_imx.c}   | 58 +--
 5 files changed, 35 insertions(+), 35 deletions(-)
 rename drivers/net/{designware_imx8.c => designware_imx.c} (73%)

diff --git a/arch/arm/configs/imx_v8_defconfig 
b/arch/arm/configs/imx_v8_defconfig
index 8084e72ea0..66dab8c4a7 100644
--- a/arch/arm/configs/imx_v8_defconfig
+++ b/arch/arm/configs/imx_v8_defconfig
@@ -92,7 +92,7 @@ CONFIG_NET_NETCONSOLE=y
 CONFIG_OFDEVICE=y
 CONFIG_OF_BAREBOX_DRIVERS=y
 CONFIG_SERIAL_DEV_BUS=y
-CONFIG_DRIVER_NET_DESIGNWARE_IMX8=y
+CONFIG_DRIVER_NET_DESIGNWARE_IMX=y
 CONFIG_DRIVER_NET_FEC_IMX=y
 CONFIG_DP83867_PHY=y
 CONFIG_MICREL_PHY=y
diff --git a/arch/arm/configs/multi_v8_defconfig 
b/arch/arm/configs/multi_v8_defconfig
index 9c538e698d..2599519351 100644
--- a/arch/arm/configs/multi_v8_defconfig
+++ b/arch/arm/configs/multi_v8_defconfig
@@ -141,7 +141,7 @@ CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_DRIVER_SERIAL_NS16550=y
 CONFIG_DRIVER_SERIAL_CADENCE=y
 CONFIG_VIRTIO_CONSOLE=y
-CONFIG_DRIVER_NET_DESIGNWARE_IMX8=y
+CONFIG_DRIVER_NET_DESIGNWARE_IMX=y
 CONFIG_DRIVER_NET_DESIGNWARE_ROCKCHIP=y
 CONFIG_DRIVER_NET_FEC_IMX=y
 CONFIG_DRIVER_NET_MACB=y
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 1c89cf9e41..9be03cf20c 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -107,14 +107,14 @@ config DRIVER_NET_DESIGNWARE_EQOS
  This option enables support for the Synopsys
  Designware Ethernet Quality-of-Service (GMAC4).
 
-config DRIVER_NET_DESIGNWARE_IMX8
-   bool "Designware EQOS i.MX8 Ethernet driver"
+config DRIVER_NET_DESIGNWARE_IMX
+   bool "Designware EQOS i.MX Ethernet driver"
depends on HAS_DMA && COMMON_CLK && OFTREE && (ARCH_IMX8M || 
COMPILE_TEST)
select DRIVER_NET_DESIGNWARE_EQOS
select MFD_SYSCON
help
  This option enables support for the Designware EQOS MAC implemented on
- the NXP i.MX8 SoCs.
+ the NXP i.MX SoCs.
 
 config DRIVER_NET_DESIGNWARE_STM32
bool "STM32 Designware Ethernet driver"
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 1a272d9158..697b5bdfb7 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -15,7 +15,7 @@ obj-$(CONFIG_DRIVER_NET_DESIGNWARE_GENERIC) += 
designware_generic.o
 obj-$(CONFIG_DRIVER_NET_DESIGNWARE_SOCFPGA) += designware_socfpga.o
 obj-$(CONFIG_DRIVER_NET_DESIGNWARE_STARFIVE) += designware_starfive.o
 obj-$(CONFIG_DRIVER_NET_DESIGNWARE_EQOS) += designware_eqos.o
-obj-$(CONFIG_DRIVER_NET_DESIGNWARE_IMX8) += designware_imx8.o
+obj-$(CONFIG_DRIVER_NET_DESIGNWARE_IMX) += designware_imx.o
 obj-$(CONFIG_DRIVER_NET_DESIGNWARE_STM32) += designware_stm32.o
 obj-$(CONFIG_DRIVER_NET_DESIGNWARE_TEGRA186) += designware_tegra186.o
 obj-$(CONFIG_DRIVER_NET_DESIGNWARE_ROCKCHIP) += designware_rockchip.o
diff --git a/drivers/net/designware_imx8.c b/drivers/net/designware_imx.c
similarity index 73%
rename from drivers/net/designware_imx8.c
rename to drivers/net/designware_imx.c
index 73a16d5e65..00164fa7c7 100644
--- a/drivers/net/designware_imx8.c
+++ b/drivers/net/designware_imx.c
@@ -18,7 +18,7 @@
 #define GPR_ENET_QOS_RGMII_EN  BIT(21)
 
 
-struct eqos_imx8_priv {
+struct eqos_imx_priv {
struct device *dev;
struct clk_bulk_data *clks;
int num_clks;
@@ -28,25 +28,25 @@ struct eqos_imx8_priv {
 };
 
 enum { CLK_STMMACETH, CLK_PCLK, CLK_PTP_REF, CLK_TX};
-static const struct clk_bulk_data imx8_clks[] = {
+static const struct clk_bulk_data imx_clks[] = {
[CLK_STMMACETH] = { .id = "stmmaceth" },
[CLK_PCLK]  = { .id = "pclk" },
[CLK_PTP_REF]   = { .id = "ptp_ref" },
[CLK_TX]= { .id = "tx" },
 };
 
-static unsigned long eqos_get_csr_clk_rate_imx8(struct eqos *eqos)
+static unsigned long eqos_get_csr_clk_rate_imx(struct eqos *eqos)
 {
-   struct eqos_imx8_priv *priv = eqos->priv;
+   struct eqos_imx_priv *priv = eqos->priv;
 
return clk_get_rate(priv->clks[CLK_PCLK].clk);
 }
 
 
-static void eqos_adjust_link_imx8(struct eth_device *edev)
+static void eqos_adjust_link_imx(struct eth_device *edev)
 {
struct eqos *eqos = edev->priv;
-   struct eqos_imx8_priv *priv = eqos->priv;
+   struct eqos_imx_priv *priv = eqos->priv;
unsigned long rate;
int ret;
 
@@ -74,9 +74,9 @@ static void eqos_adjust_link_imx8(struct eth_device *edev)
eqos_adjust_link(edev);
 }
 
-static void eqos_imx8_set_interface_mode(struct eqos *eqos)
+static void eqos_imx_set_interface_mode(struct eqos *eqos)
 {
-   struct eqos_imx8_priv *priv = eqos->priv;
+   struct eqos_imx_priv *priv = 

[PATCH 3/3] net: eqos: Add i.MX93 support

2023-11-10 Thread Sascha Hauer
Add the compatible entries and i.MX93 specific init code to make the
driver usable on i.MX93.

Signed-off-by: Sascha Hauer 
---
 drivers/net/Kconfig  |   2 +-
 drivers/net/designware_imx.c | 124 +++
 2 files changed, 97 insertions(+), 29 deletions(-)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 9be03cf20c..86d1c21856 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -109,7 +109,7 @@ config DRIVER_NET_DESIGNWARE_EQOS
 
 config DRIVER_NET_DESIGNWARE_IMX
bool "Designware EQOS i.MX Ethernet driver"
-   depends on HAS_DMA && COMMON_CLK && OFTREE && (ARCH_IMX8M || 
COMPILE_TEST)
+   depends on HAS_DMA && COMMON_CLK && OFTREE && (ARCH_IMX8M || ARCH_IMX93 
|| COMPILE_TEST)
select DRIVER_NET_DESIGNWARE_EQOS
select MFD_SYSCON
help
diff --git a/drivers/net/designware_imx.c b/drivers/net/designware_imx.c
index 13bca42c25..c281d3b64b 100644
--- a/drivers/net/designware_imx.c
+++ b/drivers/net/designware_imx.c
@@ -17,6 +17,17 @@
 #define GPR_ENET_QOS_CLK_TX_CLK_SELBIT(20)
 #define GPR_ENET_QOS_RGMII_EN  BIT(21)
 
+#define MX93_GPR_ENET_QOS_INTF_MODE_MASK   GENMASK(3, 0)
+#define MX93_GPR_ENET_QOS_INTF_MASKGENMASK(3, 1)
+#define MX93_GPR_ENET_QOS_INTF_SEL_MII (0x0 << 1)
+#define MX93_GPR_ENET_QOS_INTF_SEL_RMII(0x4 << 1)
+#define MX93_GPR_ENET_QOS_INTF_SEL_RGMII   (0x1 << 1)
+#define MX93_GPR_ENET_QOS_CLK_GEN_EN   (0x1 << 0)
+
+struct eqos_imx_soc_data {
+   int (*set_interface_mode)(struct eqos *eqos);
+   bool mac_rgmii_txclk_auto_adj;
+};
 
 struct eqos_imx_priv {
struct device *dev;
@@ -25,6 +36,7 @@ struct eqos_imx_priv {
struct regmap *intf_regmap;
u32 intf_reg_off;
bool rmii_refclk_ext;
+   struct eqos_imx_soc_data *soc_data;
 };
 
 enum { CLK_STMMACETH, CLK_PCLK, CLK_PTP_REF, CLK_TX};
@@ -42,15 +54,13 @@ static unsigned long eqos_get_csr_clk_rate_imx(struct eqos 
*eqos)
return clk_get_rate(priv->clks[CLK_PCLK].clk);
 }
 
-
-static void eqos_adjust_link_imx(struct eth_device *edev)
+static int eqos_set_txclk(struct eqos *eqos, int speed)
 {
-   struct eqos *eqos = edev->priv;
struct eqos_imx_priv *priv = eqos->priv;
unsigned long rate;
int ret;
 
-   switch (edev->phydev->speed) {
+   switch (speed) {
case SPEED_10:
rate = 250;
break;
@@ -61,28 +71,33 @@ static void eqos_adjust_link_imx(struct eth_device *edev)
rate = 12500;
break;
default:
-   dev_err(priv->dev, "unknown speed value for GMAC speed=%d",
-   edev->phydev->speed);
-   return;
+   dev_err(priv->dev, "unknown speed value for GMAC speed=%d", 
speed);
+   return -EINVAL;
}
 
ret = clk_set_rate(priv->clks[CLK_TX].clk, rate);
if (ret)
-   dev_err(priv->dev, "set TX clk rate %ld failed %d\n",
-   rate, ret);
+   dev_err(priv->dev, "set TX clk rate %ld failed %d\n", rate, 
ret);
+
+   return ret;
+}
+
+static void eqos_adjust_link_imx(struct eth_device *edev)
+{
+   struct eqos *eqos = edev->priv;
+   struct eqos_imx_priv *priv = eqos->priv;
+
+   if (!priv->soc_data->mac_rgmii_txclk_auto_adj)
+   eqos_set_txclk(eqos, edev->phydev->speed);
 
eqos_adjust_link(edev);
 }
 
-static void eqos_imx_set_interface_mode(struct eqos *eqos)
+static int eqos_imx8mp_set_interface_mode(struct eqos *eqos)
 {
struct eqos_imx_priv *priv = eqos->priv;
-   struct device_node *np = priv->dev->device_node;
int val;
 
-   if (!of_device_is_compatible(np, "nxp,imx8mp-dwmac-eqos"))
-   return;
-
switch (eqos->interface) {
case PHY_INTERFACE_MODE_MII:
val = GPR_ENET_QOS_INTF_SEL_MII;
@@ -100,34 +115,65 @@ static void eqos_imx_set_interface_mode(struct eqos *eqos)
break;
default:
dev_err(priv->dev, "no valid interface mode found!\n");
-   return;
+   return -EINVAL;
}
 
val |= GPR_ENET_QOS_CLK_GEN_EN;
 
-   regmap_update_bits(priv->intf_regmap, priv->intf_reg_off,
-  GPR_ENET_QOS_INTF_MODE_MASK, val);
+   return regmap_update_bits(priv->intf_regmap, priv->intf_reg_off,
+ GPR_ENET_QOS_INTF_MODE_MASK, val);
 }
 
+static int eqos_imx93_set_interface_mode(struct eqos *eqos)
+{
+   struct eqos_imx_priv *priv = eqos->priv;
+
+   int val;
+
+   switch (eqos->interface) {
+   case PHY_INTERFACE_MODE_MII:
+   val = MX93_GPR_ENET_QOS_INTF_SEL_MII;
+   break;
+   case PHY_INTERFACE_MODE_RMII:
+   val = MX93_GPR_ENET_QOS_INTF_SEL_RMII;
+   break;
+   case PHY_INTERFACE_MODE_RGMII:
+   case 

[PATCH 2/3] net: eqos: imx: move common stuff to probe()

2023-11-10 Thread Sascha Hauer
eqos_init_imx() currently is i.MX8 specific, but some stuff can be used
by i.MX9 as well. Move that to probe().

Signed-off-by: Sascha Hauer 
---
 drivers/net/designware_imx.c | 50 
 1 file changed, 28 insertions(+), 22 deletions(-)

diff --git a/drivers/net/designware_imx.c b/drivers/net/designware_imx.c
index 00164fa7c7..13bca42c25 100644
--- a/drivers/net/designware_imx.c
+++ b/drivers/net/designware_imx.c
@@ -115,11 +115,6 @@ static int eqos_init_imx(struct device *dev, struct eqos 
*eqos)
struct eqos_imx_priv *priv = eqos->priv;
int ret;
 
-   priv->dev = dev;
-
-   if (of_get_property(np, "snps,rmii_refclk_ext", NULL))
-   priv->rmii_refclk_ext = true;
-
if (of_device_is_compatible(np, "nxp,imx8mp-dwmac-eqos")) {
priv->intf_regmap = syscon_regmap_lookup_by_phandle(np, 
"intf_mode");
if (IS_ERR(priv->intf_regmap))
@@ -132,22 +127,6 @@ static int eqos_init_imx(struct device *dev, struct eqos 
*eqos)
}
}
 
-   priv->num_clks = ARRAY_SIZE(imx_clks);
-   priv->clks = xmalloc(priv->num_clks * sizeof(*priv->clks));
-   memcpy(priv->clks, imx_clks, sizeof imx_clks);
-
-   ret = clk_bulk_get(dev, priv->num_clks, priv->clks);
-   if (ret) {
-   dev_err(dev, "Failed to get clks: %s\n", strerror(-ret));
-   return ret;
-   }
-
-   ret = clk_bulk_enable(priv->num_clks, priv->clks);
-   if (ret) {
-   dev_err(dev, "Failed to enable clks: %s\n", strerror(-ret));
-   return ret;
-   }
-
eqos_imx_set_interface_mode(eqos);
 
return 0;
@@ -166,7 +145,34 @@ static struct eqos_ops imx_ops = {
 
 static int eqos_probe_imx(struct device *dev)
 {
-   return eqos_probe(dev, _ops, xzalloc(sizeof(struct eqos_imx_priv)));
+   struct device_node *np = dev->device_node;
+   struct eqos_imx_priv *priv;
+   int ret;
+
+   priv = xzalloc(sizeof(*priv));
+
+   priv->dev = dev;
+
+   if (of_get_property(np, "snps,rmii_refclk_ext", NULL))
+   priv->rmii_refclk_ext = true;
+
+   priv->num_clks = ARRAY_SIZE(imx_clks);
+   priv->clks = xmalloc(priv->num_clks * sizeof(*priv->clks));
+   memcpy(priv->clks, imx_clks, sizeof imx_clks);
+
+   ret = clk_bulk_get(dev, priv->num_clks, priv->clks);
+   if (ret) {
+   dev_err(dev, "Failed to get clks: %s\n", strerror(-ret));
+   return ret;
+   }
+
+   ret = clk_bulk_enable(priv->num_clks, priv->clks);
+   if (ret) {
+   dev_err(dev, "Failed to enable clks: %s\n", strerror(-ret));
+   return ret;
+   }
+
+   return eqos_probe(dev, _ops, priv);
 }
 
 static void eqos_remove_imx(struct device *dev)
-- 
2.39.2




[PATCH 0/3] Add i.MX9 EQOS networking support

2023-11-10 Thread Sascha Hauer
Like some i.MX8M variants the i.MX9 also has a designware EQOS network
controller. This series adjusts the glue code to make the driver
available on i.MX9.

Sascha

Sascha Hauer (3):
  net: eqos: rename i.MX8 driver glue code to i.MX
  net: eqos: imx: move common stuff to probe()
  net: eqos: Add i.MX93 support

 arch/arm/configs/imx_v8_defconfig   |   2 +-
 arch/arm/configs/multi_v8_defconfig |   2 +-
 drivers/net/Kconfig |   8 +-
 drivers/net/Makefile|   2 +-
 drivers/net/designware_imx.c| 269 
 drivers/net/designware_imx8.c   | 195 
 6 files changed, 276 insertions(+), 202 deletions(-)
 create mode 100644 drivers/net/designware_imx.c
 delete mode 100644 drivers/net/designware_imx8.c

-- 
2.39.2




[PATCH 03/13] ddr: imx8m: move get_trained_CDD() to SoC code

2023-11-10 Thread Sascha Hauer
get_trained_CDD() will be implemented differently on i.MX9, so move
the function to the i.MX8M specific file and add a hook to struct
dram_controller.

Signed-off-by: Sascha Hauer 
---
 drivers/ddr/imx/ddrphy_train.c   |   2 +-
 drivers/ddr/imx/ddrphy_utils.c   | 169 --
 drivers/ddr/imx/imx8m_ddr_init.c | 171 +++
 include/soc/imx8m/ddr.h  |   5 +-
 4 files changed, 173 insertions(+), 174 deletions(-)

diff --git a/drivers/ddr/imx/ddrphy_train.c b/drivers/ddr/imx/ddrphy_train.c
index 1683ffd9a8..36fb6d3c11 100644
--- a/drivers/ddr/imx/ddrphy_train.c
+++ b/drivers/ddr/imx/ddrphy_train.c
@@ -159,7 +159,7 @@ int ddr_cfg_phy(struct dram_controller *dram, struct 
dram_timing_info *dram_timi
ddrphy_init_read_msg_block(fsp_msg->fw_type);
 
if (fsp_msg->fw_type != FW_2D_IMAGE)
-   get_trained_CDD(i);
+   dram->get_trained_CDD(dram, i);
 
dwc_ddrphy_apb_wr(0xd, 0x1);
 
diff --git a/drivers/ddr/imx/ddrphy_utils.c b/drivers/ddr/imx/ddrphy_utils.c
index 353a265136..db94b85b74 100644
--- a/drivers/ddr/imx/ddrphy_utils.c
+++ b/drivers/ddr/imx/ddrphy_utils.c
@@ -362,172 +362,3 @@ void ddrphy_init_set_dfi_clk(unsigned int drate_mhz, enum 
ddrc_type type)
 void ddrphy_init_read_msg_block(enum fw_type type)
 {
 }
-
-static unsigned int g_cdd_rr_max[4];
-static unsigned int g_cdd_rw_max[4];
-static unsigned int g_cdd_wr_max[4];
-static unsigned int g_cdd_ww_max[4];
-
-static unsigned int look_for_max(unsigned int data[], unsigned int addr_start,
-unsigned int addr_end)
-{
-   unsigned int i, imax = 0;
-
-   for (i = addr_start; i <= addr_end; i++) {
-   if (((data[i] >> 7) == 0) && (data[i] > imax))
-   imax = data[i];
-   }
-
-   return imax;
-}
-
-void get_trained_CDD(u32 fsp)
-{
-   unsigned int i, ddr_type, tmp;
-   unsigned int cdd_cha[12], cdd_chb[12];
-   unsigned int cdd_cha_rr_max, cdd_cha_rw_max, cdd_cha_wr_max, 
cdd_cha_ww_max;
-   unsigned int cdd_chb_rr_max, cdd_chb_rw_max, cdd_chb_wr_max, 
cdd_chb_ww_max;
-
-   ddr_type = reg32_read(DDRC_MSTR(0)) & 0x3f;
-   if (ddr_type == 0x20) {
-   for (i = 0; i < 6; i++) {
-   tmp = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) +
-(0x54013UL + i) * 4);
-   cdd_cha[i * 2] = tmp & 0xff;
-   cdd_cha[i * 2 + 1] = (tmp >> 8) & 0xff;
-   }
-
-   for (i = 0; i < 7; i++) {
-   tmp = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) +
-(0x5402cUL + i) * 4);
-   if (i == 0) {
-   cdd_cha[0] = (tmp >> 8) & 0xff;
-   } else if (i == 6) {
-   cdd_cha[11] = tmp & 0xff;
-   } else {
-   cdd_chb[ i * 2 - 1] = tmp & 0xff;
-   cdd_chb[i * 2] = (tmp >> 8) & 0xff;
-   }
-   }
-
-   cdd_cha_rr_max = look_for_max(cdd_cha, 0, 1);
-   cdd_cha_rw_max = look_for_max(cdd_cha, 2, 5);
-   cdd_cha_wr_max = look_for_max(cdd_cha, 6, 9);
-   cdd_cha_ww_max = look_for_max(cdd_cha, 10, 11);
-   cdd_chb_rr_max = look_for_max(cdd_chb, 0, 1);
-   cdd_chb_rw_max = look_for_max(cdd_chb, 2, 5);
-   cdd_chb_wr_max = look_for_max(cdd_chb, 6, 9);
-   cdd_chb_ww_max = look_for_max(cdd_chb, 10, 11);
-   g_cdd_rr_max[fsp] =  cdd_cha_rr_max > cdd_chb_rr_max ? 
cdd_cha_rr_max : cdd_chb_rr_max;
-   g_cdd_rw_max[fsp] =  cdd_cha_rw_max > cdd_chb_rw_max ? 
cdd_cha_rw_max : cdd_chb_rw_max;
-   g_cdd_wr_max[fsp] =  cdd_cha_wr_max > cdd_chb_wr_max ? 
cdd_cha_wr_max : cdd_chb_wr_max;
-   g_cdd_ww_max[fsp] =  cdd_cha_ww_max > cdd_chb_ww_max ? 
cdd_cha_ww_max : cdd_chb_ww_max;
-   } else {
-   unsigned int ddr4_cdd[64];
-
-   for( i = 0; i < 29; i++) {
-   tmp = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) +
-(0x54012UL + i) * 4);
-   ddr4_cdd[i * 2] = tmp & 0xff;
-   ddr4_cdd[i * 2 + 1] = (tmp >> 8) & 0xff;
-   }
-
-   g_cdd_rr_max[fsp] = look_for_max(ddr4_cdd, 1, 12);
-   g_cdd_ww_max[fsp] = look_for_max(ddr4_cdd, 13, 24);
-   g_cdd_rw_max[fsp] = look_for_max(ddr4_cdd, 25, 40);
-   g_cdd_wr_max[fsp] = look_for_max(ddr4_cdd, 41, 56);
-   }
-}
-
-void update_umctl2_rank_space_setting(unsigned int pstat_num,
- enum ddrc_type type)
-{
-   unsigned int i,ddr_type;
-   unsigned int rdata, tmp, tmp_t;
-   unsigned int 

[PATCH 04/13] ddr: imx8m: move PLL init to SoC specific code

2023-11-10 Thread Sascha Hauer
The PLL initialization will be different on i.MX9, so move the
code to the i.MX8M specific file and a add a function hook to
struct dram_controller.

Signed-off-by: Sascha Hauer 
---
 drivers/ddr/imx/ddrphy_train.c   |   2 +-
 drivers/ddr/imx/ddrphy_utils.c   | 257 --
 drivers/ddr/imx/imx8m_ddr_init.c | 261 ++-
 include/soc/imx8m/ddr.h  |   2 +-
 4 files changed, 262 insertions(+), 260 deletions(-)

diff --git a/drivers/ddr/imx/ddrphy_train.c b/drivers/ddr/imx/ddrphy_train.c
index 36fb6d3c11..b44f5ef9b4 100644
--- a/drivers/ddr/imx/ddrphy_train.c
+++ b/drivers/ddr/imx/ddrphy_train.c
@@ -116,7 +116,7 @@ int ddr_cfg_phy(struct dram_controller *dram, struct 
dram_timing_info *dram_timi
for (i = 0; i < dram_timing->fsp_msg_num; i++) {
pr_debug("DRAM PHY training for %dMTS\n", fsp_msg->drate);
/* set dram PHY input clocks to desired frequency */
-   ddrphy_init_set_dfi_clk(fsp_msg->drate, dram->ddrc_type);
+   dram->set_dfi_clk(dram, fsp_msg->drate);
 
/* load the dram training firmware image */
dwc_ddrphy_apb_wr(0xd, 0x0);
diff --git a/drivers/ddr/imx/ddrphy_utils.c b/drivers/ddr/imx/ddrphy_utils.c
index db94b85b74..4577547113 100644
--- a/drivers/ddr/imx/ddrphy_utils.c
+++ b/drivers/ddr/imx/ddrphy_utils.c
@@ -13,111 +13,6 @@
 #include 
 #include 
 
-/* DDR Transfer rate, bus clock is transfer rate / 2, and the DDRC runs at bus
- * clock / 2, which is therefor transfer rate / 4.  */
-enum ddr_rate {
-   DDR_4000,
-   DDR_3720,
-   DDR_3200,
-   DDR_3000,
-   DDR_2600, /* Unused */
-   DDR_2400,
-   DDR_2376, /* Unused */
-   DDR_1600,
-   DDR_1000, /* Unused */
-   DDR_1066,
-   DDR_667,
-   DDR_400,
-   DDR_250, /* Unused */
-   DDR_100,
-   DDR_NUM_RATES
-};
-
-/* PLL config for IMX8MM type DRAM PLL.  This PLL type isn't documented, but
- * it looks like it is a basically a fractional PLL:
- * Frequency = Ref (24 MHz) / P * M / 2^S
- * Note: Divider is equal to register value
- */
-#define MDIV(x) ((x) << 12)
-#define PDIV(x) ((x) << 4)
-#define SDIV(x) ((x) << 0)
-
-#define LOCK_STATUS BIT(31)
-#define LOCK_SEL_MASK   BIT(29)
-#define CLKE_MASK   BIT(11)
-#define RST_MASKBIT(9)
-#define BYPASS_MASK BIT(4)
-
-static const struct imx8mm_fracpll_config {
-   uint32_t r1, r2;
-   bool valid;
-} imx8mm_fracpll_table[DDR_NUM_RATES] = {
-   [DDR_4000] = { .valid = true, .r1 = MDIV(250) | PDIV(3) | SDIV(1), .r2 
= 0 },
-   [DDR_3720] = { .valid = true, .r1 = MDIV(310) | PDIV(2) | SDIV(2), .r2 
= 0 },
-   [DDR_3200] = { .valid = true, .r1 = MDIV(300) | PDIV(9) | SDIV(0), .r2 
= 0 },
-   [DDR_3000] = { .valid = true, .r1 = MDIV(250) | PDIV(8) | SDIV(0), .r2 
= 0 },
-   [DDR_2600] = { .valid = true, .r1 = MDIV(325) | PDIV(3) | SDIV(2), .r2 
= 0 },
-   [DDR_2400] = { .valid = true, .r1 = MDIV(300) | PDIV(3) | SDIV(2), .r2 
= 0 },
-   [DDR_2376] = { .valid = true, .r1 = MDIV( 99) | PDIV(1) | SDIV(2), .r2 
= 0 },
-   [DDR_1600] = { .valid = true, .r1 = MDIV(300) | PDIV(9) | SDIV(1), .r2 
= 0 },
-   [DDR_1066] = { .valid = true, .r1 = MDIV(400) | PDIV(9) | SDIV(2), .r2 
= 0 },
-   [DDR_667]  = { .valid = true, .r1 = MDIV(334) | PDIV(3) | SDIV(4), .r2 
= 0 },
-   [DDR_400]  = { .valid = true, .r1 = MDIV(300) | PDIV(9) | SDIV(3), .r2 
= 0 },
-};
-
-/* PLL config for IMX8MQ type DRAM PLL.  This is SSCG_PLL:
- * Frequency = Ref (25 MHz) / divr1 * (2*divf1) / divr2 * divf2 / divq
- * Note: IMX8MQ RM, §5.1.5.4.4 Fig. 5-8 shows ÷2 on divf2, but this is not 
true.
- * Note: divider is register value + 1
- */
-#define SSCG_PLL_LOCK  BIT(31)
-#define SSCG_PLL_DRAM_PLL_CLKE BIT(9)
-#define SSCG_PLL_PDBIT(7)
-#define SSCG_PLL_BYPASS1   BIT(5)
-#define SSCG_PLL_BYPASS2   BIT(4)
-
-#define SSCG_PLL_REF_DIVR2_MASK(0x3f << 19)
-#define SSCG_PLL_REF_DIVR2_VAL(n)  (((n) << 19) & SSCG_PLL_REF_DIVR2_MASK)
-#define SSCG_PLL_FEEDBACK_DIV_F1_MASK  (0x3f << 13)
-#define SSCG_PLL_FEEDBACK_DIV_F1_VAL(n)(((n) << 13) & 
SSCG_PLL_FEEDBACK_DIV_F1_MASK)
-#define SSCG_PLL_FEEDBACK_DIV_F2_MASK  (0x3f << 7)
-#define SSCG_PLL_FEEDBACK_DIV_F2_VAL(n)(((n) << 7) & 
SSCG_PLL_FEEDBACK_DIV_F2_MASK)
-#define SSCG_PLL_OUTPUT_DIV_VAL_MASK   (0x3f << 1)
-#define SSCG_PLL_OUTPUT_DIV_VAL(n) (((n) << 1) & 
SSCG_PLL_OUTPUT_DIV_VAL_MASK)
-
-#define SSCG_PLL_CFG2(divf1, divr2, divf2, divq) \
-   (SSCG_PLL_FEEDBACK_DIV_F1_VAL(divf1) | 
SSCG_PLL_FEEDBACK_DIV_F2_VAL(divf2) | \
-   SSCG_PLL_REF_DIVR2_VAL(divr2) | SSCG_PLL_OUTPUT_DIV_VAL(divq))
-
-static const struct imx8mq_ssgcpll_config {
-   uint32_t val;
-   bool valid;
-} imx8mq_ssgcpll_table[DDR_NUM_RATES] = {
-   [DDR_3200] = { .valid = true, .val = SSCG_PLL_CFG2(39, 29, 11, 0) },
-   [DDR_2400] = { 

[PATCH 05/13] ddr: imx8m: clean up defines

2023-11-10 Thread Sascha Hauer
Use register defines we already have in mach/imx/imx8m-regs.h rather
than duplicating them in the ddr code. Also remove some unused defines.

Signed-off-by: Sascha Hauer 
---
 drivers/ddr/imx/helper.c |  8 
 drivers/ddr/imx/imx8m_ddr_init.c |  2 +-
 include/soc/imx8m/ddr.h  | 11 +++
 3 files changed, 4 insertions(+), 17 deletions(-)

diff --git a/drivers/ddr/imx/helper.c b/drivers/ddr/imx/helper.c
index 98e4084958..81c3ed7f30 100644
--- a/drivers/ddr/imx/helper.c
+++ b/drivers/ddr/imx/helper.c
@@ -10,14 +10,6 @@
 #include 
 #include 
 
-#define IMEM_LEN 32768 /* byte */
-#define DMEM_LEN 16384 /* byte */
-#define IMEM_2D_OFFSET 49152
-
-#define IMEM_OFFSET_ADDR 0x0005
-#define DMEM_OFFSET_ADDR 0x00054000
-#define DDR_TRAIN_CODE_BASE_ADDR IP2APB_DDRPHY_IPS_BASE_ADDR(0)
-
 void ddrphy_trained_csr_save(struct dram_cfg_param *ddrphy_csr,
 unsigned int num)
 {
diff --git a/drivers/ddr/imx/imx8m_ddr_init.c b/drivers/ddr/imx/imx8m_ddr_init.c
index 856e7ee4fe..f76aafe769 100644
--- a/drivers/ddr/imx/imx8m_ddr_init.c
+++ b/drivers/ddr/imx/imx8m_ddr_init.c
@@ -543,7 +543,7 @@ int imx8m_ddr_init(struct dram_controller *dram, struct 
dram_timing_info *dram_t
 */
tmp = reg32_read(DDRC_MSTR(0));
if (tmp & (0x1 << 5) && dram->ddrc_type != DDRC_TYPE_MN)
-   reg32_write(DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */
+   reg32_write(MX8M_DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */
 
/* determine the initial boot frequency */
target_freq = reg32_read(DDRC_MSTR2(0)) & 0x3;
diff --git a/include/soc/imx8m/ddr.h b/include/soc/imx8m/ddr.h
index ec82f3233a..9ff9c0a2da 100644
--- a/include/soc/imx8m/ddr.h
+++ b/include/soc/imx8m/ddr.h
@@ -8,11 +8,9 @@
 
 #include 
 #include 
+#include 
 
-#define DDRC_DDR_SS_GPR0   0x3d00
-#define DDRC_IPS_BASE_ADDR_0   0x3f40
-#define IP2APB_DDRPHY_IPS_BASE_ADDR(X) (0x3c00 + (X * 0x200))
-#define DDRPHY_MEM(X)  (0x3c00 + (X * 0x200) + 0x5)
+#define IP2APB_DDRPHY_IPS_BASE_ADDR(X) MX8M_DDRC_PHY_BASE_ADDR
 
 #define DDRC_MSTR(X) (DDRC_IPS_BASE_ADDR(X) + 0x00)
 #define DDRC_STAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x04)
@@ -320,7 +318,7 @@
 #define DRC_PERF_MON_MRR14_DAT(X)(DRC_PERF_MON_BASE_ADDR(X) + 0x78)
 #define DRC_PERF_MON_MRR15_DAT(X)(DRC_PERF_MON_BASE_ADDR(X) + 0x7C)
 
-#define DDRC_IPS_BASE_ADDR(X) (0x3d40 + (X * 0x200))
+#define DDRC_IPS_BASE_ADDR(X) MX8M_DDRC_IPS_BASE_ADDR(X)
 
 /* user data type */
 enum fw_type {
@@ -391,8 +389,6 @@ struct dram_controller {
void (*set_dfi_clk)(struct dram_controller *dram, unsigned int 
drate_mhz);
 };
 
-extern struct dram_timing_info dram_timing;
-
 void ddr_get_firmware_lpddr4(void);
 void ddr_get_firmware_ddr(void);
 
@@ -453,7 +449,6 @@ static inline int imx8mp_ddr_init(struct dram_timing_info 
*dram_timing,
 }
 
 int ddr_cfg_phy(struct dram_controller *dram, struct dram_timing_info 
*timing_info);
-void load_lpddr4_phy_pie(void);
 void ddrphy_trained_csr_save(struct dram_cfg_param *param, unsigned int num);
 void dram_config_save(struct dram_timing_info *info, unsigned long base);
 
-- 
2.39.2




[PATCH 12/13] ddr: move imx8m_ddr_old_spreadsheet to controller

2023-11-10 Thread Sascha Hauer
Signed-off-by: Sascha Hauer 
---
 drivers/ddr/imx/helper.c |  4 ++--
 drivers/ddr/imx/imx8m_ddr_init.c | 14 +++---
 include/soc/imx/ddr.h|  4 +++-
 include/soc/imx8m/ddr.h  |  2 --
 4 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/ddr/imx/helper.c b/drivers/ddr/imx/helper.c
index f38b9a0060..674ca7e4ac 100644
--- a/drivers/ddr/imx/helper.c
+++ b/drivers/ddr/imx/helper.c
@@ -27,7 +27,7 @@ void ddrphy_trained_csr_save(struct dram_controller *dram, 
struct dram_cfg_param
dwc_ddrphy_apb_wr(dram, 0xd, 0x1);
 }
 
-void *dram_config_save(struct dram_timing_info *timing_info,
+void *dram_config_save(struct dram_controller *dram, struct dram_timing_info 
*timing_info,
  unsigned long saved_timing_base)
 {
int i = 0;
@@ -54,7 +54,7 @@ void *dram_config_save(struct dram_timing_info *timing_info,
cfg++;
}
 
-   if (imx8m_ddr_old_spreadsheet) {
+   if (dram->imx8m_ddr_old_spreadsheet) {
cfg->reg = DDRC_ADDRMAP7(0);
cfg->val = 0xf0f;
cfg++;
diff --git a/drivers/ddr/imx/imx8m_ddr_init.c b/drivers/ddr/imx/imx8m_ddr_init.c
index 8d473a3e63..8b829645c0 100644
--- a/drivers/ddr/imx/imx8m_ddr_init.c
+++ b/drivers/ddr/imx/imx8m_ddr_init.c
@@ -13,19 +13,19 @@
 #include 
 #include 
 
-bool imx8m_ddr_old_spreadsheet = true;
-
 struct dram_controller imx8m_dram_controller = {
.phy_base = IOMEM(IP2APB_DDRPHY_IPS_BASE_ADDR(0)),
 };
 
-static void ddr_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num)
+static void ddr_cfg_umctl2(struct dram_controller *dram, struct dram_cfg_param 
*ddrc_cfg, int num)
 {
int i = 0;
 
+   dram->imx8m_ddr_old_spreadsheet = true;
+
for (i = 0; i < num; i++) {
if (ddrc_cfg->reg == DDRC_ADDRMAP7(0))
-   imx8m_ddr_old_spreadsheet = false;
+   dram->imx8m_ddr_old_spreadsheet = false;
reg32_write((unsigned long)ddrc_cfg->reg, ddrc_cfg->val);
ddrc_cfg++;
}
@@ -35,7 +35,7 @@ static void ddr_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, 
int num)
 * which falsifies the memory size read back from the controller
 * in barebox proper.
 */
-   if (imx8m_ddr_old_spreadsheet) {
+   if (dram->imx8m_ddr_old_spreadsheet) {
pr_warn("Working around old spreadsheet. Please regenerate\n");
/*
 * Alternatively, stick { DDRC_ADDRMAP7(0), 0xf0f } into
@@ -518,7 +518,7 @@ int imx8m_ddr_init(struct dram_controller *dram, struct 
dram_timing_info *dram_t
 
/* Step2: Program the dwc_ddr_umctl2 registers */
pr_debug("ddrc config start\n");
-   ddr_cfg_umctl2(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num);
+   ddr_cfg_umctl2(dram, dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num);
pr_debug("ddrc config done\n");
 
/* Step3: De-assert reset signal(core_ddrc_rstn & aresetn_n) */
@@ -640,7 +640,7 @@ int imx8m_ddr_init(struct dram_controller *dram, struct 
dram_timing_info *dram_t
pr_debug("ddrmix config done\n");
 
/* save the dram timing config into memory */
-   dram_config_save(dram_timing, IMX8M_SAVED_DRAM_TIMING_BASE);
+   dram_config_save(dram, dram_timing, IMX8M_SAVED_DRAM_TIMING_BASE);
 
return 0;
 }
diff --git a/include/soc/imx/ddr.h b/include/soc/imx/ddr.h
index bc793cf3ed..581a3b461c 100644
--- a/include/soc/imx/ddr.h
+++ b/include/soc/imx/ddr.h
@@ -74,6 +74,7 @@ struct dram_controller {
void __iomem *phy_base;
void (*get_trained_CDD)(struct dram_controller *dram, u32 fsp);
void (*set_dfi_clk)(struct dram_controller *dram, unsigned int 
drate_mhz);
+   bool imx8m_ddr_old_spreadsheet;
 };
 
 void ddr_get_firmware_lpddr4(void);
@@ -90,7 +91,8 @@ static inline void ddr_get_firmware(enum dram_type dram_type)
 int ddr_cfg_phy(struct dram_controller *dram, struct dram_timing_info 
*timing_info);
 void ddrphy_trained_csr_save(struct dram_controller *dram, struct 
dram_cfg_param *param,
 unsigned int num);
-void *dram_config_save(struct dram_timing_info *info, unsigned long base);
+void *dram_config_save(struct dram_controller *dram, struct dram_timing_info 
*info,
+  unsigned long base);
 
 /* utils function for ddr phy training */
 int wait_ddrphy_training_complete(struct dram_controller *dram);
diff --git a/include/soc/imx8m/ddr.h b/include/soc/imx8m/ddr.h
index abd9961099..5df07772b3 100644
--- a/include/soc/imx8m/ddr.h
+++ b/include/soc/imx8m/ddr.h
@@ -374,8 +374,6 @@ static inline int imx8m_wait_ddrphy_training_complete(void)
return wait_ddrphy_training_complete(_dram_controller);
 }
 
-extern bool imx8m_ddr_old_spreadsheet;
-
 static inline void imx8m_ddr_load_train_code(enum dram_type dram_type,
 enum fw_type fw_type)
 {
-- 
2.39.2




[PATCH 02/13] ddr: imx8m: introduce dram_controller struct

2023-11-10 Thread Sascha Hauer
Upcoming i.MX9 support will need to implement some functions
differently. Introduce a struct dram_controller to be able
to abstract these differences later. For now only add a few
members, more will come in later patches.

Signed-off-by: Sascha Hauer 
---
 drivers/ddr/imx/ddrphy_train.c   |  8 +++-
 drivers/ddr/imx/imx8m_ddr_init.c | 16 
 include/soc/imx8m/ddr.h  | 32 +---
 3 files changed, 36 insertions(+), 20 deletions(-)

diff --git a/drivers/ddr/imx/ddrphy_train.c b/drivers/ddr/imx/ddrphy_train.c
index 6a98fa0545..1683ffd9a8 100644
--- a/drivers/ddr/imx/ddrphy_train.c
+++ b/drivers/ddr/imx/ddrphy_train.c
@@ -93,10 +93,8 @@ void ddr_load_train_code(enum dram_type dram_type, enum 
fw_type fw_type)
   DDRC_PHY_DMEM, dmem, dsize);
 }
 
-int ddr_cfg_phy(struct dram_timing_info *dram_timing, unsigned type)
+int ddr_cfg_phy(struct dram_controller *dram, struct dram_timing_info 
*dram_timing)
 {
-   enum ddrc_type ddrc_type = get_ddrc_type(type);
-   enum dram_type dram_type = get_dram_type(type);
struct dram_cfg_param *dram_cfg;
struct dram_fsp_msg *fsp_msg;
unsigned int num;
@@ -118,11 +116,11 @@ int ddr_cfg_phy(struct dram_timing_info *dram_timing, 
unsigned type)
for (i = 0; i < dram_timing->fsp_msg_num; i++) {
pr_debug("DRAM PHY training for %dMTS\n", fsp_msg->drate);
/* set dram PHY input clocks to desired frequency */
-   ddrphy_init_set_dfi_clk(fsp_msg->drate, ddrc_type);
+   ddrphy_init_set_dfi_clk(fsp_msg->drate, dram->ddrc_type);
 
/* load the dram training firmware image */
dwc_ddrphy_apb_wr(0xd, 0x0);
-   ddr_load_train_code(dram_type, fsp_msg->fw_type);
+   ddr_load_train_code(dram->dram_type, fsp_msg->fw_type);
 
/* load the frequency set point message block parameter */
dram_cfg = fsp_msg->fsp_cfg;
diff --git a/drivers/ddr/imx/imx8m_ddr_init.c b/drivers/ddr/imx/imx8m_ddr_init.c
index 9a86280d9c..8acacfac35 100644
--- a/drivers/ddr/imx/imx8m_ddr_init.c
+++ b/drivers/ddr/imx/imx8m_ddr_init.c
@@ -15,6 +15,8 @@
 
 bool imx8m_ddr_old_spreadsheet = true;
 
+struct dram_controller imx8m_dram_controller;
+
 static void ddr_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num)
 {
int i = 0;
@@ -49,18 +51,16 @@ static void ddr_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, 
int num)
  */
 #define IMX8M_SAVED_DRAM_TIMING_BASE   0x18
 
-int imx8m_ddr_init(struct dram_timing_info *dram_timing,
-  unsigned type)
+int imx8m_ddr_init(struct dram_controller *dram, struct dram_timing_info 
*dram_timing)
 {
unsigned long src_ddrc_rcr = MX8M_SRC_DDRC_RCR_ADDR;
unsigned int tmp, initial_drate, target_freq;
-   enum ddrc_type ddrc_type = get_ddrc_type(type);
int ret;
 
pr_debug("start DRAM init\n");
 
/* Step1: Follow the power up procedure */
-   switch (ddrc_type) {
+   switch (dram->ddrc_type) {
case DDRC_TYPE_MQ:
reg32_write(src_ddrc_rcr + 0x04, 0x8f0f);
reg32_write(src_ddrc_rcr, 0x8f0f);
@@ -82,7 +82,7 @@ int imx8m_ddr_init(struct dram_timing_info *dram_timing,
 
initial_drate = dram_timing->fsp_msg[0].drate;
/* default to the frequency point 0 clock */
-   ddrphy_init_set_dfi_clk(initial_drate, ddrc_type);
+   ddrphy_init_set_dfi_clk(initial_drate, dram->ddrc_type);
 
/* D-aasert the presetn */
reg32_write(src_ddrc_rcr, 0x8F06);
@@ -112,7 +112,7 @@ int imx8m_ddr_init(struct dram_timing_info *dram_timing,
 * might not have been called
 */
tmp = reg32_read(DDRC_MSTR(0));
-   if (tmp & (0x1 << 5) && ddrc_type != DDRC_TYPE_MN)
+   if (tmp & (0x1 << 5) && dram->ddrc_type != DDRC_TYPE_MN)
reg32_write(DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */
 
/* determine the initial boot frequency */
@@ -139,7 +139,7 @@ int imx8m_ddr_init(struct dram_timing_info *dram_timing,
 */
pr_debug("ddrphy config start\n");
 
-   ret = ddr_cfg_phy(dram_timing, type);
+   ret = ddr_cfg_phy(dram, dram_timing);
if (ret)
return ret;
 
@@ -159,7 +159,7 @@ int imx8m_ddr_init(struct dram_timing_info *dram_timing,
reg32_write(DDRC_SWCTL(0), 0x);
 
/* Apply rank-to-rank workaround */
-   update_umctl2_rank_space_setting(dram_timing->fsp_msg_num - 1, 
ddrc_type);
+   update_umctl2_rank_space_setting(dram_timing->fsp_msg_num - 1, 
dram->ddrc_type);
 
/* Step16: Set DFIMISC.dfi_init_start to 1 */
setbits_le32(DDRC_DFIMISC(0), (0x1 << 5));
diff --git a/include/soc/imx8m/ddr.h b/include/soc/imx8m/ddr.h
index e268892957..18d7c96193 100644
--- a/include/soc/imx8m/ddr.h
+++ b/include/soc/imx8m/ddr.h
@@ -384,6 +384,11 @@ struct dram_timing_info {
unsigned int 

[PATCH 13/13] ddr: Initial i.MX9 support

2023-11-10 Thread Sascha Hauer
Signed-off-by: Sascha Hauer 
---
 drivers/ddr/imx/Kconfig |   6 +-
 drivers/ddr/imx/Makefile|   1 +
 drivers/ddr/imx/imx9_ddr_init.c | 698 
 include/soc/imx/ddr.h   |  17 +-
 include/soc/imx9/ddr.h  |  18 +
 5 files changed, 738 insertions(+), 2 deletions(-)
 create mode 100644 drivers/ddr/imx/imx9_ddr_init.c
 create mode 100644 include/soc/imx9/ddr.h

diff --git a/drivers/ddr/imx/Kconfig b/drivers/ddr/imx/Kconfig
index 43e9181582..71d4144e85 100644
--- a/drivers/ddr/imx/Kconfig
+++ b/drivers/ddr/imx/Kconfig
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 menu "i.MX DDR controllers"
-   depends on ARCH_IMX8MQ || ARCH_IMX8MM || ARCH_IMX8MN || ARCH_IMX8MP
+   depends on ARCH_IMX8MQ || ARCH_IMX8MM || ARCH_IMX8MN || ARCH_IMX8MP || 
ARCH_IMX93
 
 config IMX_DRAM
bool
@@ -9,4 +9,8 @@ config IMX8M_DRAM
select IMX_DRAM
bool "imx8m dram controller support"
 
+config IMX9_DRAM
+   select IMX_DRAM
+   bool "imx9 dram controller support"
+
 endmenu
diff --git a/drivers/ddr/imx/Makefile b/drivers/ddr/imx/Makefile
index 62d09e731a..1d24522bbb 100644
--- a/drivers/ddr/imx/Makefile
+++ b/drivers/ddr/imx/Makefile
@@ -5,3 +5,4 @@
 #
 pbl-$(CONFIG_IMX_DRAM) += helper.o ddrphy_utils.o ddrphy_train.o ddrphy_csr.o
 pbl-$(CONFIG_IMX8M_DRAM) += imx8m_ddr_init.o
+pbl-$(CONFIG_IMX9_DRAM) += imx9_ddr_init.o
diff --git a/drivers/ddr/imx/imx9_ddr_init.c b/drivers/ddr/imx/imx9_ddr_init.c
new file mode 100644
index 00..cdee18e4ad
--- /dev/null
+++ b/drivers/ddr/imx/imx9_ddr_init.c
@@ -0,0 +1,698 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2022 NXP
+ */
+
+#define pr_fmt(fmt) "imx9-ddr: " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MX9_SRC_DPHY_BASE_ADDR (MX9_SRC_BASE_ADDR + 0x1400)
+#define REG_DDR_SDRAM_MD_CNTL  (MX9_DDR_CTL_BASE + 0x120)
+#define REG_DDR_CS0_BNDS(MX9_DDR_CTL_BASE + 0x0)
+#define REG_DDR_CS1_BNDS(MX9_DDR_CTL_BASE + 0x8)
+#define REG_DDRDSR_2   (MX9_DDR_CTL_BASE + 0xB24)
+#define REG_DDR_TIMING_CFG_0   (MX9_DDR_CTL_BASE + 0x104)
+#define REG_DDR_SDRAM_CFG  (MX9_DDR_CTL_BASE + 0x110)
+#define REG_DDR_TIMING_CFG_4   (MX9_DDR_CTL_BASE + 0x160)
+#define REG_DDR_DEBUG_19   (MX9_DDR_CTL_BASE + 0xF48)
+#define REG_DDR_SDRAM_CFG_3(MX9_DDR_CTL_BASE + 0x260)
+#define REG_DDR_SDRAM_CFG_4(MX9_DDR_CTL_BASE + 0x264)
+#define REG_DDR_SDRAM_MD_CNTL_2(MX9_DDR_CTL_BASE + 0x270)
+#define REG_DDR_SDRAM_MPR4 (MX9_DDR_CTL_BASE + 0x28C)
+#define REG_DDR_SDRAM_MPR5 (MX9_DDR_CTL_BASE + 0x290)
+
+#define REG_DDR_ERR_EN (MX9_DDR_CTL_BASE + 0x1000)
+#define REG_SRC_DPHY_SW_CTRL   (MX9_SRC_DPHY_BASE_ADDR + 0x20)
+#define REG_SRC_DPHY_SINGLE_RESET_SW_CTRL  (MX9_SRC_DPHY_BASE_ADDR + 0x24)
+
+#define IMX9_SAVED_DRAM_TIMING_BASE 0x2051C000
+
+static unsigned int g_cdd_rr_max[4];
+static unsigned int g_cdd_rw_max[4];
+static unsigned int g_cdd_wr_max[4];
+static unsigned int g_cdd_ww_max[4];
+
+static void ddrphy_coldreset(void)
+{
+   /* dramphy_apb_n default 1 , assert -> 0, de_assert -> 1 */
+   /* dramphy_reset_n default 0 , assert -> 0, de_assert -> 1 */
+   /* dramphy_PwrOKIn default 0 , assert -> 1, de_assert -> 0 */
+
+   /* src_gen_dphy_apb_sw_rst_de_assert */
+   clrbits_le32(REG_SRC_DPHY_SW_CTRL, BIT(0));
+   /* src_gen_dphy_sw_rst_de_assert */
+   clrbits_le32(REG_SRC_DPHY_SINGLE_RESET_SW_CTRL, BIT(2));
+   /* src_gen_dphy_PwrOKIn_sw_rst_de_assert() */
+   setbits_le32(REG_SRC_DPHY_SINGLE_RESET_SW_CTRL, BIT(0));
+   mdelay(10);
+
+   /* src_gen_dphy_apb_sw_rst_assert */
+   setbits_le32(REG_SRC_DPHY_SW_CTRL, BIT(0));
+   /* src_gen_dphy_sw_rst_assert */
+   setbits_le32(REG_SRC_DPHY_SINGLE_RESET_SW_CTRL, BIT(2));
+   mdelay(10);
+   /* src_gen_dphy_PwrOKIn_sw_rst_assert */
+   clrbits_le32(REG_SRC_DPHY_SINGLE_RESET_SW_CTRL, BIT(0));
+   mdelay(10);
+
+   /* src_gen_dphy_apb_sw_rst_de_assert */
+   clrbits_le32(REG_SRC_DPHY_SW_CTRL, BIT(0));
+   /* src_gen_dphy_sw_rst_de_assert() */
+   clrbits_le32(REG_SRC_DPHY_SINGLE_RESET_SW_CTRL, BIT(2));
+}
+
+static void check_ddrc_idle(void)
+{
+   u32 regval;
+
+   readl_poll_timeout(REG_DDRDSR_2, regval, regval & BIT(31), 0);
+}
+
+static void check_dfi_init_complete(void)
+{
+   u32 regval;
+
+   readl_poll_timeout(REG_DDRDSR_2, regval, regval & BIT(2), 0);
+
+   setbits_le32(REG_DDRDSR_2, BIT(2));
+}
+
+static void ddrc_config(struct dram_timing_info *dram_timing)
+{
+   u32 num = dram_timing->ddrc_cfg_num;
+   struct dram_cfg_param *ddrc_config;
+   int i = 0;
+
+   ddrc_config = dram_timing->ddrc_cfg;
+   for (i = 0; i < num; i++) {
+   writel(ddrc_config->val, (ulong)ddrc_config->reg);
+   ddrc_config++;
+   }
+
+   if (dram_timing->fsp_cfg) {
+   

[PATCH 06/13] ddr: imx8m: move phy_base to controller struct

2023-11-10 Thread Sascha Hauer
The phy_base will be different on i.MX9, so move the base address to
struct dram_controller.

Signed-off-by: Sascha Hauer 
---
 drivers/ddr/imx/ddrphy_train.c   | 24 
 drivers/ddr/imx/helper.c | 12 ++--
 drivers/ddr/imx/imx8m_ddr_init.c | 13 ++---
 include/soc/imx8m/ddr.h  | 22 +-
 4 files changed, 41 insertions(+), 30 deletions(-)

diff --git a/drivers/ddr/imx/ddrphy_train.c b/drivers/ddr/imx/ddrphy_train.c
index b44f5ef9b4..af4d710dc0 100644
--- a/drivers/ddr/imx/ddrphy_train.c
+++ b/drivers/ddr/imx/ddrphy_train.c
@@ -107,7 +107,7 @@ int ddr_cfg_phy(struct dram_controller *dram, struct 
dram_timing_info *dram_timi
num  = dram_timing->ddrphy_cfg_num;
for (i = 0; i < num; i++) {
/* config phy reg */
-   dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val);
+   dwc_ddrphy_apb_wr(dram, dram_cfg->reg, dram_cfg->val);
dram_cfg++;
}
 
@@ -119,14 +119,14 @@ int ddr_cfg_phy(struct dram_controller *dram, struct 
dram_timing_info *dram_timi
dram->set_dfi_clk(dram, fsp_msg->drate);
 
/* load the dram training firmware image */
-   dwc_ddrphy_apb_wr(0xd, 0x0);
+   dwc_ddrphy_apb_wr(dram, 0xd, 0x0);
ddr_load_train_code(dram->dram_type, fsp_msg->fw_type);
 
/* load the frequency set point message block parameter */
dram_cfg = fsp_msg->fsp_cfg;
num = fsp_msg->fsp_cfg_num;
for (j = 0; j < num; j++) {
-   dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val);
+   dwc_ddrphy_apb_wr(dram, dram_cfg->reg, dram_cfg->val);
dram_cfg++;
}
 
@@ -140,10 +140,10 @@ int ddr_cfg_phy(struct dram_controller *dram, struct 
dram_timing_info *dram_timi
 * 4. read the message block result.
 * -
 */
-   dwc_ddrphy_apb_wr(0xd, 0x1);
-   dwc_ddrphy_apb_wr(0xd0099, 0x9);
-   dwc_ddrphy_apb_wr(0xd0099, 0x1);
-   dwc_ddrphy_apb_wr(0xd0099, 0x0);
+   dwc_ddrphy_apb_wr(dram, 0xd, 0x1);
+   dwc_ddrphy_apb_wr(dram, 0xd0099, 0x9);
+   dwc_ddrphy_apb_wr(dram, 0xd0099, 0x1);
+   dwc_ddrphy_apb_wr(dram, 0xd0099, 0x0);
 
/* Wait for the training firmware to complete */
ret = wait_ddrphy_training_complete();
@@ -151,17 +151,17 @@ int ddr_cfg_phy(struct dram_controller *dram, struct 
dram_timing_info *dram_timi
return ret;
 
/* Halt the microcontroller. */
-   dwc_ddrphy_apb_wr(0xd0099, 0x1);
+   dwc_ddrphy_apb_wr(dram, 0xd0099, 0x1);
 
/* Read the Message Block results */
-   dwc_ddrphy_apb_wr(0xd, 0x0);
+   dwc_ddrphy_apb_wr(dram, 0xd, 0x0);
 
ddrphy_init_read_msg_block(fsp_msg->fw_type);
 
if (fsp_msg->fw_type != FW_2D_IMAGE)
dram->get_trained_CDD(dram, i);
 
-   dwc_ddrphy_apb_wr(0xd, 0x1);
+   dwc_ddrphy_apb_wr(dram, 0xd, 0x1);
 
fsp_msg++;
}
@@ -170,12 +170,12 @@ int ddr_cfg_phy(struct dram_controller *dram, struct 
dram_timing_info *dram_timi
dram_cfg = dram_timing->ddrphy_pie;
num = dram_timing->ddrphy_pie_num;
for (i = 0; i < num; i++) {
-   dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val);
+   dwc_ddrphy_apb_wr(dram, dram_cfg->reg, dram_cfg->val);
dram_cfg++;
}
 
/* save the ddr PHY trained CSR in memory for low power use */
-   ddrphy_trained_csr_save(ddrphy_trained_csr, ddrphy_trained_csr_num);
+   ddrphy_trained_csr_save(dram, ddrphy_trained_csr, 
ddrphy_trained_csr_num);
 
return 0;
 }
diff --git a/drivers/ddr/imx/helper.c b/drivers/ddr/imx/helper.c
index 81c3ed7f30..0bd8d2688a 100644
--- a/drivers/ddr/imx/helper.c
+++ b/drivers/ddr/imx/helper.c
@@ -10,21 +10,21 @@
 #include 
 #include 
 
-void ddrphy_trained_csr_save(struct dram_cfg_param *ddrphy_csr,
+void ddrphy_trained_csr_save(struct dram_controller *dram, struct 
dram_cfg_param *ddrphy_csr,
 unsigned int num)
 {
int i = 0;
 
/* enable the ddrphy apb */
-   dwc_ddrphy_apb_wr(0xd, 0x0);
-   dwc_ddrphy_apb_wr(0xc0080, 0x3);
+   dwc_ddrphy_apb_wr(dram, 0xd, 0x0);
+   dwc_ddrphy_apb_wr(dram, 0xc0080, 0x3);
for (i = 0; i < num; i++) {
-   ddrphy_csr->val = dwc_ddrphy_apb_rd(ddrphy_csr->reg);
+   ddrphy_csr->val = dwc_ddrphy_apb_rd(dram, ddrphy_csr->reg);
ddrphy_csr++;
}
/* disable the ddrphy apb */
-   dwc_ddrphy_apb_wr(0xc0080, 0x2);
-   

[PATCH 10/13] ddr: imx8m: return cfg from dram_config_save()

2023-11-10 Thread Sascha Hauer
Upcoming i.MX9 support needs this.

Signed-off-by: Sascha Hauer 
---
 drivers/ddr/imx/helper.c | 4 +++-
 include/soc/imx/ddr.h| 2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/ddr/imx/helper.c b/drivers/ddr/imx/helper.c
index 0bd8d2688a..f21b14447c 100644
--- a/drivers/ddr/imx/helper.c
+++ b/drivers/ddr/imx/helper.c
@@ -27,7 +27,7 @@ void ddrphy_trained_csr_save(struct dram_controller *dram, 
struct dram_cfg_param
dwc_ddrphy_apb_wr(dram, 0xd, 0x1);
 }
 
-void dram_config_save(struct dram_timing_info *timing_info,
+void *dram_config_save(struct dram_timing_info *timing_info,
  unsigned long saved_timing_base)
 {
int i = 0;
@@ -83,4 +83,6 @@ void dram_config_save(struct dram_timing_info *timing_info,
cfg->val = timing_info->ddrphy_pie[i].val;
cfg++;
}
+
+   return cfg;
 }
diff --git a/include/soc/imx/ddr.h b/include/soc/imx/ddr.h
index 711abc07ba..bc793cf3ed 100644
--- a/include/soc/imx/ddr.h
+++ b/include/soc/imx/ddr.h
@@ -90,7 +90,7 @@ static inline void ddr_get_firmware(enum dram_type dram_type)
 int ddr_cfg_phy(struct dram_controller *dram, struct dram_timing_info 
*timing_info);
 void ddrphy_trained_csr_save(struct dram_controller *dram, struct 
dram_cfg_param *param,
 unsigned int num);
-void dram_config_save(struct dram_timing_info *info, unsigned long base);
+void *dram_config_save(struct dram_timing_info *info, unsigned long base);
 
 /* utils function for ddr phy training */
 int wait_ddrphy_training_complete(struct dram_controller *dram);
-- 
2.39.2




[PATCH 00/13] Add i.MX9 DDR support

2023-11-10 Thread Sascha Hauer
The i.MX9 DDR controller is very similar to the one found on i.MX8M.
Most patches in this series are for preparing the i.MX8M DDR driver
for integrating i.MX9 support. i.MX9 support is added in the last patch.

Sascha

Sascha Hauer (13):
  ddr: imx8m: rename driver to imx
  ddr: imx8m: introduce dram_controller struct
  ddr: imx8m: move get_trained_CDD() to SoC code
  ddr: imx8m: move PLL init to SoC specific code
  ddr: imx8m: clean up defines
  ddr: imx8m: move phy_base to controller struct
  ddr: imx8m: remove empty function
  ddr: imx8m: get rid of hardcoded phy address
  ddr: imx8m: split header file
  ddr: imx8m: return cfg from dram_config_save()
  ddr: imx8m: Drop '8m' suffix from pr_fmt
  ddr: move imx8m_ddr_old_spreadsheet to controller
  ddr: Initial i.MX9 support

 arch/arm/boards/nxp-imx8mq-evk/ddrphy_train.c |  10 +-
 .../boards/phytec-som-imx8mq/ddrphy_train.c   |  12 +-
 arch/arm/boards/zii-imx8mq-dev/ddrphy_train.c |  10 +-
 drivers/ddr/Kconfig   |   2 +-
 drivers/ddr/Makefile  |   2 +-
 drivers/ddr/{imx8m => imx}/Kconfig|  12 +-
 drivers/ddr/imx/Makefile  |   8 +
 drivers/ddr/{imx8m => imx}/ddrphy_csr.c   |   2 +-
 drivers/ddr/{imx8m => imx}/ddrphy_train.c |  50 +-
 drivers/ddr/imx/ddrphy_utils.c|  97 +++
 drivers/ddr/{imx8m => imx}/helper.c   |  28 +-
 .../ddrphy_utils.c => imx/imx8m_ddr_init.c}   | 595 +--
 drivers/ddr/imx/imx9_ddr_init.c   | 698 ++
 drivers/ddr/imx8m/Makefile|   7 -
 drivers/ddr/imx8m/ddr_init.c  | 217 --
 include/soc/imx/ddr.h | 167 +
 include/soc/imx8m/ddr.h   | 162 +---
 include/soc/imx9/ddr.h|  18 +
 18 files changed, 1431 insertions(+), 666 deletions(-)
 rename drivers/ddr/{imx8m => imx}/Kconfig (51%)
 create mode 100644 drivers/ddr/imx/Makefile
 rename drivers/ddr/{imx8m => imx}/ddrphy_csr.c (99%)
 rename drivers/ddr/{imx8m => imx}/ddrphy_train.c (75%)
 create mode 100644 drivers/ddr/imx/ddrphy_utils.c
 rename drivers/ddr/{imx8m => imx}/helper.c (74%)
 rename drivers/ddr/{imx8m/ddrphy_utils.c => imx/imx8m_ddr_init.c} (66%)
 create mode 100644 drivers/ddr/imx/imx9_ddr_init.c
 delete mode 100644 drivers/ddr/imx8m/Makefile
 delete mode 100644 drivers/ddr/imx8m/ddr_init.c
 create mode 100644 include/soc/imx/ddr.h
 create mode 100644 include/soc/imx9/ddr.h

-- 
2.39.2




[PATCH 08/13] ddr: imx8m: get rid of hardcoded phy address

2023-11-10 Thread Sascha Hauer
The phy address is hardcoded in several functions. Use the address
provided in struct dram_controller instead. Some functions are used
from legacy DDR setup in board code which only uses parts of the
DDR initialization code. The board code doesn't have any struct
dram_controller *, so provide some static inline wrappers for these
functions.

Signed-off-by: Sascha Hauer 
---
 arch/arm/boards/nxp-imx8mq-evk/ddrphy_train.c | 10 ++---
 .../boards/phytec-som-imx8mq/ddrphy_train.c   | 12 +++---
 arch/arm/boards/zii-imx8mq-dev/ddrphy_train.c | 10 ++---
 drivers/ddr/imx/ddrphy_train.c| 14 +++
 drivers/ddr/imx/ddrphy_utils.c| 40 ---
 include/soc/imx8m/ddr.h   | 17 ++--
 6 files changed, 53 insertions(+), 50 deletions(-)

diff --git a/arch/arm/boards/nxp-imx8mq-evk/ddrphy_train.c 
b/arch/arm/boards/nxp-imx8mq-evk/ddrphy_train.c
index e8577369dc..bac7d0a517 100644
--- a/arch/arm/boards/nxp-imx8mq-evk/ddrphy_train.c
+++ b/arch/arm/boards/nxp-imx8mq-evk/ddrphy_train.c
@@ -144,7 +144,7 @@ void ddr_cfg_phy(void) {
//enable APB bus to access DDRPHY RAM
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd, 0x0);
//load the 1D training image
-   ddr_load_train_code(DRAM_TYPE_LPDDR4, FW_1D_IMAGE);
+   imx8m_ddr_load_train_code(DRAM_TYPE_LPDDR4, FW_1D_IMAGE);
 
//configure DDRPHY-FW DMEM structure @clock0...
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x1);
@@ -189,7 +189,7 @@ void ddr_cfg_phy(void) {
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x9);
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x1);
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x0);
-   wait_ddrphy_training_complete();
+   imx8m_wait_ddrphy_training_complete();
 
//configure DDRPHY-FW DMEM structure @clock1...
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x1);
@@ -258,7 +258,7 @@ void ddr_cfg_phy(void) {
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x9);
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x1);
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x0);
-   wait_ddrphy_training_complete();
+   imx8m_wait_ddrphy_training_complete();
 
//set the PHY input clock to the desired frequency for pstate 0
reg32_write(0x3038a088,0x707);
@@ -291,7 +291,7 @@ void ddr_cfg_phy(void) {
//enable APB bus to access DDRPHY RAM
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd, 0x0);
//load the 2D training image
-   ddr_load_train_code(DRAM_TYPE_LPDDR4, FW_2D_IMAGE);
+   imx8m_ddr_load_train_code(DRAM_TYPE_LPDDR4, FW_2D_IMAGE);
 
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54003,0xc80);
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54006,0x11);
@@ -332,7 +332,7 @@ void ddr_cfg_phy(void) {
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x9);
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x1);
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x0);
-   wait_ddrphy_training_complete();
+   imx8m_wait_ddrphy_training_complete();
 
//Halt MPU
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x1);
diff --git a/arch/arm/boards/phytec-som-imx8mq/ddrphy_train.c 
b/arch/arm/boards/phytec-som-imx8mq/ddrphy_train.c
index 2ed6578093..fac9e184ae 100644
--- a/arch/arm/boards/phytec-som-imx8mq/ddrphy_train.c
+++ b/arch/arm/boards/phytec-som-imx8mq/ddrphy_train.c
@@ -148,7 +148,7 @@ void ddr_cfg_phy(void) {
//enable APB bus to access DDRPHY RAM
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd, 0x0);
//load the 1D training image
-   ddr_load_train_code(DRAM_TYPE_LPDDR4, FW_1D_IMAGE);
+   imx8m_ddr_load_train_code(DRAM_TYPE_LPDDR4, FW_1D_IMAGE);
 
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54003,0xc80);
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54004,0x2);
@@ -190,7 +190,7 @@ void ddr_cfg_phy(void) {
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x9);
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x1);
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x0);
-   wait_ddrphy_training_complete();
+   imx8m_wait_ddrphy_training_complete();
 
//configure DDRPHY-FW DMEM structure @clock1...
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd0099, 0x1);
@@ -224,7 +224,7 @@ void ddr_cfg_phy(void) {
//enable APB bus to access DDRPHY RAM
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0xd, 0x0);
//load the 1D training image
-   ddr_load_train_code(DRAM_TYPE_LPDDR4, FW_1D_IMAGE);
+   imx8m_ddr_load_train_code(DRAM_TYPE_LPDDR4, FW_1D_IMAGE);
 
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 4 * 0x54002,0x1);

[PATCH 01/13] ddr: imx8m: rename driver to imx

2023-11-10 Thread Sascha Hauer
The i.MX8M ddr driver can be re-used for i.MX93, so drop the '8m' suffix
from the driver directories and Kconfig options.

Signed-off-by: Sascha Hauer 
---
 drivers/ddr/Kconfig| 2 +-
 drivers/ddr/Makefile   | 2 +-
 drivers/ddr/{imx8m => imx}/Kconfig | 6 +-
 drivers/ddr/imx/Makefile   | 7 +++
 drivers/ddr/{imx8m => imx}/ddrphy_csr.c| 0
 drivers/ddr/{imx8m => imx}/ddrphy_train.c  | 0
 drivers/ddr/{imx8m => imx}/ddrphy_utils.c  | 0
 drivers/ddr/{imx8m => imx}/helper.c| 0
 drivers/ddr/{imx8m/ddr_init.c => imx/imx8m_ddr_init.c} | 0
 drivers/ddr/imx8m/Makefile | 7 ---
 10 files changed, 14 insertions(+), 10 deletions(-)
 rename drivers/ddr/{imx8m => imx}/Kconfig (72%)
 create mode 100644 drivers/ddr/imx/Makefile
 rename drivers/ddr/{imx8m => imx}/ddrphy_csr.c (100%)
 rename drivers/ddr/{imx8m => imx}/ddrphy_train.c (100%)
 rename drivers/ddr/{imx8m => imx}/ddrphy_utils.c (100%)
 rename drivers/ddr/{imx8m => imx}/helper.c (100%)
 rename drivers/ddr/{imx8m/ddr_init.c => imx/imx8m_ddr_init.c} (100%)
 delete mode 100644 drivers/ddr/imx8m/Makefile

diff --git a/drivers/ddr/Kconfig b/drivers/ddr/Kconfig
index 17d01ab658..0b0d7a8893 100644
--- a/drivers/ddr/Kconfig
+++ b/drivers/ddr/Kconfig
@@ -1,3 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0-only
 source "drivers/ddr/fsl/Kconfig"
-source "drivers/ddr/imx8m/Kconfig"
+source "drivers/ddr/imx/Kconfig"
diff --git a/drivers/ddr/Makefile b/drivers/ddr/Makefile
index 0b5ac949a4..e5d7bd14db 100644
--- a/drivers/ddr/Makefile
+++ b/drivers/ddr/Makefile
@@ -1,3 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_DDR_FSL) += fsl/
-obj-$(CONFIG_IMX8M_DRAM) += imx8m/
+obj-$(CONFIG_IMX_DRAM) += imx/
diff --git a/drivers/ddr/imx8m/Kconfig b/drivers/ddr/imx/Kconfig
similarity index 72%
rename from drivers/ddr/imx8m/Kconfig
rename to drivers/ddr/imx/Kconfig
index 720448f551..43e9181582 100644
--- a/drivers/ddr/imx8m/Kconfig
+++ b/drivers/ddr/imx/Kconfig
@@ -1,8 +1,12 @@
 # SPDX-License-Identifier: GPL-2.0-only
-menu "i.MX8M DDR controllers"
+menu "i.MX DDR controllers"
depends on ARCH_IMX8MQ || ARCH_IMX8MM || ARCH_IMX8MN || ARCH_IMX8MP
 
+config IMX_DRAM
+   bool
+
 config IMX8M_DRAM
+   select IMX_DRAM
bool "imx8m dram controller support"
 
 endmenu
diff --git a/drivers/ddr/imx/Makefile b/drivers/ddr/imx/Makefile
new file mode 100644
index 00..62d09e731a
--- /dev/null
+++ b/drivers/ddr/imx/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright 2018 NXP
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+pbl-$(CONFIG_IMX_DRAM) += helper.o ddrphy_utils.o ddrphy_train.o ddrphy_csr.o
+pbl-$(CONFIG_IMX8M_DRAM) += imx8m_ddr_init.o
diff --git a/drivers/ddr/imx8m/ddrphy_csr.c b/drivers/ddr/imx/ddrphy_csr.c
similarity index 100%
rename from drivers/ddr/imx8m/ddrphy_csr.c
rename to drivers/ddr/imx/ddrphy_csr.c
diff --git a/drivers/ddr/imx8m/ddrphy_train.c b/drivers/ddr/imx/ddrphy_train.c
similarity index 100%
rename from drivers/ddr/imx8m/ddrphy_train.c
rename to drivers/ddr/imx/ddrphy_train.c
diff --git a/drivers/ddr/imx8m/ddrphy_utils.c b/drivers/ddr/imx/ddrphy_utils.c
similarity index 100%
rename from drivers/ddr/imx8m/ddrphy_utils.c
rename to drivers/ddr/imx/ddrphy_utils.c
diff --git a/drivers/ddr/imx8m/helper.c b/drivers/ddr/imx/helper.c
similarity index 100%
rename from drivers/ddr/imx8m/helper.c
rename to drivers/ddr/imx/helper.c
diff --git a/drivers/ddr/imx8m/ddr_init.c b/drivers/ddr/imx/imx8m_ddr_init.c
similarity index 100%
rename from drivers/ddr/imx8m/ddr_init.c
rename to drivers/ddr/imx/imx8m_ddr_init.c
diff --git a/drivers/ddr/imx8m/Makefile b/drivers/ddr/imx8m/Makefile
deleted file mode 100644
index 2be313900f..00
--- a/drivers/ddr/imx8m/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Copyright 2018 NXP
-#
-# SPDX-License-Identifier: GPL-2.0+
-#
-
-pbl-$(CONFIG_IMX8M_DRAM) += helper.o ddrphy_utils.o ddrphy_train.o 
ddrphy_csr.o ddr_init.o
-- 
2.39.2




[PATCH 07/13] ddr: imx8m: remove empty function

2023-11-10 Thread Sascha Hauer
ddrphy_init_read_msg_block() is empty. Remove it.

Signed-off-by: Sascha Hauer 
---
 drivers/ddr/imx/ddrphy_train.c | 2 --
 drivers/ddr/imx/ddrphy_utils.c | 4 
 include/soc/imx8m/ddr.h| 1 -
 3 files changed, 7 deletions(-)

diff --git a/drivers/ddr/imx/ddrphy_train.c b/drivers/ddr/imx/ddrphy_train.c
index af4d710dc0..302acdfe62 100644
--- a/drivers/ddr/imx/ddrphy_train.c
+++ b/drivers/ddr/imx/ddrphy_train.c
@@ -156,8 +156,6 @@ int ddr_cfg_phy(struct dram_controller *dram, struct 
dram_timing_info *dram_timi
/* Read the Message Block results */
dwc_ddrphy_apb_wr(dram, 0xd, 0x0);
 
-   ddrphy_init_read_msg_block(fsp_msg->fw_type);
-
if (fsp_msg->fw_type != FW_2D_IMAGE)
dram->get_trained_CDD(dram, i);
 
diff --git a/drivers/ddr/imx/ddrphy_utils.c b/drivers/ddr/imx/ddrphy_utils.c
index 4577547113..5f80b8fdc1 100644
--- a/drivers/ddr/imx/ddrphy_utils.c
+++ b/drivers/ddr/imx/ddrphy_utils.c
@@ -101,7 +101,3 @@ int wait_ddrphy_training_complete(void)
}
}
 }
-
-void ddrphy_init_read_msg_block(enum fw_type type)
-{
-}
diff --git a/include/soc/imx8m/ddr.h b/include/soc/imx8m/ddr.h
index bdf0f25727..0a2a7b0e2f 100644
--- a/include/soc/imx8m/ddr.h
+++ b/include/soc/imx8m/ddr.h
@@ -456,7 +456,6 @@ void dram_config_save(struct dram_timing_info *info, 
unsigned long base);
 
 /* utils function for ddr phy training */
 int wait_ddrphy_training_complete(void);
-void ddrphy_init_read_msg_block(enum fw_type fw_type);
 
 #define reg32_write(a, v)  writel(v, a)
 #define reg32_read(a)  readl(a)
-- 
2.39.2




[PATCH 09/13] ddr: imx8m: split header file

2023-11-10 Thread Sascha Hauer
Split the header file to a common part and a SoC specific part so that
upcoming i.MX9 support can re-use the common part.

Signed-off-by: Sascha Hauer 
---
 include/soc/imx/ddr.h   | 150 
 include/soc/imx8m/ddr.h | 140 +
 2 files changed, 151 insertions(+), 139 deletions(-)
 create mode 100644 include/soc/imx/ddr.h

diff --git a/include/soc/imx/ddr.h b/include/soc/imx/ddr.h
new file mode 100644
index 00..711abc07ba
--- /dev/null
+++ b/include/soc/imx/ddr.h
@@ -0,0 +1,150 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2017 NXP
+ */
+
+#ifndef __SOC_IMX_DDR_H
+#define __SOC_IMX_DDR_H
+
+/* user data type */
+enum fw_type {
+   FW_1D_IMAGE,
+   FW_2D_IMAGE,
+};
+
+enum dram_type {
+#define DRAM_TYPE_MASK 0x00ff
+   DRAM_TYPE_LPDDR4= 0 << 0,
+   DRAM_TYPE_DDR4  = 1 << 0,
+};
+
+static inline enum dram_type get_dram_type(unsigned type)
+{
+   return type & DRAM_TYPE_MASK;
+}
+
+enum ddrc_type {
+#define DDRC_TYPE_MASK 0xff00
+   DDRC_TYPE_MM = 0 << 8,
+   DDRC_TYPE_MN = 1 << 8,
+   DDRC_TYPE_MQ = 2 << 8,
+   DDRC_TYPE_MP = 3 << 8,
+};
+
+static inline enum ddrc_type get_ddrc_type(unsigned type)
+{
+   return type & DDRC_TYPE_MASK;
+}
+
+struct dram_cfg_param {
+   unsigned int reg;
+   unsigned int val;
+};
+
+struct dram_fsp_msg {
+   unsigned int drate;
+   enum fw_type fw_type;
+   struct dram_cfg_param *fsp_cfg;
+   unsigned int fsp_cfg_num;
+};
+
+struct dram_timing_info {
+   /* umctl2 config */
+   struct dram_cfg_param *ddrc_cfg;
+   unsigned int ddrc_cfg_num;
+   /* ddrphy config */
+   struct dram_cfg_param *ddrphy_cfg;
+   unsigned int ddrphy_cfg_num;
+   /* ddr fsp train info */
+   struct dram_fsp_msg *fsp_msg;
+   unsigned int fsp_msg_num;
+   /* ddr phy trained CSR */
+   struct dram_cfg_param *ddrphy_trained_csr;
+   unsigned int ddrphy_trained_csr_num;
+   /* ddr phy PIE */
+   struct dram_cfg_param *ddrphy_pie;
+   unsigned int ddrphy_pie_num;
+   /* initialized drate table */
+   unsigned int fsp_table[4];
+};
+
+struct dram_controller {
+   enum ddrc_type ddrc_type;
+   enum dram_type dram_type;
+   void __iomem *phy_base;
+   void (*get_trained_CDD)(struct dram_controller *dram, u32 fsp);
+   void (*set_dfi_clk)(struct dram_controller *dram, unsigned int 
drate_mhz);
+};
+
+void ddr_get_firmware_lpddr4(void);
+void ddr_get_firmware_ddr(void);
+
+static inline void ddr_get_firmware(enum dram_type dram_type)
+{
+   if (dram_type == DRAM_TYPE_LPDDR4)
+   ddr_get_firmware_lpddr4();
+   else
+   ddr_get_firmware_ddr();
+}
+
+int ddr_cfg_phy(struct dram_controller *dram, struct dram_timing_info 
*timing_info);
+void ddrphy_trained_csr_save(struct dram_controller *dram, struct 
dram_cfg_param *param,
+unsigned int num);
+void dram_config_save(struct dram_timing_info *info, unsigned long base);
+
+/* utils function for ddr phy training */
+int wait_ddrphy_training_complete(struct dram_controller *dram);
+
+#define reg32_write(a, v)  writel(v, a)
+#define reg32_read(a)  readl(a)
+
+static inline void reg32setbit(unsigned long addr, u32 bit)
+{
+   setbits_le32(addr, (1 << bit));
+}
+
+static inline void *dwc_ddrphy_apb_addr(struct dram_controller *dram, unsigned 
int addr)
+{
+   return dram->phy_base + addr * 4;
+}
+
+static inline void dwc_ddrphy_apb_wr(struct dram_controller *dram, unsigned 
int addr, u32 data)
+{
+   reg32_write(dwc_ddrphy_apb_addr(dram, addr), data);
+}
+
+static inline u32 dwc_ddrphy_apb_rd(struct dram_controller *dram, unsigned int 
addr)
+{
+   return reg32_read(dwc_ddrphy_apb_addr(dram, addr));
+}
+
+extern struct dram_cfg_param ddrphy_trained_csr[];
+extern uint32_t ddrphy_trained_csr_num;
+
+enum ddrc_phy_firmware_offset {
+   DDRC_PHY_IMEM = 0x0005U,
+   DDRC_PHY_DMEM = 0x00054000U,
+};
+
+void ddr_load_train_code(struct dram_controller *dram, enum dram_type 
dram_type,
+enum fw_type fw_type);
+
+void ddrc_phy_load_firmware(struct dram_controller *dram,
+   enum ddrc_phy_firmware_offset,
+   const u16 *, size_t);
+
+static inline bool dram_is_lpddr4(enum dram_type dram_type)
+{
+   return IS_ENABLED(CONFIG_FIRMWARE_IMX_LPDDR4_PMU_TRAIN) &&
+   dram_type == DRAM_TYPE_LPDDR4;
+}
+
+static inline bool dram_is_ddr4(enum dram_type dram_type)
+{
+   return IS_ENABLED(CONFIG_FIRMWARE_IMX_DDR4_PMU_TRAIN) &&
+   dram_type == DRAM_TYPE_DDR4;
+}
+
+#define DDRC_PHY_REG(x)((x) * 4)
+
+#endif /* __SOC_IMX_DDR_H */
diff --git a/include/soc/imx8m/ddr.h b/include/soc/imx8m/ddr.h
index 04addc1448..abd9961099 100644
--- a/include/soc/imx8m/ddr.h
+++ b/include/soc/imx8m/ddr.h
@@ -9,6 +9,7 @@
 #include 
 #include 
 

[PATCH 11/13] ddr: imx8m: Drop '8m' suffix from pr_fmt

2023-11-10 Thread Sascha Hauer
As the driver will gain i.MX9 support, drop the '8m' suffix from the
messages.

Signed-off-by: Sascha Hauer 
---
 drivers/ddr/imx/ddrphy_csr.c   | 2 +-
 drivers/ddr/imx/ddrphy_train.c | 2 +-
 drivers/ddr/imx/ddrphy_utils.c | 2 +-
 drivers/ddr/imx/helper.c   | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/ddr/imx/ddrphy_csr.c b/drivers/ddr/imx/ddrphy_csr.c
index d1cbf8f880..744e140879 100644
--- a/drivers/ddr/imx/ddrphy_csr.c
+++ b/drivers/ddr/imx/ddrphy_csr.c
@@ -3,7 +3,7 @@
  * Copyright 2018 NXP
  */
 
-#define pr_fmt(fmt) "imx8m-ddr: " fmt
+#define pr_fmt(fmt) "imx-ddr: " fmt
 
 #include 
 #include 
diff --git a/drivers/ddr/imx/ddrphy_train.c b/drivers/ddr/imx/ddrphy_train.c
index c0555ffe01..d599445e6f 100644
--- a/drivers/ddr/imx/ddrphy_train.c
+++ b/drivers/ddr/imx/ddrphy_train.c
@@ -3,7 +3,7 @@
  * Copyright 2018 NXP
  */
 
-#define pr_fmt(fmt) "imx8m-ddr: " fmt
+#define pr_fmt(fmt) "imx-ddr: " fmt
 
 #include 
 #include 
diff --git a/drivers/ddr/imx/ddrphy_utils.c b/drivers/ddr/imx/ddrphy_utils.c
index 37274b0b5a..4925fc39d4 100644
--- a/drivers/ddr/imx/ddrphy_utils.c
+++ b/drivers/ddr/imx/ddrphy_utils.c
@@ -3,7 +3,7 @@
 * Copyright 2018 NXP
 */
 
-#define pr_fmt(fmt) "imx8m-ddr: " fmt
+#define pr_fmt(fmt) "imx-ddr: " fmt
 
 #include 
 #include 
diff --git a/drivers/ddr/imx/helper.c b/drivers/ddr/imx/helper.c
index f21b14447c..f38b9a0060 100644
--- a/drivers/ddr/imx/helper.c
+++ b/drivers/ddr/imx/helper.c
@@ -3,7 +3,7 @@
  * Copyright 2018 NXP
  */
 
-#define pr_fmt(fmt) "imx8m-ddr: " fmt
+#define pr_fmt(fmt) "imx-ddr: " fmt
 
 #include 
 #include 
-- 
2.39.2




[PATCH 16/25] ARM: Add TQ MBA9XXXCA board support

2023-11-10 Thread Sascha Hauer
The TQ MBA9XXXCA is a i.MX93 based board, see
https://www.tq-group.com/de/produkte/tq-embedded/arm-architektur/stka93xx/

Signed-off-by: Sascha Hauer 
---
 arch/arm/boards/Makefile  |1 +
 arch/arm/boards/tqmba9xxxca/Makefile  |2 +
 arch/arm/boards/tqmba9xxxca/board.c   |   58 +
 arch/arm/boards/tqmba9xxxca/lowlevel.c|   43 +
 .../tqmba9xxxca/lpddr4x_tqma93xxca_timing.c   | 1480 +
 arch/arm/dts/Makefile |1 +
 arch/arm/dts/imx93-tqma9352-mba93xxca.dts |  826 +
 arch/arm/mach-imx/Kconfig |9 +
 images/Makefile.imx   |   11 +
 9 files changed, 2431 insertions(+)
 create mode 100644 arch/arm/boards/tqmba9xxxca/Makefile
 create mode 100644 arch/arm/boards/tqmba9xxxca/board.c
 create mode 100644 arch/arm/boards/tqmba9xxxca/lowlevel.c
 create mode 100644 arch/arm/boards/tqmba9xxxca/lpddr4x_tqma93xxca_timing.c
 create mode 100644 arch/arm/dts/imx93-tqma9352-mba93xxca.dts

diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index bdac1e69ee..5b78c760b9 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -197,3 +197,4 @@ obj-$(CONFIG_MACH_RADXA_ROCK3)  += 
radxa-rock3/
 obj-$(CONFIG_MACH_RADXA_ROCK5) += radxa-rock5/
 obj-$(CONFIG_MACH_VARISCITE_DT8MCUSTOMBOARD_IMX8MP)+= 
variscite-dt8mcustomboard-imx8mp/
 obj-$(CONFIG_MACH_RADXA_CM3)   += radxa-cm3/
+obj-$(CONFIG_MACH_TQ_MBA9XXXCA)+= tqmba9xxxca/
diff --git a/arch/arm/boards/tqmba9xxxca/Makefile 
b/arch/arm/boards/tqmba9xxxca/Makefile
new file mode 100644
index 00..2957523cdd
--- /dev/null
+++ b/arch/arm/boards/tqmba9xxxca/Makefile
@@ -0,0 +1,2 @@
+lwl-y += lowlevel.o lpddr4x_tqma93xxca_timing.o
+obj-y += board.o
diff --git a/arch/arm/boards/tqmba9xxxca/board.c 
b/arch/arm/boards/tqmba9xxxca/board.c
new file mode 100644
index 00..b181784079
--- /dev/null
+++ b/arch/arm/boards/tqmba9xxxca/board.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define pr_fmt(fmt) "TQMa93xx: " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static void tqma93xx_init_pmic(struct regmap *map)
+{
+   /* BUCKxOUT_DVS0/1 control BUCK123 output */
+   regmap_write(map, PCA9450_BUCK123_DVS, 0x29);
+   /* enable DVS control through PMIC_STBY_REQ */
+   regmap_write(map, PCA9450_BUCK1CTRL, 0x59);
+   /* 0.9 V */
+   regmap_write(map, PCA9450_BUCK1OUT_DVS0, 0x18);
+   regmap_write(map, PCA9450_BUCK3OUT_DVS0, 0x18);
+   /* set standby voltage to 0.65v */
+   regmap_write(map, PCA9450_BUCK1OUT_DVS1, 0x4);
+
+   /* I2C_LT_EN*/
+   regmap_write(map, 0xa, 0x3);
+
+   /* set WDOG_B_CFG to cold reset */
+   regmap_write(map, PCA9450_RESET_CTRL, 0xA1);
+}
+
+static int tqma93xx_probe(struct device *dev)
+{
+   pca9450_register_init_callback(tqma93xx_init_pmic);
+
+   imx9_bbu_internal_mmcboot_register_handler("eMMC", "/dev/mmc0", 0);
+
+   return 0;
+}
+
+static const struct of_device_id tqma93xx_of_match[] = {
+{
+.compatible = "tq,imx93-tqma9352",
+},
+{ /* sentinel */ },
+};
+
+static struct driver tqma93xx_board_driver = {
+.name = "board-tqma93xx",
+.probe = tqma93xx_probe,
+.of_compatible = tqma93xx_of_match,
+};
+coredevice_platform_driver(tqma93xx_board_driver);
+
+BAREBOX_DEEP_PROBE_ENABLE(tqma93xx_of_match);
diff --git a/arch/arm/boards/tqmba9xxxca/lowlevel.c 
b/arch/arm/boards/tqmba9xxxca/lowlevel.c
new file mode 100644
index 00..8207cd9515
--- /dev/null
+++ b/arch/arm/boards/tqmba9xxxca/lowlevel.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+extern char __dtb_z_imx93_tqma9352_mba93xxca_start[];
+extern struct dram_timing_info tqma93xxca_dram_timing;
+
+static noinline void tqma9352_mba93xxca_continue(void)
+{
+   void *base = IOMEM(MX9_UART1_BASE_ADDR);
+   void *muxbase = IOMEM(MX9_IOMUXC_BASE_ADDR);
+
+   writel(0x0, muxbase + 0x184);
+   imx9_uart_setup(IOMEM(base));
+   pbl_set_putc(lpuart32_putc, base + 0x10);
+
+   if (current_el() == 3) {
+   imx93_ddr_init(_dram_timing, DRAM_TYPE_LPDDR4);
+
+   imx93_romapi_load_image();
+   imx93_load_and_start_image_via_tfa();
+   }
+
+   barebox_arm_entry(0x8000, 0x4000, 
__dtb_z_imx93_tqma9352_mba93xxca_start);
+}
+
+ENTRY_FUNCTION(start_imx93_tqma9352_mba93xxca, r0, r1, r2)
+{
+   if (current_el() == 3)
+   imx93_cpu_lowlevel_init();
+
+   relocate_to_current_adr();
+   setup_c();
+
+   tqma9352_mba93xxca_continue();
+}
diff --git a/arch/arm/boards/tqmba9xxxca/lpddr4x_tqma93xxca_timing.c 
b/arch/arm/boards/tqmba9xxxca/lpddr4x_tqma93xxca_timing.c
new 

[PATCH 12/25] i2c: Add lpi2c support

2023-11-10 Thread Sascha Hauer
Signed-off-by: Sascha Hauer 
---
 drivers/i2c/busses/Kconfig |   7 +
 drivers/i2c/busses/Makefile|   1 +
 drivers/i2c/busses/i2c-imx-lpi2c.c | 518 +
 3 files changed, 526 insertions(+)
 create mode 100644 drivers/i2c/busses/i2c-imx-lpi2c.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 766aa5edfa..a274baf4b6 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -30,6 +30,13 @@ config I2C_IMX
  for many i.MX ARM based SoCs, for MPC85xx and MPC5200 PowerPC based
  SoCs.
 
+config I2C_IMX_LPI2C
+   tristate "IMX Low Power I2C interface"
+   depends on ARCH_IMX || COMPILE_TEST
+   help
+ Say Y here if you want to use the Low Power IIC bus controller
+ on the Freescale i.MX processors.
+
 config I2C_DESIGNWARE
bool "Synopsys DesignWare I2C Master driver"
help
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index a1ab46fb28..48f9b5be04 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_I2C_BCM283X)   += i2c-bcm283x.o
 obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o
 obj-$(CONFIG_I2C_IMX)  += i2c-imx.o
 lwl-$(CONFIG_I2C_IMX_EARLY)+= i2c-imx-early.o
+obj-$(CONFIG_I2C_IMX_LPI2C)+= i2c-imx-lpi2c.o
 obj-$(CONFIG_I2C_MV64XXX)  += i2c-mv64xxx.o
 obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
 obj-$(CONFIG_I2C_TEGRA)+= i2c-tegra.o
diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c 
b/drivers/i2c/busses/i2c-imx-lpi2c.c
new file mode 100644
index 00..f28a445601
--- /dev/null
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -0,0 +1,518 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * This is i.MX low power i2c controller driver.
+ *
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#define DRIVER_NAME "imx-lpi2c"
+
+#define LPI2C_PARAM0x04/* i2c RX/TX FIFO size */
+#define LPI2C_MCR  0x10/* i2c contrl register */
+#define LPI2C_MSR  0x14/* i2c status register */
+#define LPI2C_MIER 0x18/* i2c interrupt enable */
+#define LPI2C_MCFGR0   0x20/* i2c master configuration */
+#define LPI2C_MCFGR1   0x24/* i2c master configuration */
+#define LPI2C_MCFGR2   0x28/* i2c master configuration */
+#define LPI2C_MCFGR3   0x2C/* i2c master configuration */
+#define LPI2C_MCCR00x48/* i2c master clk configuration */
+#define LPI2C_MCCR10x50/* i2c master clk configuration */
+#define LPI2C_MFCR 0x58/* i2c master FIFO control */
+#define LPI2C_MFSR 0x5C/* i2c master FIFO status */
+#define LPI2C_MTDR 0x60/* i2c master TX data register */
+#define LPI2C_MRDR 0x70/* i2c master RX data register */
+
+/* i2c command */
+#define TRAN_DATA  0X00
+#define RECV_DATA  0X01
+#define GEN_STOP   0X02
+#define RECV_DISCARD   0X03
+#define GEN_START  0X04
+#define START_NACK 0X05
+#define START_HIGH 0X06
+#define START_HIGH_NACK0X07
+
+#define MCR_MENBIT(0)
+#define MCR_RSTBIT(1)
+#define MCR_DOZEN  BIT(2)
+#define MCR_DBGEN  BIT(3)
+#define MCR_RTFBIT(8)
+#define MCR_RRFBIT(9)
+#define MSR_TDFBIT(0)
+#define MSR_RDFBIT(1)
+#define MSR_SDFBIT(9)
+#define MSR_NDFBIT(10)
+#define MSR_ALFBIT(11)
+#define MSR_MBFBIT(24)
+#define MSR_BBFBIT(25)
+#define MIER_TDIE  BIT(0)
+#define MIER_RDIE  BIT(1)
+#define MIER_SDIE  BIT(9)
+#define MIER_NDIE  BIT(10)
+#define MCFGR1_AUTOSTOPBIT(8)
+#define MCFGR1_IGNACK  BIT(9)
+#define MRDR_RXEMPTY   BIT(14)
+
+#define I2C_CLK_RATIO  2
+#define CHUNK_DATA 256
+
+#define I2C_PM_TIMEOUT 10 /* ms */
+
+enum lpi2c_imx_mode {
+   STANDARD,   /* 100+Kbps */
+   FAST,   /* 400+Kbps */
+   FAST_PLUS,  /* 1.0+Mbps */
+   HS, /* 3.4+Mbps */
+   ULTRA_FAST, /* 5.0+Mbps */
+};
+
+enum lpi2c_imx_pincfg {
+   TWO_PIN_OD,
+   TWO_PIN_OO,
+   TWO_PIN_PP,
+   FOUR_PIN_PP,
+};
+
+struct lpi2c_imx_struct {
+   struct i2c_adapter  adapter;
+   int num_clks;
+   struct clk_bulk_data*clks;
+   void __iomem*base;
+   __u8*rx_buf;
+   __u8*tx_buf;
+   unsigned intmsglen;
+   unsigned intdelivered;
+   unsigned intbitrate;
+   unsigned inttxfifosize;
+   unsigned intrxfifosize;
+   enum lpi2c_imx_mode mode;
+};
+
+static void lpi2c_imx_intctrl(struct lpi2c_imx_struct *lpi2c_imx,
+   

[PATCH 10/25] watchdog: Add ULP wdog support

2023-11-10 Thread Sascha Hauer
Signed-off-by: Sascha Hauer 
---
 drivers/watchdog/Kconfig  |   6 ++
 drivers/watchdog/Makefile |   1 +
 drivers/watchdog/imxulp-wdt.c | 161 ++
 3 files changed, 168 insertions(+)
 create mode 100644 drivers/watchdog/imxulp-wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e5c2036e6d..159b495acb 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -59,6 +59,12 @@ config WATCHDOG_IMX
help
  Add support for watchdog found on Freescale i.MX SoCs.
 
+config WATCHDOG_IMXULP
+   bool "i.MX ULP watchdog"
+   depends on ARCH_IMX || COMPILE_TEST
+   help
+ Add support for watchdog found on Freescale i.MX SoCs.
+
 config WATCHDOG_JZ4740
bool "Ingenic jz4740 SoC hardware watchdog"
depends on MACH_MIPS_XBURST || COMPILE_TEST
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index cdd9460e34..2b0da7cea9 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_WATCHDOG_DW) += dw_wdt.o
 obj-$(CONFIG_WATCHDOG_JZ4740) += jz4740.o
 obj-$(CONFIG_WATCHDOG_IMX_RESET_SOURCE) += imxwd.o
 obj-$(CONFIG_WATCHDOG_IMX) += imxwd.o
+obj-$(CONFIG_WATCHDOG_IMXULP) += imxulp-wdt.o
 obj-$(CONFIG_WATCHDOG_KVX) += kvx_wdt.o
 obj-$(CONFIG_WATCHDOG_ORION) += orion_wdt.o
 obj-$(CONFIG_ARCH_BCM283X) += bcm2835_wdt.o
diff --git a/drivers/watchdog/imxulp-wdt.c b/drivers/watchdog/imxulp-wdt.c
new file mode 100644
index 00..78d1527782
--- /dev/null
+++ b/drivers/watchdog/imxulp-wdt.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct imxulp_socdata {
+   unsigned int rate;
+};
+
+struct imxulp_wd {
+   struct watchdog wd;
+   void __iomem *base;
+   unsigned int rate;
+   struct device *dev;
+};
+
+#define REFRESH_WORD0 0xA602 /* 1st refresh word */
+#define REFRESH_WORD1 0xB480 /* 2nd refresh word */
+
+#define UNLOCK_WORD0 0xC520 /* 1st unlock word */
+#define UNLOCK_WORD1 0xD928 /* 2nd unlock word */
+
+#define UNLOCK_WORD 0xD928C520 /* unlock word */
+#define REFRESH_WORD 0xB480A602 /* refresh word */
+
+#define WDOG_CS 0x0
+#define WDOG_CS_UPDATE BIT(5)
+#define WDOG_CS_EN BIT(7)
+#define WDOG_CS_RCSBIT(10)
+#define WDOG_CS_ULKBIT(11)
+#define WDOG_CS_PRES   BIT(12)
+#define WDOG_CS_CMD32ENBIT(13)
+#define WDOG_CS_FLGBIT(14)
+#define WDOG_CS_INTBIT(6)
+#define WDOG_CS_LPO_CLK(0x1 << 8)
+
+#define WDOG_CNT   0x4
+#define WDOG_TOVAL 0x8
+
+#define CLK_RATE_1KHZ  1000
+#define CLK_RATE_32KHZ 125
+
+static int imxulp_watchdog_set_timeout(struct watchdog *wd, unsigned int 
timeout)
+{
+   struct imxulp_wd *imxwd = container_of(wd, struct imxulp_wd, wd);
+   u32 cmd32 = 0;
+
+   if (timeout == 0)
+   return -ENOSYS;
+
+   if (readl(imxwd->base + WDOG_CS) & WDOG_CS_CMD32EN) {
+   writel(UNLOCK_WORD, imxwd->base + WDOG_CNT);
+   cmd32 = WDOG_CS_CMD32EN;
+   } else {
+   writel(UNLOCK_WORD0, imxwd->base + WDOG_CNT);
+   writel(UNLOCK_WORD1, imxwd->base + WDOG_CNT);
+   }
+
+   /* Wait WDOG Unlock */
+   while (!(readl(imxwd->base + WDOG_CS) & WDOG_CS_ULK))
+   ;
+
+   writel(timeout * imxwd->rate, imxwd->base + WDOG_TOVAL);
+
+   writel(cmd32 | WDOG_CS_EN | WDOG_CS_UPDATE | WDOG_CS_LPO_CLK |
+  WDOG_CS_FLG | WDOG_CS_PRES | WDOG_CS_INT, imxwd->base + WDOG_CS);
+
+   /* Wait WDOG reconfiguration */
+   while (!(readl(imxwd->base + WDOG_CS) & WDOG_CS_RCS))
+   ;
+
+   if (readl(imxwd->base + WDOG_CS) & WDOG_CS_CMD32EN) {
+   writel(REFRESH_WORD, imxwd->base + WDOG_CNT);
+   } else {
+   writel(REFRESH_WORD0, imxwd->base + WDOG_CNT);
+   writel(REFRESH_WORD1, imxwd->base + WDOG_CNT);
+   }
+
+   return 0;
+}
+
+static enum wdog_hw_runnning imxulp_wd_running(struct imxulp_wd *imxwd)
+{
+   if (readl(imxwd->base + WDOG_CS) & WDOG_CS_EN)
+   return WDOG_HW_RUNNING;
+   else
+   return WDOG_HW_NOT_RUNNING;
+}
+
+static int imxulp_wd_probe(struct device *dev)
+{
+   struct imxulp_wd *imxwd;
+   struct resource *iores;
+   struct imxulp_socdata *socdata;
+   int ret;
+
+   ret = dev_get_drvdata(dev, (const void **));
+   if (ret)
+   return ret;
+
+   imxwd = xzalloc(sizeof(*imxwd));
+   iores = dev_request_mem_resource(dev, 0);
+   if (IS_ERR(iores))
+   return dev_err_probe(dev, PTR_ERR(iores), "could not get memory 
region\n");
+
+   imxwd->rate = socdata->rate;
+   imxwd->base = 

[PATCH 18/25] ARM: i.MX: romapi: rename functions to *romapi*

2023-11-10 Thread Sascha Hauer
The file the romapi is implemented in is named romapi and that's also
the name the i.MX ROM API is normally referred to, so rename the
functions accordingly.
While at it, rename some internal functions from imx8m_* to imx_* as
they can and will also be used by upcoming i.MX9 support.

Signed-off-by: Sascha Hauer 
---
 arch/arm/mach-imx/atf.c|  4 ++--
 arch/arm/mach-imx/romapi.c | 14 +++---
 include/mach/imx/romapi.h  |  4 ++--
 3 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-imx/atf.c b/arch/arm/mach-imx/atf.c
index d6d1aa3d68..1a0ac72fff 100644
--- a/arch/arm/mach-imx/atf.c
+++ b/arch/arm/mach-imx/atf.c
@@ -157,7 +157,7 @@ void imx8mp_load_bl33(void *bl33)
imx8mp_esdhc_load_image(instance, false);
break;
case BOOTSOURCE_SERIAL:
-   imx8mp_bootrom_load_image();
+   imx8mp_romapi_load_image();
break;
case BOOTSOURCE_SPI:
imx8mp_qspi_load_image(instance, false);
@@ -221,7 +221,7 @@ void imx8mn_load_bl33(void *bl33)
imx8mn_esdhc_load_image(instance, false);
break;
case BOOTSOURCE_SERIAL:
-   imx8mn_bootrom_load_image();
+   imx8mn_romapi_load_image();
break;
case BOOTSOURCE_SPI:
imx8mn_qspi_load_image(instance, false);
diff --git a/arch/arm/mach-imx/romapi.c b/arch/arm/mach-imx/romapi.c
index aef0ff0534..29c2d4005c 100644
--- a/arch/arm/mach-imx/romapi.c
+++ b/arch/arm/mach-imx/romapi.c
@@ -14,7 +14,7 @@
 #include 
 #include 
 
-static int imx8m_bootrom_load(struct rom_api *rom_api, void *adr, size_t size)
+static int imx_romapi_load(struct rom_api *rom_api, void *adr, size_t size)
 {
while (size) {
size_t chunksize = min(size, (size_t)1024);
@@ -35,25 +35,25 @@ static int imx8m_bootrom_load(struct rom_api *rom_api, void 
*adr, size_t size)
 }
 
 /* read piggydata via a bootrom callback and place it behind our copy in SDRAM 
*/
-static int imx8m_bootrom_load_image(struct rom_api *rom_api)
+static int imx_romapi_load_image(struct rom_api *rom_api)
 {
-   return imx8m_bootrom_load(rom_api,
+   return imx_romapi_load(rom_api,
  (void *)MX8M_ATF_BL33_BASE_ADDR + 
barebox_pbl_size,
  __image_end - __piggydata_start);
 }
 
-int imx8mp_bootrom_load_image(void)
+int imx8mp_romapi_load_image(void)
 {
struct rom_api *rom_api = (void *)0x980;
 
OPTIMIZER_HIDE_VAR(rom_api);
 
-   return imx8m_bootrom_load_image(rom_api);
+   return imx_romapi_load_image(rom_api);
 }
 
-int imx8mn_bootrom_load_image(void)
+int imx8mn_romapi_load_image(void)
 {
-   return imx8mp_bootrom_load_image();
+   return imx8mp_romapi_load_image();
 }
 
 const u32 *imx8m_get_bootrom_log(void)
diff --git a/include/mach/imx/romapi.h b/include/mach/imx/romapi.h
index 2243fdcf6d..8ea7fbfb04 100644
--- a/include/mach/imx/romapi.h
+++ b/include/mach/imx/romapi.h
@@ -35,8 +35,8 @@ enum boot_dev_type_e {
 
 #define ROM_API_OKAY   0xF0
 
-int imx8mp_bootrom_load_image(void);
-int imx8mn_bootrom_load_image(void);
+int imx8mp_romapi_load_image(void);
+int imx8mn_romapi_load_image(void);
 
 /* only call after DRAM has been configured */
 void imx8m_save_bootrom_log(void *dst);
-- 
2.39.2




[PATCH 14/25] serial: Add lpuart32 driver

2023-11-10 Thread Sascha Hauer
This adds a lpuart32 driver. This is a variant of the lpuart driver
that is found on i.MX9 and other SoCs.

Signed-off-by: Sascha Hauer 
---
 drivers/serial/Kconfig   |   4 +
 drivers/serial/Makefile  |   1 +
 drivers/serial/serial_lpuart32.c | 185 +++
 include/serial/lpuart32.h| 158 ++
 4 files changed, 348 insertions(+)
 create mode 100644 drivers/serial/serial_lpuart32.c
 create mode 100644 include/serial/lpuart32.h

diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 77c827e436..803f6b6aee 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -122,6 +122,10 @@ config DRIVER_SERIAL_LPUART
default y
bool "LPUART serial driver"
 
+config DRIVER_SERIAL_LPUART32
+   depends on ARCH_IMX
+   bool "LPUART32 serial driver"
+
 config VIRTIO_CONSOLE
tristate "Virtio console"
depends on VIRTIO
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index bbc517f521..4887e24ee1 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_DRIVER_SERIAL_CADENCE)   += 
serial_cadence.o
 obj-$(CONFIG_DRIVER_SERIAL_EFI_STDIO)  += efi-stdio.o
 obj-$(CONFIG_DRIVER_SERIAL_DIGIC)  += serial_digic.o
 obj-$(CONFIG_DRIVER_SERIAL_LPUART) += serial_lpuart.o
+obj-$(CONFIG_DRIVER_SERIAL_LPUART32)   += serial_lpuart32.o
 obj-$(CONFIG_VIRTIO_CONSOLE)   += virtio_console.o
 obj-$(CONFIG_SERIAL_SIFIVE)+= serial_sifive.o
 obj-$(CONFIG_SERIAL_SBI)   += serial_sbi.o
diff --git a/drivers/serial/serial_lpuart32.c b/drivers/serial/serial_lpuart32.c
new file mode 100644
index 00..0f3e7c7a04
--- /dev/null
+++ b/drivers/serial/serial_lpuart32.c
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023 Pengutronix
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct lpuart32_devtype_data {
+   unsigned int reg_offs;
+};
+
+struct lpuart32 {
+   struct console_device cdev;
+   int baudrate;
+   int dte_mode;
+   struct notifier_block notify;
+   struct resource *io;
+   void __iomem *base;
+   struct clk *clk;
+};
+
+static struct lpuart32 *cdev_to_lpuart32(struct console_device *cdev)
+{
+   return container_of(cdev, struct lpuart32, cdev);
+}
+
+static void lpuart32_enable(struct lpuart32 *lpuart32)
+{
+   writel(LPUART32_UARTCTRL_TE | LPUART32_UARTCTRL_RE,
+  lpuart32->base + LPUART32_UARTCTRL);
+}
+
+static void lpuart32_disable(struct lpuart32 *lpuart32)
+{
+   writel(0, lpuart32->base + LPUART32_UARTCTRL);
+}
+
+static int lpuart32_serial_setbaudrate(struct console_device *cdev,
+int baudrate)
+{
+   struct lpuart32 *lpuart32 = cdev_to_lpuart32(cdev);
+
+   lpuart32_disable(lpuart32);
+
+   /*
+* We treat baudrate of 0 as a request to disable UART
+*/
+   if (baudrate) {
+   lpuart32_setbrg(lpuart32->base, clk_get_rate(lpuart32->clk),
+ baudrate);
+   lpuart32_enable(lpuart32);
+   }
+
+   lpuart32->baudrate = baudrate;
+
+   return 0;
+}
+
+static int lpuart32_serial_getc(struct console_device *cdev)
+{
+   struct lpuart32 *lpuart32 = cdev_to_lpuart32(cdev);
+
+   while (!(readl(lpuart32->base + LPUART32_UARTSTAT) & 
LPUART32_UARTSTAT_RDRF));
+
+   return readl(lpuart32->base + LPUART32_UARTDATA) & 0xff;
+}
+
+static void lpuart32_serial_putc(struct console_device *cdev, char c)
+{
+   struct lpuart32 *lpuart32 = cdev_to_lpuart32(cdev);
+
+   lpuart32_putc(lpuart32->base, c);
+}
+
+/* Test whether a character is in the RX buffer */
+static int lpuart32_serial_tstc(struct console_device *cdev)
+{
+   struct lpuart32 *lpuart32 = cdev_to_lpuart32(cdev);
+
+   return readl(lpuart32->base + LPUART32_UARTSTAT) & 
LPUART32_UARTSTAT_RDRF;
+}
+
+static void lpuart32_serial_flush(struct console_device *cdev)
+{
+}
+
+static int lpuart32_serial_probe(struct device *dev)
+{
+   int ret;
+   struct console_device *cdev;
+   struct lpuart32 *lpuart32;
+   const char *devname;
+   struct lpuart32_devtype_data *devtype;
+
+   ret = dev_get_drvdata(dev, (const void **));
+   if (ret)
+   return ret;
+
+   lpuart32 = xzalloc(sizeof(*lpuart32));
+   cdev = >cdev;
+   dev->priv = lpuart32;
+
+   lpuart32->io = dev_request_mem_resource(dev, 0);
+   if (IS_ERR(lpuart32->io)) {
+   ret = PTR_ERR(lpuart32->io);
+   goto err_free;
+   }
+   lpuart32->base = IOMEM(lpuart32->io->start) + devtype->reg_offs;
+
+   lpuart32->clk = clk_get(dev, NULL);
+   if (IS_ERR(lpuart32->clk)) {
+   ret = PTR_ERR(lpuart32->clk);
+   dev_err(dev, 

[PATCH 22/25] spi: spi-nxp-fspi: Enable for i.MX9

2023-11-10 Thread Sascha Hauer
The i.MX9 flexspi is compatible to the one on i.MX8mm, just add the
necessary Kconfig dependency.

Signed-off-by: Sascha Hauer 
---
 drivers/spi/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index e37c7821fb..445c756a38 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -112,7 +112,7 @@ config DRIVER_SPI_STM32
 
 config SPI_NXP_FLEXSPI
tristate "NXP Flex SPI controller"
-   depends on ARCH_IMX8M || COMPILE_TEST
+   depends on ARCH_IMX8M || ARCH_IMX93 || COMPILE_TEST
help
  This enables support for the Flex SPI controller in master mode.
  Up to four slave devices can be connected on two buses with two
-- 
2.39.2




[PATCH 04/25] scripts: Add imx9image tool

2023-11-10 Thread Sascha Hauer
This adds a tool for building images for the NXP i.MX9 SoC. The code
is based on:
https://github.com/nxp-imx/imx-mkimage/tree/5a0faefc223e51e088433663b6e7d6fbce89bf59

Signed-off-by: Sascha Hauer 
---
 include/soc/imx9/flash_header.h |   88 ++
 scripts/Kconfig |7 +
 scripts/Makefile|1 +
 scripts/imx9image.c | 2171 +++
 4 files changed, 2267 insertions(+)
 create mode 100644 include/soc/imx9/flash_header.h
 create mode 100644 scripts/imx9image.c

diff --git a/include/soc/imx9/flash_header.h b/include/soc/imx9/flash_header.h
new file mode 100644
index 00..51819929dd
--- /dev/null
+++ b/include/soc/imx9/flash_header.h
@@ -0,0 +1,88 @@
+#ifndef SOC_IMX_FLASH_HEADER_H
+#define SOC_IMX_FLASH_HEADER_H
+
+#define HASH_MAX_LEN   64
+#define IV_MAX_LEN 32
+#define MAX_NUM_IMGS   8
+#define MAX_NUM_OF_CONTAINER   3
+#define MAX_HW_CFG_SIZE_V2 359
+
+struct img_flags {
+   char type;
+   char core_id;
+   char hash_type;
+   bool encrypted;
+   uint16_t boot_flags;
+};
+
+struct sig_blk_hdr {
+   uint8_t version;
+   uint16_t length;
+   uint8_t tag;
+   uint16_t srk_table_offset;
+   uint16_t cert_offset;
+   uint16_t blob_offset;
+   uint16_t signature_offset;
+   uint32_t reserved;
+} __attribute__((packed));
+
+struct boot_img {
+   uint32_t offset;
+   uint32_t size;
+   uint64_t dst;
+   uint64_t entry;
+   uint32_t hab_flags;
+   uint32_t meta;
+   uint8_t hash[HASH_MAX_LEN];
+   uint8_t iv[IV_MAX_LEN];
+} __attribute__((packed));
+
+struct flash_header_v3 {
+   uint8_t version;
+   uint16_t length;
+   uint8_t tag;
+   uint32_t flags;
+   uint16_t sw_version;
+   uint8_t fuse_version;
+   uint8_t num_images;
+   uint16_t sig_blk_offset;
+   uint16_t reserved;
+   struct boot_img img[MAX_NUM_IMGS];
+   struct sig_blk_hdr sig_blk_hdr;
+   uint32_t sigblk_size;
+   uint32_t padding;
+} __attribute__((packed));
+
+struct ivt_header {
+   uint8_t tag;
+   uint16_t length;
+   uint8_t version;
+} __attribute__((packed));
+
+struct write_dcd_command {
+   uint8_t tag;
+   uint16_t length;
+   uint8_t param;
+} __attribute__((packed));
+
+struct dcd_addr_data {
+   uint32_t addr;
+   uint32_t value;
+};
+
+struct dcd_v2_cmd {
+   struct write_dcd_command write_dcd_command; /*4*/
+   struct dcd_addr_data addr_data[MAX_HW_CFG_SIZE_V2]; /*2872*/
+} __attribute__((packed));
+
+struct dcd_v2 {
+   struct ivt_header header;   /*4*/
+   struct dcd_v2_cmd dcd_cmd; /*2876*/
+} __attribute__((packed)) ; /*2880*/
+
+struct imx_header_v3 {
+   struct flash_header_v3 fhdr[MAX_NUM_OF_CONTAINER];
+   struct dcd_v2 dcd_table;
+}  __attribute__((packed));
+
+#endif /* SOC_IMX_FLASH_HEADER_H */
diff --git a/scripts/Kconfig b/scripts/Kconfig
index 9be04fa7c8..4b675671ee 100644
--- a/scripts/Kconfig
+++ b/scripts/Kconfig
@@ -28,6 +28,13 @@ config ZYNQ_MKIMAGE
help
  This enables building the image creation tool for Zynq
 
+config IMX9_IMAGE
+   bool "imx9image"
+   depends on ARCH_IMX93 || COMPILE_HOST_TOOLS
+   default y if ARCH_IMX93
+   help
+ This enables building the image tool for NXP i.MX9 SoCs
+
 config MXS_HOSTTOOLS
bool "MXS host tools" if COMPILE_HOST_TOOLS
depends on ARCH_MXS || COMPILE_HOST_TOOLS
diff --git a/scripts/Makefile b/scripts/Makefile
index 42ac4e548b..cb1d916439 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -25,6 +25,7 @@ hostprogs-always-$(CONFIG_SOCFPGA_MKIMAGE)+= 
socfpga_mkimage
 hostprogs-always-$(CONFIG_MXS_HOSTTOOLS)   += mxsimage mxsboot
 hostprogs-always-$(CONFIG_LAYERSCAPE_PBLIMAGE) += pblimage
 hostprogs-always-$(CONFIG_STM32_IMAGE) += stm32image
+hostprogs-always-$(CONFIG_IMX9_IMAGE)  += imx9image
 hostprogs-always-$(CONFIG_RISCV)   += prelink-riscv
 hostprogs-always-$(CONFIG_RK_IMAGE)+= rkimage
 HOSTCFLAGS_rkimage.o = `$(PKG_CONFIG) --cflags openssl`
diff --git a/scripts/imx9image.c b/scripts/imx9image.c
new file mode 100644
index 00..a991ba5f35
--- /dev/null
+++ b/scripts/imx9image.c
@@ -0,0 +1,2171 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ *
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier:GPL-2.0+
+ * derived from u-boot's mkimage utility
+ *
+ */
+
+#define _GNU_SOURCE
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "../include/soc/imx9/flash_header.h"
+#include "compiler.h"
+
+typedef enum option_type {
+   NO_IMG = 0,
+   DCD,
+   SCFW,
+   SECO,
+   M4,
+   AP,
+  

[PATCH 20/25] ARM: i.MX: atf: add imx93_load_and_start_image_via_tfa()

2023-11-10 Thread Sascha Hauer
Signed-off-by: Sascha Hauer 
---
 arch/arm/mach-imx/atf.c  | 34 ++
 include/mach/imx/atf.h   |  2 ++
 include/mach/imx/xload.h |  1 +
 3 files changed, 37 insertions(+)

diff --git a/arch/arm/mach-imx/atf.c b/arch/arm/mach-imx/atf.c
index 1a0ac72fff..e1a89ef543 100644
--- a/arch/arm/mach-imx/atf.c
+++ b/arch/arm/mach-imx/atf.c
@@ -329,3 +329,37 @@ __noreturn void imx8mq_load_and_start_image_via_tfa(void)
 
imx8m_atf_start_bl31(bl31, bl31_size, (void *)MX8MQ_ATF_BL31_BASE_ADDR);
 }
+
+void __noreturn imx93_load_and_start_image_via_tfa(void)
+{
+   unsigned long atf_dest = MX93_ATF_BL31_BASE_ADDR;
+   void __noreturn (*bl31)(void) = (void *)atf_dest;
+   const void *tfa;
+   size_t tfa_size;
+
+   /*
+* On completion the TF-A will jump to MX93_ATF_BL33_BASE_ADDR
+* in EL2. Copy the image there, but replace the PBL part of
+* that image with ourselves. On a high assurance boot only the
+* currently running code is validated and contains the checksum
+* for the piggy data, so we need to ensure that we are running
+* the same code in DRAM.
+*
+* The second purpose of this memcpy is for USB booting. When booting
+* from USB the image comes in as a stream, so the PBL is transferred
+* only once. As we jump into the PBL again in SDRAM we need to copy
+* it there. The USB protocol transfers data in chunks of 1024 bytes,
+* so align the copy size up to the next 1KiB boundary.
+*/
+   memcpy((void *)MX93_ATF_BL33_BASE_ADDR, __image_start, 
ALIGN(barebox_pbl_size, 1024));
+
+   get_builtin_firmware(imx93_bl31_bin, , _size);
+
+   memcpy(bl31, tfa, tfa_size);
+
+   asm volatile("msr sp_el2, %0" : :
+"r" (MX93_ATF_BL33_BASE_ADDR - 16) :
+"cc");
+   bl31();
+   __builtin_unreachable();
+}
diff --git a/include/mach/imx/atf.h b/include/mach/imx/atf.h
index 587e778635..fb367d6a70 100644
--- a/include/mach/imx/atf.h
+++ b/include/mach/imx/atf.h
@@ -17,5 +17,7 @@
 #define MX8M_ATF_BL33_BASE_ADDR0x4020
 #define MX8MM_ATF_BL33_BASE_ADDR   MX8M_ATF_BL33_BASE_ADDR
 #define MX8MQ_ATF_BL33_BASE_ADDR   MX8M_ATF_BL33_BASE_ADDR
+#define MX93_ATF_BL31_BASE_ADDR0x204e
+#define MX93_ATF_BL33_BASE_ADDR0x8020
 
 #endif
diff --git a/include/mach/imx/xload.h b/include/mach/imx/xload.h
index 11c2738c2d..2c2d2fa3c5 100644
--- a/include/mach/imx/xload.h
+++ b/include/mach/imx/xload.h
@@ -30,6 +30,7 @@ void __noreturn imx8mm_load_and_start_image_via_tfa(void);
 void __noreturn imx8mn_load_and_start_image_via_tfa(void);
 void __noreturn imx8mp_load_and_start_image_via_tfa(void);
 void __noreturn imx8mq_load_and_start_image_via_tfa(void);
+void __noreturn imx93_load_and_start_image_via_tfa(void);
 
 int imx_load_image(ptrdiff_t address, ptrdiff_t entry, u32 offset,
   u32 ivt_offset, bool start, unsigned int alignment,
-- 
2.39.2




[PATCH 24/25] ARM: Update imx_v8_defconfig

2023-11-10 Thread Sascha Hauer
Enable i.MX9 support and drivers useful on that SoC.

Signed-off-by: Sascha Hauer 
---
 arch/arm/configs/imx_v8_defconfig | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/arm/configs/imx_v8_defconfig 
b/arch/arm/configs/imx_v8_defconfig
index 8084e72ea0..731156e4fe 100644
--- a/arch/arm/configs/imx_v8_defconfig
+++ b/arch/arm/configs/imx_v8_defconfig
@@ -1,5 +1,6 @@
 CONFIG_ARCH_IMX=y
 CONFIG_MACH_INNOCOMM_WB15=y
+CONFIG_MACH_MNT_REFORM=y
 CONFIG_MACH_NXP_IMX8MM_EVK=y
 CONFIG_MACH_NXP_IMX8MN_EVK=y
 CONFIG_MACH_NXP_IMX8MP_EVK=y
@@ -12,6 +13,7 @@ CONFIG_MACH_TQ_MBA8MPXL=y
 CONFIG_MACH_VARISCITE_DT8MCUSTOMBOARD_IMX8MP=y
 CONFIG_MACH_ZII_IMX8MQ_DEV=y
 CONFIG_64BIT=y
+CONFIG_MACH_TQ_MBA9XXXCA=y
 CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
 CONFIG_MMU=y
 CONFIG_MALLOC_SIZE=0x0
@@ -93,6 +95,7 @@ CONFIG_OFDEVICE=y
 CONFIG_OF_BAREBOX_DRIVERS=y
 CONFIG_SERIAL_DEV_BUS=y
 CONFIG_DRIVER_NET_DESIGNWARE_IMX8=y
+CONFIG_DRIVER_SERIAL_LPUART32=y
 CONFIG_DRIVER_NET_FEC_IMX=y
 CONFIG_DP83867_PHY=y
 CONFIG_MICREL_PHY=y
@@ -108,6 +111,7 @@ CONFIG_DRIVER_SPI_IMX=y
 CONFIG_SPI_NXP_FLEXSPI=y
 CONFIG_I2C=y
 CONFIG_I2C_IMX=y
+CONFIG_I2C_IMX_LPI2C=y
 CONFIG_MTD=y
 CONFIG_MTD_DATAFLASH=y
 CONFIG_MTD_M25P80=y
@@ -122,6 +126,7 @@ CONFIG_MCI=y
 CONFIG_MCI_MMC_BOOT_PARTITIONS=y
 CONFIG_MCI_IMX_ESDHC=y
 CONFIG_RAVE_SP_CORE=y
+CONFIG_MFD_PCA9450=y
 CONFIG_LED=y
 CONFIG_LED_GPIO=y
 CONFIG_LED_GPIO_OF=y
@@ -129,10 +134,11 @@ CONFIG_LED_TRIGGERS=y
 CONFIG_EEPROM_AT25=y
 CONFIG_EEPROM_AT24=y
 CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_POLLER=y
 CONFIG_WATCHDOG_IMX=y
+CONFIG_WATCHDOG_IMXULP=y
 CONFIG_RAVE_SP_WATCHDOG=y
 CONFIG_GPIO_PCA953X=y
-CONFIG_IMX_OCOTP=y
 CONFIG_RAVE_SP_EEPROM=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED=y
@@ -145,7 +151,6 @@ CONFIG_FS_TFTP=y
 CONFIG_FS_NFS=y
 CONFIG_FS_FAT=y
 CONFIG_FS_FAT_WRITE=y
-CONFIG_FS_FAT_LFN=y
 CONFIG_FS_RATP=y
 CONFIG_ZLIB=y
 # CONFIG_MISSING_FIRMWARE_ERROR is not set
-- 
2.39.2




[PATCH 25/25] ARM: multi_v8_defconfig: enable i.MX9 boards

2023-11-10 Thread Sascha Hauer
Signed-off-by: Sascha Hauer 
---
 arch/arm/configs/multi_v8_defconfig | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/configs/multi_v8_defconfig 
b/arch/arm/configs/multi_v8_defconfig
index 9c538e698d..aea63b32d4 100644
--- a/arch/arm/configs/multi_v8_defconfig
+++ b/arch/arm/configs/multi_v8_defconfig
@@ -8,6 +8,7 @@ CONFIG_MACH_NXP_IMX8MM_EVK=y
 CONFIG_MACH_NXP_IMX8MN_EVK=y
 CONFIG_MACH_NXP_IMX8MP_EVK=y
 CONFIG_MACH_NXP_IMX8MQ_EVK=y
+CONFIG_MACH_PHYTEC_SOM_IMX8MM=y
 CONFIG_MACH_PHYTEC_SOM_IMX8MQ=y
 CONFIG_MACH_POLYHEX_DEBIX=y
 CONFIG_MACH_PROTONIC_IMX8M=y
@@ -15,6 +16,7 @@ CONFIG_MACH_SKOV_IMX8MP=y
 CONFIG_MACH_TQ_MBA8MPXL=y
 CONFIG_MACH_VARISCITE_DT8MCUSTOMBOARD_IMX8MP=y
 CONFIG_MACH_ZII_IMX8MQ_DEV=y
+CONFIG_MACH_TQ_MBA9XXXCA=y
 CONFIG_IMX_IIM=y
 CONFIG_MACH_RK3568_EVB=y
 CONFIG_MACH_RK3568_BPI_R2PRO=y
@@ -140,6 +142,7 @@ CONFIG_SERIAL_DEV_BUS=y
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_DRIVER_SERIAL_NS16550=y
 CONFIG_DRIVER_SERIAL_CADENCE=y
+CONFIG_DRIVER_SERIAL_LPUART32=y
 CONFIG_VIRTIO_CONSOLE=y
 CONFIG_DRIVER_NET_DESIGNWARE_IMX8=y
 CONFIG_DRIVER_NET_DESIGNWARE_ROCKCHIP=y
@@ -164,9 +167,11 @@ CONFIG_SPI_NXP_FLEXSPI=y
 CONFIG_I2C=y
 CONFIG_I2C_GPIO=y
 CONFIG_I2C_IMX=y
+CONFIG_I2C_IMX_LPI2C=y
 CONFIG_I2C_RK3X=y
 CONFIG_MTD=y
 CONFIG_MTD_CONCAT=y
+CONFIG_MTD_M25P80=y
 CONFIG_DRIVER_CFI=y
 CONFIG_CFI_BUFFER_WRITE=y
 CONFIG_VIRTIO_BLK=y
@@ -195,6 +200,7 @@ CONFIG_MCI_ARASAN=y
 CONFIG_COMMON_CLK_SCMI=y
 CONFIG_MFD_ACT8846=y
 CONFIG_RAVE_SP_CORE=y
+CONFIG_MFD_PCA9450=y
 CONFIG_MFD_RK808=y
 CONFIG_LED=y
 CONFIG_LED_GPIO=y
@@ -206,6 +212,7 @@ CONFIG_WATCHDOG=y
 CONFIG_WATCHDOG_POLLER=y
 CONFIG_WATCHDOG_DW=y
 CONFIG_WATCHDOG_IMX=y
+CONFIG_WATCHDOG_IMXULP=y
 CONFIG_RAVE_SP_WATCHDOG=y
 CONFIG_HWRNG=y
 CONFIG_HW_RANDOM_VIRTIO=y
-- 
2.39.2




[PATCH 19/25] ARM: i.MX: romapi: Implement i.MX93 support

2023-11-10 Thread Sascha Hauer
We used to use the ROM API for USB loading only, now with i.MX93 we
fully rely on the ROM API also with SD/eMMC and other boot sources.

The ROM provides us information about the boot source. There are
generally two types of boot sources: seekable for storage devices
like SD/eMMC and streamable for USB. the load_image call must be
handled slightly different for both types of boot sources, so
we fist detect which type we have and call the right load_image
function accordingly.

Signed-off-by: Sascha Hauer 
---
 arch/arm/mach-imx/romapi.c | 156 -
 include/mach/imx/romapi.h  |   1 +
 2 files changed, 153 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-imx/romapi.c b/arch/arm/mach-imx/romapi.c
index 29c2d4005c..1b1800f1e0 100644
--- a/arch/arm/mach-imx/romapi.c
+++ b/arch/arm/mach-imx/romapi.c
@@ -3,6 +3,8 @@
 #define pr_fmt(fmt) "romapi: " fmt
 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -14,7 +16,39 @@
 #include 
 #include 
 
-static int imx_romapi_load(struct rom_api *rom_api, void *adr, size_t size)
+#define BOOTROM_INFO_VERSION   0x1
+#define BOOTROM_INFO_BOOT_DEVICE   0x2
+#define BOOTROM_INFO_DEVICE_PAGE_SIZE  0x3
+#define BOOTROM_INFO_OFFSET_IVT0x4
+#define BOOTROM_INFO_BOOT_STAGE0x5
+#define BOOTROM_INFO_OFFSET_IMAGE  0x6
+
+#define BOOTROM_BOOT_DEVICE_INTERFACE  GENMASK(23, 16)
+#define BOOTROM_BOOT_DEVICE_SD 0x1
+#define BOOTROM_BOOT_DEVICE_EMMC   0x2
+#define BOOTROM_BOOT_DEVICE_FLEXSPI_NOR0x4
+#define BOOTROM_BOOT_DEVICE_LPSPI  0x6
+#define BOOTROM_BOOT_DEVICE_FLEXSPI_NAND   0x8
+#define BOOTROM_BOOT_DEVICE_USB0xe
+#define BOOTROM_BOOT_DEVICE_INSTANCE   GENMASK(15, 8)
+#define BOOTROM_BOOT_DEVICE_STATE  GENMASK(7, 0)
+
+static int imx_bootrom_query(struct rom_api *rom_api, uint32_t type, uint32_t 
*__info)
+{
+   static uint32_t info;
+   uint32_t xor = type ^ (uintptr_t)
+   int ret;
+
+   ret = rom_api->query_boot_infor(type, , xor);
+   if (ret != ROM_API_OKAY)
+   return -EIO;
+
+   *__info = info;
+
+   return 0;
+}
+
+static int imx_romapi_load_stream(struct rom_api *rom_api, void *adr, size_t 
size)
 {
while (size) {
size_t chunksize = min(size, (size_t)1024);
@@ -30,6 +64,22 @@ static int imx_romapi_load(struct rom_api *rom_api, void 
*adr, size_t size)
adr += chunksize;
size -= chunksize;
}
+   return 0;
+}
+
+static int imx_romapi_load_seekable(struct rom_api *rom_api, void *adr, 
uint32_t offset,
+  size_t size)
+{
+   int ret;
+
+   size = PAGE_ALIGN(size);
+
+   ret = rom_api->download_image(adr, offset, size,
+ (uintptr_t)adr ^ offset ^ size);
+   if (ret != ROM_API_OKAY) {
+   pr_err("Failed to load piggy data (ret = %x)\n", ret);
+   return -EIO;
+   }
 
return 0;
 }
@@ -37,9 +87,9 @@ static int imx_romapi_load(struct rom_api *rom_api, void 
*adr, size_t size)
 /* read piggydata via a bootrom callback and place it behind our copy in SDRAM 
*/
 static int imx_romapi_load_image(struct rom_api *rom_api)
 {
-   return imx_romapi_load(rom_api,
- (void *)MX8M_ATF_BL33_BASE_ADDR + 
barebox_pbl_size,
- __image_end - __piggydata_start);
+   return imx_romapi_load_stream(rom_api,
+   (void *)MX8M_ATF_BL33_BASE_ADDR,
+   __image_end - __piggydata_start);
 }
 
 int imx8mp_romapi_load_image(void)
@@ -56,6 +106,104 @@ int imx8mn_romapi_load_image(void)
return imx8mp_romapi_load_image();
 }
 
+static int imx_romapi_boot_device_seekable(struct rom_api *rom_api)
+{
+   uint32_t boot_device, boot_device_type, boot_device_state;
+   int ret;
+   bool seekable;
+
+   ret = imx_bootrom_query(rom_api, BOOTROM_INFO_BOOT_DEVICE, 
_device);
+   if (ret)
+   return ret;
+
+   boot_device_type = FIELD_GET(BOOTROM_BOOT_DEVICE_INTERFACE, 
boot_device);
+
+   switch (boot_device_type) {
+   case BOOTROM_BOOT_DEVICE_SD:
+   case BOOTROM_BOOT_DEVICE_FLEXSPI_NOR:
+   case BOOTROM_BOOT_DEVICE_LPSPI:
+   case BOOTROM_BOOT_DEVICE_FLEXSPI_NAND:
+   seekable = true;
+   break;
+   case BOOTROM_BOOT_DEVICE_USB:
+   seekable = false;
+   break;
+   case BOOTROM_BOOT_DEVICE_EMMC:
+   boot_device_state = FIELD_GET(BOOTROM_BOOT_DEVICE_STATE, 
boot_device);
+   if (boot_device_state & BIT(0))
+   seekable = false;
+   else
+   seekable = true;
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   return seekable;
+}
+
+int imx93_romapi_load_image(void)

[PATCH 06/25] clk: Add i.MX93 clock support

2023-11-10 Thread Sascha Hauer
Based on Linux i.MX93 clock support as of Linux-6.6

Signed-off-by: Sascha Hauer 
---
 drivers/clk/imx/Makefile   |   1 +
 drivers/clk/imx/clk-composite-93.c | 216 
 drivers/clk/imx/clk-fracn-gppll.c  | 392 +
 drivers/clk/imx/clk-gate-93.c  | 186 ++
 drivers/clk/imx/clk-imx93.c| 331 
 drivers/clk/imx/clk.h  |  42 
 6 files changed, 1168 insertions(+)
 create mode 100644 drivers/clk/imx/clk-composite-93.c
 create mode 100644 drivers/clk/imx/clk-fracn-gppll.c
 create mode 100644 drivers/clk/imx/clk-gate-93.c
 create mode 100644 drivers/clk/imx/clk-imx93.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 4a792422d5..eb9f8334c3 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -34,4 +34,5 @@ obj-$(CONFIG_ARCH_IMX8MM) += clk-imx8mm.o
 obj-$(CONFIG_ARCH_IMX8MN) += clk-imx8mn.o
 obj-$(CONFIG_ARCH_IMX8MP) += clk-imx8mp.o
 obj-$(CONFIG_ARCH_IMX8MQ) += clk-imx8mq.o
+obj-$(CONFIG_ARCH_IMX93) += clk-imx93.o clk-composite-93.o clk-gate-93.o 
clk-fracn-gppll.o
 obj-$(CONFIG_ARCH_VF610)  += clk-vf610.o
diff --git a/drivers/clk/imx/clk-composite-93.c 
b/drivers/clk/imx/clk-composite-93.c
new file mode 100644
index 00..2b3753d569
--- /dev/null
+++ b/drivers/clk/imx/clk-composite-93.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 NXP
+ *
+ * Peng Fan 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+#define TIMEOUT_US 500U
+
+#define CCM_DIV_SHIFT  0
+#define CCM_DIV_WIDTH  8
+#define CCM_MUX_SHIFT  8
+#define CCM_MUX_MASK   3
+#define CCM_OFF_SHIFT  24
+#define CCM_BUSY_SHIFT 28
+
+#define STAT_OFFSET0x4
+#define AUTHEN_OFFSET  0x30
+#define TZ_NS_SHIFT9
+#define TZ_NS_MASK BIT(9)
+
+#define WHITE_LIST_SHIFT   16
+
+static int imx93_clk_composite_wait_ready(struct clk_hw *hw, void __iomem *reg)
+{
+   int ret;
+   u32 val;
+
+   ret = readl_poll_timeout(reg + STAT_OFFSET, val, !(val & 
BIT(CCM_BUSY_SHIFT)),
+TIMEOUT_US);
+   if (ret)
+   pr_err("Slice[%s] busy timeout\n", clk_hw_get_name(hw));
+
+   return ret;
+}
+
+static void imx93_clk_composite_gate_endisable(struct clk_hw *hw, int enable)
+{
+   struct clk_gate *gate = to_clk_gate(hw);
+   u32 reg;
+
+   reg = readl(gate->reg);
+
+   if (enable)
+   reg &= ~BIT(gate->shift);
+   else
+   reg |= BIT(gate->shift);
+
+   writel(reg, gate->reg);
+
+   imx93_clk_composite_wait_ready(hw, gate->reg);
+}
+
+static int imx93_clk_composite_gate_enable(struct clk_hw *hw)
+{
+   imx93_clk_composite_gate_endisable(hw, 1);
+
+   return 0;
+}
+
+static void imx93_clk_composite_gate_disable(struct clk_hw *hw)
+{
+   imx93_clk_composite_gate_endisable(hw, 0);
+}
+
+static const struct clk_ops imx93_clk_composite_gate_ops = {
+   .enable = imx93_clk_composite_gate_enable,
+   .disable = imx93_clk_composite_gate_disable,
+   .is_enabled = clk_gate_is_enabled,
+};
+
+static unsigned long
+imx93_clk_composite_divider_recalc_rate(struct clk_hw *hw, unsigned long 
parent_rate)
+{
+   return clk_divider_ops.recalc_rate(hw, parent_rate);
+}
+
+static long
+imx93_clk_composite_divider_round_rate(struct clk_hw *hw, unsigned long rate, 
unsigned long *prate)
+{
+   return clk_divider_ops.round_rate(hw, rate, prate);
+}
+
+static int imx93_clk_composite_divider_set_rate(struct clk_hw *hw, unsigned 
long rate,
+   unsigned long parent_rate)
+{
+   struct clk_divider *divider = to_clk_divider(hw);
+   int value;
+   u32 val;
+   int ret;
+
+   value = divider_get_val(rate, parent_rate, divider->table, 
divider->width, divider->flags);
+   if (value < 0)
+   return value;
+
+   val = readl(divider->reg);
+   val &= ~(clk_div_mask(divider->width) << divider->shift);
+   val |= (u32)value << divider->shift;
+   writel(val, divider->reg);
+
+   ret = imx93_clk_composite_wait_ready(hw, divider->reg);
+
+   return ret;
+}
+
+static const struct clk_ops imx93_clk_composite_divider_ops = {
+   .recalc_rate = imx93_clk_composite_divider_recalc_rate,
+   .round_rate = imx93_clk_composite_divider_round_rate,
+   .set_rate = imx93_clk_composite_divider_set_rate,
+};
+
+static int imx93_clk_composite_mux_get_parent(struct clk_hw *hw)
+{
+   return clk_mux_ops.get_parent(hw);
+}
+
+static int imx93_clk_composite_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+   struct clk_mux *mux = to_clk_mux(hw);
+   u32 val = clk_mux_index_to_val(mux->table, mux->flags, index);
+   u32 reg;
+   int ret;
+
+   reg = readl(mux->reg);
+   reg &= ~(((1 << mux->width) - 1) << mux->shift);
+   val = val << mux->shift;
+   reg |= val;
+   writel(reg, mux->reg);
+
+ 

[PATCH 17/25] ARM: i.MX93: Add DDR size read support

2023-11-10 Thread Sascha Hauer
Signed-off-by: Sascha Hauer 
---
 arch/arm/mach-imx/esdctl.c | 42 ++
 1 file changed, 42 insertions(+)

diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index 2fca0a44a1..ac35a2de66 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct imx_esdctl_data {
unsigned long base0;
@@ -555,6 +556,39 @@ static int imx8mn_ddrc_add_mem(void *mmdcbase, struct 
imx_esdctl_data *data)
return _imx8m_ddrc_add_mem(mmdcbase, data, 16);
 }
 
+#define IMX9_DDRC_CS_CONFIG(n) (0x80 + (n) * 4)
+#define IMX9_DDRC_CS_ROW_BITS  GENMASK(10, 8)
+#define IMX9_DDRC_CS_COL_BITS  GENMASK(2, 0)
+#define IMX9_DDRC_CS_ENBIT(31)
+
+static int imx9_ddrc_add_mem(void *mmdcbase, struct imx_esdctl_data *data)
+{
+   int width = 2;
+   int banks = 8;
+   unsigned long mem = 0;
+   int i;
+
+   for (i = 0; i < 2; i++) {
+   int rows, cols;
+   u32 cs, col_bits;
+
+   cs = readl(mmdcbase + IMX9_DDRC_CS_CONFIG(i));
+   if (!(cs & IMX9_DDRC_CS_EN))
+   continue;
+
+   rows = FIELD_GET(IMX9_DDRC_CS_ROW_BITS, cs) + 12;
+   col_bits = FIELD_GET(IMX9_DDRC_CS_COL_BITS, cs);
+   if (col_bits == 7)
+   cols = 7;
+   else
+   cols = col_bits + 8;
+
+   mem += memory_sdram_size(cols, rows, banks, width);
+   }
+
+   return arm_add_mem_device("ram0", data->base0, mem);
+}
+
 static resource_size_t imx7d_ddrc_sdram_size(void __iomem *ddrc)
 {
const u32 addrmap[DDRC_ADDRMAP_LENGTH] = {
@@ -695,6 +729,11 @@ static __maybe_unused struct imx_esdctl_data imx8mn_data = 
{
.add_mem = imx8mn_ddrc_add_mem,
 };
 
+static __maybe_unused struct imx_esdctl_data imx9_data = {
+   .base0 = MX9_DDR_CSD1_BASE_ADDR,
+   .add_mem = imx9_ddrc_add_mem,
+};
+
 static __maybe_unused struct imx_esdctl_data imx7d_data = {
.base0 = MX7_DDR_BASE_ADDR,
.add_mem = imx7d_ddrc_add_mem,
@@ -770,6 +809,9 @@ static __maybe_unused struct of_device_id 
imx_esdctl_dt_ids[] = {
}, {
.compatible = "fsl,imx8mn-ddrc",
.data = _data
+   }, {
+   .compatible = "fsl,imx93-ddrc",
+   .data = _data
}, {
.compatible = "fsl,imx7d-ddrc",
.data = _data
-- 
2.39.2




[PATCH 09/25] iomux: Add i.MX93 support

2023-11-10 Thread Sascha Hauer
Signed-off-by: Sascha Hauer 
---
 drivers/pinctrl/imx-iomux-v3.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/pinctrl/imx-iomux-v3.c b/drivers/pinctrl/imx-iomux-v3.c
index 5dbb745b13..673674c1dc 100644
--- a/drivers/pinctrl/imx-iomux-v3.c
+++ b/drivers/pinctrl/imx-iomux-v3.c
@@ -246,6 +246,8 @@ static __maybe_unused struct of_device_id 
imx_iomux_v3_dt_ids[] = {
.compatible = "fsl,imx8mp-iomuxc",
}, {
.compatible = "fsl,imx8mq-iomuxc",
+   }, {
+   .compatible = "fsl,imx93-iomuxc",
}, {
/* sentinel */
}
-- 
2.39.2




[PATCH 01/25] ARM: initial i.MX9 support

2023-11-10 Thread Sascha Hauer
Signed-off-by: Sascha Hauer 
---
 arch/arm/mach-imx/Kconfig| 17 +++
 arch/arm/mach-imx/Makefile   |  5 ++--
 arch/arm/mach-imx/cpu_init.c | 42 
 arch/arm/mach-imx/imx-bbu-internal.c |  5 
 firmware/Kconfig |  3 ++
 firmware/Makefile|  1 +
 include/mach/imx/bbu.h   |  9 ++
 include/mach/imx/generic.h   |  1 +
 include/mach/imx/imx9-regs.h | 24 
 9 files changed, 105 insertions(+), 2 deletions(-)
 create mode 100644 include/mach/imx/imx9-regs.h

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 6a7d90e2c8..358d1ef362 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -31,6 +31,14 @@ config RESET_IMX_SRC
def_bool y
depends on ARCH_IMX6 || ARCH_IMX50 || ARCH_IMX51 || ARCH_IMX53
 
+config ARCH_IMX_ATF
+   def_bool y
+   depends on ARCH_IMX8M || ARCH_IMX93
+
+config ARCH_IMX_ROMAPI
+   def_bool y
+   depends on ARCH_IMX8M || ARCH_IMX93
+
 #
 # PMIC configuration found on i.MX51 Babbadge board
 #
@@ -164,6 +172,15 @@ config ARCH_IMX8MQ
select ARCH_IMX8M
bool
 
+config ARCH_IMX93
+   bool
+   select CPU_V8
+   select PINCTRL_IMX_IOMUX_V3
+   select OFTREE
+   select COMMON_CLK_OF_PROVIDER
+   select ARM_USE_COMPRESSED_DTB
+   select ARCH_HAS_FEC_IMX
+
 config ARCH_VF610
bool
select ARCH_HAS_L2X0
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index f49bbea2b4..7b093ba7fd 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -18,8 +18,9 @@ lwl-$(CONFIG_ARCH_IMX6) += imx6-mmdc.o
 obj-$(CONFIG_ARCH_IMX7) += imx7.o
 obj-$(CONFIG_ARCH_VF610) += vf610.o
 obj-pbl-$(CONFIG_ARCH_IMX8M) += imx8m.o
-lwl-$(CONFIG_ARCH_IMX8M) += atf.o
-obj-pbl-$(CONFIG_ARCH_IMX8M) += romapi.o tzasc.o
+lwl-$(CONFIG_ARCH_IMX_ATF) += atf.o
+obj-pbl-$(CONFIG_ARCH_IMX8M) += tzasc.o
+obj-pbl-$(CONFIG_ARCH_IMX_ROMAPI) += romapi.o
 obj-$(CONFIG_IMX_IIM)  += iim.o
 obj-$(CONFIG_NAND_IMX) += nand.o
 lwl-$(CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND) += external-nand-boot.o
diff --git a/arch/arm/mach-imx/cpu_init.c b/arch/arm/mach-imx/cpu_init.c
index 4e55d72857..b20172076e 100644
--- a/arch/arm/mach-imx/cpu_init.c
+++ b/arch/arm/mach-imx/cpu_init.c
@@ -10,6 +10,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -85,4 +87,44 @@ void imx8mq_cpu_lowlevel_init(void)
 {
imx8m_cpu_lowlevel_init();
 }
+
+#define CCM_AUTHEN_TZ_NS   BIT(9)
+
+#define OSCPLLa_AUTHEN(n)  (0x5030  + (n) * 0x40) /* 0..18 */
+#define CLOCK_ROOT_AUTHEN(n)   (0x30  + (n) * 0x80) /* 0..94 */
+#define LPCGa_AUTHEN(n)(0x8030 + (n) * 0x40) /* 0..126 
*/
+#define GPR_SHARED0_AUTHEN(n)  (0x4810 + (n) * 0x10) /* 0..3 */
+#define SET 4
+
+#define SRC_SP_ISO_CTRL0x10c
+
+void imx93_cpu_lowlevel_init(void)
+{
+   void __iomem *ccm = IOMEM(MX9_CCM_BASE_ADDR);
+   void __iomem *src = IOMEM(MX9_SRC_BASE_ADDR);
+   int i;
+
+   arm_cpu_lowlevel_init();
+
+   if (current_el() != 3)
+   return;
+
+   imx9_trdc_init();
+
+   imx_cpu_timer_init(IOMEM(MX9_SYSCNT_CTRL_BASE_ADDR));
+
+   for (i = 0; i <= 18; i++)
+   writel(CCM_AUTHEN_TZ_NS, ccm + OSCPLLa_AUTHEN(i) + SET);
+   for (i = 0; i <= 94; i++)
+   writel(CCM_AUTHEN_TZ_NS, ccm + CLOCK_ROOT_AUTHEN(i) + SET);
+   for (i = 0; i <= 126 ; i++)
+   writel(CCM_AUTHEN_TZ_NS, ccm + LPCGa_AUTHEN(i) + SET);
+   for (i = 0; i <= 3 ; i++)
+   writel(CCM_AUTHEN_TZ_NS, ccm + GPR_SHARED0_AUTHEN(i) + SET);
+
+   /* clear isolation for usbphy, dsi, csi*/
+   writel(0x0, src + SRC_SP_ISO_CTRL);
+
+}
+
 #endif
diff --git a/arch/arm/mach-imx/imx-bbu-internal.c 
b/arch/arm/mach-imx/imx-bbu-internal.c
index 8cdaab5c16..e26317e8bf 100644
--- a/arch/arm/mach-imx/imx-bbu-internal.c
+++ b/arch/arm/mach-imx/imx-bbu-internal.c
@@ -617,6 +617,11 @@ int imx8m_bbu_internal_mmcboot_register_handler(const char 
*name,
 unsigned long flags)
__alias(imx_bbu_internal_mmcboot_register_handler);
 
+int imx9_bbu_internal_mmcboot_register_handler(const char *name,
+const char *devicefile,
+unsigned long flags)
+   __alias(imx_bbu_internal_mmcboot_register_handler);
+
 /*
  * Register an i.MX53 internal boot update handler for i2c/spi
  * EEPROMs / flashes. Nearly the same as MMC/SD, but we do not need to
diff --git a/firmware/Kconfig b/firmware/Kconfig
index 3328dbc0b1..38fbf8 100644
--- a/firmware/Kconfig
+++ b/firmware/Kconfig
@@ -38,6 +38,9 @@ config FIRMWARE_IMX8MP_ATF
 config FIRMWARE_IMX8MQ_ATF
bool
 
+config FIRMWARE_IMX93_ATF
+   bool
+
 config 

[PATCH 15/25] ARM: i.MX: add i.MX9 debug_ll support

2023-11-10 Thread Sascha Hauer
This adds support for debug_ll output on i.MX9 SoCs.

Signed-off-by: Sascha Hauer 
---
 common/Kconfig  |  5 +
 include/mach/imx/debug_ll.h | 13 +
 include/serial/lpuart32.h   | 10 ++
 3 files changed, 28 insertions(+)

diff --git a/common/Kconfig b/common/Kconfig
index 15c648de5d..792f93d381 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1365,6 +1365,10 @@ config DEBUG_IMX8M_UART
  Say Y here if you want barebox low-level debugging support
  on i.MX8M*.
 
+config DEBUG_IMX9_UART
+   bool "i.MX9 Debug UART"
+   select DEBUG_IMX_UART
+
 config DEBUG_VEXPRESS_UART
bool "Vexpress Debug UART"
depends on ARCH_VEXPRESS
@@ -1571,6 +1575,7 @@ config DEBUG_IMX_UART_PORT
DEBUG_IMX6Q_UART || \
DEBUG_IMX7D_UART || \
DEBUG_IMX8M_UART || \
+   DEBUG_IMX9_UART || \
DEBUG_VF610_UART
default 1
depends on ARCH_IMX
diff --git a/include/mach/imx/debug_ll.h b/include/mach/imx/debug_ll.h
index d25631d116..618cbc784e 100644
--- a/include/mach/imx/debug_ll.h
+++ b/include/mach/imx/debug_ll.h
@@ -18,10 +18,12 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
 #include 
+#include 
 
 #ifdef CONFIG_DEBUG_IMX_UART
 
@@ -54,6 +56,8 @@
 #define IMX_DEBUG_SOC MX8M
 #elif defined CONFIG_DEBUG_VF610_UART
 #define IMX_DEBUG_SOC VF610
+#elif defined CONFIG_DEBUG_IMX9_UART
+#define IMX_DEBUG_SOC MX9
 #else
 #error "unknown i.MX debug uart soc type"
 #endif
@@ -107,6 +111,13 @@ static inline void imx8m_uart_setup_ll(void)
imx8m_uart_setup(base);
 }
 
+static inline void imx9_uart_setup_ll(void)
+{
+   void *base = IOMEM(IMX_UART_BASE(IMX_DEBUG_SOC,
+CONFIG_DEBUG_IMX_UART_PORT));
+   lpuart32_setup(base + 0x10, 2400);
+}
+
 static inline void PUTC_LL(int c)
 {
void __iomem *base = IOMEM(IMX_UART_BASE(IMX_DEBUG_SOC,
@@ -117,6 +128,8 @@ static inline void PUTC_LL(int c)
 
if (IS_ENABLED(CONFIG_DEBUG_VF610_UART))
lpuart_putc(base, c);
+   else if (IS_ENABLED(CONFIG_DEBUG_IMX9_UART))
+   lpuart32_putc(base + 0x10, c);
else
imx_uart_putc(base, c);
 }
diff --git a/include/serial/lpuart32.h b/include/serial/lpuart32.h
index bcfd067113..12526ee0ae 100644
--- a/include/serial/lpuart32.h
+++ b/include/serial/lpuart32.h
@@ -155,4 +155,14 @@ static inline void lpuart32_putc(void __iomem *base, int c)
writel(c, base + LPUART32_UARTDATA);
 }
 
+static inline void imx9_uart_setup(void __iomem *uartbase)
+{
+   /*
+* On i.MX9 the registers start at offset 0x10
+*/
+   BUG_ON((unsigned long)uartbase & 0x10);
+
+   lpuart32_setup(uartbase + 0x10, 2400);
+}
+
 #endif
-- 
2.39.2




[PATCH 03/25] ARM: i.MX: Add i.MX93 trdc support

2023-11-10 Thread Sascha Hauer
Signed-off-by: Sascha Hauer 
---
 arch/arm/mach-imx/Makefile |   2 +-
 arch/arm/mach-imx/imx93-trdc.c | 364 +
 include/soc/imx9/trdc.h|  11 +
 3 files changed, 376 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/imx93-trdc.c
 create mode 100644 include/soc/imx9/trdc.h

diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 4efac08ee8..8a1ccabe15 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -33,4 +33,4 @@ obj-$(CONFIG_RESET_IMX_SRC) += src.o
 lwl-y += cpu_init.o
 pbl-y += xload-spi.o xload-common.o xload-imx-nand.o xload-gpmi-nand.o
 pbl-y += xload-qspi.o
-pbl-$(CONFIG_ARCH_IMX93) += imx93-s4mu.o
+pbl-$(CONFIG_ARCH_IMX93) += imx93-s4mu.o imx93-trdc.o
diff --git a/arch/arm/mach-imx/imx93-trdc.c b/arch/arm/mach-imx/imx93-trdc.c
new file mode 100644
index 00..a1c7d49515
--- /dev/null
+++ b/arch/arm/mach-imx/imx93-trdc.c
@@ -0,0 +1,364 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2022 NXP
+ */
+#define pr_fmt(fmt) "trdc: " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DID_NUM 16
+#define MBC_MAX_NUM 4
+#define MRC_MAX_NUM 2
+#define MBC_NUM(HWCFG) ((HWCFG >> 16) & 0xF)
+#define MRC_NUM(HWCFG) ((HWCFG >> 24) & 0x1F)
+
+struct mbc_mem_dom {
+   u32 mem_glbcfg[4];
+   u32 nse_blk_index;
+   u32 nse_blk_set;
+   u32 nse_blk_clr;
+   u32 nsr_blk_clr_all;
+   u32 memn_glbac[8];
+   /* The upper only existed in the beginning of each MBC */
+   u32 mem0_blk_cfg_w[64];
+   u32 mem0_blk_nse_w[16];
+   u32 mem1_blk_cfg_w[8];
+   u32 mem1_blk_nse_w[2];
+   u32 mem2_blk_cfg_w[8];
+   u32 mem2_blk_nse_w[2];
+   u32 mem3_blk_cfg_w[8];
+   u32 mem3_blk_nse_w[2];/*0x1F0, 0x1F4 */
+   u32 reserved[2];
+};
+
+struct mrc_rgn_dom {
+   u32 mrc_glbcfg[4];
+   u32 nse_rgn_indirect;
+   u32 nse_rgn_set;
+   u32 nse_rgn_clr;
+   u32 nse_rgn_clr_all;
+   u32 memn_glbac[8];
+   /* The upper only existed in the beginning of each MRC */
+   u32 rgn_desc_words[16][2]; /* 16  regions at max, 2 words per region */
+   u32 rgn_nse;
+   u32 reserved2[15];
+};
+
+struct mda_inst {
+   u32 mda_w[8];
+};
+
+struct trdc_mgr {
+   u32 trdc_cr;
+   u32 res0[59];
+   u32 trdc_hwcfg0;
+   u32 trdc_hwcfg1;
+   u32 res1[450];
+   struct mda_inst mda[8];
+   u32 res2[15808];
+};
+
+struct trdc_mbc {
+   struct mbc_mem_dom mem_dom[DID_NUM];
+};
+
+struct trdc_mrc {
+   struct mrc_rgn_dom mrc_dom[DID_NUM];
+};
+
+static void *trdc_get_mbc_base(ulong trdc_reg, u32 mbc_x)
+{
+   struct trdc_mgr *trdc_base = (struct trdc_mgr *)trdc_reg;
+   u32 mbc_num = MBC_NUM(trdc_base->trdc_hwcfg0);
+
+   if (mbc_x >= mbc_num)
+   return 0;
+
+   return (void *)trdc_reg + 0x1 + 0x2000 * mbc_x;
+}
+
+static void *trdc_get_mrc_base(ulong trdc_reg, u32 mrc_x)
+{
+   struct trdc_mgr *trdc_base = (struct trdc_mgr *)trdc_reg;
+   u32 mbc_num = MBC_NUM(trdc_base->trdc_hwcfg0);
+   u32 mrc_num = MRC_NUM(trdc_base->trdc_hwcfg0);
+
+   if (mrc_x >= mrc_num)
+   return 0;
+
+   return (void *)trdc_reg + 0x1 + 0x2000 * mbc_num + 0x1000 * mrc_x;
+}
+
+static int trdc_mbc_set_control(ulong trdc_reg, u32 mbc_x, u32 glbac_id,
+u32 glbac_val)
+{
+   struct trdc_mbc *mbc_base = trdc_get_mbc_base(trdc_reg, mbc_x);
+   struct mbc_mem_dom *mbc_dom;
+
+   if (mbc_base == 0 || glbac_id >= 8)
+   return -EINVAL;
+
+   /* only first dom has the glbac */
+   mbc_dom = _base->mem_dom[0];
+
+   writel(glbac_val, _dom->memn_glbac[glbac_id]);
+
+   return 0;
+}
+
+static int trdc_mbc_blk_config(ulong trdc_reg, u32 mbc_x, u32 dom_x, u32 mem_x,
+   u32 blk_x, bool sec_access, u32 glbac_id)
+{
+   struct trdc_mbc *mbc_base = trdc_get_mbc_base(trdc_reg, mbc_x);
+   struct mbc_mem_dom *mbc_dom;
+   u32 *cfg_w, *nse_w;
+   u32 index, offset, val;
+
+   if (mbc_base == 0 || glbac_id >= 8)
+   return -EINVAL;
+
+   mbc_dom = _base->mem_dom[dom_x];
+
+   switch (mem_x) {
+   case 0:
+   cfg_w = _dom->mem0_blk_cfg_w[blk_x / 8];
+   nse_w = _dom->mem0_blk_nse_w[blk_x / 32];
+   break;
+   case 1:
+   cfg_w = _dom->mem1_blk_cfg_w[blk_x / 8];
+   nse_w = _dom->mem1_blk_nse_w[blk_x / 32];
+   break;
+   case 2:
+   cfg_w = _dom->mem2_blk_cfg_w[blk_x / 8];
+   nse_w = _dom->mem2_blk_nse_w[blk_x / 32];
+   break;
+   case 3:
+   cfg_w = _dom->mem3_blk_cfg_w[blk_x / 8];
+   nse_w = _dom->mem3_blk_nse_w[blk_x / 32];
+   break;
+   default:
+   return -EINVAL;
+   };
+
+   index = blk_x % 8;
+   offset = index * 4;
+
+   val = 

[PATCH 08/25] gpio-vf610: Add i.MX93 support

2023-11-10 Thread Sascha Hauer
Signed-off-by: Sascha Hauer 
---
 drivers/gpio/Kconfig  |  3 +-
 drivers/gpio/gpio-vf610.c | 78 ---
 2 files changed, 75 insertions(+), 6 deletions(-)

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index e19f5a5aba..6f9ba2aad2 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -63,7 +63,8 @@ config GPIO_IMX
 
 config GPIO_VF610
bool "VF610 GPIO controller" if COMPILE_TEST
-   default y if ARCH_VF610
+   depends on ARCH_IMX || ARCH_VF610 || COMPILE_TEST
+   default y if ARCH_VF610 || ARCH_IMX93
 
 config GPIO_MXS
bool "MXS GPIO controller" if COMPILE_TEST
diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
index 43b2a18496..486463a2d2 100644
--- a/drivers/gpio/gpio-vf610.c
+++ b/drivers/gpio/gpio-vf610.c
@@ -21,6 +21,8 @@ struct vf610_gpio_port {
struct gpio_chip chip;
void __iomem *gpio_base;
unsigned int pinctrl_base;
+   bool have_paddr;
+   bool need_pinctrl;
 };
 
 #define GPIO_PDOR  0x00
@@ -28,9 +30,25 @@ struct vf610_gpio_port {
 #define GPIO_PCOR  0x08
 #define GPIO_PTOR  0x0c
 #define GPIO_PDIR  0x10
+#define GPIO_PDDR  0x14
+
+struct fsl_gpio_soc_data {
+   /* SoCs has a Port Data Direction Register (PDDR) */
+   bool have_paddr;
+   bool need_pinctrl;
+};
+
+static const struct fsl_gpio_soc_data vf610_data = {
+   .need_pinctrl = true,
+};
+
+static const struct fsl_gpio_soc_data imx_data = {
+   .have_paddr = true,
+};
 
 static const struct of_device_id vf610_gpio_dt_ids[] = {
-   { .compatible = "fsl,vf610-gpio" },
+   { .compatible = "fsl,vf610-gpio", .data = _data, },
+   { .compatible = "fsl,imx7ulp-gpio", .data = _data, },
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, vf610_gpio_dt_ids);
@@ -40,8 +58,16 @@ static int vf610_gpio_get_value(struct gpio_chip *chip, 
unsigned int gpio)
 {
struct vf610_gpio_port *port =
container_of(chip, struct vf610_gpio_port, chip);
+   unsigned long mask = BIT(gpio);
+   unsigned long offset = GPIO_PDIR;
+
+   if (port->have_paddr) {
+   mask &= readl(port->gpio_base + GPIO_PDDR);
+   if (mask)
+   offset = GPIO_PDOR;
+   }
 
-   return !!(readl(port->gpio_base + GPIO_PDIR) & BIT(gpio));
+   return !!(readl(port->gpio_base + offset) & BIT(gpio));
 }
 
 static void vf610_gpio_set_value(struct gpio_chip *chip,
@@ -58,8 +84,19 @@ static int vf610_gpio_direction_input(struct gpio_chip 
*chip, unsigned gpio)
 {
struct vf610_gpio_port *port =
container_of(chip, struct vf610_gpio_port, chip);
+   unsigned long mask = BIT(gpio);
+   u32 val;
 
-   return pinctrl_gpio_direction_input(port->pinctrl_base + gpio);
+   if (port->have_paddr) {
+   val = readl(port->gpio_base + GPIO_PDDR);
+   val &= ~mask;
+   writel(val, port->gpio_base + GPIO_PDDR);
+   }
+
+   if (port->need_pinctrl)
+   return pinctrl_gpio_direction_input(port->pinctrl_base + gpio);
+
+   return 0;
 }
 
 static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
@@ -67,18 +104,41 @@ static int vf610_gpio_direction_output(struct gpio_chip 
*chip, unsigned gpio,
 {
struct vf610_gpio_port *port =
container_of(chip, struct vf610_gpio_port, chip);
+   unsigned long mask = BIT(gpio);
+   u32 val;
 
vf610_gpio_set_value(chip, gpio, value);
 
-   return pinctrl_gpio_direction_output(port->pinctrl_base + gpio);
+   if (port->have_paddr) {
+   val = readl(port->gpio_base + GPIO_PDDR);
+   val |= mask;
+   writel(val, port->gpio_base + GPIO_PDDR);
+   }
+
+   if (port->need_pinctrl)
+   return pinctrl_gpio_direction_output(port->pinctrl_base + gpio);
+
+   return 0;
 }
 
 static int vf610_gpio_get_direction(struct gpio_chip *chip, unsigned gpio)
 {
struct vf610_gpio_port *port =
container_of(chip, struct vf610_gpio_port, chip);
+   u32 val;
+
+   if (port->have_paddr) {
+   val = readl(port->gpio_base + GPIO_PDDR);
+   if (val & BIT(gpio))
+   return GPIOF_DIR_OUT;
+   else
+   return GPIOF_DIR_IN;
+   }
+
+   if (port->need_pinctrl)
+   return pinctrl_gpio_get_direction(port->pinctrl_base + gpio);
 
-   return pinctrl_gpio_get_direction(port->pinctrl_base + gpio);
+   return 0;
 }
 
 static struct gpio_ops vf610_gpio_ops = {
@@ -95,6 +155,11 @@ static int vf610_gpio_probe(struct device *dev)
struct resource *iores;
struct vf610_gpio_port *port;
const __be32 *gpio_ranges;
+   struct fsl_gpio_soc_data *devtype;
+
+   ret = dev_get_drvdata(dev, (const void **));
+   if (ret)
+   

[PATCH 05/25] scripts: imx9image: Add PBL size option

2023-11-10 Thread Sascha Hauer
The i.MX9 ROM can only load images that fit into OCRAM. The barebox
image is usually bigger. This adds a -pblsize option that has the
effect that it sets the image size in the header to the provided pbl
size, so that the ROM only partially loads the image. barebox will
then use the ROMAPI to load the rest of the image.

We also add an additional alignment of 1KiB to the pblsize. This
helps us with USB booting, as the USB protocol uploads in chunks of
1KiB.

Signed-off-by: Sascha Hauer 
---
 scripts/imx9image.c | 26 +-
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/scripts/imx9image.c b/scripts/imx9image.c
index a991ba5f35..53fb879882 100644
--- a/scripts/imx9image.c
+++ b/scripts/imx9image.c
@@ -346,7 +346,7 @@ static void set_imx_hdr_v3(struct imx_header_v3 *imxhdr, 
uint32_t dcd_len,
fhdr_v3->version = IVT_VERSION_B0;
 }
 
-static void set_image_hash(struct boot_img *img, char *filename, uint32_t 
hash_type)
+static void set_image_hash(struct boot_img *img, char *filename, uint32_t 
hash_type, int size)
 {
FILE *fp = NULL;
char sha_command[512];
@@ -383,13 +383,11 @@ static void set_image_hash(struct boot_img *img, char 
*filename, uint32_t hash_t
break;
}
 
-   if (img->size == 0 || !filename)
+   if (!size || !filename)
sprintf(sha_command, "%s /dev/null", digest_type);
else
-   sprintf(sha_command, "dd status=none if=/dev/zero of=tmp_pad 
bs=%d count=1;\
-   dd status=none if=\'%s\' of=tmp_pad 
conv=notrunc;\
-   %s tmp_pad; rm -f tmp_pad",
-   img->size, filename, digest_type);
+   sprintf(sha_command, "cat \'%s\' /dev/zero | dd status=none 
bs=1 count=%d | %s",
+   filename, size, digest_type);
 
memset(img->hash, 0, HASH_MAX_LEN);
 
@@ -562,7 +560,7 @@ static void set_image_array_entry(struct flash_header_v3 
*container, soc_type_t
img->offset = offset;  /* Is re-adjusted later */
img->size = size;
 
-   set_image_hash(img, tmp_filename, get_hash_algo(images_hash));
+   set_image_hash(img, tmp_filename, get_hash_algo(images_hash), size);
 
switch (type) {
case SECO:
@@ -678,7 +676,7 @@ static void set_image_array_entry(struct flash_header_v3 
*container, soc_type_t
img = >img[container->num_images];
img->hab_flags |= IMG_TYPE_DCD_DDR;
img->hab_flags |= CORE_SC << BOOT_IMG_FLAGS_CORE_SHIFT;
-   set_image_hash(img, "/dev/null", 
IMAGE_HASH_ALGO_DEFAULT);
+   set_image_hash(img, "/dev/null", 
IMAGE_HASH_ALGO_DEFAULT, 0);
img->offset = offset + img->size;
img->entry = read_dcd_offset(tmp_filename);
img->dst = img->entry - 1;
@@ -871,6 +869,8 @@ static void copy_file(int ifd, const char *datafile, int 
pad, int offset)
(void) close (dfd);
 }
 
+static int pblsize;
+
 static int build_container_qx_qm_b0(soc_type_t soc, uint32_t sector_size, 
uint32_t ivt_offset,
char *out_file, bool emmc_fastboot, image_t 
*image_stack,
bool dcd_skip, uint8_t fuse_version, 
uint16_t sw_version,
@@ -920,6 +920,7 @@ static int build_container_qx_qm_b0(soc_type_t soc, 
uint32_t sector_size, uint32
img_sp = image_stack;
 
while (img_sp->option != NO_IMG) { /* stop once we reach null 
terminator */
+   int isize;
switch (img_sp->option) {
case FCB:
case AP:
@@ -934,11 +935,14 @@ static int build_container_qx_qm_b0(soc_type_t soc, 
uint32_t sector_size, uint32
exit(EXIT_FAILURE);
}
check_file(, img_sp->filename);
+   isize = ALIGN(sbuf.st_size, sector_size);
+   if (pblsize && isize > ALIGN(pblsize, 1024))
+   isize = ALIGN(pblsize, 1024);
set_image_array_entry(_header.fhdr[container],
soc,
img_sp,
file_off,
-   ALIGN(sbuf.st_size, 
sector_size),
+   isize,
img_sp->filename,
dcd_skip,
images_hash);
@@ -1788,6 +1792,7 @@ int main(int argc, char **argv)
{"upower", required_argument, NULL, 'w'},
{"fcb", required_argument, NULL, 'b'},
{"padding", required_argument, NULL, 'G'},
+   {"pblsize", required_argument, NULL, 

[PATCH 11/25] I2c: Add i2c_8bit_addr_from_msg()

2023-11-10 Thread Sascha Hauer
Signed-off-by: Sascha Hauer 
---
 include/i2c/i2c.h | 4 
 1 file changed, 4 insertions(+)

diff --git a/include/i2c/i2c.h b/include/i2c/i2c.h
index 4fc278f800..9094003b68 100644
--- a/include/i2c/i2c.h
+++ b/include/i2c/i2c.h
@@ -329,6 +329,10 @@ extern int i2c_transfer(struct i2c_adapter *adap, struct 
i2c_msg *msgs, int num)
 extern int i2c_master_send(struct i2c_client *client, const char *buf, int 
count);
 extern int i2c_master_recv(struct i2c_client *client, char *buf, int count);
 
+static inline u8 i2c_8bit_addr_from_msg(const struct i2c_msg *msg)
+{
+   return (msg->addr << 1) | (msg->flags & I2C_M_RD ? 1 : 0);
+}
 
 #define I2C_ADDR_16_BIT(1 << 31)
 
-- 
2.39.2




[PATCH 23/25] usb: i.MX chipidea: Enable usbmisc driver for i.MX9

2023-11-10 Thread Sascha Hauer
The usbmisc unit on the i.MX9 is compatible to the one on i.MX8MM.
Extend the #ifdef accordingly.

Signed-off-by: Sascha Hauer 
---
 drivers/usb/imx/imx-usb-misc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/imx/imx-usb-misc.c b/drivers/usb/imx/imx-usb-misc.c
index 61d01688a1..bf9583e626 100644
--- a/drivers/usb/imx/imx-usb-misc.c
+++ b/drivers/usb/imx/imx-usb-misc.c
@@ -602,7 +602,7 @@ static __maybe_unused struct of_device_id 
imx_usbmisc_dt_ids[] = {
.data = _data,
},
 #endif
-#ifdef CONFIG_ARCH_IMX8M
+#if defined CONFIG_ARCH_IMX8M || defined CONFIG_ARCH_IMX93
{
.compatible = "fsl,imx8mm-usbmisc",
.data = _data,
-- 
2.39.2




[PATCH 21/25] imx-usb-loader: Add i.MX9 support

2023-11-10 Thread Sascha Hauer
i.MX9 support is straight forward: Just upload the whole image
in one go.

Signed-off-by: Sascha Hauer 
---
 scripts/imx/imx-usb-loader.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c
index ece4603b2b..91a15345a2 100644
--- a/scripts/imx/imx-usb-loader.c
+++ b/scripts/imx/imx-usb-loader.c
@@ -76,6 +76,7 @@ struct mach_id {
unsigned short max_transfer;
 #define DEV_IMX0
 #define DEV_MXS1
+#define DEV_IMX9   2
unsigned char dev_type;
unsigned char hid_endpoint;
 };
@@ -214,6 +215,14 @@ static const struct mach_id imx_ids[] = {
.header_type = HDR_MX53,
.mode = MODE_HID,
.max_transfer = 1024,
+   }, {
+   .vid = 0x1fc9,
+   .pid = 0x014e,
+   .name = "i.MX9",
+   .mode = MODE_HID,
+   .max_transfer = 1020,
+   .hid_endpoint = 1,
+   .dev_type = DEV_IMX9,
},
 };
 
@@ -1350,6 +1359,23 @@ static int process_header(struct usb_work *curr, 
unsigned char *buf, int cnt,
return -ENODEV;
 }
 
+static int imx9_load_file(struct usb_work *curr)
+{
+   void *buf;
+   size_t fsize = 0;
+   int ret;
+
+   buf = read_file(curr->filename, );
+   if (!buf)
+   return -errno;
+
+   ret = send_buf(buf, fsize);
+   if (ret)
+   return ret;
+
+   return ret;
+}
+
 static int do_irom_download(struct usb_work *curr, int verify)
 {
int ret;
@@ -1649,6 +1675,9 @@ int main(int argc, char *argv[])
if (mach_id->dev_type == DEV_MXS) {
ret = mxs_load_file();
goto out;
+   } else if (mach_id->dev_type == DEV_IMX9) {
+   ret = imx9_load_file();
+   goto out;
}
 
if (!mach_id->hid_endpoint) {
-- 
2.39.2




[PATCH 07/25] clk: imx: clk-fracn-gppll: make usable from PBL

2023-11-10 Thread Sascha Hauer
The PBL code needs to adjust the DDR PLL before setting up DDR.
Factor out the PLL setup code as a static inline function for
PBL usage.

Signed-off-by: Sascha Hauer 
---
 drivers/clk/imx/clk-fracn-gppll.c | 135 +---
 drivers/clk/imx/clk.h |  28 +-
 include/soc/imx/clk-fracn-gppll.h | 144 ++
 3 files changed, 165 insertions(+), 142 deletions(-)
 create mode 100644 include/soc/imx/clk-fracn-gppll.h

diff --git a/drivers/clk/imx/clk-fracn-gppll.c 
b/drivers/clk/imx/clk-fracn-gppll.c
index 5fbc79f948..24e66fd65f 100644
--- a/drivers/clk/imx/clk-fracn-gppll.c
+++ b/drivers/clk/imx/clk-fracn-gppll.c
@@ -10,38 +10,10 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "clk.h"
 
-#define PLL_CTRL   0x0
-#define HW_CTRL_SELBIT(16)
-#define CLKMUX_BYPASS  BIT(2)
-#define CLKMUX_EN  BIT(1)
-#define POWERUP_MASK   BIT(0)
-
-#define PLL_ANA_PRG0x10
-#define PLL_SPREAD_SPECTRUM0x30
-
-#define PLL_NUMERATOR  0x40
-#define PLL_MFN_MASK   GENMASK(31, 2)
-
-#define PLL_DENOMINATOR0x50
-#define PLL_MFD_MASK   GENMASK(29, 0)
-
-#define PLL_DIV0x60
-#define PLL_MFI_MASK   GENMASK(24, 16)
-#define PLL_RDIV_MASK  GENMASK(15, 13)
-#define PLL_ODIV_MASK  GENMASK(7, 0)
-
-#define PLL_DFS_CTRL(x)(0x70 + (x) * 0x10)
-
-#define PLL_STATUS 0xF0
-#define LOCK_STATUSBIT(0)
-
-#define DFS_STATUS 0xF4
-
-#define LOCK_TIMEOUT_US200
-
 #define PLL_FRACN_GP(_rate, _mfi, _mfn, _mfd, _rdiv, _odiv)\
{   \
.rate   =   (_rate),\
@@ -118,19 +90,6 @@ static inline struct clk_fracn_gppll 
*to_clk_fracn_gppll(struct clk_hw *hw)
return container_of(hw, struct clk_fracn_gppll, hw);
 }
 
-static const struct imx_fracn_gppll_rate_table *
-imx_get_pll_settings(struct clk_fracn_gppll *pll, unsigned long rate)
-{
-   const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table;
-   int i;
-
-   for (i = 0; i < pll->rate_count; i++)
-   if (rate == rate_table[i].rate)
-   return _table[i];
-
-   return NULL;
-}
-
 static long clk_fracn_gppll_round_rate(struct clk_hw *hw, unsigned long rate,
   unsigned long *prate)
 {
@@ -157,17 +116,17 @@ static unsigned long clk_fracn_gppll_recalc_rate(struct 
clk_hw *hw, unsigned lon
long rate = 0;
int i;
 
-   pll_numerator = readl_relaxed(pll->base + PLL_NUMERATOR);
-   mfn = FIELD_GET(PLL_MFN_MASK, pll_numerator);
+   pll_numerator = readl_relaxed(pll->base + GPPLL_NUMERATOR);
+   mfn = FIELD_GET(GPPLL_MFN_MASK, pll_numerator);
 
-   pll_denominator = readl_relaxed(pll->base + PLL_DENOMINATOR);
-   mfd = FIELD_GET(PLL_MFD_MASK, pll_denominator);
+   pll_denominator = readl_relaxed(pll->base + GPPLL_DENOMINATOR);
+   mfd = FIELD_GET(GPPLL_MFD_MASK, pll_denominator);
 
-   pll_div = readl_relaxed(pll->base + PLL_DIV);
-   mfi = FIELD_GET(PLL_MFI_MASK, pll_div);
+   pll_div = readl_relaxed(pll->base + GPPLL_DIV);
+   mfi = FIELD_GET(GPPLL_MFI_MASK, pll_div);
 
-   rdiv = FIELD_GET(PLL_RDIV_MASK, pll_div);
-   odiv = FIELD_GET(PLL_ODIV_MASK, pll_div);
+   rdiv = FIELD_GET(GPPLL_RDIV_MASK, pll_div);
+   odiv = FIELD_GET(GPPLL_ODIV_MASK, pll_div);
 
/*
 * Sometimes, the recalculated rate has deviation due to
@@ -214,70 +173,16 @@ static unsigned long clk_fracn_gppll_recalc_rate(struct 
clk_hw *hw, unsigned lon
 
 static int clk_fracn_gppll_wait_lock(struct clk_fracn_gppll *pll)
 {
-   u32 val;
-
-   return readl_poll_timeout(pll->base + PLL_STATUS, val,
- val & LOCK_STATUS, LOCK_TIMEOUT_US);
+   return fracn_gppll_wait_lock(pll->base);
 }
 
 static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate,
unsigned long prate)
 {
struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
-   const struct imx_fracn_gppll_rate_table *rate;
-   u32 tmp, pll_div, ana_mfn;
-   int ret;
-
-   rate = imx_get_pll_settings(pll, drate);
-
-   /* Hardware control select disable. PLL is control by register */
-   tmp = readl_relaxed(pll->base + PLL_CTRL);
-   tmp &= ~HW_CTRL_SEL;
-   writel_relaxed(tmp, pll->base + PLL_CTRL);
-
-   /* Disable output */
-   tmp = readl_relaxed(pll->base + PLL_CTRL);
-   tmp &= ~CLKMUX_EN;
-   writel_relaxed(tmp, pll->base + PLL_CTRL);
-
-   /* Power Down */
-   tmp &= ~POWERUP_MASK;
-   writel_relaxed(tmp, pll->base + PLL_CTRL);
-
-   /* Disable BYPASS */
-   tmp &= ~CLKMUX_BYPASS;
-   writel_relaxed(tmp, pll->base + PLL_CTRL);
-
-   pll_div = 

[PATCH 00/25] Add i.MX93 support

2023-11-10 Thread Sascha Hauer
This series adds support for the NXP i.MX93 SoC along with board
support for the TQ TQMa93xxCA board.

Currently supported are:
- Pinctrl
- GPIO
- clock
- watchdog
- UART
- I2C
- SPI
- FEC ethernet

DDR support is not part of this series, I'll send it shortly in a
separate series.

Sascha

Sascha Hauer (25):
  ARM: initial i.MX9 support
  ARM: i.MX: Add i.MX93 s4mu support
  ARM: i.MX: Add i.MX93 trdc support
  scripts: Add imx9image tool
  scripts: imx9image: Add PBL size option
  clk: Add i.MX93 clock support
  clk: imx: clk-fracn-gppll: make usable from PBL
  gpio-vf610: Add i.MX93 support
  iomux: Add i.MX93 support
  watchdog: Add ULP wdog support
  I2c: Add i2c_8bit_addr_from_msg()
  i2c: Add lpi2c support
  ARM: Add imx93.dtsi for USB
  serial: Add lpuart32 driver
  ARM: i.MX: add i.MX9 debug_ll support
  ARM: Add TQ MBA9XXXCA board support
  ARM: i.MX93: Add DDR size read support
  ARM: i.MX: romapi: rename functions to *romapi*
  ARM: i.MX: romapi: Implement i.MX93 support
  ARM: i.MX: atf: add imx93_load_and_start_image_via_tfa()
  imx-usb-loader: Add i.MX9 support
  spi: spi-nxp-fspi: Enable for i.MX9
  usb: i.MX chipidea: Enable usbmisc driver for i.MX9
  ARM: Update imx_v8_defconfig
  ARM: multi_v8_defconfig: enable i.MX9 boards

 arch/arm/boards/Makefile  |1 +
 arch/arm/boards/tqmba9xxxca/Makefile  |2 +
 arch/arm/boards/tqmba9xxxca/board.c   |   58 +
 arch/arm/boards/tqmba9xxxca/lowlevel.c|   43 +
 .../tqmba9xxxca/lpddr4x_tqma93xxca_timing.c   | 1480 +++
 arch/arm/configs/imx_v8_defconfig |9 +-
 arch/arm/configs/multi_v8_defconfig   |7 +
 arch/arm/dts/Makefile |1 +
 arch/arm/dts/imx93-tqma9352-mba93xxca.dts |  826 +++
 arch/arm/dts/imx93.dtsi   |   62 +
 arch/arm/mach-imx/Kconfig |   26 +
 arch/arm/mach-imx/Makefile|6 +-
 arch/arm/mach-imx/atf.c   |   38 +-
 arch/arm/mach-imx/cpu_init.c  |   42 +
 arch/arm/mach-imx/esdctl.c|   42 +
 arch/arm/mach-imx/imx-bbu-internal.c  |5 +
 arch/arm/mach-imx/imx93-s4mu.c|   97 +
 arch/arm/mach-imx/imx93-trdc.c|  364 +++
 arch/arm/mach-imx/romapi.c|  166 +-
 common/Kconfig|5 +
 drivers/clk/imx/Makefile  |1 +
 drivers/clk/imx/clk-composite-93.c|  216 ++
 drivers/clk/imx/clk-fracn-gppll.c |  297 +++
 drivers/clk/imx/clk-gate-93.c |  186 ++
 drivers/clk/imx/clk-imx93.c   |  331 +++
 drivers/clk/imx/clk.h |   16 +
 drivers/gpio/Kconfig  |3 +-
 drivers/gpio/gpio-vf610.c |   78 +-
 drivers/i2c/busses/Kconfig|7 +
 drivers/i2c/busses/Makefile   |1 +
 drivers/i2c/busses/i2c-imx-lpi2c.c|  518 
 drivers/pinctrl/imx-iomux-v3.c|2 +
 drivers/serial/Kconfig|4 +
 drivers/serial/Makefile   |1 +
 drivers/serial/serial_lpuart32.c  |  185 ++
 drivers/spi/Kconfig   |2 +-
 drivers/usb/imx/imx-usb-misc.c|2 +-
 drivers/watchdog/Kconfig  |6 +
 drivers/watchdog/Makefile |1 +
 drivers/watchdog/imxulp-wdt.c |  161 ++
 firmware/Kconfig  |3 +
 firmware/Makefile |1 +
 images/Makefile.imx   |   11 +
 include/i2c/i2c.h |4 +
 include/mach/imx/atf.h|2 +
 include/mach/imx/bbu.h|9 +
 include/mach/imx/debug_ll.h   |   13 +
 include/mach/imx/generic.h|1 +
 include/mach/imx/imx9-regs.h  |   24 +
 include/mach/imx/romapi.h |5 +-
 include/mach/imx/xload.h  |1 +
 include/serial/lpuart32.h |  168 ++
 include/soc/imx/clk-fracn-gppll.h |  144 ++
 include/soc/imx9/flash_header.h   |   88 +
 include/soc/imx9/mu_hal.h |   12 +
 include/soc/imx9/s400_api.h   |  124 +
 include/soc/imx9/trdc.h   |   11 +
 scripts/Kconfig   |7 +
 scripts/Makefile  |1 +
 scripts/imx/imx-usb-loader.c  |   29 +
 scripts/imx9image.c   | 2179 +
 61 files changed, 8110 insertions(+), 25 deletions(-)
 create mode 100644 arch/arm/boards/tqmba9xxxca/Makefile
 create mode 100644 arch/arm/boards/tqmba9xxxca/board.c
 create mode 100644 arch/arm/boards/tqmba9xxxca/lowlevel.c
 create mode 100644 

[PATCH 13/25] ARM: Add imx93.dtsi for USB

2023-11-10 Thread Sascha Hauer
Current upstream i.MX93 dtsi file doesn't have USB support. Add a
local dtsi file for that.

Signed-off-by: Sascha Hauer 
---
 arch/arm/dts/imx93.dtsi | 62 +
 1 file changed, 62 insertions(+)
 create mode 100644 arch/arm/dts/imx93.dtsi

diff --git a/arch/arm/dts/imx93.dtsi b/arch/arm/dts/imx93.dtsi
new file mode 100644
index 00..2d8d4b2b58
--- /dev/null
+++ b/arch/arm/dts/imx93.dtsi
@@ -0,0 +1,62 @@
+/{
+   soc@0 {
+   usbphynop1: usbphynop1 {
+   compatible = "usb-nop-xceiv";
+   clocks = < IMX93_CLK_USB_PHY_BURUNIN>;
+   clock-names = "main_clk";
+   };
+
+   usbotg1: usb@4c10 {
+   compatible = "fsl,imx8mm-usb", "fsl,imx7d-usb";
+   reg = <0x4c10 0x200>;
+   interrupts = ;
+   clocks = < IMX93_CLK_USB_CONTROLLER_GATE>,
+< IMX93_CLK_HSIO_32K_GATE>;
+   clock-names = "usb_ctrl_root_clk", "usb_wakeup_clk";
+   assigned-clocks = < IMX93_CLK_HSIO>;
+   assigned-clock-parents = < 
IMX93_CLK_SYS_PLL_PFD1_DIV2>;
+   assigned-clock-rates = <13300>;
+   fsl,usbphy = <>;
+   fsl,usbmisc = < 0>;
+   status = "disabled";
+   };
+
+   usbmisc1: usbmisc@4c100200 {
+   compatible = "fsl,imx8mm-usbmisc", "fsl,imx7d-usbmisc";
+   #index-cells = <1>;
+   reg = <0x4c100200 0x200>;
+   };
+
+   usbphynop2: usbphynop2 {
+   compatible = "usb-nop-xceiv";
+   clocks = < IMX93_CLK_USB_PHY_BURUNIN>;
+   clock-names = "main_clk";
+   };
+
+   usbotg2: usb@4c20 {
+   compatible = "fsl,imx8mm-usb", "fsl,imx7d-usb";
+   reg = <0x4c20 0x200>;
+   interrupts = ;
+   clocks = < IMX93_CLK_USB_CONTROLLER_GATE>,
+< IMX93_CLK_HSIO_32K_GATE>;
+   clock-names = "usb_ctrl_root_clk", "usb_wakeup_clk";
+   assigned-clocks = < IMX93_CLK_HSIO>;
+   assigned-clock-parents = < 
IMX93_CLK_SYS_PLL_PFD1_DIV2>;
+   assigned-clock-rates = <13300>;
+   fsl,usbphy = <>;
+   fsl,usbmisc = < 0>;
+   status = "disabled";
+   };
+
+   usbmisc2: usbmisc@4c200200 {
+   compatible = "fsl,imx8mm-usbmisc", "fsl,imx7d-usbmisc";
+   #index-cells = <1>;
+   reg = <0x4c200200 0x200>;
+   };
+
+   ddrc: memory-controller@4e30 {
+   compatible = "fsl,imx93-ddrc";
+   reg = <0x4e30 0x40>;
+   };
+   };
+};
-- 
2.39.2




[PATCH 02/25] ARM: i.MX: Add i.MX93 s4mu support

2023-11-10 Thread Sascha Hauer
Signed-off-by: Sascha Hauer 
---
 arch/arm/mach-imx/Makefile |   1 +
 arch/arm/mach-imx/imx93-s4mu.c |  97 ++
 include/soc/imx9/mu_hal.h  |  12 
 include/soc/imx9/s400_api.h| 124 +
 4 files changed, 234 insertions(+)
 create mode 100644 arch/arm/mach-imx/imx93-s4mu.c
 create mode 100644 include/soc/imx9/mu_hal.h
 create mode 100644 include/soc/imx9/s400_api.h

diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 7b093ba7fd..4efac08ee8 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -33,3 +33,4 @@ obj-$(CONFIG_RESET_IMX_SRC) += src.o
 lwl-y += cpu_init.o
 pbl-y += xload-spi.o xload-common.o xload-imx-nand.o xload-gpmi-nand.o
 pbl-y += xload-qspi.o
+pbl-$(CONFIG_ARCH_IMX93) += imx93-s4mu.o
diff --git a/arch/arm/mach-imx/imx93-s4mu.c b/arch/arm/mach-imx/imx93-s4mu.c
new file mode 100644
index 00..11a787d44d
--- /dev/null
+++ b/arch/arm/mach-imx/imx93-s4mu.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2020-2022 NXP
+ */
+#define pr_fmt(fmt) "s4mu: " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MU_SR_TE0_MASK BIT(0)
+#define MU_SR_RF0_MASK BIT(0)
+#define MU_TR_COUNT8
+#define MU_RR_COUNT4
+
+struct mu_type {
+   u32 ver;
+   u32 par;
+   u32 cr;
+   u32 sr;
+   u32 reserved0[60];
+   u32 fcr;
+   u32 fsr;
+   u32 reserved1[2];
+   u32 gier;
+   u32 gcr;
+   u32 gsr;
+   u32 reserved2;
+   u32 tcr;
+   u32 tsr;
+   u32 rcr;
+   u32 rsr;
+   u32 reserved3[52];
+   u32 tr[16];
+   u32 reserved4[16];
+   u32 rr[16];
+   u32 reserved5[14];
+   u32 mu_attr;
+};
+
+void mu_hal_init(ulong base)
+{
+   struct mu_type *mu_base = (struct mu_type *)base;
+
+   writel(0, _base->tcr);
+   writel(0, _base->rcr);
+}
+
+int mu_hal_sendmsg(ulong base, u32 reg_index, u32 msg)
+{
+   struct mu_type *mu_base = (struct mu_type *)base;
+   u32 mask = MU_SR_TE0_MASK << reg_index;
+   u32 val;
+   int ret;
+
+   BUG_ON(reg_index >= MU_TR_COUNT);
+
+   pr_vdebug("sendmsg tsr 0x%x\n", readl(_base->tsr));
+
+   /* Wait TX register to be empty. */
+   ret = readl_poll_timeout(_base->tsr, val, val & mask, 1);
+   if (ret < 0) {
+   pr_debug("%s timeout\n", __func__);
+   return -ETIMEDOUT;
+   }
+
+   pr_vdebug("tr[%d] 0x%x\n", reg_index, msg);
+
+   writel(msg, _base->tr[reg_index]);
+
+   return 0;
+}
+
+int mu_hal_receivemsg(ulong base, u32 reg_index, u32 *msg)
+{
+   struct mu_type *mu_base = (struct mu_type *)base;
+   u32 mask = MU_SR_RF0_MASK << reg_index;
+   u32 val;
+   int ret;
+
+   BUG_ON(reg_index >= MU_RR_COUNT);
+
+   pr_vdebug("receivemsg rsr 0x%x\n", readl(_base->rsr));
+
+   /* Wait RX register to be full. */
+   ret = readl_poll_timeout(_base->rsr, val, val & mask, 1000);
+   if (ret < 0)
+   return -ETIMEDOUT;
+
+   *msg = readl(_base->rr[reg_index]);
+
+   pr_vdebug("rr[%d] 0x%x\n", reg_index, *msg);
+
+   return 0;
+}
diff --git a/include/soc/imx9/mu_hal.h b/include/soc/imx9/mu_hal.h
new file mode 100644
index 00..5db559c1ac
--- /dev/null
+++ b/include/soc/imx9/mu_hal.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2021 NXP
+ */
+
+#ifndef __SNT_MU_HAL_H__
+#define __SNT_MU_HAL_H__
+
+void mu_hal_init(ulong base);
+int mu_hal_sendmsg(ulong base, u32 reg_index, u32 msg);
+int mu_hal_receivemsg(ulong base, u32 reg_index, u32 *msg);
+#endif
diff --git a/include/soc/imx9/s400_api.h b/include/soc/imx9/s400_api.h
new file mode 100644
index 00..6d2dd71d67
--- /dev/null
+++ b/include/soc/imx9/s400_api.h
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2021 NXP
+ */
+
+#ifndef __S400_API_H__
+#define __S400_API_H__
+
+#define AHAB_VERSION0x6
+#define AHAB_CMD_TAG0x17
+#define AHAB_RESP_TAG   0xe1
+
+/* ELE commands */
+#define ELE_PING_REQ (0x01)
+#define ELE_FW_AUTH_REQ (0x02)
+#define ELE_RESTART_RST_TIMER_REQ (0x04)
+#define ELE_DUMP_DEBUG_BUFFER_REQ (0x21)
+#define ELE_OEM_CNTN_AUTH_REQ (0x87)
+#define ELE_VERIFY_IMAGE_REQ (0x88)
+#define ELE_RELEASE_CONTAINER_REQ (0x89)
+#define ELE_WRITE_SECURE_FUSE_REQ (0x91)
+#define ELE_FWD_LIFECYCLE_UP_REQ (0x95)
+#define ELE_READ_FUSE_REQ (0x97)
+#define ELE_GET_FW_VERSION_REQ (0x9D)
+#define ELE_RET_LIFECYCLE_UP_REQ (0xA0)
+#define ELE_GET_EVENTS_REQ (0xA2)
+#define ELE_START_RNG (0xA3)
+#define ELE_GENERATE_DEK_BLOB (0xAF)
+#define ELE_ENABLE_PATCH_REQ (0xC3)
+#define ELE_RELEASE_RDC_REQ (0xC4)
+#define ELE_GET_FW_STATUS_REQ (0xC5)
+#define ELE_ENABLE_OTFAD_REQ (0xC6)
+#define ELE_RESET_REQ (0xC7)
+#define ELE_UPDATE_OTP_CLKDIV_REQ (0xD0)
+#define ELE_POWER_DOWN_REQ (0xD1)
+#define ELE_ENABLE_APC_REQ (0xD2)
+#define ELE_ENABLE_RTC_REQ 

Re: Rockchip rk3328 support?

2023-11-10 Thread Sascha Hauer
Hi Konsti,

On Fri, Nov 10, 2023 at 11:16:01AM +0100, Konstantin Kletschke wrote:
> Dear barebox community,
> 
> is something like the rk3328 supported actually? I have a Dusun DSGW-210
> device here which _seems_ to be mainly 99% like a rk3328 EVB board (Olimex
> rk3328 eval bord).

The rk3328 is not yet supported. We have support for rk3568 and rk3288
though, so the ground work for generally supporting Rockchip SoCs has
been done. I don't know how similar the rk3328 is to the supported SoCs,
you could have a look at the Kernel or U-Boot to see how close they are.

> 
> From the CONFIG options or cpu support files I would say no, but there
> is dts/src/arm64/rockchip/rk3328-evb.dts which sounds rather good so I
> wonder if this is hidden as a subset under other board/cpu.

The dts/ directory is taken verbatim from
git://git.kernel.org/pub/scm/linux/kernel/git/devicetree/devicetree-rebasing.git
which contains all Linux device tree files. The ones actually supported
by barebox are in arch/*/dts/. These include the upstream device tree
files where possible

Regards,
 Sascha

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |



Rockchip rk3328 support?

2023-11-10 Thread Konstantin Kletschke
Dear barebox community,

is something like the rk3328 supported actually? I have a Dusun DSGW-210
device here which _seems_ to be mainly 99% like a rk3328 EVB board (Olimex
rk3328 eval bord). 

>From the CONFIG options or cpu support files I would say no, but there
is dts/src/arm64/rockchip/rk3328-evb.dts which sounds rather good so I
wonder if this is hidden as a subset under other board/cpu.

Kind Regards
Konstantin



-- 
INSIDE M2M GmbH
Konstantin Kletschke
Berenbosteler Strasse 76 B
30823 Garbsen

Telefon: +49 (0) 5137 90950136
Mobil: +49 (0) 151 15256238
Fax: +49 (0) 5137 9095010

konstantin.kletsc...@inside-m2m.de
http://www.inside-m2m.de 

Gesch"aftsf"uhrung: Michael Emmert, Derek Uhlig
HRB: 111204, AG Hannover




[PATCH 2/2] ARM: i.MX8M: detangle lowlevel code

2023-11-10 Thread Sascha Hauer
The i.MX8M lowlevel code uses some macros which take SoC prefix names as
arguments which then expand to SoC specific function names. The result
is hard to follow. Detangle this by open coding the macros. At the
expense of a bit of code duplication we gain readability.

Signed-off-by: Sascha Hauer 
---
 arch/arm/mach-imx/atf.c  | 116 +++
 include/mach/imx/atf.h   |  17 --
 include/mach/imx/xload.h |  15 -
 3 files changed, 80 insertions(+), 68 deletions(-)

diff --git a/arch/arm/mach-imx/atf.c b/arch/arm/mach-imx/atf.c
index 6f9b69ff9a..d6d1aa3d68 100644
--- a/arch/arm/mach-imx/atf.c
+++ b/arch/arm/mach-imx/atf.c
@@ -57,26 +57,6 @@ static __noreturn void imx8m_atf_start_bl31(const void *fw, 
size_t fw_size, void
__builtin_unreachable();
 }
 
-__noreturn void imx8mm_atf_load_bl31(const void *fw, size_t fw_size)
-{
-   imx8m_atf_start_bl31(fw, fw_size, (void *)MX8MM_ATF_BL31_BASE_ADDR);
-}
-
-__noreturn void imx8mn_atf_load_bl31(const void *fw, size_t fw_size)
-{
-   imx8m_atf_start_bl31(fw, fw_size, (void *)MX8MN_ATF_BL31_BASE_ADDR);
-}
-
-__noreturn void imx8mp_atf_load_bl31(const void *fw, size_t fw_size)
-{
-   imx8m_atf_start_bl31(fw, fw_size, (void *)MX8MP_ATF_BL31_BASE_ADDR);
-}
-
-__noreturn void imx8mq_atf_load_bl31(const void *fw, size_t fw_size)
-{
-   imx8m_atf_start_bl31(fw, fw_size, (void *)MX8MQ_ATF_BL31_BASE_ADDR);
-}
-
 void imx8mm_load_bl33(void *bl33)
 {
enum bootsource src;
@@ -138,16 +118,32 @@ void imx8mm_load_bl33(void *bl33)
 
 __noreturn void imx8mm_load_and_start_image_via_tfa(void)
 {
+   const void *bl31;
+   size_t bl31_size;
void *bl33 = (void *)MX8M_ATF_BL33_BASE_ADDR;
unsigned long endmem = MX8M_DDR_CSD1_BASE_ADDR + 
imx8m_barebox_earlymem_size(32);
 
imx8m_save_bootrom_log((void *)arm_mem_scratch(endmem));
imx8mm_load_bl33(bl33);
 
-   if (IS_ENABLED(CONFIG_FIRMWARE_IMX8MM_OPTEE))
-   imx8m_load_and_start_optee_via_tfa(imx8mm, (void 
*)arm_mem_optee(endmem), bl33);
-   else
-   imx8mm_load_and_start_tfa(imx8mm_bl31_bin);
+   if (IS_ENABLED(CONFIG_FIRMWARE_IMX8MM_OPTEE)) {
+   void *bl32 = (void *)arm_mem_optee(endmem);
+   size_t bl32_size;
+   void *bl32_image;
+
+   imx8mm_tzc380_init();
+   get_builtin_firmware_ext(imx8mm_bl32_bin,
+   bl33, _image,
+   _size);
+
+   memcpy(bl32, bl32_image, bl32_size);
+
+   get_builtin_firmware(imx8mm_bl31_bin_optee, , _size);
+   } else {
+   get_builtin_firmware(imx8mm_bl31_bin, , _size);
+   }
+
+   imx8m_atf_start_bl31(bl31, bl31_size, (void *)MX8MM_ATF_BL31_BASE_ADDR);
 }
 
 void imx8mp_load_bl33(void *bl33)
@@ -185,16 +181,32 @@ void imx8mp_load_bl33(void *bl33)
 
 __noreturn void imx8mp_load_and_start_image_via_tfa(void)
 {
+   const void *bl31;
+   size_t bl31_size;
void *bl33 = (void *)MX8M_ATF_BL33_BASE_ADDR;
unsigned long endmem = MX8M_DDR_CSD1_BASE_ADDR + 
imx8m_barebox_earlymem_size(32);
 
imx8m_save_bootrom_log((void *)arm_mem_scratch(endmem));
imx8mp_load_bl33(bl33);
 
-   if (IS_ENABLED(CONFIG_FIRMWARE_IMX8MP_OPTEE))
-   imx8m_load_and_start_optee_via_tfa(imx8mp, (void 
*)arm_mem_optee(endmem), bl33);
-   else
-   imx8mp_load_and_start_tfa(imx8mp_bl31_bin);
+   if (IS_ENABLED(CONFIG_FIRMWARE_IMX8MP_OPTEE)) {
+   void *bl32 = (void *)arm_mem_optee(endmem);
+   size_t bl32_size;
+   void *bl32_image;
+
+   imx8mp_tzc380_init();
+   get_builtin_firmware_ext(imx8mp_bl32_bin,
+   bl33, _image,
+   _size);
+
+   memcpy(bl32, bl32_image, bl32_size);
+
+   get_builtin_firmware(imx8mp_bl31_bin_optee, , _size);
+   } else {
+   get_builtin_firmware(imx8mp_bl31_bin, , _size);
+   }
+
+   imx8m_atf_start_bl31(bl31, bl31_size, (void *)MX8MP_ATF_BL31_BASE_ADDR);
 }
 
 
@@ -233,16 +245,32 @@ void imx8mn_load_bl33(void *bl33)
 
 __noreturn void imx8mn_load_and_start_image_via_tfa(void)
 {
+   const void *bl31;
+   size_t bl31_size;
void *bl33 = (void *)MX8M_ATF_BL33_BASE_ADDR;
unsigned long endmem = MX8M_DDR_CSD1_BASE_ADDR + 
imx8m_barebox_earlymem_size(16);
 
imx8m_save_bootrom_log((void *)arm_mem_scratch(endmem));
imx8mn_load_bl33(bl33);
 
-   if (IS_ENABLED(CONFIG_FIRMWARE_IMX8MN_OPTEE))
-   imx8m_load_and_start_optee_via_tfa(imx8mn, (void 
*)arm_mem_optee(endmem), bl33);
-   else
-   imx8mn_load_and_start_tfa(imx8mn_bl31_bin);
+   if (IS_ENABLED(CONFIG_FIRMWARE_IMX8MN_OPTEE)) {
+   void *bl32 = (void *)arm_mem_optee(endmem);
+   size_t bl32_size;
+   void *bl32_image;
+
+

[PATCH 1/2] ARM: i.MX8MQ: Streamline lowlevel startup code

2023-11-10 Thread Sascha Hauer
Most i.MX8M SoCs have a imx8m[nmp]_load_and_start_image_via_tfa()
function which does all the magic of loading and starting TF-A,
barebox proper and OP-TEE images. Only the i.MX8MQ boards have the
same open coded in the lowlevel code.
Implement a imx8mq_load_and_start_image_via_tfa() and switch the
i.MX8MQ boards over to it.

Signed-off-by: Sascha Hauer 
---
 arch/arm/boards/mnt-reform/lowlevel.c| 28 +
 arch/arm/boards/nxp-imx8mq-evk/lowlevel.c| 26 +
 arch/arm/boards/phytec-som-imx8mq/lowlevel.c | 27 ++---
 arch/arm/boards/zii-imx8mq-dev/lowlevel.c| 20 +-
 arch/arm/mach-imx/atf.c  | 41 
 include/mach/imx/atf.h   |  1 +
 include/mach/imx/xload.h |  2 +
 7 files changed, 51 insertions(+), 94 deletions(-)

diff --git a/arch/arm/boards/mnt-reform/lowlevel.c 
b/arch/arm/boards/mnt-reform/lowlevel.c
index 074beba099..a82991c466 100644
--- a/arch/arm/boards/mnt-reform/lowlevel.c
+++ b/arch/arm/boards/mnt-reform/lowlevel.c
@@ -128,33 +128,7 @@ static __noreturn noinline void mnt_reform_start(void)
 
imx8mq_ddr_init(_reform_dram_timing, DRAM_TYPE_LPDDR4);
 
-   imx8mq_get_boot_source(, );
-   switch (src) {
-   case BOOTSOURCE_MMC:
-   imx8m_esdhc_load_image(instance, false);
-   break;
-   case BOOTSOURCE_SERIAL:
-   imx8m_esdhc_load_image(1, false);
-   break;
-   default:
-   printf("Unhandled bootsource BOOTSOURCE_%d\n", src);
-   hang();
-   }
-
-   /*
-* On completion the TF-A will jump to MX8M_ATF_BL33_BASE_ADDR
-* in EL2. Copy the image there, but replace the PBL part of
-* that image with ourselves. On a high assurance boot only the
-* currently running code is validated and contains the checksum
-* for the piggy data, so we need to ensure that we are running
-* the same code in DRAM.
-*/
-   memcpy((void *)MX8M_ATF_BL33_BASE_ADDR,
-  __image_start, barebox_pbl_size);
-
-   get_builtin_firmware(imx8mq_bl31_bin, , _size);
-
-   imx8mq_atf_load_bl31(bl31, bl31_size);
+   imx8mq_load_and_start_image_via_tfa();
}
 
/*
diff --git a/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c 
b/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c
index 5167c5f606..d1a517dddb 100644
--- a/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c
+++ b/arch/arm/boards/nxp-imx8mq-evk/lowlevel.c
@@ -65,33 +65,9 @@ static __noreturn noinline void nxp_imx8mq_evk_start(void)
 * to DRAM in EL2.
 */
if (current_el() == 3) {
-   enum bootsource src = BOOTSOURCE_UNKNOWN;
-   int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-   int ret = -ENOTSUPP;
-   size_t bl31_size;
-   const u8 *bl31;
-
ddr_init();
 
-   /*
-* On completion the TF-A will jump to MX8MQ_ATF_BL33_BASE_ADDR
-* in EL2. Copy the image there, but replace the PBL part of
-* that image with ourselves. On a high assurance boot only the
-* currently running code is validated and contains the checksum
-* for the piggy data, so we need to ensure that we are running
-* the same code in DRAM.
-*/
-   imx8mq_get_boot_source(, );
-   if (src == BOOTSOURCE_MMC)
-   ret = imx8m_esdhc_load_image(instance, false);
-   BUG_ON(ret);
-
-   memcpy((void *)MX8MQ_ATF_BL33_BASE_ADDR,
-  __image_start, barebox_pbl_size);
-
-   get_builtin_firmware(imx8mq_bl31_bin, , _size);
-   imx8mq_atf_load_bl31(bl31, bl31_size);
-   /* not reached */
+   imx8mq_load_and_start_image_via_tfa();
}
 
/*
diff --git a/arch/arm/boards/phytec-som-imx8mq/lowlevel.c 
b/arch/arm/boards/phytec-som-imx8mq/lowlevel.c
index ba5f987d22..5708c8d754 100644
--- a/arch/arm/boards/phytec-som-imx8mq/lowlevel.c
+++ b/arch/arm/boards/phytec-som-imx8mq/lowlevel.c
@@ -43,22 +43,6 @@ static void setup_uart(void)
putc_ll('>');
 }
 
-static void phytec_imx8mq_som_sram_setup(void)
-{
-   enum bootsource src = BOOTSOURCE_UNKNOWN;
-   int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
-   int ret = -ENOTSUPP;
-
-   ddr_init();
-
-   imx8mq_get_boot_source(, );
-
-   if (src == BOOTSOURCE_MMC)
-   ret = imx8m_esdhc_load_image(instance, true);
-
-   BUG_ON(ret);
-}
-
 static __noreturn noinline void phytec_phycore_imx8mq_start(void)
 {
setup_uart();
@@ -70,7 +54,7 @@ static __noreturn noinline void