aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-imx
diff options
context:
space:
mode:
authorPeng Fan2023-06-15 18:09:17 +0800
committerStefano Babic2023-07-13 11:29:40 +0200
commit455ebf8f455d4bd78237884aaf948c54fb6639b6 (patch)
tree62d45d1cd010fca6685daeef86de99bd485e828b /arch/arm/mach-imx
parent3b5c1d0ea100933d3fadda82051ede62b5209c89 (diff)
imx: iamge-container: support secondary container
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>
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r--arch/arm/mach-imx/image-container.c94
1 files changed, 87 insertions, 7 deletions
diff --git a/arch/arm/mach-imx/image-container.c b/arch/arm/mach-imx/image-container.c
index 745de130630..5f188ab32d1 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