mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-08-16 04:07:00 +02:00
When SPL loading image to secure region, for example, ATF and tee to DDR secure region. Because the USDHC controller is non-secure master, it can't access this region and will cause loading issue. So use a trampoline buffer in non-secure region, then use CPU to copy the image from trampoline buffer to destination secure region. Signed-off-by: Ye Li <ye.li@nxp.com> Signed-off-by: Alice Guo <alice.guo@nxp.com> Reviewed-by: Peng Fan <peng.fan@nxp.com>
750 lines
16 KiB
C
750 lines
16 KiB
C
// 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
|
|
|
|
bool arch_check_dst_in_secure(void *start, ulong size)
|
|
{
|
|
ulong ns_end = CFG_SYS_SDRAM_BASE + PHYS_SDRAM_SIZE;
|
|
#ifdef PHYS_SDRAM_2_SIZE
|
|
ns_end += PHYS_SDRAM_2_SIZE;
|
|
#endif
|
|
|
|
if ((ulong)start < CFG_SYS_SDRAM_BASE || (ulong)start + size > ns_end)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
void *arch_get_container_trampoline(void)
|
|
{
|
|
return (void *)((ulong)CFG_SYS_SDRAM_BASE + PHYS_SDRAM_SIZE - SZ_16M);
|
|
}
|