diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:13:47 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:13:47 +0000 |
commit | 102b0d2daa97dae68d3eed54d8fe37a9cc38a892 (patch) | |
tree | bcf648efac40ca6139842707f0eba5a4496a6dd2 /plat/nxp/soc-ls1043a | |
parent | Initial commit. (diff) | |
download | arm-trusted-firmware-102b0d2daa97dae68d3eed54d8fe37a9cc38a892.tar.xz arm-trusted-firmware-102b0d2daa97dae68d3eed54d8fe37a9cc38a892.zip |
Adding upstream version 2.8.0+dfsg.upstream/2.8.0+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'plat/nxp/soc-ls1043a')
-rw-r--r-- | plat/nxp/soc-ls1043a/aarch64/ls1043a.S | 1637 | ||||
-rw-r--r-- | plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S | 70 | ||||
-rw-r--r-- | plat/nxp/soc-ls1043a/include/ns_access.h | 175 | ||||
-rw-r--r-- | plat/nxp/soc-ls1043a/include/soc.h | 234 | ||||
-rw-r--r-- | plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c | 163 | ||||
-rw-r--r-- | plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h | 79 | ||||
-rw-r--r-- | plat/nxp/soc-ls1043a/ls1043ardb/platform.c | 28 | ||||
-rw-r--r-- | plat/nxp/soc-ls1043a/ls1043ardb/platform.mk | 40 | ||||
-rw-r--r-- | plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h | 13 | ||||
-rw-r--r-- | plat/nxp/soc-ls1043a/ls1043ardb/policy.h | 16 | ||||
-rw-r--r-- | plat/nxp/soc-ls1043a/soc.c | 435 | ||||
-rw-r--r-- | plat/nxp/soc-ls1043a/soc.def | 107 | ||||
-rw-r--r-- | plat/nxp/soc-ls1043a/soc.mk | 114 |
13 files changed, 3111 insertions, 0 deletions
diff --git a/plat/nxp/soc-ls1043a/aarch64/ls1043a.S b/plat/nxp/soc-ls1043a/aarch64/ls1043a.S new file mode 100644 index 0000000..a1baf79 --- /dev/null +++ b/plat/nxp/soc-ls1043a/aarch64/ls1043a.S @@ -0,0 +1,1637 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <asm_macros.S> +#include <cortex_a53.h> +#include <dcfg_lsch2.h> +#include <plat_gic.h> +#include <scfg.h> + +#include <bl31_data.h> +#include <plat_psci.h> +#include <platform_def.h> + +/* the BASE address for these offsets is AUX_01_DATA in the */ +/* bootcore's psci data region */ +#define DEVDISR2_MASK_OFFSET 0x0 /* references AUX_01_DATA */ +#define DEVDISR5_MASK_OFFSET 0x8 /* references AUX_02_DATA */ +#define CPUACTLR_DATA_OFFSET 0x10 /* references AUX_03_DATA */ +/* the BASE address for these offsets is AUX_04_DATA in the */ +/* bootcore's psci data region */ +#define GICD_BASE_ADDR_OFFSET 0x0 /* references AUX_04_DATA */ +#define GICC_BASE_ADDR_OFFSET 0x8 /* references AUX_05_DATA */ + +#define DAIF_DATA AUX_06_DATA /* references AUX_06_DATA */ + +#define IPSTPACK_RETRY_CNT 0x10000 +#define DDR_SLEEP_RETRY_CNT 0x10000 +#define CPUACTLR_EL1 S3_1_C15_C2_0 +#define DDR_SDRAM_CFG_2_FRCSR 0x80000000 +#define DDR_SDRAM_CFG_2_OFFSET 0x114 +#define DDR_TIMING_CFG_4_OFFSET 0x160 +#define DDR_CNTRL_BASE_ADDR 0x01080000 + +#define DLL_LOCK_MASK 0x3 +#define DLL_LOCK_VALUE 0x2 + +#define ERROR_DDR_SLEEP -1 +#define ERROR_DDR_WAKE -2 +#define ERROR_NO_QUIESCE -3 + +#define CORE_RESTARTABLE 0 +#define CORE_NOT_RESTARTABLE 1 + +#define RESET_RETRY_CNT 800 + +.global soc_init_lowlevel +.global soc_init_percpu +.global _soc_core_release +.global _soc_core_restart +.global _soc_ck_disabled +.global _soc_sys_reset +.global _soc_sys_off +.global _getGICD_BaseAddr +.global _getGICC_BaseAddr +.global _soc_set_start_addr +.global _soc_core_prep_off +.global _soc_core_entr_off +.global _soc_core_exit_off +.global _soc_core_prep_stdby +.global _soc_core_entr_stdby +.global _soc_core_exit_stdby +.global _soc_core_prep_pwrdn +.global _soc_core_entr_pwrdn +.global _soc_core_exit_pwrdn +.global _soc_clstr_prep_stdby +.global _soc_clstr_exit_stdby +.global _soc_clstr_prep_pwrdn +.global _soc_clstr_exit_pwrdn +.global _soc_sys_prep_stdby +.global _soc_sys_exit_stdby +.global _soc_sys_prep_pwrdn +.global _soc_sys_pwrdn_wfi +.global _soc_sys_exit_pwrdn + +/* + * This function initialize the soc. + * in: void + * out: void + */ +func soc_init_lowlevel + ret +endfunc soc_init_lowlevel + +/* + * void soc_init_percpu(void) + * this function performs any soc-specific initialization that is needed on + * a per-core basis + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +func soc_init_percpu + mov x3, x30 + + bl plat_my_core_mask + mov x2, x0 + + /* see if this core is marked for prefetch disable */ + mov x0, #PREFETCH_DIS_OFFSET + bl _get_global_data /* 0-1 */ + tst x0, x2 + b.eq 1f + bl _disable_ldstr_pfetch_A53 /* 0 */ +1: + mov x30, x3 + ret +endfunc soc_init_percpu + +/* + * part of CPU_ON + * this function releases a secondary core from reset + * in: x0 = core_mask_lsb + * out: none + * uses: x0, x1, x2, x3 + */ +_soc_core_release: + +#if (TEST_BL31) + mov w2, w0 + CoreMaskMsb w2, w3 + /* x2 = core mask msb */ +#else + mov x2, x0 +#endif + /* write COREBCR */ + ldr x1, =NXP_SCFG_ADDR + rev w3, w2 + str w3, [x1, #SCFG_COREBCR_OFFSET] + isb + + /* read-modify-write BRR */ + mov x1, #NXP_DCFG_ADDR + ldr w2, [x1, #DCFG_BRR_OFFSET] + rev w3, w2 + orr w3, w3, w0 + rev w2, w3 + str w2, [x1, #DCFG_BRR_OFFSET] + isb + + /* send event */ + sev + isb + ret + + +/* + * part of CPU_ON + * this function restarts a core shutdown via _soc_core_entr_off + * in: x0 = core mask lsb (of the target cpu) + * out: x0 == 0, on success + * x0 != 0, on failure + * uses x0 ~ x5 + */ +_soc_core_restart: + mov x5, x30 + mov x3, x0 + + /* x3 = core mask lsb */ + bl _getGICD_BaseAddr + mov x4, x0 + + /* x4 = GICD_BASE_ADDR */ + /* enable forwarding of group 0 interrupts by setting GICD_CTLR[0] = 1 */ + ldr w1, [x4, #GICD_CTLR_OFFSET] + orr w1, w1, #GICD_CTLR_EN_GRP0 + str w1, [x4, #GICD_CTLR_OFFSET] + dsb sy + isb + + /* + * fire SGI by writing to GICD_SGIR the following values: + * [25:24] = 0x0 (forward interrupt to the CPU interfaces specified in CPUTargetList field) + * [23:16] = core mask lsb[7:0] (forward interrupt to target cpu) + * [15] = 0 (forward SGI only if it is configured as group 0 interrupt) + * [3:0] = 0xF (interrupt ID = 15) + */ + lsl w1, w3, #16 + orr w1, w1, #0xF + str w1, [x4, #GICD_SGIR_OFFSET] + dsb sy + isb + + /* load '0' on success */ + mov x0, xzr + + mov x30, x5 + ret + +/* + * this function determines if a core is disabled via COREDISR + * in: w0 = core_mask_lsb + * out: w0 = 0, core not disabled + * w0 != 0, core disabled + * uses x0, x1, x2 + */ +_soc_ck_disabled: + + /* get base addr of dcfg block */ + ldr x1, =NXP_DCFG_ADDR + + /* read COREDISR */ + ldr w1, [x1, #DCFG_COREDISR_OFFSET] + rev w2, w1 + + /* test core bit */ + and w0, w2, w0 + ret + +/* + * this function resets the system via SoC-specific methods + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +_soc_sys_reset: + + ldr x2, =NXP_DCFG_ADDR + + /* make sure the mask is cleared in the reset request mask register */ + mov w1, wzr + str w1, [x2, #DCFG_RSTRQMR1_OFFSET] + + /* x2 = NXP_DCFG_ADDR */ + + /* set the reset request */ + ldr w1, =RSTCR_RESET_REQ + ldr x3, =DCFG_RSTCR_OFFSET + rev w0, w1 + str w0, [x2, x3] + + /* x2 = NXP_DCFG_ADDR */ + /* x3 = DCFG_RSTCR_OFFSET */ + + /* just in case this address range is mapped as cacheable, + * flush the write out of the dcaches */ + add x3, x2, x3 + dc cvac, x3 + dsb st + isb + + /* Note: this function does not return */ +1: + wfi + b 1b + + +/* + * part of SYSTEM_OFF + * this function turns off the SoC clocks + * Note: this function is not intended to return, and the only allowable + * recovery is POR + * in: none + * out: none + * uses x0 ~ x8 + */ +_soc_sys_off: + + /* mask interrupts at the core */ + mrs x1, DAIF + mov x0, #DAIF_SET_MASK + orr x0, x1, x0 + msr DAIF, x0 + + /* disable icache, dcache, mmu @ EL1 */ + mov x1, #SCTLR_I_C_M_MASK + mrs x0, sctlr_el1 + bic x0, x0, x1 + msr sctlr_el1, x0 + + /* disable dcache for EL3 */ + mrs x1, SCTLR_EL3 + bic x1, x1, #SCTLR_C_MASK + /* make sure icache is enabled */ + orr x1, x1, #SCTLR_I_MASK + msr SCTLR_EL3, x1 + isb + + /* set WFIL2_EN in SCFG_COREPMCR */ + ldr x0, =SCFG_COREPMCR_OFFSET + ldr x1, =COREPMCR_WFIL2 + bl write_reg_scfg + + /* set OVRD_EN in RCPM2_POWMGTDCR */ + ldr x0, =RCPM2_POWMGTDCR_OFFSET + ldr x1, =POWMGTDCR_OVRD_EN + bl write_reg_rcpm2 + + /* read IPPDEXPCR0 @ RCPM_IPPDEXPCR0 */ + ldr x0, =RCPM_IPPDEXPCR0_OFFSET + bl read_reg_rcpm + mov x7, x0 + + /* build an override mask for IPSTPCR4/IPSTPACK4/DEVDISR5 */ + mov x5, xzr + ldr x6, =IPPDEXPCR_MASK2 + and x6, x6, x7 + cbz x6, 1f + + /* x5 = override mask + * x6 = IPPDEXPCR bits for DEVDISR5 + * x7 = IPPDEXPCR */ + + /* get the overrides */ + orr x4, x5, #DEVDISR5_I2C_1 + tst x6, #IPPDEXPCR_I2C1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_LPUART1 + tst x6, #IPPDEXPCR_LPUART1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_FLX_TMR + tst x6, #IPPDEXPCR_FLX_TMR1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_OCRAM1 + tst x6, #IPPDEXPCR_OCRAM1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_GPIO + tst x6, #IPPDEXPCR_GPIO1 + csel x5, x5, x4, EQ +1: + /* store the DEVDISR5 override mask */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + str w5, [x2, #DEVDISR5_MASK_OFFSET] + + /* build an override mask for IPSTPCR1/IPSTPACK1/DEVDISR2 */ + mov x5, xzr + ldr x6, =IPPDEXPCR_MASK1 + and x6, x6, x7 + cbz x6, 2f + + /* x5 = override mask */ + /* x6 = IPPDEXPCR bits for DEVDISR2 */ + + /* get the overrides */ + orr x4, x5, #DEVDISR2_FMAN1_MAC1 + tst x6, #IPPDEXPCR_MAC1_1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC2 + tst x6, #IPPDEXPCR_MAC1_2 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC3 + tst x6, #IPPDEXPCR_MAC1_3 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC4 + tst x6, #IPPDEXPCR_MAC1_4 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC5 + tst x6, #IPPDEXPCR_MAC1_5 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC6 + tst x6, #IPPDEXPCR_MAC1_6 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC9 + tst x6, #IPPDEXPCR_MAC1_9 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1 + tst x6, #IPPDEXPCR_FM1 + csel x5, x5, x4, EQ + +2: + /* store the DEVDISR2 override mask */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + str w5, [x2, #DEVDISR2_MASK_OFFSET] + + /* x5 = DEVDISR2 override mask */ + + /* write IPSTPCR0 - no overrides */ + ldr x0, =RCPM2_IPSTPCR0_OFFSET + ldr x1, =IPSTPCR0_VALUE + bl write_reg_rcpm2 + + /* x5 = DEVDISR2 override mask */ + + /* write IPSTPCR1 - overrides possible */ + ldr x0, =RCPM2_IPSTPCR1_OFFSET + ldr x1, =IPSTPCR1_VALUE + bic x1, x1, x5 + bl write_reg_rcpm2 + + /* write IPSTPCR2 - no overrides */ + ldr x0, =RCPM2_IPSTPCR2_OFFSET + ldr x1, =IPSTPCR2_VALUE + bl write_reg_rcpm2 + + /* write IPSTPCR3 - no overrides */ + ldr x0, =RCPM2_IPSTPCR3_OFFSET + ldr x1, =IPSTPCR3_VALUE + bl write_reg_rcpm2 + + /* write IPSTPCR4 - overrides possible */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + ldr w6, [x2, #DEVDISR5_MASK_OFFSET] + ldr x0, =RCPM2_IPSTPCR4_OFFSET + ldr x1, =IPSTPCR4_VALUE + bic x1, x1, x6 + bl write_reg_rcpm2 + + /* x5 = DEVDISR2 override mask */ + /* x6 = DEVDISR5 override mask */ + + /* poll on IPSTPACK0 */ + ldr x3, =RCPM2_IPSTPACKR0_OFFSET + ldr x4, =IPSTPCR0_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +3: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 14f + sub x7, x7, #1 + cbnz x7, 3b + +14: + /* poll on IPSTPACK1 */ + ldr x3, =IPSTPCR1_VALUE + ldr x7, =IPSTPACK_RETRY_CNT + bic x4, x3, x5 + ldr x3, =RCPM2_IPSTPACKR1_OFFSET +4: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 15f + sub x7, x7, #1 + cbnz x7, 4b + +15: + /* poll on IPSTPACK2 */ + ldr x3, =RCPM2_IPSTPACKR2_OFFSET + ldr x4, =IPSTPCR2_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +5: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 16f + sub x7, x7, #1 + cbnz x7, 5b + +16: + /* poll on IPSTPACK3 */ + ldr x3, =RCPM2_IPSTPACKR3_OFFSET + ldr x4, =IPSTPCR3_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +6: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 17f + sub x7, x7, #1 + cbnz x7, 6b + +17: + /* poll on IPSTPACK4 */ + ldr x3, =IPSTPCR4_VALUE + ldr x7, =IPSTPACK_RETRY_CNT + bic x4, x3, x6 + ldr x3, =RCPM2_IPSTPACKR4_OFFSET +7: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 18f + sub x7, x7, #1 + cbnz x7, 7b + +18: + ldr x7, =BC_PSCI_BASE + add x7, x7, #AUX_01_DATA + + /* x5 = DEVDISR2 override mask + * x6 = DEVDISR5 override mask + * x7 = [soc_data_area] */ + + /* DEVDISR1 - load new value */ + mov x0, #DCFG_DEVDISR1_OFFSET + bl read_reg_dcfg + mov x0, #DCFG_DEVDISR1_OFFSET + ldr x1, =DEVDISR1_VALUE + bl write_reg_dcfg + + /* DEVDISR2 - load new value */ + mov x0, #DCFG_DEVDISR2_OFFSET + bl read_reg_dcfg + mov x0, #DCFG_DEVDISR2_OFFSET + ldr x1, =DEVDISR2_VALUE + bic x1, x1, x5 + bl write_reg_dcfg + + /* x6 = DEVDISR5 override mask */ + /* x7 = [soc_data_area] */ + + /* DEVDISR3 - load new value */ + mov x0, #DCFG_DEVDISR3_OFFSET + bl read_reg_dcfg + mov x0, #DCFG_DEVDISR3_OFFSET + ldr x1, =DEVDISR3_VALUE + bl write_reg_dcfg + + /* DEVDISR4 - load new value */ + mov x0, #DCFG_DEVDISR4_OFFSET + bl read_reg_dcfg + mov x0, #DCFG_DEVDISR4_OFFSET + ldr x1, =DEVDISR4_VALUE + bl write_reg_dcfg + + /* DEVDISR5 - load new value */ + mov x0, #DCFG_DEVDISR5_OFFSET + bl read_reg_dcfg + mov x0, #DCFG_DEVDISR5_OFFSET + ldr x1, =DEVDISR5_VALUE + bic x1, x1, x6 + bl write_reg_dcfg + + /* x7 = [soc_data_area] */ + + /* disable data prefetch */ + mrs x0, CPUACTLR_EL1 + bic x0, x0, #CPUACTLR_L1PCTL_MASK + msr CPUACTLR_EL1, x0 + + /* x6 = DEVDISR5 override mask */ + + /* setup registers for cache-only execution */ + ldr x5, =IPSTPCR4_VALUE + bic x5, x5, x6 + mov x6, #DDR_CNTRL_BASE_ADDR + mov x7, #DCSR_RCPM2_BASE + mov x8, #NXP_DCFG_ADDR + dsb sy + isb + + /* set the DLL_LOCK cycle count */ + ldr w1, [x6, #DDR_TIMING_CFG_4_OFFSET] + rev w2, w1 + bic w2, w2, #DLL_LOCK_MASK + orr w2, w2, #DLL_LOCK_VALUE + rev w1, w2 + str w1, [x6, #DDR_TIMING_CFG_4_OFFSET] + + /* x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK) + * x6 = DDR_CNTRL_BASE_ADDR + * x7 = DCSR_RCPM2_BASE + * x8 = NXP_DCFG_ADDR */ + + /* enter the cache-only sequence - there is no return */ + b final_shutdown + + +/* + * part of CPU_OFF + * this function programs SoC & GIC registers in preparation for shutting down + * the core + * in: x0 = core mask lsb + * out: none + * uses x0 ~ x7 + */ +_soc_core_prep_off: + mov x7, x30 + mov x6, x0 + + /* make sure the smpen bit is set */ + mrs x2, CORTEX_A53_ECTLR_EL1 + orr x2, x2, #CPUECTLR_SMPEN_MASK + msr CORTEX_A53_ECTLR_EL1, x2 + isb + + /* configure the cpu interface */ + + /* disable signaling of ints */ + bl _getGICC_BaseAddr // 0-1 + mov x4, x0 + + ldr w3, [x4, #GICC_CTLR_OFFSET] + bic w3, w3, #GICC_CTLR_EN_GRP0 + bic w3, w3, #GICC_CTLR_EN_GRP1 + str w3, [x4, #GICC_CTLR_OFFSET] + dsb sy + isb + + /* + * x3 = GICC_CTRL + * x4 = GICC_BASE_ADDR + * x6 = core mask + */ + + /* set the priority filter */ + ldr w2, [x4, #GICC_PMR_OFFSET] + orr w2, w2, #GICC_PMR_FILTER + str w2, [x4, #GICC_PMR_OFFSET] + + /* setup GICC_CTLR */ + bic w3, w3, #GICC_CTLR_ACKCTL_MASK + orr w3, w3, #GICC_CTLR_FIQ_EN_MASK + orr w3, w3, #GICC_CTLR_EOImodeS_MASK + orr w3, w3, #GICC_CTLR_CBPR_MASK + str w3, [x4, #GICC_CTLR_OFFSET] + + /* x3 = GICC_CTRL */ + /* x4 = GICC_BASE_ADDR */ + + /* setup the banked-per-core GICD registers */ + bl _getGICD_BaseAddr + + /* + * x0 = GICD_BASE_ADDR + * x3 = GICC_CTRL + * x4 = GICC_BASE_ADDR + * x6 = core mask + */ + + /* define SGI15 as Grp0 */ + ldr w2, [x0, #GICD_IGROUPR0_OFFSET] + bic w2, w2, #GICD_IGROUP0_SGI15 + str w2, [x0, #GICD_IGROUPR0_OFFSET] + + /* set priority of SGI 15 to highest... */ + ldr w2, [x0, #GICD_IPRIORITYR3_OFFSET] + bic w2, w2, #GICD_IPRIORITY_SGI15_MASK + str w2, [x0, #GICD_IPRIORITYR3_OFFSET] + + /* enable SGI 15 */ + ldr w2, [x0, #GICD_ISENABLER0_OFFSET] + orr w2, w2, #GICD_ISENABLE0_SGI15 + str w2, [x0, #GICD_ISENABLER0_OFFSET] + + /* enable the cpu interface */ + orr w3, w3, #GICC_CTLR_EN_GRP0 + str w3, [x4, #GICC_CTLR_OFFSET] + + /* x0 = GICD_BASE_ADDR + * x6 = core mask */ + + /* clear any pending SGIs */ + add x0, x0, #GICD_CPENDSGIR3_OFFSET + ldr x2, =GICD_CPENDSGIR_CLR_MASK + str w2, [x0] + + dsb sy + isb + mov x30, x7 + ret + +/* + * part of CPU_OFF + * this function performs the final steps to shutdown the core + * in: x0 = core mask lsb + * out: none + * uses x0 ~ x5 + */ +_soc_core_entr_off: + mov x5, x30 + mov x4, x0 + + bl _getGICD_BaseAddr + mov x3, x0 + + /* x3 = GICD_BASE_ADDR */ + /* x4 = core mask (lsb) */ + +3: + /* enter low-power state by executing wfi */ + wfi + + /* x3 = GICD_BASE_ADDR */ + /* x4 = core mask (lsb) */ + + /* see if we got hit by SGI 15 */ + add x0, x3, #GICD_SPENDSGIR3_OFFSET + ldr w2, [x0] + and w2, w2, #GICD_SPENDSGIR3_SGI15_MASK + cbz w2, 4f + + /* clear the pending SGI */ + ldr x2, =GICD_CPENDSGIR_CLR_MASK + add x0, x3, #GICD_CPENDSGIR3_OFFSET + str w2, [x0] +4: + /* check if core has been turned on */ + mov x0, x4 + bl _getCoreState + + /* x0 = core state */ + cmp x0, #CORE_WAKEUP + b.ne 3b + + /* if we get here, then we have exited the wfi */ + dsb sy + isb + mov x30, x5 + ret + +/* + * part of CPU_OFF + * this function starts the process of starting a core back up + * in: x0 = core mask lsb + * out: none + * uses x0 ~ x5 + */ +_soc_core_exit_off: + mov x5, x30 + mov x4, x0 + + /* x4 = core mask */ + + bl _getGICC_BaseAddr + mov x2, x0 + + /* read GICC_IAR */ + ldr w0, [x2, #GICC_IAR_OFFSET] + + /* write GICC_EIOR - signal end-of-interrupt */ + str w0, [x2, #GICC_EOIR_OFFSET] + + /* write GICC_DIR - disable interrupt */ + str w0, [x2, #GICC_DIR_OFFSET] + + /* x2 = GICC_BASE_ADDR */ + + /* disable signaling of grp0 ints */ + ldr w1, [x2, #GICC_CTLR_OFFSET] + bic w1, w1, #GICC_CTLR_EN_GRP0 + str w1, [x2, #GICC_CTLR_OFFSET] + + dsb sy + isb + mov x30, x5 + ret + +/* + * this function loads a 64-bit execution address of the core in the soc registers + * BOOTLOCPTRL/H + * in: x0, 64-bit address to write to BOOTLOCPTRL/H + * uses x0, x1, x2, x3 + */ +_soc_set_start_addr: + /* get the 64-bit base address of the scfg block */ + ldr x2, =NXP_SCFG_ADDR + + /* write the 32-bit BOOTLOCPTRL register (offset 0x604 in the scfg block) */ + mov x1, x0 + rev w3, w1 + str w3, [x2, #SCFG_BOOTLOCPTRL_OFFSET] + + /* write the 32-bit BOOTLOCPTRH register (offset 0x600 in the scfg block) */ + lsr x1, x0, #32 + rev w3, w1 + str w3, [x2, #SCFG_BOOTLOCPTRH_OFFSET] + ret + +/* + * part of CPU_SUSPEND + * this function puts the calling core into standby state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +_soc_core_entr_stdby: + dsb sy + isb + wfi + + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_core_prep_stdby: + /* clear CORTEX_A53_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A53_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_core_exit_stdby: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_core_prep_pwrdn: + /* make sure the smp bit is set */ + mrs x1, CORTEX_A53_ECTLR_EL1 + orr x1, x1, #CPUECTLR_SMPEN_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + isb + + ret + +/* + * part of CPU_SUSPEND + * this function puts the calling core into a power-down state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +_soc_core_entr_pwrdn: + dsb sy + isb + wfi + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after power-down + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_core_exit_pwrdn: + ret + + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_clstr_prep_stdby: + /* clear CORTEX_A53_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A53_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_clstr_exit_stdby: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_clstr_prep_pwrdn: + /* make sure the smp bit is set */ + mrs x1, CORTEX_A53_ECTLR_EL1 + orr x1, x1, #CPUECTLR_SMPEN_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + isb + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after power-down + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_clstr_exit_pwrdn: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_sys_prep_stdby: + /* clear CORTEX_A53_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A53_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_sys_exit_stdby: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to + * suspend-to-power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4 + */ +_soc_sys_prep_pwrdn: + mov x4, x30 + /* make sure the smp bit is set */ + mrs x1, CORTEX_A53_ECTLR_EL1 + orr x1, x1, #CPUECTLR_SMPEN_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + isb + + /* set WFIL2_EN in SCFG_COREPMCR */ + ldr x0, =SCFG_COREPMCR_OFFSET + ldr x1, =COREPMCR_WFIL2 + bl write_reg_scfg // 0-3 + + /* set OVRD_EN in RCPM2_POWMGTDCR */ + ldr x0, =RCPM2_POWMGTDCR_OFFSET + ldr x1, =POWMGTDCR_OVRD_EN + bl write_reg_rcpm2 // 0-3 + + mov x30, x4 + ret +/* + * part of CPU_SUSPEND + * this function puts the calling core, and potentially the soc, into a + * low-power state + * in: x0 = core mask lsb + * out: x0 = 0, success + * x0 < 0, failure + * uses x0 ~ x9 + */ +_soc_sys_pwrdn_wfi: + mov x18, x30 + + /* read IPPDEXPCR0 @ RCPM_IPPDEXPCR0 */ + ldr x0, =RCPM_IPPDEXPCR0_OFFSET + bl read_reg_rcpm + mov x7, x0 + + /* build an override mask for IPSTPCR4/IPSTPACK4/DEVDISR5 */ + mov x5, xzr + ldr x6, =IPPDEXPCR_MASK2 + and x6, x6, x7 + cbz x6, 1f + + /* x5 = override mask + * x6 = IPPDEXPCR bits for DEVDISR5 + * x7 = IPPDEXPCR */ + + /* get the overrides */ + orr x4, x5, #DEVDISR5_I2C_1 + tst x6, #IPPDEXPCR_I2C1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_LPUART1 + tst x6, #IPPDEXPCR_LPUART1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_FLX_TMR + tst x6, #IPPDEXPCR_FLX_TMR1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_OCRAM1 + tst x6, #IPPDEXPCR_OCRAM1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_GPIO + tst x6, #IPPDEXPCR_GPIO1 + csel x5, x5, x4, EQ +1: + /* store the DEVDISR5 override mask */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + str w5, [x2, #DEVDISR5_MASK_OFFSET] + + /* build an override mask for IPSTPCR1/IPSTPACK1/DEVDISR2 */ + mov x5, xzr + ldr x6, =IPPDEXPCR_MASK1 + and x6, x6, x7 + cbz x6, 2f + + /* x5 = override mask */ + /* x6 = IPPDEXPCR bits for DEVDISR2 */ + + /* get the overrides */ + orr x4, x5, #DEVDISR2_FMAN1_MAC1 + tst x6, #IPPDEXPCR_MAC1_1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC2 + tst x6, #IPPDEXPCR_MAC1_2 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC3 + tst x6, #IPPDEXPCR_MAC1_3 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC4 + tst x6, #IPPDEXPCR_MAC1_4 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC5 + tst x6, #IPPDEXPCR_MAC1_5 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC6 + tst x6, #IPPDEXPCR_MAC1_6 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC9 + tst x6, #IPPDEXPCR_MAC1_9 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1 + tst x6, #IPPDEXPCR_FM1 + csel x5, x5, x4, EQ + +2: + /* store the DEVDISR2 override mask */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + str w5, [x2, #DEVDISR2_MASK_OFFSET] + + /* x5 = DEVDISR2 override mask */ + + /* write IPSTPCR0 - no overrides */ + ldr x0, =RCPM2_IPSTPCR0_OFFSET + ldr x1, =IPSTPCR0_VALUE + bl write_reg_rcpm2 + + /* x5 = DEVDISR2 override mask */ + + /* write IPSTPCR1 - overrides possible */ + ldr x0, =RCPM2_IPSTPCR1_OFFSET + ldr x1, =IPSTPCR1_VALUE + bic x1, x1, x5 + bl write_reg_rcpm2 + + /* write IPSTPCR2 - no overrides */ + ldr x0, =RCPM2_IPSTPCR2_OFFSET + ldr x1, =IPSTPCR2_VALUE + bl write_reg_rcpm2 + + /* write IPSTPCR3 - no overrides */ + ldr x0, =RCPM2_IPSTPCR3_OFFSET + ldr x1, =IPSTPCR3_VALUE + bl write_reg_rcpm2 + + /* write IPSTPCR4 - overrides possible */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + ldr w6, [x2, #DEVDISR5_MASK_OFFSET] + ldr x0, =RCPM2_IPSTPCR4_OFFSET + ldr x1, =IPSTPCR4_VALUE + bic x1, x1, x6 + bl write_reg_rcpm2 + + /* x5 = DEVDISR2 override mask */ + /* x6 = DEVDISR5 override mask */ + + /* poll on IPSTPACK0 */ + ldr x3, =RCPM2_IPSTPACKR0_OFFSET + ldr x4, =IPSTPCR0_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +3: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 14f + sub x7, x7, #1 + cbnz x7, 3b + +14: + /* poll on IPSTPACK1 */ + ldr x3, =IPSTPCR1_VALUE + ldr x7, =IPSTPACK_RETRY_CNT + bic x4, x3, x5 + ldr x3, =RCPM2_IPSTPACKR1_OFFSET +4: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 15f + sub x7, x7, #1 + cbnz x7, 4b + +15: + /* poll on IPSTPACK2 */ + ldr x3, =RCPM2_IPSTPACKR2_OFFSET + ldr x4, =IPSTPCR2_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +5: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 16f + sub x7, x7, #1 + cbnz x7, 5b + +16: + /* poll on IPSTPACK3 */ + ldr x3, =RCPM2_IPSTPACKR3_OFFSET + ldr x4, =IPSTPCR3_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +6: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 17f + sub x7, x7, #1 + cbnz x7, 6b + +17: + /* poll on IPSTPACK4 */ + ldr x3, =IPSTPCR4_VALUE + ldr x7, =IPSTPACK_RETRY_CNT + bic x4, x3, x6 + ldr x3, =RCPM2_IPSTPACKR4_OFFSET +7: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 18f + sub x7, x7, #1 + cbnz x7, 7b + +18: + ldr x7, =BC_PSCI_BASE + add x7, x7, #AUX_01_DATA + + /* x5 = DEVDISR2 override mask + * x6 = DEVDISR5 override mask + * x7 = [soc_data_area] */ + + /* save DEVDISR1 and load new value */ + mov x0, #DCFG_DEVDISR1_OFFSET + bl read_reg_dcfg + mov w13, w0 + mov x0, #DCFG_DEVDISR1_OFFSET + ldr x1, =DEVDISR1_VALUE + bl write_reg_dcfg + + /* save DEVDISR2 and load new value */ + mov x0, #DCFG_DEVDISR2_OFFSET + bl read_reg_dcfg + mov w14, w0 + mov x0, #DCFG_DEVDISR2_OFFSET + ldr x1, =DEVDISR2_VALUE + bic x1, x1, x5 + bl write_reg_dcfg + + /* x6 = DEVDISR5 override mask */ + /* x7 = [soc_data_area] */ + + /* save DEVDISR3 and load new value */ + mov x0, #DCFG_DEVDISR3_OFFSET + bl read_reg_dcfg + mov w15, w0 + mov x0, #DCFG_DEVDISR3_OFFSET + ldr x1, =DEVDISR3_VALUE + bl write_reg_dcfg + + /* save DEVDISR4 and load new value */ + mov x0, #DCFG_DEVDISR4_OFFSET + bl read_reg_dcfg + mov w16, w0 + mov x0, #DCFG_DEVDISR4_OFFSET + ldr x1, =DEVDISR4_VALUE + bl write_reg_dcfg + + /* save DEVDISR5 and load new value */ + mov x0, #DCFG_DEVDISR5_OFFSET + bl read_reg_dcfg + mov w17, w0 + mov x0, #DCFG_DEVDISR5_OFFSET + ldr x1, =DEVDISR5_VALUE + bic x1, x1, x6 + bl write_reg_dcfg + + /* x7 = [soc_data_area] */ + + /* save cpuactlr and disable data prefetch */ + mrs x0, CPUACTLR_EL1 + str w0, [x7, #CPUACTLR_DATA_OFFSET] + bic x0, x0, #CPUACTLR_L1PCTL_MASK + msr CPUACTLR_EL1, x0 + + /* x6 = DEVDISR5 override mask */ + + /* setup registers for cache-only execution */ + ldr x5, =IPSTPCR4_VALUE + bic x5, x5, x6 + mov x6, #DDR_CNTRL_BASE_ADDR + mov x7, #DCSR_RCPM2_BASE + mov x8, #NXP_DCFG_ADDR + dsb sy + isb + + /* set the DLL_LOCK cycle count */ + ldr w1, [x6, #DDR_TIMING_CFG_4_OFFSET] + rev w2, w1 + bic w2, w2, #DLL_LOCK_MASK + orr w2, w2, #DLL_LOCK_VALUE + rev w1, w2 + str w1, [x6, #DDR_TIMING_CFG_4_OFFSET] + + /* + * x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK) + * x6 = DDR_CNTRL_BASE_ADDR + * x7 = DCSR_RCPM2_BASE + * x8 = NXP_DCFG_ADDR + * w13 = DEVDISR1 saved value + * w14 = DEVDISR2 saved value + * w15 = DEVDISR3 saved value + * w16 = DEVDISR4 saved value + * w17 = DEVDISR5 saved value + */ + + /* enter the cache-only sequence */ + mov x9, #CORE_RESTARTABLE + bl final_pwrdown + + /* when we are here, the core has come out of wfi and the SoC is back up */ + + mov x30, x18 + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_sys_exit_pwrdn: + /* clear POWMGTDCR */ + mov x1, #DCSR_RCPM2_BASE + str wzr, [x1, #RCPM2_POWMGTDCR_OFFSET] + + /* clear WFIL2_EN in SCFG_COREPMCR */ + mov x1, #NXP_SCFG_ADDR + str wzr, [x1, #SCFG_COREPMCR_OFFSET] + + ret + +/* + * write a register in the SCFG block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2, x3 + */ +write_reg_scfg: + ldr x2, =NXP_SCFG_ADDR + /* swap for BE */ + rev w3, w1 + str w3, [x2, x0] + ret +/* + * read a register in the SCFG block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +read_reg_scfg: + ldr x2, =NXP_SCFG_ADDR + ldr w1, [x2, x0] + /* swap for BE */ + rev w0, w1 + ret + +/* + * write a register in the DCFG block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2, x3 + */ +write_reg_dcfg: + ldr x2, =NXP_DCFG_ADDR + /* swap for BE */ + rev w3, w1 + str w3, [x2, x0] + ret + +/* + * read a register in the DCFG block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +read_reg_dcfg: + ldr x2, =NXP_DCFG_ADDR + ldr w1, [x2, x0] + /* swap for BE */ + rev w0, w1 + ret + +/* + * write a register in the RCPM block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2, x3 + */ +write_reg_rcpm: + ldr x2, =NXP_RCPM_ADDR + /* swap for BE */ + rev w3, w1 + str w3, [x2, x0] + ret + +/* + * read a register in the RCPM block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +read_reg_rcpm: + ldr x2, =NXP_RCPM_ADDR + ldr w1, [x2, x0] + /* swap for BE */ + rev w0, w1 + ret + +/* + * write a register in the DCSR-RCPM2 block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2, x3 + */ +write_reg_rcpm2: + ldr x2, =DCSR_RCPM2_BASE + /* swap for BE */ + rev w3, w1 + str w3, [x2, x0] + ret + +/* + * read a register in the DCSR-RCPM2 block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +read_reg_rcpm2: + ldr x2, =DCSR_RCPM2_BASE + ldr w1, [x2, x0] + /* swap for BE */ + rev w0, w1 + ret + +/* + * this function returns the base address of the gic distributor + * in: none + * out: x0 = base address of gic distributor + * uses x0, x1 + */ +_getGICD_BaseAddr: + /* read SVR and get the SoC version */ + mov x0, #NXP_DCFG_ADDR + ldr w1, [x0, #DCFG_SVR_OFFSET] + rev w0, w1 + + /* x0 = svr */ + and w0, w0, #SVR_MIN_VER_MASK + cmp w0, #SVR_MINOR_VER_0 + b.ne 8f + + /* load the gic base addresses for rev 1.0 parts */ + ldr x0, =NXP_GICD_4K_ADDR + b 10f +8: + /* for rev 1.1 and later parts, the GIC base addresses */ + /* can be at 4k or 64k offsets */ + + /* read the scfg reg GIC400_ADDR_ALIGN */ + mov x0, #NXP_SCFG_ADDR + ldr w1, [x0, #SCFG_GIC400_ADDR_ALIGN_OFFSET] + rev w0, w1 + + /* x0 = GIC400_ADDR_ALIGN value */ + and x0, x0, #SCFG_GIC400_ADDR_ALIGN_4KMODE_MASK + mov x1, #SCFG_GIC400_ADDR_ALIGN_4KMODE_EN + cmp x0, x1 + b.ne 9f + + /* load the base addresses for 4k offsets */ + ldr x0, =NXP_GICD_4K_ADDR + b 10f +9: + /* load the base address for 64k offsets */ + ldr x0, =NXP_GICD_64K_ADDR +10: + ret + +/* + * this function returns the base address of the gic distributor + * in: none + * out: x0 = base address of gic controller + * uses x0, x1 + */ +_getGICC_BaseAddr: + /* read SVR and get the SoC version */ + mov x0, #NXP_DCFG_ADDR + ldr w1, [x0, #DCFG_SVR_OFFSET] + rev w0, w1 + + /* x0 = svr */ + and w0, w0, #SVR_MIN_VER_MASK + cmp w0, #SVR_MINOR_VER_0 + b.ne 8f + + /* load the gic base addresses for rev 1.0 parts */ + ldr x0, =NXP_GICC_4K_ADDR + b 10f +8: + /* for rev 1.1 and later parts, the GIC base addresses */ + /* can be at 4k or 64k offsets */ + + /* read the scfg reg GIC400_ADDR_ALIGN */ + mov x0, #NXP_SCFG_ADDR + ldr w1, [x0, #SCFG_GIC400_ADDR_ALIGN_OFFSET] + rev w0, w1 + + /* x0 = GIC400_ADDR_ALIGN value */ + and x0, x0, #SCFG_GIC400_ADDR_ALIGN_4KMODE_MASK + mov x1, #SCFG_GIC400_ADDR_ALIGN_4KMODE_EN + cmp x0, x1 + b.ne 9f + + /* load the base addresses for 4k offsets */ + ldr x0, =NXP_GICC_4K_ADDR + b 10f +9: + /* load the base address for 64k offsets */ + ldr x0, =NXP_GICC_64K_ADDR +10: + ret + +/* + * this function will pwrdown ddr and the final core - it will do this + * by loading itself into the icache and then executing from there + * in: x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK) + * x6 = DDR_CNTRL_BASE_ADDR + * x7 = DCSR_RCPM2_BASE + * x8 = NXP_DCFG_ADDR + * x9 = 0, restartable + * = 1, non-restartable + * w13 = DEVDISR1 saved value + * w14 = DEVDISR2 saved value + * w15 = DEVDISR3 saved value + * w16 = DEVDISR4 saved value + * w17 = DEVDISR5 saved value + * out: none + * uses x0 ~ x9 + */ + +/* 4Kb aligned */ +.align 12 +final_pwrdown: + mov x0, xzr + b touch_line_0 +start_line_0: + mov x0, #1 + mov x2, #DDR_SDRAM_CFG_2_FRCSR /* put ddr in self refresh - start */ + ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + rev w4, w3 + orr w4, w4, w2 + rev w3, w4 + str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] /* put ddr in self refresh - end */ + orr w3, w5, #DEVDISR5_MEM /* quiesce ddr clocks - start */ + rev w4, w3 + str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* quiesce ddr clocks - end */ + + mov w3, #DEVDISR5_MEM + rev w3, w3 /* polling mask */ + mov x2, #DDR_SLEEP_RETRY_CNT /* poll on ipstpack4 - start */ +touch_line_0: + cbz x0, touch_line_1 + +start_line_1: + ldr w1, [x7, #RCPM2_IPSTPACKR4_OFFSET] + tst w1, w3 + b.ne 1f + subs x2, x2, #1 + b.gt start_line_1 /* poll on ipstpack4 - end */ + + /* if we get here, we have a timeout err */ + rev w4, w5 + str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* re-enable ddr clks interface */ + mov x0, #ERROR_DDR_SLEEP /* load error code */ + b 2f +1: + str w4, [x8, #DCFG_DEVDISR5_OFFSET] /* disable ddr cntrlr clk in devdisr5 */ +5: + wfi /* stop the final core */ + + cbnz x9, 5b /* if non-restartable, keep in wfi */ + rev w4, w5 + str w4, [x8, #DCFG_DEVDISR5_OFFSET] /* re-enable ddr in devdisr5 */ + str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* re-enable ddr clk in ipstpcr4 */ +touch_line_1: + cbz x0, touch_line_2 + +start_line_2: + ldr w1, [x7, #RCPM2_IPSTPACKR4_OFFSET] /* poll on ipstpack4 - start */ + tst w1, w3 + b.eq 2f + nop + b start_line_2 /* poll on ipstpack4 - end */ +2: + mov x2, #DDR_SDRAM_CFG_2_FRCSR /* take ddr out-of self refresh - start */ + ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + rev w4, w3 + bic w4, w4, w2 + rev w3, w4 + mov x1, #DDR_SLEEP_RETRY_CNT /* wait for ddr cntrlr clock - start */ +3: + subs x1, x1, #1 + b.gt 3b /* wait for ddr cntrlr clock - end */ + str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] /* take ddr out-of self refresh - end */ + rev w1, w17 +touch_line_2: + cbz x0, touch_line_3 + +start_line_3: + str w1, [x8, #DCFG_DEVDISR5_OFFSET] /* reset devdisr5 */ + rev w1, w16 + str w1, [x8, #DCFG_DEVDISR4_OFFSET] /* reset devdisr4 */ + rev w1, w15 + str w1, [x8, #DCFG_DEVDISR3_OFFSET] /* reset devdisr3 */ + rev w1, w14 + str w1, [x8, #DCFG_DEVDISR2_OFFSET] /* reset devdisr2 */ + rev w1, w13 + str w1, [x8, #DCFG_DEVDISR1_OFFSET] /* reset devdisr1 */ + str wzr, [x7, #RCPM2_IPSTPCR4_OFFSET] /* reset ipstpcr4 */ + str wzr, [x7, #RCPM2_IPSTPCR3_OFFSET] /* reset ipstpcr3 */ + str wzr, [x7, #RCPM2_IPSTPCR2_OFFSET] /* reset ipstpcr2 */ + str wzr, [x7, #RCPM2_IPSTPCR1_OFFSET] /* reset ipstpcr1 */ + str wzr, [x7, #RCPM2_IPSTPCR0_OFFSET] /* reset ipstpcr0 */ + b continue_restart +touch_line_3: + cbz x0, start_line_0 + +/* execute here after ddr is back up */ +continue_restart: + /* + * if x0 = 1, all is well + * if x0 < 1, we had an error + */ + cmp x0, #1 + b.ne 4f + mov x0, #0 +4: + ret + +/* + * Note: there is no return from this function + * this function will shutdown ddr and the final core - it will do this + * by loading itself into the icache and then executing from there + * in: x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK) + * x6 = DDR_CNTRL_BASE_ADDR + * x7 = DCSR_RCPM2_BASE + * x8 = NXP_DCFG_ADDR + * out: none + * uses x0 ~ x8 + */ + +/* 4Kb aligned */ +.align 12 +final_shutdown: + + mov x0, xzr + b touch_line0 +start_line0: + mov x0, #1 + mov x2, #DDR_SDRAM_CFG_2_FRCSR /* put ddr in self refresh - start */ + ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + rev w4, w3 + orr w4, w4, w2 + rev w3, w4 + str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] /* put ddr in self refresh - end */ + orr w3, w5, #DEVDISR5_MEM /* quiesce ddr clocks - start */ + rev w4, w3 + str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* quiesce ddr clocks - end */ + + mov w3, #DEVDISR5_MEM + rev w3, w3 /* polling mask */ + mov x2, #DDR_SLEEP_RETRY_CNT /* poll on ipstpack4 - start */ +touch_line0: + cbz x0, touch_line1 + +start_line1: + ldr w1, [x7, #RCPM2_IPSTPACKR4_OFFSET] + tst w1, w3 + b.ne 1f + subs x2, x2, #1 + b.gt start_line1 /* poll on ipstpack4 - end */ + nop + nop + nop + nop +1: + str w4, [x8, #DCFG_DEVDISR5_OFFSET] /* disable ddr cntrlr clk in devdisr5 */ +5: + wfi /* stop the final core */ + b 5b /* stay here until POR */ + nop + nop + nop +touch_line1: + cbz x0, start_line0 diff --git a/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S b/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S new file mode 100644 index 0000000..bc88886 --- /dev/null +++ b/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S @@ -0,0 +1,70 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> + +#include <platform_def.h> + + .globl plat_secondary_cold_boot_setup + .globl plat_is_my_cpu_primary + .globl plat_reset_handler + .globl platform_mem_init + +func platform_mem1_init + ret +endfunc platform_mem1_init + +func platform_mem_init + ret +endfunc platform_mem_init + +func apply_platform_errata + ret +endfunc apply_platform_errata + +func plat_reset_handler + mov x29, x30 + bl apply_platform_errata + +#if defined(IMAGE_BL31) + ldr x0, =POLICY_SMMU_PAGESZ_64K + cbz x0, 1f + /* Set the SMMU page size in the sACR register */ + bl _set_smmu_pagesz_64 +#endif +1: + mov x30, x29 + ret +endfunc plat_reset_handler + +/* + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + */ +func plat_secondary_cold_boot_setup + /* ls1043a does not do cold boot for secondary CPU */ +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + +/* + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, 0x0 + cset w0, eq + ret +endfunc plat_is_my_cpu_primary diff --git a/plat/nxp/soc-ls1043a/include/ns_access.h b/plat/nxp/soc-ls1043a/include/ns_access.h new file mode 100644 index 0000000..423c454 --- /dev/null +++ b/plat/nxp/soc-ls1043a/include/ns_access.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2015, 2016 Freescale Semiconductor, Inc. + * Copyright 2017-2018, 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NS_ACCESS_H +#define NS_ACCESS_H + +#include <csu.h> + +enum csu_cslx_ind { + CSU_CSLX_PCIE2_IO = 0, + CSU_CSLX_PCIE1_IO, + CSU_CSLX_MG2TPR_IP, + CSU_CSLX_IFC_MEM, + CSU_CSLX_OCRAM, + CSU_CSLX_GIC, + CSU_CSLX_PCIE1, + CSU_CSLX_OCRAM2, + CSU_CSLX_QSPI_MEM, + CSU_CSLX_PCIE2, + CSU_CSLX_SATA, + CSU_CSLX_USB1, + CSU_CSLX_QM_BM_SWPORTAL, + CSU_CSLX_PCIE3 = 16, + CSU_CSLX_PCIE3_IO, + CSU_CSLX_USB3 = 20, + CSU_CSLX_USB2, + CSU_CSLX_PFE = 23, + CSU_CSLX_SERDES = 32, + CSU_CSLX_QDMA, + CSU_CSLX_LPUART2, + CSU_CSLX_LPUART1, + CSU_CSLX_LPUART4, + CSU_CSLX_LPUART3, + CSU_CSLX_LPUART6, + CSU_CSLX_LPUART5, + CSU_CSLX_DSPI1 = 41, + CSU_CSLX_QSPI, + CSU_CSLX_ESDHC, + CSU_CSLX_IFC = 45, + CSU_CSLX_I2C1, + CSU_CSLX_USB_2, + CSU_CSLX_I2C3 = 48, + CSU_CSLX_I2C2, + CSU_CSLX_DUART2 = 50, + CSU_CSLX_DUART1, + CSU_CSLX_WDT2, + CSU_CSLX_WDT1, + CSU_CSLX_EDMA, + CSU_CSLX_SYS_CNT, + CSU_CSLX_DMA_MUX2, + CSU_CSLX_DMA_MUX1, + CSU_CSLX_DDR, + CSU_CSLX_QUICC, + CSU_CSLX_DCFG_CCU_RCPM = 60, + CSU_CSLX_SECURE_BOOTROM, + CSU_CSLX_SFP, + CSU_CSLX_TMU, + CSU_CSLX_SECURE_MONITOR, + CSU_CSLX_SCFG, + CSU_CSLX_FM = 66, + CSU_CSLX_SEC5_5, + CSU_CSLX_BM, + CSU_CSLX_QM, + CSU_CSLX_GPIO2 = 70, + CSU_CSLX_GPIO1, + CSU_CSLX_GPIO4, + CSU_CSLX_GPIO3, + CSU_CSLX_PLATFORM_CONT, + CSU_CSLX_CSU, + CSU_CSLX_IIC4 = 77, + CSU_CSLX_WDT4, + CSU_CSLX_WDT3, + CSU_CSLX_ESDHC2 = 80, + CSU_CSLX_WDT5 = 81, + CSU_CSLX_SAI2, + CSU_CSLX_SAI1, + CSU_CSLX_SAI4, + CSU_CSLX_SAI3, + CSU_CSLX_FTM2 = 86, + CSU_CSLX_FTM1, + CSU_CSLX_FTM4, + CSU_CSLX_FTM3, + CSU_CSLX_FTM6 = 90, + CSU_CSLX_FTM5, + CSU_CSLX_FTM8, + CSU_CSLX_FTM7, + CSU_CSLX_DSCR = 121, +}; + +struct csu_ns_dev_st ns_dev[] = { + {CSU_CSLX_PCIE2_IO, CSU_ALL_RW}, + {CSU_CSLX_PCIE1_IO, CSU_ALL_RW}, + {CSU_CSLX_MG2TPR_IP, CSU_ALL_RW}, + {CSU_CSLX_IFC_MEM, CSU_ALL_RW}, + {CSU_CSLX_OCRAM, CSU_S_SUP_RW}, + {CSU_CSLX_GIC, CSU_ALL_RW}, + {CSU_CSLX_PCIE1, CSU_ALL_RW}, + {CSU_CSLX_OCRAM2, CSU_S_SUP_RW}, + {CSU_CSLX_QSPI_MEM, CSU_ALL_RW}, + {CSU_CSLX_PCIE2, CSU_ALL_RW}, + {CSU_CSLX_SATA, CSU_ALL_RW}, + {CSU_CSLX_USB1, CSU_ALL_RW}, + {CSU_CSLX_QM_BM_SWPORTAL, CSU_ALL_RW}, + {CSU_CSLX_PCIE3, CSU_ALL_RW}, + {CSU_CSLX_PCIE3_IO, CSU_ALL_RW}, + {CSU_CSLX_USB3, CSU_ALL_RW}, + {CSU_CSLX_USB2, CSU_ALL_RW}, + {CSU_CSLX_PFE, CSU_ALL_RW}, + {CSU_CSLX_SERDES, CSU_ALL_RW}, + {CSU_CSLX_QDMA, CSU_ALL_RW}, + {CSU_CSLX_LPUART2, CSU_ALL_RW}, + {CSU_CSLX_LPUART1, CSU_ALL_RW}, + {CSU_CSLX_LPUART4, CSU_ALL_RW}, + {CSU_CSLX_LPUART3, CSU_ALL_RW}, + {CSU_CSLX_LPUART6, CSU_ALL_RW}, + {CSU_CSLX_LPUART5, CSU_ALL_RW}, + {CSU_CSLX_DSPI1, CSU_ALL_RW}, + {CSU_CSLX_QSPI, CSU_ALL_RW}, + {CSU_CSLX_ESDHC, CSU_ALL_RW}, + {CSU_CSLX_IFC, CSU_ALL_RW}, + {CSU_CSLX_I2C1, CSU_ALL_RW}, + {CSU_CSLX_USB_2, CSU_ALL_RW}, + {CSU_CSLX_I2C3, CSU_ALL_RW}, + {CSU_CSLX_I2C2, CSU_ALL_RW}, + {CSU_CSLX_DUART2, CSU_ALL_RW}, + {CSU_CSLX_DUART1, CSU_ALL_RW}, + {CSU_CSLX_WDT2, CSU_ALL_RW}, + {CSU_CSLX_WDT1, CSU_ALL_RW}, + {CSU_CSLX_EDMA, CSU_ALL_RW}, + {CSU_CSLX_SYS_CNT, CSU_ALL_RW}, + {CSU_CSLX_DMA_MUX2, CSU_ALL_RW}, + {CSU_CSLX_DMA_MUX1, CSU_ALL_RW}, + {CSU_CSLX_DDR, CSU_ALL_RW}, + {CSU_CSLX_QUICC, CSU_ALL_RW}, + {CSU_CSLX_DCFG_CCU_RCPM, CSU_ALL_RW}, + {CSU_CSLX_SECURE_BOOTROM, CSU_ALL_RW}, + {CSU_CSLX_SFP, CSU_ALL_RW}, + {CSU_CSLX_TMU, CSU_ALL_RW}, + {CSU_CSLX_SECURE_MONITOR, CSU_ALL_RW}, + {CSU_CSLX_SCFG, CSU_ALL_RW}, + {CSU_CSLX_FM, CSU_ALL_RW}, + {CSU_CSLX_SEC5_5, CSU_ALL_RW}, + {CSU_CSLX_BM, CSU_ALL_RW}, + {CSU_CSLX_QM, CSU_ALL_RW}, + {CSU_CSLX_GPIO2, CSU_ALL_RW}, + {CSU_CSLX_GPIO1, CSU_ALL_RW}, + {CSU_CSLX_GPIO4, CSU_ALL_RW}, + {CSU_CSLX_GPIO3, CSU_ALL_RW}, + {CSU_CSLX_PLATFORM_CONT, CSU_ALL_RW}, + {CSU_CSLX_CSU, CSU_ALL_RW}, + {CSU_CSLX_IIC4, CSU_ALL_RW}, + {CSU_CSLX_WDT4, CSU_ALL_RW}, + {CSU_CSLX_WDT3, CSU_ALL_RW}, + {CSU_CSLX_ESDHC2, CSU_ALL_RW}, + {CSU_CSLX_WDT5, CSU_ALL_RW}, + {CSU_CSLX_SAI2, CSU_ALL_RW}, + {CSU_CSLX_SAI1, CSU_ALL_RW}, + {CSU_CSLX_SAI4, CSU_ALL_RW}, + {CSU_CSLX_SAI3, CSU_ALL_RW}, + {CSU_CSLX_FTM2, CSU_ALL_RW}, + {CSU_CSLX_FTM1, CSU_ALL_RW}, + {CSU_CSLX_FTM4, CSU_ALL_RW}, + {CSU_CSLX_FTM3, CSU_ALL_RW}, + {CSU_CSLX_FTM6, CSU_ALL_RW}, + {CSU_CSLX_FTM5, CSU_ALL_RW}, + {CSU_CSLX_FTM8, CSU_ALL_RW}, + {CSU_CSLX_FTM7, CSU_ALL_RW}, + {CSU_CSLX_DSCR, CSU_ALL_RW}, +}; + +#endif /* NS_ACCESS_H */ diff --git a/plat/nxp/soc-ls1043a/include/soc.h b/plat/nxp/soc-ls1043a/include/soc.h new file mode 100644 index 0000000..e018102 --- /dev/null +++ b/plat/nxp/soc-ls1043a/include/soc.h @@ -0,0 +1,234 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOC_H +#define SOC_H + +/* Chassis specific defines - common across SoC's of a particular platform */ +#include "dcfg_lsch2.h" +#include "soc_default_base_addr.h" +#include "soc_default_helper_macros.h" + +/* DDR Regions Info */ +#define NUM_DRAM_REGIONS 3 +#define NXP_DRAM0_ADDR 0x80000000 +#define NXP_DRAM0_MAX_SIZE 0x80000000 /* 2 GB */ + +#define NXP_DRAM1_ADDR 0x880000000 +#define NXP_DRAM1_MAX_SIZE 0x780000000 /* 30 GB */ + +#define NXP_DRAM2_ADDR 0x8800000000 +#define NXP_DRAM2_MAX_SIZE 0x7800000000 /* 480 GB */ +/* DRAM0 Size defined in platform_def.h */ +#define NXP_DRAM0_SIZE PLAT_DEF_DRAM0_SIZE + +/* + * P23: 23 x 23 package + * A: without security + * AE: with security + * SVR Definition (not include major and minor rev) + */ +#define SVR_LS1023A 0x879209 +#define SVR_LS1023AE 0x879208 +#define SVR_LS1023A_P23 0x87920B +#define SVR_LS1023AE_P23 0x87920A +#define SVR_LS1043A 0x879201 +#define SVR_LS1043AE 0x879200 +#define SVR_LS1043A_P23 0x879203 +#define SVR_LS1043AE_P23 0x879202 + +/* Number of cores in platform */ +#define PLATFORM_CORE_COUNT 4 +#define NUMBER_OF_CLUSTERS 1 +#define CORES_PER_CLUSTER 4 + +/* set to 0 if the clusters are not symmetrical */ +#define SYMMETRICAL_CLUSTERS 1 + +/* + * Required LS standard platform porting definitions + * for CCI-400 + */ +#define NXP_CCI_CLUSTER0_SL_IFACE_IX 4 + +/* ls1043 version info for GIC configuration */ +#define REV1_0 0x10 +#define REV1_1 0x11 +#define GIC_ADDR_BIT 31 + +/* Errata */ +#define NXP_ERRATUM_A009663 +#define NXP_ERRATUM_A009942 + +#define NUM_OF_DDRC 1 + +/* Defines required for using XLAT tables from ARM common code */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 40) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 40) + +/* Clock Divisors */ +#define NXP_PLATFORM_CLK_DIVIDER 1 +#define NXP_UART_CLK_DIVIDER 1 + +/* + * Set this switch to 1 if you need to keep the debug block + * clocked during system power-down. + */ +#define DEBUG_ACTIVE 0 + +#define IPPDEXPCR_MAC1_1 0x80000000 // DEVDISR2_FMAN1_MAC1 +#define IPPDEXPCR_MAC1_2 0x40000000 // DEVDISR2_FMAN1_MAC2 +#define IPPDEXPCR_MAC1_3 0x20000000 // DEVDISR2_FMAN1_MAC3 +#define IPPDEXPCR_MAC1_4 0x10000000 // DEVDISR2_FMAN1_MAC4 +#define IPPDEXPCR_MAC1_5 0x08000000 // DEVDISR2_FMAN1_MAC5 +#define IPPDEXPCR_MAC1_6 0x04000000 // DEVDISR2_FMAN1_MAC6 +#define IPPDEXPCR_MAC1_9 0x00800000 // DEVDISR2_FMAN1_MAC9 +#define IPPDEXPCR_I2C1 0x00080000 // DEVDISR5_I2C_1 +#define IPPDEXPCR_LPUART1 0x00040000 // DEVDISR5_LPUART1 +#define IPPDEXPCR_FLX_TMR1 0x00020000 // DEVDISR5_FLX_TMR +#define IPPDEXPCR_OCRAM1 0x00010000 // DEVDISR5_OCRAM1 +#define IPPDEXPCR_GPIO1 0x00000040 // DEVDISR5_GPIO +#define IPPDEXPCR_FM1 0x00000008 // DEVDISR2_FMAN1 + +#define IPPDEXPCR_MASK1 0xFC800008 // overrides for DEVDISR2 +#define IPPDEXPCR_MASK2 0x000F0040 // overriddes for DEVDISR5 + +#define IPSTPCR0_VALUE 0xA000C201 +#define IPSTPCR1_VALUE 0x00000080 +#define IPSTPCR2_VALUE 0x000C0000 +#define IPSTPCR3_VALUE 0x38000000 +#if (DEBUG_ACTIVE) + #define IPSTPCR4_VALUE 0x10833BFC +#else + #define IPSTPCR4_VALUE 0x10A33BFC +#endif + +#define DEVDISR1_QE 0x00000001 +#define DEVDISR1_SEC 0x00000200 +#define DEVDISR1_USB1 0x00004000 +#define DEVDISR1_SATA 0x00008000 +#define DEVDISR1_USB2 0x00010000 +#define DEVDISR1_USB3 0x00020000 +#define DEVDISR1_DMA2 0x00400000 +#define DEVDISR1_DMA1 0x00800000 +#define DEVDISR1_ESDHC 0x20000000 +#define DEVDISR1_PBL 0x80000000 + +#define DEVDISR2_FMAN1 0x00000080 +#define DEVDISR2_FMAN1_MAC9 0x00800000 +#define DEVDISR2_FMAN1_MAC6 0x04000000 +#define DEVDISR2_FMAN1_MAC5 0x08000000 +#define DEVDISR2_FMAN1_MAC4 0x10000000 +#define DEVDISR2_FMAN1_MAC3 0x20000000 +#define DEVDISR2_FMAN1_MAC2 0x40000000 +#define DEVDISR2_FMAN1_MAC1 0x80000000 + +#define DEVDISR3_BMAN 0x00040000 +#define DEVDISR3_QMAN 0x00080000 +#define DEVDISR3_PEX3 0x20000000 +#define DEVDISR3_PEX2 0x40000000 +#define DEVDISR3_PEX1 0x80000000 + +#define DEVDISR4_QSPI 0x08000000 +#define DEVDISR4_DUART2 0x10000000 +#define DEVDISR4_DUART1 0x20000000 + +#define DEVDISR5_ICMMU 0x00000001 +#define DEVDISR5_I2C_1 0x00000002 +#define DEVDISR5_I2C_2 0x00000004 +#define DEVDISR5_I2C_3 0x00000008 +#define DEVDISR5_I2C_4 0x00000010 +#define DEVDISR5_WDG_5 0x00000020 +#define DEVDISR5_WDG_4 0x00000040 +#define DEVDISR5_WDG_3 0x00000080 +#define DEVDISR5_DSPI1 0x00000100 +#define DEVDISR5_WDG_2 0x00000200 +#define DEVDISR5_FLX_TMR 0x00000400 +#define DEVDISR5_WDG_1 0x00000800 +#define DEVDISR5_LPUART6 0x00001000 +#define DEVDISR5_LPUART5 0x00002000 +#define DEVDISR5_LPUART3 0x00008000 +#define DEVDISR5_LPUART2 0x00010000 +#define DEVDISR5_LPUART1 0x00020000 +#define DEVDISR5_DBG 0x00200000 +#define DEVDISR5_GPIO 0x00400000 +#define DEVDISR5_IFC 0x00800000 +#define DEVDISR5_OCRAM2 0x01000000 +#define DEVDISR5_OCRAM1 0x02000000 +#define DEVDISR5_LPUART4 0x10000000 +#define DEVDISR5_DDR 0x80000000 +#define DEVDISR5_MEM 0x80000000 + +#define DEVDISR1_VALUE 0xA0C3C201 +#define DEVDISR2_VALUE 0xCC0C0080 +#define DEVDISR3_VALUE 0xE00C0000 +#define DEVDISR4_VALUE 0x38000000 +#if (DEBUG_ACTIVE) + #define DEVDISR5_VALUE 0x10833BFC +#else + #define DEVDISR5_VALUE 0x10A33BFC +#endif + +/* + * PWR mgmt features supported in the soc-specific code: + * value == 0x0 the soc code does not support this feature + * value != 0x0 the soc code supports this feature + */ +#define SOC_CORE_RELEASE 0x1 +#define SOC_CORE_RESTART 0x1 +#define SOC_CORE_OFF 0x1 +#define SOC_CORE_STANDBY 0x1 +#define SOC_CORE_PWR_DWN 0x1 +#define SOC_CLUSTER_STANDBY 0x1 +#define SOC_CLUSTER_PWR_DWN 0x1 +#define SOC_SYSTEM_STANDBY 0x1 +#define SOC_SYSTEM_PWR_DWN 0x1 +#define SOC_SYSTEM_OFF 0x1 +#define SOC_SYSTEM_RESET 0x1 + +/* PSCI-specific defines */ +#define SYSTEM_PWR_DOMAINS 1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + NUMBER_OF_CLUSTERS + \ + SYSTEM_PWR_DOMAINS) + +/* Power state coordination occurs at the system level */ +#define PLAT_PD_COORD_LVL MPIDR_AFFLVL2 +#define PLAT_MAX_PWR_LVL PLAT_PD_COORD_LVL + +/* Local power state for power domains in Run state */ +#define LS_LOCAL_STATE_RUN PSCI_LOCAL_STATE_RUN + +/* define retention state */ +#define PLAT_MAX_RET_STATE (PSCI_LOCAL_STATE_RUN + 1) +#define LS_LOCAL_STATE_RET PLAT_MAX_RET_STATE + +/* define power-down state */ +#define PLAT_MAX_OFF_STATE (PLAT_MAX_RET_STATE + 1) +#define LS_LOCAL_STATE_OFF PLAT_MAX_OFF_STATE + +/* + * Some data must be aligned on the biggest cache line size in the platform. + * This is known only to the platform as it might have a combination of + * integrated and external caches. + * CACHE_WRITEBACK_GRANULE is defined in soc.def + */ + +/* One cache line needed for bakery locks on ARM platforms */ +#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE) + +#ifndef __ASSEMBLER__ +/* CCI slave interfaces */ +static const int cci_map[] = { + NXP_CCI_CLUSTER0_SL_IFACE_IX, +}; +void soc_init_lowlevel(void); +void soc_init_percpu(void); +void _soc_set_start_addr(unsigned long addr); + +#endif + +#endif /* SOC_H */ diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c b/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c new file mode 100644 index 0000000..28e2dab --- /dev/null +++ b/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c @@ -0,0 +1,163 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <string.h> + +#include <common/debug.h> +#include <ddr.h> +#include <lib/utils.h> + +#include <errata.h> +#include <platform_def.h> + +#ifdef CONFIG_STATIC_DDR +const struct ddr_cfg_regs static_1600 = { + .cs[0].config = U(0x80040322), + .cs[0].bnds = U(0x7F), + .sdram_cfg[0] = U(0xC50C0000), + .sdram_cfg[1] = U(0x401100), + .timing_cfg[0] = U(0x91550018), + .timing_cfg[1] = U(0xBBB48C42), + .timing_cfg[2] = U(0x48C111), + .timing_cfg[3] = U(0x10C1000), + .timing_cfg[4] = U(0x2), + .timing_cfg[5] = U(0x3401400), + .timing_cfg[7] = U(0x13300000), + .timing_cfg[8] = U(0x2115600), + .sdram_mode[0] = U(0x3010210), + .sdram_mode[9] = U(0x4000000), + .sdram_mode[8] = U(0x500), + .sdram_mode[2] = U(0x10210), + .sdram_mode[10] = U(0x400), + .sdram_mode[11] = U(0x4000000), + .sdram_mode[4] = U(0x10210), + .sdram_mode[12] = U(0x400), + .sdram_mode[13] = U(0x4000000), + .sdram_mode[6] = U(0x10210), + .sdram_mode[14] = U(0x400), + .sdram_mode[15] = U(0x4000000), + .interval = U(0x18600618), + .zq_cntl = U(0x8A090705), + .clk_cntl = U(0x3000000), + .cdr[0] = U(0x80040000), + .cdr[1] = U(0xA181), + .wrlvl_cntl[0] = U(0x8675F607), + .wrlvl_cntl[1] = U(0x7090807, + .wrlvl_cntl[2] = U(0x7070707), + .debug[28] = U(0x00700046), +}; + +uint64_t board_static_ddr(struct ddr_info *priv) +{ + memcpy(&priv->ddr_reg, &static_1600, sizeof(static_1600)); + + return ULL(0x80000000); +} + +#else +static const struct rc_timing rcz[] = { + {1600, 12, 7}, + {} +}; + +static const struct board_timing ram[] = { + {0x1f, rcz, 0x00020100, 0}, +}; + +int ddr_board_options(struct ddr_info *priv) +{ + int ret; + struct memctl_opt *popts = &priv->opt; + + ret = cal_board_params(priv, ram, ARRAY_SIZE(ram)); + if (ret) + return ret; + + popts->cpo_sample = U(0x46); + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | + DDR_CDR1_ODT(DDR_CDR_ODT_80ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) | + DDR_CDR2_VREF_OVRD(70); /* Vref = 70% */ + + return 0; +} + +/* DDR model number: MT40A1G8SA-062E:R */ +struct dimm_params ddr_raw_timing = { + .n_ranks = U(1), + .rank_density = ULL(2147483648), + .capacity = ULL(2147483648), + .primary_sdram_width = U(32), + .ec_sdram_width = U(4), + .rdimm = U(0), + .mirrored_dimm = U(0), + .n_row_addr = U(16), + .n_col_addr = U(10), + .bank_group_bits = U(2), + .edc_config = U(2), + .burst_lengths_bitmask = U(0x0c), + .tckmin_x_ps = 625, + .tckmax_ps = 2200, + .caslat_x = U(0x0001FFE00), + .taa_ps = 13500, + .trcd_ps = 13500, + .trp_ps = 13500, + .tras_ps = 32000, + .trc_ps = 45500, + .twr_ps = 15000, + .trfc1_ps = 350000, + .trfc2_ps = 260000, + .trfc4_ps = 160000, + .tfaw_ps = 21000, + .trrds_ps = 3000, + .trrdl_ps = 4900, + .tccdl_ps = 5000, + .refresh_rate_ps = U(7800000), + .rc = U(0x1f), +}; + +int ddr_get_ddr_params(struct dimm_params *pdimm, + struct ddr_conf *conf) +{ + static const char dimm_model[] = "Fixed DDR on board"; + + conf->dimm_in_use[0] = 1; + memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params)); + memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1); + + return 1; +} +#endif + +int64_t init_ddr(void) +{ + struct ddr_info info; + struct sysinfo sys; + int64_t dram_size; + + zeromem(&sys, sizeof(sys)); + get_clocks(&sys); + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0); + debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1); + + zeromem(&info, sizeof(struct ddr_info)); + info.num_ctlrs = 1; + info.dimm_on_ctlr = 1; + info.clk = get_ddr_freq(&sys, 0); + info.ddr[0] = (void *)NXP_DDR_ADDR; + + dram_size = dram_init(&info); + + if (dram_size < 0) { + ERROR("DDR init failed\n"); + } + +#ifdef ERRATA_SOC_A008850 + erratum_a008850_post(); +#endif + return dram_size; +} diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h b/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h new file mode 100644 index 0000000..249f457 --- /dev/null +++ b/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h @@ -0,0 +1,79 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include <arch.h> +/* + * Required without TBBR. + * To include the defines for DDR PHY Images. + */ +#include <tbbr_img_def.h> + +#include "policy.h" +#include <soc.h> + +#define NXP_SPD_EEPROM0 0x51 + +#define NXP_SYSCLK_FREQ 100000000 +#define NXP_DDRCLK_FREQ 100000000 + +/* UART related definition */ +#define NXP_CONSOLE_ADDR NXP_UART_ADDR +#define NXP_CONSOLE_BAUDRATE 115200 + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL2) +#if defined(TRUSTED_BOARD_BOOT) +#define PLATFORM_STACK_SIZE 0x2000 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +/* SD block buffer */ +#define NXP_SD_BLOCK_BUF_SIZE (0x00100000) +#define NXP_SD_BLOCK_BUF_ADDR ULL(0x80000000) + +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES 3 +#define MAX_IO_BLOCK_DEVICES 1 +#define MAX_IO_HANDLES 4 + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#define MAX_FIP_DEVICES 2 +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 1 +#endif + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define BL32_IRQ_SEC_PHY_TIMER 29 + +/* + * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_LS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_LS_G0_IRQ_PROPS(grp) + +#endif /* PLAT_DEF_H */ diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/platform.c b/plat/nxp/soc-ls1043a/ls1043ardb/platform.c new file mode 100644 index 0000000..65d508c --- /dev/null +++ b/plat/nxp/soc-ls1043a/ls1043ardb/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat_common.h> + +#pragma weak board_enable_povdd +#pragma weak board_disable_povdd + +bool board_enable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} + +bool board_disable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/platform.mk b/plat/nxp/soc-ls1043a/ls1043ardb/platform.mk new file mode 100644 index 0000000..5d23356 --- /dev/null +++ b/plat/nxp/soc-ls1043a/ls1043ardb/platform.mk @@ -0,0 +1,40 @@ +# +# Copyright 2018-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters + +BOOT_MODE ?= nor +BOARD := ls1043ardb +POVDD_ENABLE := no + +# DDR Compilation Configs +CONFIG_DDR_NODIMM := 1 +NUM_OF_DDRC := 1 +DDRC_NUM_DIMM := 0 +DDRC_NUM_CS := 4 +DDR_ECC_EN := no +CONFIG_STATIC_DDR := 0 + +# On-Board Flash Details +# 128MB IFC NOR Flash +NOR_FLASH_SZ := 0x8000000 + +# Platform specific features. +WARM_BOOT := no + +# Adding Platform files build files +BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\ + ${BOARD_PATH}/platform.c + +SUPPORTED_BOOT_MODE := nor \ + sd \ + nand + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Adding SoC build info +include plat/nxp/soc-ls1043a/soc.mk diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h b/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h new file mode 100644 index 0000000..4721a32 --- /dev/null +++ b/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h @@ -0,0 +1,13 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <plat_def.h> +#include <plat_default_def.h> + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/policy.h b/plat/nxp/soc-ls1043a/ls1043ardb/policy.h new file mode 100644 index 0000000..843b5e2 --- /dev/null +++ b/plat/nxp/soc-ls1043a/ls1043ardb/policy.h @@ -0,0 +1,16 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef POLICY_H +#define POLICY_H + +/* + * Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +#endif /* POLICY_H */ diff --git a/plat/nxp/soc-ls1043a/soc.c b/plat/nxp/soc-ls1043a/soc.c new file mode 100644 index 0000000..7badf8c --- /dev/null +++ b/plat/nxp/soc-ls1043a/soc.c @@ -0,0 +1,435 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <arch.h> +#include <caam.h> +#include <cassert.h> +#include <cci.h> +#include <common/debug.h> +#include <dcfg.h> +#ifdef I2C_INIT +#include <i2c.h> +#endif +#include <lib/mmio.h> +#include <lib/xlat_tables/xlat_tables_v2.h> +#include <ls_interconnect.h> +#ifdef POLICY_FUSE_PROVISION +#include <nxp_gpio.h> +#endif +#if TRUSTED_BOARD_BOOT +#include <nxp_smmu.h> +#endif +#include <nxp_timer.h> +#include <plat_console.h> +#include <plat_gic.h> +#include <plat_tzc380.h> +#include <scfg.h> +#if defined(NXP_SFP_ENABLED) +#include <sfp.h> +#endif + +#include <errata.h> +#include <ns_access.h> +#ifdef CONFIG_OCRAM_ECC_EN +#include <ocram.h> +#endif +#include <plat_common.h> +#include <platform_def.h> +#include <soc.h> + +static dcfg_init_info_t dcfg_init_data = { + .g_nxp_dcfg_addr = NXP_DCFG_ADDR, + .nxp_sysclk_freq = NXP_SYSCLK_FREQ, + .nxp_ddrclk_freq = NXP_DDRCLK_FREQ, + .nxp_plat_clk_divider = NXP_PLATFORM_CLK_DIVIDER, + }; + + +/* Function to return the SoC SYS CLK */ +unsigned int get_sys_clk(void) +{ + return NXP_SYSCLK_FREQ; +} + +/* + * Function returns the base counter frequency + * after reading the first entry at CNTFID0 (0x20 offset). + * + * Function is used by: + * 1. ARM common code for PSCI management. + * 2. ARM Generic Timer init. + * + */ +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int counter_base_frequency; + + counter_base_frequency = get_sys_clk()/4; + + return counter_base_frequency; +} + +#ifdef IMAGE_BL2 + +static struct soc_type soc_list[] = { + SOC_ENTRY(LS1023A, LS1023A, 1, 2), + SOC_ENTRY(LS1023AE, LS1023AE, 1, 2), + SOC_ENTRY(LS1023A_P23, LS1023A_P23, 1, 2), + SOC_ENTRY(LS1023AE_P23, LS1023AE_P23, 1, 2), + SOC_ENTRY(LS1043A, LS1043A, 1, 4), + SOC_ENTRY(LS1043AE, LS1043AE, 1, 4), + SOC_ENTRY(LS1043A_P23, LS1043A_P23, 1, 4), + SOC_ENTRY(LS1043AE_P23, LS1043AE_P23, 1, 4), +}; + +#ifdef POLICY_FUSE_PROVISION +static gpio_init_info_t gpio_init_data = { + .gpio1_base_addr = NXP_GPIO1_ADDR, + .gpio2_base_addr = NXP_GPIO2_ADDR, + .gpio3_base_addr = NXP_GPIO3_ADDR, + .gpio4_base_addr = NXP_GPIO4_ADDR, +}; +#endif + +/* + * Function to set the base counter frequency at + * the first entry of the Frequency Mode Table, + * at CNTFID0 (0x20 offset). + * + * Set the value of the pirmary core register cntfrq_el0. + */ +static void set_base_freq_CNTFID0(void) +{ + /* + * Below register specifies the base frequency of the system counter. + * As per NXP Board Manuals: + * The system counter always works with SYS_REF_CLK/4 frequency clock. + * + */ + unsigned int counter_base_frequency = get_sys_clk()/4; + + /* + * Setting the frequency in the Frequency modes table. + * + * Note: The value for ls1046ardb board at this offset + * is not RW as stated. This offset have the + * fixed value of 100000400 Hz. + * + * The below code line has no effect. + * Keeping it for other platforms where it has effect. + */ + mmio_write_32(NXP_TIMER_ADDR + CNTFID_OFF, counter_base_frequency); + + write_cntfrq_el0(counter_base_frequency); +} + +void soc_preload_setup(void) +{ + +} + +/******************************************************************************* + * This function implements soc specific erratas + * This is called before DDR is initialized or MMU is enabled + ******************************************************************************/ +void soc_early_init(void) +{ + uint8_t num_clusters, cores_per_cluster; + dram_regions_info_t *dram_regions_info = get_dram_regions_info(); + +#ifdef CONFIG_OCRAM_ECC_EN + ocram_init(NXP_OCRAM_ADDR, NXP_OCRAM_SIZE); +#endif + dcfg_init(&dcfg_init_data); +#ifdef POLICY_FUSE_PROVISION + gpio_init(&gpio_init_data); + sec_init(NXP_CAAM_ADDR); +#endif +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif + set_base_freq_CNTFID0(); + + /* Enable snooping on SEC read and write transactions */ + scfg_setbits32((void *)(NXP_SCFG_ADDR + SCFG_SNPCNFGCR_OFFSET), + SCFG_SNPCNFGCR_SECRDSNP | SCFG_SNPCNFGCR_SECWRSNP); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map)); + + /* + * Enable Interconnect coherency for the primary CPU's cluster. + */ + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + plat_ls_interconnect_enter_coherency(num_clusters); + +#if TRUSTED_BOARD_BOOT + uint32_t mode; + + sfp_init(NXP_SFP_ADDR); + /* + * For secure boot disable SMMU. + * Later when platform security policy comes in picture, + * this might get modified based on the policy + */ + if (check_boot_mode_secure(&mode) == true) { + bypass_smmu(NXP_SMMU_ADDR); + } + + /* + * For Mbedtls currently crypto is not supported via CAAM + * enable it when that support is there. In tbbr.mk + * the CAAM_INTEG is set as 0. + */ + +#ifndef MBEDTLS_X509 + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled() == false) { + INFO("SEC is disabled.\n"); + } else { + sec_init(NXP_CAAM_ADDR); + } +#endif +#elif defined(POLICY_FUSE_PROVISION) + gpio_init(&gpio_init_data); + sfp_init(NXP_SFP_ADDR); + sec_init(NXP_CAAM_ADDR); +#endif + + soc_errata(); + + /* + * Initialize system level generic timer for Layerscape Socs. + */ + delay_timer_init(NXP_TIMER_ADDR); + +#ifdef DDR_INIT + i2c_init(NXP_I2C_ADDR); + dram_regions_info->total_dram_size = init_ddr(); +#endif +} + +void soc_bl2_prepare_exit(void) +{ +#if defined(NXP_SFP_ENABLED) && defined(DISABLE_FUSE_WRITE) + set_sfp_wr_disable(); +#endif +} + +/***************************************************************************** + * This function returns the boot device based on RCW_SRC + ****************************************************************************/ +enum boot_device get_boot_dev(void) +{ + enum boot_device src = BOOT_DEVICE_NONE; + uint32_t porsr1; + uint32_t rcw_src, val; + + porsr1 = read_reg_porsr1(); + + rcw_src = (porsr1 & PORSR1_RCW_MASK) >> PORSR1_RCW_SHIFT; + + val = rcw_src & RCW_SRC_NAND_MASK; + + if (val == RCW_SRC_NAND_VAL) { + val = rcw_src & NAND_RESERVED_MASK; + if ((val != NAND_RESERVED_1) && (val != NAND_RESERVED_2)) { + src = BOOT_DEVICE_IFC_NAND; + INFO("RCW BOOT SRC is IFC NAND\n"); + } + } else { + /* RCW SRC NOR */ + val = rcw_src & RCW_SRC_NOR_MASK; + if (val == NOR_8B_VAL || val == NOR_16B_VAL) { + src = BOOT_DEVICE_IFC_NOR; + INFO("RCW BOOT SRC is IFC NOR\n"); + } else { + switch (rcw_src) { + case QSPI_VAL1: + case QSPI_VAL2: + src = BOOT_DEVICE_QSPI; + INFO("RCW BOOT SRC is QSPI\n"); + break; + case SD_VAL: + src = BOOT_DEVICE_EMMC; + INFO("RCW BOOT SRC is SD/EMMC\n"); + break; + default: + src = BOOT_DEVICE_NONE; + } + } + } + + return src; +} + +/* This function sets up access permissions on memory regions */ +void soc_mem_access(void) +{ + struct tzc380_reg tzc380_reg_list[MAX_NUM_TZC_REGION]; + int dram_idx, index = 0U; + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); + + for (dram_idx = 0U; dram_idx < info_dram_regions->num_dram_regions; + dram_idx++) { + if (info_dram_regions->region[dram_idx].size == 0) { + ERROR("DDR init failure, or"); + ERROR("DRAM regions not populated correctly.\n"); + break; + } + + index = populate_tzc380_reg_list(tzc380_reg_list, + dram_idx, index, + info_dram_regions->region[dram_idx].addr, + info_dram_regions->region[dram_idx].size, + NXP_SECURE_DRAM_SIZE, NXP_SP_SHRD_DRAM_SIZE); + } + + mem_access_setup(NXP_TZC_ADDR, index, tzc380_reg_list); + + /* Configure CSU secure access register to disable TZASC bypass mux */ + mmio_write_32((uintptr_t)(NXP_CSU_ADDR + + CSU_SEC_ACCESS_REG_OFFSET), + bswap32(TZASC_BYPASS_MUX_DISABLE)); +} + + +#else +const unsigned char _power_domain_tree_desc[] = {1, 1, 4}; + +CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256, + assert_invalid_ls1043_cluster_count); + +/* This function returns the SoC topology */ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + + return _power_domain_tree_desc; +} + +/* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + */ +unsigned int plat_ls_get_cluster_core_count(u_register_t mpidr) +{ + return CORES_PER_CLUSTER; +} + +void soc_early_platform_setup2(void) +{ + dcfg_init(&dcfg_init_data); + /* Initialize system level generic timer for Socs */ + delay_timer_init(NXP_TIMER_ADDR); + +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif +} + +/* + * For LS1043a rev1.0, GIC base address align with 4k. + * For LS1043a rev1.1, if DCFG_GIC400_ALIGN[GIC_ADDR_BIT] + * is set, GIC base address align with 4K, or else align + * with 64k. + */ +void get_gic_offset(uint32_t *gicc_base, uint32_t *gicd_base) +{ + uint32_t *ccsr_svr = (uint32_t *)(NXP_DCFG_ADDR + DCFG_SVR_OFFSET); + uint32_t *gic_align = (uint32_t *)(NXP_SCFG_ADDR + + SCFG_GIC400_ADDR_ALIGN_OFFSET); + uint32_t val; + + val = be32toh(mmio_read_32((uintptr_t)ccsr_svr)); + + if ((val & 0xff) == REV1_1) { + val = be32toh(mmio_read_32((uintptr_t)gic_align)); + if (val & (1L << GIC_ADDR_BIT)) { + *gicc_base = NXP_GICC_4K_ADDR; + *gicd_base = NXP_GICD_4K_ADDR; + } else { + *gicc_base = NXP_GICC_64K_ADDR; + *gicd_base = NXP_GICD_64K_ADDR; + } + } else { + *gicc_base = NXP_GICC_4K_ADDR; + *gicd_base = NXP_GICD_4K_ADDR; + } +} + +void soc_platform_setup(void) +{ + /* Initialize the GIC driver, cpu and distributor interfaces */ + static uint32_t target_mask_array[PLATFORM_CORE_COUNT]; + /* + * On a GICv2 system, the Group 1 secure interrupts are treated + * as Group 0 interrupts. + */ + static interrupt_prop_t ls_interrupt_props[] = { + PLAT_LS_G1S_IRQ_PROPS(GICV2_INTR_GROUP0), + PLAT_LS_G0_IRQ_PROPS(GICV2_INTR_GROUP0) + }; + static uint32_t gicc_base, gicd_base; + + get_gic_offset(&gicc_base, &gicd_base); + plat_ls_gic_driver_init(gicd_base, gicc_base, + PLATFORM_CORE_COUNT, + ls_interrupt_props, + ARRAY_SIZE(ls_interrupt_props), + target_mask_array); + + plat_ls_gic_init(); + enable_init_timer(); +} + +/* This function initializes the soc from the BL31 module */ +void soc_init(void) +{ + /* low-level init of the soc */ + soc_init_lowlevel(); + _init_global_data(); + soc_init_percpu(); + _initialize_psci(); + + /* + * Initialize the interconnect during cold boot. + * No need for locks as no other CPU is active. + */ + cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map)); + + /* + * Enable coherency in interconnect for the primary CPU's cluster. + * Earlier bootloader stages might already do this but we can't + * assume so. No harm in executing this code twice. + */ + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr())); + + /* Init CSU to enable non-secure access to peripherals */ + enable_layerscape_ns_access(ns_dev, ARRAY_SIZE(ns_dev), NXP_CSU_ADDR); + + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled() == false) { + INFO("SEC is disabled.\n"); + } else { + sec_init(NXP_CAAM_ADDR); + } +} + +void soc_runtime_setup(void) +{ + +} +#endif diff --git a/plat/nxp/soc-ls1043a/soc.def b/plat/nxp/soc-ls1043a/soc.def new file mode 100644 index 0000000..b174bd6 --- /dev/null +++ b/plat/nxp/soc-ls1043a/soc.def @@ -0,0 +1,107 @@ +# +# Copyright 2017-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# This file contains the basic architecture definitions that drive the build +# +# ----------------------------------------------------------------------------- + +CORE_TYPE := a53 + +CACHE_LINE := 6 + +# set to GIC400 or GIC500 +GIC := GIC400 + +# set to CCI400 or CCN504 or CCN508 +INTERCONNECT := CCI400 + +# indicate layerscape chassis level - set to 3=LSCH3 or 2=LSCH2 +CHASSIS := 2 + +# TZC IP Details TZC used is TZC380 or TZC400 +TZC_ID := TZC380 + +# CONSOLE Details available is NS16550 or PL011 +CONSOLE := NS16550 + +# Select the DDR PHY generation to be used +PLAT_DDR_PHY := PHY_GEN1 + +PHYS_SYS := 64 + +# ddr controller - set to MMDC or NXP +DDRCNTLR := NXP + +# ddr phy - set to NXP or SNPS +DDRPHY := NXP + +# Area of OCRAM reserved by ROM code +NXP_ROM_RSVD := 0x5900 + +# Max Size of CSF header. Required to define BL2 TEXT LIMIT in soc.def +# Input to CST create_hdr_esbc tool +CSF_HDR_SZ := 0x3000 + +# In IMAGE_BL2, compile time flag for handling Cache coherency +# with CAAM for BL2 running from OCRAM +SEC_MEM_NON_COHERENT := yes + +# OCRAM MAP +OCRAM_START_ADDR := 0x10000000 +OCRAM_SIZE := 0x20000 + +# BL2 binary is placed at start of OCRAM. +# Also used by create_pbl.mk. +BL2_BASE := 0x10000000 + +# After BL2 bin, OCRAM is used by ROM Code: +# (OCRAM_START_ADDR + BL2_BIN_SIZE) -> (NXP_ROM_RSVD - 1) + +# After ROM Code, OCRAM is used by CSF header. +# (OCRAM_START_ADDR + BL2_TEXT_LIMIT + NXP_ROM_RSVD) -> (CSF_HDR_SZ - 1) + +# BL2_HDR_LOC has to be (OCRAM_START_ADDR + OCRAM_SIZE - NXP_ROM_RSVD - CSF_HDR_SZ) +# This value should be greater than BL2_TEXT_LIMIT +# Input to CST create_hdr_isbc tool +BL2_HDR_LOC_HDR ?= $(shell echo $$(( $(OCRAM_START_ADDR) + $(OCRAM_SIZE) - $(NXP_ROM_RSVD) - $(CSF_HDR_SZ)))) +# Covert to HEX to be used by create_pbl.mk +BL2_HDR_LOC := $$(echo "obase=16; ${BL2_HDR_LOC_HDR}" | bc) + +# Core Errata +ERRATA_A53_855873 := 1 +ERRATA_A53_1530924 := 1 + +# SoC ERRATAS to be enabled +ERRATA_SOC_A008850 := 1 +ERRATA_SOC_A010539 := 1 +ERRATA_SOC_A009660 := 1 + +# DDR Errata +ERRATA_DDR_A009663 := 1 +ERRATA_DDR_A009942 := 1 + +# enable dynamic memory mapping +PLAT_XLAT_TABLES_DYNAMIC := 1 + +# Define Endianness of each module +NXP_GUR_ENDIANNESS := BE +NXP_DDR_ENDIANNESS := BE +NXP_SEC_ENDIANNESS := BE +NXP_SFP_ENDIANNESS := BE +NXP_SNVS_ENDIANNESS := BE +NXP_ESDHC_ENDIANNESS := BE +NXP_QSPI_ENDIANNESS := BE +NXP_FSPI_ENDIANNESS := BE +NXP_SCFG_ENDIANNESS := BE +NXP_GPIO_ENDIANNESS := BE +NXP_IFC_ENDIANNESS := BE + +NXP_SFP_VER := 3_2 + +# OCRAM ECC Enabled +OCRAM_ECC_EN := yes diff --git a/plat/nxp/soc-ls1043a/soc.mk b/plat/nxp/soc-ls1043a/soc.mk new file mode 100644 index 0000000..b6ce14e --- /dev/null +++ b/plat/nxp/soc-ls1043a/soc.mk @@ -0,0 +1,114 @@ +# +# Copyright 2018-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SoC-specific build parameters +SOC := ls1043a +PLAT_PATH := plat/nxp +PLAT_COMMON_PATH := plat/nxp/common +PLAT_DRIVERS_PATH := drivers/nxp +PLAT_SOC_PATH := ${PLAT_PATH}/soc-${SOC} +BOARD_PATH := ${PLAT_SOC_PATH}/${BOARD} + +# get SoC-specific defnitions +include ${PLAT_SOC_PATH}/soc.def +include ${PLAT_COMMON_PATH}/plat_make_helper/soc_common_def.mk +include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk + +# For Security Features +DISABLE_FUSE_WRITE := 1 +ifeq (${TRUSTED_BOARD_BOOT}, 1) +$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2)) +SECURE_BOOT := yes +endif +$(eval $(call SET_NXP_MAKE_FLAG,CRYPTO_NEEDED,BL_COMM)) + +# Selecting Drivers for SoC +$(eval $(call SET_NXP_MAKE_FLAG,DCFG_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,CSU_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,TIMER_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,INTERCONNECT_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,GIC_NEEDED,BL31)) +$(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,PMU_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,DDR_DRIVER_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,TZASC_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,I2C_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2)) + +# Selecting PSCI & SIP_SVC support +$(eval $(call SET_NXP_MAKE_FLAG,PSCI_NEEDED,BL31)) +$(eval $(call SET_NXP_MAKE_FLAG,SIPSVC_NEEDED,BL31)) + +# Source File Addition +PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/include/default\ + -I${BOARD_PATH}\ + -I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\ + -I${PLAT_SOC_PATH}/include\ + -I${PLAT_COMMON_PATH}/soc_errata + +ifeq (${SECURE_BOOT},yes) +include ${PLAT_COMMON_PATH}/tbbr/tbbr.mk +endif + +ifeq ($(WARM_BOOT),yes) +include ${PLAT_COMMON_PATH}/warm_reset/warm_reset.mk +endif + +ifeq (${NXP_NV_SW_MAINT_LAST_EXEC_DATA}, yes) +include ${PLAT_COMMON_PATH}/nv_storage/nv_storage.mk +endif + +ifeq (${PSCI_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/psci/psci.mk +endif + +ifeq (${SIPSVC_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/sip_svc/sipsvc.mk +endif + +# for fuse-fip & fuse-programming +ifeq (${FUSE_PROG}, 1) +include ${PLAT_COMMON_PATH}/fip_handler/fuse_fip/fuse.mk +endif + +ifeq (${IMG_LOADR_NEEDED},yes) +include $(PLAT_COMMON_PATH)/img_loadr/img_loadr.mk +endif + +# Adding source files for the above selected drivers. +include ${PLAT_DRIVERS_PATH}/drivers.mk + +# Adding SoC specific files +include ${PLAT_COMMON_PATH}/soc_errata/errata.mk + +PLAT_INCLUDES += ${NV_STORAGE_INCLUDES}\ + ${WARM_RST_INCLUDES} + +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}.S\ + ${WARM_RST_BL31_SOURCES}\ + ${PSCI_SOURCES}\ + ${SIPSVC_SOURCES}\ + ${PLAT_COMMON_PATH}/$(ARCH)/bl31_data.S + +PLAT_BL_COMMON_SOURCES += ${PLAT_COMMON_PATH}/$(ARCH)/ls_helpers.S\ + ${PLAT_SOC_PATH}/aarch64/${SOC}_helpers.S\ + ${NV_STORAGE_SOURCES}\ + ${WARM_RST_BL_COMM_SOURCES}\ + ${PLAT_SOC_PATH}/soc.c + +ifeq (${TEST_BL31}, 1) +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/bootmain64.S\ + ${PLAT_SOC_PATH}/$(ARCH)/nonboot64.S +endif + +BL2_SOURCES += ${DDR_CNTLR_SOURCES}\ + ${TBBR_SOURCES}\ + ${FUSE_SOURCES} + +# Adding TFA setup files +include ${PLAT_PATH}/common/setup/common.mk |