Teach the "reset" command to trigger the reset modes registered with the
reboot-mode framework in addition to the existing cold and warm resets:

  reset          cold reset (unchanged)
  reset -w       warm reset (unchanged)
  reset -<mode>  reset into a mode declared in the device tree
  reset -l       list the available reset modes

For example "reset -edl" enters Qualcomm EDL/download mode when the psci
device tree node carries a "reboot-mode" subnode with
"mode-edl = <0x80000000 0x00000001>". The command never parses the magic
values itself; it strips the leading '-' and hands the mode name to
reboot_mode_request(), so the values stay in the device tree and are not
hardcoded per SoC. An unknown mode prints the registered modes rather than
silently falling through to a cold reset.

Signed-off-by: Balaji Selvanathan <[email protected]>
---
 cmd/boot.c                         |  6 +++++-
 drivers/sysreset/sysreset-uclass.c | 27 ++++++++++++++++++++++++++-
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/cmd/boot.c b/cmd/boot.c
index 23496cafdf5..5f89c3ed889 100644
--- a/cmd/boot.c
+++ b/cmd/boot.c
@@ -60,7 +60,11 @@ U_BOOT_CMD(
        reset, 2, 0,    do_reset,
        "Perform RESET of the CPU",
        "- cold boot without level specifier\n"
-       "reset -w - warm reset if implemented"
+       "reset -w - warm reset if implemented\n"
+#if IS_ENABLED(CONFIG_DM_REBOOT_MODE)
+       "reset -<mode> - reset into a mode declared in the device tree\n"
+       "reset -l - list the available reset modes\n"
+#endif
 );
 
 #ifdef CONFIG_CMD_POWEROFF
diff --git a/drivers/sysreset/sysreset-uclass.c 
b/drivers/sysreset/sysreset-uclass.c
index 536ac727142..960d8ddac23 100644
--- a/drivers/sysreset/sysreset-uclass.c
+++ b/drivers/sysreset/sysreset-uclass.c
@@ -13,6 +13,7 @@
 #include <hang.h>
 #include <log.h>
 #include <regmap.h>
+#include <reboot-mode/reboot-mode.h>
 #include <spl.h>
 #include <sysreset.h>
 #include <dm/device-internal.h>
@@ -125,8 +126,32 @@ int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
        if (argc > 2)
                return CMD_RET_USAGE;
 
-       if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'w') {
+       if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'w' &&
+           !argv[1][2]) {
                reset_type = SYSRESET_WARM;
+       } else if (CONFIG_IS_ENABLED(DM_REBOOT_MODE) && argc == 2 &&
+                  argv[1][0] == '-') {
+               /*
+                * "reset -l" lists the modes registered with the reboot-mode
+                * framework; "reset -<mode>" triggers a named mode (for
+                * example "reset -edl"). The mode magic values live in the
+                * device tree.
+                */
+               const char *name = &argv[1][1];
+
+               if (!strcmp(name, "l"))
+                       return reboot_mode_list() ? CMD_RET_FAILURE :
+                                                   CMD_RET_SUCCESS;
+
+               printf("resetting into \"%s\" mode ...\n", name);
+               mdelay(100);
+
+               /* Does not return on success. */
+               reboot_mode_request(name);
+
+               printf("Unknown reset mode \"%s\"\n", name);
+               reboot_mode_list();
+               return CMD_RET_USAGE;
        }
 
        printf("resetting ...\n");

-- 
2.34.1

Reply via email to