ARM: imx: Add support for switching primary/secondary boot mode to bmode
The i.MX6/i.MX7 is capable of booting a secondary "redundant" system
image in case the primary one is corrupted. The user can force this
boot mode as well by explicitly setting SRC GPR10 bit 30. This can be
potentially useful when upgrading the bootloader itself. Expose this
functionality to the user.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Fabio Estevam <festevam@gmail.com>
Cc: NXP i.MX U-Boot Team <uboot-imx@nxp.com>
Cc: Peng Fan <peng.fan@nxp.com>
Cc: Stefano Babic <sbabic@denx.de>
Reviewed-by: Stefano Babic <sbabic@denx.de>
diff --git a/arch/arm/include/asm/mach-imx/boot_mode.h b/arch/arm/include/asm/mach-imx/boot_mode.h
index 3a483b6..6dc5855 100644
--- a/arch/arm/include/asm/mach-imx/boot_mode.h
+++ b/arch/arm/include/asm/mach-imx/boot_mode.h
@@ -7,6 +7,8 @@
#define _ASM_BOOT_MODE_H
#define MAKE_CFGVAL(cfg1, cfg2, cfg3, cfg4) \
((cfg4) << 24) | ((cfg3) << 16) | ((cfg2) << 8) | (cfg1)
+#define MAKE_CFGVAL_PRIMARY_BOOT 0xfffffff0
+#define MAKE_CFGVAL_SECONDARY_BOOT 0xffffffff
enum boot_device {
WEIM_NOR_BOOT,
diff --git a/arch/arm/include/asm/mach-imx/sys_proto.h b/arch/arm/include/asm/mach-imx/sys_proto.h
index 2d18b1f..15d1cba 100644
--- a/arch/arm/include/asm/mach-imx/sys_proto.h
+++ b/arch/arm/include/asm/mach-imx/sys_proto.h
@@ -79,6 +79,7 @@
#ifdef CONFIG_MX6
#define IMX6_SRC_GPR10_BMODE BIT(28)
+#define IMX6_SRC_GPR10_PERSIST_SECONDARY_BOOT BIT(30)
#define IMX6_BMODE_MASK GENMASK(7, 0)
#define IMX6_BMODE_SHIFT 4
@@ -128,6 +129,7 @@
#ifdef CONFIG_MX7
#define IMX7_SRC_GPR10_BMODE BIT(28)
+#define IMX7_SRC_GPR10_PERSIST_SECONDARY_BOOT BIT(30)
#endif
/* address translation table */
diff --git a/arch/arm/mach-imx/init.c b/arch/arm/mach-imx/init.c
index e30d63b..ce3eb4b 100644
--- a/arch/arm/mach-imx/init.c
+++ b/arch/arm/mach-imx/init.c
@@ -104,20 +104,28 @@
void boot_mode_apply(unsigned cfg_val)
{
#ifdef CONFIG_MX6
+ const u32 persist_sec = IMX6_SRC_GPR10_PERSIST_SECONDARY_BOOT;
const u32 bmode = IMX6_SRC_GPR10_BMODE;
#elif CONFIG_MX7
+ const u32 persist_sec = IMX7_SRC_GPR10_PERSIST_SECONDARY_BOOT;
const u32 bmode = IMX7_SRC_GPR10_BMODE;
#endif
struct src *psrc = (struct src *)SRC_BASE_ADDR;
unsigned reg;
- writel(cfg_val, &psrc->gpr9);
- reg = readl(&psrc->gpr10);
- if (cfg_val)
- reg |= bmode;
- else
- reg &= ~bmode;
- writel(reg, &psrc->gpr10);
+ if (cfg_val == MAKE_CFGVAL_PRIMARY_BOOT)
+ clrbits_le32(&psrc->gpr10, persist_sec);
+ else if (cfg_val == MAKE_CFGVAL_SECONDARY_BOOT)
+ setbits_le32(&psrc->gpr10, persist_sec);
+ else {
+ writel(cfg_val, &psrc->gpr9);
+ reg = readl(&psrc->gpr10);
+ if (cfg_val)
+ reg |= bmode;
+ else
+ reg &= ~bmode;
+ writel(reg, &psrc->gpr10);
+ }
}
#endif
diff --git a/arch/arm/mach-imx/mx7/soc.c b/arch/arm/mach-imx/mx7/soc.c
index 979ba3e..b70ef80 100644
--- a/arch/arm/mach-imx/mx7/soc.c
+++ b/arch/arm/mach-imx/mx7/soc.c
@@ -414,6 +414,8 @@
#ifndef CONFIG_SPL_BUILD
const struct boot_mode soc_boot_modes[] = {
{"normal", MAKE_CFGVAL(0x00, 0x00, 0x00, 0x00)},
+ {"primary", MAKE_CFGVAL_PRIMARY_BOOT},
+ {"secondary", MAKE_CFGVAL_SECONDARY_BOOT},
{NULL, 0},
};
#endif