diff options
Diffstat (limited to 'plat/imx/imx93')
-rw-r--r-- | plat/imx/imx93/aarch64/plat_helpers.S | 74 | ||||
-rw-r--r-- | plat/imx/imx93/imx93_bl31_setup.c | 160 | ||||
-rw-r--r-- | plat/imx/imx93/imx93_psci.c | 253 | ||||
-rw-r--r-- | plat/imx/imx93/include/platform_def.h | 97 | ||||
-rw-r--r-- | plat/imx/imx93/include/pwr_ctrl.h | 216 | ||||
-rw-r--r-- | plat/imx/imx93/plat_topology.c | 39 | ||||
-rw-r--r-- | plat/imx/imx93/platform.mk | 46 | ||||
-rw-r--r-- | plat/imx/imx93/pwr_ctrl.c | 63 | ||||
-rw-r--r-- | plat/imx/imx93/trdc.c | 68 | ||||
-rw-r--r-- | plat/imx/imx93/trdc_config.h | 254 |
10 files changed, 1270 insertions, 0 deletions
diff --git a/plat/imx/imx93/aarch64/plat_helpers.S b/plat/imx/imx93/aarch64/plat_helpers.S new file mode 100644 index 0000000..9987a53 --- /dev/null +++ b/plat/imx/imx93/aarch64/plat_helpers.S @@ -0,0 +1,74 @@ +/* + * Copyright 2022-2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <asm_macros.S> +#include <cortex_a55.h> + +#include <platform_def.h> + + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_calc_core_pos + .globl platform_mem_init + + /* ------------------------------------------------------ + * Helper macro that reads the part number of the current + * CPU and jumps to the given label if it matches the CPU + * MIDR provided. + * + * Clobbers x0. + * ------------------------------------------------------ + */ + .macro jump_if_cpu_midr _cpu_midr, _label + + mrs x0, midr_el1 + ubfx x0, x0, MIDR_PN_SHIFT, #12 + cmp w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK) + b.eq \_label + + .endm + + /* ---------------------------------------------- + * unsigned int plat_is_my_cpu_primary(void); + * This function checks if this is the primary CPU + * ---------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + mov_imm x1, MPIDR_AFFINITY_MASK + and x0, x0, x1 + cmp x0, #PLAT_PRIMARY_CPU + cset x0, eq + ret +endfunc plat_is_my_cpu_primary + + /* ---------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses the plat_calc_core_pos() + * to get the index of the calling CPU. + * ---------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + mov x1, #MPIDR_AFFLVL_MASK + and x0, x1, x0, lsr #MPIDR_AFF1_SHIFT + ret +endfunc plat_my_core_pos + + /* + * unsigned int plat_calc_core_pos(uint64_t mpidr) + * helper function to calculate the core position. + * With this function. + */ +func plat_calc_core_pos + mov x1, #MPIDR_AFFLVL_MASK + and x0, x1, x0, lsr #MPIDR_AFF1_SHIFT + ret +endfunc plat_calc_core_pos + +func platform_mem_init + ret +endfunc platform_mem_init diff --git a/plat/imx/imx93/imx93_bl31_setup.c b/plat/imx/imx93/imx93_bl31_setup.c new file mode 100644 index 0000000..8458f6c --- /dev/null +++ b/plat/imx/imx93/imx93_bl31_setup.c @@ -0,0 +1,160 @@ +/* + * Copyright 2022-2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stdbool.h> + +#include <arch_helpers.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <context.h> +#include <drivers/console.h> +#include <drivers/generic_delay_timer.h> +#include <drivers/nxp/trdc/imx_trdc.h> +#include <lib/el3_runtime/context_mgmt.h> +#include <lib/mmio.h> +#include <lib/xlat_tables/xlat_tables_v2.h> +#include <plat/common/platform.h> + +#include <imx8_lpuart.h> +#include <plat_imx8.h> +#include <platform_def.h> + +#define MAP_BL31_TOTAL \ + MAP_REGION_FLAT(BL31_BASE, BL31_LIMIT - BL31_BASE, MT_MEMORY | MT_RW | MT_SECURE) +#define MAP_BL31_RO \ + MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE, MT_MEMORY | MT_RO | MT_SECURE) + +static const mmap_region_t imx_mmap[] = { + AIPS1_MAP, AIPS2_MAP, AIPS4_MAP, GIC_MAP, + TRDC_A_MAP, TRDC_W_MAP, TRDC_M_MAP, + TRDC_N_MAP, + {0}, +}; + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/* get SPSR for BL33 entry */ +static uint32_t get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned long mode; + uint32_t spsr; + + /* figure out what mode we enter the non-secure world */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_t console; + + console_lpuart_register(IMX_LPUART_BASE, IMX_BOOT_UART_CLK_IN_HZ, + IMX_CONSOLE_BAUDRATE, &console); + + /* This console is only used for boot stage */ + console_set_scope(&console, CONSOLE_FLAG_BOOT); + + /* + * tell BL3-1 where the non-secure software image is located + * and the entry state information. + */ + bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET; + bl33_image_ep_info.spsr = get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + +#if defined(SPD_opteed) + /* Populate entry point information for BL32 */ + SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = 0; + + /* Pass TEE base and size to bl33 */ + bl33_image_ep_info.args.arg1 = BL32_BASE; + bl33_image_ep_info.args.arg2 = BL32_SIZE; + + /* Make sure memory is clean */ + mmio_write_32(BL32_FDT_OVERLAY_ADDR, 0); + bl33_image_ep_info.args.arg3 = BL32_FDT_OVERLAY_ADDR; + bl32_image_ep_info.args.arg3 = BL32_FDT_OVERLAY_ADDR; +#endif +} + +void bl31_plat_arch_setup(void) +{ + /* no coherence memory support on i.MX9 */ + const mmap_region_t bl_regions[] = { + MAP_BL31_TOTAL, + MAP_BL31_RO, + }; + + /* Assign all the GPIO pins to non-secure world by default */ + mmio_write_32(GPIO2_BASE + 0x10, 0xffffffff); + mmio_write_32(GPIO2_BASE + 0x14, 0x3); + mmio_write_32(GPIO2_BASE + 0x18, 0xffffffff); + mmio_write_32(GPIO2_BASE + 0x1c, 0x3); + + mmio_write_32(GPIO3_BASE + 0x10, 0xffffffff); + mmio_write_32(GPIO3_BASE + 0x14, 0x3); + mmio_write_32(GPIO3_BASE + 0x18, 0xffffffff); + mmio_write_32(GPIO3_BASE + 0x1c, 0x3); + + mmio_write_32(GPIO4_BASE + 0x10, 0xffffffff); + mmio_write_32(GPIO4_BASE + 0x14, 0x3); + mmio_write_32(GPIO4_BASE + 0x18, 0xffffffff); + mmio_write_32(GPIO4_BASE + 0x1c, 0x3); + + mmio_write_32(GPIO1_BASE + 0x10, 0xffffffff); + mmio_write_32(GPIO1_BASE + 0x14, 0x3); + mmio_write_32(GPIO1_BASE + 0x18, 0xffffffff); + mmio_write_32(GPIO1_BASE + 0x1c, 0x3); + + setup_page_tables(bl_regions, imx_mmap); + enable_mmu_el3(0); + + /* trdc must be initialized */ + trdc_config(); +} + +void bl31_platform_setup(void) +{ + generic_delay_timer_init(); + + plat_gic_driver_init(); + plat_gic_init(); +} + +void bl31_plat_runtime_setup(void) +{ + console_switch_state(CONSOLE_FLAG_RUNTIME); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type) +{ + if (type == NON_SECURE) { + return &bl33_image_ep_info; + } + + if (type == SECURE) { + return &bl32_image_ep_info; + } + + return NULL; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return COUNTER_FREQUENCY; +} diff --git a/plat/imx/imx93/imx93_psci.c b/plat/imx/imx93/imx93_psci.c new file mode 100644 index 0000000..5e1fa95 --- /dev/null +++ b/plat/imx/imx93/imx93_psci.c @@ -0,0 +1,253 @@ +/* + * Copyright 2022-2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdbool.h> + +#include <arch.h> +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/delay_timer.h> +#include <lib/mmio.h> +#include <lib/psci/psci.h> + +#include <plat_imx8.h> +#include <pwr_ctrl.h> + +#define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0]) +#define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1]) +#define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) + +/* platform secure warm boot entry */ +static uintptr_t secure_entrypoint; + +static bool boot_stage = true; + +int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint) +{ + /* The non-secure entrypoint should be in RAM space */ + if (ns_entrypoint < PLAT_NS_IMAGE_OFFSET) { + return PSCI_E_INVALID_PARAMS; + } + + return PSCI_E_SUCCESS; +} + +int imx_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + int pwr_type = psci_get_pstate_type(power_state); + int state_id = psci_get_pstate_id(power_state); + + if (pwr_lvl > PLAT_MAX_PWR_LVL) { + return PSCI_E_INVALID_PARAMS; + } + + if (pwr_type == PSTATE_TYPE_STANDBY) { + CORE_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; + CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; + } + + if (pwr_type == PSTATE_TYPE_POWERDOWN && state_id == 0x33) { + CORE_PWR_STATE(req_state) = PLAT_MAX_OFF_STATE; + CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; + } + + return PSCI_E_SUCCESS; +} + +void imx_set_cpu_boot_entry(unsigned int core_id, uint64_t boot_entry) +{ + /* set the cpu core reset entry: BLK_CTRL_S */ + mmio_write_32(BLK_CTRL_S_BASE + CA55_RVBADDR0_L + core_id * 8, boot_entry >> 2); +} + +int imx_pwr_domain_on(u_register_t mpidr) +{ + unsigned int core_id; + + core_id = MPIDR_AFFLVL1_VAL(mpidr); + + imx_set_cpu_boot_entry(core_id, secure_entrypoint); + + /* + * When the core is first time boot up, the core is already ON after SoC POR, + * So 'SW_WAKEUP' can not work, so need to toggle core's reset then release + * the core from cpu_wait. + */ + if (boot_stage) { + /* assert CPU core SW reset */ + mmio_clrbits_32(SRC_SLICE(SRC_A55C0 + core_id) + 0x24, BIT(2) | BIT(0)); + /* deassert CPU core SW reset */ + mmio_setbits_32(SRC_SLICE(SRC_A55C0 + core_id) + 0x24, BIT(2) | BIT(0)); + /* release the cpuwait to kick the cpu */ + mmio_clrbits_32(BLK_CTRL_S_BASE + CA55_CPUWAIT, BIT(core_id)); + } else { + /* assert the CMC MISC SW WAKEUP BIT to kick the offline core */ + gpc_assert_sw_wakeup(CPU_A55C0 + core_id); + } + + return PSCI_E_SUCCESS; +} + +void imx_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + uint64_t mpidr = read_mpidr_el1(); + unsigned int core_id = MPIDR_AFFLVL1_VAL(mpidr); + + plat_gic_pcpu_init(); + plat_gic_cpuif_enable(); + + /* below config is ok both for boot & hotplug */ + /* clear the CPU power mode */ + gpc_set_cpu_mode(CPU_A55C0 + core_id, CM_MODE_RUN); + /* clear the SW wakeup */ + gpc_deassert_sw_wakeup(CPU_A55C0 + core_id); + /* switch to GIC wakeup source */ + gpc_select_wakeup_gic(CPU_A55C0 + core_id); + + if (boot_stage) { + /* SRC config */ + /* config the MEM LPM */ + src_mem_lpm_en(SRC_A55P0_MEM + core_id, MEM_OFF); + /* LPM config to only ON in run mode to its domain */ + src_mix_set_lpm(SRC_A55C0 + core_id, core_id, CM_MODE_WAIT); + /* white list config, only enable its own domain */ + src_authen_config(SRC_A55C0 + core_id, 1 << core_id, 0x1); + + boot_stage = false; + } +} + +void imx_pwr_domain_off(const psci_power_state_t *target_state) +{ + uint64_t mpidr = read_mpidr_el1(); + unsigned int core_id = MPIDR_AFFLVL1_VAL(mpidr); + unsigned int i; + + plat_gic_cpuif_disable(); + write_clusterpwrdn(DSU_CLUSTER_PWR_OFF); + + /* + * mask all the GPC IRQ wakeup to make sure no IRQ can wakeup this core + * as we need to use SW_WAKEUP for hotplug purpose + */ + for (i = 0U; i < IMR_NUM; i++) { + gpc_set_irq_mask(CPU_A55C0 + core_id, i, 0xffffffff); + } + /* switch to GPC wakeup source */ + gpc_select_wakeup_raw_irq(CPU_A55C0 + core_id); + /* config the target mode to suspend */ + gpc_set_cpu_mode(CPU_A55C0 + core_id, CM_MODE_SUSPEND); +} + +void imx_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + uint64_t mpidr = read_mpidr_el1(); + unsigned int core_id = MPIDR_AFFLVL1_VAL(mpidr); + + /* do cpu level config */ + if (is_local_state_off(CORE_PWR_STATE(target_state))) { + plat_gic_cpuif_disable(); + imx_set_cpu_boot_entry(core_id, secure_entrypoint); + /* config the target mode to WAIT */ + gpc_set_cpu_mode(CPU_A55C0 + core_id, CM_MODE_WAIT); + } + + /* do cluster level config */ + if (!is_local_state_run(CLUSTER_PWR_STATE(target_state))) { + /* config the A55 cluster target mode to WAIT */ + gpc_set_cpu_mode(CPU_A55_PLAT, CM_MODE_WAIT); + + /* config DSU for cluster power down with L3 MEM RET */ + if (is_local_state_retn(CLUSTER_PWR_STATE(target_state))) { + write_clusterpwrdn(DSU_CLUSTER_PWR_OFF | BIT(1)); + } + } +} + +void imx_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + uint64_t mpidr = read_mpidr_el1(); + unsigned int core_id = MPIDR_AFFLVL1_VAL(mpidr); + + /* cluster level */ + if (!is_local_state_run(CLUSTER_PWR_STATE(target_state))) { + /* set the cluster's target mode to RUN */ + gpc_set_cpu_mode(CPU_A55_PLAT, CM_MODE_RUN); + } + + /* do core level */ + if (is_local_state_off(CORE_PWR_STATE(target_state))) { + /* set A55 CORE's power mode to RUN */ + gpc_set_cpu_mode(CPU_A55C0 + core_id, CM_MODE_RUN); + plat_gic_cpuif_enable(); + } +} + +void imx_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + unsigned int i; + + for (i = IMX_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++) { + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; + } + + SYSTEM_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; + CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; +} + +void __dead2 imx_system_reset(void) +{ + mmio_write_32(WDOG3_BASE + WDOG_CNT, 0xd928c520); + while ((mmio_read_32(WDOG3_BASE + WDOG_CS) & WDOG_CS_ULK) == 0U) { + ; + } + + mmio_write_32(WDOG3_BASE + WDOG_TOVAL, 0x10); + mmio_write_32(WDOG3_BASE + WDOG_CS, 0x21e3); + + while (1) { + wfi(); + } +} + +void __dead2 imx_system_off(void) +{ + mmio_setbits_32(BBNSM_BASE + BBNSM_CTRL, BBNSM_DP_EN | BBNSM_TOSP); + + while (1) { + wfi(); + } +} + +static const plat_psci_ops_t imx_plat_psci_ops = { + .validate_ns_entrypoint = imx_validate_ns_entrypoint, + .validate_power_state = imx_validate_power_state, + .pwr_domain_on = imx_pwr_domain_on, + .pwr_domain_off = imx_pwr_domain_off, + .pwr_domain_on_finish = imx_pwr_domain_on_finish, + .pwr_domain_suspend = imx_pwr_domain_suspend, + .pwr_domain_suspend_finish = imx_pwr_domain_suspend_finish, + .get_sys_suspend_power_state = imx_get_sys_suspend_power_state, + .system_reset = imx_system_reset, + .system_off = imx_system_off, +}; + +/* export the platform specific psci ops */ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + /* sec_entrypoint is used for warm reset */ + secure_entrypoint = sec_entrypoint; + imx_set_cpu_boot_entry(0, sec_entrypoint); + + pwr_sys_init(); + + *psci_ops = &imx_plat_psci_ops; + + return 0; +} diff --git a/plat/imx/imx93/include/platform_def.h b/plat/imx/imx93/include/platform_def.h new file mode 100644 index 0000000..7efbf1c --- /dev/null +++ b/plat/imx/imx93/include/platform_def.h @@ -0,0 +1,97 @@ +/* + * Copyright 2022-2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <lib/utils_def.h> +#include <lib/xlat_tables/xlat_tables_v2.h> + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +#define PLATFORM_STACK_SIZE 0xB00 +#define CACHE_WRITEBACK_GRANULE 64 + +#define PLAT_PRIMARY_CPU U(0x0) +#define PLATFORM_MAX_CPU_PER_CLUSTER U(2) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT U(2) +#define PLATFORM_CORE_COUNT U(2) + +#define IMX_PWR_LVL0 MPIDR_AFFLVL0 + +#define PWR_DOMAIN_AT_MAX_LVL U(1) +#define PLAT_MAX_PWR_LVL U(2) +#define PLAT_MAX_OFF_STATE U(4) +#define PLAT_MAX_RET_STATE U(2) + +#define BL31_BASE U(0x204E0000) +#define BL31_LIMIT U(0x20520000) + +/* non-secure uboot base */ +/* TODO */ +#define PLAT_NS_IMAGE_OFFSET U(0x80200000) +#define BL32_FDT_OVERLAY_ADDR (PLAT_NS_IMAGE_OFFSET + 0x3000000) + +/* GICv4 base address */ +#define PLAT_GICD_BASE U(0x48000000) +#define PLAT_GICR_BASE U(0x48040000) + +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) + +#define MAX_XLAT_TABLES 8 +#define MAX_MMAP_REGIONS 16 + +#define IMX_LPUART_BASE U(0x44380000) +#define IMX_BOOT_UART_CLK_IN_HZ U(24000000) /* Select 24MHz oscillator */ +#define IMX_CONSOLE_BAUDRATE 115200 + +#define AIPSx_SIZE U(0x800000) +#define AIPS1_BASE U(0x44000000) +#define AIPS2_BASE U(0x42000000) +#define AIPS3_BASE U(0x42800000) +#define AIPS4_BASE U(0x49000000) +#define GPIO1_BASE U(0x47400000) +#define GPIO2_BASE U(0x43810000) +#define GPIO3_BASE U(0x43820000) +#define GPIO4_BASE U(0x43830000) + +#define TRDC_A_BASE U(0x44270000) +#define TRDC_W_BASE U(0x42460000) +#define TRDC_M_BASE U(0x42810000) +#define TRDC_N_BASE U(0x49010000) +#define TRDC_x_SISE U(0x20000) + +#define WDOG3_BASE U(0x42490000) +#define WDOG_CS U(0x0) +#define WDOG_CS_ULK BIT(11) +#define WDOG_CNT U(0x4) +#define WDOG_TOVAL U(0x8) + +#define BBNSM_BASE U(0x44440000) +#define BBNSM_CTRL U(0x8) +#define BBNSM_DP_EN BIT(24) +#define BBNSM_TOSP BIT(25) + +#define SRC_BASE U(0x44460000) +#define GPC_BASE U(0x44470000) +#define BLK_CTRL_S_BASE U(0x444F0000) +#define S400_MU_BASE U(0x47520000) + +/* system memory map define */ +#define AIPS2_MAP MAP_REGION_FLAT(AIPS2_BASE, AIPSx_SIZE, MT_DEVICE | MT_RW | MT_NS) +#define AIPS1_MAP MAP_REGION_FLAT(AIPS1_BASE, AIPSx_SIZE, MT_DEVICE | MT_RW) +#define AIPS4_MAP MAP_REGION_FLAT(AIPS4_BASE, AIPSx_SIZE, MT_DEVICE | MT_RW | MT_NS) +#define GIC_MAP MAP_REGION_FLAT(PLAT_GICD_BASE, 0x200000, MT_DEVICE | MT_RW) +#define TRDC_A_MAP MAP_REGION_FLAT(TRDC_A_BASE, TRDC_x_SISE, MT_DEVICE | MT_RW) +#define TRDC_W_MAP MAP_REGION_FLAT(TRDC_W_BASE, TRDC_x_SISE, MT_DEVICE | MT_RW) +#define TRDC_M_MAP MAP_REGION_FLAT(TRDC_M_BASE, TRDC_x_SISE, MT_DEVICE | MT_RW) +#define TRDC_N_MAP MAP_REGION_FLAT(TRDC_N_BASE, TRDC_x_SISE, MT_DEVICE | MT_RW) + +#define COUNTER_FREQUENCY 24000000 + +#endif /* platform_def.h */ diff --git a/plat/imx/imx93/include/pwr_ctrl.h b/plat/imx/imx93/include/pwr_ctrl.h new file mode 100644 index 0000000..9bcf486 --- /dev/null +++ b/plat/imx/imx93/include/pwr_ctrl.h @@ -0,0 +1,216 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PWR_CTRL_H +#define PWR_CTRL_H + +#include <stdbool.h> + +#include <lib/mmio.h> + +#include <platform_def.h> + +/******************************************************************************* + * GPC definitions & declarations + ******************************************************************************/ +/* GPC GLOBAL */ +#define GPC_GLOBAL_BASE U(GPC_BASE + 0x4000) +#define GPC_AUTHEN_CTRL U(0x4) +#define GPC_DOMAIN U(0x10) +#define GPC_MASTER U(0x1c) +#define GPC_SYS_SLEEP U(0x40) +#define PMIC_CTRL U(0x100) +#define PMIC_PRE_DLY_CTRL U(0x104) +#define PMIC_STBY_ACK_CTRL U(0x108) +#define GPC_ROSC_CTRL U(0x200) +#define GPC_AON_MEM_CTRL U(0x204) +#define GPC_EFUSE_CTRL U(0x208) + +#define FORCE_CPUx_DISABLE(x) (1 << (16 + (x))) +#define PMIC_STBY_EN BIT(0) +#define ROSC_OFF_EN BIT(0) + +/* GPC CPU_CTRL */ +#define CM_SLICE(x) (GPC_BASE + 0x800 * (x)) +#define CM_AUTHEN_CTRL U(0x4) +#define CM_MISC U(0xc) +#define CM_MODE_CTRL U(0x10) +#define CM_IRQ_WAKEUP_MASK0 U(0x100) +#define CM_SYS_SLEEP_CTRL U(0x380) +#define IMR_NUM U(8) + +/* CM_MISC */ +#define SLEEP_HOLD_EN BIT(1) +#define IRQ_MUX BIT(5) +#define SW_WAKEUP BIT(6) + +/* CM_SYS_SLEEP_CTRL */ +#define SS_WAIT BIT(0) +#define SS_STOP BIT(1) +#define SS_SUSPEND BIT(2) + +#define CM_MODE_RUN U(0x0) +#define CM_MODE_WAIT U(0x1) +#define CM_MODE_STOP U(0x2) +#define CM_MODE_SUSPEND U(0x3) + +#define LPM_SETTING(d, m) ((m) << (((d) % 8) * 4)) + +enum gpc_cmc_slice { + CPU_M33, + CPU_A55C0, + CPU_A55C1, + CPU_A55_PLAT, +}; + +/* set gpc domain assignment */ +static inline void gpc_assign_domains(unsigned int domains) +{ + mmio_write_32(GPC_GLOBAL_BASE + GPC_DOMAIN, domains); +} + +/* force a cpu into sleep status */ +static inline void gpc_force_cpu_suspend(unsigned int cpu) +{ + mmio_setbits_32(GPC_GLOBAL_BASE + GPC_SYS_SLEEP, FORCE_CPUx_DISABLE(cpu)); +} + +static inline void gpc_pmic_stby_en(bool en) +{ + mmio_write_32(GPC_GLOBAL_BASE + PMIC_CTRL, en ? 1 : 0); +} + +static inline void gpc_rosc_off(bool off) +{ + mmio_write_32(GPC_GLOBAL_BASE + GPC_ROSC_CTRL, off ? 1 : 0); +} + +static inline void gpc_set_cpu_mode(unsigned int cpu, unsigned int mode) +{ + mmio_write_32(CM_SLICE(cpu) + CM_MODE_CTRL, mode); +} + +static inline void gpc_select_wakeup_gic(unsigned int cpu) +{ + mmio_setbits_32(CM_SLICE(cpu) + CM_MISC, IRQ_MUX); +} + +static inline void gpc_select_wakeup_raw_irq(unsigned int cpu) +{ + mmio_clrbits_32(CM_SLICE(cpu) + CM_MISC, IRQ_MUX); +} + +static inline void gpc_assert_sw_wakeup(unsigned int cpu) +{ + mmio_setbits_32(CM_SLICE(cpu) + CM_MISC, SW_WAKEUP); +} + +static inline void gpc_deassert_sw_wakeup(unsigned int cpu) +{ + mmio_clrbits_32(CM_SLICE(cpu) + CM_MISC, SW_WAKEUP); +} + +static inline void gpc_clear_cpu_sleep_hold(unsigned int cpu) +{ + mmio_clrbits_32(CM_SLICE(cpu) + CM_MISC, SLEEP_HOLD_EN); +} + +static inline void gpc_set_irq_mask(unsigned int cpu, unsigned int idx, uint32_t mask) +{ + mmio_write_32(CM_SLICE(cpu) + idx * 0x4 + CM_IRQ_WAKEUP_MASK0, mask); +} + +/******************************************************************************* + * SRC definitions & declarations + ******************************************************************************/ +#define SRC_SLICE(x) (SRC_BASE + 0x400 * (x)) +#define SRC_AUTHEN_CTRL U(0x4) +#define SRC_LPM_SETTING0 U(0x10) +#define SRC_LPM_SETTING1 U(0x14) +#define SRC_LPM_SETTING2 U(0x18) +#define SRC_SLICE_SW_CTRL U(0x20) + +#define SRC_MEM_CTRL U(0x4) +#define MEM_LP_EN BIT(2) +#define MEM_LP_RETN BIT(1) + +enum mix_mem_mode { + MEM_OFF, + MEM_RETN, +}; + +enum src_mix_mem_slice { + SRC_GLOBAL, + + /* MIX slice */ + SRC_SENTINEL, + SRC_AON, + SRC_WKUP, + SRC_DDR, + SRC_DPHY, + SRC_ML, + SRC_NIC, + SRC_HSIO, + SRC_MEDIA, + SRC_M33P, + SRC_A55C0, + SRC_A55C1, + SRC_A55P, + + /* MEM slice */ + SRC_AON_MEM, + SRC_WKUP_MEM, + SRC_DDR_MEM, + SRC_DPHY_MEM, + SRC_ML_MEM, + SRC_NIC_MEM, + SRC_NIC_OCRAM, + SRC_HSIO_MEM, + SRC_MEDIA_MEM, + SRC_A55P0_MEM, + SRC_A55P1_MEM, + SRC_A55_SCU_MEM, + SRC_A55_L3_MEM, +}; + +static inline void src_authen_config(unsigned int mix, unsigned int wlist, + unsigned int lpm_en) +{ + mmio_write_32(SRC_SLICE(mix) + SRC_AUTHEN_CTRL, (wlist << 16) | (lpm_en << 2)); +} + +static inline void src_mix_set_lpm(unsigned int mix, unsigned int did, unsigned int lpm_mode) +{ + mmio_clrsetbits_32(SRC_SLICE(mix) + SRC_LPM_SETTING1 + (did / 8) * 0x4, + LPM_SETTING(did, 0x7), LPM_SETTING(did, lpm_mode)); +} + +static inline void src_mem_lpm_en(unsigned int mix, bool retn) +{ + mmio_setbits_32(SRC_SLICE(mix) + SRC_MEM_CTRL, MEM_LP_EN | (retn ? MEM_LP_RETN : 0)); +} + +static inline void src_mem_lpm_dis(unsigned int mix) +{ + mmio_clrbits_32(SRC_SLICE(mix) + SRC_MEM_CTRL, MEM_LP_EN | MEM_LP_RETN); +} + +/******************************************************************************* + * BLK_CTRL_S definitions & declarations + ******************************************************************************/ +#define HW_LP_HANDHSK U(0x110) +#define HW_LP_HANDHSK2 U(0x114) +#define CA55_CPUWAIT U(0x118) +#define CA55_RVBADDR0_L U(0x11c) +#define CA55_RVBADDR0_H U(0x120) + +/******************************************************************************* + * Other definitions & declarations + ******************************************************************************/ +void pwr_sys_init(void); + +#endif /* PWR_CTRL_H */ + diff --git a/plat/imx/imx93/plat_topology.c b/plat/imx/imx93/plat_topology.c new file mode 100644 index 0000000..739e2b9 --- /dev/null +++ b/plat/imx/imx93/plat_topology.c @@ -0,0 +1,39 @@ +/* + * Copyright 2022-2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <arch_helpers.h> +#include <plat/common/platform.h> + +const unsigned char imx_power_domain_tree_desc[] = { + PWR_DOMAIN_AT_MAX_LVL, + PLATFORM_CLUSTER_COUNT, + PLATFORM_CLUSTER0_CORE_COUNT, +}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return imx_power_domain_tree_desc; +} + +/* + * Only one cluster is planned for i.MX9 family, no need + * to consider the cluster id + */ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) { + return -1; + } + + cpu_id = MPIDR_AFFLVL1_VAL(mpidr); + + return cpu_id; +} diff --git a/plat/imx/imx93/platform.mk b/plat/imx/imx93/platform.mk new file mode 100644 index 0000000..ed7e81f --- /dev/null +++ b/plat/imx/imx93/platform.mk @@ -0,0 +1,46 @@ +# +# Copyright 2022-2023 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_INCLUDES := -Iplat/imx/common/include \ + -Iplat/imx/imx93/include \ +# Translation tables library +include lib/xlat_tables_v2/xlat_tables.mk + +GICV3_SUPPORT_GIC600 := 1 + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +IMX_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/common/plat_psci_common.c \ + plat/imx/common/plat_imx8_gic.c + +BL31_SOURCES += plat/common/aarch64/crash_console_helpers.S \ + plat/imx/imx93/aarch64/plat_helpers.S \ + plat/imx/imx93/plat_topology.c \ + plat/imx/common/lpuart_console.S \ + plat/imx/imx93/trdc.c \ + plat/imx/imx93/pwr_ctrl.c \ + plat/imx/imx93/imx93_bl31_setup.c \ + plat/imx/imx93/imx93_psci.c \ + lib/cpus/aarch64/cortex_a55.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/nxp/trdc/imx_trdc.c \ + ${IMX_GIC_SOURCES} \ + ${XLAT_TABLES_LIB_SRCS} + +RESET_TO_BL31 := 1 +HW_ASSISTED_COHERENCY := 1 +USE_COHERENT_MEM := 0 +PROGRAMMABLE_RESET_ADDRESS := 1 +COLD_BOOT_SINGLE_CPU := 1 + +BL32_BASE ?= 0x96000000 +BL32_SIZE ?= 0x02000000 +$(eval $(call add_define,BL32_BASE)) +$(eval $(call add_define,BL32_SIZE)) diff --git a/plat/imx/imx93/pwr_ctrl.c b/plat/imx/imx93/pwr_ctrl.c new file mode 100644 index 0000000..624c605 --- /dev/null +++ b/plat/imx/imx93/pwr_ctrl.c @@ -0,0 +1,63 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include <stdbool.h> + +#include <platform_def.h> +#include <pwr_ctrl.h> + +/*Do the necessary GPC, SRC, BLK_CTRL_S init */ +void pwr_sys_init(void) +{ + unsigned int cpu; + + /* + * Assigned A55 cluster to 3, m33 to 2, A55 CORE0 & CORE1 to 0/1. + * domain0/1 only used for trigger LPM of themselves. A55 cluster & M33's + * domain assignment should be align with the TRDC DID. + */ + gpc_assign_domains(0x3102); + + /* CA55 core0/1 config */ + for (cpu = CPU_A55C0; cpu <= CPU_A55_PLAT; cpu++) { + /* clear the cpu sleep hold */ + gpc_clear_cpu_sleep_hold(cpu); + /* use gic wakeup source by default */ + gpc_select_wakeup_gic(cpu); + /* + * Ignore A55 core0/1's LPM trigger for system sleep. + * normally, for A55 side, only the A55 cluster(plat) + * domain will be used to trigger the system wide low + * power mode transition. + */ + if (cpu != CPU_A55_PLAT) { + gpc_force_cpu_suspend(cpu); + } + } + + /* boot core(A55C0) */ + src_mem_lpm_en(SRC_A55P0_MEM, MEM_OFF); + /* For A55 core, only need to be on in RUN mode */ + src_mix_set_lpm(SRC_A55C0, 0x0, CM_MODE_WAIT); + /* whitelist: 0x1 for domain 0 only */ + src_authen_config(SRC_A55C0, 0x1, 0x1); + + /* A55 cluster */ + gpc_select_wakeup_gic(CPU_A55_PLAT); + gpc_clear_cpu_sleep_hold(CPU_A55_PLAT); + + /* SCU MEM must be OFF when A55 PLAT OFF */ + src_mem_lpm_en(SRC_A55_SCU_MEM, MEM_OFF); + /* L3 memory in retention by default */ + src_mem_lpm_en(SRC_A55_L3_MEM, MEM_RETN); + + src_mix_set_lpm(SRC_A55P, 0x3, 0x1); + /* whitelist: 0x8 for domain 3 only */ + src_authen_config(SRC_A55P, 0x8, 0x1); + + /* enable the HW LP handshake between S401 & A55 cluster */ + mmio_setbits_32(BLK_CTRL_S_BASE + HW_LP_HANDHSK, BIT(5)); +} + diff --git a/plat/imx/imx93/trdc.c b/plat/imx/imx93/trdc.c new file mode 100644 index 0000000..0d09aa6 --- /dev/null +++ b/plat/imx/imx93/trdc.c @@ -0,0 +1,68 @@ +/* + * Copyright 2022-2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> +#include <stdbool.h> + +#include <common/bl_common.h> +#include <common/debug.h> +#include <lib/mmio.h> + +#include "trdc_config.h" + +struct trdc_mgr_info trdc_mgr_blks[] = { + { TRDC_A_BASE, 0, 0, 39, 40 }, + { TRDC_W_BASE, 0, 0, 70, 71 }, + { TRDC_M_BASE, 1, 0, 1, 2 }, + { TRDC_N_BASE, 0, 1, 1, 2 }, +}; + +unsigned int trdc_mgr_num = ARRAY_SIZE(trdc_mgr_blks); + +struct trdc_config_info trdc_cfg_info[] = { + { TRDC_A_BASE, + trdc_a_mbc_glbac, ARRAY_SIZE(trdc_a_mbc_glbac), + trdc_a_mbc, ARRAY_SIZE(trdc_a_mbc), + trdc_a_mrc_glbac, ARRAY_SIZE(trdc_a_mrc_glbac), + trdc_a_mrc, ARRAY_SIZE(trdc_a_mrc) + }, /* TRDC_A */ + { TRDC_W_BASE, + trdc_w_mbc_glbac, ARRAY_SIZE(trdc_w_mbc_glbac), + trdc_w_mbc, ARRAY_SIZE(trdc_w_mbc), + trdc_w_mrc_glbac, ARRAY_SIZE(trdc_w_mrc_glbac), + trdc_w_mrc, ARRAY_SIZE(trdc_w_mrc) + }, /* TRDC_W */ + { TRDC_N_BASE, + trdc_n_mbc_glbac, ARRAY_SIZE(trdc_n_mbc_glbac), + trdc_n_mbc, ARRAY_SIZE(trdc_n_mbc), + trdc_n_mrc_glbac, ARRAY_SIZE(trdc_n_mrc_glbac), + trdc_n_mrc, ARRAY_SIZE(trdc_n_mrc) + }, /* TRDC_N */ +}; + +void trdc_config(void) +{ + unsigned int i; + + /* Set MTR to DID1 */ + trdc_mda_set_noncpu(TRDC_A_BASE, 4, false, 0x2, 0x2, 0x1); + + /* Set M33 to DID2*/ + trdc_mda_set_cpu(TRDC_A_BASE, 1, 0, 0x2, 0x0, 0x2, 0x0, 0x0, 0x0); + + /* Configure the access permission for TRDC MGR and MC slots */ + for (i = 0U; i < ARRAY_SIZE(trdc_mgr_blks); i++) { + trdc_mgr_mbc_setup(&trdc_mgr_blks[i]); + } + + /* Configure TRDC user settings from config table */ + for (i = 0U; i < ARRAY_SIZE(trdc_cfg_info); i++) { + trdc_setup(&trdc_cfg_info[i]); + } + + NOTICE("TRDC init done\n"); +} diff --git a/plat/imx/imx93/trdc_config.h b/plat/imx/imx93/trdc_config.h new file mode 100644 index 0000000..c623a19 --- /dev/null +++ b/plat/imx/imx93/trdc_config.h @@ -0,0 +1,254 @@ +/* + * Copyright 2022-2023 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <drivers/nxp/trdc/imx_trdc.h> + +#define TRDC_A_BASE U(0x44270000) +#define TRDC_W_BASE U(0x42460000) +#define TRDC_M_BASE U(0x42460000) +#define TRDC_N_BASE U(0x49010000) + +/* GLBAC7 is used for TRDC only, any setting to GLBAC7 will be ignored */ + +/* aonmix */ +struct trdc_glbac_config trdc_a_mbc_glbac[] = { + /* MBC0 */ + { 0, 0, SP(RW) | SU(RW) | NP(RW) | NU(RW) }, + /* MBC1 */ + { 1, 0, SP(RW) | SU(RW) | NP(RW) | NU(RW) }, + { 1, 1, SP(RW) | SU(R) | NP(RW) | NU(R) }, + { 1, 2, SP(RWX) | SU(RWX) | NP(RWX) | NU(RWX) }, +}; + +struct trdc_mbc_config trdc_a_mbc[] = { + { 0, 0, 0, MBC_BLK_ALL, 0, true }, /* MBC0 AIPS1 for S401 DID0 */ + { 0, 0, 1, MBC_BLK_ALL, 0, true }, /* MBC0 Sentinel_SOC_In for S401 DID0 */ + { 0, 0, 2, MBC_BLK_ALL, 0, true }, /* MBC0 GPIO1 for S401 DID0 */ + { 1, 0, 0, MBC_BLK_ALL, 0, true }, /* MBC1 CM33 code TCM for S401 DID0 */ + { 1, 0, 1, MBC_BLK_ALL, 0, true }, /* MBC1 CM33 system TCM for S401 DID0 */ + + { 0, 1, 0, MBC_BLK_ALL, 0, true }, /* MBC0 AIPS1 for MTR DID1 */ + { 0, 1, 1, MBC_BLK_ALL, 0, true }, /* MBC0 Sentinel_SOC_In for MTR DID1 */ + + { 0, 2, 0, MBC_BLK_ALL, 0, true }, /* MBC0 AIPS1 for M33 DID2 */ + { 0, 2, 1, MBC_BLK_ALL, 0, true }, /* MBC0 Sentinel_SOC_In for M33 DID2 */ + { 0, 2, 2, MBC_BLK_ALL, 0, true }, /* MBC0 GPIO1 for M33 DID2 */ + { 1, 2, 0, MBC_BLK_ALL, 2, true }, /* MBC1 CM33 code TCM for M33 DID2 */ + { 1, 2, 1, MBC_BLK_ALL, 2, true }, /* MBC1 CM33 system TCM for M33 DID2 */ + + { 0, 3, 0, MBC_BLK_ALL, 0, false }, /* MBC0 AIPS1 for A55 DID3 */ + { 0, 3, 1, MBC_BLK_ALL, 0, false }, /* MBC0 Sentinel_SOC_In for A55 DID3 */ + { 0, 3, 2, MBC_BLK_ALL, 0, false }, /* MBC0 GPIO1 for A55 DID3 */ + { 1, 3, 0, MBC_BLK_ALL, 1, false }, /* MBC1 CM33 code TCM for A55 DID3 */ + { 1, 3, 1, MBC_BLK_ALL, 1, false }, /* MBC1 CM33 system TCM for A55 DID3 */ + { 1, 10, 1, MBC_BLK_ALL, 2, false }, /* MBC1 CM33 system TCM for SoC masters DID10 */ + + { 0, 7, 0, MBC_BLK_ALL, 0, false }, /* MBC0 AIPS1 for eDMA DID7 */ +}; + +struct trdc_glbac_config trdc_a_mrc_glbac[] = { + { 0, 0, SP(RWX) | SU(RWX) | NP(RWX) | NU(RWX) }, + { 0, 1, SP(R) | SU(0) | NP(R) | NU(0) }, +}; + +struct trdc_mrc_config trdc_a_mrc[] = { + { 0, 2, 0, 0x00000000, 0x00040000, 0, true }, /* MRC0 M33 ROM for M33 DID2 */ + { 0, 3, 0, 0x00100000, 0x00040000, 1, true }, /* MRC0 M33 ROM for A55 DID3 */ +}; + +/* wakeupmix */ +struct trdc_glbac_config trdc_w_mbc_glbac[] = { + /* MBC0 */ + { 0, 0, SP(RW) | SU(RW) | NP(RW) | NU(RW) }, + /* MBC1 */ + { 1, 0, SP(RW) | SU(RW) | NP(RW) | NU(RW) }, +}; + +struct trdc_mbc_config trdc_w_mbc[] = { + { 0, 1, 0, MBC_BLK_ALL, 0, true }, /* MBC0 AIPS2 for MTR DID1 */ + { 1, 1, 0, MBC_BLK_ALL, 0, true }, /* MBC1 AIPS3 for MTR DID1 */ + + { 0, 2, 0, MBC_BLK_ALL, 0, true }, /* MBC0 AIPS2 for M33 DID2 */ + { 0, 2, 1, MBC_BLK_ALL, 0, true }, /* MBC0 GPIO2_In for M33 DID2 */ + { 0, 2, 2, MBC_BLK_ALL, 0, true }, /* MBC0 GPIO3 for M33 DID2 */ + { 0, 2, 3, MBC_BLK_ALL, 0, true }, /* MBC0 DAP for M33 DID2 */ + { 1, 2, 0, MBC_BLK_ALL, 0, true }, /* MBC1 AIPS3 for M33 DID2 */ + { 1, 2, 1, MBC_BLK_ALL, 0, true }, /* MBC1 AHB_ISPAP for M33 DID2 */ + { 1, 2, 2, MBC_BLK_ALL, 0, true }, /* MBC1 NIC_MAIN_GPV for M33 DID2 */ + { 1, 2, 3, MBC_BLK_ALL, 0, true }, /* MBC1 GPIO4 for M33 DID2 */ + + { 0, 3, 0, MBC_BLK_ALL, 0, false }, /* MBC0 AIPS2 for A55 DID3 */ + { 0, 3, 1, MBC_BLK_ALL, 0, false }, /* MBC0 GPIO2_In for A55 DID3 */ + { 0, 3, 2, MBC_BLK_ALL, 0, false }, /* MBC0 GPIO3 for A55 DID3 */ + { 0, 3, 3, MBC_BLK_ALL, 0, false }, /* MBC0 DAP for A55 DID3 */ + { 1, 3, 0, MBC_BLK_ALL, 0, false }, /* MBC1 AIPS3 for A55 DID3 */ + { 1, 3, 1, MBC_BLK_ALL, 0, false }, /* MBC1 AHB_ISPAP for A55 DID3 */ + { 1, 3, 2, MBC_BLK_ALL, 0, true }, /* MBC1 NIC_MAIN_GPV for A55 DID3 */ + { 1, 3, 3, MBC_BLK_ALL, 0, false }, /* MBC1 GPIO4 for A55 DID3 */ + + { 0, 7, 0, MBC_BLK_ALL, 0, false }, /* MBC0 AIPS2 for eDMA DID7 */ + { 1, 7, 0, MBC_BLK_ALL, 0, false }, /* MBC1 AIPS3 for eDMA DID7 */ +}; + +struct trdc_glbac_config trdc_w_mrc_glbac[] = { + /* MRC0 */ + { 0, 0, SP(RX) | SU(RX) | NP(RX) | NU(RX) }, + /* MRC1 */ + { 1, 0, SP(RWX) | SU(RWX) | NP(RWX) | NU(RWX) }, +}; + +struct trdc_mrc_config trdc_w_mrc[] = { + { 0, 3, 0, 0x00000000, 0x00040000, 0, false }, /* MRC0 A55 ROM for A55 DID3 */ + { 1, 2, 0, 0x28000000, 0x08000000, 0, true }, /* MRC1 FLEXSPI1 for M33 DID2 */ + { 1, 3, 0, 0x28000000, 0x08000000, 0, false }, /* MRC1 FLEXSPI1 for A55 DID3 */ +}; + +/* nicmix */ +struct trdc_glbac_config trdc_n_mbc_glbac[] = { + /* MBC0 */ + { 0, 0, SP(RW) | SU(RW) | NP(RW) | NU(RW) }, + /* MBC1 */ + { 1, 0, SP(RW) | SU(RW) | NP(RW) | NU(RW) }, + /* MBC2 */ + { 2, 0, SP(RW) | SU(RW) | NP(RW) | NU(RW) }, + { 2, 1, SP(R) | SU(R) | NP(R) | NU(R) }, + /* MBC3 */ + { 3, 0, SP(RW) | SU(RW) | NP(RW) | NU(RW) }, + { 3, 1, SP(RWX) | SU(RWX) | NP(RWX) | NU(RWX) }, +}; + +struct trdc_mbc_config trdc_n_mbc[] = { + { 0, 0, 0, MBC_BLK_ALL, 0, true }, /* MBC0 DDRCFG for S401 DID0 */ + { 0, 0, 1, MBC_BLK_ALL, 0, true }, /* MBC0 AIPS4 for S401 DID0 */ + { 0, 0, 2, MBC_BLK_ALL, 0, true }, /* MBC0 MEDIAMIX for S401 DID0 */ + { 0, 0, 3, MBC_BLK_ALL, 0, true }, /* MBC0 HSIOMIX for S401 DID0 */ + { 1, 0, 0, MBC_BLK_ALL, 0, true }, /* MBC1 MTR_DCA, TCU, TROUT for S401 DID0 */ + { 1, 0, 1, MBC_BLK_ALL, 0, true }, /* MBC1 MTR_DCA, TCU, TROUT for S401 DID0 */ + { 1, 0, 2, MBC_BLK_ALL, 0, true }, /* MBC1 MLMIX for S401 DID0 */ + { 1, 0, 3, MBC_BLK_ALL, 0, true }, /* MBC1 MLMIX for S401 DID0 */ + { 2, 0, 0, MBC_BLK_ALL, 0, true }, /* MBC2 GIC for S401 DID0 */ + { 2, 0, 1, MBC_BLK_ALL, 0, true }, /* MBC2 GIC for S401 DID0 */ + { 3, 0, 0, MBC_BLK_ALL, 0, true }, /* MBC3 OCRAM for S401 DID0 */ + { 3, 0, 1, MBC_BLK_ALL, 0, true }, /* MBC3 OCRAM for S401 DID0 */ + + { 0, 1, 0, MBC_BLK_ALL, 0, true }, /* MBC0 DDRCFG for MTR DID1 */ + { 0, 1, 1, MBC_BLK_ALL, 0, true }, /* MBC0 AIPS4 for MTR DID1 */ + { 0, 1, 2, MBC_BLK_ALL, 0, true }, /* MBC0 MEDIAMIX for MTR DID1 */ + { 0, 1, 3, MBC_BLK_ALL, 0, true }, /* MBC0 HSIOMIX for MTR DID1 */ + { 1, 1, 0, MBC_BLK_ALL, 0, true }, /* MBC1 MTR_DCA, TCU, TROUT for MTR DID1 */ + { 1, 1, 1, MBC_BLK_ALL, 0, true }, /* MBC1 MTR_DCA, TCU, TROUT for MTR DID1 */ + { 1, 1, 2, MBC_BLK_ALL, 0, true }, /* MBC1 MLMIX for MTR DID1 */ + { 1, 1, 3, MBC_BLK_ALL, 0, true }, /* MBC1 MLMIX for MTR DID1 */ + + { 0, 2, 0, MBC_BLK_ALL, 0, true }, /* MBC0 DDRCFG for M33 DID2 */ + { 0, 2, 1, MBC_BLK_ALL, 0, true }, /* MBC0 AIPS4 for M33 DID2 */ + { 0, 2, 2, MBC_BLK_ALL, 0, true }, /* MBC0 MEDIAMIX for M33 DID2 */ + { 0, 2, 3, MBC_BLK_ALL, 0, true }, /* MBC0 HSIOMIX for M33 DID2 */ + { 1, 2, 0, MBC_BLK_ALL, 0, true }, /* MBC1 MTR_DCA, TCU, TROUT for M33 DID2 */ + { 1, 2, 1, MBC_BLK_ALL, 0, true }, /* MBC1 MTR_DCA, TCU, TROUT for M33 DID2 */ + { 1, 2, 2, MBC_BLK_ALL, 0, true }, /* MBC1 MLMIX for M33 DID2 */ + { 1, 2, 3, MBC_BLK_ALL, 0, true }, /* MBC1 MLMIX for M33 DID2 */ + { 2, 2, 0, MBC_BLK_ALL, 1, true }, /* MBC2 GIC for M33 DID2 */ + { 2, 2, 1, MBC_BLK_ALL, 1, true }, /* MBC2 GIC for M33 DID2 */ + { 3, 2, 0, MBC_BLK_ALL, 0, true }, /* MBC3 OCRAM for M33 DID2 */ + { 3, 2, 1, MBC_BLK_ALL, 0, true }, /* MBC3 OCRAM for M33 DID2 */ + + { 0, 3, 0, MBC_BLK_ALL, 0, false }, /* MBC0 DDRCFG for A55 DID3 */ + { 0, 3, 1, MBC_BLK_ALL, 0, false }, /* MBC0 AIPS4 for A55 DID3 */ + { 0, 3, 2, MBC_BLK_ALL, 0, false }, /* MBC0 MEDIAMIX for A55 DID3 */ + { 0, 3, 3, MBC_BLK_ALL, 0, false }, /* MBC0 HSIOMIX for A55 DID3 */ + { 1, 3, 0, MBC_BLK_ALL, 0, false }, /* MBC1 MTR_DCA, TCU, TROUT for A55 DID3 */ + { 1, 3, 1, MBC_BLK_ALL, 0, false }, /* MBC1 MTR_DCA, TCU, TROUT for A55 DID3 */ + { 1, 3, 2, MBC_BLK_ALL, 0, false }, /* MBC1 MLMIX for A55 DID3 */ + { 1, 3, 3, MBC_BLK_ALL, 0, false }, /* MBC1 MLMIX for A55 DID3 */ + { 2, 3, 0, MBC_BLK_ALL, 0, false }, /* MBC2 GIC for A55 DID3 */ + { 2, 3, 1, MBC_BLK_ALL, 0, false }, /* MBC2 GIC for A55 DID3 */ + { 3, 3, 0, MBC_BLK_ALL, 1, true }, /* MBC3 OCRAM for A55 DID3 */ + { 3, 3, 1, MBC_BLK_ALL, 1, true }, /* MBC3 OCRAM for A55 DID3 */ + + { 3, 3, 0, 0, 0, false }, /* MBC3 OCRAM for A55 DID3 */ + { 3, 3, 0, 1, 0, false }, /* MBC3 OCRAM for A55 DID3 */ + { 3, 3, 0, 2, 0, false }, /* MBC3 OCRAM for A55 DID3 */ + { 3, 3, 0, 3, 0, false }, /* MBC3 OCRAM for A55 DID3 */ + { 3, 3, 0, 4, 0, false }, /* MBC3 OCRAM for A55 DID3 */ + { 3, 3, 0, 5, 0, false }, /* MBC3 OCRAM for A55 DID3 */ + { 3, 3, 1, 0, 0, false }, /* MBC3 OCRAM for A55 DID3 */ + { 3, 3, 1, 1, 0, false }, /* MBC3 OCRAM for A55 DID3 */ + { 3, 3, 1, 2, 0, false }, /* MBC3 OCRAM for A55 DID3 */ + { 3, 3, 1, 3, 0, false }, /* MBC3 OCRAM for A55 DID3 */ + { 3, 3, 1, 4, 0, false }, /* MBC3 OCRAM for A55 DID3 */ + { 3, 3, 1, 5, 0, false }, /* MBC3 OCRAM for A55 DID3 */ + + { 0, 7, 1, MBC_BLK_ALL, 0, false }, /* MBC0 AIPS4 for eDMA DID7 */ + { 0, 7, 2, MBC_BLK_ALL, 0, false }, /* MBC0 MEDIAMIX for eDMA DID7 */ + { 0, 7, 3, MBC_BLK_ALL, 0, false }, /* MBC0 HSIOMIX for eDMA DID7 */ + + { 3, 10, 0, MBC_BLK_ALL, 0, false }, /* MBC3 OCRAM for DID10 */ + { 3, 10, 1, MBC_BLK_ALL, 0, false }, /* MBC3 OCRAM for DID10 */ +}; + +struct trdc_glbac_config trdc_n_mrc_glbac[] = { + { 0, 0, SP(RW) | SU(RW) | NP(RW) | NU(RW) }, + { 0, 1, SP(RWX) | SU(RWX) | NP(RWX) | NU(RWX) }, +}; + +#if defined(SPD_opteed) +#define TEE_SHM_SIZE 0x200000 + +#define DRAM_MEM_0_START (0x80000000) +#define DRAM_MEM_0_SIZE (BL32_BASE - 0x80000000) + +#define DRAM_MEM_1_START (BL32_BASE) +#define DRAM_MEM_1_SIZE (BL32_SIZE - TEE_SHM_SIZE) + +#define DRAM_MEM_2_START (DRAM_MEM_1_START + DRAM_MEM_1_SIZE) +#define DRAM_MEM_2_SIZE (0x80000000 - DRAM_MEM_1_SIZE - DRAM_MEM_0_SIZE) + +struct trdc_mrc_config trdc_n_mrc[] = { + { 0, 0, 0, 0x80000000, 0x80000000, 0, false }, /* MRC0 DRAM for S400 DID0 */ + { 0, 1, 0, 0x80000000, 0x80000000, 0, false }, /* MRC0 DRAM for MTR DID1 */ + { 0, 2, 0, 0x80000000, 0x80000000, 0, true }, /* MRC0 DRAM for M33 DID2 */ + { 0, 8, 0, 0x80000000, 0x80000000, 1, false }, /* MRC0 DRAM for Coresight, Testport DID8 */ + { 0, 9, 0, 0x80000000, 0x80000000, 1, false }, /* MRC0 DRAM for DAP DID9 */ + + { 0, 3, 0, DRAM_MEM_0_START, DRAM_MEM_0_SIZE, 1, false }, /* MRC0 DRAM for A55 DID3 */ + { 0, 5, 0, DRAM_MEM_0_START, DRAM_MEM_0_SIZE, 0, false }, /* MRC0 DRAM for USDHC1 DID5 */ + { 0, 6, 0, DRAM_MEM_0_START, DRAM_MEM_0_SIZE, 0, false }, /* MRC0 DRAM for USDHC2 DID6 */ + { 0, 7, 0, DRAM_MEM_0_START, DRAM_MEM_0_SIZE, 0, false }, /* MRC0 DRAM for eDMA DID7 */ + { 0, 10, 0, DRAM_MEM_0_START, DRAM_MEM_0_SIZE, 0, false }, /* MRC0 DRAM for SoC masters DID10 */ + { 0, 11, 0, DRAM_MEM_0_START, DRAM_MEM_0_SIZE, 0, false }, /* MRC0 DRAM for USB DID11 */ + + /* OPTEE memory for secure access only. */ + { 0, 3, 1, DRAM_MEM_1_START, DRAM_MEM_1_SIZE, 1, true }, /* MRC0 DRAM for A55 DID3 */ + { 0, 5, 1, DRAM_MEM_1_START, DRAM_MEM_1_SIZE, 0, true }, /* MRC0 DRAM for USDHC1 DID5 */ + { 0, 6, 1, DRAM_MEM_1_START, DRAM_MEM_1_SIZE, 0, true }, /* MRC0 DRAM for USDHC2 DID6 */ + { 0, 7, 1, DRAM_MEM_1_START, DRAM_MEM_1_SIZE, 0, true }, /* MRC0 DRAM for eDMA DID7 */ + { 0, 10, 1, DRAM_MEM_1_START, DRAM_MEM_1_SIZE, 0, true }, /* MRC0 DRAM for SoC masters DID10 */ + { 0, 11, 1, DRAM_MEM_1_START, DRAM_MEM_1_SIZE, 0, true }, /* MRC0 DRAM for USB DID11 */ + + { 0, 3, 2, DRAM_MEM_2_START, DRAM_MEM_2_SIZE, 1, false }, /* MRC0 DRAM for A55 DID3 */ + { 0, 5, 2, DRAM_MEM_2_START, DRAM_MEM_2_SIZE, 0, false }, /* MRC0 DRAM for USDHC1 DID5 */ + { 0, 6, 2, DRAM_MEM_2_START, DRAM_MEM_2_SIZE, 0, false }, /* MRC0 DRAM for USDHC2 DID6 */ + { 0, 7, 2, DRAM_MEM_2_START, DRAM_MEM_2_SIZE, 0, false }, /* MRC0 DRAM for eDMA DID7 */ + { 0, 10, 2, DRAM_MEM_2_START, DRAM_MEM_2_SIZE, 0, false }, /* MRC0 DRAM for SoC masters DID10 */ + { 0, 11, 2, DRAM_MEM_2_START, DRAM_MEM_2_SIZE, 0, false }, /* MRC0 DRAM for USB DID11 */ + +}; +#else +struct trdc_mrc_config trdc_n_mrc[] = { + { 0, 0, 0, 0x80000000, 0x80000000, 0, false }, /* MRC0 DRAM for S400 DID0 */ + { 0, 1, 0, 0x80000000, 0x80000000, 0, false }, /* MRC0 DRAM for MTR DID1 */ + { 0, 2, 0, 0x80000000, 0x80000000, 0, true }, /* MRC0 DRAM for M33 DID2 */ + { 0, 3, 0, 0x80000000, 0x80000000, 1, false }, /* MRC0 DRAM for A55 DID3 */ + { 0, 5, 0, 0x80000000, 0x80000000, 0, false }, /* MRC0 DRAM for USDHC1 DID5 */ + { 0, 6, 0, 0x80000000, 0x80000000, 0, false }, /* MRC0 DRAM for USDHC2 DID6 */ + { 0, 7, 0, 0x80000000, 0x80000000, 0, false }, /* MRC0 DRAM for eDMA DID7 */ + { 0, 8, 0, 0x80000000, 0x80000000, 1, false }, /* MRC0 DRAM for Coresight, Testport DID8 */ + { 0, 9, 0, 0x80000000, 0x80000000, 1, false }, /* MRC0 DRAM for DAP DID9 */ + { 0, 10, 0, 0x80000000, 0x80000000, 0, false }, /* MRC0 DRAM for SoC masters DID10 */ + { 0, 11, 0, 0x80000000, 0x80000000, 0, false }, /* MRC0 DRAM for USB DID11 */ +}; +#endif |