| // SPDX-License-Identifier: GPL-2.0+ |
| /* |
| * Copyright 2025 NXP |
| * |
| * Peng Fan <peng.fan@nxp.com> |
| */ |
| |
| #include <asm/arch/clock.h> |
| #include <asm/arch/ddr.h> |
| #include <asm/arch/sys_proto.h> |
| #include <asm/armv8/mmu.h> |
| #include <asm/mach-imx/boot_mode.h> |
| #include <asm/mach-imx/ele_api.h> |
| #include <asm/setup.h> |
| #include <dm/uclass.h> |
| #include <dm/device.h> |
| #include <env_internal.h> |
| #include <fuse.h> |
| #include <imx_thermal.h> |
| #include <linux/iopoll.h> |
| #include <scmi_agent.h> |
| |
| DECLARE_GLOBAL_DATA_PTR; |
| |
| static rom_passover_t rom_passover_data = {0}; |
| |
| uint32_t scmi_get_rom_data(rom_passover_t *rom_data) |
| { |
| /* Read ROM passover data */ |
| struct scmi_rom_passover_get_out out; |
| struct scmi_msg msg = { |
| .protocol_id = SCMI_PROTOCOL_ID_IMX_MISC, |
| .message_id = SCMI_MISC_ROM_PASSOVER_GET, |
| .in_msg = (u8 *)NULL, |
| .in_msg_sz = 0, |
| .out_msg = (u8 *)&out, |
| .out_msg_sz = sizeof(out), |
| }; |
| int ret; |
| struct udevice *dev; |
| |
| ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev); |
| if (ret) |
| return ret; |
| |
| ret = devm_scmi_process_msg(dev, &msg); |
| if (ret == 0 && out.status == 0) { |
| memcpy(rom_data, (struct rom_passover_t *)out.passover, sizeof(rom_passover_t)); |
| } else { |
| printf("Failed to get ROM passover data, scmi_err = %d, size_of(out) = %ld\n", |
| out.status, sizeof(out)); |
| return -EINVAL; |
| } |
| |
| return 0; |
| } |
| |
| #if IS_ENABLED(CONFIG_ENV_IS_IN_MMC) |
| __weak int board_mmc_get_env_dev(int devno) |
| { |
| return devno; |
| } |
| |
| int mmc_get_env_dev(void) |
| { |
| int ret; |
| u16 boot_type; |
| u8 boot_instance; |
| |
| volatile gd_t *pgd = gd; |
| rom_passover_t *rdata; |
| |
| #if IS_ENABLED(CONFIG_XPL_BUILD) |
| rdata = &rom_passover_data; |
| #else |
| rom_passover_t rom_data = {0}; |
| |
| if (!pgd->reloc_off) |
| rdata = &rom_data; |
| else |
| rdata = &rom_passover_data; |
| #endif |
| if (rdata->tag == 0) { |
| ret = scmi_get_rom_data(rdata); |
| if (ret != 0) { |
| puts("SCMI: failure at rom_boot_info\n"); |
| return CONFIG_SYS_MMC_ENV_DEV; |
| } |
| } |
| boot_type = rdata->boot_dev_type; |
| boot_instance = rdata->boot_dev_inst; |
| set_gd(pgd); |
| |
| debug("boot_type %d, instance %d\n", boot_type, boot_instance); |
| |
| /* If not boot from sd/mmc, use default value */ |
| if (boot_type != BOOT_TYPE_SD && boot_type != BOOT_TYPE_MMC) |
| return env_get_ulong("mmcdev", 10, CONFIG_SYS_MMC_ENV_DEV); |
| |
| return board_mmc_get_env_dev(boot_instance); |
| } |
| #endif |
| |
| u32 get_cpu_speed_grade_hz(void) |
| { |
| u32 speed, max_speed; |
| int ret; |
| u32 val, word, offset; |
| |
| word = 17; |
| offset = 14; |
| |
| ret = fuse_read(word / 8, word % 8, &val); |
| if (ret) |
| val = 0; /* If read fuse failed, return as blank fuse */ |
| |
| val >>= offset; |
| val &= 0xf; |
| |
| max_speed = 2300000000; |
| speed = max_speed - val * 100000000; |
| |
| if (is_imx95()) |
| max_speed = 2000000000; |
| |
| /* In case the fuse of speed grade not programmed */ |
| if (speed > max_speed) |
| speed = max_speed; |
| |
| return speed; |
| } |
| |
| u32 get_cpu_temp_grade(int *minc, int *maxc) |
| { |
| int ret; |
| u32 val, word, offset; |
| |
| word = 17; |
| offset = 12; |
| |
| ret = fuse_read(word / 8, word % 8, &val); |
| if (ret) |
| val = 0; /* If read fuse failed, return as blank fuse */ |
| |
| val >>= offset; |
| val &= 0x3; |
| |
| if (minc && maxc) { |
| if (val == TEMP_AUTOMOTIVE) { |
| *minc = -40; |
| *maxc = 125; |
| } else if (val == TEMP_INDUSTRIAL) { |
| *minc = -40; |
| *maxc = 105; |
| } else if (val == TEMP_EXTCOMMERCIAL) { |
| *minc = -20; |
| *maxc = 105; |
| } else { |
| *minc = 0; |
| *maxc = 95; |
| } |
| } |
| return val; |
| } |
| |
| static void set_cpu_info(struct ele_get_info_data *info) |
| { |
| gd->arch.soc_rev = info->soc; |
| gd->arch.lifecycle = info->lc; |
| memcpy((void *)&gd->arch.uid, &info->uid, 4 * sizeof(u32)); |
| } |
| |
| u32 get_cpu_rev(void) |
| { |
| u32 rev = (gd->arch.soc_rev >> 24) - 0xa0; |
| |
| return (MXC_CPU_IMX95 << 12) | (CHIP_REV_1_0 + rev); |
| } |
| |
| #define UNLOCK_WORD 0xD928C520 |
| #define REFRESH_WORD 0xB480A602 |
| |
| static void disable_wdog(void __iomem *wdog_base) |
| { |
| u32 val_cs = readl(wdog_base + 0x00); |
| int ret = 0; |
| |
| if (!(val_cs & 0x80)) |
| return; |
| |
| /* default is 32bits cmd */ |
| writel(REFRESH_WORD, (wdog_base + 0x04)); /* Refresh the CNT */ |
| |
| if (!(val_cs & 0x800)) { |
| writel(UNLOCK_WORD, (wdog_base + 0x04)); |
| while (!(readl(wdog_base + 0x00) & 0x800)) |
| ; |
| } |
| writel(0x0, (wdog_base + 0x0C)); /* Set WIN to 0 */ |
| writel(0x400, (wdog_base + 0x08)); /* Set timeout to default 0x400 */ |
| writel(0x2120, (wdog_base + 0x00)); /* Disable it and set update */ |
| |
| ret = readl_poll_timeout(wdog_base, val_cs, val_cs & 0x400, 100000); |
| if (ret < 0) |
| debug("%s timeout\n", __func__); |
| } |
| |
| static struct mm_region imx9_mem_map[] = { |
| { |
| /* M7 TCM */ |
| .virt = 0x203c0000UL, |
| .phys = 0x203c0000UL, |
| .size = 0x80000UL, |
| .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | |
| PTE_BLOCK_NON_SHARE | |
| PTE_BLOCK_PXN | PTE_BLOCK_UXN |
| }, { |
| /* OCRAM */ |
| .virt = 0x20480000UL, |
| .phys = 0x20480000UL, |
| .size = 0xA0000UL, |
| .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | |
| PTE_BLOCK_OUTER_SHARE |
| }, { |
| /* AIPS */ |
| .virt = 0x40000000UL, |
| .phys = 0x40000000UL, |
| .size = 0x40000000UL, |
| .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | |
| PTE_BLOCK_NON_SHARE | |
| PTE_BLOCK_PXN | PTE_BLOCK_UXN |
| }, { |
| /* Flexible Serial Peripheral Interface */ |
| .virt = 0x28000000UL, |
| .phys = 0x28000000UL, |
| .size = 0x8000000UL, |
| .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | |
| PTE_BLOCK_NON_SHARE | |
| PTE_BLOCK_PXN | PTE_BLOCK_UXN |
| }, { |
| /* DRAM1 */ |
| .virt = PHYS_SDRAM, |
| .phys = PHYS_SDRAM, |
| .size = PHYS_SDRAM_SIZE, |
| .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | |
| PTE_BLOCK_OUTER_SHARE |
| }, { |
| #ifdef PHYS_SDRAM_2_SIZE |
| /* DRAM2 */ |
| .virt = 0x100000000UL, |
| .phys = 0x100000000UL, |
| .size = PHYS_SDRAM_2_SIZE, |
| .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | |
| PTE_BLOCK_OUTER_SHARE |
| }, { |
| #endif |
| /* empty entry to split table entry 5 if needed when TEEs are used */ |
| 0, |
| }, { |
| /* List terminator */ |
| 0, |
| } |
| }; |
| |
| struct mm_region *mem_map = imx9_mem_map; |
| |
| static unsigned int imx9_find_dram_entry_in_mem_map(void) |
| { |
| int i; |
| |
| for (i = 0; i < ARRAY_SIZE(imx9_mem_map); i++) |
| if (imx9_mem_map[i].phys == CFG_SYS_SDRAM_BASE) |
| return i; |
| |
| hang(); /* Entry not found, this must never happen. */ |
| } |
| |
| void enable_caches(void) |
| { |
| /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch |
| * If OPTEE does not run, still update the MMU table according to dram banks structure |
| * to set correct dram size from board_phys_sdram_size |
| */ |
| int i = 0; |
| /* |
| * please make sure that entry initial value matches |
| * imx9_mem_map for DRAM1 |
| */ |
| int entry = imx9_find_dram_entry_in_mem_map(); |
| u64 attrs = imx9_mem_map[entry].attrs; |
| |
| while (i < CONFIG_NR_DRAM_BANKS && |
| entry < ARRAY_SIZE(imx9_mem_map)) { |
| if (gd->bd->bi_dram[i].start == 0) |
| break; |
| imx9_mem_map[entry].phys = gd->bd->bi_dram[i].start; |
| imx9_mem_map[entry].virt = gd->bd->bi_dram[i].start; |
| imx9_mem_map[entry].size = gd->bd->bi_dram[i].size; |
| imx9_mem_map[entry].attrs = attrs; |
| debug("Added memory mapping (%d): %llx %llx\n", entry, |
| imx9_mem_map[entry].phys, imx9_mem_map[entry].size); |
| i++; entry++; |
| } |
| |
| icache_enable(); |
| dcache_enable(); |
| } |
| |
| __weak int board_phys_sdram_size(phys_size_t *size) |
| { |
| phys_size_t start, end; |
| phys_size_t val; |
| |
| if (!size) |
| return -EINVAL; |
| |
| val = readl(REG_DDR_CS0_BNDS); |
| start = (val >> 16) << 24; |
| end = (val & 0xFFFF); |
| end = end ? end + 1 : 0; |
| end = end << 24; |
| *size = end - start; |
| |
| val = readl(REG_DDR_CS1_BNDS); |
| start = (val >> 16) << 24; |
| end = (val & 0xFFFF); |
| end = end ? end + 1 : 0; |
| end = end << 24; |
| *size += end - start; |
| |
| return 0; |
| } |
| |
| int dram_init(void) |
| { |
| phys_size_t sdram_size; |
| int ret; |
| |
| ret = board_phys_sdram_size(&sdram_size); |
| if (ret) |
| return ret; |
| |
| /* rom_pointer[1] contains the size of TEE occupies */ |
| if (rom_pointer[1] && PHYS_SDRAM < (phys_addr_t)rom_pointer[0]) |
| gd->ram_size = sdram_size - rom_pointer[1]; |
| else |
| gd->ram_size = sdram_size; |
| |
| return 0; |
| } |
| |
| int dram_init_banksize(void) |
| { |
| int bank = 0; |
| int ret; |
| phys_size_t sdram_size; |
| phys_size_t sdram_b1_size, sdram_b2_size; |
| |
| ret = board_phys_sdram_size(&sdram_size); |
| if (ret) |
| return ret; |
| |
| /* Bank 1 can't cross over 4GB space */ |
| if (sdram_size > 0x80000000) { |
| sdram_b1_size = 0x100000000UL - PHYS_SDRAM; |
| sdram_b2_size = sdram_size - sdram_b1_size; |
| } else { |
| sdram_b1_size = sdram_size; |
| sdram_b2_size = 0; |
| } |
| |
| gd->bd->bi_dram[bank].start = PHYS_SDRAM; |
| if (rom_pointer[1] && PHYS_SDRAM < (phys_addr_t)rom_pointer[0]) { |
| phys_addr_t optee_start = (phys_addr_t)rom_pointer[0]; |
| phys_size_t optee_size = (size_t)rom_pointer[1]; |
| |
| gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start; |
| if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_b1_size)) { |
| if (++bank >= CONFIG_NR_DRAM_BANKS) { |
| puts("CONFIG_NR_DRAM_BANKS is not enough\n"); |
| return -1; |
| } |
| |
| gd->bd->bi_dram[bank].start = optee_start + optee_size; |
| gd->bd->bi_dram[bank].size = PHYS_SDRAM + |
| sdram_b1_size - gd->bd->bi_dram[bank].start; |
| } |
| } else { |
| gd->bd->bi_dram[bank].size = sdram_b1_size; |
| } |
| |
| if (sdram_b2_size) { |
| if (++bank >= CONFIG_NR_DRAM_BANKS) { |
| puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n"); |
| return -1; |
| } |
| gd->bd->bi_dram[bank].start = 0x100000000UL; |
| gd->bd->bi_dram[bank].size = sdram_b2_size; |
| } |
| |
| return 0; |
| } |
| |
| phys_size_t get_effective_memsize(void) |
| { |
| int ret; |
| phys_size_t sdram_size; |
| phys_size_t sdram_b1_size; |
| |
| ret = board_phys_sdram_size(&sdram_size); |
| if (!ret) { |
| /* Bank 1 can't cross over 4GB space */ |
| if (sdram_size > 0x80000000) |
| sdram_b1_size = 0x100000000UL - PHYS_SDRAM; |
| else |
| sdram_b1_size = sdram_size; |
| |
| if (rom_pointer[1]) { |
| /* We will relocate u-boot to Top of dram1. Tee position has three cases: |
| * 1. At the top of dram1, Then return the size removed optee size. |
| * 2. In the middle of dram1, return the size of dram1. |
| * 3. Not in the scope of dram1, return the size of dram1. |
| */ |
| if ((rom_pointer[0] + rom_pointer[1]) == (PHYS_SDRAM + sdram_b1_size)) |
| return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM); |
| } |
| |
| return sdram_b1_size; |
| } else { |
| return PHYS_SDRAM_SIZE; |
| } |
| } |
| |
| void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) |
| { |
| u32 val[2] = {}; |
| int ret, num_of_macs; |
| |
| ret = fuse_read(40, 5, &val[0]); |
| if (ret) |
| goto err; |
| |
| ret = fuse_read(40, 6, &val[1]); |
| if (ret) |
| goto err; |
| |
| num_of_macs = (val[1] >> 24) & 0xff; |
| if (num_of_macs <= (dev_id * 3)) { |
| printf("WARNING: no MAC address assigned for MAC%d\n", dev_id); |
| goto err; |
| } |
| |
| mac[0] = val[0] & 0xff; |
| mac[1] = (val[0] >> 8) & 0xff; |
| mac[2] = (val[0] >> 16) & 0xff; |
| mac[3] = (val[0] >> 24) & 0xff; |
| mac[4] = val[1] & 0xff; |
| mac[5] = (val[1] >> 8) & 0xff; |
| if (dev_id == 1) |
| mac[5] = mac[5] + 3; |
| if (dev_id == 2) |
| mac[5] = mac[5] + 6; |
| |
| debug("%s: MAC%d: %pM\n", __func__, dev_id, mac); |
| return; |
| err: |
| memset(mac, 0, 6); |
| printf("%s: fuse read err: %d\n", __func__, ret); |
| } |
| |
| const char *get_imx_type(u32 imxtype) |
| { |
| switch (imxtype) { |
| case MXC_CPU_IMX95: |
| return "95";/* iMX95 FULL */ |
| default: |
| return "??"; |
| } |
| } |
| |
| void build_info(void) |
| { |
| u32 fw_version, sha1, res = 0, status; |
| int ret; |
| |
| printf("\nBuildInfo:\n"); |
| |
| ret = ele_get_fw_status(&status, &res); |
| if (ret) { |
| printf(" - ELE firmware status failed %d, 0x%x\n", ret, res); |
| } else if ((status & 0xff) == 1) { |
| ret = ele_get_fw_version(&fw_version, &sha1, &res); |
| if (ret) { |
| printf(" - ELE firmware version failed %d, 0x%x\n", ret, res); |
| } else { |
| printf(" - ELE firmware version %u.%u.%u-%x", |
| (fw_version & (0x00ff0000)) >> 16, |
| (fw_version & (0x0000fff0)) >> 4, |
| (fw_version & (0x0000000f)), sha1); |
| ((fw_version & (0x80000000)) >> 31) == 1 ? puts("-dirty\n") : puts("\n"); |
| } |
| } else { |
| printf(" - ELE firmware not included\n"); |
| } |
| puts("\n"); |
| } |
| |
| int arch_misc_init(void) |
| { |
| build_info(); |
| return 0; |
| } |
| |
| #if defined(CONFIG_OF_BOARD_FIXUP) && !defined(CONFIG_SPL_BUILD) |
| int board_fix_fdt(void *fdt) |
| { |
| return 0; |
| } |
| #endif |
| |
| int ft_system_setup(void *blob, struct bd_info *bd) |
| { |
| return 0; |
| } |
| |
| #if IS_ENABLED(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG) |
| void get_board_serial(struct tag_serialnr *serialnr) |
| { |
| printf("UID: %08x%08x%08x%08x\n", __be32_to_cpu(gd->arch.uid[0]), |
| __be32_to_cpu(gd->arch.uid[1]), __be32_to_cpu(gd->arch.uid[2]), |
| __be32_to_cpu(gd->arch.uid[3])); |
| |
| serialnr->low = __be32_to_cpu(gd->arch.uid[1]); |
| serialnr->high = __be32_to_cpu(gd->arch.uid[0]); |
| } |
| #endif |
| |
| static void gpio_reset(ulong gpio_base) |
| { |
| writel(0, gpio_base + 0x10); |
| writel(0, gpio_base + 0x14); |
| writel(0, gpio_base + 0x18); |
| writel(0, gpio_base + 0x1c); |
| } |
| |
| int arch_cpu_init(void) |
| { |
| if (IS_ENABLED(CONFIG_SPL_BUILD)) { |
| disable_wdog((void __iomem *)WDG3_BASE_ADDR); |
| disable_wdog((void __iomem *)WDG4_BASE_ADDR); |
| |
| gpio_reset(GPIO2_BASE_ADDR); |
| gpio_reset(GPIO3_BASE_ADDR); |
| gpio_reset(GPIO4_BASE_ADDR); |
| gpio_reset(GPIO5_BASE_ADDR); |
| } |
| |
| return 0; |
| } |
| |
| int imx9_probe_mu(void) |
| { |
| struct udevice *dev; |
| int ret; |
| u32 res; |
| struct ele_get_info_data info; |
| |
| ret = uclass_get_device_by_driver(UCLASS_SCMI_AGENT, DM_DRIVER_GET(scmi_mbox), &dev); |
| if (ret) |
| return ret; |
| |
| ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev); |
| if (ret) |
| return ret; |
| |
| ret = devm_scmi_of_get_channel(dev); |
| if (ret) |
| return ret; |
| |
| ret = uclass_get_device_by_name(UCLASS_PINCTRL, "protocol@19", &dev); |
| if (ret) |
| return ret; |
| |
| #if defined(CONFIG_SPL_BUILD) |
| ret = uclass_get_device_by_name(UCLASS_MISC, "mailbox@47530000", &dev); |
| #else |
| ret = uclass_get_device_by_name(UCLASS_MISC, "mailbox@47550000", &dev); |
| #endif |
| if (ret) |
| return ret; |
| |
| if (gd->flags & GD_FLG_RELOC) |
| return 0; |
| |
| ret = ele_get_info(&info, &res); |
| if (ret) |
| return ret; |
| |
| set_cpu_info(&info); |
| |
| return 0; |
| } |
| |
| EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_F, imx9_probe_mu); |
| EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_R, imx9_probe_mu); |
| |
| int timer_init(void) |
| { |
| gd->arch.tbl = 0; |
| gd->arch.tbu = 0; |
| |
| if (IS_ENABLED(CONFIG_SPL_BUILD)) { |
| unsigned long freq = 24000000; |
| |
| asm volatile("msr cntfrq_el0, %0" : : "r" (freq) : "memory"); |
| |
| /* Clear the compare frame interrupt */ |
| unsigned long sctr_cmpcr_addr = SYSCNT_CMP_BASE_ADDR + 0x2c; |
| unsigned long sctr_cmpcr = readl(sctr_cmpcr_addr); |
| |
| sctr_cmpcr &= ~0x1; |
| writel(sctr_cmpcr, sctr_cmpcr_addr); |
| } |
| |
| return 0; |
| } |
| |
| enum env_location env_get_location(enum env_operation op, int prio) |
| { |
| enum boot_device dev = get_boot_device(); |
| enum env_location env_loc = ENVL_UNKNOWN; |
| |
| if (prio) |
| return env_loc; |
| |
| switch (dev) { |
| case QSPI_BOOT: |
| env_loc = ENVL_SPI_FLASH; |
| break; |
| case SD1_BOOT: |
| case SD2_BOOT: |
| case SD3_BOOT: |
| case MMC1_BOOT: |
| case MMC2_BOOT: |
| case MMC3_BOOT: |
| env_loc = ENVL_MMC; |
| break; |
| default: |
| env_loc = ENVL_NOWHERE; |
| break; |
| } |
| |
| return env_loc; |
| } |
| |
| enum imx9_soc_voltage_mode soc_target_voltage_mode(void) |
| { |
| u32 speed = get_cpu_speed_grade_hz(); |
| enum imx9_soc_voltage_mode voltage = VOLT_OVER_DRIVE; |
| |
| if (is_imx95()) { |
| if (speed == 2000000000) |
| voltage = VOLT_SUPER_OVER_DRIVE; |
| else if (speed == 1800000000) |
| voltage = VOLT_OVER_DRIVE; |
| else if (speed == 1400000000) |
| voltage = VOLT_NOMINAL_DRIVE; |
| else /* boot not support low drive mode according to AS */ |
| printf("Unexpected A55 freq %u, default to OD\n", speed); |
| } |
| |
| return voltage; |
| } |
| |
| #if IS_ENABLED(CONFIG_SCMI_FIRMWARE) |
| enum boot_device get_boot_device(void) |
| { |
| volatile gd_t *pgd = gd; |
| int ret; |
| u16 boot_type; |
| u8 boot_instance; |
| enum boot_device boot_dev = 0; |
| rom_passover_t *rdata; |
| |
| #if IS_ENABLED(CONFIG_SPL_BUILD) |
| rdata = &rom_passover_data; |
| #else |
| rom_passover_t rom_data = {0}; |
| |
| if (pgd->reloc_off == 0) |
| rdata = &rom_data; |
| else |
| rdata = &rom_passover_data; |
| #endif |
| if (rdata->tag == 0) { |
| ret = scmi_get_rom_data(rdata); |
| if (ret != 0) { |
| puts("SCMI: failure at rom_boot_info\n"); |
| return -1; |
| } |
| } |
| boot_type = rdata->boot_dev_type; |
| boot_instance = rdata->boot_dev_inst; |
| |
| set_gd(pgd); |
| |
| switch (boot_type) { |
| case BT_DEV_TYPE_SD: |
| boot_dev = boot_instance + SD1_BOOT; |
| break; |
| case BT_DEV_TYPE_MMC: |
| boot_dev = boot_instance + MMC1_BOOT; |
| break; |
| case BT_DEV_TYPE_NAND: |
| boot_dev = NAND_BOOT; |
| break; |
| case BT_DEV_TYPE_FLEXSPINOR: |
| boot_dev = QSPI_BOOT; |
| break; |
| case BT_DEV_TYPE_USB: |
| boot_dev = boot_instance + USB_BOOT; |
| if (IS_ENABLED(CONFIG_IMX95)) |
| boot_dev -= 3; //iMX95 usb instance start at 3 |
| break; |
| default: |
| break; |
| } |
| |
| return boot_dev; |
| } |
| #endif |