diff mbox series

[2/4] ARM: imx: Add support for switching primary/secondary boot mode to bmode

Message ID 20200805133407.101338-2-marex@denx.de
State Accepted
Commit 5ec83561c42cddd0f78a1e183b937f44902a18e4
Delegated to: Stefano Babic
Headers show
Series [1/4] ARM: imx: Add bmode support for iMX7 | expand

Commit Message

Marek Vasut Aug. 5, 2020, 1:34 p.m. UTC
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>
---
 arch/arm/include/asm/mach-imx/boot_mode.h |  2 ++
 arch/arm/include/asm/mach-imx/sys_proto.h |  2 ++
 arch/arm/mach-imx/init.c                  | 22 +++++++++++++++-------
 arch/arm/mach-imx/mx7/soc.c               |  2 ++
 4 files changed, 21 insertions(+), 7 deletions(-)

Comments

Stefano Babic Aug. 5, 2020, 2 p.m. UTC | #1
On 05.08.20 15:34, Marek Vasut wrote:
> 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>
> ---
>  arch/arm/include/asm/mach-imx/boot_mode.h |  2 ++
>  arch/arm/include/asm/mach-imx/sys_proto.h |  2 ++
>  arch/arm/mach-imx/init.c                  | 22 +++++++++++++++-------
>  arch/arm/mach-imx/mx7/soc.c               |  2 ++
>  4 files changed, 21 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/include/asm/mach-imx/boot_mode.h b/arch/arm/include/asm/mach-imx/boot_mode.h
> index 3a483b6afa..6dc5855968 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 2d18b1f56b..15d1cba8e7 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 @@ struct bd_info;
>  
>  #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 @@ void gpr_init(void);
>  
>  #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 e30d63b896..ce3eb4b0b8 100644
> --- a/arch/arm/mach-imx/init.c
> +++ b/arch/arm/mach-imx/init.c
> @@ -104,20 +104,28 @@ void init_src(void)
>  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 2698ae623e..b6fd25a991 100644
> --- a/arch/arm/mach-imx/mx7/soc.c
> +++ b/arch/arm/mach-imx/mx7/soc.c
> @@ -415,6 +415,8 @@ void s_init(void)
>  #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
> 

Reviewed-by: Stefano Babic <sbabic@denx.de>

Regards,
Stefano
Stefano Babic Aug. 18, 2020, 12:33 p.m. UTC | #2
> 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>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic
diff mbox series

Patch

diff --git a/arch/arm/include/asm/mach-imx/boot_mode.h b/arch/arm/include/asm/mach-imx/boot_mode.h
index 3a483b6afa..6dc5855968 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 2d18b1f56b..15d1cba8e7 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 @@  struct bd_info;
 
 #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 @@  void gpr_init(void);
 
 #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 e30d63b896..ce3eb4b0b8 100644
--- a/arch/arm/mach-imx/init.c
+++ b/arch/arm/mach-imx/init.c
@@ -104,20 +104,28 @@  void init_src(void)
 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 2698ae623e..b6fd25a991 100644
--- a/arch/arm/mach-imx/mx7/soc.c
+++ b/arch/arm/mach-imx/mx7/soc.c
@@ -415,6 +415,8 @@  void s_init(void)
 #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