@@ -20,6 +20,23 @@
#define NAND_DEV 2
#define QSPI_NOR_DEV 3
+/* 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)
+
+#if IS_ENABLED(CONFIG_IMX8QM)
+#define FUSE_IMG_SET_OFF_WORD 464
+#elif IS_ENABLED(CONFIG_IMX8QXP)
+#define FUSE_IMG_SET_OFF_WORD 720
+#endif
+
static int __get_container_size(ulong addr)
{
struct container_hdr *phdr;
@@ -122,15 +139,46 @@ static int get_container_size(void *dev, int dev_type, unsigned long offset)
return ret;
}
+static bool check_secondary_cnt_set(unsigned long *set_off)
+{
+ 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) {
+ /* 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(fuse_val);
+ return true;
+ }
+ }
+ }
+ }
+
+ 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;
+
+ 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);
@@ -140,17 +188,21 @@ 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;
}
+ debug("container set offset 0x%lx\n", offset);
+
return offset;
}
@@ -210,6 +262,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 = 0;
+
+ 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