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
