The reboot-mode framework currently stores a single u32 magic value per
mode and parses exactly one cell from each "mode-*" device tree property.
That is sufficient for the existing backing-store users (nvmem, gpio,
rtc), but a PSCI SYSTEM_RESET2 vendor reset is described by up to three
32-bit cells: <reset_type[, cookie_hi[, cookie_lo]]>, matching the
reboot-mode binding for the psci "reboot-mode" subnode.

Restructure struct reboot_mode_mode to hold an array of up to
REBOOT_MODE_MAX_MAGIC (3) cells plus a cell count, and make
dm_reboot_mode_pre_probe() length-aware so it reads 1 to 3 cells from
each property. dm_reboot_mode_update() now matches the backing-store
value against magic[0].

Existing single-cell modes (e.g. nvmem "mode-bootloader = <0x02>") parse
to magic[0] = 0x02, count = 1 and keep matching exactly as before, so
there is no functional change for current users.

Signed-off-by: Balaji Selvanathan <[email protected]>
---
 drivers/reboot-mode/reboot-mode-uclass.c | 28 ++++++++++++++++++++++------
 include/reboot-mode/reboot-mode.h        |  8 +++++++-
 2 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/drivers/reboot-mode/reboot-mode-uclass.c 
b/drivers/reboot-mode/reboot-mode-uclass.c
index 7cbe02eb4ed..80aabf54750 100644
--- a/drivers/reboot-mode/reboot-mode-uclass.c
+++ b/drivers/reboot-mode/reboot-mode-uclass.c
@@ -30,7 +30,7 @@ int dm_reboot_mode_update(struct udevice *dev)
                dev_get_uclass_plat(dev);
 
        for (i = 0; i < plat_data->count; i++) {
-               if (plat_data->modes[i].mode_id == rebootmode) {
+               if (plat_data->modes[i].magic[0] == rebootmode) {
                        ret = env_set(plat_data->env_variable,
                                      plat_data->modes[i].mode_name);
                        if (ret) {
@@ -68,6 +68,7 @@ int dm_reboot_mode_pre_probe(struct udevice *dev)
        struct ofprop property;
        const u32 *propvalue;
        const char *propname;
+       int len, cells, i;
 
        plat_data->env_variable = dev_read_string(dev, "u-boot,env-variable");
        if (!plat_data->env_variable)
@@ -93,19 +94,34 @@ int dm_reboot_mode_pre_probe(struct udevice *dev)
        struct reboot_mode_mode *next = plat_data->modes;
 
        dev_for_each_property(property, dev) {
-               propvalue = dev_read_prop_by_prop(&property, &propname, NULL);
+               propvalue = dev_read_prop_by_prop(&property, &propname, &len);
                if (!propvalue) {
                        dev_err(dev, "Could not get the value for property 
%s\n",
                                propname);
                        return -EINVAL;
                }
 
-               if (!strncmp(propname, mode_prefix, mode_prefix_len)) {
-                       next->mode_name = &propname[mode_prefix_len];
-                       next->mode_id = fdt32_to_cpu(*propvalue);
+               if (strncmp(propname, mode_prefix, mode_prefix_len))
+                       continue;
 
-                       next++;
+               /*
+                * A mode may carry 1 to REBOOT_MODE_MAX_MAGIC 32-bit cells.
+                * Cells beyond the maximum are ignored.
+                */
+               cells = len / sizeof(u32);
+               if (cells < 1) {
+                       dev_err(dev, "Mode %s has no magic value\n", propname);
+                       return -EINVAL;
                }
+               if (cells > REBOOT_MODE_MAX_MAGIC)
+                       cells = REBOOT_MODE_MAX_MAGIC;
+
+               next->mode_name = &propname[mode_prefix_len];
+               next->count = cells;
+               for (i = 0; i < cells; i++)
+                       next->magic[i] = fdt32_to_cpu(propvalue[i]);
+
+               next++;
        }
 #else
        if (!plat_data->env_variable)
diff --git a/include/reboot-mode/reboot-mode.h 
b/include/reboot-mode/reboot-mode.h
index 5fbd7c801af..54a8c09650e 100644
--- a/include/reboot-mode/reboot-mode.h
+++ b/include/reboot-mode/reboot-mode.h
@@ -9,9 +9,15 @@
 #include <asm/types.h>
 #include <dm/device.h>
 
+/*
+ * Maximum number of 32-bit magic cells a reboot mode may carry.
+ */
+#define REBOOT_MODE_MAX_MAGIC  3
+
 struct reboot_mode_mode {
        const char *mode_name;
-       u32 mode_id;
+       u32 magic[REBOOT_MODE_MAX_MAGIC];
+       u8 count;
 };
 
 struct reboot_mode_uclass_platdata {

-- 
2.34.1

Reply via email to