From 9df5ba05b4fe4cd44157363a897b73553ba6e2f1 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Fri, 18 Feb 2022 15:26:08 +0800 Subject: [PATCH] feat(ls1088a): add new SoC platform ls1088a LS1088A is a cost-effective, powerefficient, and highly integrated SoC device featuring eight extremely power-efficient 64-bit ARM Cortex-A53 cores with ECC-protected L1 and L2 cache memories for high reliability, running up to 1.6 GHz. This patch is to add ls1088a SoC support in TF-A. Signed-off-by: Ruchika Gupta Signed-off-by: rocket Signed-off-by: Pankaj Gupta Signed-off-by: Biwen Li Signed-off-by: Jiafei Pan Change-Id: Id9ebcdad1beab07ea81a41955edd4f471d6cf090 --- plat/nxp/common/setup/ls_bl2_el3_setup.c | 2 +- plat/nxp/soc-ls1088a/aarch64/ls1088a.S | 1817 +++++++++++++++++ .../nxp/soc-ls1088a/aarch64/ls1088a_helpers.S | 69 + plat/nxp/soc-ls1088a/include/soc.h | 229 +++ plat/nxp/soc-ls1088a/soc.c | 397 ++++ plat/nxp/soc-ls1088a/soc.def | 87 + plat/nxp/soc-ls1088a/soc.mk | 110 + 7 files changed, 2710 insertions(+), 1 deletion(-) create mode 100644 plat/nxp/soc-ls1088a/aarch64/ls1088a.S create mode 100644 plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S create mode 100644 plat/nxp/soc-ls1088a/include/soc.h create mode 100644 plat/nxp/soc-ls1088a/soc.c create mode 100644 plat/nxp/soc-ls1088a/soc.def create mode 100644 plat/nxp/soc-ls1088a/soc.mk diff --git a/plat/nxp/common/setup/ls_bl2_el3_setup.c b/plat/nxp/common/setup/ls_bl2_el3_setup.c index 14422e2a5..a4cbaef45 100644 --- a/plat/nxp/common/setup/ls_bl2_el3_setup.c +++ b/plat/nxp/common/setup/ls_bl2_el3_setup.c @@ -182,7 +182,7 @@ void ls_bl2_el3_plat_arch_setup(void) unsigned int flags = 0U; /* Initialise the IO layer and register platform IO devices */ ls_setup_page_tables( -#if SEPARATE_RW_AND_NOLOAD +#if SEPARATE_BL2_NOLOAD_REGION BL2_START, BL2_LIMIT - BL2_START, #else diff --git a/plat/nxp/soc-ls1088a/aarch64/ls1088a.S b/plat/nxp/soc-ls1088a/aarch64/ls1088a.S new file mode 100644 index 000000000..0c6b7ea7d --- /dev/null +++ b/plat/nxp/soc-ls1088a/aarch64/ls1088a.S @@ -0,0 +1,1817 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +.section .text, "ax" + +#include +#include +#include +#include + +#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 */ + +/* + * 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 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 + +.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 _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 + +.global _set_platform_security +.global _soc_set_start_addr + +.equ TZPCDECPROT_0_SET_BASE, 0x02200804 +.equ TZPCDECPROT_1_SET_BASE, 0x02200810 +.equ TZPCDECPROT_2_SET_BASE, 0x0220081C + +.equ TZASC_REGION_ATTRIBUTES_0_0, 0x01100110 + +.equ MPIDR_AFFINITY0_MASK, 0x00FF +.equ MPIDR_AFFINITY1_MASK, 0xFF00 +.equ CPUECTLR_DISABLE_TWALK_PREFETCH, 0x4000000000 +.equ CPUECTLR_INS_PREFETCH_MASK, 0x1800000000 +.equ CPUECTLR_DAT_PREFETCH_MASK, 0x0300000000 +.equ OSDLR_EL1_DLK_LOCK, 0x1 +.equ CNTP_CTL_EL0_EN, 0x1 +.equ CNTP_CTL_EL0_IMASK, 0x2 +/* shifted value for incrementing cluster count in mpidr */ +.equ MPIDR_CLUSTER, 0x100 + +/* + * This function initialize the soc, + * in: none + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11 + */ +func soc_init_lowlevel + /* + * called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + /* + * make sure the personality has been established by releasing cores + * that are marked "to-be-disabled" from reset + */ + bl release_disabled + + /* set SCRATCHRW7 to 0x0 */ + ldr x0, =DCFG_SCRATCHRW7_OFFSET + mov x1, xzr + bl _write_reg_dcfg + + /* restore the aarch32/64 non-volatile registers */ + ldp x18, x30, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + 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 + stp x4, x30, [sp, #-16]! + + bl plat_my_core_mask + mov x2, x0 + + /* x2 = core mask */ + + /* see if this core is marked for prefetch disable */ + mov x0, #PREFETCH_DIS_OFFSET + bl _get_global_data + tst x0, x2 + b.eq 1f + bl _disable_ldstr_pfetch_A53 +1: + mov x0, #NXP_PMU_ADDR + bl enable_timer_base_to_cluster + ldp x4, x30, [sp], #16 + ret +endfunc soc_init_percpu + +/* + * this function sets the security mechanisms in the SoC to implement the + * Platform Security Policy + */ +func _set_platform_security + mov x3, x30 + +#if (!SUPPRESS_TZC) + /* initialize the tzpc */ + bl init_tzpc +#endif + +#if (!SUPPRESS_SEC) + /* initialize secmon */ + bl initSecMon +#endif + mov x30, x3 + ret +endfunc _set_platform_security + +/* + * this function writes a 64-bit address to bootlocptrh/l + * in: x0, 64-bit address to write to BOOTLOCPTRL/H + * out: none + * uses x0, x1, x2 + */ +func _soc_set_start_addr + /* get the 64-bit base address of the dcfg block */ + ldr x2, =NXP_DCFG_ADDR + + /* write the 32-bit BOOTLOCPTRL register */ + mov x1, x0 + str w1, [x2, #DCFG_BOOTLOCPTRL_OFFSET] + + /* write the 32-bit BOOTLOCPTRH register */ + lsr x1, x0, #32 + str w1, [x2, #DCFG_BOOTLOCPTRH_OFFSET] + ret +endfunc _soc_set_start_addr + +/* + * 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: + mov x3, x30 + + /* x0 = core mask */ + + ldr x1, =NXP_SEC_REGFILE_ADDR + /* + * write to CORE_HOLD to tell the bootrom that we want this core + * to run + */ + str w0, [x1, #CORE_HOLD_OFFSET] + + /* x0 = core mask */ + + /* read-modify-write BRRL to release core */ + mov x1, #NXP_RESET_ADDR + ldr w2, [x1, #BRR_OFFSET] + orr w2, w2, w0 + str w2, [x1, #BRR_OFFSET] + dsb sy + isb + + /* send event */ + sev + isb + + mov x30, x3 + ret + +/* + * this function determines if a core is disabled via COREDISABLEDSR + * in: w0 = core_mask_lsb + * out: w0 = 0, core not disabled + * w0 != 0, core disabled + * uses x0, x1 + */ +_soc_ck_disabled: + /* get base addr of dcfg block */ + ldr x1, =NXP_DCFG_ADDR + + /* read COREDISABLEDSR */ + ldr w1, [x1, #DCFG_COREDISABLEDSR_OFFSET] + + /* test core bit */ + and w0, w1, w0 + + 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, x1, x2, x3, x4, x5, x6 + */ +_soc_core_restart: + mov x6, x30 + mov x4, x0 + + /* x4 = core mask lsb */ + + /* pgm GICD_CTLR - enable secure grp0 */ + mov x5, #NXP_GICD_ADDR + ldr w2, [x5, #GICD_CTLR_OFFSET] + orr w2, w2, #GICD_CTLR_EN_GRP_0 + str w2, [x5, #GICD_CTLR_OFFSET] + dsb sy + isb + /* poll on RWP til write completes */ +4: + ldr w2, [x5, #GICD_CTLR_OFFSET] + tst w2, #GICD_CTLR_RWP + b.ne 4b + + /* + * x4 = core mask lsb + * x5 = gicd base addr + */ + + mov x0, x4 + bl get_mpidr_value + + /* + * x0 = mpidr of target core + * x4 = core mask lsb of target core + * x5 = gicd base addr + */ + + /* generate target list bit */ + and x1, x0, #MPIDR_AFFINITY0_MASK + mov x2, #1 + lsl x2, x2, x1 + /* get the affinity1 field */ + and x1, x0, #MPIDR_AFFINITY1_MASK + lsl x1, x1, #8 + orr x2, x2, x1 + /* insert the INTID for SGI15 */ + orr x2, x2, #ICC_SGI0R_EL1_INTID + /* fire the SGI */ + msr ICC_SGI0R_EL1, x2 + dsb sy + isb + + /* load '0' on success */ + mov x0, xzr + + mov x30, x6 + ret + +/* + * 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, x1, x2, x3, x4, x5, x6, x7 + */ +_soc_core_prep_off: + mov x8, x30 + mov x7, x0 + + /* x7 = core mask lsb */ + + mrs x1, CPUECTLR_EL1 + /* set smp and disable L2 snoops in cpuectlr */ + orr x1, x1, #CPUECTLR_SMPEN_EN + orr x1, x1, #CPUECTLR_DISABLE_TWALK_PREFETCH + bic x1, x1, #CPUECTLR_INS_PREFETCH_MASK + bic x1, x1, #CPUECTLR_DAT_PREFETCH_MASK + /* set retention control in cpuectlr */ + bic x1, x1, #CPUECTLR_TIMER_MASK + orr x1, x1, #CPUECTLR_TIMER_8TICKS + msr CPUECTLR_EL1, x1 + + /* get redistributor rd base addr for this core */ + mov x0, x7 + bl get_gic_rd_base + mov x6, x0 + + /* get redistributor sgi base addr for this core */ + mov x0, x7 + bl get_gic_sgi_base + mov x5, x0 + + /* x5 = gicr sgi base addr + * x6 = gicr rd base addr + * x7 = core mask lsb + */ + + /* disable SGI 15 at redistributor - GICR_ICENABLER0 */ + mov w3, #GICR_ICENABLER0_SGI15 + str w3, [x5, #GICR_ICENABLER0_OFFSET] +2: + /* poll on rwp bit in GICR_CTLR */ + ldr w4, [x6, #GICR_CTLR_OFFSET] + tst w4, #GICR_CTLR_RWP + b.ne 2b + + /* disable GRP1 interrupts at cpu interface */ + msr ICC_IGRPEN1_EL3, xzr + + /* disable GRP0 ints at cpu interface */ + msr ICC_IGRPEN0_EL1, xzr + + /* program the redistributor - poll on GICR_CTLR.RWP as needed */ + + /* define SGI 15 as Grp0 - GICR_IGROUPR0 */ + ldr w4, [x5, #GICR_IGROUPR0_OFFSET] + bic w4, w4, #GICR_IGROUPR0_SGI15 + str w4, [x5, #GICR_IGROUPR0_OFFSET] + + /* define SGI 15 as Grp0 - GICR_IGRPMODR0 */ + ldr w3, [x5, #GICR_IGRPMODR0_OFFSET] + bic w3, w3, #GICR_IGRPMODR0_SGI15 + str w3, [x5, #GICR_IGRPMODR0_OFFSET] + + /* set priority of SGI 15 to highest (0x0) - GICR_IPRIORITYR3 */ + ldr w4, [x5, #GICR_IPRIORITYR3_OFFSET] + bic w4, w4, #GICR_IPRIORITYR3_SGI15_MASK + str w4, [x5, #GICR_IPRIORITYR3_OFFSET] + + /* enable SGI 15 at redistributor - GICR_ISENABLER0 */ + mov w3, #GICR_ISENABLER0_SGI15 + str w3, [x5, #GICR_ISENABLER0_OFFSET] + dsb sy + isb +3: + /* poll on rwp bit in GICR_CTLR */ + ldr w4, [x6, #GICR_CTLR_OFFSET] + tst w4, #GICR_CTLR_RWP + b.ne 3b + + /* quiesce the debug interfaces */ + mrs x3, osdlr_el1 + orr x3, x3, #OSDLR_EL1_DLK_LOCK + msr osdlr_el1, x3 + isb + + /* enable grp0 ints */ + mov x3, #ICC_IGRPEN0_EL1_EN + msr ICC_IGRPEN0_EL1, x3 + + /* + * x5 = gicr sgi base addr + * x6 = gicr rd base addr + * x7 = core mask lsb + */ + + /* clear any pending interrupts */ + mvn w1, wzr + str w1, [x5, #GICR_ICPENDR0_OFFSET] + + /* make sure system counter is enabled */ + ldr x3, =NXP_TIMER_ADDR + ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 4f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] +4: + /* enable the core timer and mask timer interrupt */ + mov x1, #CNTP_CTL_EL0_EN + orr x1, x1, #CNTP_CTL_EL0_IMASK + msr cntp_ctl_el0, x1 + + mov x30, x8 + ret + +/* + * part of CPU_OFF + * this function performs the final steps to shutdown the core + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5 + */ +_soc_core_entr_off: + mov x5, x30 + mov x4, x0 + + /* x4 = core mask */ +1: + /* enter low-power state by executing wfi */ + wfi + + /* see if SGI15 woke us up */ + mrs x2, ICC_IAR0_EL1 + mov x3, #ICC_IAR0_EL1_SGI15 + cmp x2, x3 + b.ne 2f + + /* deactivate the int */ + msr ICC_EOIR0_EL1, x2 + + /* x4 = core mask */ +2: + /* check if core has been turned on */ + mov x0, x4 + bl _getCoreState + + /* x0 = core state */ + + cmp x0, #CORE_WAKEUP + b.ne 1b + + /* if we get here, then we have exited the wfi */ + + 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, x1, x2, x3, x4, x5, x6 + */ +_soc_core_exit_off: + mov x6, x30 + mov x5, x0 + + /* disable forwarding of GRP0 ints at cpu interface */ + msr ICC_IGRPEN0_EL1, xzr + + /* get redistributor sgi base addr for this core */ + mov x0, x5 + bl get_gic_sgi_base + mov x4, x0 + + /* + * x4 = gicr sgi base addr + * x5 = core mask + */ + + /* disable SGI 15 at redistributor - GICR_ICENABLER0 */ + mov w1, #GICR_ICENABLER0_SGI15 + str w1, [x4, #GICR_ICENABLER0_OFFSET] + + /* get redistributor rd base addr for this core */ + mov x0, x5 + bl get_gic_rd_base + mov x4, x0 + + /* x4 = gicr rd base addr */ +2: + /* poll on rwp bit in GICR_CTLR */ + ldr w2, [x4, #GICR_CTLR_OFFSET] + tst w2, #GICR_CTLR_RWP + b.ne 2b + + /* x4 = gicr rd base addr */ + + /* unlock the debug interfaces */ + mrs x3, osdlr_el1 + bic x3, x3, #OSDLR_EL1_DLK_LOCK + msr osdlr_el1, x3 + isb + + dsb sy + isb + mov x30, x6 + ret + +/* + * this function requests a reset of the entire SOC + * in: none + * out: none + * uses: x0, x1, x2, x3, x4, x5, x6 + */ +_soc_sys_reset: + mov x3, x30 + + /* make sure the mask is cleared in the reset request mask register */ + mov x0, #RST_RSTRQMR1_OFFSET + mov w1, wzr + bl _write_reg_reset + + /* set the reset request */ + mov x4, #RST_RSTCR_OFFSET + mov x0, x4 + mov w1, #RSTCR_RESET_REQ + bl _write_reg_reset + + /* x4 = RST_RSTCR_OFFSET */ + + /* + * just in case this address range is mapped as cacheable, + * flush the write out of the dcaches + */ + mov x2, #NXP_RESET_ADDR + add x2, x2, x4 + dc cvac, x2 + dsb st + isb + + /* this function does not return */ + b . + +/* + * this function turns off the SoC + * Note: this function is not intended to return, and the only allowable + * recovery is POR + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +_soc_sys_off: + /* + * A-009810: LPM20 entry sequence might cause + * spurious timeout reset request + * workaround: MASK RESET REQ RPTOE + */ + ldr x0, =NXP_RESET_ADDR + ldr w1, [x0, #RST_RSTRQMR1_OFFSET] + orr w1, w1, #RSTRQMR_RPTOE_MASK + str w1, [x0, #RST_RSTRQMR1_OFFSET] + + /* disable SEC, QBman spi and qspi */ + ldr x2, =NXP_DCFG_ADDR + ldr x0, =DCFG_DEVDISR1_OFFSET + ldr w1, =DCFG_DEVDISR1_SEC + str w1, [x2, x0] + ldr x0, =DCFG_DEVDISR3_OFFSET + ldr w1, =DCFG_DEVDISR3_QBMAIN + str w1, [x2, x0] + ldr x0, =DCFG_DEVDISR4_OFFSET + ldr w1, =DCFG_DEVDISR4_SPI_QSPI + str w1, [x2, x0] + + /* set TPMWAKEMR0 */ + ldr x0, =TPMWAKEMR0_ADDR + mov w1, #0x1 + str w1, [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 L2 prefetches */ + mrs x0, CPUECTLR_EL1 + orr x0, x0, #CPUECTLR_SMPEN_EN + orr x0, x0, #CPUECTLR_TIMER_8TICKS + msr CPUECTLR_EL1, x0 + dsb sy + isb + + /* disable CCN snoop domain */ + ldr x0, =NXP_CCI_ADDR + mov w1, #0x1 + str w1, [x0] + + mov x2, #DAIF_SET_MASK + + mrs x1, spsr_el1 + orr x1, x1, x2 + msr spsr_el1, x1 + + mrs x1, spsr_el2 + orr x1, x1, x2 + msr spsr_el2, x1 + + bl get_pmu_idle_cluster_mask + mov x3, #NXP_PMU_ADDR + + /* x3 = pmu base addr */ + + /* idle the ACP interfaces */ + str w0, [x3, #PMU_CLAINACTSETR_OFFSET] + + /* force the debug interface to be quiescent */ + mrs x0, osdlr_el1 + orr x0, x0, #0x1 + msr osdlr_el1, x0 + + bl get_pmu_flush_cluster_mask + /* x3 = pmu base addr */ + mov x3, #NXP_PMU_ADDR + + /* clear flush request and status */ + ldr x2, =PMU_CLSL2FLUSHCLRR_OFFSET + str w0, [x3, x2] + + /* close the Skyros master port */ + ldr x2, =PMU_CLSINACTSETR_OFFSET + str w0, [x3, x2] + + /* request lpm20 */ + ldr x0, =PMU_POWMGTCSR_OFFSET + ldr w1, =PMU_POWMGTCSR_VAL + str w1, [x3, x0] + + /* this function does not return */ +1: + wfi + b 1b + +/* + * 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 CPUECTLR_EL1[2:0] */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CPUECTLR_EL1, x1 + + 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: + /* X0 = core mask lsb */ + dsb sy + isb + wfi + + 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, x2, x3 + */ +_soc_core_prep_pwrdn: + /* make sure system counter is enabled */ + ldr x3, =NXP_TIMER_ADDR + ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 1f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] +1: + /* + * enable dynamic retention control (CPUECTLR[2:0]) + * set the SMPEN bit (CPUECTLR[6]) + */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_RET_MASK + orr x1, x1, #CPUECTLR_TIMER_8TICKS + orr x1, x1, #CPUECTLR_SMPEN_EN + msr CPUECTLR_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: + /* X0 = core mask lsb */ + dsb sy + isb + wfi + + ret + +/* + * part of CPU_SUSPEND + * this function cleans up after a core exits power-down + * in: x0 = core mask lsb + * out: none + * uses + */ +_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 CPUECTLR_EL1[2:0] */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CPUECTLR_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, x2, x3 + */ +_soc_clstr_prep_pwrdn: + /* make sure system counter is enabled */ + ldr x3, =NXP_TIMER_ADDR + ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 1f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] +1: + /* + * enable dynamic retention control (CPUECTLR[2:0]) + * set the SMPEN bit (CPUECTLR[6]) + */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_RET_MASK + orr x1, x1, #CPUECTLR_TIMER_8TICKS + orr x1, x1, #CPUECTLR_SMPEN_EN + msr CPUECTLR_EL1, x1 + + isb + ret + +/* + * part of CPU_SUSPEND + * this function cleans up after a core exits power-down + * in: x0 = core mask lsb + * out: none + * uses + */ +_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 CPUECTLR_EL1[2:0] */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CPUECTLR_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 + */ +_soc_sys_prep_pwrdn: + /* set retention control */ + mrs x0, CPUECTLR_EL1 + bic x0, x0, #CPUECTLR_TIMER_MASK + orr x0, x0, #CPUECTLR_TIMER_8TICKS + orr x0, x0, #CPUECTLR_SMPEN_EN + msr CPUECTLR_EL1, x0 + dsb sy + isb + + 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, x1, x2, x3, x4, x5, x6, x7, x8 + */ +_soc_sys_pwrdn_wfi: + /* Save LR to stack */ + stp x18, x30, [sp, #-16]! + + /* Poll PCPW20SR for all secondary cores to be placed in PW20 */ + bl get_tot_num_cores + mov x3, #0x1 + lsl x3, x3, x0 + sub x3, x3, #2 +1: + mov x0, #NXP_PMU_ADDR + ldr w1, [x0, #PMU_PCPW20SR_OFFSET] + cmp w1, w3 + b.ne 1b + + /* backup EPU registers to stack */ + mov x3, #NXP_PMU_ADDR + ldr x2, =NXP_EPU_ADDR + ldr w4, [x2, #EPU_EPIMCR10_OFFSET] + ldr w5, [x2, #EPU_EPCCR10_OFFSET] + ldr w6, [x2, #EPU_EPCTR10_OFFSET] + ldr w7, [x2, #EPU_EPGCR_OFFSET] + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + + /* + * x2 = epu base addr + * x3 = pmu base addr + */ + + /* set up EPU event to receive the wake signal from PMU */ + mov w4, #EPU_EPIMCR10_VAL + mov w5, #EPU_EPCCR10_VAL + mov w6, #EPU_EPCTR10_VAL + mov w7, #EPU_EPGCR_VAL + str w4, [x2, #EPU_EPIMCR10_OFFSET] + str w5, [x2, #EPU_EPCCR10_OFFSET] + str w6, [x2, #EPU_EPCTR10_OFFSET] + str w7, [x2, #EPU_EPGCR_OFFSET] + + /* + * A-010194: There is logic problem + * in the path of GIC-to-PMU to issue + * wake request to core0 + * Workaround: Re-target the wakeup interrupts + * to a core other than the last active core0 + */ + ldr x2, =NXP_GICD_ADDR + + /* backup flextimer/mmc/usb interrupt router */ + ldr x0, =GICD_IROUTER60_OFFSET + ldr x1, =GICD_IROUTER76_OFFSET + ldr w4, [x2, x0] + ldr w5, [x2, x1] + ldr x0, =GICD_IROUTER112_OFFSET + ldr x1, =GICD_IROUTER113_OFFSET + ldr w6, [x2, x0] + ldr w7, [x2, x1] + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + + /* + * x2 = gicd base addr + * x0 = GICD_IROUTER112_OFFSET + * x1 = GICD_IROUTER113_OFFSET + */ + + /* re-route interrupt to cluster 1 */ + ldr w4, =GICD_IROUTER_VALUE + str w4, [x2, x0] + str w4, [x2, x1] + ldr x0, =GICD_IROUTER60_OFFSET + ldr x1, =GICD_IROUTER76_OFFSET + str w4, [x2, x0] + str w4, [x2, x1] + dsb sy + isb + + /* backup flextimer/mmc/usb interrupt enabler */ + ldr x0, =GICD_ISENABLER_1 + ldr w4, [x2, x0] + ldr x1, =GICD_ISENABLER_2 + ldr w5, [x2, x1] + stp x4, x5, [sp, #-16]! + + ldr x0, =GICD_ISENABLER_3 + ldr w4, [x2, x0] + ldr x1, =GICD_ICENABLER_1 + ldr w5, [x2, x1] + stp x4, x5, [sp, #-16]! + + ldr x0, =GICD_ICENABLER_2 + ldr w4, [x2, x0] + ldr x1, =GICD_ICENABLER_3 + ldr w5, [x2, x1] + stp x4, x5, [sp, #-16]! + + /* enable related interrupt routing */ + ldr w4, =GICD_ISENABLER_1_VALUE + ldr x0, =GICD_ISENABLER_1 + str w4, [x2, x0] + dsb sy + isb + + ldr w4, =GICD_ISENABLER_2_VALUE + ldr x0, =GICD_ISENABLER_2 + str w4, [x2, x0] + dsb sy + isb + + ldr w4, =GICD_ISENABLER_3_VALUE + ldr x0, =GICD_ISENABLER_3 + str w4, [x2, x0] + dsb sy + isb + + /* set POWMGTDCR [STP_PV_EN] = 1 */ + ldr x2, =NXP_POWMGTDCR + ldr w4, =0x01 + str w4, [x2] + + /* program IPSTPCR for override stop request (except DDR) */ + mov x3, #NXP_PMU_ADDR + + /* build an override mask for IPSTPCR4/IPSTPACK4/DEVDISR5 */ + ldr x2, =PMU_IPPDEXPCR4_OFFSET + ldr w7, [x3, x2] + + mov x5, xzr + ldr x6, =IPPDEXPCR4_MASK + and x6, x6, x7 + cbz x6, 1f + + /* + * x5 = override mask + * x6 = IPPDEXPCR bits for DEVDISR5 + * x7 = IPPDEXPCR + */ + + /* get the overrides */ + orr x4, x5, #DEVDISR5_FLX_TMR + tst x6, #IPPDEXPCR_FLX_TMR + 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] + + mov x3, #NXP_PMU_ADDR + + /* write IPSTPCR0 - no overrides */ + ldr x2, =PMU_IPSTPCR0_OFFSET + ldr w5, =IPSTPCR0_VALUE + str w5, [x3, x2] + + /* write IPSTPCR1 - no overrides */ + ldr x2, =PMU_IPSTPCR1_OFFSET + ldr w5, =IPSTPCR1_VALUE + str w5, [x3, x2] + + /* write IPSTPCR2 - no overrides */ + ldr x2, =PMU_IPSTPCR2_OFFSET + ldr w5, =IPSTPCR2_VALUE + str w5, [x3, x2] + + /* write IPSTPCR3 - no overrides */ + ldr x2, =PMU_IPSTPCR3_OFFSET + ldr w5, =IPSTPCR3_VALUE + str w5, [x3, x2] + + /* write IPSTPCR4 - overrides possible */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + ldr w6, [x2, #DEVDISR5_MASK_OFFSET] + ldr x2, =PMU_IPSTPCR4_OFFSET + ldr w5, =IPSTPCR4_VALUE + bic x5, x5, x6 + str w5, [x3, x2] + + /* write IPSTPCR5 - no overrides */ + ldr x2, =PMU_IPSTPCR5_OFFSET + ldr w5, =IPSTPCR5_VALUE + str w5, [x3, x2] + + /* write IPSTPCR6 - no overrides */ + ldr x2, =PMU_IPSTPCR6_OFFSET + ldr w5, =IPSTPCR6_VALUE + str w5, [x3, x2] + + /* poll IPSTPACK for IP stop acknowledgment (except DDR) */ + mov x3, #NXP_PMU_ADDR + + /* poll on IPSTPACK0 */ + ldr x2, =PMU_IPSTPACK0_OFFSET + ldr x4, =IPSTPCR0_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +3: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 14f + sub x7, x7, #1 + cbnz x7, 3b + +14: + /* poll on IPSTPACK1 */ + ldr x2, =PMU_IPSTPACK1_OFFSET + ldr x4, =IPSTPCR1_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +4: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 15f + sub x7, x7, #1 + cbnz x7, 4b + +15: + /* poll on IPSTPACK2 */ + ldr x2, =PMU_IPSTPACK2_OFFSET + ldr x4, =IPSTPCR2_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +5: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 16f + sub x7, x7, #1 + cbnz x7, 5b + +16: + /* poll on IPSTPACK3 */ + ldr x2, =PMU_IPSTPACK3_OFFSET + ldr x4, =IPSTPCR3_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +6: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 17f + sub x7, x7, #1 + cbnz x7, 6b + +17: + /* poll on IPSTPACK4 */ + ldr x2, =PMU_IPSTPACK4_OFFSET + ldr x4, =IPSTPCR4_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +7: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 18f + sub x7, x7, #1 + cbnz x7, 7b + +18: + /* poll on IPSTPACK5 */ + ldr x2, =PMU_IPSTPACK5_OFFSET + ldr x4, =IPSTPCR5_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +8: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 19f + sub x7, x7, #1 + cbnz x7, 8b + +19: + /* poll on IPSTPACK6 */ + ldr x2, =PMU_IPSTPACK6_OFFSET + ldr x4, =IPSTPCR6_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +9: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 20f + sub x7, x7, #1 + cbnz x7, 9b + +20: + /* save current DEVDISR states to DDR. */ + ldr x2, =NXP_DCFG_ADDR + + /* save DEVDISR1 and load new value */ + ldr x0, =DCFG_DEVDISR1_OFFSET + ldr w1, [x2, x0] + mov w13, w1 + ldr x1, =DEVDISR1_VALUE + str w1, [x2, x0] + /* save DEVDISR2 and load new value */ + ldr x0, =DCFG_DEVDISR2_OFFSET + ldr w1, [x2, x0] + mov w14, w1 + ldr x1, =DEVDISR2_VALUE + str w1, [x2, x0] + + /* x6 = DEVDISR5 override mask */ + + /* save DEVDISR3 and load new value */ + ldr x0, =DCFG_DEVDISR3_OFFSET + ldr w1, [x2, x0] + mov w15, w1 + ldr x1, =DEVDISR3_VALUE + str w1, [x2, x0] + + /* save DEVDISR4 and load new value */ + ldr x0, =DCFG_DEVDISR4_OFFSET + ldr w1, [x2, x0] + mov w16, w1 + /* not stop uart print */ + ldr x1, =0x0000332 + str w1, [x2, x0] + + /* save DEVDISR5 and load new value */ + ldr x0, =DCFG_DEVDISR5_OFFSET + ldr w1, [x2, x0] + mov w17, w1 + /* Enable this wakeup will fail, should enable OCRAM */ + ldr x1, =0x00102300 + str w1, [x2, x0] + + /* save DEVDISR6 and load new value */ + ldr x0, =DCFG_DEVDISR6_OFFSET + ldr w1, [x2, x0] + mov w18, w1 + ldr x1, =DEVDISR6_VALUE + str w1, [x2, x0] + + /* + * w13 = DEVDISR1 saved value + * w14 = DEVDISR2 saved value + * w15 = DEVDISR3 saved value + * w16 = DEVDISR4 saved value + * w17 = DEVDISR5 saved value + * w18 = DEVDISR6 saved value + */ + /* + * A-009810: LPM20 entry sequence might cause + * spurious timeout reset request + * workaround: MASK RESET REQ RPTOE + */ + ldr x0, =NXP_RESET_ADDR + ldr w1, =RSTRQMR_RPTOE_MASK + str w1, [x0, #RST_RSTRQMR1_OFFSET] + + /* disable SEC, QBman spi and qspi */ + ldr x2, =NXP_DCFG_ADDR + ldr x0, =DCFG_DEVDISR1_OFFSET + ldr w1, =DCFG_DEVDISR1_SEC + str w1, [x2, x0] + ldr x0, =DCFG_DEVDISR3_OFFSET + ldr w1, =DCFG_DEVDISR3_QBMAIN + str w1, [x2, x0] + ldr x0, =DCFG_DEVDISR4_OFFSET + ldr w1, =DCFG_DEVDISR4_SPI_QSPI + str w1, [x2, x0] + + /* + * write the GICR_WAKER.ProcessorSleep bits to 1 + * enable the WakeRequest signal + * x3 is cpu mask starting from cpu7 + */ + bl get_tot_num_cores + sub x0, x0, #1 + mov x3, #0x1 + lsl x3, x3, x0 +2: + mov x0, x3 + bl get_gic_rd_base + ldr w1, [x0, #GICR_WAKER_OFFSET] + orr w1, w1, #GICR_WAKER_SLEEP_BIT + str w1, [x0, #GICR_WAKER_OFFSET] +1: + ldr w1, [x0, #GICR_WAKER_OFFSET] + cmp w1, #GICR_WAKER_ASLEEP + b.ne 1b + + lsr x3, x3, #1 + cbnz x3, 2b + + /* x3 = pmu base addr */ + + /* perform Icache Warming Sequence */ + ldr x5, =IPSTPCR4_VALUE + mov x6, DDR_CNTRL_BASE_ADDR + mov x7, #NXP_PMU_ADDR + mov x8, #NXP_DCFG_ADDR + mov x10, #PMU_IPSTPCR4_OFFSET + mov x11, #PMU_IPSTPACK4_OFFSET + mov x12, #PMU_IPSTPCR3_OFFSET + mov x18, #PMU_IPSTPCR2_OFFSET + mov x19, #PMU_IPSTPCR1_OFFSET + mov x21, #PMU_IPSTPCR0_OFFSET + ldr x22, =DCFG_DEVDISR5_OFFSET + ldr x23, =NXP_EPU_ADDR + mov x9, #CORE_RESTARTABLE + bl final_pwrdown + + /* + * disable the WakeRequest signal on cpu 0-7 + * x3 is cpu mask starting from cpu7 + */ + bl get_tot_num_cores + sub x0, x0, #1 + mov x3, #0x1 + lsl x3, x3, x0 +2: + mov x0, x3 + bl get_gic_rd_base + ldr w1, [x0, #GICR_WAKER_OFFSET] + bic w1, w1, #GICR_WAKER_SLEEP_BIT + str w1, [x0, #GICR_WAKER_OFFSET] +1: + ldr w1, [x0, #GICR_WAKER_OFFSET] + cbnz w1, 1b + + lsr x3, x3, #1 + cbnz x3, 2b + + /* set SGI for secondary core wakeup */ + ldr x0, =0x1000002 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x2000004 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x3000008 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x4010001 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x5010002 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x6010004 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x7010008 + msr S3_0_C12_C11_7, x0 + + /* enable SEC, QBman spi and qspi */ + ldr x2, =NXP_DCFG_ADDR + str wzr, [x2, #DCFG_DEVDISR1_OFFSET] + str wzr, [x2, #DCFG_DEVDISR3_OFFSET] + str wzr, [x2, #DCFG_DEVDISR4_OFFSET] + + /* clear POWMGTDCR [STP_PV_EN] */ + ldr x2, =NXP_POWMGTDCR + ldr w4, [x2] + bic w4, w4, #0x01 + str w4, [x2] + + /* restore flextimer/mmc/usb interrupt enabler */ + ldr x3, =NXP_GICD_ADDR + ldp x0, x2, [sp], #16 + ldr x1, =GICD_ICENABLER_2 + mvn w0, w0 + str w0, [x3, x1] + ldr x1, =GICD_ICENABLER_3 + mvn w2, w2 + str w2, [x3, x1] + + ldp x0, x2, [sp], #16 + ldr x1, =GICD_ISENABLER_3 + str w0, [x3, x1] + ldr x1, =GICD_ICENABLER_1 + mvn w2, w2 + str w0, [x3, x1] + + ldp x0, x2, [sp], #16 + ldr x1, =GICD_ISENABLER_1 + str w0, [x3, x1] + ldr x1, =GICD_ISENABLER_2 + str w0, [x3, x1] + + /* restore flextimer/mmc/usb interrupt router */ + ldr x3, =NXP_GICD_ADDR + ldp x0, x2, [sp], #16 + ldr x1, =GICD_IROUTER113_OFFSET + str w2, [x3, x1] + ldr x1, =GICD_IROUTER112_OFFSET + str w0, [x3, x1] + ldp x0, x2, [sp], #16 + ldr x1, =GICD_IROUTER76_OFFSET + str w2, [x3, x1] + ldr x1, =GICD_IROUTER60_OFFSET + str w0, [x3, x1] + + /* restore EPU registers */ + ldr x3, =NXP_EPU_ADDR + ldp x0, x2, [sp], #16 + str w2, [x3, #EPU_EPGCR_OFFSET] + str w0, [x3, #EPU_EPCTR10_OFFSET] + ldp x2, x1, [sp], #16 + str w1, [x3, #EPU_EPCCR10_OFFSET] + str w2, [x3, #EPU_EPIMCR10_OFFSET] + + isb + /* Restor LR */ + ldp x18, x30, [sp], #16 + 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: + mrs x1, SCTLR_EL1 + orr x1, x1, #SCTLR_I_MASK + msr SCTLR_EL1, x1 + isb + ret + +/* + * this function checks to see if cores which are to be disabled have been + * released from reset - if not, it releases them + * in: none + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8 + */ +release_disabled: + mov x8, x30 + + /* read COREDISABLESR */ + mov x0, #NXP_DCFG_ADDR + ldr w4, [x0, #DCFG_COREDISABLEDSR_OFFSET] + + /* get the number of cpus on this device */ + mov x6, #PLATFORM_CORE_COUNT + + mov x0, #NXP_RESET_ADDR + ldr w5, [x0, #BRR_OFFSET] + + /* load the core mask for the first core */ + mov x7, #1 + + /* + * x4 = COREDISABLESR + * x5 = BRR + * x6 = loop count + * x7 = core mask bit + */ +2: + /* check if the core is to be disabled */ + tst x4, x7 + b.eq 1f + + /* see if disabled cores have already been released from reset */ + tst x5, x7 + b.ne 1f + + /* if core has not been released, then release it (0-3) */ + mov x0, x7 + bl _soc_core_release + + /* record the core state in the data area (0-3) */ + mov x0, x7 + mov x1, #CORE_DISABLED + bl _setCoreState + +1: + /* decrement the counter */ + subs x6, x6, #1 + b.le 3f + + /* shift the core mask to the next core */ + lsl x7, x7, #1 + /* continue */ + b 2b +3: + mov x30, x8 + ret + +/* + * write a register in the DCFG block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2 + */ +_write_reg_dcfg: + ldr x2, =NXP_DCFG_ADDR + str w1, [x2, x0] + ret + +/* + * read a register in the DCFG block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1 + */ +_read_reg_dcfg: + ldr x1, =NXP_DCFG_ADDR + ldr w0, [x1, x0] + ret + +/* + * this function sets up the TrustZone Address Space Controller (TZASC) + * in: none + * out: none + * uses x0, x1 + */ +init_tzpc: + /* + * set Non Secure access for all devices protected via TZPC + * decode Protection-0 Set Reg + */ + ldr x1, =TZPCDECPROT_0_SET_BASE + /* set decode region to NS, Bits[7:0] */ + mov w0, #0xFF + str w0, [x1] + + /* decode Protection-1 Set Reg */ + ldr x1, =TZPCDECPROT_1_SET_BASE + /* set decode region to NS, Bits[7:0] */ + mov w0, #0xFF + str w0, [x1] + + /* decode Protection-2 Set Reg */ + ldr x1, =TZPCDECPROT_2_SET_BASE + /* set decode region to NS, Bits[7:0] */ + mov w0, #0xFF + str w0, [x1] + + /* + * entire SRAM as NS + * secure RAM region size Reg + */ + ldr x1, =NXP_OCRAM_TZPC_ADDR + /* 0x00000000 = no secure region */ + mov w0, #0x00000000 + str w0, [x1] + + ret + +/* this function performs initialization on SecMon for boot services */ +initSecMon: + /* read the register hpcomr */ + ldr x1, =NXP_SNVS_ADDR + ldr w0, [x1, #SECMON_HPCOMR_OFFSET] + /* turn off secure access for the privileged registers */ + orr w0, w0, #SECMON_HPCOMR_NPSWAEN + /* write back */ + str w0, [x1, #SECMON_HPCOMR_OFFSET] + + ret + +/* + * this function returns the redistributor base address for the core specified + * in x1 + * in: x0 - core mask lsb of specified core + * out: x0 = redistributor rd base address for specified core + * uses x0, x1, x2 + */ +get_gic_rd_base: + /* get the 0-based core number */ + clz w1, w0 + mov w2, #0x20 + sub w2, w2, w1 + sub w2, w2, #1 + + /* x2 = core number / loop counter */ + + ldr x0, =NXP_GICR_ADDR + mov x1, #GIC_RD_OFFSET +2: + cbz x2, 1f + add x0, x0, x1 + sub x2, x2, #1 + b 2b +1: + ret + +/* + * this function returns the redistributor base address for the core specified + * in x1 + * in: x0 - core mask lsb of specified core + * out: x0 = redistributor sgi base address for specified core + * uses x0, x1, x2 + */ +get_gic_sgi_base: + /* get the 0-based core number */ + clz w1, w0 + mov w2, #0x20 + sub w2, w2, w1 + sub w2, w2, #1 + + /* x2 = core number / loop counter */ + + ldr x0, =NXP_GICR_SGI_ADDR + mov x1, #GIC_SGI_OFFSET +2: + cbz x2, 1f + add x0, x0, x1 + sub x2, x2, #1 + b 2b +1: + ret + +/* + * this function returns an mpidr value for a core, given a core_mask_lsb + * in: x0 = core mask lsb + * out: x0 = affinity2:affinity1:affinity0, where affinity is 8-bits + * uses x0, x1 + */ +get_mpidr_value: + /* convert a core mask to an SoC core number */ + clz w0, w0 + mov w1, #31 + sub w0, w1, w0 + + /* w0 = SoC core number */ + + mov w1, wzr +2: + cmp w0, #CORES_PER_CLUSTER + b.lt 1f + sub w0, w0, #CORES_PER_CLUSTER + add w1, w1, #MPIDR_CLUSTER + b 2b + + /* insert the mpidr core number */ +1: + orr w0, w1, w0 + ret + +/* + * write a register in the RESET block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2 + */ +_write_reg_reset: + ldr x2, =NXP_RESET_ADDR + str w1, [x2, x0] + ret + +/* + * read a register in the RESET block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1 + */ +_read_reg_reset: + ldr x1, =NXP_RESET_ADDR + ldr w0, [x1, x0] + 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 = NXP_PMU_ADDR + * x8 = NXP_DCFG_ADDR + * x9 = 0, restartable + * = 1, non-restartable + * x10 = PMU_IPSTPCR4_OFFSET + * x11 = PMU_IPSTPACK4_OFFSET + * x12 = PMU_IPSTPCR3_OFFSET + * x18 = PMU_IPSTPCR2_OFFSET + * x19 = PMU_IPSTPCR1_OFFSET + * x21 = PMU_IPSTPCR0_OFFSET + * w13 = DEVDISR1 saved value + * w14 = DEVDISR2 saved value + * w15 = DEVDISR3 saved value + * w16 = DEVDISR4 saved value + * w17 = DEVDISR5 saved value + * x22 = DCFG_DEVDISR5_OFFSET + * x23 = NXP_EPU_ADDR + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x13, x14, x15, x16, x17 + * x10, x11, x12, x18, x19, x21, x22, x23 + */ + +final_pwrdown: + /* delay */ + mov w4, #0xffffff +554: + sub w4, w4, #1 + cmp w4, #0 + b.ge 554b + + mov x0, xzr + b touch_line_0 + +/* 4Kb aligned */ +.align 12 +start_line_0: + mov x0, #1 + /* put ddr in self refresh - start */ + mov x2, #DDR_SDRAM_CFG_2_FRCSR + ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + orr w3, w3, w2 + /* put ddr in self refresh - end */ + str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + nop + nop +touch_line_0: + cbz x0, touch_line_1 + +start_line_1: + /* quiesce ddr clocks - start */ + orr w3, w5, #DCFG_DEVDISR5_MEM + mov w4, w3 + /* quiesce ddr clocks - end */ + str w4, [x7, x10] + mov w3, #DCFG_DEVDISR5_MEM + /* poll on ipstpack4 - start */ + mov x2, #DDR_SLEEP_RETRY_CNT + nop + nop +touch_line_1: + cbz x0, touch_line_2 + +start_line_2: + /* x11 = PMU_IPSTPACK4_OFFSET */ + ldr w1, [x7, x11] + tst w1, w3 + b.ne 5f + subs x2, x2, #1 + /* poll on ipstpack4 - end */ + b.gt start_line_2 + + /* if we get here, we have a timeout err */ + mov w4, w5 + /* x10 = PMU_IPSTPCR4_OFFSET re-enable ddr clks interface */ + str w4, [x7, x10] +touch_line_2: + cbz x0, touch_line_3 + +start_line_3: + /* load error code */ + mov x0, #ERROR_DDR_SLEEP + b 2f +5: + wfe + ldr w1, [x23, #EPU_EPCTR10_OFFSET] + cbz w1, 5b + + mov w4, w5 +touch_line_3: + cbz x0, touch_line_4 + +start_line_4: + /* re-enable ddr in devdisr5 */ + str w4, [x8, x22] + /* re-enable ddr clk in ipstpcr4 */ + str w4, [x7, x10] +13: + /* poll on ipstpack4 - start */ + ldr w1, [x7, x11] + tst w1, w3 + b.eq 2f + nop + b 13b + /* poll on ipstpack4 - end */ +2: +touch_line_4: + cbz x0, touch_line_5 + +start_line_5: + /* take ddr out-of self refresh - start */ + mov x2, #DDR_SDRAM_CFG_2_FRCSR + ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + mov w4, w3 + bic w4, w4, w2 + mov w3, w4 + /* wait for ddr cntrlr clock- start */ + mov x1, #DDR_SLEEP_RETRY_CNT +3: + subs x1, x1, #1 +touch_line_5: + cbz x0, touch_line_6 + +start_line_6: + /* wait for ddr cntrlr clock - end */ + b.gt 3b + /* take ddr out-of self refresh - end */ + str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + mov w1, w17 + /* reset devdisr5 */ + str w1, [x8, #DCFG_DEVDISR5_OFFSET] + mov w1, w16 + /* reset devdisr4 */ + str w1, [x8, #DCFG_DEVDISR4_OFFSET] + mov w1, w15 +touch_line_6: + cbz x0, touch_line_7 + +start_line_7: + /* reset devdisr3 */ + str w1, [x8, #DCFG_DEVDISR3_OFFSET] + mov w1, w14 + /* reset devdisr2 */ + str w1, [x8, #DCFG_DEVDISR2_OFFSET] + mov w1, w13 + /* reset devdisr1 */ + str w1, [x8, #DCFG_DEVDISR1_OFFSET] + /* reset ipstpcr4 */ + str wzr, [x7, x10] + /* reset ipstpcr3 */ + str wzr, [x7, x12] +touch_line_7: + cbz x0, touch_line_8 + +start_line_8: + /* reset ipstpcr2 */ + str wzr, [x7, x18] + /* reset ipstpcr1 */ + str wzr, [x7, x19] + /* reset ipstpcr0 */ + str wzr, [x7, x21] + +touch_line_8: + cbz x0, touch_line_9 + +start_line_9: + b continue_restart +touch_line_9: + 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 diff --git a/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S b/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S new file mode 100644 index 000000000..890cf8188 --- /dev/null +++ b/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S @@ -0,0 +1,69 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .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 + /* ls1088a 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-ls1088a/include/soc.h b/plat/nxp/soc-ls1088a/include/soc.h new file mode 100644 index 000000000..eb36c2e13 --- /dev/null +++ b/plat/nxp/soc-ls1088a/include/soc.h @@ -0,0 +1,229 @@ +/* + * Copyright 2022 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_lsch3.h" +#include "soc_default_base_addr.h" +#include "soc_default_helper_macros.h" + +/* + * SVR Definition of LS1088A + * A: without security + * AE: with security + * (not include major and minor rev) + */ +#define SVR_LS1044A 0x870323 +#define SVR_LS1044AE 0x870322 +#define SVR_LS1048A 0x870321 +#define SVR_LS1048AE 0x870320 +#define SVR_LS1084A 0x870303 +#define SVR_LS1084AE 0x870302 +#define SVR_LS1088A 0x870301 +#define SVR_LS1088AE 0x870300 + +#define SVR_WO_E 0xFFFFFE + +/* Number of cores in platform */ +#define NUMBER_OF_CLUSTERS 2 +#define CORES_PER_CLUSTER 4 +#define PLATFORM_CORE_COUNT (NUMBER_OF_CLUSTERS * CORES_PER_CLUSTER) + +/* set to 0 if the clusters are not symmetrical */ +#define SYMMETRICAL_CLUSTERS 1 + + +#define NUM_DRAM_REGIONS 2 +#define NXP_DRAM0_ADDR 0x80000000 +#define NXP_DRAM0_MAX_SIZE 0x80000000 /* 2 GB */ + +#define NXP_DRAM1_ADDR 0x8080000000 +#define NXP_DRAM1_MAX_SIZE 0x7F80000000 /* 510 G */ + +/* DRAM0 Size defined in platform_def.h */ +#define NXP_DRAM0_SIZE PLAT_DEF_DRAM0_SIZE + +#define NXP_POWMGTDCR 0x700123C20 + +/* epu register offsets and values */ +#define EPU_EPGCR_OFFSET 0x0 +#define EPU_EPIMCR10_OFFSET 0x128 +#define EPU_EPCTR10_OFFSET 0xa28 +#define EPU_EPCCR10_OFFSET 0x828 + +#ifdef EPU_EPCCR10_VAL +#undef EPU_EPCCR10_VAL +#endif +#define EPU_EPCCR10_VAL 0xf2800000 + +#define EPU_EPIMCR10_VAL 0xba000000 +#define EPU_EPCTR10_VAL 0x0 +#define EPU_EPGCR_VAL (1 << 31) + +/* pmu register offsets and values */ +#define PMU_PCPW20SR_OFFSET 0x830 +#define PMU_CLAINACTSETR_OFFSET 0x1100 +#define PMU_CLAINACTCLRR_OFFSET 0x1104 +#define PMU_CLSINACTSETR_OFFSET 0x1108 +#define PMU_CLSINACTCLRR_OFFSET 0x110C +#define PMU_CLL2FLUSHSETR_OFFSET 0x1110 +#define PMU_CLSL2FLUSHCLRR_OFFSET 0x1114 +#define PMU_CLL2FLUSHSR_OFFSET 0x1118 +#define PMU_POWMGTCSR_OFFSET 0x4000 +#define PMU_IPPDEXPCR0_OFFSET 0x4040 +#define PMU_IPPDEXPCR1_OFFSET 0x4044 +#define PMU_IPPDEXPCR2_OFFSET 0x4048 +#define PMU_IPPDEXPCR3_OFFSET 0x404C +#define PMU_IPPDEXPCR4_OFFSET 0x4050 +#define PMU_IPPDEXPCR5_OFFSET 0x4054 +#define PMU_IPSTPCR0_OFFSET 0x4120 +#define PMU_IPSTPCR1_OFFSET 0x4124 +#define PMU_IPSTPCR2_OFFSET 0x4128 +#define PMU_IPSTPCR3_OFFSET 0x412C +#define PMU_IPSTPCR4_OFFSET 0x4130 +#define PMU_IPSTPCR5_OFFSET 0x4134 +#define PMU_IPSTPCR6_OFFSET 0x4138 +#define PMU_IPSTPACK0_OFFSET 0x4140 +#define PMU_IPSTPACK1_OFFSET 0x4144 +#define PMU_IPSTPACK2_OFFSET 0x4148 +#define PMU_IPSTPACK3_OFFSET 0x414C +#define PMU_IPSTPACK4_OFFSET 0x4150 +#define PMU_IPSTPACK5_OFFSET 0x4154 +#define PMU_IPSTPACK6_OFFSET 0x4158 +#define PMU_POWMGTCSR_VAL (1 << 20) + +#define IPPDEXPCR0_MASK 0xFFFFFFFF +#define IPPDEXPCR1_MASK 0xFFFFFFFF +#define IPPDEXPCR2_MASK 0xFFFFFFFF +#define IPPDEXPCR3_MASK 0xFFFFFFFF +#define IPPDEXPCR4_MASK 0xFFFFFFFF +#define IPPDEXPCR5_MASK 0xFFFFFFFF + +/* DEVDISR5_FLX_TMR */ +#define IPPDEXPCR_FLX_TMR 0x00004000 +#define DEVDISR5_FLX_TMR 0x00004000 + +#define IPSTPCR0_VALUE 0x0041310C +#define IPSTPCR1_VALUE 0x000003FF +#define IPSTPCR2_VALUE 0x00013006 + +/* Dont' stop UART */ +#define IPSTPCR3_VALUE 0x0000033A + +#define IPSTPCR4_VALUE 0x00103300 +#define IPSTPCR5_VALUE 0x00000001 +#define IPSTPCR6_VALUE 0x00000000 + + +#define TZPC_BLOCK_SIZE 0x1000 + +/* PORSR1 */ +#define PORSR1_RCW_MASK 0xFF800000 +#define PORSR1_RCW_SHIFT 23 + +/* CFG_RCW_SRC[6:0] */ +#define RCW_SRC_TYPE_MASK 0x70 + +/* RCW SRC NOR */ +#define NOR_16B_VAL 0x20 + +/* + * RCW SRC Serial Flash + * 1. SERAIL NOR (QSPI) + * 2. OTHERS (SD/MMC, SPI, I2C1) + */ +#define RCW_SRC_SERIAL_MASK 0x7F +#define QSPI_VAL 0x62 +#define SDHC_VAL 0x40 +#define EMMC_VAL 0x41 + +/* + * Required LS standard platform porting definitions + * for CCN-504 - Read from RN-F node ID register + */ +#define PLAT_CLUSTER_TO_CCN_ID_MAP 1, 9, 11, 19 + +/* 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 2 + +/* dcfg register offsets and values */ +#define DCFG_DEVDISR1_OFFSET 0x70 +#define DCFG_DEVDISR2_OFFSET 0x74 +#define DCFG_DEVDISR3_OFFSET 0x78 +#define DCFG_DEVDISR5_OFFSET 0x80 +#define DCFG_DEVDISR6_OFFSET 0x84 + +#define DCFG_DEVDISR1_SEC (1 << 22) +#define DCFG_DEVDISR3_QBMAIN (1 << 12) +#define DCFG_DEVDISR4_SPI_QSPI (1 << 4 | 1 << 5) +#define DCFG_DEVDISR5_MEM (1 << 0) + +#define DEVDISR1_VALUE 0x0041310c +#define DEVDISR2_VALUE 0x000003ff +#define DEVDISR3_VALUE 0x00013006 +#define DEVDISR4_VALUE 0x0000033e +#define DEVDISR5_VALUE 0x00103300 +#define DEVDISR6_VALUE 0x00000001 + +/* + * 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 + +#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 + +#ifndef __ASSEMBLER__ +/* CCI slave interfaces */ +static const int cci_map[] = { + 3, + 4, +}; +void soc_init_lowlevel(void); +void soc_init_percpu(void); +void _soc_set_start_addr(unsigned long addr); +void _set_platform_security(void); +#endif + +#endif /* SOC_H */ diff --git a/plat/nxp/soc-ls1088a/soc.c b/plat/nxp/soc-ls1088a/soc.c new file mode 100644 index 000000000..5f9f313e2 --- /dev/null +++ b/plat/nxp/soc-ls1088a/soc.c @@ -0,0 +1,397 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#ifdef I2C_INIT +#include +#endif +#include +#include +#include +#if TRUSTED_BOARD_BOOT +#include +#endif +#include +#include +#include +#include +#include +#if defined(NXP_SFP_ENABLED) +#include +#endif + +#include +#ifdef CONFIG_OCRAM_ECC_EN +#include +#endif +#include +#include +#include + +static unsigned char _power_domain_tree_desc[NUMBER_OF_CLUSTERS + 2]; +static struct soc_type soc_list[] = { + SOC_ENTRY(LS1044A, LS1044A, 1, 4), + SOC_ENTRY(LS1044AE, LS1044AE, 1, 4), + SOC_ENTRY(LS1048A, LS1048A, 1, 4), + SOC_ENTRY(LS1048AE, LS1048AE, 1, 4), + SOC_ENTRY(LS1084A, LS1084A, 2, 4), + SOC_ENTRY(LS1084AE, LS1084AE, 2, 4), + SOC_ENTRY(LS1088A, LS1088A, 2, 4), + SOC_ENTRY(LS1088AE, LS1088AE, 2, 4), +}; + +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, +}; + +/* + * This function dynamically constructs the topology according to + * SoC Flavor and returns it. + */ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + unsigned int i; + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + + /* + * The highest level is the system level. The next level is constituted + * by clusters and then cores in clusters. + */ + _power_domain_tree_desc[0] = 1; + _power_domain_tree_desc[1] = num_clusters; + + for (i = 0; i < _power_domain_tree_desc[1]; i++) { + _power_domain_tree_desc[i + 2] = cores_per_cluster; + } + + + return _power_domain_tree_desc; +} + +CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256, + assert_invalid_ls1088a_cluster_count); + +/* + * 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; +} + +/* + * This function returns the total number of cores in the SoC + */ +unsigned int get_tot_num_cores(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + + return (num_clusters * cores_per_cluster); +} + +/* + * This function returns the PMU IDLE Cluster mask. + */ +unsigned int get_pmu_idle_cluster_mask(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + + return ((1 << num_clusters) - 2); +} + +/* + * This function returns the PMU Flush Cluster mask. + */ +unsigned int get_pmu_flush_cluster_mask(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + + return ((1 << num_clusters) - 2); +} + +/* + * This function returns the PMU IDLE Core mask. + */ +unsigned int get_pmu_idle_core_mask(void) +{ + return ((1 << get_tot_num_cores()) - 2); +} + +#ifdef IMAGE_BL2 + +void soc_bl2_prepare_exit(void) +{ +#if defined(NXP_SFP_ENABLED) && defined(DISABLE_FUSE_WRITE) + set_sfp_wr_disable(); +#endif +} + +void soc_preload_setup(void) +{ + +} + +/* + * 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; + + /* RCW SRC NOR */ + val = rcw_src & RCW_SRC_TYPE_MASK; + if (val == NOR_16B_VAL) { + src = BOOT_DEVICE_IFC_NOR; + INFO("RCW BOOT SRC is IFC NOR\n"); + } else { + val = rcw_src & RCW_SRC_SERIAL_MASK; + switch (val) { + case QSPI_VAL: + src = BOOT_DEVICE_QSPI; + INFO("RCW BOOT SRC is QSPI\n"); + break; + case SDHC_VAL: + src = BOOT_DEVICE_EMMC; + INFO("RCW BOOT SRC is SD/EMMC\n"); + break; + case EMMC_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) +{ + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); + int i = 0; + struct tzc400_reg tzc400_reg_list[MAX_NUM_TZC_REGION]; + int dram_idx, index = 1; + + for (dram_idx = 0; dram_idx < info_dram_regions->num_dram_regions; + dram_idx++) { + if (info_dram_regions->region[i].size == 0) { + ERROR("DDR init failure, or"); + ERROR("DRAM regions not populated correctly.\n"); + break; + } + + index = populate_tzc400_reg_list(tzc400_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, + tzc400_reg_list); +} + +/* + * This function implements soc specific erratum + * This is called before DDR is initialized or MMU is enabled + */ +void soc_early_init(void) +{ + enum boot_device dev; + 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); +#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 + enable_timer_base_to_cluster(NXP_PMU_ADDR); + enable_core_tb(NXP_PMU_ADDR); + + /* + * Use the region(NXP_SD_BLOCK_BUF_ADDR + NXP_SD_BLOCK_BUF_SIZE) + * as dma of sd + */ + dev = get_boot_dev(); + if (dev == BOOT_DEVICE_EMMC) { + mmap_add_region(NXP_SD_BLOCK_BUF_ADDR, NXP_SD_BLOCK_BUF_ADDR, + NXP_SD_BLOCK_BUF_SIZE, + MT_DEVICE | MT_RW | MT_NS); + } + +#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 +#endif + + soc_errata(); + + delay_timer_init(NXP_TIMER_ADDR); + i2c_init(NXP_I2C_ADDR); + dram_regions_info->total_dram_size = init_ddr(); +} +#else /* !IMAGE_BL2 */ + +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 +} + +void soc_platform_setup(void) +{ + /* Initialize the GIC driver, cpu and distributor interfaces */ + static uintptr_t target_mask_array[PLATFORM_CORE_COUNT]; + static interrupt_prop_t ls_interrupt_props[] = { + PLAT_LS_G1S_IRQ_PROPS(INTR_GROUP1S), + PLAT_LS_G0_IRQ_PROPS(INTR_GROUP0) + }; + + plat_ls_gic_driver_init(NXP_GICD_ADDR, NXP_GICR_ADDR, + PLATFORM_CORE_COUNT, + ls_interrupt_props, + ARRAY_SIZE(ls_interrupt_props), + target_mask_array, + plat_core_pos); + + plat_ls_gic_init(); + enable_init_timer(); +} + +/* + * This function initializes the soc from the BL31 module + */ +void soc_init(void) +{ + uint8_t num_clusters, cores_per_cluster; + + /* low-level init of the soc */ + soc_init_lowlevel(); + _init_global_data(); + soc_init_percpu(); + _initialize_psci(); + + /* + * 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); + + /* set platform security policies */ + _set_platform_security(); + + /* 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 /* IMAGE_BL2 */ + +/* + * 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; + /* + * 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. + */ + counter_base_frequency = mmio_read_32(NXP_TIMER_ADDR + CNTFID_OFF); + + return counter_base_frequency; +} diff --git a/plat/nxp/soc-ls1088a/soc.def b/plat/nxp/soc-ls1088a/soc.def new file mode 100644 index 000000000..25d0847f4 --- /dev/null +++ b/plat/nxp/soc-ls1088a/soc.def @@ -0,0 +1,87 @@ +# +# Copyright 2022 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 := GIC500 + +# Set to CCI400 or CCN504 or CCN508 +INTERCONNECT := CCI400 + +# Select the DDR PHY generation to be used +PLAT_DDR_PHY := PHY_GEN1 + +PHYS_SYS := 64 + +# Indicate layerscape chassis level - set to 3=LSCH3 or 2=LSCH2 +CHASSIS := 3 + +# TZC IP Details TZC used is TZC380 or TZC400 +TZC_ID := TZC400 + +# CONSOLE Details available is NS16550 or PL011 +CONSOLE := NS16550 + +NXP_SFP_VER := 3_4 + +# In IMAGE_BL2, compile time flag for handling Cache coherency +# with CAAM for BL2 running from OCRAM +SEC_MEM_NON_COHERENT := yes + + +# OCRAM MAP for BL2 +# Before BL2 +# 0x18000000 - 0x18009fff -> Used by ROM code, (TBD - can it be used for xlat tables) +# 0x1800a000 - 0x1801Cfff -> Reserved for BL2 binary (76 KB) +# 0x1801D000 - 0x1801ffff -> CSF header for BL2 (12 KB) +OCRAM_START_ADDR := 0x18000000 +OCRAM_SIZE := 0x20000 + +CSF_HDR_SZ := 0x3000 + +# Area of OCRAM reserved by ROM code +NXP_ROM_RSVD := 0xa000 + +# Input to CST create_hdr_isbc tool +BL2_HDR_LOC := 0x1801D000 + +# Location of BL2 on OCRAM +# BL2_BASE=OCRAM_START_ADDR+NXP_ROM_RSVD +BL2_BASE := 0x1800a000 + +# SoC ERRATUM to be enabled +ERRATA_SOC_A008850 := 1 + +# ARM Erratum +ERRATA_A53_855873 := 1 + +# DDR Erratum +ERRATA_DDR_A008511 := 1 +ERRATA_DDR_A009803 := 1 +ERRATA_DDR_A009942 := 1 +ERRATA_DDR_A010165 := 1 + +# Define Endianness of each module +NXP_ESDHC_ENDIANNESS := LE +NXP_SFP_ENDIANNESS := LE +NXP_GPIO_ENDIANNESS := LE +NXP_SNVS_ENDIANNESS := LE +NXP_GUR_ENDIANNESS := LE +NXP_SEC_ENDIANNESS := LE +NXP_DDR_ENDIANNESS := LE +NXP_QSPI_ENDIANNESS := LE + +# OCRAM ECC Enabled +OCRAM_ECC_EN := yes diff --git a/plat/nxp/soc-ls1088a/soc.mk b/plat/nxp/soc-ls1088a/soc.mk new file mode 100644 index 000000000..83ac9d08f --- /dev/null +++ b/plat/nxp/soc-ls1088a/soc.mk @@ -0,0 +1,110 @@ +# +# Copyright 2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SoC-specific build parameters +SOC := ls1088a +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} + +# Separate BL2 NOLOAD region (.bss, stack, page tables). need to +# define BL2_NOLOAD_START and BL2_NOLOAD_LIMIT +SEPARATE_BL2_NOLOAD_REGION := 1 + +# 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) +ifeq (${GENERATE_COT},1) +# Save Keys to be used by DDR FIP image +SAVE_KEYS=1 +endif +$(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)) +# Used by create_pbl tool to +# create bl2__sec.pbl image +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,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)) + + +# Adding SoC specific files +include ${PLAT_COMMON_PATH}/soc_errata/errata.mk + +PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/include/default\ + -I${BOARD_PATH}\ + -I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\ + -I${PLAT_COMMON_PATH}/soc_errata\ + -I${PLAT_COMMON_PATH}/include\ + -I${PLAT_SOC_PATH}/include + +ifeq (${SECURE_BOOT},yes) +include ${PLAT_COMMON_PATH}/tbbr/tbbr.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 + +PLAT_BL_COMMON_SOURCES += ${PLAT_COMMON_PATH}/$(ARCH)/ls_helpers.S\ + ${PLAT_SOC_PATH}/${ARCH}/${SOC}_helpers.S\ + ${PLAT_SOC_PATH}/soc.c + +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}.S\ + ${PSCI_SOURCES}\ + ${SIPSVC_SOURCES}\ + ${PLAT_COMMON_PATH}/$(ARCH)/bl31_data.S + +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