diff --git a/arch/arm/mach-imx/image-container.c b/arch/arm/mach-imx/image-container.c index 745de13063..5f188ab32d 100644 --- a/arch/arm/mach-imx/image-container.c +++ b/arch/arm/mach-imx/image-container.c @@ -22,6 +22,25 @@ #define QSPI_NOR_DEV 3 #define ROM_API_DEV 4 +/* The unit of second image offset number which provision by the fuse bits */ +#define SND_IMG_OFF_UNIT (0x100000UL) + +/* + * If num = 0, off = (2 ^ 2) * 1MB + * else If num = 2, off = (2 ^ 0) * 1MB + * else off = (2 ^ num) * 1MB + */ +#define SND_IMG_NUM_TO_OFF(num) \ + ((1UL << ((0 == (num)) ? 2 : (2 == (num)) ? 0 : (num))) * SND_IMG_OFF_UNIT) + +#define GET_SND_IMG_NUM(fuse) (((fuse) >> 24) & 0x1F) + +#if defined(CONFIG_IMX8QM) +#define FUSE_IMG_SET_OFF_WORD 464 +#elif defined(CONFIG_IMX8QXP) +#define FUSE_IMG_SET_OFF_WORD 720 +#endif + int get_container_size(ulong addr, u16 *header_length) { struct container_hdr *phdr; @@ -136,15 +155,53 @@ static int get_dev_container_size(void *dev, int dev_type, unsigned long offset, return ret; } +static bool check_secondary_cnt_set(unsigned long *set_off) +{ +#if IS_ENABLED(CONFIG_ARCH_IMX8) + int ret; + u8 set_id = 1; + u32 fuse_val = 0; + + if (!(is_imx8qxp() && is_soc_rev(CHIP_REV_B))) { + ret = sc_misc_get_boot_container(-1, &set_id); + if (ret) + return false; + /* Secondary boot */ + if (set_id == 2) { + ret = sc_misc_otp_fuse_read(-1, FUSE_IMG_SET_OFF_WORD, &fuse_val); + if (!ret) { + if (set_off) + *set_off = SND_IMG_NUM_TO_OFF(GET_SND_IMG_NUM(fuse_val)); + return true; + } + } + } +#endif + + return false; +} + static unsigned long get_boot_device_offset(void *dev, int dev_type) { - unsigned long offset = 0; + unsigned long offset = 0, sec_set_off = 0; + bool sec_boot = false; + + if (dev_type == ROM_API_DEV) { + offset = (unsigned long)dev; + return offset; + } + + sec_boot = check_secondary_cnt_set(&sec_set_off); + if (sec_boot) + printf("Secondary set selected\n"); + else + printf("Primary set selected\n"); if (dev_type == MMC_DEV) { struct mmc *mmc = (struct mmc *)dev; if (IS_SD(mmc) || mmc->part_config == MMCPART_NOAVAILABLE) { - offset = CONTAINER_HDR_MMCSD_OFFSET; + offset = sec_boot ? sec_set_off : CONTAINER_HDR_MMCSD_OFFSET; } else { u8 part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config); @@ -154,19 +211,23 @@ static unsigned long get_boot_device_offset(void *dev, int dev_type) else offset = CONTAINER_HDR_EMMC_OFFSET; } else { - offset = CONTAINER_HDR_MMCSD_OFFSET; + offset = sec_boot ? sec_set_off : CONTAINER_HDR_MMCSD_OFFSET; } } } else if (dev_type == QSPI_DEV) { - offset = CONTAINER_HDR_QSPI_OFFSET; + offset = sec_boot ? (sec_set_off + CONTAINER_HDR_QSPI_OFFSET) : + CONTAINER_HDR_QSPI_OFFSET; } else if (dev_type == NAND_DEV) { - offset = CONTAINER_HDR_NAND_OFFSET; + offset = sec_boot ? (sec_set_off + CONTAINER_HDR_NAND_OFFSET) : + CONTAINER_HDR_NAND_OFFSET; } else if (dev_type == QSPI_NOR_DEV) { offset = CONTAINER_HDR_QSPI_OFFSET + 0x08000000; - } else if (dev_type == ROM_API_DEV) { - offset = (unsigned long)dev; + } else { + printf("Not supported dev_type: %d\n", dev_type); } + debug("container set offset 0x%lx\n", offset); + return offset; } @@ -227,6 +288,25 @@ unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc, return end / mmc->read_bl_len; } + +int spl_mmc_emmc_boot_partition(struct mmc *mmc) +{ + int part; + + part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config); + if (part == 1 || part == 2) { + unsigned long sec_set_off = 0; + bool sec_boot = false; + + sec_boot = check_secondary_cnt_set(&sec_set_off); + if (sec_boot) + part = (part == 1) ? 2 : 1; + } else if (part == 7) { + part = 0; + } + + return part; +} #endif #ifdef CONFIG_SPL_NAND_SUPPORT