stm32mp1: support forced boot mode
authorPatrick Delaunay <patrick.delaunay@st.com>
Wed, 27 Feb 2019 16:01:20 +0000 (17:01 +0100)
committerPatrick Delaunay <patrick.delaunay@st.com>
Fri, 12 Apr 2019 14:09:13 +0000 (16:09 +0200)
The boot mode can be forced by key press
or by TAMP register, requested in kernel by syscon-reboot-mode

tamp: tamp@5c00a000 {
compatible = "simple-bus", "syscon", "simple-mfd";
reg = <0x5c00a000 0x400>;

reboot-mode {
compatible = "syscon-reboot-mode";
offset = <0x150>; /* reg20 */
mask = <0xff>;
mode-normal = <0>;
mode-fastboot = <0x1>;
mode-recovery = <0x2>;
mode-stm32cubeprogrammer = <0x3>;
mode-ums_mmc0 = <0x10>;
mode-ums_mmc1 = <0x11>;
mode-ums_mmc2 = <0x12>;
};
};

Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi
arch/arm/mach-stm32mp/cpu.c
arch/arm/mach-stm32mp/include/mach/stm32.h
board/st/stm32mp1/stm32mp1.c

index 70bbf66704262ba55eb4b2cb8a8d5369e58acfa9..d22401c26e460bbb7e1648cd209987a228c90a12 100644 (file)
                i2c3 = &i2c4;
        };
 
+       config {
+               st,fastboot-gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;
+               st,stm32prog-gpios = <&gpioa 14 GPIO_ACTIVE_LOW>;
+       };
+
        led {
                compatible = "gpio-leds";
 
index 206b82e9e929d3e129713160113cc7774ea97698..305ea6dd643fb532e38ca7e229a75eec966765ed 100644 (file)
@@ -359,12 +359,12 @@ static void setup_boot_mode(void)
        u32 boot_mode =
                (boot_ctx & TAMP_BOOT_MODE_MASK) >> TAMP_BOOT_MODE_SHIFT;
        int instance = (boot_mode & TAMP_BOOT_INSTANCE_MASK) - 1;
+       u32 forced_mode = (boot_ctx & TAMP_BOOT_FORCED_MASK);
        struct udevice *dev;
        int alias;
 
-       pr_debug("%s: boot_ctx=0x%x => boot_mode=%x, instance=%d\n",
-                __func__, boot_ctx, boot_mode, instance);
-
+       pr_debug("%s: boot_ctx=0x%x => boot_mode=%x, instance=%d forced=%x\n",
+                __func__, boot_ctx, boot_mode, instance, forced_mode);
        switch (boot_mode & TAMP_BOOT_DEVICE_MASK) {
        case BOOT_SERIAL_UART:
                if (instance > ARRAY_SIZE(serial_addr))
@@ -409,6 +409,36 @@ static void setup_boot_mode(void)
                pr_debug("unexpected boot mode = %x\n", boot_mode);
                break;
        }
+
+       switch (forced_mode) {
+       case BOOT_FASTBOOT:
+               printf("Enter fastboot!\n");
+               env_set("preboot", "env set preboot; fastboot 0");
+               break;
+       case BOOT_STM32PROG:
+               env_set("boot_device", "usb");
+               env_set("boot_instance", "0");
+               break;
+       case BOOT_UMS_MMC0:
+       case BOOT_UMS_MMC1:
+       case BOOT_UMS_MMC2:
+               printf("Enter UMS!\n");
+               instance = forced_mode - BOOT_UMS_MMC0;
+               sprintf(cmd, "env set preboot; ums 0 mmc %d", instance);
+               env_set("preboot", cmd);
+               break;
+       case BOOT_RECOVERY:
+               env_set("preboot", "env set preboot; run altbootcmd");
+               break;
+       case BOOT_NORMAL:
+               break;
+       default:
+               pr_debug("unexpected forced boot mode = %x\n", forced_mode);
+               break;
+       }
+
+       /* clear TAMP for next reboot */
+       clrsetbits_le32(TAMP_BOOT_CONTEXT, TAMP_BOOT_FORCED_MASK, BOOT_NORMAL);
 }
 
 /*
index f2ab026a5a44fda5751b6144556b2fe4c46e198e..da23af0a64e5b48dc077c6c42bacca8bd1eb3ed7 100644 (file)
@@ -92,6 +92,17 @@ enum boot_device {
 #define TAMP_BOOT_MODE_SHIFT           8
 #define TAMP_BOOT_DEVICE_MASK          GENMASK(7, 4)
 #define TAMP_BOOT_INSTANCE_MASK                GENMASK(3, 0)
+#define TAMP_BOOT_FORCED_MASK          GENMASK(7, 0)
+
+enum forced_boot_mode {
+       BOOT_NORMAL = 0x00,
+       BOOT_FASTBOOT = 0x01,
+       BOOT_RECOVERY = 0x02,
+       BOOT_STM32PROG = 0x03,
+       BOOT_UMS_MMC0 = 0x10,
+       BOOT_UMS_MMC1 = 0x11,
+       BOOT_UMS_MMC2 = 0x12,
+};
 
 /* offset used for BSEC driver: misc_read and misc_write */
 #define STM32_BSEC_SHADOW_OFFSET       0x0
index 0d963c2af4f2d80215730c6b17ea6f15932ddb4e..d13793ed6a945492af4998ab9ef7fc2a354476b2 100644 (file)
@@ -67,6 +67,55 @@ int checkboard(void)
        return 0;
 }
 
+static void board_key_check(void)
+{
+#if defined(CONFIG_FASTBOOT) || defined(CONFIG_CMD_STM32PROG)
+       ofnode node;
+       struct gpio_desc gpio;
+       enum forced_boot_mode boot_mode = BOOT_NORMAL;
+
+       node = ofnode_path("/config");
+       if (!ofnode_valid(node)) {
+               debug("%s: no /config node?\n", __func__);
+               return;
+       }
+#ifdef CONFIG_FASTBOOT
+       if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0,
+                                      &gpio, GPIOD_IS_IN)) {
+               debug("%s: could not find a /config/st,fastboot-gpios\n",
+                     __func__);
+       } else {
+               if (dm_gpio_get_value(&gpio)) {
+                       puts("Fastboot key pressed, ");
+                       boot_mode = BOOT_FASTBOOT;
+               }
+
+               dm_gpio_free(NULL, &gpio);
+       }
+#endif
+#ifdef CONFIG_CMD_STM32PROG
+       if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0,
+                                      &gpio, GPIOD_IS_IN)) {
+               debug("%s: could not find a /config/st,stm32prog-gpios\n",
+                     __func__);
+       } else {
+               if (dm_gpio_get_value(&gpio)) {
+                       puts("STM32Programmer key pressed, ");
+                       boot_mode = BOOT_STM32PROG;
+               }
+               dm_gpio_free(NULL, &gpio);
+       }
+#endif
+
+       if (boot_mode != BOOT_NORMAL) {
+               puts("entering download mode...\n");
+               clrsetbits_le32(TAMP_BOOT_CONTEXT,
+                               TAMP_BOOT_FORCED_MASK,
+                               boot_mode);
+       }
+#endif
+}
+
 static struct dwc2_plat_otg_data stm32mp_otg_data = {
        .usb_gusbcfg = STM32MP_GUSBCFG,
 };
@@ -227,6 +276,8 @@ int board_init(void)
        /* address of boot parameters */
        gd->bd->bi_boot_params = STM32_DDR_BASE + 0x100;
 
+       board_key_check();
+
        if (IS_ENABLED(CONFIG_LED))
                led_default_state();