From: Frieder Schrempf <[email protected]> The i.MX6 allows to boot from a SPI NOR as a fallback if the primary boot fails. Parse the ROM log in order to detect this and return the proper boot device in spl_boot_device(). Otherwise the primary boot device is returned even if it was not used.
To make imx6_is_ecspi_recovery_boot() usable in U-Boot proper, add them in arch/arm/mach-imx/init.c. This was tested on i.MX6S and the implementation covers other i.MX6 variants based on the documentation from NXP (AN12853). Assisted-by: Claude:claude-opus-5 Signed-off-by: Frieder Schrempf <[email protected]> --- arch/arm/include/asm/mach-imx/sys_proto.h | 1 + arch/arm/mach-imx/init.c | 75 +++++++++++++++++++++++ arch/arm/mach-imx/spl.c | 7 +++ 3 files changed, 83 insertions(+) diff --git a/arch/arm/include/asm/mach-imx/sys_proto.h b/arch/arm/include/asm/mach-imx/sys_proto.h index d25c08f8fe7..06b5636c7a0 100644 --- a/arch/arm/include/asm/mach-imx/sys_proto.h +++ b/arch/arm/include/asm/mach-imx/sys_proto.h @@ -159,6 +159,7 @@ enum imx6_bmode { }; u32 imx6_src_get_boot_mode(void); +bool imx6_is_ecspi_recovery_boot(void); void gpr_init(void); #endif /* CONFIG_MX6 */ diff --git a/arch/arm/mach-imx/init.c b/arch/arm/mach-imx/init.c index ce3eb4b0b8a..4193b350e03 100644 --- a/arch/arm/mach-imx/init.c +++ b/arch/arm/mach-imx/init.c @@ -137,4 +137,79 @@ u32 imx6_src_get_boot_mode(void) else return readl(&src_base->sbmr1); } + +/* + * The boot ROM records what it did in an event log buffer in OCRAM. The + * address of that buffer is stored at a fixed, SoC specific location inside + * the ROM, see AN12853 "i.MX ROMs Log Events". i.MX6 uses the version 0 log + * format, where an entry consists of a 32-bit word holding a 24-bit event + * ID, optionally followed by up to three parameter words. + */ +#define IMX6_ROM_LOG_ID_MASK GENMASK(23, 0) +#define IMX6_ROM_LOG_MAX_ENTRIES 128 + +static const u32 *imx6_get_rom_log(void) +{ + uintptr_t log; + ulong addr; + + if (is_mx6dq() || is_mx6dqp() || is_mx6sl()) + addr = 0xd4; + else if (is_mx6sdl()) + addr = 0xd8; + else if (is_mx6sx() || is_mx6sll() || is_mx6ul() || is_mx6ull()) + addr = 0x1e0; + else + return NULL; + + log = readl(addr); + + /* The log buffer lives in OCRAM, ignore an invalid pointer */ + if (log < IRAM_BASE_ADDR || log >= IRAM_BASE_ADDR + IRAM_SIZE || + log & 0x3) + return NULL; + + return (const u32 *)log; +} + +/* + * If BOOT_CFG4[6] is fused, the boot ROM does not fall back to the serial + * downloader right away when the primary boot device fails, but first tries + * a recovery boot from the serial ROM selected by BOOT_CFG4[2:0]. Neither + * SRC_SBMR1 nor SRC_SBMR2 reflect that this happened, so ask the ROM event + * log instead. + */ +bool imx6_is_ecspi_recovery_boot(void) +{ + const u32 *log = imx6_get_rom_log(); + u32 event_id; + int i; + + if (!log) + return false; + + for (i = 0; i < IMX6_ROM_LOG_MAX_ENTRIES; i++) { + event_id = log[i] & IMX6_ROM_LOG_ID_MASK; + + switch (event_id) { + case 0x000000: /* End of list */ + return false; + /* Recovery boot from ECSPI NOR device */ + case 0x061004: + return true; + /* Log entries with 1 parameter, skip 1 */ + case 0x080000: /* Start to read data from boot device */ + case 0x090000: /* Image authentication result */ + case 0x0a0000: /* Start to execute the plugin program */ + case 0x0b0000: /* Jump to the boot image soon */ + case 0x0d0000: /* Jump to the SDP boot image soon */ + i += 1; + continue; + default: + continue; + } + } + + return false; +} #endif diff --git a/arch/arm/mach-imx/spl.c b/arch/arm/mach-imx/spl.c index 1029c1e4e85..fbe5172d385 100644 --- a/arch/arm/mach-imx/spl.c +++ b/arch/arm/mach-imx/spl.c @@ -93,6 +93,13 @@ u32 spl_boot_device(void) if (is_usbotg_phy_active()) return BOOT_DEVICE_BOARD; + /* + * Likewise the boot ROM may have done a recovery boot from a serial + * ROM on ECSPI after the primary boot device failed. + */ + if (imx6_is_ecspi_recovery_boot()) + return BOOT_DEVICE_SPI; + /* BOOT_CFG1[7:4] - see IMX6DQRM Table 8-8 */ switch ((reg & IMX6_BMODE_MASK) >> IMX6_BMODE_SHIFT) { /* EIM: See 8.5.1, Table 8-9 */ -- 2.55.0
