]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
imx: iamge-container: support secondary container
authorPeng Fan <peng.fan@nxp.com>
Thu, 15 Jun 2023 10:09:17 +0000 (18:09 +0800)
committerStefano Babic <sbabic@denx.de>
Thu, 13 Jul 2023 09:29:40 +0000 (11:29 +0200)
Add the support for loading image from secondary container set on
iMX8QM B0, iMX8QXP C0.

Using the SCFW API to get container set index, if it is the secondary
boot, get the offset from fuse and apply to offset of current container
set beginning for loading.

Also override the emmc boot partition to check secondary boot and switch
to the other boot part.

This patch is modified from NXP downstream:
imx8: Fix the fuse used by secondary container offset
imx: container: Skip container set check for ROM API
imx8: spl: Support booting from secondary container set

Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
arch/arm/mach-imx/image-container.c

index 745de130630f10f6718ca0bc031bb8d7db251c5b..5f188ab32d18fc54f27a90c3dc2fb80163806307 100644 (file)
 #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