summaryrefslogtreecommitdiffstats
path: root/plat/imx/imx93
diff options
context:
space:
mode:
Diffstat (limited to 'plat/imx/imx93')
-rw-r--r--plat/imx/imx93/aarch64/plat_helpers.S74
-rw-r--r--plat/imx/imx93/imx93_bl31_setup.c160
-rw-r--r--plat/imx/imx93/imx93_psci.c253
-rw-r--r--plat/imx/imx93/include/platform_def.h97
-rw-r--r--plat/imx/imx93/include/pwr_ctrl.h216
-rw-r--r--plat/imx/imx93/plat_topology.c39
-rw-r--r--plat/imx/imx93/platform.mk46
-rw-r--r--plat/imx/imx93/pwr_ctrl.c63
-rw-r--r--plat/imx/imx93/trdc.c68
-rw-r--r--plat/imx/imx93/trdc_config.h254
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