Add a configurable Rockchip SPL hotkey feature that checks the
serial console during SPL startup.

Ctrl+B can be used to enter MaskROM mode and be widely used.
Ctrl+D can be used to enter Loader mode, Ctrl+F for Fastboot mode.
We can add more boot mode support in future.

Add CONFIG_SPL_ROCKCHIP_HOTKEY to enable the feature and wait for
the serial port to be ready to receive input before checking for
hotkeys.

Signed-off-by: Valentin Liu <[email protected]>
---
Changes for v2:
- Simplify the dependencies of SPL_ROCKCHIP_HOTKEY.
- Remove the conditions for the newly added includes.
---
Changes for v3:
- Add a dummy spl_hotkey_init() to avoid undefined reference errors
  when building without CONFIG_SPL_ROCKCHIP_HOTKEY.
---
Changes for v4:
- Add condition of CONFIG_ROCKCHIP_BOOT_MODE_REG != 0 to prevent
  SPL hotkey be compiled and used on unsupported platforms.
- Add more hotkey support (Ctrl+D and Ctrl+F).
- Remove prints on the standard path.
- Add some code comment.

 arch/arm/mach-rockchip/Kconfig | 14 +++++++++
 arch/arm/mach-rockchip/spl.c   | 54 ++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+)

diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 1a2e7847c9e..0e485e8caf6 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -743,6 +743,20 @@ config TPL_ROCKCHIP_EARLYRETURN_TO_BROM
 config SPL_MMC
        default y if !SPL_ROCKCHIP_BACK_TO_BROM
 
+config SPL_ROCKCHIP_HOTKEY
+       bool "SPL hotkey support"
+       depends on SPL_DM_RESET && SPL_SERIAL
+       help
+         Enable hotkey detection during SPL booting stage.
+
+         When enabled, SPL checks the serial console for a control
+         character and can execute Rockchip-specific hotkey actions,
+         such as entering MaskROM mode with Ctrl+B, entering Loader
+         mode with Ctrl+D, entering Fastboot mode with Ctrl+F.
+
+         The hotkey is checked after the SPL console has been
+         initialized.
+
 config ROCKCHIP_SPI_IMAGE
        bool "Build a SPI image for rockchip"
        help
diff --git a/arch/arm/mach-rockchip/spl.c b/arch/arm/mach-rockchip/spl.c
index e989c148079..8d0f605040f 100644
--- a/arch/arm/mach-rockchip/spl.c
+++ b/arch/arm/mach-rockchip/spl.c
@@ -13,11 +13,14 @@
 #include <log.h>
 #include <mapmem.h>
 #include <ram.h>
+#include <serial.h>
 #include <spl.h>
+#include <asm/arch-rockchip/boot_mode.h>
 #include <asm/arch-rockchip/bootrom.h>
 #include <asm/arch-rockchip/timer.h>
 #include <asm/global_data.h>
 #include <asm/io.h>
+#include <linux/delay.h>
 #include <linux/bitops.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -107,6 +110,54 @@ __weak int arch_cpu_init(void)
        return 0;
 }
 
+#if CONFIG_IS_ENABLED(SPL_ROCKCHIP_HOTKEY) && (CONFIG_ROCKCHIP_BOOT_MODE_REG 
!= 0)
+static void rockchip_reset_from_hotkey(const int code)
+{
+       switch (code) {
+       case 0x02: /* Ctrl+B */
+               printf("Ctrl+B pressed, entering download mode...\n");
+               writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG);
+               do_reset(NULL, 0, 0, NULL);
+               /* NOTREACHED */
+       case 0x04: /* Ctrl+D */
+               printf("Ctrl+D pressed, entering loader mode...\n");
+               writel(BOOT_LOADER, CONFIG_ROCKCHIP_BOOT_MODE_REG);
+               do_reset(NULL, 0, 0, NULL);
+               /* NOTREACHED */
+       case 0x06: /* Ctrl+F */
+               printf("Ctrl+F pressed, entering fastboot mode...\n");
+               writel(BOOT_FASTBOOT, CONFIG_ROCKCHIP_BOOT_MODE_REG);
+               do_reset(NULL, 0, 0, NULL);
+               /* NOTREACHED */
+       default:
+               if (code <= 0x1a) /* 'z' */
+                       log_debug("SPL Hotkey: Ctrl+%c\n", code + 'A' - 1);
+               else
+                       log_debug("SPL Hotkey: Unknown code: 0x%x, ignore\n", 
code);
+       }
+}
+
+static void spl_hotkey_init(void)
+{
+       if (!gd || !(gd->flags & GD_FLG_HAVE_CONSOLE))
+               return;
+       if (gd->flags & GD_FLG_DISABLE_CONSOLE)
+               return;
+
+       /* Wait for the serial port to be ready to receive data. */
+       mdelay(100);
+
+       if (serial_tstc())
+               rockchip_reset_from_hotkey(serial_getc());
+       else
+               log_debug("SPL Hotkey: No key pressed, continue\n");
+}
+#else
+static void spl_hotkey_init(void)
+{
+}
+#endif
+
 void board_init_f(ulong dummy)
 {
        int ret;
@@ -143,6 +194,9 @@ void board_init_f(ulong dummy)
        }
 #endif
        preloader_console_init();
+
+       if (CONFIG_IS_ENABLED(SPL_ROCKCHIP_HOTKEY))
+               spl_hotkey_init();
 }
 
 void spl_board_prepare_for_boot(void)
-- 
2.53.0

Reply via email to