[PATCH 11/11] cmd: eeprom: Extend to EEPROMs probed via driver model

2024-05-21 Thread Marek Behún
Extend the 'eeprom' command to allow accessing EEPROMs probed via
driver model, uclass UCLASS_I2C_EEPROM.

When the CONFIG_I2C_EEPROM config option is enabled (and so the
i2c-eeprom driver is built), the 'eeprom' command now accepts driver
model device name as EEPROM specifier for the 'eeprom' command, in
addition to the legacy [[bus] devaddr] specifier.

Moreover if no device specifier is given, then the first
UCLASS_I2C_EEPROM device is used, if found.

Signed-off-by: Marek Behún 
---
 cmd/eeprom.c | 122 ++-
 1 file changed, 112 insertions(+), 10 deletions(-)

diff --git a/cmd/eeprom.c b/cmd/eeprom.c
index 9c4af88738..a39fc5ffdc 100644
--- a/cmd/eeprom.c
+++ b/cmd/eeprom.c
@@ -22,8 +22,10 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -209,10 +211,41 @@ static long parse_numeric_param(char *str)
 }
 
 struct eeprom_dev_spec {
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+   struct udevice *dev;
+#endif
int i2c_bus;
ulong i2c_addr;
 };
 
+static void eeprom_dev_spec_init(struct eeprom_dev_spec *dev)
+{
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+   if (!dev->dev)
+#endif
+   eeprom_init(dev->i2c_bus);
+}
+
+static int eeprom_dev_spec_read(struct eeprom_dev_spec *dev,
+   unsigned offset, uchar *buffer, unsigned cnt)
+{
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+   if (dev->dev)
+   return i2c_eeprom_read(dev->dev, offset, buffer, cnt);
+#endif
+   return eeprom_read(dev->i2c_addr, offset, buffer, cnt);
+}
+
+static int eeprom_dev_spec_write(struct eeprom_dev_spec *dev,
+unsigned offset, uchar *buffer, unsigned cnt)
+{
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+   if (dev->dev)
+   return i2c_eeprom_write(dev->dev, offset, buffer, cnt);
+#endif
+   return eeprom_write(dev->i2c_addr, offset, buffer, cnt);
+}
+
 /**
  * parse_eeprom_dev_spec - parse the eeprom device specifier
  *
@@ -226,6 +259,28 @@ struct eeprom_dev_spec {
 static int parse_eeprom_dev_spec(struct eeprom_dev_spec *dev, int argc,
 char *const argv[])
 {
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+   if (argc == 0) {
+   if (!uclass_first_device_err(UCLASS_I2C_EEPROM, >dev))
+   return 0;
+   }
+
+   if (argc == 1) {
+   if (!uclass_get_device_by_name(UCLASS_I2C_EEPROM, argv[0],
+  >dev))
+   return 1;
+
+   /*
+* If we could not find the device by name and the parameter is
+* not numeric (and so won't be handled later), fail.
+*/
+   if (parse_numeric_param(argv[0]) == -1) {
+   printf("Can't get eeprom device: %s\n", argv[0]);
+   return CMD_RET_USAGE;
+   }
+   }
+#endif
+
 #ifdef CONFIG_SYS_I2C_EEPROM_ADDR
if (argc == 0) {
dev->i2c_bus = -1;
@@ -265,6 +320,7 @@ static unsigned char eeprom_buf[CONFIG_SYS_EEPROM_SIZE];
 #endif
 
 enum eeprom_action {
+   EEPROM_LIST,
EEPROM_READ,
EEPROM_WRITE,
EEPROM_PRINT,
@@ -274,6 +330,10 @@ enum eeprom_action {
 
 static enum eeprom_action parse_action(char *cmd)
 {
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+   if (!strncmp(cmd, "list", 4))
+   return EEPROM_LIST;
+#endif
if (!strncmp(cmd, "read", 4))
return EEPROM_READ;
if (!strncmp(cmd, "write", 5))
@@ -288,6 +348,24 @@ static enum eeprom_action parse_action(char *cmd)
return EEPROM_ACTION_INVALID;
 }
 
+#if CONFIG_IS_ENABLED(I2C_EEPROM)
+static int do_eeprom_list(void)
+{
+   struct udevice *dev;
+   struct uclass *uc;
+   int err;
+
+   err = uclass_get(UCLASS_I2C_EEPROM, );
+   if (err)
+   return CMD_RET_FAILURE;
+
+   uclass_foreach_dev(dev, uc)
+   printf("%s (%s)\n", dev->name, dev->driver->name);
+
+   return CMD_RET_SUCCESS;
+}
+#endif
+
 static int do_eeprom_rw(struct eeprom_dev_spec *dev, bool read,
ulong addr, ulong off, ulong cnt)
 {
@@ -298,9 +376,9 @@ static int do_eeprom_rw(struct eeprom_dev_spec *dev, bool 
read,
 
printf(fmt, dev->i2c_addr, read ? "read" : "write", addr, off, cnt);
if (read)
-   ret = eeprom_read(dev->i2c_addr, off, memloc, cnt);
+   ret = eeprom_dev_spec_read(dev, off, memloc, cnt);
else
-   ret = eeprom_write(dev->i2c_addr, off, memloc, cnt);
+   ret = eeprom_dev_spec_write(dev, off, memloc, cnt);
puts("done\n");
 
return ret;
@@ -314,7 +392,7 @@ static int do_eeprom_layout(struct eeprom_dev_spec *dev, 
int layout_ver,
eeprom_layout_setup

[PATCH 10/11] cmd: eeprom: Don't read/write whole EEPROM if not necessary

2024-05-21 Thread Marek Behún
Don't read/write whole EEPROM if not necessary when printing / updating
EEPROM layout fields. Only read/write layout.data_size bytes.

Signed-off-by: Marek Behún 
---
 cmd/eeprom.c | 11 ++-
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/cmd/eeprom.c b/cmd/eeprom.c
index c76cf43157..9c4af88738 100644
--- a/cmd/eeprom.c
+++ b/cmd/eeprom.c
@@ -311,16 +311,10 @@ static int do_eeprom_rw(struct eeprom_dev_spec *dev, bool 
read,
 static int do_eeprom_layout(struct eeprom_dev_spec *dev, int layout_ver,
struct eeprom_layout *layout)
 {
-   int ret;
-
-   ret = eeprom_read(dev->i2c_addr, 0, eeprom_buf, CONFIG_SYS_EEPROM_SIZE);
-   if (ret)
-   return ret;
-
eeprom_layout_setup(layout, eeprom_buf, CONFIG_SYS_EEPROM_SIZE,
layout_ver);
 
-   return 0;
+   return eeprom_read(dev->i2c_addr, 0, eeprom_buf, layout->data_size);
 }
 
 static int do_eeprom_print(struct eeprom_dev_spec *dev, int layout_ver)
@@ -351,8 +345,7 @@ static int do_eeprom_update(struct eeprom_dev_spec *dev, 
int layout_ver,
if (ret)
return CMD_RET_FAILURE;
 
-   return eeprom_write(dev->i2c_addr, 0, layout.data,
-   CONFIG_SYS_EEPROM_SIZE);
+   return eeprom_write(dev->i2c_addr, 0, layout.data, layout.data_size);
 }
 
 #endif
-- 
2.44.1



[PATCH 08/11] cmd: eeprom: Refactor eeprom device specifier parsing

2024-05-21 Thread Marek Behún
In preparation for allowing to access eeprom by driver-model device
name, refactor the eeprom device specifier parsing. Instead of filling
two parameters (i2c_bus, i2c_addr), the parsing function now fills one
parameter of type struct eeprom_dev_spec.

Signed-off-by: Marek Behún 
---
 cmd/eeprom.c | 77 
 1 file changed, 41 insertions(+), 36 deletions(-)

diff --git a/cmd/eeprom.c b/cmd/eeprom.c
index 12902e812e..e29639780d 100644
--- a/cmd/eeprom.c
+++ b/cmd/eeprom.c
@@ -208,41 +208,42 @@ static long parse_numeric_param(char *str)
return (*endptr != '\0') ? -1 : value;
 }
 
+struct eeprom_dev_spec {
+   int i2c_bus;
+   ulong i2c_addr;
+};
+
 /**
- * parse_i2c_bus_addr - parse the i2c bus and i2c devaddr parameters
+ * parse_eeprom_dev_spec - parse the eeprom device specifier
  *
- * @i2c_bus:   address to store the i2c bus
- * @i2c_addr:  address to store the device i2c address
- * @argc:  count of command line arguments left to parse
+ * @dev:   pointer to eeprom device specifier
+ * @argc:  count of command line arguments that can be used to parse
+ * the device specifier
  * @argv:  command line arguments left to parse
- * @argc_no_bus_addr:  argc value we expect to see when bus & addr aren't given
  *
  * @returns:   number of arguments parsed or CMD_RET_USAGE if error
  */
-static int parse_i2c_bus_addr(int *i2c_bus, ulong *i2c_addr, int argc,
- char *const argv[], int argc_no_bus_addr)
+static int parse_eeprom_dev_spec(struct eeprom_dev_spec *dev, int argc,
+char *const argv[])
 {
-   int argc_no_bus = argc_no_bus_addr + 1;
-   int argc_bus_addr = argc_no_bus_addr + 2;
-
 #ifdef CONFIG_SYS_I2C_EEPROM_ADDR
-   if (argc == argc_no_bus_addr) {
-   *i2c_bus = -1;
-   *i2c_addr = CONFIG_SYS_I2C_EEPROM_ADDR;
+   if (argc == 0) {
+   dev->i2c_bus = -1;
+   dev->i2c_addr = CONFIG_SYS_I2C_EEPROM_ADDR;
 
return 0;
}
 #endif
-   if (argc == argc_no_bus) {
-   *i2c_bus = -1;
-   *i2c_addr = parse_numeric_param(argv[0]);
+   if (argc == 1) {
+   dev->i2c_bus = -1;
+   dev->i2c_addr = parse_numeric_param(argv[0]);
 
return 1;
}
 
-   if (argc == argc_bus_addr) {
-   *i2c_bus = parse_numeric_param(argv[0]);
-   *i2c_addr = parse_numeric_param(argv[1]);
+   if (argc == 2) {
+   dev->i2c_bus = parse_numeric_param(argv[0]);
+   dev->i2c_addr = parse_numeric_param(argv[1]);
 
return 2;
}
@@ -287,9 +288,10 @@ static enum eeprom_action parse_action(char *cmd)
return EEPROM_ACTION_INVALID;
 }
 
-static int eeprom_execute_command(enum eeprom_action action, int i2c_bus,
- ulong i2c_addr, int layout_ver, char *key,
- char *value, ulong addr, ulong off, ulong cnt)
+static int eeprom_execute_command(enum eeprom_action action,
+ struct eeprom_dev_spec *dev,
+ int layout_ver, char *key, char *value,
+ ulong addr, ulong off, ulong cnt)
 {
int rcode = 0;
const char *const fmt =
@@ -301,25 +303,26 @@ static int eeprom_execute_command(enum eeprom_action 
action, int i2c_bus,
if (action == EEPROM_ACTION_INVALID)
return CMD_RET_USAGE;
 
-   eeprom_init(i2c_bus);
+   eeprom_init(dev->i2c_bus);
if (action == EEPROM_READ) {
-   printf(fmt, i2c_addr, "read", addr, off, cnt);
+   printf(fmt, dev->i2c_addr, "read", addr, off, cnt);
 
-   rcode = eeprom_read(i2c_addr, off, (uchar *)addr, cnt);
+   rcode = eeprom_read(dev->i2c_addr, off, (uchar *)addr, cnt);
 
puts("done\n");
return rcode;
} else if (action == EEPROM_WRITE) {
-   printf(fmt, i2c_addr, "write", addr, off, cnt);
+   printf(fmt, dev->i2c_addr, "write", addr, off, cnt);
 
-   rcode = eeprom_write(i2c_addr, off, (uchar *)addr, cnt);
+   rcode = eeprom_write(dev->i2c_addr, off, (uchar *)addr, cnt);
 
puts("done\n");
return rcode;
}
 
 #ifdef CONFIG_CMD_EEPROM_LAYOUT
-   rcode = eeprom_read(i2c_addr, 0, eeprom_buf, CONFIG_SYS_EEPROM_SIZE);
+   rcode = eeprom_read(dev->i2c_addr, 0, eeprom_buf,
+   CONFIG_SYS_EEPROM_SIZE);
if (rcode < 0)
return rcode;
 
@@ -333,7 +336,8 @@ static int eeprom_execute_command(enum eeprom_action 
action, int i2c_bus,
 
layout.update(, key, value);
 
-   rcode = eeprom_write(i2c_ad

[PATCH 09/11] cmd: eeprom: Refactor command execution into function by action

2024-05-21 Thread Marek Behún
Refactor the eeprom_execute_command() function into separate functions
do_eeprom_rw(), do_eeprom_print() and do_eeprom_update().

Signed-off-by: Marek Behún 
---
 cmd/eeprom.c | 111 ---
 1 file changed, 71 insertions(+), 40 deletions(-)

diff --git a/cmd/eeprom.c b/cmd/eeprom.c
index e29639780d..c76cf43157 100644
--- a/cmd/eeprom.c
+++ b/cmd/eeprom.c
@@ -288,61 +288,75 @@ static enum eeprom_action parse_action(char *cmd)
return EEPROM_ACTION_INVALID;
 }
 
-static int eeprom_execute_command(enum eeprom_action action,
- struct eeprom_dev_spec *dev,
- int layout_ver, char *key, char *value,
- ulong addr, ulong off, ulong cnt)
+static int do_eeprom_rw(struct eeprom_dev_spec *dev, bool read,
+   ulong addr, ulong off, ulong cnt)
 {
-   int rcode = 0;
const char *const fmt =
"\nEEPROM @0x%lX %s: addr 0x%08lx  off 0x%04lx  count %ld ... ";
+   uchar *memloc = (uchar *)addr;
+   int ret;
+
+   printf(fmt, dev->i2c_addr, read ? "read" : "write", addr, off, cnt);
+   if (read)
+   ret = eeprom_read(dev->i2c_addr, off, memloc, cnt);
+   else
+   ret = eeprom_write(dev->i2c_addr, off, memloc, cnt);
+   puts("done\n");
+
+   return ret;
+}
+
 #ifdef CONFIG_CMD_EEPROM_LAYOUT
-   struct eeprom_layout layout;
-#endif
 
-   if (action == EEPROM_ACTION_INVALID)
-   return CMD_RET_USAGE;
+static int do_eeprom_layout(struct eeprom_dev_spec *dev, int layout_ver,
+   struct eeprom_layout *layout)
+{
+   int ret;
 
-   eeprom_init(dev->i2c_bus);
-   if (action == EEPROM_READ) {
-   printf(fmt, dev->i2c_addr, "read", addr, off, cnt);
+   ret = eeprom_read(dev->i2c_addr, 0, eeprom_buf, CONFIG_SYS_EEPROM_SIZE);
+   if (ret)
+   return ret;
 
-   rcode = eeprom_read(dev->i2c_addr, off, (uchar *)addr, cnt);
+   eeprom_layout_setup(layout, eeprom_buf, CONFIG_SYS_EEPROM_SIZE,
+   layout_ver);
 
-   puts("done\n");
-   return rcode;
-   } else if (action == EEPROM_WRITE) {
-   printf(fmt, dev->i2c_addr, "write", addr, off, cnt);
+   return 0;
+}
 
-   rcode = eeprom_write(dev->i2c_addr, off, (uchar *)addr, cnt);
+static int do_eeprom_print(struct eeprom_dev_spec *dev, int layout_ver)
+{
+   struct eeprom_layout layout;
+   int ret;
 
-   puts("done\n");
-   return rcode;
-   }
+   ret = do_eeprom_layout(dev, layout_ver, );
+   if (ret)
+   return ret;
 
-#ifdef CONFIG_CMD_EEPROM_LAYOUT
-   rcode = eeprom_read(dev->i2c_addr, 0, eeprom_buf,
-   CONFIG_SYS_EEPROM_SIZE);
-   if (rcode < 0)
-   return rcode;
+   layout.print();
 
-   eeprom_layout_setup(, eeprom_buf, CONFIG_SYS_EEPROM_SIZE,
-   layout_ver);
+   return 0;
+}
 
-   if (action == EEPROM_PRINT) {
-   layout.print();
-   return 0;
-   }
+static int do_eeprom_update(struct eeprom_dev_spec *dev, int layout_ver,
+   char *key, char *value)
+{
+   struct eeprom_layout layout;
+   int ret;
 
-   layout.update(, key, value);
+   ret = do_eeprom_layout(dev, layout_ver, );
+   if (ret)
+   return ret;
 
-   rcode = eeprom_write(dev->i2c_addr, 0, layout.data,
-CONFIG_SYS_EEPROM_SIZE);
-#endif
+   ret = layout.update(, key, value);
+   if (ret)
+   return CMD_RET_FAILURE;
 
-   return rcode;
+   return eeprom_write(dev->i2c_addr, 0, layout.data,
+   CONFIG_SYS_EEPROM_SIZE);
 }
 
+#endif
+
 static int eeprom_action_expected_argc(enum eeprom_action action)
 {
switch (action) {
@@ -361,13 +375,15 @@ static int eeprom_action_expected_argc(enum eeprom_action 
action)
 #define NEXT_PARAM(argc, index){ (argc)--; (index)++; }
 int do_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-   int layout_ver = LAYOUT_VERSION_AUTODETECT;
enum eeprom_action action = EEPROM_ACTION_INVALID;
struct eeprom_dev_spec dev;
ulong addr = 0, cnt = 0, off = 0;
int ret, index = 0;
+#ifdef CONFIG_CMD_EEPROM_LAYOUT
char *field_name = "";
char *field_value = "";
+   int layout_ver = LAYOUT_VERSION_AUTODETECT;
+#endif
 
if (argc <= 1)
return CMD_RET_USAGE;
@@ -416,8 +432,23 @@ int do_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
}
 #endif
 
-   return eeprom_execute_command(action, , layout_v

[PATCH 07/11] cmd: eeprom: Deduplicate parse_i2c_bus_addr() calls

2024-05-21 Thread Marek Behún
Deduplicate the calls to parse_i2c_bus_addr().

Signed-off-by: Marek Behún 
---
 cmd/eeprom.c | 36 +---
 1 file changed, 17 insertions(+), 19 deletions(-)

diff --git a/cmd/eeprom.c b/cmd/eeprom.c
index d610dc9931..12902e812e 100644
--- a/cmd/eeprom.c
+++ b/cmd/eeprom.c
@@ -339,6 +339,21 @@ static int eeprom_execute_command(enum eeprom_action 
action, int i2c_bus,
return rcode;
 }
 
+static int eeprom_action_expected_argc(enum eeprom_action action)
+{
+   switch (action) {
+   case EEPROM_READ:
+   case EEPROM_WRITE:
+   return 3;
+   case EEPROM_PRINT:
+   return 0;
+   case EEPROM_UPDATE:
+   return 2;
+   default:
+   return CMD_RET_USAGE;
+   }
+}
+
 #define NEXT_PARAM(argc, index){ (argc)--; (index)++; }
 int do_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
@@ -371,25 +386,8 @@ int do_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
}
 #endif
 
-   switch (action) {
-   case EEPROM_READ:
-   case EEPROM_WRITE:
-   ret = parse_i2c_bus_addr(_bus, _addr, argc,
-argv + index, 3);
-   break;
-   case EEPROM_PRINT:
-   ret = parse_i2c_bus_addr(_bus, _addr, argc,
-argv + index, 0);
-   break;
-   case EEPROM_UPDATE:
-   ret = parse_i2c_bus_addr(_bus, _addr, argc,
-argv + index, 2);
-   break;
-   default:
-   /* Get compiler to stop whining */
-   return CMD_RET_USAGE;
-   }
-
+   ret = parse_i2c_bus_addr(_bus, _addr, argc, argv + index,
+eeprom_action_expected_argc(action));
if (ret == CMD_RET_USAGE)
return ret;
 
-- 
2.44.1



[PATCH 06/11] cmd: eeprom: Hide eeprom layout versioning behind a Kconfig option

2024-05-21 Thread Marek Behún
Add a new Kconfig option EEPROM_LAYOUT_VERSIONS, and hide eeprom
layout versionsing code behind it. Only print the relevant help in
'eeprom' command usage if this option is enabled.

Enable this new option for cm_fx6_defconfig and cm_t43_defconfig.
These are the only boards using EEPROM layout versioning.

Signed-off-by: Marek Behún 
---
 cmd/Kconfig  |  9 -
 cmd/eeprom.c | 20 +++-
 configs/cm_fx6_defconfig |  1 +
 configs/cm_t43_defconfig |  1 +
 4 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/cmd/Kconfig b/cmd/Kconfig
index b026439c77..8c370993f6 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -803,9 +803,16 @@ config CMD_EEPROM_LAYOUT
types of eeprom fields. Can be used for defining
custom layouts.
 
+config EEPROM_LAYOUT_VERSIONS
+   bool "Support specifying eeprom layout version"
+   depends on CMD_EEPROM_LAYOUT
+   help
+ Support specifying eeprom layout version in the 'eeprom' command
+ via the -l option.
+
 config EEPROM_LAYOUT_HELP_STRING
  string "Tells user what layout names are supported"
- depends on CMD_EEPROM_LAYOUT
+ depends on EEPROM_LAYOUT_VERSIONS
  default ""
  help
Help printed with the LAYOUT VERSIONS part of the 'eeprom'
diff --git a/cmd/eeprom.c b/cmd/eeprom.c
index 0d604832e4..d610dc9931 100644
--- a/cmd/eeprom.c
+++ b/cmd/eeprom.c
@@ -252,10 +252,12 @@ static int parse_i2c_bus_addr(int *i2c_bus, ulong 
*i2c_addr, int argc,
 
 #ifdef CONFIG_CMD_EEPROM_LAYOUT
 
+#ifdef CONFIG_EEPROM_LAYOUT_VERSIONS
 __weak int eeprom_parse_layout_version(char *str)
 {
return LAYOUT_VERSION_UNRECOGNIZED;
 }
+#endif
 
 static unsigned char eeprom_buf[CONFIG_SYS_EEPROM_SIZE];
 
@@ -359,7 +361,7 @@ int do_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
if (action == EEPROM_ACTION_INVALID)
return CMD_RET_USAGE;
 
-#ifdef CONFIG_CMD_EEPROM_LAYOUT
+#ifdef CONFIG_EEPROM_LAYOUT_VERSIONS
if (action == EEPROM_PRINT || action == EEPROM_UPDATE) {
if (!strcmp(argv[index], "-l")) {
NEXT_PARAM(argc, index);
@@ -415,6 +417,12 @@ int do_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
  field_name, field_value, addr, off, cnt);
 }
 
+#ifdef CONFIG_EEPROM_LAYOUT_VERSIONS
+#define EEPROM_LAYOUT_SPEC "[-l ] "
+#else
+#define EEPROM_LAYOUT_SPEC ""
+#endif
+
 U_BOOT_CMD(
eeprom, 8,  1,  do_eeprom,
"EEPROM sub-system",
@@ -423,16 +431,18 @@ U_BOOT_CMD(
"   - read/write `cnt' bytes from `devaddr` EEPROM at offset `off'"
 #ifdef CONFIG_CMD_EEPROM_LAYOUT
"\n"
-   "eeprom print [-l ] [[bus] devaddr]\n"
+   "eeprom print " EEPROM_LAYOUT_SPEC "[[bus] devaddr]\n"
"   - Print layout fields and their data in human readable format\n"
-   "eeprom update [-l ] [[bus] devaddr] field_name 
field_value\n"
+   "eeprom update " EEPROM_LAYOUT_SPEC "[[bus] devaddr] field_name 
field_value\n"
"   - Update a specific eeprom field with new data.\n"
-   " The new data must be written in the same human readable 
format as shown by the print command.\n"
-   "\n"
+   " The new data must be written in the same human readable 
format as shown by the print command."
+#ifdef CONFIG_EEPROM_LAYOUT_VERSIONS
+   "\n\n"
"LAYOUT VERSIONS\n"
"The -l option can be used to force the command to interpret the EEPROM 
data using the chosen layout.\n"
"If the -l option is omitted, the command will auto detect the layout 
based on the data in the EEPROM.\n"
"The values which can be provided with the -l option are:\n"
CONFIG_EEPROM_LAYOUT_HELP_STRING"\n"
 #endif
+#endif
 );
diff --git a/configs/cm_fx6_defconfig b/configs/cm_fx6_defconfig
index a4d5f91b35..386616cc42 100644
--- a/configs/cm_fx6_defconfig
+++ b/configs/cm_fx6_defconfig
@@ -46,6 +46,7 @@ CONFIG_SYS_MAXARGS=32
 CONFIG_CMD_GREPENV=y
 CONFIG_CMD_EEPROM=y
 CONFIG_CMD_EEPROM_LAYOUT=y
+CONFIG_EEPROM_LAYOUT_VERSIONS=y
 CONFIG_EEPROM_LAYOUT_HELP_STRING="v2, v3"
 CONFIG_SYS_I2C_EEPROM_BUS=2
 CONFIG_SYS_EEPROM_PAGE_WRITE_BITS=4
diff --git a/configs/cm_t43_defconfig b/configs/cm_t43_defconfig
index 93e667292c..32f126a517 100644
--- a/configs/cm_t43_defconfig
+++ b/configs/cm_t43_defconfig
@@ -50,6 +50,7 @@ CONFIG_SYS_PROMPT="CM-T43 # "
 CONFIG_CMD_ASKENV=y
 CONFIG_CMD_EEPROM=y
 CONFIG_CMD_EEPROM_LAYOUT=y
+CONFIG_EEPROM_LAYOUT_VERSIONS=y
 CONFIG_EEPROM_LAYOUT_HELP_STRING="v2, v3"
 CONFIG_SYS_EEPROM_PAGE_WRITE_BITS=4
 CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS=5
-- 
2.44.1



[PATCH 05/11] cmd: eeprom: Fix usage help for the eeprom command

2024-05-21 Thread Marek Behún
The bus and devaddr arguments of the eeprom command are optional, and if
only one is given, it is assumed to be devaddr. Change the usage help
from
   
to
  [[bus] [devaddr]

Signed-off-by: Marek Behún 
---
 cmd/eeprom.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/cmd/eeprom.c b/cmd/eeprom.c
index 322765ad02..0d604832e4 100644
--- a/cmd/eeprom.c
+++ b/cmd/eeprom.c
@@ -418,14 +418,14 @@ int do_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
 U_BOOT_CMD(
eeprom, 8,  1,  do_eeprom,
"EEPROM sub-system",
-   "readaddr off cnt\n"
-   "eeprom write   addr off cnt\n"
+   "read  [[bus] devaddr] addr off cnt\n"
+   "eeprom write [[bus] devaddr] addr off cnt\n"
"   - read/write `cnt' bytes from `devaddr` EEPROM at offset `off'"
 #ifdef CONFIG_CMD_EEPROM_LAYOUT
"\n"
-   "eeprom print [-l ]  \n"
+   "eeprom print [-l ] [[bus] devaddr]\n"
"   - Print layout fields and their data in human readable format\n"
-   "eeprom update [-l ]   field_name 
field_value\n"
+   "eeprom update [-l ] [[bus] devaddr] field_name 
field_value\n"
"   - Update a specific eeprom field with new data.\n"
" The new data must be written in the same human readable 
format as shown by the print command.\n"
"\n"
-- 
2.44.1



[PATCH 04/11] common: eeprom_field: Drop unnecessary comparison

2024-05-21 Thread Marek Behún
The byte variable is of type unsigned char, it is never less than zero.
The error case is handled by *endptr, so drop the comparison altogether.

Signed-off-by: Marek Behún 
---
 common/eeprom/eeprom_field.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/eeprom/eeprom_field.c b/common/eeprom/eeprom_field.c
index 9b831414a4..26f6041e54 100644
--- a/common/eeprom/eeprom_field.c
+++ b/common/eeprom/eeprom_field.c
@@ -56,7 +56,7 @@ static int __eeprom_field_update_bin(struct eeprom_field 
*field,
}
 
byte = simple_strtoul(tmp, , 16);
-   if (*endptr != '\0' || byte < 0)
+   if (*endptr != '\0')
return -1;
 
field->buf[j] = byte;
-- 
2.44.1



[PATCH 03/11] common: eeprom_field: Fix updating binary field

2024-05-21 Thread Marek Behún
The __eeprom_field_update_bin() function is expected to parse a hex
string into bytes (potentially in reverse order), but the
simple_strtoul() function is given 0 as base. This does not work since
the string does not contain '0x' prefix. Add explicit base 16.

Signed-off-by: Marek Behún 
---
 common/eeprom/eeprom_field.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/eeprom/eeprom_field.c b/common/eeprom/eeprom_field.c
index f56eebe679..9b831414a4 100644
--- a/common/eeprom/eeprom_field.c
+++ b/common/eeprom/eeprom_field.c
@@ -55,7 +55,7 @@ static int __eeprom_field_update_bin(struct eeprom_field 
*field,
tmp[k] = value[reverse ? i - 1 + k : i + k];
}
 
-   byte = simple_strtoul(tmp, , 0);
+   byte = simple_strtoul(tmp, , 16);
if (*endptr != '\0' || byte < 0)
return -1;
 
-- 
2.44.1



[PATCH 02/11] common: eeprom_layout: Split field finding code from the field update function

2024-05-21 Thread Marek Behún
Split the eeprom layout field finding code from the
eeprom_layout_update_field() function in order to make it usable in
alternative implementations of update method.

Signed-off-by: Marek Behún 
---
 common/eeprom/eeprom_layout.c | 46 +++
 include/eeprom_layout.h   |  4 +++
 2 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/common/eeprom/eeprom_layout.c b/common/eeprom/eeprom_layout.c
index 406db3f7d1..801e90d38d 100644
--- a/common/eeprom/eeprom_layout.c
+++ b/common/eeprom/eeprom_layout.c
@@ -56,6 +56,28 @@ static void eeprom_layout_print(const struct eeprom_layout 
*layout)
fields[i].print([i]);
 }
 
+/*
+ * eeprom_layout_find_field() - finds a layout field by name
+ * @layout:A pointer to an existing struct layout.
+ * @field_name:The name of the field to update.
+ * @warn:  Whether to print a warning if the field is not found.
+ *
+ * Returns: a pointer to the found field or NULL on failure.
+ */
+struct eeprom_field *eeprom_layout_find_field(struct eeprom_layout *layout,
+ char *field_name, bool warn)
+{
+   for (int i = 0; i < layout->num_of_fields; i++)
+   if (layout->fields[i].name != RESERVED_FIELDS &&
+   !strcmp(layout->fields[i].name, field_name))
+   return >fields[i];
+
+   if (warn)
+   printf("No such field '%s'\n", field_name);
+
+   return NULL;
+}
+
 /*
  * eeprom_layout_update_field() - update a single field in the layout data.
  * @layout:A pointer to an existing struct layout.
@@ -67,8 +89,8 @@ static void eeprom_layout_print(const struct eeprom_layout 
*layout)
 static int eeprom_layout_update_field(struct eeprom_layout *layout,
  char *field_name, char *new_data)
 {
-   int i, err;
-   struct eeprom_field *fields = layout->fields;
+   struct eeprom_field *field;
+   int err;
 
if (new_data == NULL)
return 0;
@@ -76,21 +98,15 @@ static int eeprom_layout_update_field(struct eeprom_layout 
*layout,
if (field_name == NULL)
return -1;
 
-   for (i = 0; i < layout->num_of_fields; i++) {
-   if (fields[i].name == RESERVED_FIELDS ||
-   strcmp(fields[i].name, field_name))
-   continue;
-
-   err = fields[i].update([i], new_data);
-   if (err)
-   printf("Invalid data for field %s\n", field_name);
-
-   return err;
-   }
+   field = eeprom_layout_find_field(layout, field_name, true);
+   if (field == NULL)
+   return -1;
 
-   printf("No such field '%s'\n", field_name);
+   err = field->update(field, new_data);
+   if (err)
+   printf("Invalid data for field %s\n", field_name);
 
-   return -1;
+   return err;
 }
 
 /*
diff --git a/include/eeprom_layout.h b/include/eeprom_layout.h
index 730d963ab9..b1d6220595 100644
--- a/include/eeprom_layout.h
+++ b/include/eeprom_layout.h
@@ -9,6 +9,8 @@
 #ifndef _LAYOUT_
 #define _LAYOUT_
 
+#include 
+
 #define RESERVED_FIELDSNULL
 #define LAYOUT_VERSION_UNRECOGNIZED-1
 #define LAYOUT_VERSION_AUTODETECT  -2
@@ -24,6 +26,8 @@ struct eeprom_layout {
  char *new_data);
 };
 
+struct eeprom_field *eeprom_layout_find_field(struct eeprom_layout *layout,
+ char *field_name, bool warn);
 void eeprom_layout_setup(struct eeprom_layout *layout, unsigned char *buf,
 unsigned int buf_size, int layout_version);
 __weak void __eeprom_layout_assign(struct eeprom_layout *layout,
-- 
2.44.1



[PATCH 01/11] common: eeprom_layout: Assign default layout methods and parameters before specific ones

2024-05-21 Thread Marek Behún
Assign the default eeprom layout parameter .data_size and methods
.print() and .update() before calling eeprom_layout_assign() in
eeprom_layout_setup().

This allows eeprom_layout_assign() to overwrite these if needed.

Signed-off-by: Marek Behún 
---
 common/eeprom/eeprom_layout.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/common/eeprom/eeprom_layout.c b/common/eeprom/eeprom_layout.c
index 5a9be1da06..406db3f7d1 100644
--- a/common/eeprom/eeprom_layout.c
+++ b/common/eeprom/eeprom_layout.c
@@ -111,14 +111,14 @@ void eeprom_layout_setup(struct eeprom_layout *layout, 
unsigned char *buf,
else
layout->layout_version = layout_version;
 
+   layout->data_size = buf_size;
+   layout->print = eeprom_layout_print;
+   layout->update = eeprom_layout_update_field;
+
eeprom_layout_assign(layout, layout_version);
layout->data = buf;
for (i = 0; i < layout->num_of_fields; i++) {
layout->fields[i].buf = buf;
buf += layout->fields[i].size;
}
-
-   layout->data_size = buf_size;
-   layout->print = eeprom_layout_print;
-   layout->update = eeprom_layout_update_field;
 }
-- 
2.44.1



[PATCH 00/11] 'eeprom' command improvements

2024-05-21 Thread Marek Behún
Hi Tom,

this series contains improvements for the 'eeprom' command:
- refactors
- fixes
- improvements
- ability to use driver model EEPROMs (uclass UCLASS_I2C_EEPROM)
- more flexible EEPROM layout support

It should not cause any behavior change for any existing board.

This series is a dependency for some DDR issue fixes for Turris Omnia.
I will be sending that one separately.

github PR link (with CI):
  https://github.com/u-boot/u-boot/pull/540
- there is a failure for
test.py for sandbox sandbox_clang
  but it seems unrelated to these changes

Marek Behún (11):
  common: eeprom_layout: Assign default layout methods and parameters
before specific ones
  common: eeprom_layout: Split field finding code from the field update
function
  common: eeprom_field: Fix updating binary field
  common: eeprom_field: Drop unnecessary comparison
  cmd: eeprom: Fix usage help for the eeprom command
  cmd: eeprom: Hide eeprom layout versioning behind a Kconfig option
  cmd: eeprom: Deduplicate parse_i2c_bus_addr() calls
  cmd: eeprom: Refactor eeprom device specifier parsing
  cmd: eeprom: Refactor command execution into function by action
  cmd: eeprom: Don't read/write whole EEPROM if not necessary
  cmd: eeprom: Extend to EEPROMs probed via driver model

 cmd/Kconfig   |   9 +-
 cmd/eeprom.c  | 305 +-
 common/eeprom/eeprom_field.c  |   4 +-
 common/eeprom/eeprom_layout.c |  54 +++---
 configs/cm_fx6_defconfig  |   1 +
 configs/cm_t43_defconfig  |   1 +
 include/eeprom_layout.h   |   4 +
 7 files changed, 273 insertions(+), 105 deletions(-)

-- 
2.44.1



Re: [PATCH u-boot-mvebu 10/10] arm: mvebu: turris_omnia: Support old DDR3 training, selectable via env var

2024-05-15 Thread Marek Behún
On Wed, 15 May 2024 11:10:09 +0200
Stefan Roese  wrote:

> Hi Marek,
> 
> On 5/15/24 10:59, Marek Behún wrote:
> > On Mon, 6 May 2024 12:03:55 +0200
> > Stefan Roese  wrote:
> >   
> >> Hi Marek,
> >>
> >> On 4/15/24 18:30, Marek Behún wrote:  
> >>> Support old DDR3 training code on Turris Omnia, selectable by U-Boot
> >>> enviroment variable.
> >>>
> >>> Users experiencing DDR3 initialization failures or random crashes of the
> >>> operating system due to incorrect DDR3 configuration can select the old
> >>> DDR3 training implementation to fix those issues by setting the
> >>> environment variable
> >>> env set omnia_ddr3_training old
> >>> env save
> >>>
> >>> Signed-off-by: Marek Behún 
> >>> ---
> >>>arch/arm/mach-mvebu/Kconfig   |  1 +
> >>>board/CZ.NIC/turris_omnia/Makefile|  1 +
> >>>board/CZ.NIC/turris_omnia/old_ddr3_training.c | 79 +++
> >>>board/CZ.NIC/turris_omnia/turris_omnia.c  |  2 +-
> >>>4 files changed, 82 insertions(+), 1 deletion(-)
> >>>create mode 100644 board/CZ.NIC/turris_omnia/old_ddr3_training.c  
> >>
> >> For turris_omnia_defconfig, this is dropped when compiled:
> >>
> >> drivers/ddr/marvell/a38x/old/ddr3_debug.c:776:12: warning:
> >> 'ddr3_tip_access_atr' declared 'static' but never defined
> >> [-Wunused-function]
> >> 776 | static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32
> >> value, u32 **ptr);
> >> |^~~  
> > 
> > And it also seems that there is still something wrong with this
> > old DDR training code port. Some boards still experience random bugs
> > with this, but not with the U-Boot from 2015. :-(  
> 
> Hmmm, strange.
> 
> How to continue? Are these "old DDR training patches" on hold for now?

The first 5 patches should be fine, the "old DDR training" comes in the
second half. Is it possible to merge only the first 5? And also the one
patch I sent on April 30:
  arm: mvebu: turris_omnia: Fix ethernet PHY reset gpio FDT fixup

Marek


Re: [PATCH u-boot-mvebu 10/10] arm: mvebu: turris_omnia: Support old DDR3 training, selectable via env var

2024-05-15 Thread Marek Behún
On Mon, 6 May 2024 12:03:55 +0200
Stefan Roese  wrote:

> Hi Marek,
> 
> On 4/15/24 18:30, Marek Behún wrote:
> > Support old DDR3 training code on Turris Omnia, selectable by U-Boot
> > enviroment variable.
> > 
> > Users experiencing DDR3 initialization failures or random crashes of the
> > operating system due to incorrect DDR3 configuration can select the old
> > DDR3 training implementation to fix those issues by setting the
> > environment variable
> >env set omnia_ddr3_training old
> >env save
> > 
> > Signed-off-by: Marek Behún 
> > ---
> >   arch/arm/mach-mvebu/Kconfig   |  1 +
> >   board/CZ.NIC/turris_omnia/Makefile|  1 +
> >   board/CZ.NIC/turris_omnia/old_ddr3_training.c | 79 +++
> >   board/CZ.NIC/turris_omnia/turris_omnia.c  |  2 +-
> >   4 files changed, 82 insertions(+), 1 deletion(-)
> >   create mode 100644 board/CZ.NIC/turris_omnia/old_ddr3_training.c  
> 
> For turris_omnia_defconfig, this is dropped when compiled:
> 
> drivers/ddr/marvell/a38x/old/ddr3_debug.c:776:12: warning: 
> 'ddr3_tip_access_atr' declared 'static' but never defined 
> [-Wunused-function]
>776 | static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 
> value, u32 **ptr);
>|^~~

And it also seems that there is still something wrong with this
old DDR training code port. Some boards still experience random bugs
with this, but not with the U-Boot from 2015. :-(


Re: [PATCH 0/3] Add eFuse access for ZynqMP

2024-05-15 Thread Marek Behún
On Tue, 14 May 2024 16:04:13 +0200
lukas.funke-...@weidmueller.com wrote:

> From: Lukas Funke 
> 
> 
> This series adds a driver to read and write ZynqMP eFuses [1]. The
> driver can be accessed by the 'efuse_read' and 'efuse_write' subcommands
> of the 'zynqmp' command.

Vendor specific commands aren't great.

There is the 'fuse' command in u-boot. You need to implement the
  fuse_read()
  fuse_sense()
  fuse_prog()
  fuse_override()
functions.

See for example arch/arm/mach-mvebu/efuse.c, or other implementations.

Please don't invent new vendor specific commands in new code, it is an
antipattern.

Marek


[PATCH u-boot-mvebu] arm: mvebu: turris_omnia: Fix ethernet PHY reset gpio FDT fixup

2024-04-30 Thread Marek Behún
For board revisions where the WAN ethernet PHY reset GPIO is controllable
via MCU we currently insert a phy-reset-gpios property into the ethernet
controller node. The mvneta driver parses this property and uses the
GPIO to reset the PHY.

But this phy-reset-gpios property is not a valid DT binding in upstream
kernel. Instead, a reset-gpios property should be inserted into the
ethernet PHY node. This correct DT binding is supported by the DM ETH PHY
U-Boot driver.

Insert the reset-gpios property into the WAN PHY node instead the
phy-reset-gpios property in WAN ETH node so that Linux will correctly use
the reset GPIO.

Enable the CONFIG_DM_ETH_PHY config option so that U-Boot will also use
the correct DT property.

Note: currently there are 4 ethernet controller drivers parsing the
wrong DT property: dwc_eth_qos, fex_mxc, mvneta and mvpp2. We should
convert all relevant device-trees to use reset-gpios so that we can get
rid of these drivers parsing this property.

Fixes: 1da53ae26afc ("arm: mvebu: turris_omnia: Add support for design with SW 
reset signals")
Signed-off-by: Marek Behún 
---
 board/CZ.NIC/turris_omnia/turris_omnia.c | 44 ++--
 configs/turris_omnia_defconfig   |  1 +
 2 files changed, 26 insertions(+), 19 deletions(-)

diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index 3b7a71bdad..448655c294 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -978,11 +978,21 @@ static int fixup_mcu_gpio_in_pcie_nodes(void *blob)
return 0;
 }
 
-static int fixup_mcu_gpio_in_eth_wan_node(void *blob)
+static int get_phy_wan_node_offset(const void *blob)
+{
+   u32 phy_wan_phandle;
+
+   phy_wan_phandle = fdt_getprop_u32_default(blob, "ethernet2", 
"phy-handle", 0);
+   if (!phy_wan_phandle)
+   return -FDT_ERR_NOTFOUND;
+
+   return fdt_node_offset_by_phandle(blob, phy_wan_phandle);
+}
+
+static int fixup_mcu_gpio_in_phy_wan_node(void *blob)
 {
unsigned int mcu_phandle;
-   int eth_wan_node;
-   int ret;
+   int phy_wan_node, ret;
 
ret = fdt_increase_size(blob, 64);
if (ret < 0) {
@@ -990,21 +1000,17 @@ static int fixup_mcu_gpio_in_eth_wan_node(void *blob)
return ret;
}
 
-   eth_wan_node = fdt_path_offset(blob, "ethernet2");
-   if (eth_wan_node < 0)
-   return eth_wan_node;
+   phy_wan_node = get_phy_wan_node_offset(blob);
+   if (phy_wan_node < 0)
+   return phy_wan_node;
 
mcu_phandle = fdt_create_phandle_by_compatible(blob, 
"cznic,turris-omnia-mcu");
if (!mcu_phandle)
return -FDT_ERR_NOPHANDLES;
 
-   /* insert: phy-reset-gpios = < 2 gpio GPIO_ACTIVE_LOW>; */
-   ret = insert_mcu_gpio_prop(blob, eth_wan_node, "phy-reset-gpios",
-  mcu_phandle, 2, ilog2(EXT_CTL_nRES_PHY), 
GPIO_ACTIVE_LOW);
-   if (ret < 0)
-   return ret;
-
-   return 0;
+   /* insert: reset-gpios = < 2 gpio GPIO_ACTIVE_LOW>; */
+   return insert_mcu_gpio_prop(blob, phy_wan_node, "reset-gpios",
+   mcu_phandle, 2, ilog2(EXT_CTL_nRES_PHY), 
GPIO_ACTIVE_LOW);
 }
 
 static void fixup_atsha_node(void *blob)
@@ -1033,7 +1039,7 @@ int board_fix_fdt(void *blob)
 {
if (omnia_mcu_has_feature(FEAT_PERIPH_MCU)) {
fixup_mcu_gpio_in_pcie_nodes(blob);
-   fixup_mcu_gpio_in_eth_wan_node(blob);
+   fixup_mcu_gpio_in_phy_wan_node(blob);
}
 
fixup_msata_port_nodes(blob);
@@ -1218,14 +1224,14 @@ int ft_board_setup(void *blob, struct bd_info *bd)
int node;
 
/*
-* U-Boot's FDT blob contains phy-reset-gpios in ethernet2
-* node when MCU controls all peripherals resets.
+* U-Boot's FDT blob contains reset-gpios in ethernet2 PHY node when MCU
+* controls all peripherals resets.
 * Fixup MCU GPIO nodes in PCIe and eth wan nodes in this case.
 */
-   node = fdt_path_offset(gd->fdt_blob, "ethernet2");
-   if (node >= 0 && fdt_getprop(gd->fdt_blob, node, "phy-reset-gpios", 
NULL)) {
+   node = get_phy_wan_node_offset(gd->fdt_blob);
+   if (node >= 0 && fdt_getprop(gd->fdt_blob, node, "reset-gpios", NULL)) {
fixup_mcu_gpio_in_pcie_nodes(blob);
-   fixup_mcu_gpio_in_eth_wan_node(blob);
+   fixup_mcu_gpio_in_phy_wan_node(blob);
}
 
fixup_spi_nor_partitions(blob);
diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 11256be8dd..d7005e7334 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -100,6 +100,7 @@ CONFIG_SPI_FLASH_MTD=y
 CONFIG_PHY_MARVELL=y
 CONFIG_PHY_FIXED=y
 CONFIG_DM_DSA=y
+CONFIG_DM_ETH_PHY=y
 CONFIG_PHY_GIGE=y
 CONFIG_MV88E6XXX=y
 CONFIG_MVNETA=y
-- 
2.43.2



Re: [PATCH v2 5/5] common: Convert *.c/h from UTF-8 to ASCII enconfing

2024-04-16 Thread Marek Behún
Acked-by: Marek Behún 


Re: [PATCH u-boot-mvebu 00/10] Turris Omnia DDR training changes

2024-04-16 Thread Marek Behún
Hi Tony,

hmm no I did not change the version number.

The changes are only relevant for debug messages, there is no
functional changes in how the DDR training is done, unless I made a
mistake.

I am not sure that changing the version is a good idea unless this is
also done for the upstream where I sent the PR. But who knows if
Marvell will have some people assigned to merge the PR.

Since U-Boot prints its own version, people can easily reproduce the
code for a given binary from U-Boot version string.

Marek

On Mon, 15 Apr 2024 15:20:49 -0700
Tony Dinh  wrote:

> Hi Marek,
> 
> I'm running a regression test with this patch on another Armada 385
> board (Synology DS116). And
> it is running without problem.
> 
> I noticed that there is no version bump. Is this still 14.0.0? It's kind of
> hard to see which version we are using without a minor revision such as 
> 14.0.1.
> 
> All the best,
> Tony
> 
> On Mon, Apr 15, 2024 at 9:39 AM Marek Behún  wrote:
> >
> > Hi Stefan,
> >
> > this series adds some changes to DDR3 training for Armada 38x and
> > Turris Omnia.
> >
> > - patches 1-4 are meant to allow for reducing another 10 KiB in the
> >   SPL binary. They were also sent to mv-ddr-marvell, via PR on github,
> >   https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell/pull/45/
> >   but I am told that Armada team has left Marvell, so who knows if this
> >   will ever be merged there
> > - patch 5 enables this reduction for Turris Omnia
> > - patches 6-8 import old DDR3 training code and make some changes so
> >   that it works with U-Boot. The reason why this is being done is
> >   explained in patch 6
> > - patch 9 glues the old DDR3 training code to current U-Boot
> > - patch 10 allows for dynamic selection of old DDR3 training code on
> >   Turris Omnia, via an U-Boot environment variable
> >
> > Marek
> >
> > Marek Behún (10):
> >   ddr: marvell: a38x: debug: return from ddr3_tip_print_log() early if
> > we won't print anything
> >   ddr: marvell: a38x: debug: Remove unused variables
> >   ddr: marvell: a38x: debug: Define DDR_VIEWER_TOOL variables only if
> > needed, and make them static
> >   ddr: marvell: a38x: debug: Allow compiling with immutable debug
> > settings to reduce binary size
> >   arm: mvebu: turris_omnia: Enable immutable debug settings in DDR3
> > training by default
> >   ddr: marvell: a38x: Import old DDR training code from 2017 version of
> > U-Boot
> >   ddr: marvell: a38x: old: Fix some compiler warning of the old code
> >   ddr: marvell: a38x: old: Backport immutable debug settings
> >   arm: mvebu: a38x: Add optional support for using old DDR3 training
> > code
> >   arm: mvebu: turris_omnia: Support old DDR3 training, selectable via
> > env var
> >
> >  arch/arm/mach-mvebu/Kconfig   |   15 +
> >  arch/arm/mach-mvebu/include/mach/cpu.h|1 +
> >  arch/arm/mach-mvebu/spl.c |   37 +-
> >  board/CZ.NIC/turris_omnia/Makefile|1 +
> >  board/CZ.NIC/turris_omnia/old_ddr3_training.c |   79 +
> >  board/CZ.NIC/turris_omnia/turris_omnia.c  |2 +-
> >  configs/turris_omnia_defconfig|1 +
> >  drivers/ddr/marvell/a38x/Makefile |2 +
> >  drivers/ddr/marvell/a38x/ddr3_debug.c |   30 +-
> >  drivers/ddr/marvell/a38x/ddr3_init.c  |3 +-
> >  drivers/ddr/marvell/a38x/ddr3_init.h  |   43 +-
> >  drivers/ddr/marvell/a38x/old/Makefile |   29 +
> >  drivers/ddr/marvell/a38x/old/ddr3_a38x.c  |  738 +
> >  drivers/ddr/marvell/a38x/old/ddr3_a38x.h  |   93 +
> >  .../marvell/a38x/old/ddr3_a38x_mc_static.h|  226 ++
> >  .../ddr/marvell/a38x/old/ddr3_a38x_topology.h |   22 +
> >  .../ddr/marvell/a38x/old/ddr3_a38x_training.c |   40 +
> >  drivers/ddr/marvell/a38x/old/ddr3_debug.c | 1545 ++
> >  .../marvell/a38x/old/ddr3_hws_hw_training.c   |  148 +
> >  .../marvell/a38x/old/ddr3_hws_hw_training.h   |   49 +
> >  .../a38x/old/ddr3_hws_hw_training_def.h   |  464 +++
> >  .../marvell/a38x/old/ddr3_hws_sil_training.h  |   17 +
> >  drivers/ddr/marvell/a38x/old/ddr3_init.c  |  770 +
> >  drivers/ddr/marvell/a38x/old/ddr3_init.h  |  405 +++
> >  .../ddr/marvell/a38x/old/ddr3_logging_def.h   |  101 +
> >  .../marvell/a38x/old/ddr3_patterns_64bit.h|  924 ++
> >  .../ddr/marvell/a38x/old/ddr3_topology_def.h  |   76 +
> >  drivers/ddr/marvell/a38x/old/ddr3_training.c  | 2651 +
> >  .../ddr/marvell/a38x/old/ddr3

[PATCH u-boot-mvebu 10/10] arm: mvebu: turris_omnia: Support old DDR3 training, selectable via env var

2024-04-15 Thread Marek Behún
Support old DDR3 training code on Turris Omnia, selectable by U-Boot
enviroment variable.

Users experiencing DDR3 initialization failures or random crashes of the
operating system due to incorrect DDR3 configuration can select the old
DDR3 training implementation to fix those issues by setting the
environment variable
  env set omnia_ddr3_training old
  env save

Signed-off-by: Marek Behún 
---
 arch/arm/mach-mvebu/Kconfig   |  1 +
 board/CZ.NIC/turris_omnia/Makefile|  1 +
 board/CZ.NIC/turris_omnia/old_ddr3_training.c | 79 +++
 board/CZ.NIC/turris_omnia/turris_omnia.c  |  2 +-
 4 files changed, 82 insertions(+), 1 deletion(-)
 create mode 100644 board/CZ.NIC/turris_omnia/old_ddr3_training.c

diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index e377e8a48a..4a8328760e 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -149,6 +149,7 @@ config TARGET_TURRIS_OMNIA
select SPL_SYS_MALLOC_SIMPLE
select SYS_I2C_MVTWSI
select ATSHA204A
+   select ARMADA_38X_SUPPORT_OLD_DDR3_TRAINING
 
 config TARGET_TURRIS_MOX
bool "Support CZ.NIC's Turris Mox / RIPE Atlas Probe"
diff --git a/board/CZ.NIC/turris_omnia/Makefile 
b/board/CZ.NIC/turris_omnia/Makefile
index 341378b4e5..28142cca7e 100644
--- a/board/CZ.NIC/turris_omnia/Makefile
+++ b/board/CZ.NIC/turris_omnia/Makefile
@@ -3,3 +3,4 @@
 # Copyright (C) 2017 Marek Behún 
 
 obj-y  := turris_omnia.o ../turris_atsha_otp.o ../turris_common.o
+obj-$(CONFIG_SPL_BUILD)+= old_ddr3_training.o
diff --git a/board/CZ.NIC/turris_omnia/old_ddr3_training.c 
b/board/CZ.NIC/turris_omnia/old_ddr3_training.c
new file mode 100644
index 00..f7e89c58d4
--- /dev/null
+++ b/board/CZ.NIC/turris_omnia/old_ddr3_training.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2024 Marek Behún 
+ */
+
+#include 
+#include 
+#include 
+
+#include "../drivers/ddr/marvell/a38x/old/ddr3_init.h"
+
+static struct hws_topology_map board_topology_map_1g = {
+   0x1, /* active interfaces */
+   /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */
+   { { { {0x1, 0, 0, 0},
+ {0x1, 0, 0, 0},
+ {0x1, 0, 0, 0},
+ {0x1, 0, 0, 0},
+ {0x1, 0, 0, 0} },
+   SPEED_BIN_DDR_1600K,/* speed_bin */
+   BUS_WIDTH_16,   /* memory_width */
+   MEM_4G, /* mem_size */
+   DDR_FREQ_800,   /* frequency */
+   0, 0,   /* cas_l cas_wl */
+   HWS_TEMP_NORMAL,/* temperature */
+   HWS_TIM_2T} },  /* timing (force 2t) */
+   5,  /* Num Of Bus Per Interface*/
+   BUS_MASK_32BIT  /* Busses mask */
+};
+
+static struct hws_topology_map board_topology_map_2g = {
+   0x1, /* active interfaces */
+   /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */
+   { { { {0x1, 0, 0, 0},
+ {0x1, 0, 0, 0},
+ {0x1, 0, 0, 0},
+ {0x1, 0, 0, 0},
+ {0x1, 0, 0, 0} },
+   SPEED_BIN_DDR_1600K,/* speed_bin */
+   BUS_WIDTH_16,   /* memory_width */
+   MEM_8G, /* mem_size */
+   DDR_FREQ_800,   /* frequency */
+   0, 0,   /* cas_l cas_wl */
+   HWS_TEMP_NORMAL,/* temperature */
+   HWS_TIM_2T} },  /* timing (force 2t) */
+   5,  /* Num Of Bus Per Interface*/
+   BUS_MASK_32BIT  /* Busses mask */
+};
+
+/* defined in turris_omnia.c */
+extern int omnia_get_ram_size_gb(void);
+
+struct hws_topology_map *ddr3_get_topology_map(void)
+{
+   if (omnia_get_ram_size_gb() == 2)
+   return _topology_map_2g;
+   else
+   return _topology_map_1g;
+}
+
+bool board_use_old_ddr3_training(void)
+{
+   const char *env_val = NULL;
+
+   if (CONFIG_IS_ENABLED(ENV_SUPPORT) && !env_init())
+   env_val = env_get("omnia_ddr3_training");
+
+   if (env_val && !strcmp(env_val, "old")) {
+   printf("Using old DDR3 training implementation\n");
+   return true;
+   }
+
+   return false;
+}
+
+__weak u32 sys_env_get_topology_update_info(struct topology_update_info *tui)
+{
+   return MV_OK;
+}
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index 3b7a71bdad..225c6f4bc5 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -465,7 +465,7 @@ static bool omnia_read_eeprom(struct omnia_eeprom *oep)
return true;
 }
 
-static int omnia_get_ram_size_gb(void)
+int omnia_get_ram_size_gb(void)
 {
static int ram_size;
struct omnia_eeprom oep;
-- 
2.43.2



[PATCH u-boot-mvebu 09/10] arm: mvebu: a38x: Add optional support for using old DDR3 training code

2024-04-15 Thread Marek Behún
Add optional support for using old DDR3 training code from 2017.

The code lives in drivers/ddr/marvell/a38x/old/. To prevent symbol
clashing with new DDR3 training code, a special header which renames all
clashing symbols via macros is included and the symbols are prefixed
with 'old_'.

If old DDR3 training support is selected for a board, then the SPL
initialization code calls a new function
  board_use_old_ddr3_training()
to check whether it should use old DDR3 training code. The default
weak implementation returns false, defaulting to new DDR3 training code.

Boards that wish to support this need to select the
  ARMADA_38X_SUPPORT_OLD_DDR3_TRAINING
config option and implement the old version of DDR topology provider,
ddr3_get_topology_map().

Signed-off-by: Marek Behún 
---
 arch/arm/mach-mvebu/Kconfig   |   4 +
 arch/arm/mach-mvebu/include/mach/cpu.h|   1 +
 arch/arm/mach-mvebu/spl.c |  37 ++-
 drivers/ddr/marvell/a38x/Makefile |   2 +
 drivers/ddr/marvell/a38x/old/Makefile |  11 +
 .../marvell/a38x/old/glue_symbol_renames.h| 247 ++
 6 files changed, 293 insertions(+), 9 deletions(-)
 create mode 100644 drivers/ddr/marvell/a38x/old/glue_symbol_renames.h

diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index a320793a30..e377e8a48a 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -37,6 +37,10 @@ config ARMADA_38X_HS_IMPEDANCE_THRESH
default 0x6
range 0x0 0x7
 
+config ARMADA_38X_SUPPORT_OLD_DDR3_TRAINING
+   bool
+   depends on ARMADA_38X
+
 config ARMADA_XP
bool
select ARMADA_32BIT
diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h 
b/arch/arm/mach-mvebu/include/mach/cpu.h
index 904e7157ba..af6ce2920e 100644
--- a/arch/arm/mach-mvebu/include/mach/cpu.h
+++ b/arch/arm/mach-mvebu/include/mach/cpu.h
@@ -174,6 +174,7 @@ int serdes_phy_config(void);
  * drivers/ddr/marvell
  */
 int ddr3_init(void);
+int old_ddr3_init(void);
 
 /* Auto Voltage Scaling */
 #if defined(CONFIG_ARMADA_38X)
diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c
index 79f8877745..fd1030b33b 100644
--- a/arch/arm/mach-mvebu/spl.c
+++ b/arch/arm/mach-mvebu/spl.c
@@ -314,6 +314,33 @@ int board_return_to_bootrom(struct spl_image_info 
*spl_image,
hang();
 }
 
+#if !defined(CONFIG_ARMADA_375)
+__weak bool board_use_old_ddr3_training(void)
+{
+   return false;
+}
+
+static void ddr3_init_or_fail(void)
+{
+   int ret;
+
+   if (IS_ENABLED(CONFIG_ARMADA_38X_SUPPORT_OLD_DDR3_TRAINING) &&
+   board_use_old_ddr3_training())
+   ret = old_ddr3_init();
+   else
+   ret = ddr3_init();
+
+   if (ret) {
+   printf("ddr3 init failed: %d\n", ret);
+   if (IS_ENABLED(CONFIG_DDR_RESET_ON_TRAINING_FAILURE) &&
+   get_boot_device() != BOOT_DEVICE_UART)
+   reset_cpu();
+   else
+   hang();
+   }
+}
+#endif
+
 void board_init_f(ulong dummy)
 {
int ret;
@@ -348,15 +375,7 @@ void board_init_f(ulong dummy)
serdes_phy_config();
 
/* Setup DDR */
-   ret = ddr3_init();
-   if (ret) {
-   printf("ddr3_init() failed: %d\n", ret);
-   if (IS_ENABLED(CONFIG_DDR_RESET_ON_TRAINING_FAILURE) &&
-   get_boot_device() != BOOT_DEVICE_UART)
-   reset_cpu();
-   else
-   hang();
-   }
+   ddr3_init_or_fail();
 #endif
 
/* Initialize Auto Voltage Scaling */
diff --git a/drivers/ddr/marvell/a38x/Makefile 
b/drivers/ddr/marvell/a38x/Makefile
index fcfb615686..4e8a9d190d 100644
--- a/drivers/ddr/marvell/a38x/Makefile
+++ b/drivers/ddr/marvell/a38x/Makefile
@@ -18,6 +18,8 @@ obj-$(CONFIG_SPL_BUILD) += mv_ddr_spd.o
 obj-$(CONFIG_SPL_BUILD) += mv_ddr_topology.o
 obj-$(CONFIG_SPL_BUILD) += xor.o
 
+obj-$(CONFIG_ARMADA_38X_SUPPORT_OLD_DDR3_TRAINING) += old/
+
 ifdef CONFIG_DDR4
obj-$(CONFIG_SPL_BUILD) += mv_ddr4_mpr_pda_if.o
obj-$(CONFIG_SPL_BUILD) += mv_ddr4_training.o
diff --git a/drivers/ddr/marvell/a38x/old/Makefile 
b/drivers/ddr/marvell/a38x/old/Makefile
index e7b723bb24..1645a79b40 100644
--- a/drivers/ddr/marvell/a38x/old/Makefile
+++ b/drivers/ddr/marvell/a38x/old/Makefile
@@ -16,3 +16,14 @@ obj-$(CONFIG_SPL_BUILD) += ddr3_training_ip_engine.o
 obj-$(CONFIG_SPL_BUILD) += ddr3_training_leveling.o
 obj-$(CONFIG_SPL_BUILD) += ddr3_training_pbs.o
 obj-$(CONFIG_SPL_BUILD) += ddr3_training_static.o
+
+define IncludeSymbolRename
+  CFLAGS_$(1) = -include 
$(srctree)/drivers/ddr/marvell/a38x/old/glue_symbol_renames.h
+endef
+
+$(foreach obj,$(obj-y),$(eval $(call IncludeSymbolRename,$(obj
+
+# The old version of DDR training fails weirdly on some boards if the whole
+# driver is compiled with LTO. It seems to work if at 

[PATCH u-boot-mvebu 08/10] ddr: marvell: a38x: old: Backport immutable debug settings

2024-04-15 Thread Marek Behún
Backport the option to compile with immutable debug settings also to
the old implementation of the DDR3 training code.

The original PR for mv-ddr-marvell can be seen at
  https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell/pull/45/

Signed-off-by: Marek Behún 
---
 drivers/ddr/marvell/a38x/old/ddr3_debug.c | 32 ++
 drivers/ddr/marvell/a38x/old/ddr3_init.c  |  3 +-
 drivers/ddr/marvell/a38x/old/ddr3_init.h  | 40 ++-
 3 files changed, 52 insertions(+), 23 deletions(-)

diff --git a/drivers/ddr/marvell/a38x/old/ddr3_debug.c 
b/drivers/ddr/marvell/a38x/old/ddr3_debug.c
index a704a3e9d3..e1ae46dc82 100644
--- a/drivers/ddr/marvell/a38x/old/ddr3_debug.c
+++ b/drivers/ddr/marvell/a38x/old/ddr3_debug.c
@@ -13,13 +13,15 @@
 
 #include "ddr3_init.h"
 
+#if !defined(CONFIG_DDR_IMMUTABLE_DEBUG_SETTINGS)
 u8 is_reg_dump = 0;
 u8 debug_pbs = DEBUG_LEVEL_ERROR;
+#endif
 
 /*
  * API to change flags outside of the lib
  */
-#ifndef SILENT_LIB
+#if !defined(SILENT_LIB) && !defined(CONFIG_DDR_IMMUTABLE_DEBUG_SETTINGS)
 /* Debug flags for other Training modules */
 u8 debug_training_static = DEBUG_LEVEL_ERROR;
 u8 debug_training = DEBUG_LEVEL_ERROR;
@@ -84,12 +86,13 @@ void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, 
u8 level)
 #endif
 
 struct hws_tip_config_func_db config_func_info[HWS_MAX_DEVICE_NUM];
-u8 is_default_centralization = 0;
-u8 is_tune_result = 0;
-u8 is_validate_window_per_if = 0;
-u8 is_validate_window_per_pup = 0;
-u8 sweep_cnt = 1;
-u32 is_bist_reset_bit = 1;
+
+#if 0
+static u8 is_validate_window_per_if = 0;
+static u8 is_validate_window_per_pup = 0;
+static u8 sweep_cnt = 1;
+#endif
+
 static struct hws_xsb_info xsb_info[HWS_MAX_DEVICE_NUM];
 
 /*
@@ -292,6 +295,7 @@ int print_device_info(u8 dev_num)
return MV_OK;
 }
 
+#if 0
 void hws_ddr3_tip_sweep_test(int enable)
 {
if (enable) {
@@ -304,6 +308,7 @@ void hws_ddr3_tip_sweep_test(int enable)
}
 }
 #endif
+#endif
 
 char *ddr3_tip_convert_tune_result(enum hws_result tune_result)
 {
@@ -327,6 +332,7 @@ int ddr3_tip_print_log(u32 dev_num, u32 mem_addr)
u32 if_id = 0;
struct hws_topology_map *tm = ddr3_get_topology_map();
 
+#if 0
 #ifndef EXCLUDE_SWITCH_DEBUG
if ((is_validate_window_per_if != 0) ||
(is_validate_window_per_pup != 0)) {
@@ -347,8 +353,18 @@ int ddr3_tip_print_log(u32 dev_num, u32 mem_addr)
CHECK_STATUS(ddr3_tip_restore_dunit_regs(dev_num));
ddr3_tip_reg_dump(dev_num);
}
+#endif
 #endif
 
+   /* return early if we won't print anything anyway */
+   if (
+#if defined(SILENT_LIB)
+   1 ||
+#endif
+   debug_training < DEBUG_LEVEL_INFO) {
+   return MV_OK;
+   }
+
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
 
@@ -789,6 +805,7 @@ int ddr3_tip_print_adll(void)
return MV_OK;
 }
 
+#if 0
 /*
  * Set attribute value
  */
@@ -1156,6 +1173,7 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, 
u32 value, u32 **ptr)
 
return MV_OK;
 }
+#endif
 
 #ifndef EXCLUDE_SWITCH_DEBUG
 /*
diff --git a/drivers/ddr/marvell/a38x/old/ddr3_init.c 
b/drivers/ddr/marvell/a38x/old/ddr3_init.c
index 55baad498a..7230bc2a86 100644
--- a/drivers/ddr/marvell/a38x/old/ddr3_init.c
+++ b/drivers/ddr/marvell/a38x/old/ddr3_init.c
@@ -386,7 +386,8 @@ int ddr3_init(void)
return status;
 
/* Set log level for training lib */
-   ddr3_hws_set_log_level(DEBUG_BLOCK_ALL, DEBUG_LEVEL_ERROR);
+   if (!IS_ENABLED(CONFIG_DDR_IMMUTABLE_DEBUG_SETTINGS))
+   ddr3_hws_set_log_level(DEBUG_BLOCK_ALL, DEBUG_LEVEL_ERROR);
 
/* Start New Training IP */
status = ddr3_hws_hw_training();
diff --git a/drivers/ddr/marvell/a38x/old/ddr3_init.h 
b/drivers/ddr/marvell/a38x/old/ddr3_init.h
index ad95cc9ef8..5090cf97a7 100644
--- a/drivers/ddr/marvell/a38x/old/ddr3_init.h
+++ b/drivers/ddr/marvell/a38x/old/ddr3_init.h
@@ -152,17 +152,38 @@ enum log_level  {
 };
 
 /* Globals */
-extern u8 debug_training;
+#if defined(CONFIG_DDR_IMMUTABLE_DEBUG_SETTINGS)
+static const u8 is_reg_dump = 0;
+static const u8 debug_training_static = DEBUG_LEVEL_ERROR;
+static const u8 debug_training = DEBUG_LEVEL_ERROR;
+static const u8 debug_leveling = DEBUG_LEVEL_ERROR;
+static const u8 debug_centralization = DEBUG_LEVEL_ERROR;
+static const u8 debug_training_ip = DEBUG_LEVEL_ERROR;
+static const u8 debug_training_bist = DEBUG_LEVEL_ERROR;
+static const u8 debug_training_hw_alg = DEBUG_LEVEL_ERROR;
+static const u8 debug_training_access = DEBUG_LEVEL_ERROR;
+static const u8 debug_training_a38x = DEBUG_LEVEL_ERROR;
+static const u8 debug_pbs = DEBUG_LEVEL_ERROR;
+#else /* !CONFIG_DDR_IMMUTABLE_DEBUG_SETTINGS */
 extern u8 is_reg_dump;
+extern u8 debug_training_static;
+extern u8 debug_training;
+extern u8 debug_leveling;
+extern u8 debug

[PATCH u-boot-mvebu 07/10] ddr: marvell: a38x: old: Fix some compiler warning of the old code

2024-04-15 Thread Marek Behún
Fix some compilation warning in the old DDR training code.

Signed-off-by: Marek Behún 
---
 drivers/ddr/marvell/a38x/old/ddr3_a38x.c   | 1 +
 drivers/ddr/marvell/a38x/old/ddr3_init.h   | 2 ++
 drivers/ddr/marvell/a38x/old/ddr3_training.c   | 1 +
 drivers/ddr/marvell/a38x/old/ddr3_training_ip_engine.c | 1 +
 drivers/ddr/marvell/a38x/old/ddr3_training_leveling.c  | 1 +
 5 files changed, 6 insertions(+)

diff --git a/drivers/ddr/marvell/a38x/old/ddr3_a38x.c 
b/drivers/ddr/marvell/a38x/old/ddr3_a38x.c
index c082122f25..32a14ca4c9 100644
--- a/drivers/ddr/marvell/a38x/old/ddr3_a38x.c
+++ b/drivers/ddr/marvell/a38x/old/ddr3_a38x.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "ddr3_init.h"
 
diff --git a/drivers/ddr/marvell/a38x/old/ddr3_init.h 
b/drivers/ddr/marvell/a38x/old/ddr3_init.h
index 8cb08864c2..ad95cc9ef8 100644
--- a/drivers/ddr/marvell/a38x/old/ddr3_init.h
+++ b/drivers/ddr/marvell/a38x/old/ddr3_init.h
@@ -291,7 +291,9 @@ extern struct cl_val_per_freq cas_latency_table[];
 extern u32 target_freq;
 extern struct hws_tip_config_func_db config_func_info[HWS_MAX_DEVICE_NUM];
 extern u32 clamp_tbl[];
+#if 0
 extern u32 init_freq;
+#endif
 /* list of allowed frequency listed in order of enum hws_ddr_freq */
 extern u32 freq_val[];
 extern u8 debug_training_static;
diff --git a/drivers/ddr/marvell/a38x/old/ddr3_training.c 
b/drivers/ddr/marvell/a38x/old/ddr3_training.c
index e70ca4b425..572a69d45a 100644
--- a/drivers/ddr/marvell/a38x/old/ddr3_training.c
+++ b/drivers/ddr/marvell/a38x/old/ddr3_training.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "ddr3_init.h"
 
diff --git a/drivers/ddr/marvell/a38x/old/ddr3_training_ip_engine.c 
b/drivers/ddr/marvell/a38x/old/ddr3_training_ip_engine.c
index 011824ab42..ee789f0993 100644
--- a/drivers/ddr/marvell/a38x/old/ddr3_training_ip_engine.c
+++ b/drivers/ddr/marvell/a38x/old/ddr3_training_ip_engine.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "ddr3_init.h"
 
diff --git a/drivers/ddr/marvell/a38x/old/ddr3_training_leveling.c 
b/drivers/ddr/marvell/a38x/old/ddr3_training_leveling.c
index 3c40f198e7..c5043eefa3 100644
--- a/drivers/ddr/marvell/a38x/old/ddr3_training_leveling.c
+++ b/drivers/ddr/marvell/a38x/old/ddr3_training_leveling.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "ddr3_init.h"
 
-- 
2.43.2



[PATCH u-boot-mvebu 05/10] arm: mvebu: turris_omnia: Enable immutable debug settings in DDR3 training by default

2024-04-15 Thread Marek Behún
Save 10 KiB in Turris Omnia's SPL binary by enabling immutable debug
settings for DDR3 training code.

Signed-off-by: Marek Behún 
---
 configs/turris_omnia_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index f2b39115fe..02edd335c1 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -10,6 +10,7 @@ CONFIG_NR_DRAM_BANKS=2
 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
 CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xff
 CONFIG_TARGET_TURRIS_OMNIA=y
+CONFIG_DDR_IMMUTABLE_DEBUG_SETTINGS=y
 CONFIG_DDR_RESET_ON_TRAINING_FAILURE=y
 CONFIG_MVEBU_EFUSE_VHV_GPIO="mcu_56"
 CONFIG_MVEBU_EFUSE_VHV_GPIO_ACTIVE_LOW=y
-- 
2.43.2



[PATCH u-boot-mvebu 04/10] ddr: marvell: a38x: debug: Allow compiling with immutable debug settings to reduce binary size

2024-04-15 Thread Marek Behún
Allow compiling with immutable debug settings:
- DEBUG_LEVEL is always set to DEBUG_LEVEL_ERROR
- register dumps are disabled

This can save around 10 KiB of space in the resulting binary, which is a
lot in U-Boot SPL.

Signed-off-by: Marek Behún 
---
 arch/arm/mach-mvebu/Kconfig   | 10 +++
 drivers/ddr/marvell/a38x/ddr3_debug.c |  9 --
 drivers/ddr/marvell/a38x/ddr3_init.c  |  3 +-
 drivers/ddr/marvell/a38x/ddr3_init.h  | 42 ++-
 4 files changed, 53 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index f15d3cc5ed..a320793a30 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -250,6 +250,16 @@ config DDR_LOG_LEVEL
  At level 3, rovides the windows margin of each DQ as a results of
  DQS centeralization.
 
+config DDR_IMMUTABLE_DEBUG_SETTINGS
+   bool "Immutable DDR debug level (always DEBUG_LEVEL_ERROR)"
+   depends on ARMADA_38X
+   help
+ Makes the DDR training code debug level settings immutable.
+ The debug level setting from board topology definition is ignored.
+ The debug level is always set to DEBUG_LEVEL_ERROR and register
+ dumps are disabled.
+ This can save around 10 KiB of space in SPL binary.
+
 config DDR_RESET_ON_TRAINING_FAILURE
bool "Reset the board on DDR training failure instead of hanging"
depends on ARMADA_38X || ARMADA_XP
diff --git a/drivers/ddr/marvell/a38x/ddr3_debug.c 
b/drivers/ddr/marvell/a38x/ddr3_debug.c
index d32d42c408..0b65168d82 100644
--- a/drivers/ddr/marvell/a38x/ddr3_debug.c
+++ b/drivers/ddr/marvell/a38x/ddr3_debug.c
@@ -7,18 +7,21 @@
 #include "mv_ddr_training_db.h"
 #include "mv_ddr_regs.h"
 
+#if !defined(CONFIG_DDR_IMMUTABLE_DEBUG_SETTINGS)
 u8 is_reg_dump = 0;
 u8 debug_pbs = DEBUG_LEVEL_ERROR;
+#endif
 
 /*
  * API to change flags outside of the lib
  */
-#if defined(SILENT_LIB)
+#if defined(SILENT_LIB) || defined(CONFIG_DDR_IMMUTABLE_DEBUG_SETTINGS)
 void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level)
 {
/* do nothing */
 }
-#else /* SILENT_LIB */
+#else /* !SILENT_LIB && !CONFIG_DDR_IMMUTABLE_DEBUG_SETTINGS */
+
 /* Debug flags for other Training modules */
 u8 debug_training_static = DEBUG_LEVEL_ERROR;
 u8 debug_training = DEBUG_LEVEL_ERROR;
@@ -104,7 +107,7 @@ void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, 
u8 level)
 #endif /* CONFIG_DDR4 */
}
 }
-#endif /* SILENT_LIB */
+#endif /* !SILENT_LIB && !CONFIG_DDR_IMMUTABLE_DEBUG_SETTINGS */
 
 #if defined(DDR_VIEWER_TOOL)
 static char *convert_freq(enum mv_ddr_freq freq);
diff --git a/drivers/ddr/marvell/a38x/ddr3_init.c 
b/drivers/ddr/marvell/a38x/ddr3_init.c
index 27eb3ac173..7c5147f474 100644
--- a/drivers/ddr/marvell/a38x/ddr3_init.c
+++ b/drivers/ddr/marvell/a38x/ddr3_init.c
@@ -41,7 +41,8 @@ int ddr3_init(void)
mv_ddr_pre_training_soc_config(ddr_type);
 
/* Set log level for training library */
-   mv_ddr_user_log_level_set(DEBUG_BLOCK_ALL);
+   if (!IS_ENABLED(CONFIG_DDR_IMMUTABLE_DEBUG_SETTINGS))
+   mv_ddr_user_log_level_set(DEBUG_BLOCK_ALL);
 
mv_ddr_early_init();
 
diff --git a/drivers/ddr/marvell/a38x/ddr3_init.h 
b/drivers/ddr/marvell/a38x/ddr3_init.h
index 9288073a78..b513a13c53 100644
--- a/drivers/ddr/marvell/a38x/ddr3_init.h
+++ b/drivers/ddr/marvell/a38x/ddr3_init.h
@@ -45,15 +45,46 @@ enum log_level  {
 #define MISL_PHY_ODT_N_OFFS0x0
 
 /* Globals */
-extern u8 debug_training, debug_calibration, debug_ddr4_centralization,
-   debug_tap_tuning, debug_dm_tuning;
+#if defined(CONFIG_DDR_IMMUTABLE_DEBUG_SETTINGS)
+static const u8 is_reg_dump = 0;
+static const u8 debug_training_static = DEBUG_LEVEL_ERROR;
+static const u8 debug_training = DEBUG_LEVEL_ERROR;
+static const u8 debug_leveling = DEBUG_LEVEL_ERROR;
+static const u8 debug_centralization = DEBUG_LEVEL_ERROR;
+static const u8 debug_training_ip = DEBUG_LEVEL_ERROR;
+static const u8 debug_training_bist = DEBUG_LEVEL_ERROR;
+static const u8 debug_training_hw_alg = DEBUG_LEVEL_ERROR;
+static const u8 debug_training_access = DEBUG_LEVEL_ERROR;
+static const u8 debug_training_device = DEBUG_LEVEL_ERROR;
+static const u8 debug_pbs = DEBUG_LEVEL_ERROR;
+
+static const u8 debug_tap_tuning = DEBUG_LEVEL_ERROR;
+static const u8 debug_calibration = DEBUG_LEVEL_ERROR;
+static const u8 debug_ddr4_centralization = DEBUG_LEVEL_ERROR;
+static const u8 debug_dm_tuning = DEBUG_LEVEL_ERROR;
+#else /* !CONFIG_DDR_IMMUTABLE_DEBUG_SETTINGS */
 extern u8 is_reg_dump;
+extern u8 debug_training_static;
+extern u8 debug_training;
+extern u8 debug_leveling;
+extern u8 debug_centralization;
+extern u8 debug_training_ip;
+extern u8 debug_training_bist;
+extern u8 debug_training_hw_alg;
+extern u8 debug_training_access;
+extern u8 debug_training_device;
+extern u8 debug_pbs;
+
+extern u8 de

[PATCH u-boot-mvebu 03/10] ddr: marvell: a38x: debug: Define DDR_VIEWER_TOOL variables only if needed, and make them static

2024-04-15 Thread Marek Behún
The variables is_validate_window_per_if, is_validate_window_per_pup,
sweep_cnt and is_run_leveling_sweep_tests are only used if
DDR_VIEWER_TOOL macro is defined, so define them only in that case.

Make them static since they are only used in ddr3_debug.c.

Signed-off-by: Marek Behún 
---
 drivers/ddr/marvell/a38x/ddr3_debug.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/ddr/marvell/a38x/ddr3_debug.c 
b/drivers/ddr/marvell/a38x/ddr3_debug.c
index c659ae92d8..d32d42c408 100644
--- a/drivers/ddr/marvell/a38x/ddr3_debug.c
+++ b/drivers/ddr/marvell/a38x/ddr3_debug.c
@@ -114,13 +114,14 @@ u32 ctrl_adll[MAX_CS_NUM * MAX_INTERFACE_NUM * 
MAX_BUS_NUM];
 u32 ctrl_adll1[MAX_CS_NUM * MAX_INTERFACE_NUM * MAX_BUS_NUM];
 u32 ctrl_level_phase[MAX_CS_NUM * MAX_INTERFACE_NUM * MAX_BUS_NUM];
 #endif /* EXCLUDE_SWITCH_DEBUG */
+
+static u8 is_validate_window_per_if = 0;
+static u8 is_validate_window_per_pup = 0;
+static u8 sweep_cnt = 1;
+static u8 is_run_leveling_sweep_tests;
 #endif /* DDR_VIEWER_TOOL */
 
 struct hws_tip_config_func_db config_func_info[MAX_DEVICE_NUM];
-u8 is_validate_window_per_if = 0;
-u8 is_validate_window_per_pup = 0;
-u8 sweep_cnt = 1;
-u8 is_run_leveling_sweep_tests;
 
 static struct hws_xsb_info xsb_info[MAX_DEVICE_NUM];
 
-- 
2.43.2



[PATCH u-boot-mvebu 01/10] ddr: marvell: a38x: debug: return from ddr3_tip_print_log() early if we won't print anything

2024-04-15 Thread Marek Behún
Return from ddr3_tip_print_log() early if we won't print anything
anyway.

This way the compiler can optimize away the VALIDATE_IF_ACTIVE() calls
in the for-loop, so if the SILENT_LIB macro is defined, no code is
generated for the rest of the function, which saves some space.

Signed-off-by: Marek Behún 
---
 drivers/ddr/marvell/a38x/ddr3_debug.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/ddr/marvell/a38x/ddr3_debug.c 
b/drivers/ddr/marvell/a38x/ddr3_debug.c
index 9e499cfb99..0374a84387 100644
--- a/drivers/ddr/marvell/a38x/ddr3_debug.c
+++ b/drivers/ddr/marvell/a38x/ddr3_debug.c
@@ -399,6 +399,15 @@ int ddr3_tip_print_log(u32 dev_num, u32 mem_addr)
}
 #endif /* DDR_VIEWER_TOOL */
 
+   /* return early if we won't print anything anyway */
+   if (
+#if defined(SILENT_LIB)
+   1 ||
+#endif
+   debug_training < DEBUG_LEVEL_INFO) {
+   return MV_OK;
+   }
+
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
 
-- 
2.43.2



[PATCH u-boot-mvebu 02/10] ddr: marvell: a38x: debug: Remove unused variables

2024-04-15 Thread Marek Behún
The variables is_default_centralization, is_tune_result and
is_bist_reset_bit are never used.

Signed-off-by: Marek Behún 
---
 drivers/ddr/marvell/a38x/ddr3_debug.c | 3 ---
 drivers/ddr/marvell/a38x/ddr3_init.h  | 1 -
 2 files changed, 4 deletions(-)

diff --git a/drivers/ddr/marvell/a38x/ddr3_debug.c 
b/drivers/ddr/marvell/a38x/ddr3_debug.c
index 0374a84387..c659ae92d8 100644
--- a/drivers/ddr/marvell/a38x/ddr3_debug.c
+++ b/drivers/ddr/marvell/a38x/ddr3_debug.c
@@ -117,12 +117,9 @@ u32 ctrl_level_phase[MAX_CS_NUM * MAX_INTERFACE_NUM * 
MAX_BUS_NUM];
 #endif /* DDR_VIEWER_TOOL */
 
 struct hws_tip_config_func_db config_func_info[MAX_DEVICE_NUM];
-u8 is_default_centralization = 0;
-u8 is_tune_result = 0;
 u8 is_validate_window_per_if = 0;
 u8 is_validate_window_per_pup = 0;
 u8 sweep_cnt = 1;
-u32 is_bist_reset_bit = 1;
 u8 is_run_leveling_sweep_tests;
 
 static struct hws_xsb_info xsb_info[MAX_DEVICE_NUM];
diff --git a/drivers/ddr/marvell/a38x/ddr3_init.h 
b/drivers/ddr/marvell/a38x/ddr3_init.h
index 6854bb49de..9288073a78 100644
--- a/drivers/ddr/marvell/a38x/ddr3_init.h
+++ b/drivers/ddr/marvell/a38x/ddr3_init.h
@@ -116,7 +116,6 @@ extern u32 clamp_tbl[];
 extern u32 freq_mask[MAX_DEVICE_NUM][MV_DDR_FREQ_LAST];
 
 extern u32 maxt_poll_tries;
-extern u32 is_bist_reset_bit;
 
 extern u8 vref_window_size[MAX_INTERFACE_NUM][MAX_BUS_NUM];
 extern u32 effective_cs;
-- 
2.43.2



[PATCH u-boot-mvebu 00/10] Turris Omnia DDR training changes

2024-04-15 Thread Marek Behún
Hi Stefan,

this series adds some changes to DDR3 training for Armada 38x and
Turris Omnia.

- patches 1-4 are meant to allow for reducing another 10 KiB in the
  SPL binary. They were also sent to mv-ddr-marvell, via PR on github,
  https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell/pull/45/
  but I am told that Armada team has left Marvell, so who knows if this
  will ever be merged there
- patch 5 enables this reduction for Turris Omnia
- patches 6-8 import old DDR3 training code and make some changes so
  that it works with U-Boot. The reason why this is being done is
  explained in patch 6
- patch 9 glues the old DDR3 training code to current U-Boot
- patch 10 allows for dynamic selection of old DDR3 training code on
  Turris Omnia, via an U-Boot environment variable

Marek

Marek Behún (10):
  ddr: marvell: a38x: debug: return from ddr3_tip_print_log() early if
we won't print anything
  ddr: marvell: a38x: debug: Remove unused variables
  ddr: marvell: a38x: debug: Define DDR_VIEWER_TOOL variables only if
needed, and make them static
  ddr: marvell: a38x: debug: Allow compiling with immutable debug
settings to reduce binary size
  arm: mvebu: turris_omnia: Enable immutable debug settings in DDR3
training by default
  ddr: marvell: a38x: Import old DDR training code from 2017 version of
U-Boot
  ddr: marvell: a38x: old: Fix some compiler warning of the old code
  ddr: marvell: a38x: old: Backport immutable debug settings
  arm: mvebu: a38x: Add optional support for using old DDR3 training
code
  arm: mvebu: turris_omnia: Support old DDR3 training, selectable via
env var

 arch/arm/mach-mvebu/Kconfig   |   15 +
 arch/arm/mach-mvebu/include/mach/cpu.h|1 +
 arch/arm/mach-mvebu/spl.c |   37 +-
 board/CZ.NIC/turris_omnia/Makefile|1 +
 board/CZ.NIC/turris_omnia/old_ddr3_training.c |   79 +
 board/CZ.NIC/turris_omnia/turris_omnia.c  |2 +-
 configs/turris_omnia_defconfig|1 +
 drivers/ddr/marvell/a38x/Makefile |2 +
 drivers/ddr/marvell/a38x/ddr3_debug.c |   30 +-
 drivers/ddr/marvell/a38x/ddr3_init.c  |3 +-
 drivers/ddr/marvell/a38x/ddr3_init.h  |   43 +-
 drivers/ddr/marvell/a38x/old/Makefile |   29 +
 drivers/ddr/marvell/a38x/old/ddr3_a38x.c  |  738 +
 drivers/ddr/marvell/a38x/old/ddr3_a38x.h  |   93 +
 .../marvell/a38x/old/ddr3_a38x_mc_static.h|  226 ++
 .../ddr/marvell/a38x/old/ddr3_a38x_topology.h |   22 +
 .../ddr/marvell/a38x/old/ddr3_a38x_training.c |   40 +
 drivers/ddr/marvell/a38x/old/ddr3_debug.c | 1545 ++
 .../marvell/a38x/old/ddr3_hws_hw_training.c   |  148 +
 .../marvell/a38x/old/ddr3_hws_hw_training.h   |   49 +
 .../a38x/old/ddr3_hws_hw_training_def.h   |  464 +++
 .../marvell/a38x/old/ddr3_hws_sil_training.h  |   17 +
 drivers/ddr/marvell/a38x/old/ddr3_init.c  |  770 +
 drivers/ddr/marvell/a38x/old/ddr3_init.h  |  405 +++
 .../ddr/marvell/a38x/old/ddr3_logging_def.h   |  101 +
 .../marvell/a38x/old/ddr3_patterns_64bit.h|  924 ++
 .../ddr/marvell/a38x/old/ddr3_topology_def.h  |   76 +
 drivers/ddr/marvell/a38x/old/ddr3_training.c  | 2651 +
 .../ddr/marvell/a38x/old/ddr3_training_bist.c |  289 ++
 .../a38x/old/ddr3_training_centralization.c   |  712 +
 .../ddr/marvell/a38x/old/ddr3_training_db.c   |  652 
 .../marvell/a38x/old/ddr3_training_hw_algo.c  |  686 +
 .../marvell/a38x/old/ddr3_training_hw_algo.h  |   14 +
 .../ddr/marvell/a38x/old/ddr3_training_ip.h   |  178 ++
 .../marvell/a38x/old/ddr3_training_ip_bist.h  |   54 +
 .../old/ddr3_training_ip_centralization.h |   15 +
 .../marvell/a38x/old/ddr3_training_ip_db.h|   34 +
 .../marvell/a38x/old/ddr3_training_ip_def.h   |  173 ++
 .../a38x/old/ddr3_training_ip_engine.c| 1355 +
 .../a38x/old/ddr3_training_ip_engine.h|   85 +
 .../marvell/a38x/old/ddr3_training_ip_flow.h  |  349 +++
 .../marvell/a38x/old/ddr3_training_ip_pbs.h   |   41 +
 .../a38x/old/ddr3_training_ip_prv_if.h|  107 +
 .../a38x/old/ddr3_training_ip_static.h|   31 +
 .../marvell/a38x/old/ddr3_training_leveling.c | 1837 
 .../marvell/a38x/old/ddr3_training_leveling.h |   17 +
 .../ddr/marvell/a38x/old/ddr3_training_pbs.c  |  995 +++
 .../marvell/a38x/old/ddr3_training_static.c   |  538 
 .../ddr/marvell/a38x/old/ddr_topology_def.h   |  121 +
 .../ddr/marvell/a38x/old/ddr_training_ip_db.h |   16 +
 .../marvell/a38x/old/glue_symbol_renames.h|  247 ++
 drivers/ddr/marvell/a38x/old/silicon_if.h |   17 +
 drivers/ddr/marvell/a38x/old/xor.h|   92 +
 53 files changed, 17138 insertions(+), 29 deletions(-)
 create mode 100644 board/CZ.NIC/turris_omnia/old_ddr3_training.c
 create mode 100644 drivers/ddr/marvell/a38x/old/Makefile
 create mode 100644 drivers/ddr/marvell/a38x/old/ddr3_a38x.c
 create mode 100644 drivers/ddr/marvell/a38x/old

[PATCH u-boot-mvebu v4 18/18] arm: mvebu: turris_omnia: Enable rng command in defconfig

2024-04-04 Thread Marek Behún
Now that Turris Omnia has a rng driver provided in the MCU driver,
enable the rng command in defconfig.

Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 configs/turris_omnia_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 4c21635ec9..f2b39115fe 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -73,6 +73,7 @@ CONFIG_CMD_WDT=y
 CONFIG_CMD_TFTPPUT=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
+CONFIG_CMD_RNG=y
 CONFIG_CMD_AES=y
 CONFIG_CMD_HASH=y
 CONFIG_CMD_BTRFS=y
-- 
2.43.2



[PATCH u-boot-mvebu v4 17/18] misc: turris_omnia_mcu: Add support for rng provided by MCU

2024-04-04 Thread Marek Behún
Add support for true random number generator provided by the MCU on
Turris Omnia. The MCU firmware supports TRNG if the FEAT_TRNG bit is set
in features. In that case we bind the rng driver.

Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 configs/turris_omnia_defconfig  |  1 +
 drivers/misc/Kconfig|  1 +
 drivers/misc/turris_omnia_mcu.c | 57 +
 3 files changed, 59 insertions(+)

diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 0df0f3c90b..4c21635ec9 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -107,6 +107,7 @@ CONFIG_NVME_PCI=y
 CONFIG_PCI_MVEBU=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_ARMADA_38X=y
+CONFIG_DM_RNG=y
 CONFIG_DM_RTC=y
 CONFIG_RTC_ARMADA38X=y
 CONFIG_SERIAL_PROBE_ALL=y
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 041de538fa..6b06888454 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -509,6 +509,7 @@ config TURRIS_OMNIA_MCU
bool "Enable Turris Omnia MCU driver"
depends on DM_I2C
depends on DM_GPIO
+   depends on DM_RNG
depends on SYSRESET
default y if TARGET_TURRIS_OMNIA
help
diff --git a/drivers/misc/turris_omnia_mcu.c b/drivers/misc/turris_omnia_mcu.c
index 77a0424d61..6b2f17c000 100644
--- a/drivers/misc/turris_omnia_mcu.c
+++ b/drivers/misc/turris_omnia_mcu.c
@@ -5,15 +5,20 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 
+#define CMD_TRNG_MAX_ENTROPY_LEN   64
+
 struct turris_omnia_mcu_info {
u32 features;
 };
@@ -282,6 +287,49 @@ U_BOOT_DRIVER(turris_omnia_mcu_sysreset) = {
.ops= _sysreset_ops,
 };
 
+static int omnia_rng_read(struct udevice *dev, void *data, size_t count)
+{
+   u8 buf[1 + CMD_TRNG_MAX_ENTROPY_LEN];
+   size_t len;
+   int ret;
+
+   while (count) {
+   ret = dm_i2c_read(dev->parent, CMD_TRNG_COLLECT_ENTROPY, buf,
+ sizeof(buf));
+   if (ret)
+   return ret;
+
+   len = min_t(size_t, buf[0],
+   min_t(size_t, CMD_TRNG_MAX_ENTROPY_LEN, count));
+
+   if (!len) {
+   /* wait 500ms (fail if interrupted), then try again */
+   for (int i = 0; i < 5; ++i) {
+   mdelay(100);
+   if (ctrlc())
+   return -EINTR;
+   }
+   continue;
+   }
+
+   memcpy(data, [1], len);
+   data += len;
+   count -= len;
+   }
+
+   return 0;
+}
+
+static const struct dm_rng_ops omnia_rng_ops = {
+   .read   = omnia_rng_read,
+};
+
+U_BOOT_DRIVER(turris_omnia_mcu_trng) = {
+   .name   = "turris-omnia-mcu-trng",
+   .id = UCLASS_RNG,
+   .ops= _rng_ops,
+};
+
 static int turris_omnia_mcu_bind(struct udevice *dev)
 {
/* bind MCU GPIOs as a child device */
@@ -336,6 +384,15 @@ static int turris_omnia_mcu_probe(struct udevice *dev)
return ret;
}
 
+   /* bind rng if trng is supported */
+   if (info->features & FEAT_TRNG) {
+   ret = device_bind_driver_to_node(dev, "turris-omnia-mcu-trng",
+"turris-omnia-mcu-trng",
+dev_ofnode(dev), NULL);
+   if (ret < 0)
+   return ret;
+   }
+
return 0;
 }
 
-- 
2.43.2



[PATCH u-boot-mvebu v4 16/18] cmd: rng: Print "Abort" on -EINTR

2024-04-04 Thread Marek Behún
In the rng command, print
  Abort
instead of
  Reading RNG failed
if the error number is -EINTR, which can happen if the user pressed
CTRL-C.

Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 cmd/rng.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/cmd/rng.c b/cmd/rng.c
index b073a6c849..e5ab868112 100644
--- a/cmd/rng.c
+++ b/cmd/rng.c
@@ -17,7 +17,7 @@ static int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
u8 buf[64];
int devnum;
struct udevice *dev;
-   int ret = CMD_RET_SUCCESS;
+   int ret = CMD_RET_SUCCESS, err;
 
if (argc == 2 && !strcmp(argv[1], "list")) {
int idx = 0;
@@ -62,8 +62,9 @@ static int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
 
n = min(n, sizeof(buf));
 
-   if (dm_rng_read(dev, buf, n)) {
-   printf("Reading RNG failed\n");
+   err = dm_rng_read(dev, buf, n);
+   if (err) {
+   puts(err == -EINTR ? "Abort\n" : "Reading RNG failed\n");
ret = CMD_RET_FAILURE;
} else {
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, n);
-- 
2.43.2



[PATCH u-boot-mvebu v4 15/18] arm: mvebu: turris_omnia: Enable poweroff command via sysreset in defconfig

2024-04-04 Thread Marek Behún
Enable support for the poweroff command via sysreset for Turris Omnia.

Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 configs/turris_omnia_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 9d5171c6a8..0df0f3c90b 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -65,6 +65,7 @@ CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_MTD=y
 CONFIG_CMD_PCI=y
+CONFIG_CMD_POWEROFF=y
 CONFIG_CMD_SATA=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
@@ -114,6 +115,7 @@ CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_KIRKWOOD_SPI=y
 CONFIG_SYSRESET=y
+CONFIG_SYSRESET_CMD_POWEROFF=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
-- 
2.43.2



[PATCH u-boot-mvebu v4 14/18] gpio: turris_omnia_mcu: Add support for system power off via sysreset

2024-04-04 Thread Marek Behún
Add support for system power off via UCLASS_SYSRESET. Newer versions of
Turris Omnia MCU firmware can power off the board (MCU will disable
almost all voltage regulators and go into low power mode).

Move the MCU driver into drivers/misc and register it under UCLASS_MISC.
The sysreset and gpio device are bound as child devices of the MCU device.

Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 configs/turris_omnia_defconfig|   1 +
 drivers/gpio/Kconfig  |   7 -
 drivers/gpio/Makefile |   1 -
 drivers/misc/Kconfig  |  10 ++
 drivers/misc/Makefile |   1 +
 drivers/{gpio => misc}/turris_omnia_mcu.c | 150 --
 6 files changed, 120 insertions(+), 50 deletions(-)
 rename drivers/{gpio => misc}/turris_omnia_mcu.c (60%)

diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 39e15043df..9d5171c6a8 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -113,6 +113,7 @@ CONFIG_SPL_DEBUG_UART_BASE=0xd0012000
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_KIRKWOOD_SPI=y
+CONFIG_SYSRESET=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index a7fb1eb3f4..b050585389 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -665,13 +665,6 @@ config SLG7XL45106_I2C_GPO
   8-bit gpo expander, all gpo lines are controlled by writing
   value into data register.
 
-config TURRIS_OMNIA_MCU
-   bool "Turris Omnia MCU GPIO driver"
-   depends on DM_GPIO
-   default y if TARGET_TURRIS_OMNIA
-   help
-  Support for GPIOs on MCU connected to Turris Omnia via i2c.
-
 config FTGPIO010
bool "Faraday Technology FTGPIO010 driver"
depends on DM_GPIO
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 90711702a6..4a29315435 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -73,7 +73,6 @@ obj-$(CONFIG_$(SPL_)MAX77663_GPIO)+= max77663_gpio.o
 obj-$(CONFIG_SL28CPLD_GPIO)+= sl28cpld-gpio.o
 obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN)  += zynqmp_gpio_modepin.o
 obj-$(CONFIG_SLG7XL45106_I2C_GPO)  += gpio_slg7xl45106.o
-obj-$(CONFIG_$(SPL_TPL_)TURRIS_OMNIA_MCU)  += turris_omnia_mcu.o
 obj-$(CONFIG_FTGPIO010)+= ftgpio010.o
 obj-$(CONFIG_ADP5585_GPIO) += adp5585_gpio.o
 obj-$(CONFIG_RZG2L_GPIO)   += rzg2l-gpio.o
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 98043fc2ff..041de538fa 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -505,6 +505,16 @@ config TEST_DRV
  model. This should only be enabled for testing as it is not useful for
  anything else.
 
+config TURRIS_OMNIA_MCU
+   bool "Enable Turris Omnia MCU driver"
+   depends on DM_I2C
+   depends on DM_GPIO
+   depends on SYSRESET
+   default y if TARGET_TURRIS_OMNIA
+   help
+ This enables support for Turris Omnia MCU connected GPIOs and
+ board power off.
+
 config USB_HUB_USB251XB
tristate "USB251XB Hub Controller Configuration Driver"
depends on I2C
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 1522f6c3b7..9e829905f1 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_SYS_DPAA_QBMAN) += fsl_portals.o
 obj-$(CONFIG_TEGRA186_BPMP) += tegra186_bpmp.o
 obj-$(CONFIG_TEGRA_CAR) += tegra_car.o
 obj-$(CONFIG_TEST_DRV) += test_drv.o
+obj-$(CONFIG_$(SPL_TPL_)TURRIS_OMNIA_MCU) += turris_omnia_mcu.o
 obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
 obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress_config.o
 obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o
diff --git a/drivers/gpio/turris_omnia_mcu.c b/drivers/misc/turris_omnia_mcu.c
similarity index 60%
rename from drivers/gpio/turris_omnia_mcu.c
rename to drivers/misc/turris_omnia_mcu.c
index 40ced261e3..77a0424d61 100644
--- a/drivers/gpio/turris_omnia_mcu.c
+++ b/drivers/misc/turris_omnia_mcu.c
@@ -1,9 +1,14 @@
 // SPDX-License-Identifier: GPL-2.0+
-// (C) 2022 Pali Rohár 
+/*
+ * Copyright (C) 2022 Pali Rohár 
+ * Copyright (C) 2024 Marek Behún 
+ */
 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -13,9 +18,9 @@ struct turris_omnia_mcu_info {
u32 features;
 };
 
-static int turris_omnia_mcu_get_function(struct udevice *dev, uint offset)
+static int omnia_gpio_get_function(struct udevice *dev, uint offset)
 {
-   struct turris_omnia_mcu_info *info = dev_get_plat(dev);
+   struct turris_omnia_mcu_info *info = dev_get_priv(dev->parent);
 
switch (offset) {
/* bank 0 */
@@ -49,9 +54,9 @@ static int turris_omnia_mcu_get_function(struct udevice *dev, 
uint offset)
}
 }
 
-static int turris_omnia_mcu_get_value(struct udevice *dev, uint offset)
+static int omnia_gpio_get_value(st

[PATCH u-boot-mvebu v4 13/18] gpio: turris_omnia_mcu: Update firmware features reading

2024-04-04 Thread Marek Behún
Update firmware features reading to try reading 32 bits of features and
fallback to reading 16 bits.

Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 drivers/gpio/turris_omnia_mcu.c | 32 ++--
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/gpio/turris_omnia_mcu.c b/drivers/gpio/turris_omnia_mcu.c
index c441d07d69..40ced261e3 100644
--- a/drivers/gpio/turris_omnia_mcu.c
+++ b/drivers/gpio/turris_omnia_mcu.c
@@ -10,7 +10,7 @@
 #include 
 
 struct turris_omnia_mcu_info {
-   u16 features;
+   u32 features;
 };
 
 static int turris_omnia_mcu_get_function(struct udevice *dev, uint offset)
@@ -228,25 +228,37 @@ static int turris_omnia_mcu_probe(struct udevice *dev)
 {
struct turris_omnia_mcu_info *info = dev_get_plat(dev);
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
-   u16 val;
+   u32 dword;
+   u16 word;
int ret;
 
-   ret = dm_i2c_read(dev, CMD_GET_STATUS_WORD, (void *), sizeof(val));
+   ret = dm_i2c_read(dev, CMD_GET_STATUS_WORD, (void *), 
sizeof(word));
if (ret < 0) {
printf("Error: turris_omnia_mcu CMD_GET_STATUS_WORD failed: 
%d\n",
   ret);
return ret;
}
 
-   if (le16_to_cpu(val) & STS_FEATURES_SUPPORTED) {
-   ret = dm_i2c_read(dev, CMD_GET_FEATURES, (void *),
- sizeof(val));
+   if (le16_to_cpu(word) & STS_FEATURES_SUPPORTED) {
+   /* try read 32-bit features */
+   ret = dm_i2c_read(dev, CMD_GET_FEATURES, (void *),
+ sizeof(dword));
if (ret < 0) {
-   printf("Error: turris_omnia_mcu CMD_GET_FEATURES 
failed: %d\n",
-  ret);
-   return ret;
+   /* try read 16-bit features */
+   ret = dm_i2c_read(dev, CMD_GET_FEATURES, (void *),
+ sizeof(word));
+   if (ret < 0) {
+   printf("Error: turris_omnia_mcu 
CMD_GET_FEATURES failed: %d\n",
+  ret);
+   return ret;
+   }
+
+   info->features = le16_to_cpu(word);
+   } else {
+   info->features = le32_to_cpu(dword);
+   if (info->features & FEAT_FROM_BIT_16_INVALID)
+   info->features &= GENMASK(15, 0);
}
-   info->features = le16_to_cpu(val);
}
 
uc_priv->bank_name = "mcu_";
-- 
2.43.2



[PATCH u-boot-mvebu v4 12/18] gpio: turris_omnia_mcu: Use byteorder conversion functions

2024-04-04 Thread Marek Behún
Use byteorder conversion function instead of manually assembling data
from/to MCU.

Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 drivers/gpio/turris_omnia_mcu.c | 80 +++--
 1 file changed, 46 insertions(+), 34 deletions(-)

diff --git a/drivers/gpio/turris_omnia_mcu.c b/drivers/gpio/turris_omnia_mcu.c
index da9a6efe6d..c441d07d69 100644
--- a/drivers/gpio/turris_omnia_mcu.c
+++ b/drivers/gpio/turris_omnia_mcu.c
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -51,27 +52,31 @@ static int turris_omnia_mcu_get_function(struct udevice 
*dev, uint offset)
 static int turris_omnia_mcu_get_value(struct udevice *dev, uint offset)
 {
struct turris_omnia_mcu_info *info = dev_get_plat(dev);
-   u8 val16[2];
-   u8 val32[4];
+   u32 val32;
+   u16 val16;
int ret;
 
switch (offset) {
/* bank 0 */
case 0 ... 15:
-   ret = dm_i2c_read(dev, CMD_GET_STATUS_WORD, val16, 2);
+   ret = dm_i2c_read(dev, CMD_GET_STATUS_WORD, (void *),
+ sizeof(val16));
if (ret)
return ret;
-   return u16)val16[1] << 8) | val16[0]) >> offset) & 0x1;
+
+   return !!(le16_to_cpu(val16) & BIT(offset));
 
/* bank 1 - supported only when FEAT_EXT_CMDS is set */
case (16 + 0) ... (16 + 31):
if (!(info->features & FEAT_EXT_CMDS))
return -EINVAL;
-   ret = dm_i2c_read(dev, CMD_GET_EXT_STATUS_DWORD, val32, 4);
+
+   ret = dm_i2c_read(dev, CMD_GET_EXT_STATUS_DWORD, (void *),
+ sizeof(val32));
if (ret)
return ret;
-   return u32)val32[3] << 24) | ((u32)val32[2] << 16) |
-((u32)val32[1] << 8) | val32[0]) >> (offset - 16)) & 
0x1;
+
+   return !!(le32_to_cpu(val32) & BIT(offset - 16));
 
/* bank 2 - supported only when FEAT_EXT_CMDS and FEAT_PERIPH_MCU is 
set */
case (16 + 32 + 0) ... (16 + 32 + 15):
@@ -79,10 +84,13 @@ static int turris_omnia_mcu_get_value(struct udevice *dev, 
uint offset)
return -EINVAL;
if (!(info->features & FEAT_PERIPH_MCU))
return -EINVAL;
-   ret = dm_i2c_read(dev, CMD_GET_EXT_CONTROL_STATUS, val16, 2);
+
+   ret = dm_i2c_read(dev, CMD_GET_EXT_CONTROL_STATUS,
+ (void *), sizeof(val16));
if (ret)
return ret;
-   return u16)val16[1] << 8) | val16[0]) >> (offset - 16 - 
32)) & 0x1;
+
+   return !!(le16_to_cpu(val16) & BIT(offset - 16 - 32));
 
default:
return -EINVAL;
@@ -92,30 +100,33 @@ static int turris_omnia_mcu_get_value(struct udevice *dev, 
uint offset)
 static int turris_omnia_mcu_set_value(struct udevice *dev, uint offset, int 
value)
 {
struct turris_omnia_mcu_info *info = dev_get_plat(dev);
-   u8 val16[2];
-   u8 val32[4];
+   u16 valmask16[2];
+   u8 valmask8[2];
 
switch (offset) {
/* bank 0 */
case 0 ... 15:
switch (offset) {
case ilog2(STS_USB30_PWRON):
-   val16[1] = CTL_USB30_PWRON;
+   valmask8[1] = CTL_USB30_PWRON;
break;
case ilog2(STS_USB31_PWRON):
-   val16[1] = CTL_USB31_PWRON;
+   valmask8[1] = CTL_USB31_PWRON;
break;
case ilog2(STS_ENABLE_4V5):
-   val16[1] = CTL_ENABLE_4V5;
+   valmask8[1] = CTL_ENABLE_4V5;
break;
case ilog2(STS_BUTTON_MODE):
-   val16[1] = CTL_BUTTON_MODE;
+   valmask8[1] = CTL_BUTTON_MODE;
break;
default:
return -EINVAL;
}
-   val16[0] = value ? val16[1] : 0;
-   return dm_i2c_write(dev, CMD_GENERAL_CONTROL, val16, 
sizeof(val16));
+
+   valmask8[0] = value ? valmask8[1] : 0;
+
+   return dm_i2c_write(dev, CMD_GENERAL_CONTROL, valmask8,
+   sizeof(valmask8));
 
/* bank 2 - supported only when FEAT_EXT_CMDS and FEAT_PERIPH_MCU is 
set */
case (16 + 32 + 0) ... (16 + 32 + 15):
@@ -123,11 +134,12 @@ static int turris_omnia_mcu_set_value(struct udevice 
*dev, uint offset, int valu
return -EINVAL;
if (!(info->features & FEAT_PERIPH_MCU))
return -EINVAL;
-   val32[3] = BIT(offset - 16 - 32) >> 8;
-

[PATCH u-boot-mvebu v4 11/18] arm: mvebu: system-controller: Add support for SYSRESET

2024-04-04 Thread Marek Behún
Add driver model support for sysreset via mvebu system controller. This is
currently only available for U-Boot proper.

Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 arch/arm/mach-mvebu/Kconfig | 18 +-
 arch/arm/mach-mvebu/Makefile|  2 +-
 arch/arm/mach-mvebu/cpu.c   |  2 +
 arch/arm/mach-mvebu/system-controller.c | 75 +++--
 4 files changed, 90 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 623432a60e..f15d3cc5ed 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -19,6 +19,7 @@ config ARMADA_32BIT
select SPL_SYS_NO_VECTOR_TABLE if SPL
select ARCH_VERY_EARLY_INIT
select ARMADA_32BIT_SYSCON_RESET if DM_RESET && PCI_MVEBU
+   select ARMADA_32BIT_SYSCON_SYSRESET if SYSRESET
 
 # ARMv7 SoCs...
 config ARMADA_375
@@ -457,16 +458,29 @@ config SF_DEFAULT_MODE
default 0x0
depends on MVEBU_SPL_BOOT_DEVICE_SPI
 
+config ARMADA_32BIT_SYSCON
+   bool
+   depends on ARMADA_32BIT
+   select REGMAP
+   select SYSCON
+
 config ARMADA_32BIT_SYSCON_RESET
bool "Support Armada XP/375/38x/39x reset controller"
depends on ARMADA_32BIT
depends on DM_RESET
-   select REGMAP
-   select SYSCON
+   select ARMADA_32BIT_SYSCON
help
  Build support for Armada XP/375/38x/39x reset controller. This is
  needed for PCIe support.
 
+config ARMADA_32BIT_SYSCON_SYSRESET
+   bool "Support Armada XP/375/38x/39x sysreset via driver model"
+   depends on ARMADA_32BIT
+   depends on SYSRESET
+   select ARMADA_32BIT_SYSCON
+   help
+ Build support for Armada XP/375/38x/39x system reset via driver model.
+
 source "board/solidrun/clearfog/Kconfig"
 source "board/kobol/helios4/Kconfig"
 
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index d44ca3a0df..329c2e4915 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -28,7 +28,7 @@ obj-$(CONFIG_ARMADA_38X) += 
../../../drivers/ddr/marvell/a38x/xor.o
 obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_MSYS) += ../../../drivers/ddr/marvell/axp/xor.o
 
-obj-$(CONFIG_ARMADA_32BIT_SYSCON_RESET) += system-controller.o
+obj-$(CONFIG_ARMADA_32BIT_SYSCON) += system-controller.o
 
 ifdef CONFIG_ARMADA_38X
 obj-$(CONFIG_MVEBU_EFUSE) += efuse.o
diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c
index 8e0de93538..7c62a5dbb6 100644
--- a/arch/arm/mach-mvebu/cpu.c
+++ b/arch/arm/mach-mvebu/cpu.c
@@ -52,6 +52,7 @@ void lowlevel_init(void)
 */
 }
 
+#if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_ARMADA_32BIT_SYSCON_SYSRESET)
 void reset_cpu(void)
 {
struct mvebu_system_registers *reg =
@@ -62,6 +63,7 @@ void reset_cpu(void)
while (1)
;
 }
+#endif
 
 u32 get_boot_device(void)
 {
diff --git a/arch/arm/mach-mvebu/system-controller.c 
b/arch/arm/mach-mvebu/system-controller.c
index c5c05922f2..682431ee11 100644
--- a/arch/arm/mach-mvebu/system-controller.c
+++ b/arch/arm/mach-mvebu/system-controller.c
@@ -10,11 +10,24 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
-#define MVEBU_SOC_CONTROL_1_REG 0x4
+#define MVEBU_SOC_CONTROL_1_REG0x4
 
-#define MVEBU_PCIE_ID 0
+#if defined(CONFIG_ARMADA_375)
+# define MVEBU_RSTOUTN_MASK_REG0x54
+# define MVEBU_SYS_SOFT_RST_REG0x58
+#else
+# define MVEBU_RSTOUTN_MASK_REG0x60
+# define MVEBU_SYS_SOFT_RST_REG0x64
+#endif
+
+#define MVEBU_GLOBAL_SOFT_RST_BIT  BIT(0)
+
+#define MVEBU_PCIE_ID  0
+
+#if IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_RESET)
 
 static int mvebu_reset_of_xlate(struct reset_ctl *rst,
struct ofnode_phandle_args *args)
@@ -90,11 +103,65 @@ U_BOOT_DRIVER(mvebu_reset) = {
.ops = _reset_ops,
 };
 
+#endif /* IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_RESET) */
+
+#if IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_SYSRESET)
+
+static int mvebu_sysreset_request(struct udevice *dev, enum sysreset_t type)
+{
+   struct regmap *regmap = syscon_get_regmap(dev->parent);
+   uint bit;
+
+   if (type != SYSRESET_COLD)
+   return -EPROTONOSUPPORT;
+
+   bit = MVEBU_GLOBAL_SOFT_RST_BIT;
+
+   regmap_update_bits(regmap, MVEBU_RSTOUTN_MASK_REG, bit, bit);
+   regmap_update_bits(regmap, MVEBU_SYS_SOFT_RST_REG, bit, bit);
+
+   /* Loop while waiting for the reset */
+   while (1)
+   ;
+
+   return 0;
+}
+
+static struct sysreset_ops mvebu_sysreset_ops = {
+   .request = mvebu_sysreset_request,
+};
+
+U_BOOT_DRIVER(mvebu_sysreset) = {
+   .name = "mvebu-sysreset",
+   .id = UCLASS_SYSRESET,
+   .ops = _sysreset_ops,
+};
+
+#endif /* IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_SYS

[PATCH u-boot-mvebu v4 10/18] arm: mvebu: system-controller: Select mvebu-reset if DM_RESET && PCI_MVEBU

2024-04-04 Thread Marek Behún
The mvebu-reset driver is only needed by the mvebu PCIe driver, but
currently it is automatically selected if DM_RESET is enabled. Add the
condition of PCI_MVEBU also being enabled for mvebu-reset to be
selected.

Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 arch/arm/mach-mvebu/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 62a2bc5958..623432a60e 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -18,7 +18,7 @@ config ARMADA_32BIT
select TOOLS_KWBIMAGE if SPL
select SPL_SYS_NO_VECTOR_TABLE if SPL
select ARCH_VERY_EARLY_INIT
-   select ARMADA_32BIT_SYSCON_RESET if DM_RESET
+   select ARMADA_32BIT_SYSCON_RESET if DM_RESET && PCI_MVEBU
 
 # ARMv7 SoCs...
 config ARMADA_375
-- 
2.43.2



[PATCH u-boot-mvebu v4 09/18] arm: mvebu: system-controller: Rework to use UCLASS_SYSCON

2024-04-04 Thread Marek Behún
The system-controller driver for 32-bit Armada is currently registered
as UCLASS_RESET, since it only provides enabling/disabling PCIe ports.

Rework it as UCLASS_SYSCON and bind mvebu-reset as a child device.

Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 arch/arm/mach-mvebu/Kconfig | 11 
 arch/arm/mach-mvebu/Makefile|  2 +-
 arch/arm/mach-mvebu/system-controller.c | 76 ++---
 3 files changed, 54 insertions(+), 35 deletions(-)

diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 2058c95ca2..62a2bc5958 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -18,6 +18,7 @@ config ARMADA_32BIT
select TOOLS_KWBIMAGE if SPL
select SPL_SYS_NO_VECTOR_TABLE if SPL
select ARCH_VERY_EARLY_INIT
+   select ARMADA_32BIT_SYSCON_RESET if DM_RESET
 
 # ARMv7 SoCs...
 config ARMADA_375
@@ -456,6 +457,16 @@ config SF_DEFAULT_MODE
default 0x0
depends on MVEBU_SPL_BOOT_DEVICE_SPI
 
+config ARMADA_32BIT_SYSCON_RESET
+   bool "Support Armada XP/375/38x/39x reset controller"
+   depends on ARMADA_32BIT
+   depends on DM_RESET
+   select REGMAP
+   select SYSCON
+   help
+ Build support for Armada XP/375/38x/39x reset controller. This is
+ needed for PCIe support.
+
 source "board/solidrun/clearfog/Kconfig"
 source "board/kobol/helios4/Kconfig"
 
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index ef790d97fe..d44ca3a0df 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -28,7 +28,7 @@ obj-$(CONFIG_ARMADA_38X) += 
../../../drivers/ddr/marvell/a38x/xor.o
 obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_MSYS) += ../../../drivers/ddr/marvell/axp/xor.o
 
-obj-$(CONFIG_DM_RESET) += system-controller.o
+obj-$(CONFIG_ARMADA_32BIT_SYSCON_RESET) += system-controller.o
 
 ifdef CONFIG_ARMADA_38X
 obj-$(CONFIG_MVEBU_EFUSE) += efuse.o
diff --git a/arch/arm/mach-mvebu/system-controller.c 
b/arch/arm/mach-mvebu/system-controller.c
index 7cdde11cbd..c5c05922f2 100644
--- a/arch/arm/mach-mvebu/system-controller.c
+++ b/arch/arm/mach-mvebu/system-controller.c
@@ -1,19 +1,21 @@
 // SPDX-License-Identifier: GPL-2.0+
-// (C) 2021 Pali Rohár 
+/*
+ * Copyright (C) 2021 Pali Rohár 
+ * Copyright (C) 2024 Marek Behún 
+ */
 
 #include 
 #include 
+#include 
+#include 
 #include 
+#include 
 #include 
 
 #define MVEBU_SOC_CONTROL_1_REG 0x4
 
 #define MVEBU_PCIE_ID 0
 
-struct mvebu_reset_data {
-   void *base;
-};
-
 static int mvebu_reset_of_xlate(struct reset_ctl *rst,
struct ofnode_phandle_args *args)
 {
@@ -46,46 +48,33 @@ static int mvebu_reset_free(struct reset_ctl *rst)
 
 static int mvebu_reset_assert(struct reset_ctl *rst)
 {
-   struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+   struct regmap *regmap = syscon_get_regmap(rst->dev->parent);
 
-   clrbits_32(data->base + MVEBU_SOC_CONTROL_1_REG, BIT(rst->data));
-   return 0;
+   return regmap_update_bits(regmap, MVEBU_SOC_CONTROL_1_REG,
+ BIT(rst->data), 0);
 }
 
 static int mvebu_reset_deassert(struct reset_ctl *rst)
 {
-   struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+   struct regmap *regmap = syscon_get_regmap(rst->dev->parent);
 
-   setbits_32(data->base + MVEBU_SOC_CONTROL_1_REG, BIT(rst->data));
-   return 0;
+   return regmap_update_bits(regmap, MVEBU_SOC_CONTROL_1_REG,
+ BIT(rst->data), BIT(rst->data));
 }
 
 static int mvebu_reset_status(struct reset_ctl *rst)
 {
-   struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+   struct regmap *regmap = syscon_get_regmap(rst->dev->parent);
+   uint val;
+   int ret;
 
-   return !(readl(data->base + MVEBU_SOC_CONTROL_1_REG) & BIT(rst->data));
-}
-
-static int mvebu_reset_of_to_plat(struct udevice *dev)
-{
-   struct mvebu_reset_data *data = dev_get_priv(dev);
+   ret = regmap_read(regmap, MVEBU_SOC_CONTROL_1_REG, );
+   if (ret < 0)
+   return ret;
 
-   data->base = dev_read_addr_ptr(dev);
-   if (!data->base)
-   return -EINVAL;
-
-   return 0;
+   return !(val & BIT(rst->data));
 }
 
-static const struct udevice_id mvebu_reset_of_match[] = {
-   { .compatible = "marvell,armada-370-xp-system-controller" },
-   { .compatible = "marvell,armada-375-system-controller" },
-   { .compatible = "marvell,armada-380-system-controller" },
-   { .compatible = "marvell,armada-390-system-controller" },
-   { },
-};
-
 static const struct reset_ops mvebu_reset_ops = {
.of_xlate = mvebu_reset_of_xlate,
.request = mvebu_reset_request,
@@ -98,8 +87,2

[PATCH u-boot-mvebu v4 08/18] arm: mvebu: spl: Do not build mvebu-reset in SPL

2024-04-04 Thread Marek Behún
Commit 35e29e89a386 ("arm: mvebu: Implement simple mvebu-reset driver
for enabling/disabling PCIe ports") made it so that the mvebu reset
driver for enabling/disabling PCIe ports is build if CONFIG_DM_RESET is
enabled. This is because PCI_MVEBU depends on DM_RESET.

But the driver should not be built for SPL. Indeed the PCI_MVEBU driver
is not supported in SPL now, and so the mvebu-reset driver is not needed.

Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 arch/arm/mach-mvebu/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index 0584ed2be5..ef790d97fe 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -22,13 +22,14 @@ else # CONFIG_ARCH_KIRKWOOD
 obj-y  = cpu.o
 obj-y  += dram.o
 obj-y  += lowlevel.o
-obj-$(CONFIG_DM_RESET) += system-controller.o
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_ARMADA_375) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_38X) += ../../../drivers/ddr/marvell/a38x/xor.o
 obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_MSYS) += ../../../drivers/ddr/marvell/axp/xor.o
 
+obj-$(CONFIG_DM_RESET) += system-controller.o
+
 ifdef CONFIG_ARMADA_38X
 obj-$(CONFIG_MVEBU_EFUSE) += efuse.o
 endif
-- 
2.43.2



[PATCH u-boot-mvebu v4 07/18] arm: mvebu: turris_omnia: Disable Atmel SHA node if not present

2024-04-04 Thread Marek Behún
If the FEAT_CRYPTO feature bit is present in MCU features, the board
crypto is implemented by MCU and the Atmel SHA chip is not present.
Disable Atmel SHA device-tree node in that case.

Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 board/CZ.NIC/turris_omnia/turris_omnia.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index b2f0088e5e..3b7a71bdad 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -1007,6 +1007,25 @@ static int fixup_mcu_gpio_in_eth_wan_node(void *blob)
return 0;
 }
 
+static void fixup_atsha_node(void *blob)
+{
+   int node;
+
+   if (!omnia_mcu_has_feature(FEAT_CRYPTO))
+   return;
+
+   node = fdt_node_offset_by_compatible(blob, -1, "atmel,atsha204a");
+   if (node < 0) {
+   printf("Cannot find ATSHA204A node!\n");
+   return;
+   }
+
+   if (fdt_status_disabled(blob, node) < 0)
+   printf("Cannot disable ATSHA204A node!\n");
+   else
+   debug("Disabled ATSHA204A node\n");
+}
+
 #endif
 
 #if IS_ENABLED(CONFIG_OF_BOARD_FIXUP)
@@ -1020,6 +1039,8 @@ int board_fix_fdt(void *blob)
fixup_msata_port_nodes(blob);
fixup_wwan_port_nodes(blob);
 
+   fixup_atsha_node(blob);
+
return 0;
 }
 #endif
@@ -1211,6 +1232,8 @@ int ft_board_setup(void *blob, struct bd_info *bd)
fixup_msata_port_nodes(blob);
fixup_wwan_port_nodes(blob);
 
+   fixup_atsha_node(blob);
+
return 0;
 }
 #endif
-- 
2.43.2



[PATCH u-boot-mvebu v4 06/18] arm: mvebu: turris_omnia: Print board ECDSA public key if available

2024-04-04 Thread Marek Behún
If MCU supports the FEAT_CRYPTO feature, read board ECDSA public key
from MCU and print it.

Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 board/CZ.NIC/turris_omnia/turris_omnia.c | 25 +++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index f63640ad64..b2f0088e5e 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -253,6 +253,24 @@ static int omnia_mcu_board_info(char *serial, u8 *mac, 
char *version)
return 0;
 }
 
+static int omnia_mcu_get_board_public_key(char pub_key[static 67])
+{
+   u8 reply[34];
+   int ret;
+
+   ret = omnia_mcu_read(CMD_CRYPTO_GET_PUBLIC_KEY, reply, sizeof(reply));
+   if (ret)
+   return ret;
+
+   if (reply[0] != 33)
+   return -EBADMSG;
+
+   bin2hex(pub_key, [1], 33);
+   pub_key[66] = '\0';
+
+   return 0;
+}
+
 static void enable_a385_watchdog(unsigned int timeout_minutes)
 {
struct sar_freq_modes sar_freq;
@@ -1032,7 +1050,7 @@ int board_late_init(void)
 
 int checkboard(void)
 {
-   char serial[17], version[4];
+   char serial[17], version[4], pub_key[67];
bool has_version;
int err;
 
@@ -1051,6 +1069,11 @@ int checkboard(void)
printf("  Board version: %s\n", has_version ? version : "unknown");
printf("  Serial Number: %s\n", !err ? serial : "unknown");
 
+   if (omnia_mcu_has_feature(FEAT_CRYPTO)) {
+   err = omnia_mcu_get_board_public_key(pub_key);
+   printf("  ECDSA Public Key: %s\n", !err ? pub_key : "unknown");
+   }
+
return 0;
 }
 
-- 
2.43.2



[PATCH u-boot-mvebu v4 05/18] arm: mvebu: turris_omnia: Implement getting board information from MCU

2024-04-04 Thread Marek Behún
Implement reading board serial number, first MAC address and board
version from MCU. MCU supports board information if the FEAT_BOARD_INFO
feature bit is set in MCU features.

Prefer getting board information from MCU if supported, fallback to
Atmel SHA chip.

Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 board/CZ.NIC/turris_atsha_otp.c  | 27 +--
 board/CZ.NIC/turris_common.c | 42 +++
 board/CZ.NIC/turris_common.h | 10 +++
 board/CZ.NIC/turris_omnia/Makefile   |  2 +-
 board/CZ.NIC/turris_omnia/turris_omnia.c | 94 +++-
 5 files changed, 145 insertions(+), 30 deletions(-)
 create mode 100644 board/CZ.NIC/turris_common.c
 create mode 100644 board/CZ.NIC/turris_common.h

diff --git a/board/CZ.NIC/turris_atsha_otp.c b/board/CZ.NIC/turris_atsha_otp.c
index a29fe36231..85eebcdf18 100644
--- a/board/CZ.NIC/turris_atsha_otp.c
+++ b/board/CZ.NIC/turris_atsha_otp.c
@@ -11,6 +11,7 @@
 #include 
 
 #include "turris_atsha_otp.h"
+#include "turris_common.h"
 
 #define TURRIS_ATSHA_OTP_VERSION   0
 #define TURRIS_ATSHA_OTP_SERIAL1
@@ -32,26 +33,6 @@ static struct udevice *get_atsha204a_dev(void)
return dev;
 }
 
-static void increment_mac(u8 *mac)
-{
-   int i;
-
-   for (i = 5; i >= 3; i--) {
-   mac[i] += 1;
-   if (mac[i])
-   break;
-   }
-}
-
-static void set_mac_if_invalid(int i, u8 *mac)
-{
-   u8 oldmac[6];
-
-   if (is_valid_ethaddr(mac) &&
-   !eth_env_get_enetaddr_by_index("eth", i, oldmac))
-   eth_env_set_enetaddr_by_index("eth", i, mac);
-}
-
 int turris_atsha_otp_init_mac_addresses(int first_idx)
 {
struct udevice *dev = get_atsha204a_dev();
@@ -84,11 +65,7 @@ int turris_atsha_otp_init_mac_addresses(int first_idx)
mac[4] = mac1[2];
mac[5] = mac1[3];
 
-   set_mac_if_invalid((first_idx + 0) % 3, mac);
-   increment_mac(mac);
-   set_mac_if_invalid((first_idx + 1) % 3, mac);
-   increment_mac(mac);
-   set_mac_if_invalid((first_idx + 2) % 3, mac);
+   turris_init_mac_addresses(first_idx, mac);
 
return 0;
 }
diff --git a/board/CZ.NIC/turris_common.c b/board/CZ.NIC/turris_common.c
new file mode 100644
index 00..1717dda82e
--- /dev/null
+++ b/board/CZ.NIC/turris_common.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Marek Behún 
+ */
+
+#include 
+#include 
+
+#include "turris_common.h"
+
+static void increment_mac(u8 *mac)
+{
+   int i;
+
+   for (i = 5; i >= 3; i--) {
+   mac[i] += 1;
+   if (mac[i])
+   break;
+   }
+}
+
+static void set_mac_if_invalid(int i, u8 *mac)
+{
+   u8 oldmac[6];
+
+   if (is_valid_ethaddr(mac) &&
+   !eth_env_get_enetaddr_by_index("eth", i, oldmac))
+   eth_env_set_enetaddr_by_index("eth", i, mac);
+}
+
+void turris_init_mac_addresses(int first_idx, const u8 *first_mac)
+{
+   u8 mac[6];
+
+   memcpy(mac, first_mac, sizeof(mac));
+
+   set_mac_if_invalid((first_idx + 0) % 3, mac);
+   increment_mac(mac);
+   set_mac_if_invalid((first_idx + 1) % 3, mac);
+   increment_mac(mac);
+   set_mac_if_invalid((first_idx + 2) % 3, mac);
+}
diff --git a/board/CZ.NIC/turris_common.h b/board/CZ.NIC/turris_common.h
new file mode 100644
index 00..5565ea9fd2
--- /dev/null
+++ b/board/CZ.NIC/turris_common.h
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#ifndef TURRIS_COMMON_H
+#define TURRIS_COMMON_H
+
+#include 
+
+void turris_init_mac_addresses(int first_idx, const u8 *first_mac);
+
+#endif
diff --git a/board/CZ.NIC/turris_omnia/Makefile 
b/board/CZ.NIC/turris_omnia/Makefile
index dc39b44ae1..341378b4e5 100644
--- a/board/CZ.NIC/turris_omnia/Makefile
+++ b/board/CZ.NIC/turris_omnia/Makefile
@@ -2,4 +2,4 @@
 #
 # Copyright (C) 2017 Marek Behún 
 
-obj-y  := turris_omnia.o ../turris_atsha_otp.o
+obj-y  := turris_omnia.o ../turris_atsha_otp.o ../turris_common.o
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index 6dfde5ee7a..f63640ad64 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -25,12 +26,14 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
 #include "../drivers/ddr/marvell/a38x/ddr3_init.h"
 #include <../serdes/a38x/high_speed_env_spec.h>
 #include "../turris_atsha_otp.h"
+#include "../turris_common.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -186,6 +189,70 @@ static bool omnia_mcu_has_feature(u32 feature)
return feature & features;
 }
 
+static u32 omnia_mcu_crc32(const void *p, size_t len)
+{
+   u32 val, crc = 0;

[PATCH u-boot-mvebu v4 04/18] arm: mvebu: turris_omnia: Update MCU status and features reading

2024-04-04 Thread Marek Behún
Refactor MCU status word and MCU firmware features reading to make it
simpler to use.

Try reading 32 bits of features, if that fails, read 16 bits. Older MCU
firmware supports only 16-bit wide features, and if more bytes are read,
either 0xff is sent or I2C transaction fails. Handle both cases.

Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 board/CZ.NIC/turris_omnia/turris_omnia.c | 100 +++
 1 file changed, 68 insertions(+), 32 deletions(-)

diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index 87e33d88c4..6dfde5ee7a 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -133,6 +133,59 @@ static int omnia_mcu_write(u8 cmd, const void *buf, int 
len)
return dm_i2c_write(chip, cmd, buf, len);
 }
 
+static int omnia_mcu_get_sts_and_features(u16 *psts, u32 *pfeatures)
+{
+   u16 sts, feat16;
+   int ret;
+
+   ret = omnia_mcu_read(CMD_GET_STATUS_WORD, , sizeof(sts));
+   if (ret)
+   return ret;
+
+   if (psts)
+   *psts = sts;
+
+   if (!pfeatures)
+   return 0;
+
+   if (sts & STS_FEATURES_SUPPORTED) {
+   /* try read 32-bit features */
+   ret = omnia_mcu_read(CMD_GET_FEATURES, pfeatures,
+sizeof(*pfeatures));
+   if (ret) {
+   /* try read 16-bit features */
+   ret = omnia_mcu_read(CMD_GET_FEATURES, ,
+sizeof());
+   if (ret)
+   return ret;
+
+   *pfeatures = feat16;
+   } else {
+   if (*pfeatures & FEAT_FROM_BIT_16_INVALID)
+   *pfeatures &= GENMASK(15, 0);
+   }
+   } else {
+   *pfeatures = 0;
+   }
+
+   return 0;
+}
+
+static int omnia_mcu_get_sts(u16 *sts)
+{
+   return omnia_mcu_get_sts_and_features(sts, NULL);
+}
+
+static bool omnia_mcu_has_feature(u32 feature)
+{
+   u32 features;
+
+   if (omnia_mcu_get_sts_and_features(NULL, ))
+   return false;
+
+   return feature & features;
+}
+
 static void enable_a385_watchdog(unsigned int timeout_minutes)
 {
struct sar_freq_modes sar_freq;
@@ -194,7 +247,7 @@ static bool disable_mcu_watchdog(void)
 static bool omnia_detect_sata(const char *msata_slot)
 {
int ret;
-   u16 stsword;
+   u16 sts;
 
puts("MiniPCIe/mSATA card detection... ");
 
@@ -210,24 +263,24 @@ static bool omnia_detect_sata(const char *msata_slot)
}
}
 
-   ret = omnia_mcu_read(CMD_GET_STATUS_WORD, , sizeof(stsword));
+   ret = omnia_mcu_get_sts();
if (ret) {
printf("omnia_mcu_read failed: %i, defaulting to MiniPCIe 
card\n",
   ret);
return false;
}
 
-   if (!(stsword & STS_CARD_DET)) {
+   if (!(sts & STS_CARD_DET)) {
puts("none\n");
return false;
}
 
-   if (stsword & STS_MSATA_IND)
+   if (sts & STS_MSATA_IND)
puts("mSATA\n");
else
puts("MiniPCIe\n");
 
-   return stsword & STS_MSATA_IND;
+   return sts & STS_MSATA_IND;
 }
 
 static bool omnia_detect_wwan_usb3(const char *wwan_slot)
@@ -355,14 +408,14 @@ static int omnia_get_ram_size_gb(void)
 static const char * const omnia_get_mcu_type(void)
 {
static char result[] = "xxx (with peripheral resets)";
-   u16 stsword, features;
+   u16 sts;
int ret;
 
-   ret = omnia_mcu_read(CMD_GET_STATUS_WORD, , sizeof(stsword));
+   ret = omnia_mcu_get_sts();
if (ret)
return "unknown";
 
-   switch (stsword & STS_MCU_TYPE_MASK) {
+   switch (sts & STS_MCU_TYPE_MASK) {
case STS_MCU_TYPE_STM32:
strcpy(result, "STM32");
break;
@@ -377,11 +430,8 @@ static const char * const omnia_get_mcu_type(void)
break;
}
 
-   if (stsword & STS_FEATURES_SUPPORTED) {
-   ret = omnia_mcu_read(CMD_GET_FEATURES, , 
sizeof(features));
-   if (ret == 0 && (features & FEAT_PERIPH_MCU))
-   strcat(result, " (with peripheral resets)");
-   }
+   if (omnia_mcu_has_feature(FEAT_PERIPH_MCU))
+   strcat(result, " (with peripheral resets)");
 
return result;
 }
@@ -660,9 +710,6 @@ int board_early_init_f(void)
 
 void spl_board_init(void)
 {
-   u16 val;
-   int ret;
-
/*
 * If booting from UART, disable MCU watchdog in SPL, since uploading
 * U-Boot proper can take too much time and trigger it. Ins

[PATCH u-boot-mvebu v4 03/18] arm: mvebu: turris_{omnia, mox}: Don't print model two times

2024-04-04 Thread Marek Behún
Since commit 8cd4bf7dc9ba ("turris: Use checkboard() instead of
show_board_info()") the model is show two times during boot:
  Model: Turris Omnia
  Model: Turris Omnia

This is because the common function show_board_info() shows it, and
Turris' checkboard() also does.

Remove the second print.

Fixes: 8cd4bf7dc9ba ("turris: Use checkboard() instead of show_board_info()")
Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 board/CZ.NIC/turris_mox/turris_mox.c | 5 +
 board/CZ.NIC/turris_omnia/turris_omnia.c | 1 -
 2 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/board/CZ.NIC/turris_mox/turris_mox.c 
b/board/CZ.NIC/turris_mox/turris_mox.c
index 3489bdd74b..1a2f60e3d1 100644
--- a/board/CZ.NIC/turris_mox/turris_mox.c
+++ b/board/CZ.NIC/turris_mox/turris_mox.c
@@ -565,13 +565,10 @@ static void handle_reset_button(void)
 int checkboard(void)
 {
int i, ret, board_version, ram_size, is_sd;
-   const char *pub_key, *model;
+   const char *pub_key;
const u8 *topology;
u64 serial_number;
 
-   model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
-   printf("Model: %s\n", model);
-
ret = mbox_sp_get_board_info(_number, NULL, NULL, _version,
 _size, NULL);
if (ret < 0) {
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index 6c2d7da528..87e33d88c4 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -933,7 +933,6 @@ int checkboard(void)
int err;
 
err = turris_atsha_otp_get_serial_number(serial);
-   printf("Model: Turris Omnia\n");
printf("  MCU type: %s\n", omnia_get_mcu_type());
printf("  MCU version: %s\n", omnia_get_mcu_version());
printf("  RAM size: %i MiB\n", omnia_get_ram_size_gb() * 1024);
-- 
2.43.2



[PATCH u-boot-mvebu v4 02/18] arm: mvebu: turris_omnia: Add header containing MCU command interface and use it

2024-04-04 Thread Marek Behún
Add header containing all MCU command definitions and use it in board
code and in MCU driver.

Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 board/CZ.NIC/turris_omnia/turris_omnia.c |  81 +++-
 drivers/gpio/turris_omnia_mcu.c  |  54 +
 include/turris-omnia-mcu-interface.h | 248 +++
 3 files changed, 272 insertions(+), 111 deletions(-)
 create mode 100644 include/turris-omnia-mcu-interface.h

diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index adeb69a205..6c2d7da528 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -59,46 +60,6 @@ DECLARE_GLOBAL_DATA_PTR;
 #define A385_WD_RSTOUT_UNMASK  MVEBU_REGISTER(0x20704)
 #define   A385_WD_RSTOUT_UNMASK_GLOBAL BIT(8)
 
-enum mcu_commands {
-   CMD_GET_STATUS_WORD = 0x01,
-   CMD_GET_RESET   = 0x09,
-   CMD_GET_FW_VERSION_APP  = 0x0a,
-   CMD_WATCHDOG_STATE  = 0x0b,
-   CMD_GET_FW_VERSION_BOOT = 0x0e,
-
-   /* available if STS_FEATURES_SUPPORTED bit set in status word */
-   CMD_GET_FEATURES= 0x10,
-
-   /* available if EXT_CMD bit set in features */
-   CMD_EXT_CONTROL = 0x12,
-};
-
-enum status_word_bits {
-   STS_MCU_TYPE_MASK   = GENMASK(1, 0),
-   STS_MCU_TYPE_STM32  = 0,
-   STS_MCU_TYPE_GD32   = 1,
-   STS_MCU_TYPE_MKL= 2,
-   STS_MCU_TYPE_UNKN   = 3,
-   STS_FEATURES_SUPPORTED  = BIT(2),
-   CARD_DET_STSBIT = 0x0010,
-   MSATA_IND_STSBIT= 0x0020,
-};
-
-/* CMD_GET_FEATURES */
-enum features_e {
-   FEAT_PERIPH_MCU = BIT(0),
-   FEAT_EXT_CMDS   = BIT(1),
-};
-
-/* CMD_EXT_CONTROL */
-enum ext_ctl_e {
-   EXT_CTL_nRES_LAN= BIT(1),
-   EXT_CTL_nRES_PHY= BIT(2),
-   EXT_CTL_nPERST0 = BIT(3),
-   EXT_CTL_nPERST1 = BIT(4),
-   EXT_CTL_nPERST2 = BIT(5),
-};
-
 /*
  * Those values and defines are taken from the Marvell U-Boot version
  * "u-boot-2013.01-2014_T3.0"
@@ -219,7 +180,7 @@ static bool disable_mcu_watchdog(void)
 
puts("Disabling MCU watchdog... ");
 
-   ret = omnia_mcu_write(CMD_WATCHDOG_STATE, "\x00", 1);
+   ret = omnia_mcu_write(CMD_SET_WATCHDOG_STATE, "\x00", 1);
if (ret) {
printf("omnia_mcu_write failed: %i\n", ret);
return false;
@@ -256,17 +217,17 @@ static bool omnia_detect_sata(const char *msata_slot)
return false;
}
 
-   if (!(stsword & CARD_DET_STSBIT)) {
+   if (!(stsword & STS_CARD_DET)) {
puts("none\n");
return false;
}
 
-   if (stsword & MSATA_IND_STSBIT)
+   if (stsword & STS_MSATA_IND)
puts("mSATA\n");
else
puts("MiniPCIe\n");
 
-   return stsword & MSATA_IND_STSBIT ? true : false;
+   return stsword & STS_MSATA_IND;
 }
 
 static bool omnia_detect_wwan_usb3(const char *wwan_slot)
@@ -393,18 +354,7 @@ static int omnia_get_ram_size_gb(void)
 
 static const char * const omnia_get_mcu_type(void)
 {
-   static const char * const mcu_types[] = {
-   [STS_MCU_TYPE_STM32] = "STM32",
-   [STS_MCU_TYPE_GD32]  = "GD32",
-   [STS_MCU_TYPE_MKL]   = "MKL",
-   [STS_MCU_TYPE_UNKN]  = "unknown",
-   };
-   static const char * const mcu_types_with_perip_resets[] = {
-   [STS_MCU_TYPE_STM32] = "STM32 (with peripheral resets)",
-   [STS_MCU_TYPE_GD32]  = "GD32 (with peripheral resets)",
-   [STS_MCU_TYPE_MKL]   = "MKL (with peripheral resets)",
-   [STS_MCU_TYPE_UNKN]  = "unknown (with peripheral resets)",
-   };
+   static char result[] = "xxx (with peripheral resets)";
u16 stsword, features;
int ret;
 
@@ -412,13 +362,28 @@ static const char * const omnia_get_mcu_type(void)
if (ret)
return "unknown";
 
+   switch (stsword & STS_MCU_TYPE_MASK) {
+   case STS_MCU_TYPE_STM32:
+   strcpy(result, "STM32");
+   break;
+   case STS_MCU_TYPE_GD32:
+   strcpy(result, "GD32");
+   break;
+   case STS_MCU_TYPE_MKL:
+   strcpy(result, "MKL");
+   break;
+   default:
+   strcpy(result, "unknown");
+   break;
+   }
+
if (stsword & STS_FEATURES_SUPPORTED) {
ret = omnia_mcu_read(CMD_GET_FEATURES, , 
sizeof(features));
if (ret == 0 &

[PATCH u-boot-mvebu v4 01/18] arm: mvebu: turris_omnia: Enable LTO by default on Turris Omnia

2024-04-04 Thread Marek Behún
U-Boot builds for Turris Omnia are approaching the limit of 0xf
bytes, which is the size of the U-Boot partition on Omnia.

Enable LTO to get more size optimized binaries.

Signed-off-by: Marek Behún 
Reviewed-by: Stefan Roese 
---
 configs/turris_omnia_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 29148402a1..39e15043df 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -31,6 +31,7 @@ CONFIG_AHCI=y
 CONFIG_OF_BOARD_FIXUP=y
 CONFIG_SYS_MEMTEST_START=0x0080
 CONFIG_SYS_MEMTEST_END=0x00ff
+CONFIG_LTO=y
 CONFIG_HAS_BOARD_SIZE_LIMIT=y
 CONFIG_BOARD_SIZE_LIMIT=983040
 CONFIG_FIT=y
-- 
2.43.2



[PATCH u-boot-mvebu v4 00/18] Turris Omnia - New board revision support

2024-04-04 Thread Marek Behún
changes since v3:
- added missing files turris_common.c and turris_common.h to patch 05/18
- added comment to patch 11/18 before while (1); as discussed in v3

v1, v2 and v3 at:
  
https://patchwork.ozlabs.org/project/uboot/cover/20240304152148.3847-1-ka...@kernel.org/
  
https://patchwork.ozlabs.org/project/uboot/cover/20240323180711.5498-1-ka...@kernel.org/
  
https://patchwork.ozlabs.org/project/uboot/cover/20240327162355.24584-1-ka...@kernel.org/

Marek Behún (18):
  arm: mvebu: turris_omnia: Enable LTO by default on Turris Omnia
  arm: mvebu: turris_omnia: Add header containing MCU command interface
and use it
  arm: mvebu: turris_{omnia, mox}: Don't print model two times
  arm: mvebu: turris_omnia: Update MCU status and features reading
  arm: mvebu: turris_omnia: Implement getting board information from MCU
  arm: mvebu: turris_omnia: Print board ECDSA public key if available
  arm: mvebu: turris_omnia: Disable Atmel SHA node if not present
  arm: mvebu: spl: Do not build mvebu-reset in SPL
  arm: mvebu: system-controller: Rework to use UCLASS_SYSCON
  arm: mvebu: system-controller: Select mvebu-reset if DM_RESET &&
PCI_MVEBU
  arm: mvebu: system-controller: Add support for SYSRESET
  gpio: turris_omnia_mcu: Use byteorder conversion functions
  gpio: turris_omnia_mcu: Update firmware features reading
  gpio: turris_omnia_mcu: Add support for system power off via sysreset
  arm: mvebu: turris_omnia: Enable poweroff command via sysreset in
defconfig
  cmd: rng: Print "Abort" on -EINTR
  misc: turris_omnia_mcu: Add support for rng provided by MCU
  arm: mvebu: turris_omnia: Enable rng command in defconfig

 arch/arm/mach-mvebu/Kconfig  |  25 ++
 arch/arm/mach-mvebu/Makefile |   3 +-
 arch/arm/mach-mvebu/cpu.c|   2 +
 arch/arm/mach-mvebu/system-controller.c  | 145 ++--
 board/CZ.NIC/turris_atsha_otp.c  |  27 +-
 board/CZ.NIC/turris_common.c |  42 +++
 board/CZ.NIC/turris_common.h |  10 +
 board/CZ.NIC/turris_mox/turris_mox.c |   5 +-
 board/CZ.NIC/turris_omnia/Makefile   |   2 +-
 board/CZ.NIC/turris_omnia/turris_omnia.c | 310 -
 cmd/rng.c|   7 +-
 configs/turris_omnia_defconfig   |   6 +
 drivers/gpio/Kconfig |   7 -
 drivers/gpio/Makefile|   1 -
 drivers/gpio/turris_omnia_mcu.c  | 316 -
 drivers/misc/Kconfig |  11 +
 drivers/misc/Makefile|   1 +
 drivers/misc/turris_omnia_mcu.c  | 411 +++
 include/turris-omnia-mcu-interface.h | 248 ++
 19 files changed, 1097 insertions(+), 482 deletions(-)
 create mode 100644 board/CZ.NIC/turris_common.c
 create mode 100644 board/CZ.NIC/turris_common.h
 delete mode 100644 drivers/gpio/turris_omnia_mcu.c
 create mode 100644 drivers/misc/turris_omnia_mcu.c
 create mode 100644 include/turris-omnia-mcu-interface.h

-- 
2.43.2



Re: [PATCH u-boot-mvebu v3 00/18] Turris Omnia - New board revision support

2024-04-04 Thread Marek Behún
On Thu, 4 Apr 2024 08:38:02 +0200
Stefan Roese  wrote:

> Hi Marek,
> 
> On 3/27/24 17:23, Marek Behún wrote:
> > Hi Stefan,
> > 
> > this is v3 of series adding support for new board revision of Turris
> > Omnia.
> > 
> > Changes since v2:
> > - patch 2: updated MCU command interface header
> > - patch 6: fixed bug setting \0 as end of string in src array instead
> > of dst array after bin2hex() call
> > - patch 16: updated commit message (added the bit about ctrl+c)
> > 
> > v1 and v2 at:
> >
> > https://patchwork.ozlabs.org/project/uboot/cover/20240304152148.3847-1-ka...@kernel.org/
> >
> > https://patchwork.ozlabs.org/project/uboot/cover/20240323180711.5498-1-ka...@kernel.org/
> >   
> 
> After pushing there changes in my current master I get these build
> errors for "turris_omnia_defconfig":
> 
> make[1]: *** No rule to make target 
> 'board/CZ.NIC/turris_omnia/../turris_common.o', needed by 
> 'board/CZ.NIC/turris_omnia/built-in.o'.  Stop.
> make[1]: *** Waiting for unfinished jobs
> board/CZ.NIC/turris_omnia/../turris_atsha_otp.c:14:10: fatal error: 
> turris_common.h: No such file or directory
> 14 | #include "turris_common.h"
>|  ^
> compilation terminated.
> make[1]: *** [scripts/Makefile.build:257: 
> board/CZ.NIC/turris_omnia/../turris_atsha_otp.o] Error 1
> board/CZ.NIC/turris_omnia/turris_omnia.c:36:10: fatal error: 
> ../turris_common.h: No such file or directory
> 36 | #include "../turris_common.h"
>|  ^~~~
> compilation terminated.
> 
> Available here:
> 
> https://source.denx.de/u-boot/custodians/u-boot-marvell/-/commits/master?ref_type=heads
> 
> Could you please have a look?

I forgot to do a git add on the new files turris_common.c and
turris_common.h in patch 05/18. Will send v4.

Marek


Re: [PATCH u-boot-mvebu v3 11/18] arm: mvebu: system-controller: Add support for SYSRESET

2024-03-28 Thread Marek Behún
On Thu, 28 Mar 2024 14:01:22 +0100
Stefan Roese  wrote:

> On 3/28/24 12:21, Marek Behún wrote:
> > On Thu, 28 Mar 2024 11:04:45 +0100
> > Stefan Roese  wrote:
> >   
> >>> +static int mvebu_sysreset_request(struct udevice *dev, enum sysreset_t 
> >>> type)
> >>> +{
> >>> + struct regmap *regmap = syscon_get_regmap(dev->parent);
> >>> + uint bit;
> >>> +
> >>> + if (type != SYSRESET_COLD)
> >>> + return -EPROTONOSUPPORT;
> >>> +
> >>> + bit = MVEBU_GLOBAL_SOFT_RST_BIT;
> >>> +
> >>> + regmap_update_bits(regmap, MVEBU_RSTOUTN_MASK_REG, bit, bit);
> >>> + regmap_update_bits(regmap, MVEBU_SYS_SOFT_RST_REG, bit, bit);
> >>> +
> >>> + while (1)
> >>> + ;  
> >>
> >> A comment before this endless loop might be helpful here.  
> > 
> > The code does the same as reset_cpu() in cpu.c, and the while() cycle
> > is not commented there.  
> 
> Sure, other code might suffer this undocumented endless loop as well.
> And again, this is more a nitpicking comment than a real requirement.
> 
> > But we can add something like
> >/* something has gone wrong if we reach here, so we may as well stay
> > * here */
> > 
> > What do you think? Could you amend the patch?  
> 
> More something like this:
> 
>   /* Loop while waiting for the reset */
>   while (1)
>   ;

As of now I don't see a need for v4.

I may sent another patches regarding DDR training, but it will be
made on top of this series.

Marek


Re: [PATCH u-boot-mvebu v3 11/18] arm: mvebu: system-controller: Add support for SYSRESET

2024-03-28 Thread Marek Behún
On Thu, 28 Mar 2024 11:04:45 +0100
Stefan Roese  wrote:

> > +static int mvebu_sysreset_request(struct udevice *dev, enum sysreset_t 
> > type)
> > +{
> > +   struct regmap *regmap = syscon_get_regmap(dev->parent);
> > +   uint bit;
> > +
> > +   if (type != SYSRESET_COLD)
> > +   return -EPROTONOSUPPORT;
> > +
> > +   bit = MVEBU_GLOBAL_SOFT_RST_BIT;
> > +
> > +   regmap_update_bits(regmap, MVEBU_RSTOUTN_MASK_REG, bit, bit);
> > +   regmap_update_bits(regmap, MVEBU_SYS_SOFT_RST_REG, bit, bit);
> > +
> > +   while (1)
> > +   ;  
> 
> A comment before this endless loop might be helpful here.

The code does the same as reset_cpu() in cpu.c, and the while() cycle
is not commented there.

But we can add something like
  /* something has gone wrong if we reach here, so we may as well stay
   * here */

What do you think? Could you amend the patch?

Marek


Re: [PATCH u-boot-mvebu v3 05/18] arm: mvebu: turris_omnia: Implement getting board information from MCU

2024-03-28 Thread Marek Behún
On Thu, 28 Mar 2024 10:56:01 +0100
Stefan Roese  wrote:

> On 3/27/24 17:23, Marek Behún wrote:
> > Implement reading board serial number, first MAC address and board
> > version from MCU. MCU supports board information if the FEAT_BOARD_INFO
> > feature bit is set in MCU features.
> > 
> > Prefer getting board information from MCU if supported, fallback to
> > Atmel SHA chip.
> > 
> > Signed-off-by: Marek Behún   
> 
> Minor comment below. Other than this:
> 
> Reviewed-by: Stefan Roese 
> 
> Thanks,
> Stefan
> 
> > ---
> >   board/CZ.NIC/turris_atsha_otp.c  | 27 +--
> >   board/CZ.NIC/turris_omnia/Makefile   |  2 +-
> >   board/CZ.NIC/turris_omnia/turris_omnia.c | 94 +++-
> >   3 files changed, 93 insertions(+), 30 deletions(-)
> > 
> > diff --git a/board/CZ.NIC/turris_atsha_otp.c 
> > b/board/CZ.NIC/turris_atsha_otp.c
> > index a29fe36231..85eebcdf18 100644
> > --- a/board/CZ.NIC/turris_atsha_otp.c
> > +++ b/board/CZ.NIC/turris_atsha_otp.c
> > @@ -11,6 +11,7 @@
> >   #include 
> >   
> >   #include "turris_atsha_otp.h"
> > +#include "turris_common.h"
> >   
> >   #define TURRIS_ATSHA_OTP_VERSION  0
> >   #define TURRIS_ATSHA_OTP_SERIAL   1
> > @@ -32,26 +33,6 @@ static struct udevice *get_atsha204a_dev(void)
> > return dev;
> >   }
> >   
> > -static void increment_mac(u8 *mac)
> > -{
> > -   int i;
> > -
> > -   for (i = 5; i >= 3; i--) {
> > -   mac[i] += 1;
> > -   if (mac[i])
> > -   break;
> > -   }
> > -}
> > -
> > -static void set_mac_if_invalid(int i, u8 *mac)
> > -{
> > -   u8 oldmac[6];
> > -
> > -   if (is_valid_ethaddr(mac) &&
> > -   !eth_env_get_enetaddr_by_index("eth", i, oldmac))
> > -   eth_env_set_enetaddr_by_index("eth", i, mac);
> > -}
> > -
> >   int turris_atsha_otp_init_mac_addresses(int first_idx)
> >   {
> > struct udevice *dev = get_atsha204a_dev();
> > @@ -84,11 +65,7 @@ int turris_atsha_otp_init_mac_addresses(int first_idx)
> > mac[4] = mac1[2];
> > mac[5] = mac1[3];
> >   
> > -   set_mac_if_invalid((first_idx + 0) % 3, mac);
> > -   increment_mac(mac);
> > -   set_mac_if_invalid((first_idx + 1) % 3, mac);
> > -   increment_mac(mac);
> > -   set_mac_if_invalid((first_idx + 2) % 3, mac);
> > +   turris_init_mac_addresses(first_idx, mac);
> >   
> > return 0;
> >   }
> > diff --git a/board/CZ.NIC/turris_omnia/Makefile 
> > b/board/CZ.NIC/turris_omnia/Makefile
> > index dc39b44ae1..341378b4e5 100644
> > --- a/board/CZ.NIC/turris_omnia/Makefile
> > +++ b/board/CZ.NIC/turris_omnia/Makefile
> > @@ -2,4 +2,4 @@
> >   #
> >   # Copyright (C) 2017 Marek Behún 
> >   
> > -obj-y  := turris_omnia.o ../turris_atsha_otp.o
> > +obj-y  := turris_omnia.o ../turris_atsha_otp.o ../turris_common.o
> > diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
> > b/board/CZ.NIC/turris_omnia/turris_omnia.c
> > index 6dfde5ee7a..f63640ad64 100644
> > --- a/board/CZ.NIC/turris_omnia/turris_omnia.c
> > +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
> > @@ -18,6 +18,7 @@
> >   #include 
> >   #include 
> >   #include 
> > +#include 
> >   #include 
> >   #include 
> >   #include 
> > @@ -25,12 +26,14 @@
> >   #include 
> >   #include 
> >   #include 
> > +#include 
> >   #include 
> >   #include 
> >   
> >   #include "../drivers/ddr/marvell/a38x/ddr3_init.h"
> >   #include <../serdes/a38x/high_speed_env_spec.h>
> >   #include "../turris_atsha_otp.h"
> > +#include "../turris_common.h"
> >   
> >   DECLARE_GLOBAL_DATA_PTR;
> >   
> > @@ -186,6 +189,70 @@ static bool omnia_mcu_has_feature(u32 feature)
> > return feature & features;
> >   }
> >   
> > +static u32 omnia_mcu_crc32(const void *p, size_t len)
> > +{
> > +   u32 val, crc = 0;
> > +
> > +   compiletime_assert(!(len % 4), "length has to be a multiple of 4");
> > +
> > +   while (len) {
> > +   val = bitrev32(get_unaligned_le32(p));
> > +   crc = crc32(crc, (void *), 4);
> > +   p += 4;
> > +   len -= 4;
> > +   }
> > +
> > +   return ~bitrev32(crc);
> > +}
> > +
> > +/* Can only be called after relocatio

[PATCH u-boot-mvebu v3 18/18] arm: mvebu: turris_omnia: Enable rng command in defconfig

2024-03-27 Thread Marek Behún
Now that Turris Omnia has a rng driver provided in the MCU driver,
enable the rng command in defconfig.

Signed-off-by: Marek Behún 
---
 configs/turris_omnia_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 4c21635ec9..f2b39115fe 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -73,6 +73,7 @@ CONFIG_CMD_WDT=y
 CONFIG_CMD_TFTPPUT=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
+CONFIG_CMD_RNG=y
 CONFIG_CMD_AES=y
 CONFIG_CMD_HASH=y
 CONFIG_CMD_BTRFS=y
-- 
2.43.2



[PATCH u-boot-mvebu v3 17/18] misc: turris_omnia_mcu: Add support for rng provided by MCU

2024-03-27 Thread Marek Behún
Add support for true random number generator provided by the MCU on
Turris Omnia. The MCU firmware supports TRNG if the FEAT_TRNG bit is set
in features. In that case we bind the rng driver.

Signed-off-by: Marek Behún 
---
 configs/turris_omnia_defconfig  |  1 +
 drivers/misc/Kconfig|  1 +
 drivers/misc/turris_omnia_mcu.c | 57 +
 3 files changed, 59 insertions(+)

diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 0df0f3c90b..4c21635ec9 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -107,6 +107,7 @@ CONFIG_NVME_PCI=y
 CONFIG_PCI_MVEBU=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_ARMADA_38X=y
+CONFIG_DM_RNG=y
 CONFIG_DM_RTC=y
 CONFIG_RTC_ARMADA38X=y
 CONFIG_SERIAL_PROBE_ALL=y
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 844a21be47..a08f02196f 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -509,6 +509,7 @@ config TURRIS_OMNIA_MCU
bool "Enable Turris Omnia MCU driver"
depends on DM_I2C
depends on DM_GPIO
+   depends on DM_RNG
depends on SYSRESET
default y if TARGET_TURRIS_OMNIA
help
diff --git a/drivers/misc/turris_omnia_mcu.c b/drivers/misc/turris_omnia_mcu.c
index 77a0424d61..6b2f17c000 100644
--- a/drivers/misc/turris_omnia_mcu.c
+++ b/drivers/misc/turris_omnia_mcu.c
@@ -5,15 +5,20 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 
+#define CMD_TRNG_MAX_ENTROPY_LEN   64
+
 struct turris_omnia_mcu_info {
u32 features;
 };
@@ -282,6 +287,49 @@ U_BOOT_DRIVER(turris_omnia_mcu_sysreset) = {
.ops= _sysreset_ops,
 };
 
+static int omnia_rng_read(struct udevice *dev, void *data, size_t count)
+{
+   u8 buf[1 + CMD_TRNG_MAX_ENTROPY_LEN];
+   size_t len;
+   int ret;
+
+   while (count) {
+   ret = dm_i2c_read(dev->parent, CMD_TRNG_COLLECT_ENTROPY, buf,
+ sizeof(buf));
+   if (ret)
+   return ret;
+
+   len = min_t(size_t, buf[0],
+   min_t(size_t, CMD_TRNG_MAX_ENTROPY_LEN, count));
+
+   if (!len) {
+   /* wait 500ms (fail if interrupted), then try again */
+   for (int i = 0; i < 5; ++i) {
+   mdelay(100);
+   if (ctrlc())
+   return -EINTR;
+   }
+   continue;
+   }
+
+   memcpy(data, [1], len);
+   data += len;
+   count -= len;
+   }
+
+   return 0;
+}
+
+static const struct dm_rng_ops omnia_rng_ops = {
+   .read   = omnia_rng_read,
+};
+
+U_BOOT_DRIVER(turris_omnia_mcu_trng) = {
+   .name   = "turris-omnia-mcu-trng",
+   .id = UCLASS_RNG,
+   .ops= _rng_ops,
+};
+
 static int turris_omnia_mcu_bind(struct udevice *dev)
 {
/* bind MCU GPIOs as a child device */
@@ -336,6 +384,15 @@ static int turris_omnia_mcu_probe(struct udevice *dev)
return ret;
}
 
+   /* bind rng if trng is supported */
+   if (info->features & FEAT_TRNG) {
+   ret = device_bind_driver_to_node(dev, "turris-omnia-mcu-trng",
+"turris-omnia-mcu-trng",
+dev_ofnode(dev), NULL);
+   if (ret < 0)
+   return ret;
+   }
+
return 0;
 }
 
-- 
2.43.2



[PATCH u-boot-mvebu v3 16/18] cmd: rng: Print "Abort" on -EINTR

2024-03-27 Thread Marek Behún
In the rng command, print
  Abort
instead of
  Reading RNG failed
if the error number is -EINTR, which can happen if the user pressed
CTRL-C.

Signed-off-by: Marek Behún 
---
 cmd/rng.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/cmd/rng.c b/cmd/rng.c
index 52f722c7af..48ba67061b 100644
--- a/cmd/rng.c
+++ b/cmd/rng.c
@@ -17,7 +17,7 @@ static int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
u8 buf[64];
int devnum;
struct udevice *dev;
-   int ret = CMD_RET_SUCCESS;
+   int ret = CMD_RET_SUCCESS, err;
 
switch (argc) {
case 1:
@@ -46,8 +46,9 @@ static int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
 
n = min(n, sizeof(buf));
 
-   if (dm_rng_read(dev, buf, n)) {
-   printf("Reading RNG failed\n");
+   err = dm_rng_read(dev, buf, n);
+   if (err) {
+   puts(err == -EINTR ? "Abort\n" : "Reading RNG failed\n");
ret = CMD_RET_FAILURE;
} else {
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, n);
-- 
2.43.2



[PATCH u-boot-mvebu v3 15/18] arm: mvebu: turris_omnia: Enable poweroff command via sysreset in defconfig

2024-03-27 Thread Marek Behún
Enable support for the poweroff command via sysreset for Turris Omnia.

Signed-off-by: Marek Behún 
---
 configs/turris_omnia_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 9d5171c6a8..0df0f3c90b 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -65,6 +65,7 @@ CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_MTD=y
 CONFIG_CMD_PCI=y
+CONFIG_CMD_POWEROFF=y
 CONFIG_CMD_SATA=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
@@ -114,6 +115,7 @@ CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_KIRKWOOD_SPI=y
 CONFIG_SYSRESET=y
+CONFIG_SYSRESET_CMD_POWEROFF=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
-- 
2.43.2



[PATCH u-boot-mvebu v3 14/18] gpio: turris_omnia_mcu: Add support for system power off via sysreset

2024-03-27 Thread Marek Behún
Add support for system power off via UCLASS_SYSRESET. Newer versions of
Turris Omnia MCU firmware can power off the board (MCU will disable
almost all voltage regulators and go into low power mode).

Move the MCU driver into drivers/misc and register it under UCLASS_MISC.
The sysreset and gpio device are bound as child devices of the MCU device.

Signed-off-by: Marek Behún 
---
 configs/turris_omnia_defconfig|   1 +
 drivers/gpio/Kconfig  |   7 -
 drivers/gpio/Makefile |   1 -
 drivers/misc/Kconfig  |  10 ++
 drivers/misc/Makefile |   1 +
 drivers/{gpio => misc}/turris_omnia_mcu.c | 150 --
 6 files changed, 120 insertions(+), 50 deletions(-)
 rename drivers/{gpio => misc}/turris_omnia_mcu.c (60%)

diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 39e15043df..9d5171c6a8 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -113,6 +113,7 @@ CONFIG_SPL_DEBUG_UART_BASE=0xd0012000
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_KIRKWOOD_SPI=y
+CONFIG_SYSRESET=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 2df3dc42d0..020c6ae74c 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -662,13 +662,6 @@ config SLG7XL45106_I2C_GPO
   8-bit gpo expander, all gpo lines are controlled by writing
   value into data register.
 
-config TURRIS_OMNIA_MCU
-   bool "Turris Omnia MCU GPIO driver"
-   depends on DM_GPIO
-   default y if TARGET_TURRIS_OMNIA
-   help
-  Support for GPIOs on MCU connected to Turris Omnia via i2c.
-
 config FTGPIO010
bool "Faraday Technology FTGPIO010 driver"
depends on DM_GPIO
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index da3da5da2b..d637895c7a 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -73,7 +73,6 @@ obj-$(CONFIG_$(SPL_)MAX77663_GPIO)+= max77663_gpio.o
 obj-$(CONFIG_SL28CPLD_GPIO)+= sl28cpld-gpio.o
 obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN)  += zynqmp_gpio_modepin.o
 obj-$(CONFIG_SLG7XL45106_I2C_GPO)  += gpio_slg7xl45106.o
-obj-$(CONFIG_$(SPL_TPL_)TURRIS_OMNIA_MCU)  += turris_omnia_mcu.o
 obj-$(CONFIG_FTGPIO010)+= ftgpio010.o
 obj-$(CONFIG_ADP5585_GPIO) += adp5585_gpio.o
 obj-$(CONFIG_RZG2L_GPIO)   += rzg2l-gpio.o
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index f11ce72525..844a21be47 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -505,6 +505,16 @@ config TEST_DRV
  model. This should only be enabled for testing as it is not useful for
  anything else.
 
+config TURRIS_OMNIA_MCU
+   bool "Enable Turris Omnia MCU driver"
+   depends on DM_I2C
+   depends on DM_GPIO
+   depends on SYSRESET
+   default y if TARGET_TURRIS_OMNIA
+   help
+ This enables support for Turris Omnia MCU connected GPIOs and
+ board power off.
+
 config USB_HUB_USB251XB
tristate "USB251XB Hub Controller Configuration Driver"
depends on I2C
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 0432db6ed1..3cd8e2fd48 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_SYS_DPAA_QBMAN) += fsl_portals.o
 obj-$(CONFIG_TEGRA186_BPMP) += tegra186_bpmp.o
 obj-$(CONFIG_TEGRA_CAR) += tegra_car.o
 obj-$(CONFIG_TEST_DRV) += test_drv.o
+obj-$(CONFIG_$(SPL_TPL_)TURRIS_OMNIA_MCU) += turris_omnia_mcu.o
 obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
 obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress_config.o
 obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o
diff --git a/drivers/gpio/turris_omnia_mcu.c b/drivers/misc/turris_omnia_mcu.c
similarity index 60%
rename from drivers/gpio/turris_omnia_mcu.c
rename to drivers/misc/turris_omnia_mcu.c
index 40ced261e3..77a0424d61 100644
--- a/drivers/gpio/turris_omnia_mcu.c
+++ b/drivers/misc/turris_omnia_mcu.c
@@ -1,9 +1,14 @@
 // SPDX-License-Identifier: GPL-2.0+
-// (C) 2022 Pali Rohár 
+/*
+ * Copyright (C) 2022 Pali Rohár 
+ * Copyright (C) 2024 Marek Behún 
+ */
 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -13,9 +18,9 @@ struct turris_omnia_mcu_info {
u32 features;
 };
 
-static int turris_omnia_mcu_get_function(struct udevice *dev, uint offset)
+static int omnia_gpio_get_function(struct udevice *dev, uint offset)
 {
-   struct turris_omnia_mcu_info *info = dev_get_plat(dev);
+   struct turris_omnia_mcu_info *info = dev_get_priv(dev->parent);
 
switch (offset) {
/* bank 0 */
@@ -49,9 +54,9 @@ static int turris_omnia_mcu_get_function(struct udevice *dev, 
uint offset)
}
 }
 
-static int turris_omnia_mcu_get_value(struct udevice *dev, uint offset)
+static int omnia_gpio_get_value(struct udevice *dev, uint offset)
 {
-   

[PATCH u-boot-mvebu v3 13/18] gpio: turris_omnia_mcu: Update firmware features reading

2024-03-27 Thread Marek Behún
Update firmware features reading to try reading 32 bits of features and
fallback to reading 16 bits.

Signed-off-by: Marek Behún 
---
 drivers/gpio/turris_omnia_mcu.c | 32 ++--
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/gpio/turris_omnia_mcu.c b/drivers/gpio/turris_omnia_mcu.c
index c441d07d69..40ced261e3 100644
--- a/drivers/gpio/turris_omnia_mcu.c
+++ b/drivers/gpio/turris_omnia_mcu.c
@@ -10,7 +10,7 @@
 #include 
 
 struct turris_omnia_mcu_info {
-   u16 features;
+   u32 features;
 };
 
 static int turris_omnia_mcu_get_function(struct udevice *dev, uint offset)
@@ -228,25 +228,37 @@ static int turris_omnia_mcu_probe(struct udevice *dev)
 {
struct turris_omnia_mcu_info *info = dev_get_plat(dev);
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
-   u16 val;
+   u32 dword;
+   u16 word;
int ret;
 
-   ret = dm_i2c_read(dev, CMD_GET_STATUS_WORD, (void *), sizeof(val));
+   ret = dm_i2c_read(dev, CMD_GET_STATUS_WORD, (void *), 
sizeof(word));
if (ret < 0) {
printf("Error: turris_omnia_mcu CMD_GET_STATUS_WORD failed: 
%d\n",
   ret);
return ret;
}
 
-   if (le16_to_cpu(val) & STS_FEATURES_SUPPORTED) {
-   ret = dm_i2c_read(dev, CMD_GET_FEATURES, (void *),
- sizeof(val));
+   if (le16_to_cpu(word) & STS_FEATURES_SUPPORTED) {
+   /* try read 32-bit features */
+   ret = dm_i2c_read(dev, CMD_GET_FEATURES, (void *),
+ sizeof(dword));
if (ret < 0) {
-   printf("Error: turris_omnia_mcu CMD_GET_FEATURES 
failed: %d\n",
-  ret);
-   return ret;
+   /* try read 16-bit features */
+   ret = dm_i2c_read(dev, CMD_GET_FEATURES, (void *),
+ sizeof(word));
+   if (ret < 0) {
+   printf("Error: turris_omnia_mcu 
CMD_GET_FEATURES failed: %d\n",
+  ret);
+   return ret;
+   }
+
+   info->features = le16_to_cpu(word);
+   } else {
+   info->features = le32_to_cpu(dword);
+   if (info->features & FEAT_FROM_BIT_16_INVALID)
+   info->features &= GENMASK(15, 0);
}
-   info->features = le16_to_cpu(val);
}
 
uc_priv->bank_name = "mcu_";
-- 
2.43.2



[PATCH u-boot-mvebu v3 12/18] gpio: turris_omnia_mcu: Use byteorder conversion functions

2024-03-27 Thread Marek Behún
Use byteorder conversion function instead of manually assembling data
from/to MCU.

Signed-off-by: Marek Behún 
---
 drivers/gpio/turris_omnia_mcu.c | 80 +++--
 1 file changed, 46 insertions(+), 34 deletions(-)

diff --git a/drivers/gpio/turris_omnia_mcu.c b/drivers/gpio/turris_omnia_mcu.c
index da9a6efe6d..c441d07d69 100644
--- a/drivers/gpio/turris_omnia_mcu.c
+++ b/drivers/gpio/turris_omnia_mcu.c
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -51,27 +52,31 @@ static int turris_omnia_mcu_get_function(struct udevice 
*dev, uint offset)
 static int turris_omnia_mcu_get_value(struct udevice *dev, uint offset)
 {
struct turris_omnia_mcu_info *info = dev_get_plat(dev);
-   u8 val16[2];
-   u8 val32[4];
+   u32 val32;
+   u16 val16;
int ret;
 
switch (offset) {
/* bank 0 */
case 0 ... 15:
-   ret = dm_i2c_read(dev, CMD_GET_STATUS_WORD, val16, 2);
+   ret = dm_i2c_read(dev, CMD_GET_STATUS_WORD, (void *),
+ sizeof(val16));
if (ret)
return ret;
-   return u16)val16[1] << 8) | val16[0]) >> offset) & 0x1;
+
+   return !!(le16_to_cpu(val16) & BIT(offset));
 
/* bank 1 - supported only when FEAT_EXT_CMDS is set */
case (16 + 0) ... (16 + 31):
if (!(info->features & FEAT_EXT_CMDS))
return -EINVAL;
-   ret = dm_i2c_read(dev, CMD_GET_EXT_STATUS_DWORD, val32, 4);
+
+   ret = dm_i2c_read(dev, CMD_GET_EXT_STATUS_DWORD, (void *),
+ sizeof(val32));
if (ret)
return ret;
-   return u32)val32[3] << 24) | ((u32)val32[2] << 16) |
-((u32)val32[1] << 8) | val32[0]) >> (offset - 16)) & 
0x1;
+
+   return !!(le32_to_cpu(val32) & BIT(offset - 16));
 
/* bank 2 - supported only when FEAT_EXT_CMDS and FEAT_PERIPH_MCU is 
set */
case (16 + 32 + 0) ... (16 + 32 + 15):
@@ -79,10 +84,13 @@ static int turris_omnia_mcu_get_value(struct udevice *dev, 
uint offset)
return -EINVAL;
if (!(info->features & FEAT_PERIPH_MCU))
return -EINVAL;
-   ret = dm_i2c_read(dev, CMD_GET_EXT_CONTROL_STATUS, val16, 2);
+
+   ret = dm_i2c_read(dev, CMD_GET_EXT_CONTROL_STATUS,
+ (void *), sizeof(val16));
if (ret)
return ret;
-   return u16)val16[1] << 8) | val16[0]) >> (offset - 16 - 
32)) & 0x1;
+
+   return !!(le16_to_cpu(val16) & BIT(offset - 16 - 32));
 
default:
return -EINVAL;
@@ -92,30 +100,33 @@ static int turris_omnia_mcu_get_value(struct udevice *dev, 
uint offset)
 static int turris_omnia_mcu_set_value(struct udevice *dev, uint offset, int 
value)
 {
struct turris_omnia_mcu_info *info = dev_get_plat(dev);
-   u8 val16[2];
-   u8 val32[4];
+   u16 valmask16[2];
+   u8 valmask8[2];
 
switch (offset) {
/* bank 0 */
case 0 ... 15:
switch (offset) {
case ilog2(STS_USB30_PWRON):
-   val16[1] = CTL_USB30_PWRON;
+   valmask8[1] = CTL_USB30_PWRON;
break;
case ilog2(STS_USB31_PWRON):
-   val16[1] = CTL_USB31_PWRON;
+   valmask8[1] = CTL_USB31_PWRON;
break;
case ilog2(STS_ENABLE_4V5):
-   val16[1] = CTL_ENABLE_4V5;
+   valmask8[1] = CTL_ENABLE_4V5;
break;
case ilog2(STS_BUTTON_MODE):
-   val16[1] = CTL_BUTTON_MODE;
+   valmask8[1] = CTL_BUTTON_MODE;
break;
default:
return -EINVAL;
}
-   val16[0] = value ? val16[1] : 0;
-   return dm_i2c_write(dev, CMD_GENERAL_CONTROL, val16, 
sizeof(val16));
+
+   valmask8[0] = value ? valmask8[1] : 0;
+
+   return dm_i2c_write(dev, CMD_GENERAL_CONTROL, valmask8,
+   sizeof(valmask8));
 
/* bank 2 - supported only when FEAT_EXT_CMDS and FEAT_PERIPH_MCU is 
set */
case (16 + 32 + 0) ... (16 + 32 + 15):
@@ -123,11 +134,12 @@ static int turris_omnia_mcu_set_value(struct udevice 
*dev, uint offset, int valu
return -EINVAL;
if (!(info->features & FEAT_PERIPH_MCU))
return -EINVAL;
-   val32[3] = BIT(offset - 16 - 32) >> 8;
-   val32[2] = BIT(offset - 16 - 32) 

[PATCH u-boot-mvebu v3 10/18] arm: mvebu: system-controller: Select mvebu-reset if DM_RESET && PCI_MVEBU

2024-03-27 Thread Marek Behún
The mvebu-reset driver is only needed by the mvebu PCIe driver, but
currently it is automatically selected if DM_RESET is enabled. Add the
condition of PCI_MVEBU also being enabled for mvebu-reset to be
selected.

Signed-off-by: Marek Behún 
---
 arch/arm/mach-mvebu/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 62a2bc5958..623432a60e 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -18,7 +18,7 @@ config ARMADA_32BIT
select TOOLS_KWBIMAGE if SPL
select SPL_SYS_NO_VECTOR_TABLE if SPL
select ARCH_VERY_EARLY_INIT
-   select ARMADA_32BIT_SYSCON_RESET if DM_RESET
+   select ARMADA_32BIT_SYSCON_RESET if DM_RESET && PCI_MVEBU
 
 # ARMv7 SoCs...
 config ARMADA_375
-- 
2.43.2



[PATCH u-boot-mvebu v3 11/18] arm: mvebu: system-controller: Add support for SYSRESET

2024-03-27 Thread Marek Behún
Add driver model support for sysreset via mvebu system controller. This is
currently only available for U-Boot proper.

Signed-off-by: Marek Behún 
---
 arch/arm/mach-mvebu/Kconfig | 18 +-
 arch/arm/mach-mvebu/Makefile|  2 +-
 arch/arm/mach-mvebu/cpu.c   |  2 +
 arch/arm/mach-mvebu/system-controller.c | 74 +++--
 4 files changed, 89 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 623432a60e..f15d3cc5ed 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -19,6 +19,7 @@ config ARMADA_32BIT
select SPL_SYS_NO_VECTOR_TABLE if SPL
select ARCH_VERY_EARLY_INIT
select ARMADA_32BIT_SYSCON_RESET if DM_RESET && PCI_MVEBU
+   select ARMADA_32BIT_SYSCON_SYSRESET if SYSRESET
 
 # ARMv7 SoCs...
 config ARMADA_375
@@ -457,16 +458,29 @@ config SF_DEFAULT_MODE
default 0x0
depends on MVEBU_SPL_BOOT_DEVICE_SPI
 
+config ARMADA_32BIT_SYSCON
+   bool
+   depends on ARMADA_32BIT
+   select REGMAP
+   select SYSCON
+
 config ARMADA_32BIT_SYSCON_RESET
bool "Support Armada XP/375/38x/39x reset controller"
depends on ARMADA_32BIT
depends on DM_RESET
-   select REGMAP
-   select SYSCON
+   select ARMADA_32BIT_SYSCON
help
  Build support for Armada XP/375/38x/39x reset controller. This is
  needed for PCIe support.
 
+config ARMADA_32BIT_SYSCON_SYSRESET
+   bool "Support Armada XP/375/38x/39x sysreset via driver model"
+   depends on ARMADA_32BIT
+   depends on SYSRESET
+   select ARMADA_32BIT_SYSCON
+   help
+ Build support for Armada XP/375/38x/39x system reset via driver model.
+
 source "board/solidrun/clearfog/Kconfig"
 source "board/kobol/helios4/Kconfig"
 
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index d44ca3a0df..329c2e4915 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -28,7 +28,7 @@ obj-$(CONFIG_ARMADA_38X) += 
../../../drivers/ddr/marvell/a38x/xor.o
 obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_MSYS) += ../../../drivers/ddr/marvell/axp/xor.o
 
-obj-$(CONFIG_ARMADA_32BIT_SYSCON_RESET) += system-controller.o
+obj-$(CONFIG_ARMADA_32BIT_SYSCON) += system-controller.o
 
 ifdef CONFIG_ARMADA_38X
 obj-$(CONFIG_MVEBU_EFUSE) += efuse.o
diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c
index 8e0de93538..7c62a5dbb6 100644
--- a/arch/arm/mach-mvebu/cpu.c
+++ b/arch/arm/mach-mvebu/cpu.c
@@ -52,6 +52,7 @@ void lowlevel_init(void)
 */
 }
 
+#if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_ARMADA_32BIT_SYSCON_SYSRESET)
 void reset_cpu(void)
 {
struct mvebu_system_registers *reg =
@@ -62,6 +63,7 @@ void reset_cpu(void)
while (1)
;
 }
+#endif
 
 u32 get_boot_device(void)
 {
diff --git a/arch/arm/mach-mvebu/system-controller.c 
b/arch/arm/mach-mvebu/system-controller.c
index c5c05922f2..b5f8afb96d 100644
--- a/arch/arm/mach-mvebu/system-controller.c
+++ b/arch/arm/mach-mvebu/system-controller.c
@@ -10,11 +10,24 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
-#define MVEBU_SOC_CONTROL_1_REG 0x4
+#define MVEBU_SOC_CONTROL_1_REG0x4
 
-#define MVEBU_PCIE_ID 0
+#if defined(CONFIG_ARMADA_375)
+# define MVEBU_RSTOUTN_MASK_REG0x54
+# define MVEBU_SYS_SOFT_RST_REG0x58
+#else
+# define MVEBU_RSTOUTN_MASK_REG0x60
+# define MVEBU_SYS_SOFT_RST_REG0x64
+#endif
+
+#define MVEBU_GLOBAL_SOFT_RST_BIT  BIT(0)
+
+#define MVEBU_PCIE_ID  0
+
+#if IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_RESET)
 
 static int mvebu_reset_of_xlate(struct reset_ctl *rst,
struct ofnode_phandle_args *args)
@@ -90,11 +103,64 @@ U_BOOT_DRIVER(mvebu_reset) = {
.ops = _reset_ops,
 };
 
+#endif /* IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_RESET) */
+
+#if IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_SYSRESET)
+
+static int mvebu_sysreset_request(struct udevice *dev, enum sysreset_t type)
+{
+   struct regmap *regmap = syscon_get_regmap(dev->parent);
+   uint bit;
+
+   if (type != SYSRESET_COLD)
+   return -EPROTONOSUPPORT;
+
+   bit = MVEBU_GLOBAL_SOFT_RST_BIT;
+
+   regmap_update_bits(regmap, MVEBU_RSTOUTN_MASK_REG, bit, bit);
+   regmap_update_bits(regmap, MVEBU_SYS_SOFT_RST_REG, bit, bit);
+
+   while (1)
+   ;
+
+   return 0;
+}
+
+static struct sysreset_ops mvebu_sysreset_ops = {
+   .request = mvebu_sysreset_request,
+};
+
+U_BOOT_DRIVER(mvebu_sysreset) = {
+   .name = "mvebu-sysreset",
+   .id = UCLASS_SYSRESET,
+   .ops = _sysreset_ops,
+};
+
+#endif /* IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_SYSRESET) */
+
 static int mvebu_syscon_bind(struct udevice *de

[PATCH u-boot-mvebu v3 09/18] arm: mvebu: system-controller: Rework to use UCLASS_SYSCON

2024-03-27 Thread Marek Behún
The system-controller driver for 32-bit Armada is currently registered
as UCLASS_RESET, since it only provides enabling/disabling PCIe ports.

Rework it as UCLASS_SYSCON and bind mvebu-reset as a child device.

Signed-off-by: Marek Behún 
---
 arch/arm/mach-mvebu/Kconfig | 11 
 arch/arm/mach-mvebu/Makefile|  2 +-
 arch/arm/mach-mvebu/system-controller.c | 76 ++---
 3 files changed, 54 insertions(+), 35 deletions(-)

diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 2058c95ca2..62a2bc5958 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -18,6 +18,7 @@ config ARMADA_32BIT
select TOOLS_KWBIMAGE if SPL
select SPL_SYS_NO_VECTOR_TABLE if SPL
select ARCH_VERY_EARLY_INIT
+   select ARMADA_32BIT_SYSCON_RESET if DM_RESET
 
 # ARMv7 SoCs...
 config ARMADA_375
@@ -456,6 +457,16 @@ config SF_DEFAULT_MODE
default 0x0
depends on MVEBU_SPL_BOOT_DEVICE_SPI
 
+config ARMADA_32BIT_SYSCON_RESET
+   bool "Support Armada XP/375/38x/39x reset controller"
+   depends on ARMADA_32BIT
+   depends on DM_RESET
+   select REGMAP
+   select SYSCON
+   help
+ Build support for Armada XP/375/38x/39x reset controller. This is
+ needed for PCIe support.
+
 source "board/solidrun/clearfog/Kconfig"
 source "board/kobol/helios4/Kconfig"
 
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index ef790d97fe..d44ca3a0df 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -28,7 +28,7 @@ obj-$(CONFIG_ARMADA_38X) += 
../../../drivers/ddr/marvell/a38x/xor.o
 obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_MSYS) += ../../../drivers/ddr/marvell/axp/xor.o
 
-obj-$(CONFIG_DM_RESET) += system-controller.o
+obj-$(CONFIG_ARMADA_32BIT_SYSCON_RESET) += system-controller.o
 
 ifdef CONFIG_ARMADA_38X
 obj-$(CONFIG_MVEBU_EFUSE) += efuse.o
diff --git a/arch/arm/mach-mvebu/system-controller.c 
b/arch/arm/mach-mvebu/system-controller.c
index 7cdde11cbd..c5c05922f2 100644
--- a/arch/arm/mach-mvebu/system-controller.c
+++ b/arch/arm/mach-mvebu/system-controller.c
@@ -1,19 +1,21 @@
 // SPDX-License-Identifier: GPL-2.0+
-// (C) 2021 Pali Rohár 
+/*
+ * Copyright (C) 2021 Pali Rohár 
+ * Copyright (C) 2024 Marek Behún 
+ */
 
 #include 
 #include 
+#include 
+#include 
 #include 
+#include 
 #include 
 
 #define MVEBU_SOC_CONTROL_1_REG 0x4
 
 #define MVEBU_PCIE_ID 0
 
-struct mvebu_reset_data {
-   void *base;
-};
-
 static int mvebu_reset_of_xlate(struct reset_ctl *rst,
struct ofnode_phandle_args *args)
 {
@@ -46,46 +48,33 @@ static int mvebu_reset_free(struct reset_ctl *rst)
 
 static int mvebu_reset_assert(struct reset_ctl *rst)
 {
-   struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+   struct regmap *regmap = syscon_get_regmap(rst->dev->parent);
 
-   clrbits_32(data->base + MVEBU_SOC_CONTROL_1_REG, BIT(rst->data));
-   return 0;
+   return regmap_update_bits(regmap, MVEBU_SOC_CONTROL_1_REG,
+ BIT(rst->data), 0);
 }
 
 static int mvebu_reset_deassert(struct reset_ctl *rst)
 {
-   struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+   struct regmap *regmap = syscon_get_regmap(rst->dev->parent);
 
-   setbits_32(data->base + MVEBU_SOC_CONTROL_1_REG, BIT(rst->data));
-   return 0;
+   return regmap_update_bits(regmap, MVEBU_SOC_CONTROL_1_REG,
+ BIT(rst->data), BIT(rst->data));
 }
 
 static int mvebu_reset_status(struct reset_ctl *rst)
 {
-   struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+   struct regmap *regmap = syscon_get_regmap(rst->dev->parent);
+   uint val;
+   int ret;
 
-   return !(readl(data->base + MVEBU_SOC_CONTROL_1_REG) & BIT(rst->data));
-}
-
-static int mvebu_reset_of_to_plat(struct udevice *dev)
-{
-   struct mvebu_reset_data *data = dev_get_priv(dev);
+   ret = regmap_read(regmap, MVEBU_SOC_CONTROL_1_REG, );
+   if (ret < 0)
+   return ret;
 
-   data->base = dev_read_addr_ptr(dev);
-   if (!data->base)
-   return -EINVAL;
-
-   return 0;
+   return !(val & BIT(rst->data));
 }
 
-static const struct udevice_id mvebu_reset_of_match[] = {
-   { .compatible = "marvell,armada-370-xp-system-controller" },
-   { .compatible = "marvell,armada-375-system-controller" },
-   { .compatible = "marvell,armada-380-system-controller" },
-   { .compatible = "marvell,armada-390-system-controller" },
-   { },
-};
-
 static const struct reset_ops mvebu_reset_ops = {
.of_xlate = mvebu_reset_of_xlate,
.request = mvebu_reset_request,
@@ -98,8 +87,27 @@ static const struct reset_ops mvebu_r

[PATCH u-boot-mvebu v3 08/18] arm: mvebu: spl: Do not build mvebu-reset in SPL

2024-03-27 Thread Marek Behún
Commit 35e29e89a386 ("arm: mvebu: Implement simple mvebu-reset driver
for enabling/disabling PCIe ports") made it so that the mvebu reset
driver for enabling/disabling PCIe ports is build if CONFIG_DM_RESET is
enabled. This is because PCI_MVEBU depends on DM_RESET.

But the driver should not be built for SPL. Indeed the PCI_MVEBU driver
is not supported in SPL now, and so the mvebu-reset driver is not needed.

Signed-off-by: Marek Behún 
---
 arch/arm/mach-mvebu/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index 0584ed2be5..ef790d97fe 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -22,13 +22,14 @@ else # CONFIG_ARCH_KIRKWOOD
 obj-y  = cpu.o
 obj-y  += dram.o
 obj-y  += lowlevel.o
-obj-$(CONFIG_DM_RESET) += system-controller.o
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_ARMADA_375) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_38X) += ../../../drivers/ddr/marvell/a38x/xor.o
 obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_MSYS) += ../../../drivers/ddr/marvell/axp/xor.o
 
+obj-$(CONFIG_DM_RESET) += system-controller.o
+
 ifdef CONFIG_ARMADA_38X
 obj-$(CONFIG_MVEBU_EFUSE) += efuse.o
 endif
-- 
2.43.2



[PATCH u-boot-mvebu v3 07/18] arm: mvebu: turris_omnia: Disable Atmel SHA node if not present

2024-03-27 Thread Marek Behún
If the FEAT_CRYPTO feature bit is present in MCU features, the board
crypto is implemented by MCU and the Atmel SHA chip is not present.
Disable Atmel SHA device-tree node in that case.

Signed-off-by: Marek Behún 
---
 board/CZ.NIC/turris_omnia/turris_omnia.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index b2f0088e5e..3b7a71bdad 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -1007,6 +1007,25 @@ static int fixup_mcu_gpio_in_eth_wan_node(void *blob)
return 0;
 }
 
+static void fixup_atsha_node(void *blob)
+{
+   int node;
+
+   if (!omnia_mcu_has_feature(FEAT_CRYPTO))
+   return;
+
+   node = fdt_node_offset_by_compatible(blob, -1, "atmel,atsha204a");
+   if (node < 0) {
+   printf("Cannot find ATSHA204A node!\n");
+   return;
+   }
+
+   if (fdt_status_disabled(blob, node) < 0)
+   printf("Cannot disable ATSHA204A node!\n");
+   else
+   debug("Disabled ATSHA204A node\n");
+}
+
 #endif
 
 #if IS_ENABLED(CONFIG_OF_BOARD_FIXUP)
@@ -1020,6 +1039,8 @@ int board_fix_fdt(void *blob)
fixup_msata_port_nodes(blob);
fixup_wwan_port_nodes(blob);
 
+   fixup_atsha_node(blob);
+
return 0;
 }
 #endif
@@ -1211,6 +1232,8 @@ int ft_board_setup(void *blob, struct bd_info *bd)
fixup_msata_port_nodes(blob);
fixup_wwan_port_nodes(blob);
 
+   fixup_atsha_node(blob);
+
return 0;
 }
 #endif
-- 
2.43.2



[PATCH u-boot-mvebu v3 06/18] arm: mvebu: turris_omnia: Print board ECDSA public key if available

2024-03-27 Thread Marek Behún
If MCU supports the FEAT_CRYPTO feature, read board ECDSA public key
from MCU and print it.

Signed-off-by: Marek Behún 
---
 board/CZ.NIC/turris_omnia/turris_omnia.c | 25 +++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index f63640ad64..b2f0088e5e 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -253,6 +253,24 @@ static int omnia_mcu_board_info(char *serial, u8 *mac, 
char *version)
return 0;
 }
 
+static int omnia_mcu_get_board_public_key(char pub_key[static 67])
+{
+   u8 reply[34];
+   int ret;
+
+   ret = omnia_mcu_read(CMD_CRYPTO_GET_PUBLIC_KEY, reply, sizeof(reply));
+   if (ret)
+   return ret;
+
+   if (reply[0] != 33)
+   return -EBADMSG;
+
+   bin2hex(pub_key, [1], 33);
+   pub_key[66] = '\0';
+
+   return 0;
+}
+
 static void enable_a385_watchdog(unsigned int timeout_minutes)
 {
struct sar_freq_modes sar_freq;
@@ -1032,7 +1050,7 @@ int board_late_init(void)
 
 int checkboard(void)
 {
-   char serial[17], version[4];
+   char serial[17], version[4], pub_key[67];
bool has_version;
int err;
 
@@ -1051,6 +1069,11 @@ int checkboard(void)
printf("  Board version: %s\n", has_version ? version : "unknown");
printf("  Serial Number: %s\n", !err ? serial : "unknown");
 
+   if (omnia_mcu_has_feature(FEAT_CRYPTO)) {
+   err = omnia_mcu_get_board_public_key(pub_key);
+   printf("  ECDSA Public Key: %s\n", !err ? pub_key : "unknown");
+   }
+
return 0;
 }
 
-- 
2.43.2



[PATCH u-boot-mvebu v3 05/18] arm: mvebu: turris_omnia: Implement getting board information from MCU

2024-03-27 Thread Marek Behún
Implement reading board serial number, first MAC address and board
version from MCU. MCU supports board information if the FEAT_BOARD_INFO
feature bit is set in MCU features.

Prefer getting board information from MCU if supported, fallback to
Atmel SHA chip.

Signed-off-by: Marek Behún 
---
 board/CZ.NIC/turris_atsha_otp.c  | 27 +--
 board/CZ.NIC/turris_omnia/Makefile   |  2 +-
 board/CZ.NIC/turris_omnia/turris_omnia.c | 94 +++-
 3 files changed, 93 insertions(+), 30 deletions(-)

diff --git a/board/CZ.NIC/turris_atsha_otp.c b/board/CZ.NIC/turris_atsha_otp.c
index a29fe36231..85eebcdf18 100644
--- a/board/CZ.NIC/turris_atsha_otp.c
+++ b/board/CZ.NIC/turris_atsha_otp.c
@@ -11,6 +11,7 @@
 #include 
 
 #include "turris_atsha_otp.h"
+#include "turris_common.h"
 
 #define TURRIS_ATSHA_OTP_VERSION   0
 #define TURRIS_ATSHA_OTP_SERIAL1
@@ -32,26 +33,6 @@ static struct udevice *get_atsha204a_dev(void)
return dev;
 }
 
-static void increment_mac(u8 *mac)
-{
-   int i;
-
-   for (i = 5; i >= 3; i--) {
-   mac[i] += 1;
-   if (mac[i])
-   break;
-   }
-}
-
-static void set_mac_if_invalid(int i, u8 *mac)
-{
-   u8 oldmac[6];
-
-   if (is_valid_ethaddr(mac) &&
-   !eth_env_get_enetaddr_by_index("eth", i, oldmac))
-   eth_env_set_enetaddr_by_index("eth", i, mac);
-}
-
 int turris_atsha_otp_init_mac_addresses(int first_idx)
 {
struct udevice *dev = get_atsha204a_dev();
@@ -84,11 +65,7 @@ int turris_atsha_otp_init_mac_addresses(int first_idx)
mac[4] = mac1[2];
mac[5] = mac1[3];
 
-   set_mac_if_invalid((first_idx + 0) % 3, mac);
-   increment_mac(mac);
-   set_mac_if_invalid((first_idx + 1) % 3, mac);
-   increment_mac(mac);
-   set_mac_if_invalid((first_idx + 2) % 3, mac);
+   turris_init_mac_addresses(first_idx, mac);
 
return 0;
 }
diff --git a/board/CZ.NIC/turris_omnia/Makefile 
b/board/CZ.NIC/turris_omnia/Makefile
index dc39b44ae1..341378b4e5 100644
--- a/board/CZ.NIC/turris_omnia/Makefile
+++ b/board/CZ.NIC/turris_omnia/Makefile
@@ -2,4 +2,4 @@
 #
 # Copyright (C) 2017 Marek Behún 
 
-obj-y  := turris_omnia.o ../turris_atsha_otp.o
+obj-y  := turris_omnia.o ../turris_atsha_otp.o ../turris_common.o
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index 6dfde5ee7a..f63640ad64 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -25,12 +26,14 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
 #include "../drivers/ddr/marvell/a38x/ddr3_init.h"
 #include <../serdes/a38x/high_speed_env_spec.h>
 #include "../turris_atsha_otp.h"
+#include "../turris_common.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -186,6 +189,70 @@ static bool omnia_mcu_has_feature(u32 feature)
return feature & features;
 }
 
+static u32 omnia_mcu_crc32(const void *p, size_t len)
+{
+   u32 val, crc = 0;
+
+   compiletime_assert(!(len % 4), "length has to be a multiple of 4");
+
+   while (len) {
+   val = bitrev32(get_unaligned_le32(p));
+   crc = crc32(crc, (void *), 4);
+   p += 4;
+   len -= 4;
+   }
+
+   return ~bitrev32(crc);
+}
+
+/* Can only be called after relocation, since it needs cleared BSS */
+static int omnia_mcu_board_info(char *serial, u8 *mac, char *version)
+{
+   static u8 reply[17];
+   static bool cached;
+
+   if (!cached) {
+   u8 csum;
+   int ret;
+
+   ret = omnia_mcu_read(CMD_BOARD_INFO_GET, reply, sizeof(reply));
+   if (ret)
+   return ret;
+
+   if (reply[0] != 16)
+   return -EBADMSG;
+
+   csum = reply[16];
+   reply[16] = 0;
+
+   if ((omnia_mcu_crc32([1], 16) & 0xff) != csum)
+   return -EBADMSG;
+
+   cached = true;
+   }
+
+   if (serial) {
+   const char *serial_env;
+
+   serial_env = env_get("serial#");
+   if (serial_env && strlen(serial_env) == 16) {
+   strcpy(serial, serial_env);
+   } else {
+   sprintf(serial, "%016llX",
+   get_unaligned_le64([1]));
+   env_set("serial#", serial);
+   }
+   }
+
+   if (mac)
+   memcpy(mac, [9], ETH_ALEN);
+
+   if (version)
+   sprintf(version, "%u", reply[15]);
+
+   return 0;
+}
+
 static void enable_a385_watchdog(unsigned int timeout_minutes)
 {
struct sar_fre

[PATCH u-boot-mvebu v3 04/18] arm: mvebu: turris_omnia: Update MCU status and features reading

2024-03-27 Thread Marek Behún
Refactor MCU status word and MCU firmware features reading to make it
simpler to use.

Try reading 32 bits of features, if that fails, read 16 bits. Older MCU
firmware supports only 16-bit wide features, and if more bytes are read,
either 0xff is sent or I2C transaction fails. Handle both cases.

Signed-off-by: Marek Behún 
---
 board/CZ.NIC/turris_omnia/turris_omnia.c | 100 +++
 1 file changed, 68 insertions(+), 32 deletions(-)

diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index 87e33d88c4..6dfde5ee7a 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -133,6 +133,59 @@ static int omnia_mcu_write(u8 cmd, const void *buf, int 
len)
return dm_i2c_write(chip, cmd, buf, len);
 }
 
+static int omnia_mcu_get_sts_and_features(u16 *psts, u32 *pfeatures)
+{
+   u16 sts, feat16;
+   int ret;
+
+   ret = omnia_mcu_read(CMD_GET_STATUS_WORD, , sizeof(sts));
+   if (ret)
+   return ret;
+
+   if (psts)
+   *psts = sts;
+
+   if (!pfeatures)
+   return 0;
+
+   if (sts & STS_FEATURES_SUPPORTED) {
+   /* try read 32-bit features */
+   ret = omnia_mcu_read(CMD_GET_FEATURES, pfeatures,
+sizeof(*pfeatures));
+   if (ret) {
+   /* try read 16-bit features */
+   ret = omnia_mcu_read(CMD_GET_FEATURES, ,
+sizeof());
+   if (ret)
+   return ret;
+
+   *pfeatures = feat16;
+   } else {
+   if (*pfeatures & FEAT_FROM_BIT_16_INVALID)
+   *pfeatures &= GENMASK(15, 0);
+   }
+   } else {
+   *pfeatures = 0;
+   }
+
+   return 0;
+}
+
+static int omnia_mcu_get_sts(u16 *sts)
+{
+   return omnia_mcu_get_sts_and_features(sts, NULL);
+}
+
+static bool omnia_mcu_has_feature(u32 feature)
+{
+   u32 features;
+
+   if (omnia_mcu_get_sts_and_features(NULL, ))
+   return false;
+
+   return feature & features;
+}
+
 static void enable_a385_watchdog(unsigned int timeout_minutes)
 {
struct sar_freq_modes sar_freq;
@@ -194,7 +247,7 @@ static bool disable_mcu_watchdog(void)
 static bool omnia_detect_sata(const char *msata_slot)
 {
int ret;
-   u16 stsword;
+   u16 sts;
 
puts("MiniPCIe/mSATA card detection... ");
 
@@ -210,24 +263,24 @@ static bool omnia_detect_sata(const char *msata_slot)
}
}
 
-   ret = omnia_mcu_read(CMD_GET_STATUS_WORD, , sizeof(stsword));
+   ret = omnia_mcu_get_sts();
if (ret) {
printf("omnia_mcu_read failed: %i, defaulting to MiniPCIe 
card\n",
   ret);
return false;
}
 
-   if (!(stsword & STS_CARD_DET)) {
+   if (!(sts & STS_CARD_DET)) {
puts("none\n");
return false;
}
 
-   if (stsword & STS_MSATA_IND)
+   if (sts & STS_MSATA_IND)
puts("mSATA\n");
else
puts("MiniPCIe\n");
 
-   return stsword & STS_MSATA_IND;
+   return sts & STS_MSATA_IND;
 }
 
 static bool omnia_detect_wwan_usb3(const char *wwan_slot)
@@ -355,14 +408,14 @@ static int omnia_get_ram_size_gb(void)
 static const char * const omnia_get_mcu_type(void)
 {
static char result[] = "xxx (with peripheral resets)";
-   u16 stsword, features;
+   u16 sts;
int ret;
 
-   ret = omnia_mcu_read(CMD_GET_STATUS_WORD, , sizeof(stsword));
+   ret = omnia_mcu_get_sts();
if (ret)
return "unknown";
 
-   switch (stsword & STS_MCU_TYPE_MASK) {
+   switch (sts & STS_MCU_TYPE_MASK) {
case STS_MCU_TYPE_STM32:
strcpy(result, "STM32");
break;
@@ -377,11 +430,8 @@ static const char * const omnia_get_mcu_type(void)
break;
}
 
-   if (stsword & STS_FEATURES_SUPPORTED) {
-   ret = omnia_mcu_read(CMD_GET_FEATURES, , 
sizeof(features));
-   if (ret == 0 && (features & FEAT_PERIPH_MCU))
-   strcat(result, " (with peripheral resets)");
-   }
+   if (omnia_mcu_has_feature(FEAT_PERIPH_MCU))
+   strcat(result, " (with peripheral resets)");
 
return result;
 }
@@ -660,9 +710,6 @@ int board_early_init_f(void)
 
 void spl_board_init(void)
 {
-   u16 val;
-   int ret;
-
/*
 * If booting from UART, disable MCU watchdog in SPL, since uploading
 * U-Boot proper can take too much time and trigger it. Instead enable
@@ -679,12 +726

[PATCH u-boot-mvebu v3 02/18] arm: mvebu: turris_omnia: Add header containing MCU command interface and use it

2024-03-27 Thread Marek Behún
Add header containing all MCU command definitions and use it in board
code and in MCU driver.

Signed-off-by: Marek Behún 
---
 board/CZ.NIC/turris_omnia/turris_omnia.c |  81 +++-
 drivers/gpio/turris_omnia_mcu.c  |  54 +
 include/turris-omnia-mcu-interface.h | 248 +++
 3 files changed, 272 insertions(+), 111 deletions(-)
 create mode 100644 include/turris-omnia-mcu-interface.h

diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index adeb69a205..6c2d7da528 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -59,46 +60,6 @@ DECLARE_GLOBAL_DATA_PTR;
 #define A385_WD_RSTOUT_UNMASK  MVEBU_REGISTER(0x20704)
 #define   A385_WD_RSTOUT_UNMASK_GLOBAL BIT(8)
 
-enum mcu_commands {
-   CMD_GET_STATUS_WORD = 0x01,
-   CMD_GET_RESET   = 0x09,
-   CMD_GET_FW_VERSION_APP  = 0x0a,
-   CMD_WATCHDOG_STATE  = 0x0b,
-   CMD_GET_FW_VERSION_BOOT = 0x0e,
-
-   /* available if STS_FEATURES_SUPPORTED bit set in status word */
-   CMD_GET_FEATURES= 0x10,
-
-   /* available if EXT_CMD bit set in features */
-   CMD_EXT_CONTROL = 0x12,
-};
-
-enum status_word_bits {
-   STS_MCU_TYPE_MASK   = GENMASK(1, 0),
-   STS_MCU_TYPE_STM32  = 0,
-   STS_MCU_TYPE_GD32   = 1,
-   STS_MCU_TYPE_MKL= 2,
-   STS_MCU_TYPE_UNKN   = 3,
-   STS_FEATURES_SUPPORTED  = BIT(2),
-   CARD_DET_STSBIT = 0x0010,
-   MSATA_IND_STSBIT= 0x0020,
-};
-
-/* CMD_GET_FEATURES */
-enum features_e {
-   FEAT_PERIPH_MCU = BIT(0),
-   FEAT_EXT_CMDS   = BIT(1),
-};
-
-/* CMD_EXT_CONTROL */
-enum ext_ctl_e {
-   EXT_CTL_nRES_LAN= BIT(1),
-   EXT_CTL_nRES_PHY= BIT(2),
-   EXT_CTL_nPERST0 = BIT(3),
-   EXT_CTL_nPERST1 = BIT(4),
-   EXT_CTL_nPERST2 = BIT(5),
-};
-
 /*
  * Those values and defines are taken from the Marvell U-Boot version
  * "u-boot-2013.01-2014_T3.0"
@@ -219,7 +180,7 @@ static bool disable_mcu_watchdog(void)
 
puts("Disabling MCU watchdog... ");
 
-   ret = omnia_mcu_write(CMD_WATCHDOG_STATE, "\x00", 1);
+   ret = omnia_mcu_write(CMD_SET_WATCHDOG_STATE, "\x00", 1);
if (ret) {
printf("omnia_mcu_write failed: %i\n", ret);
return false;
@@ -256,17 +217,17 @@ static bool omnia_detect_sata(const char *msata_slot)
return false;
}
 
-   if (!(stsword & CARD_DET_STSBIT)) {
+   if (!(stsword & STS_CARD_DET)) {
puts("none\n");
return false;
}
 
-   if (stsword & MSATA_IND_STSBIT)
+   if (stsword & STS_MSATA_IND)
puts("mSATA\n");
else
puts("MiniPCIe\n");
 
-   return stsword & MSATA_IND_STSBIT ? true : false;
+   return stsword & STS_MSATA_IND;
 }
 
 static bool omnia_detect_wwan_usb3(const char *wwan_slot)
@@ -393,18 +354,7 @@ static int omnia_get_ram_size_gb(void)
 
 static const char * const omnia_get_mcu_type(void)
 {
-   static const char * const mcu_types[] = {
-   [STS_MCU_TYPE_STM32] = "STM32",
-   [STS_MCU_TYPE_GD32]  = "GD32",
-   [STS_MCU_TYPE_MKL]   = "MKL",
-   [STS_MCU_TYPE_UNKN]  = "unknown",
-   };
-   static const char * const mcu_types_with_perip_resets[] = {
-   [STS_MCU_TYPE_STM32] = "STM32 (with peripheral resets)",
-   [STS_MCU_TYPE_GD32]  = "GD32 (with peripheral resets)",
-   [STS_MCU_TYPE_MKL]   = "MKL (with peripheral resets)",
-   [STS_MCU_TYPE_UNKN]  = "unknown (with peripheral resets)",
-   };
+   static char result[] = "xxx (with peripheral resets)";
u16 stsword, features;
int ret;
 
@@ -412,13 +362,28 @@ static const char * const omnia_get_mcu_type(void)
if (ret)
return "unknown";
 
+   switch (stsword & STS_MCU_TYPE_MASK) {
+   case STS_MCU_TYPE_STM32:
+   strcpy(result, "STM32");
+   break;
+   case STS_MCU_TYPE_GD32:
+   strcpy(result, "GD32");
+   break;
+   case STS_MCU_TYPE_MKL:
+   strcpy(result, "MKL");
+   break;
+   default:
+   strcpy(result, "unknown");
+   break;
+   }
+
if (stsword & STS_FEATURES_SUPPORTED) {
ret = omnia_mcu_read(CMD_GET_FEATURES, , 
sizeof(features));
if (ret == 0 && (features & FEAT_PERIPH_MCU

[PATCH u-boot-mvebu v3 03/18] arm: mvebu: turris_{omnia, mox}: Don't print model two times

2024-03-27 Thread Marek Behún
Since commit 8cd4bf7dc9ba ("turris: Use checkboard() instead of
show_board_info()") the model is show two times during boot:
  Model: Turris Omnia
  Model: Turris Omnia

This is because the common function show_board_info() shows it, and
Turris' checkboard() also does.

Remove the second print.

Fixes: 8cd4bf7dc9ba ("turris: Use checkboard() instead of show_board_info()")
Signed-off-by: Marek Behún 
---
 board/CZ.NIC/turris_mox/turris_mox.c | 5 +
 board/CZ.NIC/turris_omnia/turris_omnia.c | 1 -
 2 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/board/CZ.NIC/turris_mox/turris_mox.c 
b/board/CZ.NIC/turris_mox/turris_mox.c
index 3489bdd74b..1a2f60e3d1 100644
--- a/board/CZ.NIC/turris_mox/turris_mox.c
+++ b/board/CZ.NIC/turris_mox/turris_mox.c
@@ -565,13 +565,10 @@ static void handle_reset_button(void)
 int checkboard(void)
 {
int i, ret, board_version, ram_size, is_sd;
-   const char *pub_key, *model;
+   const char *pub_key;
const u8 *topology;
u64 serial_number;
 
-   model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
-   printf("Model: %s\n", model);
-
ret = mbox_sp_get_board_info(_number, NULL, NULL, _version,
 _size, NULL);
if (ret < 0) {
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index 6c2d7da528..87e33d88c4 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -933,7 +933,6 @@ int checkboard(void)
int err;
 
err = turris_atsha_otp_get_serial_number(serial);
-   printf("Model: Turris Omnia\n");
printf("  MCU type: %s\n", omnia_get_mcu_type());
printf("  MCU version: %s\n", omnia_get_mcu_version());
printf("  RAM size: %i MiB\n", omnia_get_ram_size_gb() * 1024);
-- 
2.43.2



[PATCH u-boot-mvebu v3 01/18] arm: mvebu: turris_omnia: Enable LTO by default on Turris Omnia

2024-03-27 Thread Marek Behún
U-Boot builds for Turris Omnia are approaching the limit of 0xf
bytes, which is the size of the U-Boot partition on Omnia.

Enable LTO to get more size optimized binaries.

Signed-off-by: Marek Behún 
---
 configs/turris_omnia_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 29148402a1..39e15043df 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -31,6 +31,7 @@ CONFIG_AHCI=y
 CONFIG_OF_BOARD_FIXUP=y
 CONFIG_SYS_MEMTEST_START=0x0080
 CONFIG_SYS_MEMTEST_END=0x00ff
+CONFIG_LTO=y
 CONFIG_HAS_BOARD_SIZE_LIMIT=y
 CONFIG_BOARD_SIZE_LIMIT=983040
 CONFIG_FIT=y
-- 
2.43.2



[PATCH u-boot-mvebu v3 00/18] Turris Omnia - New board revision support

2024-03-27 Thread Marek Behún
Hi Stefan,

this is v3 of series adding support for new board revision of Turris
Omnia.

Changes since v2:
- patch 2: updated MCU command interface header
- patch 6: fixed bug setting \0 as end of string in src array instead
   of dst array after bin2hex() call
- patch 16: updated commit message (added the bit about ctrl+c)

v1 and v2 at:
  
https://patchwork.ozlabs.org/project/uboot/cover/20240304152148.3847-1-ka...@kernel.org/
  
https://patchwork.ozlabs.org/project/uboot/cover/20240323180711.5498-1-ka...@kernel.org/

Marek Behún (18):
  arm: mvebu: turris_omnia: Enable LTO by default on Turris Omnia
  arm: mvebu: turris_omnia: Add header containing MCU command interface
and use it
  arm: mvebu: turris_{omnia, mox}: Don't print model two times
  arm: mvebu: turris_omnia: Update MCU status and features reading
  arm: mvebu: turris_omnia: Implement getting board information from MCU
  arm: mvebu: turris_omnia: Print board ECDSA public key if available
  arm: mvebu: turris_omnia: Disable Atmel SHA node if not present
  arm: mvebu: spl: Do not build mvebu-reset in SPL
  arm: mvebu: system-controller: Rework to use UCLASS_SYSCON
  arm: mvebu: system-controller: Select mvebu-reset if DM_RESET &&
PCI_MVEBU
  arm: mvebu: system-controller: Add support for SYSRESET
  gpio: turris_omnia_mcu: Use byteorder conversion functions
  gpio: turris_omnia_mcu: Update firmware features reading
  gpio: turris_omnia_mcu: Add support for system power off via sysreset
  arm: mvebu: turris_omnia: Enable poweroff command via sysreset in
defconfig
  cmd: rng: Print "Abort" on -EINTR
  misc: turris_omnia_mcu: Add support for rng provided by MCU
  arm: mvebu: turris_omnia: Enable rng command in defconfig

 arch/arm/mach-mvebu/Kconfig  |  25 ++
 arch/arm/mach-mvebu/Makefile |   3 +-
 arch/arm/mach-mvebu/cpu.c|   2 +
 arch/arm/mach-mvebu/system-controller.c  | 144 ++--
 board/CZ.NIC/turris_atsha_otp.c  |  27 +-
 board/CZ.NIC/turris_mox/turris_mox.c |   5 +-
 board/CZ.NIC/turris_omnia/Makefile   |   2 +-
 board/CZ.NIC/turris_omnia/turris_omnia.c | 310 -
 cmd/rng.c|   7 +-
 configs/turris_omnia_defconfig   |   6 +
 drivers/gpio/Kconfig |   7 -
 drivers/gpio/Makefile|   1 -
 drivers/gpio/turris_omnia_mcu.c  | 316 -
 drivers/misc/Kconfig |  11 +
 drivers/misc/Makefile|   1 +
 drivers/misc/turris_omnia_mcu.c  | 411 +++
 include/turris-omnia-mcu-interface.h | 248 ++
 17 files changed, 1044 insertions(+), 482 deletions(-)
 delete mode 100644 drivers/gpio/turris_omnia_mcu.c
 create mode 100644 drivers/misc/turris_omnia_mcu.c
 create mode 100644 include/turris-omnia-mcu-interface.h

-- 
2.43.2



Re: [PATCH u-boot-mvebu v2 06/18] arm: mvebu: turris_omnia: Print board ECDSA public key if available

2024-03-25 Thread Marek Behún
On Sat, 23 Mar 2024 19:06:59 +0100
Marek Behún  wrote:

> If MCU supports the FEAT_CRYPTO feature, read board ECDSA public key
> from MCU and print it.
> 
> Signed-off-by: Marek Behún 
> ---
>  board/CZ.NIC/turris_omnia/turris_omnia.c | 25 +++-
>  1 file changed, 24 insertions(+), 1 deletion(-)
> 
> diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
> b/board/CZ.NIC/turris_omnia/turris_omnia.c
> index f63640ad64..896c14bb99 100644
> --- a/board/CZ.NIC/turris_omnia/turris_omnia.c
> +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
> @@ -253,6 +253,24 @@ static int omnia_mcu_board_info(char *serial, u8 *mac, 
> char *version)
>   return 0;
>  }
>  
> +static int omnia_mcu_get_board_public_key(char pub_key[static 67])
> +{
> + u8 reply[34];
> + int ret;
> +
> + ret = omnia_mcu_read(CMD_CRYPTO_GET_PUBLIC_KEY, reply, sizeof(reply));
> + if (ret)
> + return ret;
> +
> + if (reply[0] != 33)
> + return -EBADMSG;
> +
> + bin2hex(pub_key, [1], 33);
> + reply[66] = '\0';

Aargh, this should be pub_key[66] = '\0'.

And I noticed once more thing, so I will sent another version.


Re: [PATCH u-boot-mvebu v2 16/18] cmd: rng: Print "Abort" on -EINTR

2024-03-23 Thread Marek Behún
On Sat, 23 Mar 2024 19:30:20 +0100
Heinrich Schuchardt  wrote:

> Am 23. März 2024 19:07:09 MEZ schrieb "Marek Behún" :
> >In the rng command, print
> >  Abort
> >instead of
> >  Reading RNG failed
> >if the error number is -EINTR.  
> 
> 
> It is unclear what would be the user benefit.
> 
> 'Abort' relates to a user pressing CTRL-C?
> 

Precisely. The next patch of this series adds a rng driver that handles
ctrlc() events.

Marek


[PATCH u-boot-mvebu v2 17/18] misc: turris_omnia_mcu: Add support for rng provided by MCU

2024-03-23 Thread Marek Behún
Add support for true random number generator provided by the MCU on
Turris Omnia. The MCU firmware supports TRNG if the FEAT_TRNG bit is set
in features. In that case we bind the rng driver.

Signed-off-by: Marek Behún 
---
 configs/turris_omnia_defconfig  |  1 +
 drivers/misc/Kconfig|  1 +
 drivers/misc/turris_omnia_mcu.c | 57 +
 3 files changed, 59 insertions(+)

diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 0df0f3c90b..4c21635ec9 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -107,6 +107,7 @@ CONFIG_NVME_PCI=y
 CONFIG_PCI_MVEBU=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_ARMADA_38X=y
+CONFIG_DM_RNG=y
 CONFIG_DM_RTC=y
 CONFIG_RTC_ARMADA38X=y
 CONFIG_SERIAL_PROBE_ALL=y
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 844a21be47..a08f02196f 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -509,6 +509,7 @@ config TURRIS_OMNIA_MCU
bool "Enable Turris Omnia MCU driver"
depends on DM_I2C
depends on DM_GPIO
+   depends on DM_RNG
depends on SYSRESET
default y if TARGET_TURRIS_OMNIA
help
diff --git a/drivers/misc/turris_omnia_mcu.c b/drivers/misc/turris_omnia_mcu.c
index 77a0424d61..6b2f17c000 100644
--- a/drivers/misc/turris_omnia_mcu.c
+++ b/drivers/misc/turris_omnia_mcu.c
@@ -5,15 +5,20 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 
+#define CMD_TRNG_MAX_ENTROPY_LEN   64
+
 struct turris_omnia_mcu_info {
u32 features;
 };
@@ -282,6 +287,49 @@ U_BOOT_DRIVER(turris_omnia_mcu_sysreset) = {
.ops= _sysreset_ops,
 };
 
+static int omnia_rng_read(struct udevice *dev, void *data, size_t count)
+{
+   u8 buf[1 + CMD_TRNG_MAX_ENTROPY_LEN];
+   size_t len;
+   int ret;
+
+   while (count) {
+   ret = dm_i2c_read(dev->parent, CMD_TRNG_COLLECT_ENTROPY, buf,
+ sizeof(buf));
+   if (ret)
+   return ret;
+
+   len = min_t(size_t, buf[0],
+   min_t(size_t, CMD_TRNG_MAX_ENTROPY_LEN, count));
+
+   if (!len) {
+   /* wait 500ms (fail if interrupted), then try again */
+   for (int i = 0; i < 5; ++i) {
+   mdelay(100);
+   if (ctrlc())
+   return -EINTR;
+   }
+   continue;
+   }
+
+   memcpy(data, [1], len);
+   data += len;
+   count -= len;
+   }
+
+   return 0;
+}
+
+static const struct dm_rng_ops omnia_rng_ops = {
+   .read   = omnia_rng_read,
+};
+
+U_BOOT_DRIVER(turris_omnia_mcu_trng) = {
+   .name   = "turris-omnia-mcu-trng",
+   .id = UCLASS_RNG,
+   .ops= _rng_ops,
+};
+
 static int turris_omnia_mcu_bind(struct udevice *dev)
 {
/* bind MCU GPIOs as a child device */
@@ -336,6 +384,15 @@ static int turris_omnia_mcu_probe(struct udevice *dev)
return ret;
}
 
+   /* bind rng if trng is supported */
+   if (info->features & FEAT_TRNG) {
+   ret = device_bind_driver_to_node(dev, "turris-omnia-mcu-trng",
+"turris-omnia-mcu-trng",
+dev_ofnode(dev), NULL);
+   if (ret < 0)
+   return ret;
+   }
+
return 0;
 }
 
-- 
2.43.2



[PATCH u-boot-mvebu v2 18/18] arm: mvebu: turris_omnia: Enable rng command in defconfig

2024-03-23 Thread Marek Behún
Now that Turris Omnia has a rng driver provided in the MCU driver,
enable the rng command in defconfig.

Signed-off-by: Marek Behún 
---
 configs/turris_omnia_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 4c21635ec9..f2b39115fe 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -73,6 +73,7 @@ CONFIG_CMD_WDT=y
 CONFIG_CMD_TFTPPUT=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
+CONFIG_CMD_RNG=y
 CONFIG_CMD_AES=y
 CONFIG_CMD_HASH=y
 CONFIG_CMD_BTRFS=y
-- 
2.43.2



[PATCH u-boot-mvebu v2 16/18] cmd: rng: Print "Abort" on -EINTR

2024-03-23 Thread Marek Behún
In the rng command, print
  Abort
instead of
  Reading RNG failed
if the error number is -EINTR.

Signed-off-by: Marek Behún 
---
 cmd/rng.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/cmd/rng.c b/cmd/rng.c
index 52f722c7af..48ba67061b 100644
--- a/cmd/rng.c
+++ b/cmd/rng.c
@@ -17,7 +17,7 @@ static int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
u8 buf[64];
int devnum;
struct udevice *dev;
-   int ret = CMD_RET_SUCCESS;
+   int ret = CMD_RET_SUCCESS, err;
 
switch (argc) {
case 1:
@@ -46,8 +46,9 @@ static int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
 
n = min(n, sizeof(buf));
 
-   if (dm_rng_read(dev, buf, n)) {
-   printf("Reading RNG failed\n");
+   err = dm_rng_read(dev, buf, n);
+   if (err) {
+   puts(err == -EINTR ? "Abort\n" : "Reading RNG failed\n");
ret = CMD_RET_FAILURE;
} else {
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, n);
-- 
2.43.2



[PATCH u-boot-mvebu v2 15/18] arm: mvebu: turris_omnia: Enable poweroff command via sysreset in defconfig

2024-03-23 Thread Marek Behún
Enable support for the poweroff command via sysreset for Turris Omnia.

Signed-off-by: Marek Behún 
---
 configs/turris_omnia_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 9d5171c6a8..0df0f3c90b 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -65,6 +65,7 @@ CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_MTD=y
 CONFIG_CMD_PCI=y
+CONFIG_CMD_POWEROFF=y
 CONFIG_CMD_SATA=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
@@ -114,6 +115,7 @@ CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_KIRKWOOD_SPI=y
 CONFIG_SYSRESET=y
+CONFIG_SYSRESET_CMD_POWEROFF=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
-- 
2.43.2



[PATCH u-boot-mvebu v2 14/18] gpio: turris_omnia_mcu: Add support for system power off via sysreset

2024-03-23 Thread Marek Behún
Add support for system power off via UCLASS_SYSRESET. Newer versions of
Turris Omnia MCU firmware can power off the board (MCU will disable
almost all voltage regulators and go into low power mode).

Move the MCU driver into drivers/misc and register it under UCLASS_MISC.
The sysreset and gpio device are bound as child devices of the MCU device.

Signed-off-by: Marek Behún 
---
 configs/turris_omnia_defconfig|   1 +
 drivers/gpio/Kconfig  |   7 -
 drivers/gpio/Makefile |   1 -
 drivers/misc/Kconfig  |  10 ++
 drivers/misc/Makefile |   1 +
 drivers/{gpio => misc}/turris_omnia_mcu.c | 150 --
 6 files changed, 120 insertions(+), 50 deletions(-)
 rename drivers/{gpio => misc}/turris_omnia_mcu.c (60%)

diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 39e15043df..9d5171c6a8 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -113,6 +113,7 @@ CONFIG_SPL_DEBUG_UART_BASE=0xd0012000
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_KIRKWOOD_SPI=y
+CONFIG_SYSRESET=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 2df3dc42d0..020c6ae74c 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -662,13 +662,6 @@ config SLG7XL45106_I2C_GPO
   8-bit gpo expander, all gpo lines are controlled by writing
   value into data register.
 
-config TURRIS_OMNIA_MCU
-   bool "Turris Omnia MCU GPIO driver"
-   depends on DM_GPIO
-   default y if TARGET_TURRIS_OMNIA
-   help
-  Support for GPIOs on MCU connected to Turris Omnia via i2c.
-
 config FTGPIO010
bool "Faraday Technology FTGPIO010 driver"
depends on DM_GPIO
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index da3da5da2b..d637895c7a 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -73,7 +73,6 @@ obj-$(CONFIG_$(SPL_)MAX77663_GPIO)+= max77663_gpio.o
 obj-$(CONFIG_SL28CPLD_GPIO)+= sl28cpld-gpio.o
 obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN)  += zynqmp_gpio_modepin.o
 obj-$(CONFIG_SLG7XL45106_I2C_GPO)  += gpio_slg7xl45106.o
-obj-$(CONFIG_$(SPL_TPL_)TURRIS_OMNIA_MCU)  += turris_omnia_mcu.o
 obj-$(CONFIG_FTGPIO010)+= ftgpio010.o
 obj-$(CONFIG_ADP5585_GPIO) += adp5585_gpio.o
 obj-$(CONFIG_RZG2L_GPIO)   += rzg2l-gpio.o
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index f11ce72525..844a21be47 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -505,6 +505,16 @@ config TEST_DRV
  model. This should only be enabled for testing as it is not useful for
  anything else.
 
+config TURRIS_OMNIA_MCU
+   bool "Enable Turris Omnia MCU driver"
+   depends on DM_I2C
+   depends on DM_GPIO
+   depends on SYSRESET
+   default y if TARGET_TURRIS_OMNIA
+   help
+ This enables support for Turris Omnia MCU connected GPIOs and
+ board power off.
+
 config USB_HUB_USB251XB
tristate "USB251XB Hub Controller Configuration Driver"
depends on I2C
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 0432db6ed1..3cd8e2fd48 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_SYS_DPAA_QBMAN) += fsl_portals.o
 obj-$(CONFIG_TEGRA186_BPMP) += tegra186_bpmp.o
 obj-$(CONFIG_TEGRA_CAR) += tegra_car.o
 obj-$(CONFIG_TEST_DRV) += test_drv.o
+obj-$(CONFIG_$(SPL_TPL_)TURRIS_OMNIA_MCU) += turris_omnia_mcu.o
 obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
 obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress_config.o
 obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o
diff --git a/drivers/gpio/turris_omnia_mcu.c b/drivers/misc/turris_omnia_mcu.c
similarity index 60%
rename from drivers/gpio/turris_omnia_mcu.c
rename to drivers/misc/turris_omnia_mcu.c
index 40ced261e3..77a0424d61 100644
--- a/drivers/gpio/turris_omnia_mcu.c
+++ b/drivers/misc/turris_omnia_mcu.c
@@ -1,9 +1,14 @@
 // SPDX-License-Identifier: GPL-2.0+
-// (C) 2022 Pali Rohár 
+/*
+ * Copyright (C) 2022 Pali Rohár 
+ * Copyright (C) 2024 Marek Behún 
+ */
 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -13,9 +18,9 @@ struct turris_omnia_mcu_info {
u32 features;
 };
 
-static int turris_omnia_mcu_get_function(struct udevice *dev, uint offset)
+static int omnia_gpio_get_function(struct udevice *dev, uint offset)
 {
-   struct turris_omnia_mcu_info *info = dev_get_plat(dev);
+   struct turris_omnia_mcu_info *info = dev_get_priv(dev->parent);
 
switch (offset) {
/* bank 0 */
@@ -49,9 +54,9 @@ static int turris_omnia_mcu_get_function(struct udevice *dev, 
uint offset)
}
 }
 
-static int turris_omnia_mcu_get_value(struct udevice *dev, uint offset)
+static int omnia_gpio_get_value(struct udevice *dev, uint offset)
 {
-   

[PATCH u-boot-mvebu v2 13/18] gpio: turris_omnia_mcu: Update firmware features reading

2024-03-23 Thread Marek Behún
Update firmware features reading to try reading 32 bits of features and
fallback to reading 16 bits.

Signed-off-by: Marek Behún 
---
 drivers/gpio/turris_omnia_mcu.c | 32 ++--
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/gpio/turris_omnia_mcu.c b/drivers/gpio/turris_omnia_mcu.c
index c441d07d69..40ced261e3 100644
--- a/drivers/gpio/turris_omnia_mcu.c
+++ b/drivers/gpio/turris_omnia_mcu.c
@@ -10,7 +10,7 @@
 #include 
 
 struct turris_omnia_mcu_info {
-   u16 features;
+   u32 features;
 };
 
 static int turris_omnia_mcu_get_function(struct udevice *dev, uint offset)
@@ -228,25 +228,37 @@ static int turris_omnia_mcu_probe(struct udevice *dev)
 {
struct turris_omnia_mcu_info *info = dev_get_plat(dev);
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
-   u16 val;
+   u32 dword;
+   u16 word;
int ret;
 
-   ret = dm_i2c_read(dev, CMD_GET_STATUS_WORD, (void *), sizeof(val));
+   ret = dm_i2c_read(dev, CMD_GET_STATUS_WORD, (void *), 
sizeof(word));
if (ret < 0) {
printf("Error: turris_omnia_mcu CMD_GET_STATUS_WORD failed: 
%d\n",
   ret);
return ret;
}
 
-   if (le16_to_cpu(val) & STS_FEATURES_SUPPORTED) {
-   ret = dm_i2c_read(dev, CMD_GET_FEATURES, (void *),
- sizeof(val));
+   if (le16_to_cpu(word) & STS_FEATURES_SUPPORTED) {
+   /* try read 32-bit features */
+   ret = dm_i2c_read(dev, CMD_GET_FEATURES, (void *),
+ sizeof(dword));
if (ret < 0) {
-   printf("Error: turris_omnia_mcu CMD_GET_FEATURES 
failed: %d\n",
-  ret);
-   return ret;
+   /* try read 16-bit features */
+   ret = dm_i2c_read(dev, CMD_GET_FEATURES, (void *),
+ sizeof(word));
+   if (ret < 0) {
+   printf("Error: turris_omnia_mcu 
CMD_GET_FEATURES failed: %d\n",
+  ret);
+   return ret;
+   }
+
+   info->features = le16_to_cpu(word);
+   } else {
+   info->features = le32_to_cpu(dword);
+   if (info->features & FEAT_FROM_BIT_16_INVALID)
+   info->features &= GENMASK(15, 0);
}
-   info->features = le16_to_cpu(val);
}
 
uc_priv->bank_name = "mcu_";
-- 
2.43.2



[PATCH u-boot-mvebu v2 12/18] gpio: turris_omnia_mcu: Use byteorder conversion functions

2024-03-23 Thread Marek Behún
Use byteorder conversion function instead of manually assembling data
from/to MCU.

Signed-off-by: Marek Behún 
---
 drivers/gpio/turris_omnia_mcu.c | 80 +++--
 1 file changed, 46 insertions(+), 34 deletions(-)

diff --git a/drivers/gpio/turris_omnia_mcu.c b/drivers/gpio/turris_omnia_mcu.c
index da9a6efe6d..c441d07d69 100644
--- a/drivers/gpio/turris_omnia_mcu.c
+++ b/drivers/gpio/turris_omnia_mcu.c
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -51,27 +52,31 @@ static int turris_omnia_mcu_get_function(struct udevice 
*dev, uint offset)
 static int turris_omnia_mcu_get_value(struct udevice *dev, uint offset)
 {
struct turris_omnia_mcu_info *info = dev_get_plat(dev);
-   u8 val16[2];
-   u8 val32[4];
+   u32 val32;
+   u16 val16;
int ret;
 
switch (offset) {
/* bank 0 */
case 0 ... 15:
-   ret = dm_i2c_read(dev, CMD_GET_STATUS_WORD, val16, 2);
+   ret = dm_i2c_read(dev, CMD_GET_STATUS_WORD, (void *),
+ sizeof(val16));
if (ret)
return ret;
-   return u16)val16[1] << 8) | val16[0]) >> offset) & 0x1;
+
+   return !!(le16_to_cpu(val16) & BIT(offset));
 
/* bank 1 - supported only when FEAT_EXT_CMDS is set */
case (16 + 0) ... (16 + 31):
if (!(info->features & FEAT_EXT_CMDS))
return -EINVAL;
-   ret = dm_i2c_read(dev, CMD_GET_EXT_STATUS_DWORD, val32, 4);
+
+   ret = dm_i2c_read(dev, CMD_GET_EXT_STATUS_DWORD, (void *),
+ sizeof(val32));
if (ret)
return ret;
-   return u32)val32[3] << 24) | ((u32)val32[2] << 16) |
-((u32)val32[1] << 8) | val32[0]) >> (offset - 16)) & 
0x1;
+
+   return !!(le32_to_cpu(val32) & BIT(offset - 16));
 
/* bank 2 - supported only when FEAT_EXT_CMDS and FEAT_PERIPH_MCU is 
set */
case (16 + 32 + 0) ... (16 + 32 + 15):
@@ -79,10 +84,13 @@ static int turris_omnia_mcu_get_value(struct udevice *dev, 
uint offset)
return -EINVAL;
if (!(info->features & FEAT_PERIPH_MCU))
return -EINVAL;
-   ret = dm_i2c_read(dev, CMD_GET_EXT_CONTROL_STATUS, val16, 2);
+
+   ret = dm_i2c_read(dev, CMD_GET_EXT_CONTROL_STATUS,
+ (void *), sizeof(val16));
if (ret)
return ret;
-   return u16)val16[1] << 8) | val16[0]) >> (offset - 16 - 
32)) & 0x1;
+
+   return !!(le16_to_cpu(val16) & BIT(offset - 16 - 32));
 
default:
return -EINVAL;
@@ -92,30 +100,33 @@ static int turris_omnia_mcu_get_value(struct udevice *dev, 
uint offset)
 static int turris_omnia_mcu_set_value(struct udevice *dev, uint offset, int 
value)
 {
struct turris_omnia_mcu_info *info = dev_get_plat(dev);
-   u8 val16[2];
-   u8 val32[4];
+   u16 valmask16[2];
+   u8 valmask8[2];
 
switch (offset) {
/* bank 0 */
case 0 ... 15:
switch (offset) {
case ilog2(STS_USB30_PWRON):
-   val16[1] = CTL_USB30_PWRON;
+   valmask8[1] = CTL_USB30_PWRON;
break;
case ilog2(STS_USB31_PWRON):
-   val16[1] = CTL_USB31_PWRON;
+   valmask8[1] = CTL_USB31_PWRON;
break;
case ilog2(STS_ENABLE_4V5):
-   val16[1] = CTL_ENABLE_4V5;
+   valmask8[1] = CTL_ENABLE_4V5;
break;
case ilog2(STS_BUTTON_MODE):
-   val16[1] = CTL_BUTTON_MODE;
+   valmask8[1] = CTL_BUTTON_MODE;
break;
default:
return -EINVAL;
}
-   val16[0] = value ? val16[1] : 0;
-   return dm_i2c_write(dev, CMD_GENERAL_CONTROL, val16, 
sizeof(val16));
+
+   valmask8[0] = value ? valmask8[1] : 0;
+
+   return dm_i2c_write(dev, CMD_GENERAL_CONTROL, valmask8,
+   sizeof(valmask8));
 
/* bank 2 - supported only when FEAT_EXT_CMDS and FEAT_PERIPH_MCU is 
set */
case (16 + 32 + 0) ... (16 + 32 + 15):
@@ -123,11 +134,12 @@ static int turris_omnia_mcu_set_value(struct udevice 
*dev, uint offset, int valu
return -EINVAL;
if (!(info->features & FEAT_PERIPH_MCU))
return -EINVAL;
-   val32[3] = BIT(offset - 16 - 32) >> 8;
-   val32[2] = BIT(offset - 16 - 32) 

[PATCH u-boot-mvebu v2 10/18] arm: mvebu: system-controller: Select mvebu-reset if DM_RESET && PCI_MVEBU

2024-03-23 Thread Marek Behún
The mvebu-reset driver is only needed by the mvebu PCIe driver, but
currently it is automatically selected if DM_RESET is enabled. Add the
condition of PCI_MVEBU also being enabled for mvebu-reset to be
selected.

Signed-off-by: Marek Behún 
---
 arch/arm/mach-mvebu/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 62a2bc5958..623432a60e 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -18,7 +18,7 @@ config ARMADA_32BIT
select TOOLS_KWBIMAGE if SPL
select SPL_SYS_NO_VECTOR_TABLE if SPL
select ARCH_VERY_EARLY_INIT
-   select ARMADA_32BIT_SYSCON_RESET if DM_RESET
+   select ARMADA_32BIT_SYSCON_RESET if DM_RESET && PCI_MVEBU
 
 # ARMv7 SoCs...
 config ARMADA_375
-- 
2.43.2



[PATCH u-boot-mvebu v2 11/18] arm: mvebu: system-controller: Add support for SYSRESET

2024-03-23 Thread Marek Behún
Add driver model support for sysreset via mvebu system controller. This is
currently only available for U-Boot proper.

Signed-off-by: Marek Behún 
---
 arch/arm/mach-mvebu/Kconfig | 18 +-
 arch/arm/mach-mvebu/Makefile|  2 +-
 arch/arm/mach-mvebu/cpu.c   |  2 +
 arch/arm/mach-mvebu/system-controller.c | 74 +++--
 4 files changed, 89 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 623432a60e..f15d3cc5ed 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -19,6 +19,7 @@ config ARMADA_32BIT
select SPL_SYS_NO_VECTOR_TABLE if SPL
select ARCH_VERY_EARLY_INIT
select ARMADA_32BIT_SYSCON_RESET if DM_RESET && PCI_MVEBU
+   select ARMADA_32BIT_SYSCON_SYSRESET if SYSRESET
 
 # ARMv7 SoCs...
 config ARMADA_375
@@ -457,16 +458,29 @@ config SF_DEFAULT_MODE
default 0x0
depends on MVEBU_SPL_BOOT_DEVICE_SPI
 
+config ARMADA_32BIT_SYSCON
+   bool
+   depends on ARMADA_32BIT
+   select REGMAP
+   select SYSCON
+
 config ARMADA_32BIT_SYSCON_RESET
bool "Support Armada XP/375/38x/39x reset controller"
depends on ARMADA_32BIT
depends on DM_RESET
-   select REGMAP
-   select SYSCON
+   select ARMADA_32BIT_SYSCON
help
  Build support for Armada XP/375/38x/39x reset controller. This is
  needed for PCIe support.
 
+config ARMADA_32BIT_SYSCON_SYSRESET
+   bool "Support Armada XP/375/38x/39x sysreset via driver model"
+   depends on ARMADA_32BIT
+   depends on SYSRESET
+   select ARMADA_32BIT_SYSCON
+   help
+ Build support for Armada XP/375/38x/39x system reset via driver model.
+
 source "board/solidrun/clearfog/Kconfig"
 source "board/kobol/helios4/Kconfig"
 
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index d44ca3a0df..329c2e4915 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -28,7 +28,7 @@ obj-$(CONFIG_ARMADA_38X) += 
../../../drivers/ddr/marvell/a38x/xor.o
 obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_MSYS) += ../../../drivers/ddr/marvell/axp/xor.o
 
-obj-$(CONFIG_ARMADA_32BIT_SYSCON_RESET) += system-controller.o
+obj-$(CONFIG_ARMADA_32BIT_SYSCON) += system-controller.o
 
 ifdef CONFIG_ARMADA_38X
 obj-$(CONFIG_MVEBU_EFUSE) += efuse.o
diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c
index 8e0de93538..7c62a5dbb6 100644
--- a/arch/arm/mach-mvebu/cpu.c
+++ b/arch/arm/mach-mvebu/cpu.c
@@ -52,6 +52,7 @@ void lowlevel_init(void)
 */
 }
 
+#if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_ARMADA_32BIT_SYSCON_SYSRESET)
 void reset_cpu(void)
 {
struct mvebu_system_registers *reg =
@@ -62,6 +63,7 @@ void reset_cpu(void)
while (1)
;
 }
+#endif
 
 u32 get_boot_device(void)
 {
diff --git a/arch/arm/mach-mvebu/system-controller.c 
b/arch/arm/mach-mvebu/system-controller.c
index c5c05922f2..b5f8afb96d 100644
--- a/arch/arm/mach-mvebu/system-controller.c
+++ b/arch/arm/mach-mvebu/system-controller.c
@@ -10,11 +10,24 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
-#define MVEBU_SOC_CONTROL_1_REG 0x4
+#define MVEBU_SOC_CONTROL_1_REG0x4
 
-#define MVEBU_PCIE_ID 0
+#if defined(CONFIG_ARMADA_375)
+# define MVEBU_RSTOUTN_MASK_REG0x54
+# define MVEBU_SYS_SOFT_RST_REG0x58
+#else
+# define MVEBU_RSTOUTN_MASK_REG0x60
+# define MVEBU_SYS_SOFT_RST_REG0x64
+#endif
+
+#define MVEBU_GLOBAL_SOFT_RST_BIT  BIT(0)
+
+#define MVEBU_PCIE_ID  0
+
+#if IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_RESET)
 
 static int mvebu_reset_of_xlate(struct reset_ctl *rst,
struct ofnode_phandle_args *args)
@@ -90,11 +103,64 @@ U_BOOT_DRIVER(mvebu_reset) = {
.ops = _reset_ops,
 };
 
+#endif /* IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_RESET) */
+
+#if IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_SYSRESET)
+
+static int mvebu_sysreset_request(struct udevice *dev, enum sysreset_t type)
+{
+   struct regmap *regmap = syscon_get_regmap(dev->parent);
+   uint bit;
+
+   if (type != SYSRESET_COLD)
+   return -EPROTONOSUPPORT;
+
+   bit = MVEBU_GLOBAL_SOFT_RST_BIT;
+
+   regmap_update_bits(regmap, MVEBU_RSTOUTN_MASK_REG, bit, bit);
+   regmap_update_bits(regmap, MVEBU_SYS_SOFT_RST_REG, bit, bit);
+
+   while (1)
+   ;
+
+   return 0;
+}
+
+static struct sysreset_ops mvebu_sysreset_ops = {
+   .request = mvebu_sysreset_request,
+};
+
+U_BOOT_DRIVER(mvebu_sysreset) = {
+   .name = "mvebu-sysreset",
+   .id = UCLASS_SYSRESET,
+   .ops = _sysreset_ops,
+};
+
+#endif /* IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_SYSRESET) */
+
 static int mvebu_syscon_bind(struct udevice *de

[PATCH u-boot-mvebu v2 09/18] arm: mvebu: system-controller: Rework to use UCLASS_SYSCON

2024-03-23 Thread Marek Behún
The system-controller driver for 32-bit Armada is currently registered
as UCLASS_RESET, since it only provides enabling/disabling PCIe ports.

Rework it as UCLASS_SYSCON and bind mvebu-reset as a child device.

Signed-off-by: Marek Behún 
---
 arch/arm/mach-mvebu/Kconfig | 11 
 arch/arm/mach-mvebu/Makefile|  2 +-
 arch/arm/mach-mvebu/system-controller.c | 76 ++---
 3 files changed, 54 insertions(+), 35 deletions(-)

diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 2058c95ca2..62a2bc5958 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -18,6 +18,7 @@ config ARMADA_32BIT
select TOOLS_KWBIMAGE if SPL
select SPL_SYS_NO_VECTOR_TABLE if SPL
select ARCH_VERY_EARLY_INIT
+   select ARMADA_32BIT_SYSCON_RESET if DM_RESET
 
 # ARMv7 SoCs...
 config ARMADA_375
@@ -456,6 +457,16 @@ config SF_DEFAULT_MODE
default 0x0
depends on MVEBU_SPL_BOOT_DEVICE_SPI
 
+config ARMADA_32BIT_SYSCON_RESET
+   bool "Support Armada XP/375/38x/39x reset controller"
+   depends on ARMADA_32BIT
+   depends on DM_RESET
+   select REGMAP
+   select SYSCON
+   help
+ Build support for Armada XP/375/38x/39x reset controller. This is
+ needed for PCIe support.
+
 source "board/solidrun/clearfog/Kconfig"
 source "board/kobol/helios4/Kconfig"
 
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index ef790d97fe..d44ca3a0df 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -28,7 +28,7 @@ obj-$(CONFIG_ARMADA_38X) += 
../../../drivers/ddr/marvell/a38x/xor.o
 obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_MSYS) += ../../../drivers/ddr/marvell/axp/xor.o
 
-obj-$(CONFIG_DM_RESET) += system-controller.o
+obj-$(CONFIG_ARMADA_32BIT_SYSCON_RESET) += system-controller.o
 
 ifdef CONFIG_ARMADA_38X
 obj-$(CONFIG_MVEBU_EFUSE) += efuse.o
diff --git a/arch/arm/mach-mvebu/system-controller.c 
b/arch/arm/mach-mvebu/system-controller.c
index 7cdde11cbd..c5c05922f2 100644
--- a/arch/arm/mach-mvebu/system-controller.c
+++ b/arch/arm/mach-mvebu/system-controller.c
@@ -1,19 +1,21 @@
 // SPDX-License-Identifier: GPL-2.0+
-// (C) 2021 Pali Rohár 
+/*
+ * Copyright (C) 2021 Pali Rohár 
+ * Copyright (C) 2024 Marek Behún 
+ */
 
 #include 
 #include 
+#include 
+#include 
 #include 
+#include 
 #include 
 
 #define MVEBU_SOC_CONTROL_1_REG 0x4
 
 #define MVEBU_PCIE_ID 0
 
-struct mvebu_reset_data {
-   void *base;
-};
-
 static int mvebu_reset_of_xlate(struct reset_ctl *rst,
struct ofnode_phandle_args *args)
 {
@@ -46,46 +48,33 @@ static int mvebu_reset_free(struct reset_ctl *rst)
 
 static int mvebu_reset_assert(struct reset_ctl *rst)
 {
-   struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+   struct regmap *regmap = syscon_get_regmap(rst->dev->parent);
 
-   clrbits_32(data->base + MVEBU_SOC_CONTROL_1_REG, BIT(rst->data));
-   return 0;
+   return regmap_update_bits(regmap, MVEBU_SOC_CONTROL_1_REG,
+ BIT(rst->data), 0);
 }
 
 static int mvebu_reset_deassert(struct reset_ctl *rst)
 {
-   struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+   struct regmap *regmap = syscon_get_regmap(rst->dev->parent);
 
-   setbits_32(data->base + MVEBU_SOC_CONTROL_1_REG, BIT(rst->data));
-   return 0;
+   return regmap_update_bits(regmap, MVEBU_SOC_CONTROL_1_REG,
+ BIT(rst->data), BIT(rst->data));
 }
 
 static int mvebu_reset_status(struct reset_ctl *rst)
 {
-   struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+   struct regmap *regmap = syscon_get_regmap(rst->dev->parent);
+   uint val;
+   int ret;
 
-   return !(readl(data->base + MVEBU_SOC_CONTROL_1_REG) & BIT(rst->data));
-}
-
-static int mvebu_reset_of_to_plat(struct udevice *dev)
-{
-   struct mvebu_reset_data *data = dev_get_priv(dev);
+   ret = regmap_read(regmap, MVEBU_SOC_CONTROL_1_REG, );
+   if (ret < 0)
+   return ret;
 
-   data->base = dev_read_addr_ptr(dev);
-   if (!data->base)
-   return -EINVAL;
-
-   return 0;
+   return !(val & BIT(rst->data));
 }
 
-static const struct udevice_id mvebu_reset_of_match[] = {
-   { .compatible = "marvell,armada-370-xp-system-controller" },
-   { .compatible = "marvell,armada-375-system-controller" },
-   { .compatible = "marvell,armada-380-system-controller" },
-   { .compatible = "marvell,armada-390-system-controller" },
-   { },
-};
-
 static const struct reset_ops mvebu_reset_ops = {
.of_xlate = mvebu_reset_of_xlate,
.request = mvebu_reset_request,
@@ -98,8 +87,27 @@ static const struct reset_ops mvebu_r

[PATCH u-boot-mvebu v2 08/18] arm: mvebu: spl: Do not build mvebu-reset in SPL

2024-03-23 Thread Marek Behún
Commit 35e29e89a386 ("arm: mvebu: Implement simple mvebu-reset driver
for enabling/disabling PCIe ports") made it so that the mvebu reset
driver for enabling/disabling PCIe ports is build if CONFIG_DM_RESET is
enabled. This is because PCI_MVEBU depends on DM_RESET.

But the driver should not be built for SPL. Indeed the PCI_MVEBU driver
is not supported in SPL now, and so the mvebu-reset driver is not needed.

Signed-off-by: Marek Behún 
---
 arch/arm/mach-mvebu/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index 0584ed2be5..ef790d97fe 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -22,13 +22,14 @@ else # CONFIG_ARCH_KIRKWOOD
 obj-y  = cpu.o
 obj-y  += dram.o
 obj-y  += lowlevel.o
-obj-$(CONFIG_DM_RESET) += system-controller.o
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_ARMADA_375) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_38X) += ../../../drivers/ddr/marvell/a38x/xor.o
 obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_MSYS) += ../../../drivers/ddr/marvell/axp/xor.o
 
+obj-$(CONFIG_DM_RESET) += system-controller.o
+
 ifdef CONFIG_ARMADA_38X
 obj-$(CONFIG_MVEBU_EFUSE) += efuse.o
 endif
-- 
2.43.2



[PATCH u-boot-mvebu v2 07/18] arm: mvebu: turris_omnia: Disable Atmel SHA node if not present

2024-03-23 Thread Marek Behún
If the FEAT_CRYPTO feature bit is present in MCU features, the board
crypto is implemented by MCU and the Atmel SHA chip is not present.
Disable Atmel SHA device-tree node in that case.

Signed-off-by: Marek Behún 
---
 board/CZ.NIC/turris_omnia/turris_omnia.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index 896c14bb99..6f3aae55a8 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -1007,6 +1007,25 @@ static int fixup_mcu_gpio_in_eth_wan_node(void *blob)
return 0;
 }
 
+static void fixup_atsha_node(void *blob)
+{
+   int node;
+
+   if (!omnia_mcu_has_feature(FEAT_CRYPTO))
+   return;
+
+   node = fdt_node_offset_by_compatible(blob, -1, "atmel,atsha204a");
+   if (node < 0) {
+   printf("Cannot find ATSHA204A node!\n");
+   return;
+   }
+
+   if (fdt_status_disabled(blob, node) < 0)
+   printf("Cannot disable ATSHA204A node!\n");
+   else
+   debug("Disabled ATSHA204A node\n");
+}
+
 #endif
 
 #if IS_ENABLED(CONFIG_OF_BOARD_FIXUP)
@@ -1020,6 +1039,8 @@ int board_fix_fdt(void *blob)
fixup_msata_port_nodes(blob);
fixup_wwan_port_nodes(blob);
 
+   fixup_atsha_node(blob);
+
return 0;
 }
 #endif
@@ -1211,6 +1232,8 @@ int ft_board_setup(void *blob, struct bd_info *bd)
fixup_msata_port_nodes(blob);
fixup_wwan_port_nodes(blob);
 
+   fixup_atsha_node(blob);
+
return 0;
 }
 #endif
-- 
2.43.2



[PATCH u-boot-mvebu v2 05/18] arm: mvebu: turris_omnia: Implement getting board information from MCU

2024-03-23 Thread Marek Behún
Implement reading board serial number, first MAC address and board
version from MCU. MCU supports board information if the FEAT_BOARD_INFO
feature bit is set in MCU features.

Prefer getting board information from MCU if supported, fallback to
Atmel SHA chip.

Signed-off-by: Marek Behún 
---
 board/CZ.NIC/turris_atsha_otp.c  | 27 +--
 board/CZ.NIC/turris_omnia/Makefile   |  2 +-
 board/CZ.NIC/turris_omnia/turris_omnia.c | 94 +++-
 3 files changed, 93 insertions(+), 30 deletions(-)

diff --git a/board/CZ.NIC/turris_atsha_otp.c b/board/CZ.NIC/turris_atsha_otp.c
index a29fe36231..85eebcdf18 100644
--- a/board/CZ.NIC/turris_atsha_otp.c
+++ b/board/CZ.NIC/turris_atsha_otp.c
@@ -11,6 +11,7 @@
 #include 
 
 #include "turris_atsha_otp.h"
+#include "turris_common.h"
 
 #define TURRIS_ATSHA_OTP_VERSION   0
 #define TURRIS_ATSHA_OTP_SERIAL1
@@ -32,26 +33,6 @@ static struct udevice *get_atsha204a_dev(void)
return dev;
 }
 
-static void increment_mac(u8 *mac)
-{
-   int i;
-
-   for (i = 5; i >= 3; i--) {
-   mac[i] += 1;
-   if (mac[i])
-   break;
-   }
-}
-
-static void set_mac_if_invalid(int i, u8 *mac)
-{
-   u8 oldmac[6];
-
-   if (is_valid_ethaddr(mac) &&
-   !eth_env_get_enetaddr_by_index("eth", i, oldmac))
-   eth_env_set_enetaddr_by_index("eth", i, mac);
-}
-
 int turris_atsha_otp_init_mac_addresses(int first_idx)
 {
struct udevice *dev = get_atsha204a_dev();
@@ -84,11 +65,7 @@ int turris_atsha_otp_init_mac_addresses(int first_idx)
mac[4] = mac1[2];
mac[5] = mac1[3];
 
-   set_mac_if_invalid((first_idx + 0) % 3, mac);
-   increment_mac(mac);
-   set_mac_if_invalid((first_idx + 1) % 3, mac);
-   increment_mac(mac);
-   set_mac_if_invalid((first_idx + 2) % 3, mac);
+   turris_init_mac_addresses(first_idx, mac);
 
return 0;
 }
diff --git a/board/CZ.NIC/turris_omnia/Makefile 
b/board/CZ.NIC/turris_omnia/Makefile
index dc39b44ae1..341378b4e5 100644
--- a/board/CZ.NIC/turris_omnia/Makefile
+++ b/board/CZ.NIC/turris_omnia/Makefile
@@ -2,4 +2,4 @@
 #
 # Copyright (C) 2017 Marek Behún 
 
-obj-y  := turris_omnia.o ../turris_atsha_otp.o
+obj-y  := turris_omnia.o ../turris_atsha_otp.o ../turris_common.o
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index 6dfde5ee7a..f63640ad64 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -25,12 +26,14 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
 #include "../drivers/ddr/marvell/a38x/ddr3_init.h"
 #include <../serdes/a38x/high_speed_env_spec.h>
 #include "../turris_atsha_otp.h"
+#include "../turris_common.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -186,6 +189,70 @@ static bool omnia_mcu_has_feature(u32 feature)
return feature & features;
 }
 
+static u32 omnia_mcu_crc32(const void *p, size_t len)
+{
+   u32 val, crc = 0;
+
+   compiletime_assert(!(len % 4), "length has to be a multiple of 4");
+
+   while (len) {
+   val = bitrev32(get_unaligned_le32(p));
+   crc = crc32(crc, (void *), 4);
+   p += 4;
+   len -= 4;
+   }
+
+   return ~bitrev32(crc);
+}
+
+/* Can only be called after relocation, since it needs cleared BSS */
+static int omnia_mcu_board_info(char *serial, u8 *mac, char *version)
+{
+   static u8 reply[17];
+   static bool cached;
+
+   if (!cached) {
+   u8 csum;
+   int ret;
+
+   ret = omnia_mcu_read(CMD_BOARD_INFO_GET, reply, sizeof(reply));
+   if (ret)
+   return ret;
+
+   if (reply[0] != 16)
+   return -EBADMSG;
+
+   csum = reply[16];
+   reply[16] = 0;
+
+   if ((omnia_mcu_crc32([1], 16) & 0xff) != csum)
+   return -EBADMSG;
+
+   cached = true;
+   }
+
+   if (serial) {
+   const char *serial_env;
+
+   serial_env = env_get("serial#");
+   if (serial_env && strlen(serial_env) == 16) {
+   strcpy(serial, serial_env);
+   } else {
+   sprintf(serial, "%016llX",
+   get_unaligned_le64([1]));
+   env_set("serial#", serial);
+   }
+   }
+
+   if (mac)
+   memcpy(mac, [9], ETH_ALEN);
+
+   if (version)
+   sprintf(version, "%u", reply[15]);
+
+   return 0;
+}
+
 static void enable_a385_watchdog(unsigned int timeout_minutes)
 {
struct sar_fre

[PATCH u-boot-mvebu v2 06/18] arm: mvebu: turris_omnia: Print board ECDSA public key if available

2024-03-23 Thread Marek Behún
If MCU supports the FEAT_CRYPTO feature, read board ECDSA public key
from MCU and print it.

Signed-off-by: Marek Behún 
---
 board/CZ.NIC/turris_omnia/turris_omnia.c | 25 +++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index f63640ad64..896c14bb99 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -253,6 +253,24 @@ static int omnia_mcu_board_info(char *serial, u8 *mac, 
char *version)
return 0;
 }
 
+static int omnia_mcu_get_board_public_key(char pub_key[static 67])
+{
+   u8 reply[34];
+   int ret;
+
+   ret = omnia_mcu_read(CMD_CRYPTO_GET_PUBLIC_KEY, reply, sizeof(reply));
+   if (ret)
+   return ret;
+
+   if (reply[0] != 33)
+   return -EBADMSG;
+
+   bin2hex(pub_key, [1], 33);
+   reply[66] = '\0';
+
+   return 0;
+}
+
 static void enable_a385_watchdog(unsigned int timeout_minutes)
 {
struct sar_freq_modes sar_freq;
@@ -1032,7 +1050,7 @@ int board_late_init(void)
 
 int checkboard(void)
 {
-   char serial[17], version[4];
+   char serial[17], version[4], pub_key[67];
bool has_version;
int err;
 
@@ -1051,6 +1069,11 @@ int checkboard(void)
printf("  Board version: %s\n", has_version ? version : "unknown");
printf("  Serial Number: %s\n", !err ? serial : "unknown");
 
+   if (omnia_mcu_has_feature(FEAT_CRYPTO)) {
+   err = omnia_mcu_get_board_public_key(pub_key);
+   printf("  ECDSA Public Key: %s\n", !err ? pub_key : "unknown");
+   }
+
return 0;
 }
 
-- 
2.43.2



[PATCH u-boot-mvebu v2 04/18] arm: mvebu: turris_omnia: Update MCU status and features reading

2024-03-23 Thread Marek Behún
Refactor MCU status word and MCU firmware features reading to make it
simpler to use.

Try reading 32 bits of features, if that fails, read 16 bits. Older MCU
firmware supports only 16-bit wide features, and if more bytes are read,
either 0xff is sent or I2C transaction fails. Handle both cases.

Signed-off-by: Marek Behún 
---
 board/CZ.NIC/turris_omnia/turris_omnia.c | 100 +++
 1 file changed, 68 insertions(+), 32 deletions(-)

diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index 87e33d88c4..6dfde5ee7a 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -133,6 +133,59 @@ static int omnia_mcu_write(u8 cmd, const void *buf, int 
len)
return dm_i2c_write(chip, cmd, buf, len);
 }
 
+static int omnia_mcu_get_sts_and_features(u16 *psts, u32 *pfeatures)
+{
+   u16 sts, feat16;
+   int ret;
+
+   ret = omnia_mcu_read(CMD_GET_STATUS_WORD, , sizeof(sts));
+   if (ret)
+   return ret;
+
+   if (psts)
+   *psts = sts;
+
+   if (!pfeatures)
+   return 0;
+
+   if (sts & STS_FEATURES_SUPPORTED) {
+   /* try read 32-bit features */
+   ret = omnia_mcu_read(CMD_GET_FEATURES, pfeatures,
+sizeof(*pfeatures));
+   if (ret) {
+   /* try read 16-bit features */
+   ret = omnia_mcu_read(CMD_GET_FEATURES, ,
+sizeof());
+   if (ret)
+   return ret;
+
+   *pfeatures = feat16;
+   } else {
+   if (*pfeatures & FEAT_FROM_BIT_16_INVALID)
+   *pfeatures &= GENMASK(15, 0);
+   }
+   } else {
+   *pfeatures = 0;
+   }
+
+   return 0;
+}
+
+static int omnia_mcu_get_sts(u16 *sts)
+{
+   return omnia_mcu_get_sts_and_features(sts, NULL);
+}
+
+static bool omnia_mcu_has_feature(u32 feature)
+{
+   u32 features;
+
+   if (omnia_mcu_get_sts_and_features(NULL, ))
+   return false;
+
+   return feature & features;
+}
+
 static void enable_a385_watchdog(unsigned int timeout_minutes)
 {
struct sar_freq_modes sar_freq;
@@ -194,7 +247,7 @@ static bool disable_mcu_watchdog(void)
 static bool omnia_detect_sata(const char *msata_slot)
 {
int ret;
-   u16 stsword;
+   u16 sts;
 
puts("MiniPCIe/mSATA card detection... ");
 
@@ -210,24 +263,24 @@ static bool omnia_detect_sata(const char *msata_slot)
}
}
 
-   ret = omnia_mcu_read(CMD_GET_STATUS_WORD, , sizeof(stsword));
+   ret = omnia_mcu_get_sts();
if (ret) {
printf("omnia_mcu_read failed: %i, defaulting to MiniPCIe 
card\n",
   ret);
return false;
}
 
-   if (!(stsword & STS_CARD_DET)) {
+   if (!(sts & STS_CARD_DET)) {
puts("none\n");
return false;
}
 
-   if (stsword & STS_MSATA_IND)
+   if (sts & STS_MSATA_IND)
puts("mSATA\n");
else
puts("MiniPCIe\n");
 
-   return stsword & STS_MSATA_IND;
+   return sts & STS_MSATA_IND;
 }
 
 static bool omnia_detect_wwan_usb3(const char *wwan_slot)
@@ -355,14 +408,14 @@ static int omnia_get_ram_size_gb(void)
 static const char * const omnia_get_mcu_type(void)
 {
static char result[] = "xxx (with peripheral resets)";
-   u16 stsword, features;
+   u16 sts;
int ret;
 
-   ret = omnia_mcu_read(CMD_GET_STATUS_WORD, , sizeof(stsword));
+   ret = omnia_mcu_get_sts();
if (ret)
return "unknown";
 
-   switch (stsword & STS_MCU_TYPE_MASK) {
+   switch (sts & STS_MCU_TYPE_MASK) {
case STS_MCU_TYPE_STM32:
strcpy(result, "STM32");
break;
@@ -377,11 +430,8 @@ static const char * const omnia_get_mcu_type(void)
break;
}
 
-   if (stsword & STS_FEATURES_SUPPORTED) {
-   ret = omnia_mcu_read(CMD_GET_FEATURES, , 
sizeof(features));
-   if (ret == 0 && (features & FEAT_PERIPH_MCU))
-   strcat(result, " (with peripheral resets)");
-   }
+   if (omnia_mcu_has_feature(FEAT_PERIPH_MCU))
+   strcat(result, " (with peripheral resets)");
 
return result;
 }
@@ -660,9 +710,6 @@ int board_early_init_f(void)
 
 void spl_board_init(void)
 {
-   u16 val;
-   int ret;
-
/*
 * If booting from UART, disable MCU watchdog in SPL, since uploading
 * U-Boot proper can take too much time and trigger it. Instead enable
@@ -679,12 +726

[PATCH u-boot-mvebu v2 03/18] arm: mvebu: turris_{omnia, mox}: Don't print model two times

2024-03-23 Thread Marek Behún
Since commit 8cd4bf7dc9ba ("turris: Use checkboard() instead of
show_board_info()") the model is show two times during boot:
  Model: Turris Omnia
  Model: Turris Omnia

This is because the common function show_board_info() shows it, and
Turris' checkboard() also does.

Remove the second print.

Fixes: 8cd4bf7dc9ba ("turris: Use checkboard() instead of show_board_info()")
Signed-off-by: Marek Behún 
---
 board/CZ.NIC/turris_mox/turris_mox.c | 5 +
 board/CZ.NIC/turris_omnia/turris_omnia.c | 1 -
 2 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/board/CZ.NIC/turris_mox/turris_mox.c 
b/board/CZ.NIC/turris_mox/turris_mox.c
index 3489bdd74b..1a2f60e3d1 100644
--- a/board/CZ.NIC/turris_mox/turris_mox.c
+++ b/board/CZ.NIC/turris_mox/turris_mox.c
@@ -565,13 +565,10 @@ static void handle_reset_button(void)
 int checkboard(void)
 {
int i, ret, board_version, ram_size, is_sd;
-   const char *pub_key, *model;
+   const char *pub_key;
const u8 *topology;
u64 serial_number;
 
-   model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
-   printf("Model: %s\n", model);
-
ret = mbox_sp_get_board_info(_number, NULL, NULL, _version,
 _size, NULL);
if (ret < 0) {
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index 6c2d7da528..87e33d88c4 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -933,7 +933,6 @@ int checkboard(void)
int err;
 
err = turris_atsha_otp_get_serial_number(serial);
-   printf("Model: Turris Omnia\n");
printf("  MCU type: %s\n", omnia_get_mcu_type());
printf("  MCU version: %s\n", omnia_get_mcu_version());
printf("  RAM size: %i MiB\n", omnia_get_ram_size_gb() * 1024);
-- 
2.43.2



[PATCH u-boot-mvebu v2 01/18] arm: mvebu: turris_omnia: Enable LTO by default on Turris Omnia

2024-03-23 Thread Marek Behún
U-Boot builds for Turris Omnia are approaching the limit of 0xf
bytes, which is the size of the U-Boot partition on Omnia.

Enable LTO to get more size optimized binaries.

Signed-off-by: Marek Behún 
---
 configs/turris_omnia_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 29148402a1..39e15043df 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -31,6 +31,7 @@ CONFIG_AHCI=y
 CONFIG_OF_BOARD_FIXUP=y
 CONFIG_SYS_MEMTEST_START=0x0080
 CONFIG_SYS_MEMTEST_END=0x00ff
+CONFIG_LTO=y
 CONFIG_HAS_BOARD_SIZE_LIMIT=y
 CONFIG_BOARD_SIZE_LIMIT=983040
 CONFIG_FIT=y
-- 
2.43.2



[PATCH u-boot-mvebu v2 02/18] arm: mvebu: turris_omnia: Add header containing MCU command interface and use it

2024-03-23 Thread Marek Behún
Add header containing all MCU command definitions and use it in board
code and in MCU driver.

Signed-off-by: Marek Behún 
---
 board/CZ.NIC/turris_omnia/turris_omnia.c |  81 +++-
 drivers/gpio/turris_omnia_mcu.c  |  54 +
 include/turris-omnia-mcu-interface.h | 238 +++
 3 files changed, 262 insertions(+), 111 deletions(-)
 create mode 100644 include/turris-omnia-mcu-interface.h

diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index adeb69a205..6c2d7da528 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -59,46 +60,6 @@ DECLARE_GLOBAL_DATA_PTR;
 #define A385_WD_RSTOUT_UNMASK  MVEBU_REGISTER(0x20704)
 #define   A385_WD_RSTOUT_UNMASK_GLOBAL BIT(8)
 
-enum mcu_commands {
-   CMD_GET_STATUS_WORD = 0x01,
-   CMD_GET_RESET   = 0x09,
-   CMD_GET_FW_VERSION_APP  = 0x0a,
-   CMD_WATCHDOG_STATE  = 0x0b,
-   CMD_GET_FW_VERSION_BOOT = 0x0e,
-
-   /* available if STS_FEATURES_SUPPORTED bit set in status word */
-   CMD_GET_FEATURES= 0x10,
-
-   /* available if EXT_CMD bit set in features */
-   CMD_EXT_CONTROL = 0x12,
-};
-
-enum status_word_bits {
-   STS_MCU_TYPE_MASK   = GENMASK(1, 0),
-   STS_MCU_TYPE_STM32  = 0,
-   STS_MCU_TYPE_GD32   = 1,
-   STS_MCU_TYPE_MKL= 2,
-   STS_MCU_TYPE_UNKN   = 3,
-   STS_FEATURES_SUPPORTED  = BIT(2),
-   CARD_DET_STSBIT = 0x0010,
-   MSATA_IND_STSBIT= 0x0020,
-};
-
-/* CMD_GET_FEATURES */
-enum features_e {
-   FEAT_PERIPH_MCU = BIT(0),
-   FEAT_EXT_CMDS   = BIT(1),
-};
-
-/* CMD_EXT_CONTROL */
-enum ext_ctl_e {
-   EXT_CTL_nRES_LAN= BIT(1),
-   EXT_CTL_nRES_PHY= BIT(2),
-   EXT_CTL_nPERST0 = BIT(3),
-   EXT_CTL_nPERST1 = BIT(4),
-   EXT_CTL_nPERST2 = BIT(5),
-};
-
 /*
  * Those values and defines are taken from the Marvell U-Boot version
  * "u-boot-2013.01-2014_T3.0"
@@ -219,7 +180,7 @@ static bool disable_mcu_watchdog(void)
 
puts("Disabling MCU watchdog... ");
 
-   ret = omnia_mcu_write(CMD_WATCHDOG_STATE, "\x00", 1);
+   ret = omnia_mcu_write(CMD_SET_WATCHDOG_STATE, "\x00", 1);
if (ret) {
printf("omnia_mcu_write failed: %i\n", ret);
return false;
@@ -256,17 +217,17 @@ static bool omnia_detect_sata(const char *msata_slot)
return false;
}
 
-   if (!(stsword & CARD_DET_STSBIT)) {
+   if (!(stsword & STS_CARD_DET)) {
puts("none\n");
return false;
}
 
-   if (stsword & MSATA_IND_STSBIT)
+   if (stsword & STS_MSATA_IND)
puts("mSATA\n");
else
puts("MiniPCIe\n");
 
-   return stsword & MSATA_IND_STSBIT ? true : false;
+   return stsword & STS_MSATA_IND;
 }
 
 static bool omnia_detect_wwan_usb3(const char *wwan_slot)
@@ -393,18 +354,7 @@ static int omnia_get_ram_size_gb(void)
 
 static const char * const omnia_get_mcu_type(void)
 {
-   static const char * const mcu_types[] = {
-   [STS_MCU_TYPE_STM32] = "STM32",
-   [STS_MCU_TYPE_GD32]  = "GD32",
-   [STS_MCU_TYPE_MKL]   = "MKL",
-   [STS_MCU_TYPE_UNKN]  = "unknown",
-   };
-   static const char * const mcu_types_with_perip_resets[] = {
-   [STS_MCU_TYPE_STM32] = "STM32 (with peripheral resets)",
-   [STS_MCU_TYPE_GD32]  = "GD32 (with peripheral resets)",
-   [STS_MCU_TYPE_MKL]   = "MKL (with peripheral resets)",
-   [STS_MCU_TYPE_UNKN]  = "unknown (with peripheral resets)",
-   };
+   static char result[] = "xxx (with peripheral resets)";
u16 stsword, features;
int ret;
 
@@ -412,13 +362,28 @@ static const char * const omnia_get_mcu_type(void)
if (ret)
return "unknown";
 
+   switch (stsword & STS_MCU_TYPE_MASK) {
+   case STS_MCU_TYPE_STM32:
+   strcpy(result, "STM32");
+   break;
+   case STS_MCU_TYPE_GD32:
+   strcpy(result, "GD32");
+   break;
+   case STS_MCU_TYPE_MKL:
+   strcpy(result, "MKL");
+   break;
+   default:
+   strcpy(result, "unknown");
+   break;
+   }
+
if (stsword & STS_FEATURES_SUPPORTED) {
ret = omnia_mcu_read(CMD_GET_FEATURES, , 
sizeof(features));
if (ret == 0 && (features & FEAT_PERIPH_MCU

[PATCH u-boot-mvebu v2 00/18] Turris Omnia - New board revision support

2024-03-23 Thread Marek Behún
Hi Stefan,

this is v2 of series adding support for new board revision of Turris
Omnia.

See v1 at
  
https://patchwork.ozlabs.org/project/uboot/cover/20240304152148.3847-1-ka...@kernel.org/

Changes since v1:
- MCU firmware features can be 32-bit wide, updated the code to support
  reading 32 bits of features (both in board driver and in gpio driver)
- gpio driver now moved to misc, since it handles more functionality
  (rng, sysreset)
- mvebu system-controller driver expanded to also support UCLASS_SYSRESET,
  configurable by config option
- LTO enabled by default for Turris Omnia, otherwise it won't fit into
  the space reserved for U-Boot with these changes
- enabled the poweroff command (via sysreset) in defconfig (new MCU
  firmware can power off the board voltage regulators)
- enabled the rng command in defconfig

Marek Behún (18):
  arm: mvebu: turris_omnia: Enable LTO by default on Turris Omnia
  arm: mvebu: turris_omnia: Add header containing MCU command interface
and use it
  arm: mvebu: turris_{omnia, mox}: Don't print model two times
  arm: mvebu: turris_omnia: Update MCU status and features reading
  arm: mvebu: turris_omnia: Implement getting board information from MCU
  arm: mvebu: turris_omnia: Print board ECDSA public key if available
  arm: mvebu: turris_omnia: Disable Atmel SHA node if not present
  arm: mvebu: spl: Do not build mvebu-reset in SPL
  arm: mvebu: system-controller: Rework to use UCLASS_SYSCON
  arm: mvebu: system-controller: Select mvebu-reset if DM_RESET &&
PCI_MVEBU
  arm: mvebu: system-controller: Add support for SYSRESET
  gpio: turris_omnia_mcu: Use byteorder conversion functions
  gpio: turris_omnia_mcu: Update firmware features reading
  gpio: turris_omnia_mcu: Add support for system power off via sysreset
  arm: mvebu: turris_omnia: Enable poweroff command via sysreset in
defconfig
  cmd: rng: Print "Abort" on -EINTR
  misc: turris_omnia_mcu: Add support for rng provided by MCU
  arm: mvebu: turris_omnia: Enable rng command in defconfig

 arch/arm/mach-mvebu/Kconfig  |  25 ++
 arch/arm/mach-mvebu/Makefile |   3 +-
 arch/arm/mach-mvebu/cpu.c|   2 +
 arch/arm/mach-mvebu/system-controller.c  | 144 ++--
 board/CZ.NIC/turris_atsha_otp.c  |  27 +-
 board/CZ.NIC/turris_mox/turris_mox.c |   5 +-
 board/CZ.NIC/turris_omnia/Makefile   |   2 +-
 board/CZ.NIC/turris_omnia/turris_omnia.c | 310 -
 cmd/rng.c|   7 +-
 configs/turris_omnia_defconfig   |   6 +
 drivers/gpio/Kconfig |   7 -
 drivers/gpio/Makefile|   1 -
 drivers/gpio/turris_omnia_mcu.c  | 316 -
 drivers/misc/Kconfig |  11 +
 drivers/misc/Makefile|   1 +
 drivers/misc/turris_omnia_mcu.c  | 411 +++
 include/turris-omnia-mcu-interface.h | 238 +
 17 files changed, 1034 insertions(+), 482 deletions(-)
 delete mode 100644 drivers/gpio/turris_omnia_mcu.c
 create mode 100644 drivers/misc/turris_omnia_mcu.c
 create mode 100644 include/turris-omnia-mcu-interface.h

-- 
2.43.2



Re: [PATCH u-boot-mvebu 0/4] Turris Omnia - New board revision support

2024-03-23 Thread Marek Behún
Hello Stefan,

I've been doing some work on this and will be sending version 2 of this
series.

Marek


[PATCH u-boot-mvebu 4/4] arm: mvebu: turris_omnia: Disable Atmel SHA node if not present

2024-03-04 Thread Marek Behún
If the FEAT_CRYPTO feature bit is present in MCU features, the board
crypto is implemented by MCU and the Atmel SHA chip is not present.
Disable Atmel SHA device-tree node in that case.

Signed-off-by: Marek Behún 
---
 board/CZ.NIC/turris_omnia/turris_omnia.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index 46f576a460e..1f90ac5c7a7 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -1039,6 +1039,25 @@ static int fixup_mcu_gpio_in_eth_wan_node(void *blob)
return 0;
 }
 
+static void fixup_atsha_node(void *blob)
+{
+   int node;
+
+   if (!omnia_mcu_has_feature(FEAT_CRYPTO))
+   return;
+
+   node = fdt_node_offset_by_compatible(blob, -1, "atmel,atsha204a");
+   if (node < 0) {
+   printf("Cannot find ATSHA204A node!\n");
+   return;
+   }
+
+   if (fdt_status_disabled(blob, node) < 0)
+   printf("Cannot disable ATSHA204A node!\n");
+   else
+   debug("Disabled ATSHA204A node\n");
+}
+
 #endif
 
 #if IS_ENABLED(CONFIG_OF_BOARD_FIXUP)
@@ -1052,6 +1071,8 @@ int board_fix_fdt(void *blob)
fixup_msata_port_nodes(blob);
fixup_wwan_port_nodes(blob);
 
+   fixup_atsha_node(blob);
+
return 0;
 }
 #endif
@@ -1244,6 +1265,8 @@ int ft_board_setup(void *blob, struct bd_info *bd)
fixup_msata_port_nodes(blob);
fixup_wwan_port_nodes(blob);
 
+   fixup_atsha_node(blob);
+
return 0;
 }
 #endif
-- 
2.43.0



[PATCH u-boot-mvebu 3/4] arm: mvebu: turris_omnia: Print board ECDSA public key if available

2024-03-04 Thread Marek Behún
If MCU supports the FEAT_CRYPTO feature, read board ECDSA public key
from MCU and print it.

Signed-off-by: Marek Behún 
---
 board/CZ.NIC/turris_omnia/turris_omnia.c | 29 +++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index 7a51ed3ace5..46f576a460e 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -75,6 +75,9 @@ enum mcu_commands {
/* available if EXT_CMD bit set in features */
CMD_EXT_CONTROL = 0x12,
 
+   /* available if CRYPTO bit set in features */
+   CMD_CRYPTO_GET_PUBLIC_KEY   = 0x29,
+
/* available if BOARD_INFO it set in features */
CMD_BOARD_INFO_GET  = 0x2c,
 };
@@ -94,6 +97,7 @@ enum status_word_bits {
 enum features_e {
FEAT_PERIPH_MCU = BIT(0),
FEAT_EXT_CMDS   = BIT(1),
+   FEAT_CRYPTO = BIT(14),
FEAT_BOARD_INFO = BIT(15),
 };
 
@@ -285,6 +289,24 @@ static int omnia_mcu_board_info(char *serial, u8 *mac, 
char *version)
return 0;
 }
 
+static int omnia_mcu_get_board_public_key(char pub_key[static 67])
+{
+   u8 reply[34];
+   int ret;
+
+   ret = omnia_mcu_read(CMD_CRYPTO_GET_PUBLIC_KEY, reply, sizeof(reply));
+   if (ret)
+   return ret;
+
+   if (reply[0] != 33)
+   return -EBADMSG;
+
+   bin2hex(pub_key, [1], 33);
+   reply[66] = '\0';
+
+   return 0;
+}
+
 static void enable_a385_watchdog(unsigned int timeout_minutes)
 {
struct sar_freq_modes sar_freq;
@@ -1060,7 +1082,7 @@ int board_late_init(void)
 
 int checkboard(void)
 {
-   char serial[17], version[4];
+   char serial[17], version[4], pub_key[67];
bool has_version;
int err;
 
@@ -1080,6 +1102,11 @@ int checkboard(void)
printf("  Board version: %s\n", has_version ? version : "unknown");
printf("  Serial Number: %s\n", !err ? serial : "unknown");
 
+   if (omnia_mcu_has_feature(FEAT_CRYPTO)) {
+   err = omnia_mcu_get_board_public_key(pub_key);
+   printf("  ECDSA Public Key: %s\n", !err ? pub_key : "unknown");
+   }
+
return 0;
 }
 
-- 
2.43.0



[PATCH u-boot-mvebu 1/4] arm: mvebu: turris_omnia: Refactor MCU status and features reading

2024-03-04 Thread Marek Behún
Refactor MCU status word and MCU firmware features reading to make it
simpler to use.

Signed-off-by: Marek Behún 
---
 board/CZ.NIC/turris_omnia/turris_omnia.c | 81 
 1 file changed, 53 insertions(+), 28 deletions(-)

diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index adeb69a205b..b285e959d06 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -172,6 +172,48 @@ static int omnia_mcu_write(u8 cmd, const void *buf, int 
len)
return dm_i2c_write(chip, cmd, buf, len);
 }
 
+static int omnia_mcu_get_sts_and_features(u16 *psts, u16 *pfeatures)
+{
+   u16 sts;
+   int ret;
+
+   ret = omnia_mcu_read(CMD_GET_STATUS_WORD, , sizeof(sts));
+   if (ret)
+   return ret;
+
+   if (psts)
+   *psts = sts;
+
+   if (!pfeatures)
+   return 0;
+
+   if (sts & STS_FEATURES_SUPPORTED) {
+   ret = omnia_mcu_read(CMD_GET_FEATURES, pfeatures,
+sizeof(*pfeatures));
+   if (ret)
+   return ret;
+   } else {
+   *pfeatures = 0;
+   }
+
+   return 0;
+}
+
+static int omnia_mcu_get_sts(u16 *sts)
+{
+   return omnia_mcu_get_sts_and_features(sts, NULL);
+}
+
+static bool omnia_mcu_has_feature(u16 feature)
+{
+   u16 features;
+
+   if (omnia_mcu_get_sts_and_features(NULL, ))
+   return false;
+
+   return feature & features;
+}
+
 static void enable_a385_watchdog(unsigned int timeout_minutes)
 {
struct sar_freq_modes sar_freq;
@@ -249,7 +291,7 @@ static bool omnia_detect_sata(const char *msata_slot)
}
}
 
-   ret = omnia_mcu_read(CMD_GET_STATUS_WORD, , sizeof(stsword));
+   ret = omnia_mcu_get_sts();
if (ret) {
printf("omnia_mcu_read failed: %i, defaulting to MiniPCIe 
card\n",
   ret);
@@ -405,20 +447,17 @@ static const char * const omnia_get_mcu_type(void)
[STS_MCU_TYPE_MKL]   = "MKL (with peripheral resets)",
[STS_MCU_TYPE_UNKN]  = "unknown (with peripheral resets)",
};
-   u16 stsword, features;
+   u16 sts;
int ret;
 
-   ret = omnia_mcu_read(CMD_GET_STATUS_WORD, , sizeof(stsword));
+   ret = omnia_mcu_get_sts();
if (ret)
return "unknown";
 
-   if (stsword & STS_FEATURES_SUPPORTED) {
-   ret = omnia_mcu_read(CMD_GET_FEATURES, , 
sizeof(features));
-   if (ret == 0 && (features & FEAT_PERIPH_MCU))
-   return mcu_types_with_perip_resets[stsword & 
STS_MCU_TYPE_MASK];
-   }
+   if (omnia_mcu_has_feature(FEAT_PERIPH_MCU))
+   return mcu_types_with_perip_resets[sts & STS_MCU_TYPE_MASK];
 
-   return mcu_types[stsword & STS_MCU_TYPE_MASK];
+   return mcu_types[sts & STS_MCU_TYPE_MASK];
 }
 
 static const char * const omnia_get_mcu_version(void)
@@ -695,9 +734,6 @@ int board_early_init_f(void)
 
 void spl_board_init(void)
 {
-   u16 val;
-   int ret;
-
/*
 * If booting from UART, disable MCU watchdog in SPL, since uploading
 * U-Boot proper can take too much time and trigger it. Instead enable
@@ -714,12 +750,8 @@ void spl_board_init(void)
 * resets then LAN eth switch is initialized automatically by bootstrap
 * pins when A385 is released from the reset.
 */
-   ret = omnia_mcu_read(CMD_GET_STATUS_WORD, , sizeof(val));
-   if (ret == 0 && (val & STS_FEATURES_SUPPORTED)) {
-   ret = omnia_mcu_read(CMD_GET_FEATURES, , sizeof(val));
-   if (ret == 0 && (val & FEAT_PERIPH_MCU))
-   initialize_switch();
-   }
+   if (omnia_mcu_has_feature(FEAT_PERIPH_MCU))
+   initialize_switch();
 }
 
 #if IS_ENABLED(CONFIG_OF_BOARD_FIXUP) || IS_ENABLED(CONFIG_OF_BOARD_SETUP)
@@ -919,16 +951,9 @@ static int fixup_mcu_gpio_in_eth_wan_node(void *blob)
 #if IS_ENABLED(CONFIG_OF_BOARD_FIXUP)
 int board_fix_fdt(void *blob)
 {
-   u16 val;
-   int ret;
-
-   ret = omnia_mcu_read(CMD_GET_STATUS_WORD, , sizeof(val));
-   if (ret == 0 && (val & STS_FEATURES_SUPPORTED)) {
-   ret = omnia_mcu_read(CMD_GET_FEATURES, , sizeof(val));
-   if (ret == 0 && (val & FEAT_PERIPH_MCU)) {
-   fixup_mcu_gpio_in_pcie_nodes(blob);
-   fixup_mcu_gpio_in_eth_wan_node(blob);
-   }
+   if (omnia_mcu_has_feature(FEAT_PERIPH_MCU)) {
+   fixup_mcu_gpio_in_pcie_nodes(blob);
+   fixup_mcu_gpio_in_eth_wan_node(blob);
}
 
fixup_msata_port_nodes(blob);
-- 
2.43.0



[PATCH u-boot-mvebu 2/4] arm: mvebu: turris_omnia: Implement getting board information from MCU

2024-03-04 Thread Marek Behún
Implement reading board serial number, first MAC address and board
version from MCU. MCU supports board information if the FEAT_BOARD_INFO
feature bit is set in MCU features.

Prefer getting board information from MCU if supported, fallback to
Atmel SHA chip.

Signed-off-by: Marek Behún 
---
 board/CZ.NIC/turris_atsha_otp.c  | 27 +--
 board/CZ.NIC/turris_common.c | 42 ++
 board/CZ.NIC/turris_common.h | 10 +++
 board/CZ.NIC/turris_omnia/Makefile   |  2 +-
 board/CZ.NIC/turris_omnia/turris_omnia.c | 98 +++-
 5 files changed, 149 insertions(+), 30 deletions(-)
 create mode 100644 board/CZ.NIC/turris_common.c
 create mode 100644 board/CZ.NIC/turris_common.h

diff --git a/board/CZ.NIC/turris_atsha_otp.c b/board/CZ.NIC/turris_atsha_otp.c
index a29fe362317..85eebcdf18e 100644
--- a/board/CZ.NIC/turris_atsha_otp.c
+++ b/board/CZ.NIC/turris_atsha_otp.c
@@ -11,6 +11,7 @@
 #include 
 
 #include "turris_atsha_otp.h"
+#include "turris_common.h"
 
 #define TURRIS_ATSHA_OTP_VERSION   0
 #define TURRIS_ATSHA_OTP_SERIAL1
@@ -32,26 +33,6 @@ static struct udevice *get_atsha204a_dev(void)
return dev;
 }
 
-static void increment_mac(u8 *mac)
-{
-   int i;
-
-   for (i = 5; i >= 3; i--) {
-   mac[i] += 1;
-   if (mac[i])
-   break;
-   }
-}
-
-static void set_mac_if_invalid(int i, u8 *mac)
-{
-   u8 oldmac[6];
-
-   if (is_valid_ethaddr(mac) &&
-   !eth_env_get_enetaddr_by_index("eth", i, oldmac))
-   eth_env_set_enetaddr_by_index("eth", i, mac);
-}
-
 int turris_atsha_otp_init_mac_addresses(int first_idx)
 {
struct udevice *dev = get_atsha204a_dev();
@@ -84,11 +65,7 @@ int turris_atsha_otp_init_mac_addresses(int first_idx)
mac[4] = mac1[2];
mac[5] = mac1[3];
 
-   set_mac_if_invalid((first_idx + 0) % 3, mac);
-   increment_mac(mac);
-   set_mac_if_invalid((first_idx + 1) % 3, mac);
-   increment_mac(mac);
-   set_mac_if_invalid((first_idx + 2) % 3, mac);
+   turris_init_mac_addresses(first_idx, mac);
 
return 0;
 }
diff --git a/board/CZ.NIC/turris_common.c b/board/CZ.NIC/turris_common.c
new file mode 100644
index 000..1717dda82eb
--- /dev/null
+++ b/board/CZ.NIC/turris_common.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Marek Behún 
+ */
+
+#include 
+#include 
+
+#include "turris_common.h"
+
+static void increment_mac(u8 *mac)
+{
+   int i;
+
+   for (i = 5; i >= 3; i--) {
+   mac[i] += 1;
+   if (mac[i])
+   break;
+   }
+}
+
+static void set_mac_if_invalid(int i, u8 *mac)
+{
+   u8 oldmac[6];
+
+   if (is_valid_ethaddr(mac) &&
+   !eth_env_get_enetaddr_by_index("eth", i, oldmac))
+   eth_env_set_enetaddr_by_index("eth", i, mac);
+}
+
+void turris_init_mac_addresses(int first_idx, const u8 *first_mac)
+{
+   u8 mac[6];
+
+   memcpy(mac, first_mac, sizeof(mac));
+
+   set_mac_if_invalid((first_idx + 0) % 3, mac);
+   increment_mac(mac);
+   set_mac_if_invalid((first_idx + 1) % 3, mac);
+   increment_mac(mac);
+   set_mac_if_invalid((first_idx + 2) % 3, mac);
+}
diff --git a/board/CZ.NIC/turris_common.h b/board/CZ.NIC/turris_common.h
new file mode 100644
index 000..5565ea9fd2a
--- /dev/null
+++ b/board/CZ.NIC/turris_common.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef TURRIS_COMMON_H
+#define TURRIS_COMMON_H
+
+#include 
+
+void turris_init_mac_addresses(int first_idx, const u8 *first_mac);
+
+#endif
diff --git a/board/CZ.NIC/turris_omnia/Makefile 
b/board/CZ.NIC/turris_omnia/Makefile
index dc39b44ae19..341378b4e54 100644
--- a/board/CZ.NIC/turris_omnia/Makefile
+++ b/board/CZ.NIC/turris_omnia/Makefile
@@ -2,4 +2,4 @@
 #
 # Copyright (C) 2017 Marek Behún 
 
-obj-y  := turris_omnia.o ../turris_atsha_otp.o
+obj-y  := turris_omnia.o ../turris_atsha_otp.o ../turris_common.o
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c 
b/board/CZ.NIC/turris_omnia/turris_omnia.c
index b285e959d06..7a51ed3ace5 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -18,18 +18,21 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
 #include "../drivers/ddr/marvell/a38x/ddr3_init.h"
 #include <../serdes/a38x/high_speed_env_spec.h>
 #include "../turris_atsha_otp.h"
+#include "../turris_common.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -71,6 +74,9 @@ enum mcu_commands {
 
/* available if EXT_CMD bit set in features */
CMD_EXT_CONTROL = 0x12,
+
+   /* available if BOARD_INFO it set in features */
+   CMD_BOARD_INFO_GET  = 0x2c,
 

[PATCH u-boot-mvebu 0/4] Turris Omnia - New board revision support

2024-03-04 Thread Marek Behún
Hi Stefan,

a new board revision of Omnia is coming. In this new revision the board
information (serial number, MAC address) and board cryptography is
implemented by the microcontroller. The ATSHA204A cryptochip is not
present on this new revision.

Here are some changes regarding this.

Marek

Marek Behún (4):
  arm: mvebu: turris_omnia: Refactor MCU status and features reading
  arm: mvebu: turris_omnia: Implement getting board information from MCU
  arm: mvebu: turris_omnia: Print board ECDSA public key if available
  arm: mvebu: turris_omnia: Disable Atmel SHA node if not present

 board/CZ.NIC/turris_atsha_otp.c  |  27 +--
 board/CZ.NIC/turris_common.c |  42 +
 board/CZ.NIC/turris_common.h |  10 +
 board/CZ.NIC/turris_omnia/Makefile   |   2 +-
 board/CZ.NIC/turris_omnia/turris_omnia.c | 229 +++
 5 files changed, 252 insertions(+), 58 deletions(-)
 create mode 100644 board/CZ.NIC/turris_common.c
 create mode 100644 board/CZ.NIC/turris_common.h

-- 
2.43.0



Re: [PATCH v2] net: mv88e6xxx: fix missing SMI address initialization

2024-03-04 Thread Marek Behún
Hi Stefan,

On Wed, 14 Feb 2024 08:50:16 +0100
Stefan Roese  wrote:

> Hi Ramon,
> 
> On 1/9/24 10:37, Stefan Roese wrote:
> > On 12/18/23 17:09, Marek Behún wrote:  
> >> On Wed, 6 Dec 2023 15:35:56 +0100
> >> Marek Mojík  wrote:
> >>  
> >>> The mv88e6xxx driver does not currently initialize the smi_addr 
> >>> field, but
> >>> instead keeps the default zero value. This leads to driver being 
> >>> unusable
> >>> on devices where the switch is not on address zero of the mdio bus. Fix
> >>> this problem by reading the SMI address from device tree.
> >>>
> >>> Signed-off-by: Marek Mojík 
> >>> ---
> >>>   drivers/net/mv88e6xxx.c | 8 
> >>>   1 file changed, 8 insertions(+)
> >>>
> >>> diff --git a/drivers/net/mv88e6xxx.c b/drivers/net/mv88e6xxx.c
> >>> index c073f81e72..8fbbc1cacc 100644
> >>> --- a/drivers/net/mv88e6xxx.c
> >>> +++ b/drivers/net/mv88e6xxx.c
> >>> @@ -745,6 +745,7 @@ static int mv88e6xxx_probe(struct udevice *dev)
> >>>   {
> >>>   struct dsa_pdata *dsa_pdata = dev_get_uclass_plat(dev);
> >>>   struct mv88e6xxx_priv *priv = dev_get_priv(dev);
> >>> +    fdt_addr_t smi_addr;
> >>>   int val, ret;
> >>>   if (ofnode_valid(dev_ofnode(dev)) &&
> >>> @@ -753,6 +754,13 @@ static int mv88e6xxx_probe(struct udevice *dev)
> >>>   return -ENODEV;
> >>>   }
> >>> +    smi_addr = dev_read_addr(dev);
> >>> +    if (smi_addr == FDT_ADDR_T_NONE) {
> >>> +    dev_err(dev, "Missing SMI address\n");
> >>> +    return -EINVAL;
> >>> +    }
> >>> +    priv->smi_addr = smi_addr;
> >>> +
> >>>   /* probe internal mdio bus */
> >>>   ret = mv88e6xxx_probe_mdio(dev);
> >>>   if (ret)  
> >>
> >> Reviewed-by: Marek Behún   
> > 
> > Reviewed-by: Stefan Roese 
> > 
> > Ramon, this patch was assigned to me as an Marvell MVEBU patch
> > depends on it. I've assigned it to you now. Or if it's okay that
> > I pull it with the Marvell tree, just let me know.  
> 
> Any updates on this?
> 
> Thanks,
> Stefan

Stefan, it seems that Ramon is unavailable for this.
Can we take this? We've been using it on Omnia and it works correctly.

Marek


Re: [PATCH v4] rng: Add Turris Mox rTWM RNG driver

2024-02-13 Thread Marek Behún
On Tue, 13 Feb 2024 10:49:43 +0100
Heinrich Schuchardt  wrote:

> On 2/13/24 10:16, Stefan Roese wrote:
> > Hi Max,
> >
> > mostly some nitpicking comments below.
> >
> > On 2/11/24 14:04, Max Resch wrote:  
> >> A RNG driver for Armada 3720 boards running the Turris Mox rWTM firmware
> >> from CZ.NIC in the secure processor.
> >>
> >> Signed-off-by: Max Resch 
> >> ---
> >>
> >> Changes in v4:
> >>   - wrongful/missing git rebase
> >>
> >> Changes in v3:
> >>   - More meaningful variable names in accordance with review
> >>
> >> Changes in v2:
> >>   - Removed ring buffer implementation
> >>
> >>   drivers/rng/Kconfig   |   8 +++
> >>   drivers/rng/Makefile  |   1 +
> >>   drivers/rng/turris_rwtm_rng.c | 122 ++
> >>   3 files changed, 131 insertions(+)
> >>   create mode 100644 drivers/rng/turris_rwtm_rng.c
> >>
> >> diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig
> >> index a89c899568..cd72852a47 100644
> >> --- a/drivers/rng/Kconfig
> >> +++ b/drivers/rng/Kconfig
> >> @@ -105,4 +105,12 @@ config RNG_JH7110
> >>   help
> >>     Enable True Random Number Generator in StarFive JH7110 SoCs.
> >> +config RNG_TURRIS_RWTM
> >> +    bool "Turris Mox TRNG in Secure Processor"
> >> +    depends on DM_RNG && ARMADA_3700
> >> +    help
> >> +  Use TRNG in Turris Mox Secure Processor Firmware. Can be used
> >> +  on other Armada-3700 devices (like EspressoBin) if Secure
> >> +  Firmware from CZ.NIC is used.
> >> +
> >>   endif
> >> diff --git a/drivers/rng/Makefile b/drivers/rng/Makefile
> >> index 7e64c4cdfc..ecae1a3da3 100644
> >> --- a/drivers/rng/Makefile
> >> +++ b/drivers/rng/Makefile
> >> @@ -17,3 +17,4 @@ obj-$(CONFIG_RNG_SMCCC_TRNG) += smccc_trng.o
> >>   obj-$(CONFIG_RNG_ARM_RNDR) += arm_rndr.o
> >>   obj-$(CONFIG_TPM_RNG) += tpm_rng.o
> >>   obj-$(CONFIG_RNG_JH7110) += jh7110_rng.o
> >> +obj-$(CONFIG_RNG_TURRIS_RWTM) += turris_rwtm_rng.o
> >> diff --git a/drivers/rng/turris_rwtm_rng.c
> >> b/drivers/rng/turris_rwtm_rng.c
> >> new file mode 100644
> >> index 00..ec2cb0bca3
> >> --- /dev/null
> >> +++ b/drivers/rng/turris_rwtm_rng.c
> >> @@ -0,0 +1,122 @@
> >> +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
> >> +/*
> >> + * Copyright (c) 2024, Max Resch
> >> + */
> >> +
> >> +#include 
> >> +#include 
> >> +#include 
> >> +#include 
> >> +#include 
> >> +#include 
> >> +
> >> +/* size of entropy buffer */
> >> +#define RNG_BUFFER_SIZE    128U
> >> +
> >> +struct turris_rwtm_rng_priv {
> >> +    phys_addr_t buffer;
> >> +};
> >> +
> >> +static int turris_rwtm_rng_fill_entropy(phys_addr_t entropy, size_t
> >> size)
> >> +{
> >> +    u32 args[3] = { 1, (u32)entropy, size };  
> 
> On a device with memory above 4 GiB this (u32) conversion may point to a
> different location than rwtm_rng_priv.
> 
> Is the Armada 3700 family restricted to below 4 GiB?

Indeed it is. Only virtual memory can be mapped to higher locations,
all physical resources (DDR, registers, PCIe, DMA, rWTM) can only be
confiured with 32 bits.

> Should we add a check in the probe function?

No need.


Re: [PATCH v2] rng: Add Turris Mox rWTM RNG driver

2024-02-05 Thread Marek Behún
So you're using A3720 with OpenBSD? Can I ask which A3720 boards do you
use?

Marek

On Mon, 05 Feb 2024 14:46:24 +0100
Mark Kettenis  wrote:

> > Date: Mon, 5 Feb 2024 12:40:14 +0100
> > From: Marek Behún 
> > 
> > Hello Max,
> > 
> > Out of curiousity, what is your use case for having these random
> > numbers on this platform in U-Boot?  
> 
> It means that U-Boot will implement the EFI RNG protocol.  The OpenBSD
> bootloader will use that to fill an initial pool of random numbers for
> the kernel.  And the Linux kernel EFI stub uses it to do kernel
> address space randomization.
> 
> Cheers,
> 
> Mark
> 
> > Below are a few more things to change and then you I'll give my
> > Reviewed-by tag.
> > 
> > On Sun, 21 Jan 2024 21:17:16 +0100
> > Max Resch  wrote:
> >   
> > > A RNG driver for Armada 3720 boards running the Turris Mox rWTM firmware
> > > from CZ.NIC in the secure processor.
> > > 
> > > Signed-off-by: Max Resch 
> > > ---
> > > 
> > > Changes in v2:
> > >  - Removed ring buffer implementation
> > > 
> > >  drivers/rng/Kconfig   |   8 +++
> > >  drivers/rng/Makefile  |   1 +
> > >  drivers/rng/turris_rwtm_rng.c | 122 ++
> > >  3 files changed, 131 insertions(+)
> > >  create mode 100644 drivers/rng/turris_rwtm_rng.c
> > > 
> > > diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig
> > > index a89c899568..cd72852a47 100644
> > > --- a/drivers/rng/Kconfig
> > > +++ b/drivers/rng/Kconfig
> > > @@ -105,4 +105,12 @@ config RNG_JH7110
> > >   help
> > > Enable True Random Number Generator in StarFive JH7110 SoCs.
> > >  
> > > +config RNG_TURRIS_RWTM
> > > + bool "Turris Mox TRNG in Secure Processor"
> > > + depends on DM_RNG && ARMADA_3700
> > > + help
> > > +   Use TRNG in Turris Mox Secure Processor Firmware. Can be used
> > > +   on other Armada-3700 devices (like EspressoBin) if Secure
> > > +   Firmware from CZ.NIC is used.
> > > +
> > >  endif
> > > diff --git a/drivers/rng/Makefile b/drivers/rng/Makefile
> > > index 7e64c4cdfc..ecae1a3da3 100644
> > > --- a/drivers/rng/Makefile
> > > +++ b/drivers/rng/Makefile
> > > @@ -17,3 +17,4 @@ obj-$(CONFIG_RNG_SMCCC_TRNG) += smccc_trng.o
> > >  obj-$(CONFIG_RNG_ARM_RNDR) += arm_rndr.o
> > >  obj-$(CONFIG_TPM_RNG) += tpm_rng.o
> > >  obj-$(CONFIG_RNG_JH7110) += jh7110_rng.o
> > > +obj-$(CONFIG_RNG_TURRIS_RWTM) += turris_rwtm_rng.o
> > > diff --git a/drivers/rng/turris_rwtm_rng.c b/drivers/rng/turris_rwtm_rng.c
> > > new file mode 100644
> > > index 00..143fe0b47f
> > > --- /dev/null
> > > +++ b/drivers/rng/turris_rwtm_rng.c
> > > @@ -0,0 +1,122 @@
> > > +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
> > > +/*
> > > + * Copyright (c) 2024, Max Resch
> > > + */
> > > +
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +
> > > +/* size of entropy buffer */
> > > +#define RNG_BUFFER_SIZE  128U
> > > +
> > > +struct turris_rwtm_rng_priv {
> > > + phys_addr_t buffer;
> > > +};
> > > +
> > > +static int turris_rwtm_rng_fill_entropy(phys_addr_t entropy, size_t size)
> > > +{
> > > + u32 args[3] = { 1, (u32)entropy, size };
> > > + int ret;
> > > +
> > > + /* flush data cache */
> > > + flush_dcache_range(entropy, entropy + size);
> > > +
> > > + /*
> > > +  * get entropy
> > > +  * args[0] = 1 copies BYTES array in args[1] of length args[2]
> > > +  */
> > > + ret = mbox_do_cmd(MBOX_CMD_GET_RANDOM, args, 3, NULL, 0);
> > > + if (ret < 0)
> > > + return ret;
> > > +
> > > + /* invalidate data cache */
> > > + invalidate_dcache_range(entropy, entropy + size);
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int turris_rwtm_rng_random_read(struct udevice *dev, void *data, 
> > > size_t count)
> > > +{
> > > + phys_addr_t p;
> > > + size_t size;
> > > + int ret;
> > > +
> > > + p = ((struct turris_rwtm_rng_priv *)dev_get_priv(dev))->buffer;  
> > 
> > Please declare
> > 
> >   struct turris_rwtm_rng_priv *priv = d

  1   2   3   4   5   6   7   8   9   10   >