stm32mp1: support forced boot mode
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>
diff --git a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi
index 70bbf66..d22401c 100644
--- a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi
+++ b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi
@@ -14,6 +14,11 @@
i2c3 = &i2c4;
};
+ config {
+ st,fastboot-gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;
+ st,stm32prog-gpios = <&gpioa 14 GPIO_ACTIVE_LOW>;
+ };
+
led {
compatible = "gpio-leds";
diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c
index 206b82e..305ea6d 100644
--- a/arch/arm/mach-stm32mp/cpu.c
+++ b/arch/arm/mach-stm32mp/cpu.c
@@ -359,12 +359,12 @@
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 @@
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);
}
/*
diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h
index f2ab026..da23af0 100644
--- a/arch/arm/mach-stm32mp/include/mach/stm32.h
+++ b/arch/arm/mach-stm32mp/include/mach/stm32.h
@@ -92,6 +92,17 @@
#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