[PATCH v2 1/4] spl: mmc: Introduce proper layering for spl_mmc_get_uboot_raw_sector()

Introduce two new weak functions, arch_spl_mmc_get_uboot_raw_sector() and board_spl_mmc_get_uboot_raw_sector(), each of which can be overridden at a matching level, that is arch/ and board/ , in addition to the existing weak function spl_mmc_get_uboot_raw_sector().
This way, architecture code can define a default architecture specific implementation of arch_spl_mmc_get_uboot_raw_sector(), while the board code can override that using board_spl_mmc_get_uboot_raw_sector() which takes precedence over the architecture code. In some sort of unlikely special case where code has to take precedence over board code too, the spl_mmc_get_uboot_raw_sector() is still left out to be a weak function, but it should be unlikely that this is ever needed to be overridden.
Signed-off-by: Marek Vasut marex@denx.de --- Cc: "NXP i.MX U-Boot Team" uboot-imx@nxp.com Cc: "Ying-Chun Liu (PaulLiu)" paul.liu@linaro.org Cc: Andre Przywara andre.przywara@arm.com Cc: Chanho Park chanho61.park@samsung.com Cc: Elena Popa elena.popa@nxp.com Cc: Fabio Estevam festevam@gmail.com Cc: Fedor Ross fedor.ross@ifm.com Cc: Heinrich Schuchardt xypron.glpk@gmx.de Cc: Hugo Villeneuve hvilleneuve@dimonoff.com Cc: Jagan Teki jagan@amarulasolutions.com Cc: Kever Yang kever.yang@rock-chips.com Cc: Manoj Sai abbaraju.manojsai@amarulasolutions.com Cc: Michal Simek michal.simek@amd.com Cc: Neil Armstrong neil.armstrong@linaro.org Cc: Peng Fan peng.fan@nxp.com Cc: Qu Wenruo wqu@suse.com Cc: Roger Quadros rogerq@kernel.org Cc: Simon Glass sjg@chromium.org Cc: Stefan Roese sr@denx.de Cc: Stefano Babic sbabic@denx.de Cc: Tim Harvey tharvey@gateworks.com --- V2: New patch --- arch/arm/mach-imx/image-container.c | 4 +-- arch/arm/mach-mvebu/spl.c | 4 +-- arch/arm/mach-sunxi/board.c | 4 +-- .../imx8mp_rsb3720a1/imx8mp_rsb3720a1.c | 2 +- board/data_modul/imx8mp_edm_sbc/spl.c | 2 +- board/gateworks/venice/spl.c | 2 +- common/spl/spl_mmc.c | 14 +++++++++- include/spl.h | 26 +++++++++++++++++++ 8 files changed, 48 insertions(+), 10 deletions(-)
diff --git a/arch/arm/mach-imx/image-container.c b/arch/arm/mach-imx/image-container.c index 5f188ab32d1..0285bbdaf20 100644 --- a/arch/arm/mach-imx/image-container.c +++ b/arch/arm/mach-imx/image-container.c @@ -276,8 +276,8 @@ unsigned long spl_spi_get_uboot_offs(struct spi_flash *flash) #endif
#ifdef CONFIG_SPL_MMC -unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc, - unsigned long raw_sect) +unsigned long arch_spl_mmc_get_uboot_raw_sector(struct mmc *mmc, + unsigned long raw_sect) { int end;
diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c index 379daa88a4d..eaaa68a8564 100644 --- a/arch/arm/mach-mvebu/spl.c +++ b/arch/arm/mach-mvebu/spl.c @@ -123,8 +123,8 @@ u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device) { return IS_SD(mmc) ? MMCSD_MODE_RAW : MMCSD_MODE_EMMCBOOT; } -unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc, - unsigned long raw_sect) +unsigned long arch_spl_mmc_get_uboot_raw_sector(struct mmc *mmc, + unsigned long raw_sect) { return IS_SD(mmc) ? 1 : 0; } diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c index 78597ad932c..61a4245c499 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -323,8 +323,8 @@ uint32_t sunxi_get_spl_size(void) * Also U-Boot proper is located at least 32KB after the SPL, but will * immediately follow the SPL if that is bigger than that. */ -unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc, - unsigned long raw_sect) +unsigned long board_spl_mmc_get_uboot_raw_sector(struct mmc *mmc, + unsigned long raw_sect) { unsigned long spl_size = sunxi_get_spl_size(); unsigned long sector; diff --git a/board/advantech/imx8mp_rsb3720a1/imx8mp_rsb3720a1.c b/board/advantech/imx8mp_rsb3720a1/imx8mp_rsb3720a1.c index b79a2380aa5..d87fe3606f6 100644 --- a/board/advantech/imx8mp_rsb3720a1/imx8mp_rsb3720a1.c +++ b/board/advantech/imx8mp_rsb3720a1/imx8mp_rsb3720a1.c @@ -193,7 +193,7 @@ int board_late_init(void)
#ifdef CONFIG_SPL_MMC #define UBOOT_RAW_SECTOR_OFFSET 0x40 -unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc, +unsigned long board_spl_mmc_get_uboot_raw_sector(struct mmc *mmc, unsigned long raw_sector) { u32 boot_dev = spl_boot_device(); diff --git a/board/data_modul/imx8mp_edm_sbc/spl.c b/board/data_modul/imx8mp_edm_sbc/spl.c index 2fdd95a730c..cfc4b65e0f9 100644 --- a/board/data_modul/imx8mp_edm_sbc/spl.c +++ b/board/data_modul/imx8mp_edm_sbc/spl.c @@ -107,7 +107,7 @@ void board_boot_order(u32 *spl_boot_list) spl_boot_list[4] = BOOT_DEVICE_NONE; }
-unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc, unsigned long sect) +unsigned long board_spl_mmc_get_uboot_raw_sector(struct mmc *mmc, unsigned long sect) { const u32 boot_dev = spl_boot_device(); int part; diff --git a/board/gateworks/venice/spl.c b/board/gateworks/venice/spl.c index 774a99041c8..4851dc1c53f 100644 --- a/board/gateworks/venice/spl.c +++ b/board/gateworks/venice/spl.c @@ -346,7 +346,7 @@ int spl_board_boot_device(enum boot_device boot_dev_spl) } }
-unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc, unsigned long raw_sect) +unsigned long board_spl_mmc_get_uboot_raw_sector(struct mmc *mmc, unsigned long raw_sect) { if (!IS_SD(mmc)) { switch (EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config)) { diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 0ab85d2168c..612b11ef5b9 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -361,10 +361,22 @@ int __weak spl_mmc_boot_partition(const u32 boot_device) } #endif
+unsigned long __weak arch_spl_mmc_get_uboot_raw_sector(struct mmc *mmc, + unsigned long raw_sect) +{ + return raw_sect; +} + +unsigned long __weak board_spl_mmc_get_uboot_raw_sector(struct mmc *mmc, + unsigned long raw_sect) +{ + return arch_spl_mmc_get_uboot_raw_sector(mmc, raw_sect); +} + unsigned long __weak spl_mmc_get_uboot_raw_sector(struct mmc *mmc, unsigned long raw_sect) { - return raw_sect; + return board_spl_mmc_get_uboot_raw_sector(mmc, raw_sect); }
int default_spl_mmc_emmc_boot_partition(struct mmc *mmc) diff --git a/include/spl.h b/include/spl.h index 7d30fb57dac..7ff1518f55c 100644 --- a/include/spl.h +++ b/include/spl.h @@ -486,6 +486,32 @@ int spl_mmc_emmc_boot_partition(struct mmc *mmc);
void spl_set_bd(void);
+/** + * spl_mmc_get_uboot_raw_sector() - Provide raw sector of the start of U-Boot (architecture override) + * + * This is a weak function which by default will provide the raw sector that is + * where the start of the U-Boot image has been written to. + * + * @mmc: struct mmc that describes the devie where U-Boot resides + * @raw_sect: The raw sector number where U-Boot is by default. + * Return: The raw sector location that U-Boot resides at + */ +unsigned long arch_spl_mmc_get_uboot_raw_sector(struct mmc *mmc, + unsigned long raw_sect); + +/** + * spl_mmc_get_uboot_raw_sector() - Provide raw sector of the start of U-Boot (board override) + * + * This is a weak function which by default will provide the raw sector that is + * where the start of the U-Boot image has been written to. + * + * @mmc: struct mmc that describes the devie where U-Boot resides + * @raw_sect: The raw sector number where U-Boot is by default. + * Return: The raw sector location that U-Boot resides at + */ +unsigned long board_spl_mmc_get_uboot_raw_sector(struct mmc *mmc, + unsigned long raw_sect); + /** * spl_mmc_get_uboot_raw_sector() - Provide raw sector of the start of U-Boot *

From: Fedor Ross fedor.ross@ifm.com
Factor out parsing of ROM log in function spl_mmc_emmc_boot_partition(). This can be helpful to detect a secondary image boot without fiddling around with MMC partitions. This way for example, U-Boot is able to detect a secondary image boot and can enter some fallback scenario like starting a recovery mode.
Signed-off-by: Fedor Ross fedor.ross@ifm.com Signed-off-by: Marek Vasut marex@denx.de --- Cc: "NXP i.MX U-Boot Team" uboot-imx@nxp.com Cc: "Ying-Chun Liu (PaulLiu)" paul.liu@linaro.org Cc: Andre Przywara andre.przywara@arm.com Cc: Chanho Park chanho61.park@samsung.com Cc: Elena Popa elena.popa@nxp.com Cc: Fabio Estevam festevam@gmail.com Cc: Fedor Ross fedor.ross@ifm.com Cc: Heinrich Schuchardt xypron.glpk@gmx.de Cc: Hugo Villeneuve hvilleneuve@dimonoff.com Cc: Jagan Teki jagan@amarulasolutions.com Cc: Kever Yang kever.yang@rock-chips.com Cc: Manoj Sai abbaraju.manojsai@amarulasolutions.com Cc: Michal Simek michal.simek@amd.com Cc: Neil Armstrong neil.armstrong@linaro.org Cc: Peng Fan peng.fan@nxp.com Cc: Qu Wenruo wqu@suse.com Cc: Roger Quadros rogerq@kernel.org Cc: Simon Glass sjg@chromium.org Cc: Stefan Roese sr@denx.de Cc: Stefano Babic sbabic@denx.de Cc: Tim Harvey tharvey@gateworks.com --- V2: No change --- arch/arm/mach-imx/imx8m/soc.c | 55 +++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 18 deletions(-)
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index fc829588ce8..930ee5f59f9 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -648,19 +648,17 @@ struct rom_api *g_rom_api = (struct rom_api *)0x980;
#if defined(CONFIG_IMX8M) #include <spl.h> -int spl_mmc_emmc_boot_partition(struct mmc *mmc) +int imx8m_detect_secondary_image_boot(void) { u32 *rom_log_addr = (u32 *)0x9e0; u32 *rom_log; u8 event_id; - int i, part; - - part = default_spl_mmc_emmc_boot_partition(mmc); + int i, boot_secondary = 0;
/* If the ROM event log pointer is not valid. */ if (*rom_log_addr < 0x900000 || *rom_log_addr >= 0xb00000 || *rom_log_addr & 0x3) - return part; + return -EINVAL;
/* Parse the ROM event ID version 2 log */ rom_log = (u32 *)(uintptr_t)(*rom_log_addr); @@ -668,7 +666,7 @@ int spl_mmc_emmc_boot_partition(struct mmc *mmc) event_id = rom_log[i] >> 24; switch (event_id) { case 0x00: /* End of list */ - return part; + return boot_secondary; /* Log entries with 1 parameter, skip 1 */ case 0x80: /* Start to perform the device initialization */ case 0x81: /* The boot device initialization completes */ @@ -686,24 +684,45 @@ int spl_mmc_emmc_boot_partition(struct mmc *mmc) continue; /* Boot from the secondary boot image */ case 0x51: - /* - * Swap the eMMC boot partitions in case there was a - * fallback event (i.e. primary image was corrupted - * and that corruption was recognized by the BootROM), - * so the SPL loads the rest of the U-Boot from the - * correct eMMC boot partition, since the BootROM - * leaves the boot partition set to the corrupted one. - */ - if (part == 1) - part = 2; - else if (part == 2) - part = 1; + boot_secondary = 1; continue; default: continue; } }
+ return boot_secondary; +} + +int spl_mmc_emmc_boot_partition(struct mmc *mmc) +{ + int part, ret; + + part = default_spl_mmc_emmc_boot_partition(mmc); + if (part == 0) + return part; + + ret = imx8m_detect_secondary_image_boot(); + if (ret < 0) { + printf("Could not get boot partition! Using %d\n", part); + return part; + } + + if (ret == 1) { + /* + * Swap the eMMC boot partitions in case there was a + * fallback event (i.e. primary image was corrupted + * and that corruption was recognized by the BootROM), + * so the SPL loads the rest of the U-Boot from the + * correct eMMC boot partition, since the BootROM + * leaves the boot partition set to the corrupted one. + */ + if (part == 1) + part = 2; + else if (part == 2) + part = 1; + } + return part; } #endif

From: Fedor Ross fedor.ross@ifm.com
In case of a secondary image boot from the user area of an eMMC device, the correct offset must be calculated. The offset is fused in the fuse IMG_CNTN_SET1_OFFSET of the i.MX8M Nano and Plus. The calculation of the offset is described in the reference manual (IMX8MNRM Rev. 2, 07/2022 and IMX8MPRM Rev. 1, 06/2021):
The fuse IMG_CNTN_SET1_OFFSET (0x490[22:19]) is defined as follows: * Secondary boot is disabled if fuse value is bigger than 10, n = fuse value bigger than 10. * n == 0: Offset = 4MB * n == 2: Offset = 1MB * Others & n <= 10 : Offset = 1MB*2^n
Signed-off-by: Fedor Ross fedor.ross@ifm.com Signed-off-by: Marek Vasut marex@denx.de --- Cc: "NXP i.MX U-Boot Team" uboot-imx@nxp.com Cc: "Ying-Chun Liu (PaulLiu)" paul.liu@linaro.org Cc: Andre Przywara andre.przywara@arm.com Cc: Chanho Park chanho61.park@samsung.com Cc: Elena Popa elena.popa@nxp.com Cc: Fabio Estevam festevam@gmail.com Cc: Fedor Ross fedor.ross@ifm.com Cc: Heinrich Schuchardt xypron.glpk@gmx.de Cc: Hugo Villeneuve hvilleneuve@dimonoff.com Cc: Jagan Teki jagan@amarulasolutions.com Cc: Kever Yang kever.yang@rock-chips.com Cc: Manoj Sai abbaraju.manojsai@amarulasolutions.com Cc: Michal Simek michal.simek@amd.com Cc: Neil Armstrong neil.armstrong@linaro.org Cc: Peng Fan peng.fan@nxp.com Cc: Qu Wenruo wqu@suse.com Cc: Roger Quadros rogerq@kernel.org Cc: Simon Glass sjg@chromium.org Cc: Stefan Roese sr@denx.de Cc: Stefano Babic sbabic@denx.de Cc: Tim Harvey tharvey@gateworks.com --- V2: Use arch_spl_mmc_get_uboot_raw_sector() --- arch/arm/mach-imx/imx8m/soc.c | 39 +++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index 930ee5f59f9..d33ac06cab4 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -28,8 +28,10 @@ #include <errno.h> #include <fdt_support.h> #include <fsl_wdog.h> +#include <fuse.h> #include <imx_sip.h> #include <linux/bitops.h> +#include <linux/bitfield.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -727,6 +729,43 @@ int spl_mmc_emmc_boot_partition(struct mmc *mmc) } #endif
+#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP) +#define IMG_CNTN_SET1_OFFSET GENMASK(22, 19) +unsigned long arch_spl_mmc_get_uboot_raw_sector(struct mmc *mmc, + unsigned long raw_sect) +{ + u32 val, offset; + + if (fuse_read(2, 1, &val)) { + debug("Error reading fuse!\n"); + return raw_sect; + } + + val = FIELD_GET(IMG_CNTN_SET1_OFFSET, val); + if (val > 10) { + debug("Secondary image boot disabled!\n"); + return raw_sect; + } + + if (val == 0) + offset = SZ_4M; + else if (val == 1) + offset = SZ_2M; + else if (val == 2) + offset = SZ_1M; + else /* flash.bin offset = 1 MiB * 2^n */ + offset = SZ_1M << val; + + offset /= 512; + offset -= CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET; + + if (imx8m_detect_secondary_image_boot()) + raw_sect += offset; + + return raw_sect; +} +#endif + bool is_usb_boot(void) { return get_boot_device() == USB_BOOT;

From: Fedor Ross fedor.ross@ifm.com
Implement the 'getprisec' subcommand of 'bmode' command for i.MX8M by reading out the ROM log events. This event is set by the BootROM if it switched to the secondary copy due to primary copy being corrupted.
Signed-off-by: Fedor Ross fedor.ross@ifm.com Signed-off-by: Marek Vasut marex@denx.de --- Cc: "NXP i.MX U-Boot Team" uboot-imx@nxp.com Cc: "Ying-Chun Liu (PaulLiu)" paul.liu@linaro.org Cc: Andre Przywara andre.przywara@arm.com Cc: Chanho Park chanho61.park@samsung.com Cc: Elena Popa elena.popa@nxp.com Cc: Fabio Estevam festevam@gmail.com Cc: Fedor Ross fedor.ross@ifm.com Cc: Heinrich Schuchardt xypron.glpk@gmx.de Cc: Hugo Villeneuve hvilleneuve@dimonoff.com Cc: Jagan Teki jagan@amarulasolutions.com Cc: Kever Yang kever.yang@rock-chips.com Cc: Manoj Sai abbaraju.manojsai@amarulasolutions.com Cc: Michal Simek michal.simek@amd.com Cc: Neil Armstrong neil.armstrong@linaro.org Cc: Peng Fan peng.fan@nxp.com Cc: Qu Wenruo wqu@suse.com Cc: Roger Quadros rogerq@kernel.org Cc: Simon Glass sjg@chromium.org Cc: Stefan Roese sr@denx.de Cc: Stefano Babic sbabic@denx.de Cc: Tim Harvey tharvey@gateworks.com --- V2: Mask out boot_mode_apply() on MX8M and newer, since this functionality is not available. --- arch/arm/mach-imx/Kconfig | 2 +- arch/arm/mach-imx/cmd_bmode.c | 4 ++++ arch/arm/mach-imx/imx8m/soc.c | 5 +++++ 3 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 266bb20df9d..44e1e1628ba 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -71,7 +71,7 @@ config CSF_SIZE config CMD_BMODE bool "Support the 'bmode' command" default y - depends on ARCH_MX7 || ARCH_MX6 || ARCH_MX5 + depends on ARCH_IMX8M || ARCH_MX7 || ARCH_MX6 || ARCH_MX5 help This enables the 'bmode' (bootmode) command for forcing a boot from specific media. diff --git a/arch/arm/mach-imx/cmd_bmode.c b/arch/arm/mach-imx/cmd_bmode.c index cb317499d54..5b2f4686230 100644 --- a/arch/arm/mach-imx/cmd_bmode.c +++ b/arch/arm/mach-imx/cmd_bmode.c @@ -83,7 +83,11 @@ static int do_boot_mode(struct cmd_tbl *cmdtp, int flag, int argc, reset_requested = 0; }
+/* No longer applicable to i.MX8M */ +#if IS_ENABLED(CONFIG_MX53) || IS_ENABLED(CONFIG_MX6) || IS_ENABLED(CONFIG_MX7) boot_mode_apply(p->cfg_val); +#endif + if (reset_requested && p->cfg_val) do_reset(NULL, 0, 0, NULL); return 0; diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index d33ac06cab4..556611a04e7 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -727,6 +727,11 @@ int spl_mmc_emmc_boot_partition(struct mmc *mmc)
return part; } + +int boot_mode_getprisec(void) +{ + return !!imx8m_detect_secondary_image_boot(); +} #endif
#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
participants (1)
-
Marek Vasut