diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 17:43:51 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 17:43:51 +0000 |
commit | be58c81aff4cd4c0ccf43dbd7998da4a6a08c03b (patch) | |
tree | 779c248fb61c83f65d1f0dc867f2053d76b4e03a /plat/nxp/soc-lx2160a | |
parent | Initial commit. (diff) | |
download | arm-trusted-firmware-upstream.tar.xz arm-trusted-firmware-upstream.zip |
Adding upstream version 2.10.0+dfsg.upstream/2.10.0+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
28 files changed, 4989 insertions, 0 deletions
diff --git a/plat/nxp/soc-lx2160a/aarch64/lx2160a.S b/plat/nxp/soc-lx2160a/aarch64/lx2160a.S new file mode 100644 index 0000000..cc679f2 --- /dev/null +++ b/plat/nxp/soc-lx2160a/aarch64/lx2160a.S @@ -0,0 +1,1816 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +.section .text, "ax" + +#include <asm_macros.S> + +#include <lib/psci/psci.h> +#include <nxp_timer.h> +#include <plat_gic.h> +#include <pmu.h> + +#include <bl31_data.h> +#include <plat_psci.h> +#include <platform_def.h> + +.global soc_init_start +.global soc_init_percpu +.global soc_init_finish +.global _set_platform_security +.global _soc_set_start_addr + +.global _soc_core_release +.global _soc_ck_disabled +.global _soc_core_restart +.global _soc_core_prep_off +.global _soc_core_entr_off +.global _soc_core_exit_off +.global _soc_sys_reset +.global _soc_sys_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 + +.equ TZPC_BASE, 0x02200000 +.equ TZPCDECPROT_0_SET_BASE, 0x02200804 +.equ TZPCDECPROT_1_SET_BASE, 0x02200810 +.equ TZPCDECPROT_2_SET_BASE, 0x0220081C + +#define CLUSTER_3_CORES_MASK 0xC0 +#define CLUSTER_3_IN_RESET 1 +#define CLUSTER_3_NORMAL 0 + +/* cluster 3 handling no longer based on frequency, but rather on RCW[850], + * which is bit 18 of RCWSR27 + */ +#define CLUSTER_3_RCW_BIT 0x40000 + +/* retry count for clock-stop acks */ +.equ CLOCK_RETRY_CNT, 800 + +/* disable prefetching in the A72 core */ +#define CPUACTLR_DIS_LS_HW_PRE 0x100000000000000 +#define CPUACTLR_DIS_L2_TLB_PRE 0x200000 + +/* Function starts the initialization tasks of the soc, + * using secondary cores if they are available + * + * Called from C, saving the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + * + * in: + * out: + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11 + */ +func soc_init_start + 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 /* 0-9 */ + + /* init the task flags */ + bl _init_task_flags /* 0-1 */ + + /* set SCRATCHRW7 to 0x0 */ + ldr x0, =DCFG_SCRATCHRW7_OFFSET + mov x1, xzr + bl _write_reg_dcfg + +1: + /* 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_start + + +/* 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 */ + + /* Check 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_A72 /* 0 */ +1: + mov x0, #NXP_PMU_ADDR + bl enable_timer_base_to_cluster + ldp x4, x30, [sp], #16 + ret +endfunc soc_init_percpu + + +/* Function completes the initialization tasks of the soc + * in: + * out: + * uses x0, x1, x2, x3, x4 + */ +func soc_init_finish + stp x4, x30, [sp, #-16]! + + ldp x4, x30, [sp], #16 + ret +endfunc soc_init_finish + + +/* Function sets the security mechanisms in the SoC to implement the + * Platform Security Policy + */ +func _set_platform_security + mov x8, x30 + +#if (!SUPPRESS_TZC) + /* initialize the tzpc */ + bl init_tzpc +#endif + +#if (!SUPPRESS_SEC) + /* initialize secmon */ +#ifdef NXP_SNVS_ENABLED + mov x0, #NXP_SNVS_ADDR + bl init_sec_mon +#endif +#endif + + mov x30, x8 + ret +endfunc _set_platform_security + + +/* Function writes a 64-bit address to bootlocptrh/l + * in: x0, 64-bit address to write to BOOTLOCPTRL/H + * 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 + +/* Function releases a secondary core from reset + * in: x0 = core_mask_lsb + * out: none + * uses: x0, x1, x2, x3 + */ +func _soc_core_release + mov x3, x30 + + ldr x1, =NXP_SEC_REGFILE_ADDR + /* write to CORE_HOLD to tell + * the bootrom that this core is + * expected to run. + */ + str w0, [x1, #CORE_HOLD_OFFSET] + + /* read-modify-write BRRL to release core */ + mov x1, #NXP_RESET_ADDR + ldr w2, [x1, #BRR_OFFSET] + + /* x0 = core mask */ + orr w2, w2, w0 + str w2, [x1, #BRR_OFFSET] + dsb sy + isb + + /* send event */ + sev + isb + + mov x30, x3 + ret +endfunc _soc_core_release + + +/* 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 + */ +func _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 +endfunc _soc_ck_disabled + + +/* Part of CPU_ON + * 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 + */ +func _soc_core_restart + mov x6, x30 + mov x4, x0 + + /* 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 +endfunc _soc_core_restart + + +/* Part of CPU_OFF + * 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 + */ +func _soc_core_prep_off + mov x8, x30 + mov x7, x0 /* x7 = core mask lsb */ + + mrs x1, CORTEX_A72_ECTLR_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 CORTEX_A72_ECTLR_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 + + isb + mov x30, x8 + ret +endfunc _soc_core_prep_off + + +/* Part of CPU_OFF: + * Function performs the final steps to shutdown the core + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5 + */ +func _soc_core_entr_off + mov x5, x30 + mov x4, x0 + +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 intrrupts. */ + msr ICC_EOIR0_EL1, x2 + +2: + /* check if core is turned ON */ + mov x0, x4 + /* Fetched the core state in x0 */ + bl _getCoreState + + cmp x0, #CORE_WAKEUP + b.ne 1b + + /* Reached here, exited the wfi */ + + mov x30, x5 + ret +endfunc _soc_core_entr_off + + +/* Part of CPU_OFF: + * 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 + */ +func _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 + +2: + /* poll on rwp bit in GICR_CTLR */ + ldr w2, [x4, #GICR_CTLR_OFFSET] + tst w2, #GICR_CTLR_RWP + b.ne 2b + + /* 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 +endfunc _soc_core_exit_off + + +/* Function requests a reset of the entire SOC + * in: none + * out: none + * uses: x0, x1, x2, x3, x4, x5, x6 + */ +func _soc_sys_reset + mov x6, x30 + + ldr x2, =NXP_RST_ADDR + /* clear the RST_REQ_MSK and SW_RST_REQ */ + + mov w0, #0x00000000 + str w0, [x2, #RSTCNTL_OFFSET] + + /* initiate the sw reset request */ + mov w0, #SW_RST_REQ_INIT + str w0, [x2, #RSTCNTL_OFFSET] + + /* In case this address range is mapped as cacheable, + * flush the write out of the dcaches. + */ + add x2, x2, #RSTCNTL_OFFSET + dc cvac, x2 + dsb st + isb + + /* Function does not return */ + b . +endfunc _soc_sys_reset + + +/* Part of SYSTEM_OFF: + * Function turns off the SoC clocks + * Note: Function is not intended to return, and the only allowable + * recovery is POR + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +func _soc_sys_off + + /* 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, CORTEX_A72_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + orr x0, x0, #CPUECTLR_SMPEN_EN + orr x0, x0, #CPUECTLR_TIMER_8TICKS + msr CORTEX_A72_ECTLR_EL1, x0 + isb + + /* disable CCN snoop domain */ + mov x1, #NXP_CCN_HN_F_0_ADDR + ldr x0, =CCN_HN_F_SNP_DMN_CTL_MASK + str x0, [x1, #CCN_HN_F_SNP_DMN_CTL_CLR_OFFSET] +3: + ldr w2, [x1, #CCN_HN_F_SNP_DMN_CTL_OFFSET] + cmp w2, #0x2 + b.ne 3b + + mov x3, #NXP_PMU_ADDR + +4: + ldr w1, [x3, #PMU_PCPW20SR_OFFSET] + cmp w1, #PMU_IDLE_CORE_MASK + b.ne 4b + + mov w1, #PMU_IDLE_CLUSTER_MASK + str w1, [x3, #PMU_CLAINACTSETR_OFFSET] + +1: + ldr w1, [x3, #PMU_PCPW20SR_OFFSET] + cmp w1, #PMU_IDLE_CORE_MASK + b.ne 1b + + mov w1, #PMU_FLUSH_CLUSTER_MASK + str w1, [x3, #PMU_CLL2FLUSHSETR_OFFSET] + +2: + ldr w1, [x3, #PMU_CLL2FLUSHSR_OFFSET] + cmp w1, #PMU_FLUSH_CLUSTER_MASK + b.ne 2b + + mov w1, #PMU_FLUSH_CLUSTER_MASK + str w1, [x3, #PMU_CLSL2FLUSHCLRR_OFFSET] + + mov w1, #PMU_FLUSH_CLUSTER_MASK + str w1, [x3, #PMU_CLSINACTSETR_OFFSET] + + 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 + + /* force the debug interface to be quiescent */ + mrs x0, osdlr_el1 + orr x0, x0, #0x1 + msr osdlr_el1, x0 + + /* invalidate all TLB entries at all 3 exception levels */ + tlbi alle1 + tlbi alle2 + tlbi alle3 + + /* x3 = pmu base addr */ + + /* request lpm20 */ + ldr x0, =PMU_POWMGTCSR_OFFSET + ldr w1, =PMU_POWMGTCSR_VAL + str w1, [x3, x0] + +5: + wfe + b.eq 5b +endfunc _soc_sys_off + + +/* Part of CPU_SUSPEND + * Function puts the calling core into standby state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +func _soc_core_entr_stdby + + dsb sy + isb + wfi + + ret +endfunc _soc_core_entr_stdby + + +/* Part of CPU_SUSPEND + * Function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +func _soc_core_prep_stdby + + /* clear CORTEX_A72_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A72_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A72_ECTLR_EL1, x1 + + ret +endfunc _soc_core_prep_stdby + + +/* Part of CPU_SUSPEND + * Function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_core_exit_stdby + + ret +endfunc _soc_core_exit_stdby + + +/* Part of CPU_SUSPEND + * Function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_core_prep_pwrdn + + /* make sure system counter is enabled */ + ldr x2, =NXP_TIMER_ADDR + ldr w0, [x2, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 1f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x2, #SYS_COUNTER_CNTCR_OFFSET] +1: + + /* enable dynamic retention control (CPUECTLR[2:0]) + * set the SMPEN bit (CPUECTLR[6]) + */ + mrs x1, CORTEX_A72_ECTLR_EL1 + bic x1, x1, #CPUECTLR_RET_MASK + orr x1, x1, #CPUECTLR_TIMER_8TICKS + orr x1, x1, #CPUECTLR_SMPEN_EN + msr CORTEX_A72_ECTLR_EL1, x1 + + isb + ret +endfunc _soc_core_prep_pwrdn + + +/* Part of CPU_SUSPEND + * Function puts the calling core into a power-down state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +func _soc_core_entr_pwrdn + + /* X0 = core mask lsb */ + + dsb sy + isb + wfi + + ret +endfunc _soc_core_entr_pwrdn + + +/* Part of CPU_SUSPEND + * Function performs any SoC-specific cleanup after power-down state + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_core_exit_pwrdn + + ret +endfunc _soc_core_exit_pwrdn + + +/* Part of CPU_SUSPEND + * Function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +func _soc_clstr_prep_stdby + + /* clear CORTEX_A72_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A72_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A72_ECTLR_EL1, x1 + + ret +endfunc _soc_clstr_prep_stdby + + +/* Part of CPU_SUSPEND + * Function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_clstr_exit_stdby + + ret +endfunc _soc_clstr_exit_stdby + + +/* Part of CPU_SUSPEND + * Function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_clstr_prep_pwrdn + + /* make sure system counter is enabled */ + ldr x2, =NXP_TIMER_ADDR + ldr w0, [x2, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 1f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x2, #SYS_COUNTER_CNTCR_OFFSET] +1: + + /* enable dynamic retention control (CPUECTLR[2:0]) + * set the SMPEN bit (CPUECTLR[6]) + */ + mrs x1, CORTEX_A72_ECTLR_EL1 + bic x1, x1, #CPUECTLR_RET_MASK + orr x1, x1, #CPUECTLR_TIMER_8TICKS + orr x1, x1, #CPUECTLR_SMPEN_EN + msr CORTEX_A72_ECTLR_EL1, x1 + + isb + ret +endfunc _soc_clstr_prep_pwrdn + + +/* Part of CPU_SUSPEND + * Function performs any SoC-specific cleanup after power-down state + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_clstr_exit_pwrdn + + ret +endfunc _soc_clstr_exit_pwrdn + + +/* Part of CPU_SUSPEND + * Function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +func _soc_sys_prep_stdby + + /* clear CORTEX_A72_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A72_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A72_ECTLR_EL1, x1 + ret +endfunc _soc_sys_prep_stdby + + +/* Part of CPU_SUSPEND + * Function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +func _soc_sys_exit_stdby + + ret +endfunc _soc_sys_exit_stdby + + +/* Part of CPU_SUSPEND + * Function performs SoC-specific programming prior to + * suspend-to-power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +func _soc_sys_prep_pwrdn + + mrs x1, CORTEX_A72_ECTLR_EL1 + /* make sure the smp bit is set */ + orr x1, x1, #CPUECTLR_SMPEN_MASK + /* set the retention control */ + orr x1, x1, #CPUECTLR_RET_8CLK + /* disable tablewalk prefetch */ + orr x1, x1, #CPUECTLR_DISABLE_TWALK_PREFETCH + msr CORTEX_A72_ECTLR_EL1, x1 + isb + + ret +endfunc _soc_sys_prep_pwrdn + + +/* Part of CPU_SUSPEND + * 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, x9, x10, x11, x12, x13, x14, + * x15, x16, x17, x18, x19, x20, x21, x28 + */ +func _soc_sys_pwrdn_wfi + mov x28, x30 + + /* disable cluster snooping in the CCN-508 */ + ldr x1, =NXP_CCN_HN_F_0_ADDR + ldr x7, [x1, #CCN_HN_F_SNP_DMN_CTL_OFFSET] + mov x6, #CCN_HNF_NODE_COUNT +1: + str x7, [x1, #CCN_HN_F_SNP_DMN_CTL_CLR_OFFSET] + sub x6, x6, #1 + add x1, x1, #CCN_HNF_OFFSET + cbnz x6, 1b + + /* x0 = core mask + * x7 = hnf sdcr + */ + + ldr x1, =NXP_PMU_CCSR_ADDR + ldr x2, =NXP_PMU_DCSR_ADDR + + /* enable the stop-request-override */ + mov x3, #PMU_POWMGTDCR0_OFFSET + mov x4, #POWMGTDCR_STP_OV_EN + str w4, [x2, x3] + + /* x0 = core mask + * x1 = NXP_PMU_CCSR_ADDR + * x2 = NXP_PMU_DCSR_ADDR + * x7 = hnf sdcr + */ + + /* disable prefetching in the A72 core */ + mrs x8, CORTEX_A72_CPUACTLR_EL1 + tst x8, #CPUACTLR_DIS_LS_HW_PRE + b.ne 2f + dsb sy + isb + /* disable data prefetch */ + orr x16, x8, #CPUACTLR_DIS_LS_HW_PRE + /* disable tlb prefetch */ + orr x16, x16, #CPUACTLR_DIS_L2_TLB_PRE + msr CORTEX_A72_CPUACTLR_EL1, x16 + isb + + /* x0 = core mask + * x1 = NXP_PMU_CCSR_ADDR + * x2 = NXP_PMU_DCSR_ADDR + * x7 = hnf sdcr + * x8 = cpuactlr + */ + +2: + /* save hnf-sdcr and cpuactlr to stack */ + stp x7, x8, [sp, #-16]! + + /* x0 = core mask + * x1 = NXP_PMU_CCSR_ADDR + * x2 = NXP_PMU_DCSR_ADDR + */ + + /* save the IPSTPCRn registers to stack */ + mov x15, #PMU_IPSTPCR0_OFFSET + ldr w9, [x1, x15] + mov x16, #PMU_IPSTPCR1_OFFSET + ldr w10, [x1, x16] + mov x17, #PMU_IPSTPCR2_OFFSET + ldr w11, [x1, x17] + mov x18, #PMU_IPSTPCR3_OFFSET + ldr w12, [x1, x18] + mov x19, #PMU_IPSTPCR4_OFFSET + ldr w13, [x1, x19] + mov x20, #PMU_IPSTPCR5_OFFSET + ldr w14, [x1, x20] + + stp x9, x10, [sp, #-16]! + stp x11, x12, [sp, #-16]! + stp x13, x14, [sp, #-16]! + + /* x0 = core mask + * x1 = NXP_PMU_CCSR_ADDR + * x2 = NXP_PMU_DCSR_ADDR + * x15 = PMU_IPSTPCR0_OFFSET + * x16 = PMU_IPSTPCR1_OFFSET + * x17 = PMU_IPSTPCR2_OFFSET + * x18 = PMU_IPSTPCR3_OFFSET + * x19 = PMU_IPSTPCR4_OFFSET + * x20 = PMU_IPSTPCR5_OFFSET + */ + + /* load the full clock mask for IPSTPCR0 */ + ldr x3, =DEVDISR1_MASK + /* get the exclusions */ + mov x21, #PMU_IPPDEXPCR0_OFFSET + ldr w4, [x1, x21] + /* apply the exclusions to the mask */ + bic w7, w3, w4 + /* stop the clocks in IPSTPCR0 */ + str w7, [x1, x15] + + /* use same procedure for IPSTPCR1-IPSTPCR5 */ + + /* stop the clocks in IPSTPCR1 */ + ldr x5, =DEVDISR2_MASK + mov x21, #PMU_IPPDEXPCR1_OFFSET + ldr w6, [x1, x21] + bic w8, w5, w6 + str w8, [x1, x16] + + /* stop the clocks in IPSTPCR2 */ + ldr x3, =DEVDISR3_MASK + mov x21, #PMU_IPPDEXPCR2_OFFSET + ldr w4, [x1, x21] + bic w9, w3, w4 + str w9, [x1, x17] + + /* stop the clocks in IPSTPCR3 */ + ldr x5, =DEVDISR4_MASK + mov x21, #PMU_IPPDEXPCR3_OFFSET + ldr w6, [x1, x21] + bic w10, w5, w6 + str w10, [x1, x18] + + /* stop the clocks in IPSTPCR4 + * - exclude the ddr clocks as we are currently executing + * out of *some* memory, might be ddr + * - exclude the OCRAM clk so that we retain any code/data in + * OCRAM + * - may need to exclude the debug clock if we are testing + */ + ldr x3, =DEVDISR5_MASK + mov w6, #DEVDISR5_MASK_ALL_MEM + bic w3, w3, w6 + + mov w5, #POLICY_DEBUG_ENABLE + cbz w5, 3f + mov w6, #DEVDISR5_MASK_DBG + bic w3, w3, w6 +3: + mov x21, #PMU_IPPDEXPCR4_OFFSET + ldr w4, [x1, x21] + bic w11, w3, w4 + str w11, [x1, x19] + + /* stop the clocks in IPSTPCR5 */ + ldr x5, =DEVDISR6_MASK + mov x21, #PMU_IPPDEXPCR5_OFFSET + ldr w6, [x1, x21] + bic w12, w5, w6 + str w12, [x1, x20] + + /* x0 = core mask + * x1 = NXP_PMU_CCSR_ADDR + * x2 = NXP_PMU_DCSR_ADDR + * x7 = IPSTPCR0 + * x8 = IPSTPCR1 + * x9 = IPSTPCR2 + * x10 = IPSTPCR3 + * x11 = IPSTPCR4 + * x12 = IPSTPCR5 + */ + + /* poll until the clocks are stopped in IPSTPACKSR0 */ + mov w4, #CLOCK_RETRY_CNT + mov x21, #PMU_IPSTPACKSR0_OFFSET +4: + ldr w5, [x1, x21] + cmp w5, w7 + b.eq 5f + sub w4, w4, #1 + cbnz w4, 4b + + /* poll until the clocks are stopped in IPSTPACKSR1 */ +5: + mov w4, #CLOCK_RETRY_CNT + mov x21, #PMU_IPSTPACKSR1_OFFSET +6: + ldr w5, [x1, x21] + cmp w5, w8 + b.eq 7f + sub w4, w4, #1 + cbnz w4, 6b + + /* poll until the clocks are stopped in IPSTPACKSR2 */ +7: + mov w4, #CLOCK_RETRY_CNT + mov x21, #PMU_IPSTPACKSR2_OFFSET +8: + ldr w5, [x1, x21] + cmp w5, w9 + b.eq 9f + sub w4, w4, #1 + cbnz w4, 8b + + /* poll until the clocks are stopped in IPSTPACKSR3 */ +9: + mov w4, #CLOCK_RETRY_CNT + mov x21, #PMU_IPSTPACKSR3_OFFSET +10: + ldr w5, [x1, x21] + cmp w5, w10 + b.eq 11f + sub w4, w4, #1 + cbnz w4, 10b + + /* poll until the clocks are stopped in IPSTPACKSR4 */ +11: + mov w4, #CLOCK_RETRY_CNT + mov x21, #PMU_IPSTPACKSR4_OFFSET +12: + ldr w5, [x1, x21] + cmp w5, w11 + b.eq 13f + sub w4, w4, #1 + cbnz w4, 12b + + /* poll until the clocks are stopped in IPSTPACKSR5 */ +13: + mov w4, #CLOCK_RETRY_CNT + mov x21, #PMU_IPSTPACKSR5_OFFSET +14: + ldr w5, [x1, x21] + cmp w5, w12 + b.eq 15f + sub w4, w4, #1 + cbnz w4, 14b + + /* x0 = core mask + * x1 = NXP_PMU_CCSR_ADDR + * x2 = NXP_PMU_DCSR_ADDR + * x7 = IPSTPCR0 + * x8 = IPSTPCR1 + * x9 = IPSTPCR2 + * x10 = IPSTPCR3 + * x11 = IPSTPCR4 + * x12 = IPSTPCR5 + */ + +15: + mov x3, #NXP_DCFG_ADDR + + /* save the devdisr registers to stack */ + ldr w13, [x3, #DCFG_DEVDISR1_OFFSET] + ldr w14, [x3, #DCFG_DEVDISR2_OFFSET] + ldr w15, [x3, #DCFG_DEVDISR3_OFFSET] + ldr w16, [x3, #DCFG_DEVDISR4_OFFSET] + ldr w17, [x3, #DCFG_DEVDISR5_OFFSET] + ldr w18, [x3, #DCFG_DEVDISR6_OFFSET] + + stp x13, x14, [sp, #-16]! + stp x15, x16, [sp, #-16]! + stp x17, x18, [sp, #-16]! + + /* power down the IP in DEVDISR1 - corresponds to IPSTPCR0 */ + str w7, [x3, #DCFG_DEVDISR1_OFFSET] + + /* power down the IP in DEVDISR2 - corresponds to IPSTPCR1 */ + str w8, [x3, #DCFG_DEVDISR2_OFFSET] + + /* power down the IP in DEVDISR3 - corresponds to IPSTPCR2 */ + str w9, [x3, #DCFG_DEVDISR3_OFFSET] + + /* power down the IP in DEVDISR4 - corresponds to IPSTPCR3 */ + str w10, [x3, #DCFG_DEVDISR4_OFFSET] + + /* power down the IP in DEVDISR5 - corresponds to IPSTPCR4 */ + str w11, [x3, #DCFG_DEVDISR5_OFFSET] + + /* power down the IP in DEVDISR6 - corresponds to IPSTPCR5 */ + str w12, [x3, #DCFG_DEVDISR6_OFFSET] + + /* setup register values for the cache-only sequence */ + mov x4, #NXP_DDR_ADDR + mov x5, #NXP_DDR2_ADDR + mov x6, x11 + mov x7, x17 + ldr x12, =PMU_CLAINACTSETR_OFFSET + ldr x13, =PMU_CLSINACTSETR_OFFSET + ldr x14, =PMU_CLAINACTCLRR_OFFSET + ldr x15, =PMU_CLSINACTCLRR_OFFSET + + /* x0 = core mask + * x1 = NXP_PMU_CCSR_ADDR + * x2 = NXP_PMU_DCSR_ADDR + * x3 = NXP_DCFG_ADDR + * x4 = NXP_DDR_ADDR + * x5 = NXP_DDR2_ADDR + * w6 = IPSTPCR4 + * w7 = DEVDISR5 + * x12 = PMU_CLAINACTSETR_OFFSET + * x13 = PMU_CLSINACTSETR_OFFSET + * x14 = PMU_CLAINACTCLRR_OFFSET + * x15 = PMU_CLSINACTCLRR_OFFSET + */ + + mov x8, #POLICY_DEBUG_ENABLE + cbnz x8, 29f + /* force the debug interface to be quiescent */ + mrs x9, OSDLR_EL1 + orr x9, x9, #0x1 + msr OSDLR_EL1, x9 + + /* enter the cache-only sequence */ +29: + bl final_pwrdown + + /* when we are here, the core has come out of wfi and the + * ddr is back up + */ + + mov x8, #POLICY_DEBUG_ENABLE + cbnz x8, 30f + /* restart the debug interface */ + mrs x9, OSDLR_EL1 + mov x10, #1 + bic x9, x9, x10 + msr OSDLR_EL1, x9 + + /* get saved DEVDISR regs off stack */ +30: + ldp x17, x18, [sp], #16 + ldp x15, x16, [sp], #16 + ldp x13, x14, [sp], #16 + /* restore DEVDISR regs */ + str w18, [x3, #DCFG_DEVDISR6_OFFSET] + str w17, [x3, #DCFG_DEVDISR5_OFFSET] + str w16, [x3, #DCFG_DEVDISR4_OFFSET] + str w15, [x3, #DCFG_DEVDISR3_OFFSET] + str w14, [x3, #DCFG_DEVDISR2_OFFSET] + str w13, [x3, #DCFG_DEVDISR1_OFFSET] + isb + + /* get saved IPSTPCRn regs off stack */ + ldp x13, x14, [sp], #16 + ldp x11, x12, [sp], #16 + ldp x9, x10, [sp], #16 + + /* restore IPSTPCRn regs */ + mov x15, #PMU_IPSTPCR5_OFFSET + str w14, [x1, x15] + mov x16, #PMU_IPSTPCR4_OFFSET + str w13, [x1, x16] + mov x17, #PMU_IPSTPCR3_OFFSET + str w12, [x1, x17] + mov x18, #PMU_IPSTPCR2_OFFSET + str w11, [x1, x18] + mov x19, #PMU_IPSTPCR1_OFFSET + str w10, [x1, x19] + mov x20, #PMU_IPSTPCR0_OFFSET + str w9, [x1, x20] + isb + + /* poll on IPSTPACKCRn regs til IP clocks are restarted */ + mov w4, #CLOCK_RETRY_CNT + mov x15, #PMU_IPSTPACKSR5_OFFSET +16: + ldr w5, [x1, x15] + and w5, w5, w14 + cbz w5, 17f + sub w4, w4, #1 + cbnz w4, 16b + +17: + mov w4, #CLOCK_RETRY_CNT + mov x15, #PMU_IPSTPACKSR4_OFFSET +18: + ldr w5, [x1, x15] + and w5, w5, w13 + cbz w5, 19f + sub w4, w4, #1 + cbnz w4, 18b + +19: + mov w4, #CLOCK_RETRY_CNT + mov x15, #PMU_IPSTPACKSR3_OFFSET +20: + ldr w5, [x1, x15] + and w5, w5, w12 + cbz w5, 21f + sub w4, w4, #1 + cbnz w4, 20b + +21: + mov w4, #CLOCK_RETRY_CNT + mov x15, #PMU_IPSTPACKSR2_OFFSET +22: + ldr w5, [x1, x15] + and w5, w5, w11 + cbz w5, 23f + sub w4, w4, #1 + cbnz w4, 22b + +23: + mov w4, #CLOCK_RETRY_CNT + mov x15, #PMU_IPSTPACKSR1_OFFSET +24: + ldr w5, [x1, x15] + and w5, w5, w10 + cbz w5, 25f + sub w4, w4, #1 + cbnz w4, 24b + +25: + mov w4, #CLOCK_RETRY_CNT + mov x15, #PMU_IPSTPACKSR0_OFFSET +26: + ldr w5, [x1, x15] + and w5, w5, w9 + cbz w5, 27f + sub w4, w4, #1 + cbnz w4, 26b + +27: + /* disable the stop-request-override */ + mov x8, #PMU_POWMGTDCR0_OFFSET + mov w9, #POWMGTDCR_STP_OV_EN + str w9, [x2, x8] + isb + + /* get hnf-sdcr and cpuactlr off stack */ + ldp x7, x8, [sp], #16 + + /* restore cpuactlr */ + msr CORTEX_A72_CPUACTLR_EL1, x8 + isb + + /* restore snooping in the hnf nodes */ + ldr x9, =NXP_CCN_HN_F_0_ADDR + mov x6, #CCN_HNF_NODE_COUNT +28: + str x7, [x9, #CCN_HN_F_SNP_DMN_CTL_SET_OFFSET] + sub x6, x6, #1 + add x9, x9, #CCN_HNF_OFFSET + cbnz x6, 28b + isb + + mov x30, x28 + ret +endfunc _soc_sys_pwrdn_wfi + + +/* Part of CPU_SUSPEND + * Function performs any SoC-specific cleanup after power-down + * in: x0 = core mask lsb + * out: none + * uses x0, + */ +func _soc_sys_exit_pwrdn + + mrs x1, CORTEX_A72_ECTLR_EL1 + /* make sure the smp bit is set */ + orr x1, x1, #CPUECTLR_SMPEN_MASK + /* clr the retention control */ + mov x2, #CPUECTLR_RET_8CLK + bic x1, x1, x2 + /* enable tablewalk prefetch */ + mov x2, #CPUECTLR_DISABLE_TWALK_PREFETCH + bic x1, x1, x2 + msr CORTEX_A72_ECTLR_EL1, x1 + isb + + ret +endfunc _soc_sys_exit_pwrdn + + +/* Function will pwrdown ddr and the final core - it will do this + * by loading itself into the icache and then executing from there + * in: + * x0 = core mask + * x1 = NXP_PMU_CCSR_ADDR + * x2 = NXP_PMU_DCSR_ADDR + * x3 = NXP_DCFG_ADDR + * x4 = NXP_DDR_ADDR + * x5 = NXP_DDR2_ADDR + * w6 = IPSTPCR4 + * w7 = DEVDISR5 + * x12 = PMU_CLAINACTSETR_OFFSET + * x13 = PMU_CLSINACTSETR_OFFSET + * x14 = PMU_CLAINACTCLRR_OFFSET + * x15 = PMU_CLSINACTCLRR_OFFSET + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x13, x14, x15, x16, + * x17, x18 + */ + +/* 4Kb aligned */ +.align 12 +func final_pwrdown + + mov x0, xzr + b touch_line_0 +start_line_0: + mov x0, #1 + /* put ddr controller 1 into self-refresh */ + ldr w8, [x4, #DDR_CFG_2_OFFSET] + orr w8, w8, #CFG_2_FORCE_REFRESH + str w8, [x4, #DDR_CFG_2_OFFSET] + + /* put ddr controller 2 into self-refresh */ + ldr w8, [x5, #DDR_CFG_2_OFFSET] + orr w8, w8, #CFG_2_FORCE_REFRESH + str w8, [x5, #DDR_CFG_2_OFFSET] + + /* stop the clocks in both ddr controllers */ + mov w10, #DEVDISR5_MASK_DDR + mov x16, #PMU_IPSTPCR4_OFFSET + orr w9, w6, w10 + str w9, [x1, x16] + isb + + mov x17, #PMU_IPSTPACKSR4_OFFSET +touch_line_0: + cbz x0, touch_line_1 + +start_line_1: + /* poll IPSTPACKSR4 until + * ddr controller clocks are stopped. + */ +1: + ldr w8, [x1, x17] + and w8, w8, w10 + cmp w8, w10 + b.ne 1b + + /* shut down power to the ddr controllers */ + orr w9, w7, #DEVDISR5_MASK_DDR + str w9, [x3, #DCFG_DEVDISR5_OFFSET] + + /* disable cluster acp ports */ + mov w8, #CLAINACT_DISABLE_ACP + str w8, [x1, x12] + + /* disable skyros ports */ + mov w9, #CLSINACT_DISABLE_SKY + str w9, [x1, x13] + isb + +touch_line_1: + cbz x0, touch_line_2 + +start_line_2: + isb +3: + wfi + + /* if we are here then we are awake + * - bring this device back up + */ + + /* enable skyros ports */ + mov w9, #CLSINACT_DISABLE_SKY + str w9, [x1, x15] + + /* enable acp ports */ + mov w8, #CLAINACT_DISABLE_ACP + str w8, [x1, x14] + isb + + /* bring up the ddr controllers */ + str w7, [x3, #DCFG_DEVDISR5_OFFSET] + isb + str w6, [x1, x16] + isb + + nop +touch_line_2: + cbz x0, touch_line_3 + +start_line_3: + /* poll IPSTPACKSR4 until + * ddr controller clocks are running + */ + mov w10, #DEVDISR5_MASK_DDR +2: + ldr w8, [x1, x17] + and w8, w8, w10 + cbnz w8, 2b + + /* take ddr controller 2 out of self-refresh */ + mov w8, #CFG_2_FORCE_REFRESH + ldr w9, [x5, #DDR_CFG_2_OFFSET] + bic w9, w9, w8 + str w9, [x5, #DDR_CFG_2_OFFSET] + + /* take ddr controller 1 out of self-refresh */ + ldr w9, [x4, #DDR_CFG_2_OFFSET] + bic w9, w9, w8 + str w9, [x4, #DDR_CFG_2_OFFSET] + isb + + nop + nop + nop +touch_line_3: + cbz x0, start_line_0 + + /* execute here after ddr is back up */ + + ret +endfunc final_pwrdown + +/* Function returns CLUSTER_3_NORMAL if the cores of cluster 3 are + * to be handled normally, and it returns CLUSTER_3_IN_RESET if the cores + * are to be held in reset + * in: none + * out: x0 = #CLUSTER_3_NORMAL, cluster 3 treated normal + * x0 = #CLUSTER_3_IN_RESET, cluster 3 cores held in reset + * uses x0, x1, x2 + */ +func cluster3InReset + + /* default return is treat cores normal */ + mov x0, #CLUSTER_3_NORMAL + + /* read RCW_SR27 register */ + mov x1, #NXP_DCFG_ADDR + ldr w2, [x1, #RCW_SR27_OFFSET] + + /* test the cluster 3 bit */ + tst w2, #CLUSTER_3_RCW_BIT + b.eq 1f + + /* if we are here, then the bit was set */ + mov x0, #CLUSTER_3_IN_RESET +1: + ret +endfunc cluster3InReset + + +/* Function checks to see if cores which are to be disabled have been + * released from reset - if not, it releases them + * Note: there may be special handling of cluster 3 cores depending upon the + * sys clk frequency + * in: none + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9 + */ +func release_disabled + mov x9, x30 + + /* check if we need to keep cluster 3 cores in reset */ + bl cluster3InReset /* 0-2 */ + mov x8, x0 + + /* x8 = cluster 3 handling */ + + /* read COREDISABLESR */ + mov x0, #NXP_DCFG_ADDR + ldr w4, [x0, #DCFG_COREDISABLEDSR_OFFSET] + cmp x8, #CLUSTER_3_IN_RESET + b.ne 4f + + /* the cluster 3 cores are to be held in reset, so remove + * them from the disable mask + */ + bic x4, x4, #CLUSTER_3_CORES_MASK +4: + /* 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 5f + + /* 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_STATE_DATA + mov x2, #CORE_DISABLED + bl _setCoreData + +1: + /* see if this is a cluster 3 core */ + mov x3, #CLUSTER_3_CORES_MASK + tst x3, x7 + b.eq 5f + + /* this is a cluster 3 core - see if it needs to be held in reset */ + cmp x8, #CLUSTER_3_IN_RESET + b.ne 5f + + /* record the core state as disabled in the data area (0-3) */ + mov x0, x7 + mov x1, #CORE_STATE_DATA + mov x2, #CORE_DISABLED + bl _setCoreData + +5: + /* 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: + cmp x8, #CLUSTER_3_IN_RESET + b.ne 6f + + /* we need to hold the cluster 3 cores in reset, + * so mark them in the COREDISR and COREDISABLEDSR registers as + * "disabled", and the rest of the sw stack will leave them alone + * thinking that they have been disabled + */ + mov x0, #NXP_DCFG_ADDR + ldr w1, [x0, #DCFG_COREDISR_OFFSET] + orr w1, w1, #CLUSTER_3_CORES_MASK + str w1, [x0, #DCFG_COREDISR_OFFSET] + + ldr w2, [x0, #DCFG_COREDISABLEDSR_OFFSET] + orr w2, w2, #CLUSTER_3_CORES_MASK + str w2, [x0, #DCFG_COREDISABLEDSR_OFFSET] + dsb sy + isb + +#if (PSCI_TEST) + /* x0 = NXP_DCFG_ADDR : read COREDISABLESR */ + ldr w4, [x0, #DCFG_COREDISABLEDSR_OFFSET] + /* read COREDISR */ + ldr w3, [x0, #DCFG_COREDISR_OFFSET] +#endif + +6: + mov x30, x9 + ret + +endfunc release_disabled + + +/* Function setc up the TrustZone Address Space Controller (TZASC) + * in: none + * out: none + * uses x0, x1 + */ +func 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, =TZPC_BASE + /* 0x00000000 = no secure region */ + mov w0, #0x00000000 + str w0, [x1] + + ret +endfunc init_tzpc + +/* write a register in the DCFG block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2 + */ +func _write_reg_dcfg + ldr x2, =NXP_DCFG_ADDR + str w1, [x2, x0] + ret +endfunc _write_reg_dcfg + + +/* read a register in the DCFG block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +func _read_reg_dcfg + ldr x2, =NXP_DCFG_ADDR + ldr w1, [x2, x0] + mov w0, w1 + ret +endfunc _read_reg_dcfg + + +/* 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 + */ +func get_mpidr_value + + /* convert a core mask to an SoC core number */ + clz w0, w0 + mov w1, #31 + sub w0, w1, w0 + + /* get the mpidr core number from the SoC core number */ + mov w1, wzr + tst x0, #1 + b.eq 1f + orr w1, w1, #1 + +1: + /* extract the cluster number */ + lsr w0, w0, #1 + orr w0, w1, w0, lsl #8 + + ret +endfunc get_mpidr_value + + +/* 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 + */ +func get_gic_rd_base + clz w1, w0 + mov w2, #0x20 + sub w2, w2, w1 + sub w2, w2, #1 + + ldr x0, =NXP_GICR_ADDR + mov x1, #GIC_RD_OFFSET + + /* x2 = core number + * loop counter + */ +2: + cbz x2, 1f + add x0, x0, x1 + sub x2, x2, #1 + b 2b +1: + ret +endfunc get_gic_rd_base + + +/* 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 + */ +func get_gic_sgi_base + clz w1, w0 + mov w2, #0x20 + sub w2, w2, w1 + sub w2, w2, #1 + + ldr x0, =NXP_GICR_SGI_ADDR + mov x1, #GIC_SGI_OFFSET + + /* loop counter */ +2: + cbz x2, 1f /* x2 = core number */ + add x0, x0, x1 + sub x2, x2, #1 + b 2b +1: + ret +endfunc get_gic_sgi_base + +/* Function writes a register in the RESET block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2 + */ +func _write_reg_reset + ldr x2, =NXP_RESET_ADDR + str w1, [x2, x0] + ret +endfunc _write_reg_reset + + +/* Function reads a register in the RESET block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1 + */ +func _read_reg_reset + ldr x1, =NXP_RESET_ADDR + ldr w0, [x1, x0] + ret +endfunc _read_reg_reset diff --git a/plat/nxp/soc-lx2160a/aarch64/lx2160a_helpers.S b/plat/nxp/soc-lx2160a/aarch64/lx2160a_helpers.S new file mode 100644 index 0000000..c364dec --- /dev/null +++ b/plat/nxp/soc-lx2160a/aarch64/lx2160a_helpers.S @@ -0,0 +1,77 @@ +/* + * Copyright 2018-2020 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 + /* lx2160a 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-lx2160a/aarch64/lx2160a_warm_rst.S b/plat/nxp/soc-lx2160a/aarch64/lx2160a_warm_rst.S new file mode 100644 index 0000000..9dec3f2 --- /dev/null +++ b/plat/nxp/soc-lx2160a/aarch64/lx2160a_warm_rst.S @@ -0,0 +1,229 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +.section .text, "ax" + +#include <asm_macros.S> + +#ifndef NXP_COINED_BB +#include <flash_info.h> +#include <fspi.h> +#endif +#include <regs.h> +#ifdef NXP_COINED_BB +#include <snvs.h> +#endif + +#include <plat_warm_rst.h> +#include <platform_def.h> + +#define SDRAM_CFG 0x110 +#define SDRAM_CFG_2 0x114 +#define SDRAM_MD_CNTL 0x120 +#define SDRAM_INTERVAL 0x124 +#define TIMING_CFG_10 0x258 +#define DEBUG_2 0xF04 +#define DEBUG_26 0xF64 +#define DDR_DSR2 0xB24 + +#define DDR_CNTRLR_2 0x2 +#define COUNT_100 1000 + + .globl _soc_sys_warm_reset + .align 12 + +func _soc_sys_warm_reset + mov x3, xzr + b touch_line0 +start_line0: + mov x3, #1 + mov x2, #NUM_OF_DDRC + ldr x1, =NXP_DDR_ADDR +1: + ldr w0, [x1, #SDRAM_CFG] + orr w0, w0, #SDRAM_CFG_MEM_HLT + str w0, [x1, #SDRAM_CFG] +2: + ldr w0, [x1, #DEBUG_2] + and w0, w0, #DDR_DBG_2_MEM_IDLE + cbz w0, 2b + + ldr w0, [x1, #DEBUG_26] + orr w0, w0, #DDR_DEBUG_26_BIT_12 + orr w0, w0, #DDR_DEBUG_26_BIT_13 + orr w0, w0, #DDR_DEBUG_26_BIT_14 +touch_line0: + cbz x3, touch_line1 + + orr w0, w0, #DDR_DEBUG_26_BIT_15 + orr w0, w0, #DDR_DEBUG_26_BIT_16 + str w0, [x1, #DEBUG_26] + + ldr w0, [x1, #SDRAM_CFG_2] + orr w0, w0, #SDRAM_CFG2_FRC_SR + str w0, [x1, #SDRAM_CFG_2] + +3: + ldr w0, [x1, #DDR_DSR2] + orr w0, w0, #DDR_DSR_2_PHY_INIT_CMPLT + str w0, [x1, #DDR_DSR2] + ldr w0, [x1, #DDR_DSR2] + and w0, w0, #DDR_DSR_2_PHY_INIT_CMPLT + cbnz w0, 3b + + ldr w0, [x1, #SDRAM_INTERVAL] + and w0, w0, #SDRAM_INTERVAL_REFINT_CLEAR + str w0, [x1, #SDRAM_INTERVAL] +touch_line1: + cbz x3, touch_line2 + + ldr w0, [x1, #SDRAM_MD_CNTL] + orr w0, w0, #MD_CNTL_CKE(1) + orr w0, w0, #MD_CNTL_MD_EN + str w0, [x1, #SDRAM_MD_CNTL] + + ldr w0, [x1, #TIMING_CFG_10] + orr w0, w0, #DDR_TIMING_CFG_10_T_STAB + str w0, [x1, #TIMING_CFG_10] + + ldr w0, [x1, #SDRAM_CFG_2] + and w0, w0, #SDRAM_CFG2_FRC_SR_CLEAR + str w0, [x1, #SDRAM_CFG_2] + +4: + ldr w0, [x1, #DDR_DSR2] + and w0, w0, #DDR_DSR_2_PHY_INIT_CMPLT + cbz w0, 4b + nop +touch_line2: + cbz x3, touch_line3 + + ldr w0, [x1, #DEBUG_26] + orr w0, w0, #DDR_DEBUG_26_BIT_25 + and w0, w0, #DDR_DEBUG_26_BIT_24_CLEAR + str w0, [x1, #DEBUG_26] + + cmp x2, #DDR_CNTRLR_2 + b.ne 5f + ldr x1, =NXP_DDR2_ADDR + mov x2, xzr + b 1b + +5: + mov x5, xzr +6: + add x5, x5, #1 + cmp x5, #COUNT_100 + b.ne 6b + nop +touch_line3: + cbz x3, touch_line4 +#ifdef NXP_COINED_BB + ldr x1, =NXP_SNVS_ADDR + ldr w0, [x1, #NXP_APP_DATA_LP_GPR_OFFSET] + + /* On Warm Boot is enabled, then zeroth bit + * of SNVS LP GPR register 0 will used + * to save the status of warm-reset as a cause. + */ + orr w0, w0, #(1 << NXP_LPGPR_ZEROTH_BIT) + + /* write back */ + str w0, [x1, #NXP_APP_DATA_LP_GPR_OFFSET] + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop +touch_line4: + cbz x3, touch_line6 +#elif !(ERLY_WRM_RST_FLG_FLSH_UPDT) + ldr x1, =NXP_FLEXSPI_ADDR + ldr w0, [x1, #FSPI_IPCMD] + orr w0, w0, #FSPI_IPCMD_TRG_MASK + str w0, [x1, #FSPI_IPCMD] +7: + ldr w0, [x1, #FSPI_INTR] + and w0, w0, #FSPI_INTR_IPCMDDONE_MASK + cmp w0, #0 + b.eq 7b + + ldr w0, [x1, #FSPI_IPTXFCR] + orr w0, w0, #FSPI_IPTXFCR_CLR + str w0, [x1, #FSPI_IPTXFCR] + + ldr w0, [x1, #FSPI_INTR] + orr w0, w0, #FSPI_INTR_IPCMDDONE_MASK + str w0, [x1, #FSPI_INTR] + nop +touch_line4: + cbz x3, touch_line5 + /* flexspi driver has an api + * is_flash_busy(). + * Impelementation of the api will not + * fit-in in 1 cache line. + * instead a nop-cycles are introduced to + * simulate the wait time for flash write + * completion. + * + * Note: This wait time varies from flash to flash. + */ + + mov x0, #FLASH_WR_COMP_WAIT_BY_NOP_COUNT +8: + sub x0, x0, #1 + nop + cmp x0, #0 + b.ne 8b + nop + nop + nop + nop + nop + nop + nop + nop + nop +touch_line5: + cbz x3, touch_line6 +#endif + ldr x2, =NXP_RST_ADDR + /* clear the RST_REQ_MSK and SW_RST_REQ */ + mov w0, #0x00000000 + str w0, [x2, #RSTCNTL_OFFSET] + + /* initiate the sw reset request */ + mov w0, #SW_RST_REQ_INIT + str w0, [x2, #RSTCNTL_OFFSET] + + /* In case this address range is mapped as cacheable, + * flush the write out of the dcaches. + */ + add x2, x2, #RSTCNTL_OFFSET + dc cvac, x2 + dsb st + isb + + /* Function does not return */ + b . + nop + nop + nop + nop + nop + nop + nop +touch_line6: + cbz x3, start_line0 + +endfunc _soc_sys_warm_reset diff --git a/plat/nxp/soc-lx2160a/ddr_fip.mk b/plat/nxp/soc-lx2160a/ddr_fip.mk new file mode 100644 index 0000000..f14a9e8 --- /dev/null +++ b/plat/nxp/soc-lx2160a/ddr_fip.mk @@ -0,0 +1,97 @@ +# +# Copyright 2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +DDR_PHY_BIN_PATH ?= ./ddr-phy-binary/lx2160a + +ifeq (${DDR_IMEM_UDIMM_1D},) + DDR_IMEM_UDIMM_1D := ${DDR_PHY_BIN_PATH}/ddr4_pmu_train_imem.bin +endif + +ifeq (${DDR_IMEM_UDIMM_2D},) + DDR_IMEM_UDIMM_2D := ${DDR_PHY_BIN_PATH}/ddr4_2d_pmu_train_imem.bin +endif + +ifeq (${DDR_DMEM_UDIMM_1D},) + DDR_DMEM_UDIMM_1D := ${DDR_PHY_BIN_PATH}/ddr4_pmu_train_dmem.bin +endif + +ifeq (${DDR_DMEM_UDIMM_2D},) + DDR_DMEM_UDIMM_2D := ${DDR_PHY_BIN_PATH}/ddr4_2d_pmu_train_dmem.bin +endif + +ifeq (${DDR_IMEM_RDIMM_1D},) + DDR_IMEM_RDIMM_1D := ${DDR_PHY_BIN_PATH}/ddr4_rdimm_pmu_train_imem.bin +endif + +ifeq (${DDR_IMEM_RDIMM_2D},) + DDR_IMEM_RDIMM_2D := ${DDR_PHY_BIN_PATH}/ddr4_rdimm2d_pmu_train_imem.bin +endif + +ifeq (${DDR_DMEM_RDIMM_1D},) + DDR_DMEM_RDIMM_1D := ${DDR_PHY_BIN_PATH}/ddr4_rdimm_pmu_train_dmem.bin +endif + +ifeq (${DDR_DMEM_RDIMM_2D},) + DDR_DMEM_RDIMM_2D := ${DDR_PHY_BIN_PATH}/ddr4_rdimm2d_pmu_train_dmem.bin +endif + +$(shell mkdir -p '${BUILD_PLAT}') + +ifeq (${DDR_FIP_NAME},) +ifeq (${TRUSTED_BOARD_BOOT},1) + DDR_FIP_NAME := ddr_fip_sec.bin +else + DDR_FIP_NAME := ddr_fip.bin +endif +endif + +ifneq (${TRUSTED_BOARD_BOOT},1) + +DDR_FIP_ARGS += --ddr-immem-udimm-1d ${DDR_IMEM_UDIMM_1D} \ + --ddr-immem-udimm-2d ${DDR_IMEM_UDIMM_2D} \ + --ddr-dmmem-udimm-1d ${DDR_DMEM_UDIMM_1D} \ + --ddr-dmmem-udimm-2d ${DDR_DMEM_UDIMM_2D} \ + --ddr-immem-rdimm-1d ${DDR_IMEM_RDIMM_1D} \ + --ddr-immem-rdimm-2d ${DDR_IMEM_RDIMM_2D} \ + --ddr-dmmem-rdimm-1d ${DDR_DMEM_RDIMM_1D} \ + --ddr-dmmem-rdimm-2d ${DDR_DMEM_RDIMM_2D} +endif + + +ifeq (${TRUSTED_BOARD_BOOT},1) +ifeq (${MBEDTLS_DIR},) +include plat/nxp/soc-lx2160a/ddr_sb.mk +else +include plat/nxp/soc-lx2160a/ddr_tbbr.mk + +# Variables for use with Certificate Generation Tool +CRTTOOLPATH ?= tools/cert_create +CRTTOOL ?= ${CRTTOOLPATH}/cert_create${BIN_EXT} + +ifneq (${GENERATE_COT},0) +ddr_certificates: ${DDR_CRT_DEPS} ${CRTTOOL} + ${Q}${CRTTOOL} ${DDR_CRT_ARGS} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @echo "DDR certificates can be found in ${BUILD_PLAT}" + @${ECHO_BLANK_LINE} +endif +endif +endif + +# Variables for use with Firmware Image Package +FIPTOOLPATH ?= tools/fiptool +FIPTOOL ?= ${FIPTOOLPATH}/fiptool${BIN_EXT} + +${BUILD_PLAT}/${DDR_FIP_NAME}: ${DDR_FIP_DEPS} ${FIPTOOL} + $(eval ${CHECK_DDR_FIP_CMD}) + ${Q}${FIPTOOL} create ${DDR_FIP_ARGS} $@ + ${Q}${FIPTOOL} info $@ + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +fip_ddr: ${BUILD_PLAT}/${DDR_FIP_NAME} diff --git a/plat/nxp/soc-lx2160a/ddr_sb.mk b/plat/nxp/soc-lx2160a/ddr_sb.mk new file mode 100644 index 0000000..c11651e --- /dev/null +++ b/plat/nxp/soc-lx2160a/ddr_sb.mk @@ -0,0 +1,43 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifneq (${TRUSTED_BOARD_BOOT},0) + +ifeq (${GENERATE_COT},0) + +DDR_FIP_ARGS += --ddr-immem-udimm-1d ${DDR_IMEM_UDIMM_1D}.sb \ + --ddr-immem-udimm-2d ${DDR_IMEM_UDIMM_2D}.sb \ + --ddr-dmmem-udimm-1d ${DDR_DMEM_UDIMM_1D}.sb \ + --ddr-dmmem-udimm-2d ${DDR_DMEM_UDIMM_2D}.sb \ + --ddr-immem-rdimm-1d ${DDR_IMEM_RDIMM_1D}.sb \ + --ddr-immem-rdimm-2d ${DDR_IMEM_RDIMM_2D}.sb \ + --ddr-dmmem-rdimm-1d ${DDR_DMEM_RDIMM_1D}.sb \ + --ddr-dmmem-rdimm-2d ${DDR_DMEM_RDIMM_2D}.sb +endif + +UDIMM_DEPS = ${DDR_IMEM_UDIMM_1D}.sb ${DDR_IMEM_UDIMM_2D}.sb ${DDR_DMEM_UDIMM_1D}.sb ${DDR_DMEM_UDIMM_2D}.sb +RDIMM_DEPS = ${DDR_IMEM_RDIMM_1D}.sb ${DDR_IMEM_RDIMM_2D}.sb ${DDR_DMEM_RDIMM_1D}.sb ${DDR_DMEM_RDIMM_2D}.sb +DDR_FIP_DEPS += ${UDIMM_DEPS} +DDR_FIP_DEPS += ${RDIMM_DEPS} + +# Max Size of CSF header (CSF_HDR_SZ = 0x3000). +# Image will be appended at this offset of the header. +# Path to CST directory is required to generate the CSF header, +# and prepend it to image before fip image gets generated +ifeq (${CST_DIR},) + $(error Error: CST_DIR not set) +endif + +ifeq (${DDR_INPUT_FILE},) +DDR_INPUT_FILE:= drivers/nxp/auth/csf_hdr_parser/${CSF_FILE} +endif + +%.sb: % + @echo " Generating CSF Header for $@ $<" + $(CST_DIR)/create_hdr_esbc --in $< --out $@ --app_off ${CSF_HDR_SZ} \ + --app $< ${DDR_INPUT_FILE} + +endif diff --git a/plat/nxp/soc-lx2160a/ddr_tbbr.mk b/plat/nxp/soc-lx2160a/ddr_tbbr.mk new file mode 100644 index 0000000..deb475b --- /dev/null +++ b/plat/nxp/soc-lx2160a/ddr_tbbr.mk @@ -0,0 +1,95 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# This file defines the keys and certificates that must be created to establish +# a Chain of Trust for the DDR FW. These definitions include the +# command line options passed to the cert_create and fiptool commands for DDR FW. +# A DDR FW key is used for signing the DDR Firmware. The DDR key is authenticated +# by the Trusted World Key. Two content certificates are created: +# For DDR RDIMM Images [ signed by DDR FW Key] +# For DDR UDIMM Images [ signed by DDR FW Key] +# +# Expected environment: +# +# BUILD_PLAT: output directory +# +# Build options added by this file: +# +# KEY_ALG +# KEY_SIZE +# TRUSTED_WORLD_KEY +# NON_TRUSTED_WORLD_KEY +# + +# Copy the tbbr.mk from PLAT_TOOL_PATH/cert_create_helper +# to the ${PLAT_DIR}. So that cert_create is enabled +# to create certificates for DDR +$(shell cp ${PLAT_TOOL_PATH}/cert_create_helper/cert_create_tbbr.mk ${PLAT_DIR}) + +# Certificate generation tool default parameters +DDR_FW_CERT := ${BUILD_PLAT}/ddr_fw_key_cert.crt + +# Default non-volatile counter values (overridable by the platform) +TFW_NVCTR_VAL ?= 0 +NTFW_NVCTR_VAL ?= 0 + +# Pass the non-volatile counters to the cert_create tool +$(eval $(call CERT_ADD_CMD_OPT,${TFW_NVCTR_VAL},--tfw-nvctr,DDR_)) + +$(shell mkdir -p '${BUILD_PLAT}') + +ifeq (${DDR_KEY},) +DDR_KEY=${BUILD_PLAT}/ddr.pem +endif + +ifeq (${TRUSTED_KEY_CERT},) +$(info Generating: Trusted key certificate as part of DDR cert creation) +TRUSTED_KEY_CERT := ${BUILD_PLAT}/trusted_key.crt +$(eval $(call TOOL_ADD_PAYLOAD,${TRUSTED_KEY_CERT},--trusted-key-cert,)) +$(eval $(call TOOL_ADD_PAYLOAD,${TRUSTED_KEY_CERT},--trusted-key-cert,,DDR_)) +else +$(info Using: Trusted key certificate as part of DDR cert creation) +DDR_FIP_ARGS += --trusted-key-cert ${TRUSTED_KEY_CERT} +endif + +# Add the keys to the cert_create command line options (private keys are NOT +# packed in the FIP). Developers can use their own keys by specifying the proper +# build option in the command line when building the Trusted Firmware +$(if ${KEY_ALG},$(eval $(call CERT_ADD_CMD_OPT,${KEY_ALG},--key-alg,DDR_))) +$(if ${KEY_SIZE},$(eval $(call CERT_ADD_CMD_OPT,${KEY_SIZE},--key-size,DDR_))) +$(if ${HASH_ALG},$(eval $(call CERT_ADD_CMD_OPT,${HASH_ALG},--hash-alg,DDR_))) +$(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key,DDR_))) +$(if ${TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${TRUSTED_WORLD_KEY},--trusted-world-key,DDR_))) +$(if ${NON_TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${NON_TRUSTED_WORLD_KEY},--non-trusted-world-key, DDR_))) + +# Add the DDR CoT (key cert + img cert) +$(if ${DDR_KEY},$(eval $(call CERT_ADD_CMD_OPT,${DDR_KEY},--ddr-fw-key,DDR_))) +$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/ddr_fw_key.crt,--ddr-fw-key-cert,,DDR_)) +$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/ddr_udimm_fw_content.crt,--ddr-udimm-fw-cert,,DDR_)) +$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/ddr_rdimm_fw_content.crt,--ddr-rdimm-fw-cert,,DDR_)) + +$(eval $(call TOOL_ADD_IMG,DDR_IMEM_UDIMM_1D,--ddr-immem-udimm-1d,DDR_)) +$(eval $(call TOOL_ADD_IMG,DDR_IMEM_UDIMM_2D,--ddr-immem-udimm-2d,DDR_)) +$(eval $(call TOOL_ADD_IMG,DDR_DMEM_UDIMM_1D,--ddr-dmmem-udimm-1d,DDR_)) +$(eval $(call TOOL_ADD_IMG,DDR_DMEM_UDIMM_2D,--ddr-dmmem-udimm-2d,DDR_)) + +$(eval $(call TOOL_ADD_IMG,DDR_IMEM_RDIMM_1D,--ddr-immem-rdimm-1d,DDR_)) +$(eval $(call TOOL_ADD_IMG,DDR_IMEM_RDIMM_2D,--ddr-immem-rdimm-2d,DDR_)) +$(eval $(call TOOL_ADD_IMG,DDR_DMEM_RDIMM_1D,--ddr-dmmem-rdimm-1d,DDR_)) +$(eval $(call TOOL_ADD_IMG,DDR_DMEM_RDIMM_2D,--ddr-dmmem-rdimm-2d,DDR_)) + +DDR_FIP_DEPS += ddr_certificates + +# Process TBB related flags +ifneq (${GENERATE_COT},0) + # Common cert_create options + ifneq (${CREATE_KEYS},0) + $(eval DDR_CRT_ARGS += -n) + ifneq (${SAVE_KEYS},0) + $(eval DDR_CRT_ARGS += -k) + endif + endif +endif diff --git a/plat/nxp/soc-lx2160a/include/soc.h b/plat/nxp/soc-lx2160a/include/soc.h new file mode 100644 index 0000000..b781ff8 --- /dev/null +++ b/plat/nxp/soc-lx2160a/include/soc.h @@ -0,0 +1,164 @@ +/* + * Copyright 2018-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_lsch3.h> +#include <soc_default_base_addr.h> +#include <soc_default_helper_macros.h> + + +#define NUM_DRAM_REGIONS 3 +#define NXP_DRAM0_ADDR 0x80000000 +#define NXP_DRAM0_MAX_SIZE 0x80000000 /* 2 GB */ + +#define NXP_DRAM1_ADDR 0x2080000000 +#define NXP_DRAM1_MAX_SIZE 0x1F80000000 /* 126 G */ + +#define NXP_DRAM2_ADDR 0x6000000000 +#define NXP_DRAM2_MAX_SIZE 0x2000000000 /* 128G */ + +/*DRAM0 Size defined in platform_def.h */ +#define NXP_DRAM0_SIZE PLAT_DEF_DRAM0_SIZE + +#define DDR_PLL_FIX +#define NXP_DDR_PHY1_ADDR 0x01400000 +#define NXP_DDR_PHY2_ADDR 0x01600000 + +#if defined(IMAGE_BL31) +#define LS_SYS_TIMCTL_BASE 0x2890000 + +#ifdef LS_SYS_TIMCTL_BASE +#define PLAT_LS_NSTIMER_FRAME_ID 0 +#define LS_CONFIG_CNTACR 1 +#endif +#endif + +/* Start: Macros used by soc.c: get_boot_dev */ +#define PORSR1_RCW_MASK 0x07800000 +#define PORSR1_RCW_SHIFT 23 + +#define SDHC1_VAL 0x8 +#define SDHC2_VAL 0x9 +#define I2C1_VAL 0xa +#define FLEXSPI_NAND2K_VAL 0xc +#define FLEXSPI_NAND4K_VAL 0xd +#define FLEXSPI_NOR 0xf +/* End: Macros used by soc.c: get_boot_dev */ + +/* SVR Definition (not include major and minor rev) */ +#define SVR_LX2160A 0x873601 +#define SVR_LX2160E 0x873610 +#define SVR_LX2160C 0x873600 +#define SVR_LX2160N 0x873611 +#define SVR_LX2120A 0x873621 +#define SVR_LX2120E 0x873630 +#define SVR_LX2120C 0x873620 +#define SVR_LX2120N 0x873631 +#define SVR_LX2080A 0x873603 +#define SVR_LX2080E 0x873612 +#define SVR_LX2080C 0x873602 +#define SVR_LX2080N 0x873613 + +/* SVR Definition of SoC LX2162A. */ +#define SVR_LX2162A 0x873609 +#define SVR_LX2162E 0x873618 +#define SVR_LX2162C 0x873608 +#define SVR_LX2162N 0x873619 +#define SVR_LX2122A 0x873629 +#define SVR_LX2122E 0x873638 +#define SVR_LX2122C 0x873628 +#define SVR_LX2122N 0x873639 +#define SVR_LX2082A 0x87360b +#define SVR_LX2082E 0x87361a +#define SVR_LX2082C 0x87360a +#define SVR_LX2082N 0x87361b + +/* Number of cores in platform */ +/* Used by common code for array initialization */ +#define NUMBER_OF_CLUSTERS 8 +#define CORES_PER_CLUSTER 2 +#define PLATFORM_CORE_COUNT NUMBER_OF_CLUSTERS * CORES_PER_CLUSTER + +/* + * Required LS standard platform porting definitions + * for CCN-508 + */ +#define PLAT_CLUSTER_TO_CCN_ID_MAP 11, 15, 27, 31, 12, 28, 16, 0 +#define PLAT_6CLUSTER_TO_CCN_ID_MAP 11, 15, 27, 31, 12, 28 + + +/* 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 2 +#define NXP_UART_CLK_DIVIDER 4 + +/* Start: Macros used by lx2160a.S */ +#define MPIDR_AFFINITY0_MASK 0x00FF +#define MPIDR_AFFINITY1_MASK 0xFF00 +#define CPUECTLR_DISABLE_TWALK_PREFETCH 0x4000000000 +#define CPUECTLR_INS_PREFETCH_MASK 0x1800000000 +#define CPUECTLR_DAT_PREFETCH_MASK 0x0300000000 +#define CPUECTLR_RET_8CLK 0x2 +#define OSDLR_EL1_DLK_LOCK 0x1 +#define CNTP_CTL_EL0_EN 0x1 +#define CNTP_CTL_EL0_IMASK 0x2 +/* set to 0 if the clusters are not symmetrical */ +#define SYMMETRICAL_CLUSTERS 1 +/* End: Macros used by lx2160a.S */ + +/* Start: Macros used by lib/psci files */ +#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_MAX_PWR_LVL MPIDR_AFFLVL2 + +/* define retention state */ +#define PLAT_MAX_RET_STATE (PSCI_LOCAL_STATE_RUN + 1) + +/* define power-down state */ +#define PLAT_MAX_OFF_STATE (PLAT_MAX_RET_STATE + 1) +/* End: Macros used by lib/psci files */ + +/* 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 WDOG_RESET_FLAG +#define WDOG_RESET_FLAG DEFAULT_SET_VALUE +#endif + +#ifndef WARM_BOOT_SUCCESS +#define WARM_BOOT_SUCCESS DEFAULT_SET_VALUE +#endif + +#ifndef __ASSEMBLER__ + +void set_base_freq_CNTFID0(void); +void soc_init_start(void); +void soc_init_finish(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-lx2160a/lx2160aqds/ddr_init.c b/plat/nxp/soc-lx2160a/lx2160aqds/ddr_init.c new file mode 100644 index 0000000..d44733c --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2160aqds/ddr_init.c @@ -0,0 +1,355 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <assert.h> +#include <errno.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <common/debug.h> +#include <ddr.h> +#include <lib/utils.h> +#include <load_img.h> + +#include "plat_common.h" +#include <platform_def.h> + +#ifdef CONFIG_STATIC_DDR + +const struct ddr_cfg_regs static_3200 = { + .cs[0].bnds = U(0x03FF), + .cs[1].bnds = U(0x03FF), + .cs[0].config = U(0x80050422), + .cs[1].config = U(0x80000422), + .cs[2].bnds = U(0x00), + .cs[3].bnds = U(0x00), + .cs[2].config = U(0x00), + .cs[3].config = U(0x00), + .timing_cfg[0] = U(0xFFAA0018), + .timing_cfg[1] = U(0x646A8844), + .timing_cfg[2] = U(0x00058022), + .timing_cfg[3] = U(0x13622100), + .timing_cfg[4] = U(0x02), + .timing_cfg[5] = U(0x07401400), + .timing_cfg[7] = U(0x3BB00000), + .timing_cfg[8] = U(0x0944AC00), + .sdram_cfg[0] = U(0x65044008), + .sdram_cfg[1] = U(0x00401011), + .sdram_cfg[2] = U(0x00), + .sdram_mode[0] = U(0x06010C50), + .sdram_mode[1] = U(0x00280400), + .sdram_mode[2] = U(0x00), + .sdram_mode[3] = U(0x00), + .sdram_mode[4] = U(0x00), + .sdram_mode[5] = U(0x00), + .sdram_mode[6] = U(0x00), + .sdram_mode[7] = U(0x00), + .sdram_mode[8] = U(0x0500), + .sdram_mode[9] = U(0x10240000), + .sdram_mode[10] = U(0x00), + .sdram_mode[11] = U(0x00), + .sdram_mode[12] = U(0x00), + .sdram_mode[13] = U(0x00), + .sdram_mode[14] = U(0x00), + .sdram_mode[15] = U(0x00), + .md_cntl = U(0x00), + .interval = U(0x30C00000), + .data_init = U(0xDEADBEEF), + .init_addr = U(0x00), + .zq_cntl = U(0x8A090705), + .sdram_rcw[0] = U(0x00), + .sdram_rcw[1] = U(0x00), + .sdram_rcw[2] = U(0x00), + .sdram_rcw[3] = U(0x00), + .sdram_rcw[4] = U(0x00), + .sdram_rcw[5] = U(0x00), + .err_disable = U(0x00), + .err_int_en = U(0x00), +}; + +const struct ddr_cfg_regs static_2900 = { + .cs[0].bnds = U(0x03FF), + .cs[1].bnds = U(0x03FF), + .cs[0].config = U(0x80050422), + .cs[1].config = U(0x80000422), + .cs[2].bnds = U(0x00), + .cs[3].bnds = U(0x00), + .cs[2].config = U(0x00), + .cs[3].config = U(0x00), + .timing_cfg[0] = U(0xFF990018), + .timing_cfg[1] = U(0x4F4A4844), + .timing_cfg[2] = U(0x0005601F), + .timing_cfg[3] = U(0x125F2100), + .timing_cfg[4] = U(0x02), + .timing_cfg[5] = U(0x07401400), + .timing_cfg[7] = U(0x3AA00000), + .timing_cfg[8] = U(0x09449B00), + .sdram_cfg[0] = U(0x65044008), + .sdram_cfg[1] = U(0x00401011), + .sdram_cfg[2] = U(0x00), + .sdram_mode[0] = U(0x06010C50), + .sdram_mode[1] = U(0x00280400), + .sdram_mode[2] = U(0x00), + .sdram_mode[3] = U(0x00), + .sdram_mode[4] = U(0x00), + .sdram_mode[5] = U(0x00), + .sdram_mode[6] = U(0x00), + .sdram_mode[7] = U(0x00), + .sdram_mode[8] = U(0x0500), + .sdram_mode[9] = U(0x10240000), + .sdram_mode[10] = U(0x00), + .sdram_mode[11] = U(0x00), + .sdram_mode[12] = U(0x00), + .sdram_mode[13] = U(0x00), + .sdram_mode[14] = U(0x00), + .sdram_mode[15] = U(0x00), + .md_cntl = U(0x00), + .interval = U(0x2C2E0000), + .data_init = U(0xDEADBEEF), + .init_addr = U(0x00), + .zq_cntl = U(0x8A090705), + .sdram_rcw[0] = U(0x00), + .sdram_rcw[1] = U(0x00), + .sdram_rcw[2] = U(0x00), + .sdram_rcw[3] = U(0x00), + .sdram_rcw[4] = U(0x00), + .sdram_rcw[5] = U(0x00), + .err_disable = U(0x00), + .err_int_en = U(0x00), +}; + +const struct ddr_cfg_regs static_2600 = { + .cs[0].bnds = U(0x03FF), + .cs[1].bnds = U(0x03FF), + .cs[0].config = U(0x80050422), + .cs[1].config = U(0x80000422), + .cs[2].bnds = U(0x00), + .cs[3].bnds = U(0x00), + .cs[2].config = U(0x00), + .cs[3].config = U(0x00), + .timing_cfg[0] = U(0xFF880018), + .timing_cfg[1] = U(0x2A24F444), + .timing_cfg[2] = U(0x007141DC), + .timing_cfg[3] = U(0x125B2100), + .timing_cfg[4] = U(0x02), + .timing_cfg[5] = U(0x06401400), + .timing_cfg[7] = U(0x28800000), + .timing_cfg[8] = U(0x07338A00), + .sdram_cfg[0] = U(0x65044008), + .sdram_cfg[1] = U(0x00401011), + .sdram_cfg[2] = U(0x00), + .sdram_mode[0] = U(0x06010A70), + .sdram_mode[1] = U(0x00200400), + .sdram_mode[2] = U(0x00), + .sdram_mode[3] = U(0x00), + .sdram_mode[4] = U(0x00), + .sdram_mode[5] = U(0x00), + .sdram_mode[6] = U(0x00), + .sdram_mode[7] = U(0x00), + .sdram_mode[8] = U(0x0500), + .sdram_mode[9] = U(0x0C240000), + .sdram_mode[10] = U(0x00), + .sdram_mode[11] = U(0x00), + .sdram_mode[12] = U(0x00), + .sdram_mode[13] = U(0x00), + .sdram_mode[14] = U(0x00), + .sdram_mode[15] = U(0x00), + .md_cntl = U(0x00), + .interval = U(0x279C0000), + .data_init = U(0xDEADBEEF), + .init_addr = U(0x00), + .zq_cntl = U(0x8A090705), + .sdram_rcw[0] = U(0x00), + .sdram_rcw[1] = U(0x00), + .sdram_rcw[2] = U(0x00), + .sdram_rcw[3] = U(0x00), + .sdram_rcw[4] = U(0x00), + .sdram_rcw[5] = U(0x00), + .err_disable = U(0x00), + .err_int_en = U(0x00), +}; + +const struct dimm_params static_dimm = { + .rdimm = U(0), + .primary_sdram_width = U(64), + .ec_sdram_width = U(8), + .n_ranks = U(2), + .device_width = U(8), + .mirrored_dimm = U(1), +}; + +/* Sample code using two UDIMM MT18ASF1G72AZ-2G6B1, on each DDR controller */ +unsigned long long board_static_ddr(struct ddr_info *priv) +{ + (void)memcpy(&priv->ddr_reg, &static_2900, sizeof(static_2900)); + (void)memcpy(&priv->dimm, &static_dimm, sizeof(static_dimm)); + priv->conf.cs_on_dimm[0] = 0x3; + ddr_board_options(priv); + compute_ddr_phy(priv); + + return ULL(0x400000000); +} + +#elif defined(CONFIG_DDR_NODIMM) +/* + * Sample code to bypass reading SPD. This is a sample, not recommended + * for boards with slots. DDR model number: UDIMM MT18ASF1G72AZ-2G6B1. + */ + +const struct dimm_params ddr_raw_timing = { + .n_ranks = U(2), + .rank_density = U(4294967296u), + .capacity = U(8589934592u), + .primary_sdram_width = U(64), + .ec_sdram_width = U(8), + .device_width = U(8), + .die_density = U(0x4), + .rdimm = U(0), + .mirrored_dimm = U(1), + .n_row_addr = U(15), + .n_col_addr = U(10), + .bank_addr_bits = U(0), + .bank_group_bits = U(2), + .edc_config = U(2), + .burst_lengths_bitmask = U(0x0c), + .tckmin_x_ps = 750, + .tckmax_ps = 1600, + .caslat_x = U(0x00FFFC00), + .taa_ps = 13750, + .trcd_ps = 13750, + .trp_ps = 13750, + .tras_ps = 32000, + .trc_ps = 457500, + .twr_ps = 15000, + .trfc1_ps = 260000, + .trfc2_ps = 160000, + .trfc4_ps = 110000, + .tfaw_ps = 21000, + .trrds_ps = 3000, + .trrdl_ps = 4900, + .tccdl_ps = 5000, + .refresh_rate_ps = U(7800000), +}; + +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; /* Modify accordingly */ + memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params)); + memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1); + + /* valid DIMM mask, change accordingly, together with dimm_on_ctlr. */ + return 0x5; +} +#endif /* CONFIG_DDR_NODIMM */ + +int ddr_board_options(struct ddr_info *priv) +{ + struct memctl_opt *popts = &priv->opt; + const struct ddr_conf *conf = &priv->conf; + + popts->vref_dimm = U(0x24); /* range 1, 83.4% */ + popts->rtt_override = 0; + popts->rtt_park = U(240); + popts->otf_burst_chop_en = 0; + popts->burst_length = U(DDR_BL8); + popts->trwt_override = U(1); + popts->bstopre = U(0); /* auto precharge */ + popts->addr_hash = 1; + + /* Set ODT impedance on PHY side */ + switch (conf->cs_on_dimm[1]) { + case 0xc: /* Two slots dual rank */ + case 0x4: /* Two slots single rank, not valid for interleaving */ + popts->trwt = U(0xf); + popts->twrt = U(0x7); + popts->trrt = U(0x7); + popts->twwt = U(0x7); + popts->vref_phy = U(0x6B); /* 83.6% */ + popts->odt = U(60); + popts->phy_tx_impedance = U(28); + break; + case 0: /* One slot used */ + default: + popts->trwt = U(0x3); + popts->twrt = U(0x3); + popts->trrt = U(0x3); + popts->twwt = U(0x3); + popts->vref_phy = U(0x60); /* 75% */ + popts->odt = U(48); + popts->phy_tx_impedance = U(28); + break; + } + + return 0; +} + +#ifdef NXP_WARM_BOOT +long long init_ddr(uint32_t wrm_bt_flg) +#else +long long init_ddr(void) +#endif +{ + int spd_addr[] = {0x51U, 0x52U, 0x53U, 0x54U}; + struct ddr_info info; + struct sysinfo sys; + long long dram_size; + + zeromem(&sys, sizeof(sys)); + if (get_clocks(&sys) == 1) { + ERROR("System clocks are not set.\n"); + panic(); + } + 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(info)); + + /* Set two DDRC. Unused DDRC will be removed automatically. */ + info.num_ctlrs = NUM_OF_DDRC; + info.spd_addr = spd_addr; + info.ddr[0] = (void *)NXP_DDR_ADDR; + info.ddr[1] = (void *)NXP_DDR2_ADDR; + info.phy[0] = (void *)NXP_DDR_PHY1_ADDR; + info.phy[1] = (void *)NXP_DDR_PHY2_ADDR; + info.clk = get_ddr_freq(&sys, 0); + info.img_loadr = load_img; + info.phy_gen2_fw_img_buf = PHY_GEN2_FW_IMAGE_BUFFER; + if (info.clk == 0) { + info.clk = get_ddr_freq(&sys, 1); + } + info.dimm_on_ctlr = DDRC_NUM_DIMM; + + info.warm_boot_flag = DDR_WRM_BOOT_NT_SUPPORTED; +#ifdef NXP_WARM_BOOT + info.warm_boot_flag = DDR_COLD_BOOT; + if (wrm_bt_flg != 0U) { + info.warm_boot_flag = DDR_WARM_BOOT; + } else { + info.warm_boot_flag = DDR_COLD_BOOT; + } +#endif + + dram_size = dram_init(&info +#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) + , NXP_CCN_HN_F_0_ADDR +#endif + ); + + + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + + return dram_size; +} diff --git a/plat/nxp/soc-lx2160a/lx2160aqds/plat_def.h b/plat/nxp/soc-lx2160a/lx2160aqds/plat_def.h new file mode 100644 index 0000000..f480f92 --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2160aqds/plat_def.h @@ -0,0 +1,105 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include <arch.h> +#include <cortex_a72.h> +/* Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include <tbbr_img_def.h> + +#include <policy.h> +#include <soc.h> + +#if defined(IMAGE_BL31) +#define LS_SYS_TIMCTL_BASE 0x2890000 +#define PLAT_LS_NSTIMER_FRAME_ID 0 +#define LS_CONFIG_CNTACR 1 +#endif + +#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 (0x8000) +#define NXP_SD_BLOCK_BUF_ADDR (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \ + - NXP_SD_BLOCK_BUF_SIZE) + +#ifdef SD_BOOT +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \ + - NXP_SD_BLOCK_BUF_SIZE) +#else +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) +#endif + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES 4 +#define MAX_IO_BLOCK_DEVICES 1 +#define MAX_IO_HANDLES 4 + +#define PHY_GEN2_FW_IMAGE_BUFFER (NXP_OCRAM_ADDR + CSF_HDR_SZ) + +/* + * 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 3 +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 2 +#endif + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define BL32_IRQ_SEC_PHY_TIMER 29 + +#define BL31_WDOG_SEC 89 + +#define BL31_NS_WDOG_WS1 108 + +/* + * 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_EDGE) + +/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */ +#define NXP_IRQ_SEC_SGI_7 15 + +#define PLAT_LS_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(BL31_NS_WDOG_WS1, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(NXP_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) +#endif diff --git a/plat/nxp/soc-lx2160a/lx2160aqds/platform.c b/plat/nxp/soc-lx2160a/lx2160aqds/platform.c new file mode 100644 index 0000000..b00adb5 --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2160aqds/platform.c @@ -0,0 +1,29 @@ +/* + * Copyright 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-lx2160a/lx2160aqds/platform.mk b/plat/nxp/soc-lx2160a/lx2160aqds/platform.mk new file mode 100644 index 0000000..226b22b --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2160aqds/platform.mk @@ -0,0 +1,51 @@ +# +# Copyright 2018-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters + +BOOT_MODE ?= flexspi_nor +BOARD ?= lx2160aqds +POVDD_ENABLE := no +NXP_COINED_BB := no + + # DDR Compilation Configs +NUM_OF_DDRC := 1 +DDRC_NUM_DIMM := 1 +DDRC_NUM_CS := 2 +DDR_ECC_EN := yes + #enable address decoding feature +DDR_ADDR_DEC := yes +APPLY_MAX_CDD := yes + +# DDR Errata +ERRATA_DDR_A011396 := 1 +ERRATA_DDR_A050450 := 1 + + # On-Board Flash Details +FLASH_TYPE := MT35XU512A +XSPI_FLASH_SZ := 0x10000000 +NXP_XSPI_NOR_UNIT_SIZE := 0x20000 +BL2_BIN_XSPI_NOR_END_ADDRESS := 0x100000 +# CONFIG_FSPI_ERASE_4K is required to erase 4K sector sizes. This +# config is enabled for future use cases. +FSPI_ERASE_4K := 0 + +# Platform specific features. +WARM_BOOT := yes + +# Adding Platform files build files +BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\ + ${BOARD_PATH}/platform.c + +SUPPORTED_BOOT_MODE := flexspi_nor \ + sd \ + emmc + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Adding SoC build info +include plat/nxp/soc-lx2160a/soc.mk diff --git a/plat/nxp/soc-lx2160a/lx2160aqds/platform_def.h b/plat/nxp/soc-lx2160a/lx2160aqds/platform_def.h new file mode 100644 index 0000000..5fa774e --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2160aqds/platform_def.h @@ -0,0 +1,14 @@ +/* + * Copyright 2018-2020 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 diff --git a/plat/nxp/soc-lx2160a/lx2160aqds/policy.h b/plat/nxp/soc-lx2160a/lx2160aqds/policy.h new file mode 100644 index 0000000..05d23e2 --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2160aqds/policy.h @@ -0,0 +1,38 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef POLICY_H +#define POLICY_H + +/* Following defines affect the PLATFORM SECURITY POLICY */ + +/* set this to 0x0 if the platform is not using/responding to ECC errors + * set this to 0x1 if ECC is being used (we have to do some init) + */ +#define POLICY_USING_ECC 0x0 + +/* 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 + +/* + * POLICY_PERF_WRIOP = 0 : No Performance enhancement for WRIOP RN-I + * POLICY_PERF_WRIOP = 1 : No Performance enhancement for WRIOP RN-I = 7 + * POLICY_PERF_WRIOP = 2 : No Performance enhancement for WRIOP RN-I = 23 + */ +#define POLICY_PERF_WRIOP 0 + +/* + * set this to '1' if the debug clocks need to remain enabled during + * system entry to low-power (LPM20) - this should only be necessary + * for testing and NEVER set for normal production + */ +#define POLICY_DEBUG_ENABLE 0 + + +#endif /* POLICY_H */ diff --git a/plat/nxp/soc-lx2160a/lx2160ardb/ddr_init.c b/plat/nxp/soc-lx2160a/lx2160ardb/ddr_init.c new file mode 100644 index 0000000..8669b1d --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2160ardb/ddr_init.c @@ -0,0 +1,212 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <assert.h> +#include <errno.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <common/debug.h> +#include <ddr.h> +#include <lib/utils.h> +#include <load_img.h> + +#include "plat_common.h" +#include <platform_def.h> + +#ifdef CONFIG_STATIC_DDR +const struct ddr_cfg_regs static_1600 = { + .cs[0].config = U(0xA8050322), + .cs[1].config = U(0x80000322), + .cs[0].bnds = U(0x3FF), + .cs[1].bnds = U(0x3FF), + .sdram_cfg[0] = U(0xE5044000), + .sdram_cfg[1] = U(0x401011), + .timing_cfg[0] = U(0xFF550018), + .timing_cfg[1] = U(0xBAB48C42), + .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(0x2114600), + .sdram_mode[0] = U(0x6010210), + .sdram_mode[8] = U(0x500), + .sdram_mode[9] = U(0x4240000), + .interval = U(0x18600000), + .data_init = U(0xDEADBEEF), + .zq_cntl = U(0x8A090705), +}; + +const struct dimm_params static_dimm = { + .rdimm = U(0), + .primary_sdram_width = U(64), + .ec_sdram_width = U(8), + .n_ranks = U(2), + .device_width = U(8), + .mirrored_dimm = U(1), +}; + +/* Sample code using two UDIMM MT18ASF1G72AZ-2G6B1, on each DDR controller */ +unsigned long long board_static_ddr(struct ddr_info *priv) +{ + memcpy(&priv->ddr_reg, &static_1600, sizeof(static_1600)); + memcpy(&priv->dimm, &static_dimm, sizeof(static_dimm)); + priv->conf.cs_on_dimm[0] = 0x3; + ddr_board_options(priv); + compute_ddr_phy(priv); + + return ULL(0x400000000); +} + +#elif defined(CONFIG_DDR_NODIMM) +/* + * Sample code to bypass reading SPD. This is a sample, not recommended + * for boards with slots. DDR model number: UDIMM MT18ASF1G72AZ-2G6B1. + */ + +const struct dimm_params ddr_raw_timing = { + .n_ranks = U(2), + .rank_density = U(4294967296u), + .capacity = U(8589934592u), + .primary_sdram_width = U(64), + .ec_sdram_width = U(8), + .device_width = U(8), + .die_density = U(0x4), + .rdimm = U(0), + .mirrored_dimm = U(1), + .n_row_addr = U(15), + .n_col_addr = U(10), + .bank_addr_bits = U(0), + .bank_group_bits = U(2), + .edc_config = U(2), + .burst_lengths_bitmask = U(0x0c), + .tckmin_x_ps = 750, + .tckmax_ps = 1600, + .caslat_x = U(0x00FFFC00), + .taa_ps = 13750, + .trcd_ps = 13750, + .trp_ps = 13750, + .tras_ps = 32000, + .trc_ps = 457500, + .twr_ps = 15000, + .trfc1_ps = 260000, + .trfc2_ps = 160000, + .trfc4_ps = 110000, + .tfaw_ps = 21000, + .trrds_ps = 3000, + .trrdl_ps = 4900, + .tccdl_ps = 5000, + .refresh_rate_ps = U(7800000), +}; + +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; /* Modify accordingly */ + memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params)); + memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1); + + /* valid DIMM mask, change accordingly, together with dimm_on_ctlr. */ + return 0x5; +} +#endif /* CONFIG_DDR_NODIMM */ + +int ddr_board_options(struct ddr_info *priv) +{ + struct memctl_opt *popts = &priv->opt; + const struct ddr_conf *conf = &priv->conf; + + popts->vref_dimm = U(0x24); /* range 1, 83.4% */ + popts->rtt_override = 0; + popts->rtt_park = U(240); + popts->otf_burst_chop_en = 0; + popts->burst_length = U(DDR_BL8); + popts->trwt_override = U(1); + popts->bstopre = U(0); /* auto precharge */ + popts->addr_hash = 1; + + /* Set ODT impedance on PHY side */ + switch (conf->cs_on_dimm[1]) { + case 0xc: /* Two slots dual rank */ + case 0x4: /* Two slots single rank, not valid for interleaving */ + popts->trwt = U(0xf); + popts->twrt = U(0x7); + popts->trrt = U(0x7); + popts->twwt = U(0x7); + popts->vref_phy = U(0x6B); /* 83.6% */ + popts->odt = U(60); + popts->phy_tx_impedance = U(28); + break; + case 0: /* One slot used */ + default: + popts->trwt = U(0x3); + popts->twrt = U(0x3); + popts->trrt = U(0x3); + popts->twwt = U(0x3); + popts->vref_phy = U(0x60); /* 75% */ + popts->odt = U(48); + popts->phy_tx_impedance = U(28); + break; + } + + return 0; +} + +long long init_ddr(void) +{ + int spd_addr[] = { 0x51, 0x52, 0x53, 0x54 }; + struct ddr_info info; + struct sysinfo sys; + long long dram_size; + + zeromem(&sys, sizeof(sys)); + if (get_clocks(&sys) != 0) { + ERROR("System clocks are not set\n"); + panic(); + } + 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(info)); + + /* Set two DDRC. Unused DDRC will be removed automatically. */ + info.num_ctlrs = NUM_OF_DDRC; + info.spd_addr = spd_addr; + info.ddr[0] = (void *)NXP_DDR_ADDR; + info.ddr[1] = (void *)NXP_DDR2_ADDR; + info.phy[0] = (void *)NXP_DDR_PHY1_ADDR; + info.phy[1] = (void *)NXP_DDR_PHY2_ADDR; + info.clk = get_ddr_freq(&sys, 0); + info.img_loadr = load_img; + info.phy_gen2_fw_img_buf = PHY_GEN2_FW_IMAGE_BUFFER; + if (info.clk == 0) { + info.clk = get_ddr_freq(&sys, 1); + } + info.dimm_on_ctlr = DDRC_NUM_DIMM; + + info.warm_boot_flag = DDR_WRM_BOOT_NT_SUPPORTED; + + dram_size = dram_init(&info +#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) + , NXP_CCN_HN_F_0_ADDR +#endif + ); + + + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + + return dram_size; +} diff --git a/plat/nxp/soc-lx2160a/lx2160ardb/plat_def.h b/plat/nxp/soc-lx2160a/lx2160ardb/plat_def.h new file mode 100644 index 0000000..02f51e7 --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2160ardb/plat_def.h @@ -0,0 +1,105 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include <arch.h> +#include <cortex_a72.h> +/* Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include <tbbr_img_def.h> + +#include <policy.h> +#include <soc.h> + +#if defined(IMAGE_BL31) +#define LS_SYS_TIMCTL_BASE 0x2890000 +#define PLAT_LS_NSTIMER_FRAME_ID 0 +#define LS_CONFIG_CNTACR 1 +#endif + +#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 (0x8000) +#define NXP_SD_BLOCK_BUF_ADDR (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \ + - NXP_SD_BLOCK_BUF_SIZE) + +#ifdef SD_BOOT +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \ + - NXP_SD_BLOCK_BUF_SIZE) +#else +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) +#endif + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES 4 +#define MAX_IO_BLOCK_DEVICES 1 +#define MAX_IO_HANDLES 4 + +#define PHY_GEN2_FW_IMAGE_BUFFER (NXP_OCRAM_ADDR + CSF_HDR_SZ) + +/* + * 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 3 +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 2 +#endif + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define BL32_IRQ_SEC_PHY_TIMER 29 + +#define BL31_WDOG_SEC 89 + +#define BL31_NS_WDOG_WS1 108 + +/* + * 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_EDGE) + +/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */ +#define NXP_IRQ_SEC_SGI_7 15 + +#define PLAT_LS_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(BL31_NS_WDOG_WS1, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(NXP_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) +#endif diff --git a/plat/nxp/soc-lx2160a/lx2160ardb/platform.c b/plat/nxp/soc-lx2160a/lx2160ardb/platform.c new file mode 100644 index 0000000..b00adb5 --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2160ardb/platform.c @@ -0,0 +1,29 @@ +/* + * Copyright 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-lx2160a/lx2160ardb/platform.mk b/plat/nxp/soc-lx2160a/lx2160ardb/platform.mk new file mode 100644 index 0000000..ffb5fad --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2160ardb/platform.mk @@ -0,0 +1,51 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters + +BOOT_MODE ?= flexspi_nor +BOARD ?= lx2160ardb +POVDD_ENABLE := no +NXP_COINED_BB := no + + # DDR Compilation Configs +NUM_OF_DDRC := 2 +DDRC_NUM_DIMM := 2 +DDRC_NUM_CS := 4 +DDR_ECC_EN := yes + #enable address decoding feature +DDR_ADDR_DEC := yes +APPLY_MAX_CDD := yes + +# DDR Errata +ERRATA_DDR_A011396 := 1 +ERRATA_DDR_A050450 := 1 + + # On-Board Flash Details +FLASH_TYPE := MT35XU512A +XSPI_FLASH_SZ := 0x10000000 +NXP_XSPI_NOR_UNIT_SIZE := 0x20000 +BL2_BIN_XSPI_NOR_END_ADDRESS := 0x100000 +# CONFIG_FSPI_ERASE_4K is required to erase 4K sector sizes. This +# config is enabled for future use cases. +FSPI_ERASE_4K := 0 + + # 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 := flexspi_nor \ + sd \ + emmc + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + + # Adding SoC build info +include plat/nxp/soc-lx2160a/soc.mk diff --git a/plat/nxp/soc-lx2160a/lx2160ardb/platform_def.h b/plat/nxp/soc-lx2160a/lx2160ardb/platform_def.h new file mode 100644 index 0000000..6660998 --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2160ardb/platform_def.h @@ -0,0 +1,14 @@ +/* + * Copyright 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 diff --git a/plat/nxp/soc-lx2160a/lx2160ardb/policy.h b/plat/nxp/soc-lx2160a/lx2160ardb/policy.h new file mode 100644 index 0000000..19ad6db --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2160ardb/policy.h @@ -0,0 +1,38 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef POLICY_H +#define POLICY_H + +/* Following defines affect the PLATFORM SECURITY POLICY */ + +/* set this to 0x0 if the platform is not using/responding to ECC errors + * set this to 0x1 if ECC is being used (we have to do some init) + */ +#define POLICY_USING_ECC 0x0 + +/* 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 + +/* + * POLICY_PERF_WRIOP = 0 : No Performance enhancement for WRIOP RN-I + * POLICY_PERF_WRIOP = 1 : No Performance enhancement for WRIOP RN-I = 7 + * POLICY_PERF_WRIOP = 2 : No Performance enhancement for WRIOP RN-I = 23 + */ +#define POLICY_PERF_WRIOP 0 + +/* + * set this to '1' if the debug clocks need to remain enabled during + * system entry to low-power (LPM20) - this should only be necessary + * for testing and NEVER set for normal production + */ +#define POLICY_DEBUG_ENABLE 0 + + +#endif /* POLICY_H */ diff --git a/plat/nxp/soc-lx2160a/lx2162aqds/ddr_init.c b/plat/nxp/soc-lx2160a/lx2162aqds/ddr_init.c new file mode 100644 index 0000000..73bcc93 --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2162aqds/ddr_init.c @@ -0,0 +1,354 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <assert.h> +#include <errno.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <common/debug.h> +#include <ddr.h> +#include <lib/utils.h> +#include <load_img.h> + +#include "plat_common.h" +#include <platform_def.h> + +#ifdef CONFIG_STATIC_DDR + +const struct ddr_cfg_regs static_3200 = { + .cs[0].bnds = U(0x03FFU), + .cs[1].bnds = U(0x03FF), + .cs[0].config = U(0x80050422), + .cs[1].config = U(0x80000422), + .cs[2].bnds = U(0x00), + .cs[3].bnds = U(0x00), + .cs[2].config = U(0x00), + .cs[3].config = U(0x00), + .timing_cfg[0] = U(0xFFAA0018), + .timing_cfg[1] = U(0x646A8844), + .timing_cfg[2] = U(0x00058022), + .timing_cfg[3] = U(0x13622100), + .timing_cfg[4] = U(0x02), + .timing_cfg[5] = U(0x07401400), + .timing_cfg[7] = U(0x3BB00000), + .timing_cfg[8] = U(0x0944AC00), + .sdram_cfg[0] = U(0x65044008), + .sdram_cfg[1] = U(0x00401011), + .sdram_cfg[2] = U(0x00), + .sdram_mode[0] = U(0x06010C50), + .sdram_mode[1] = U(0x00280400), + .sdram_mode[2] = U(0x00), + .sdram_mode[3] = U(0x00), + .sdram_mode[4] = U(0x00), + .sdram_mode[5] = U(0x00), + .sdram_mode[6] = U(0x00), + .sdram_mode[7] = U(0x00), + .sdram_mode[8] = U(0x0500), + .sdram_mode[9] = U(0x10240000), + .sdram_mode[10] = U(0x00), + .sdram_mode[11] = U(0x00), + .sdram_mode[12] = U(0x00), + .sdram_mode[13] = U(0x00), + .sdram_mode[14] = U(0x00), + .sdram_mode[15] = U(0x00), + .md_cntl = U(0x00), + .interval = U(0x30C00000), + .data_init = U(0xDEADBEEF), + .init_addr = U(0x00), + .zq_cntl = U(0x8A090705), + .sdram_rcw[0] = U(0x00), + .sdram_rcw[1] = U(0x00), + .sdram_rcw[2] = U(0x00), + .sdram_rcw[3] = U(0x00), + .sdram_rcw[4] = U(0x00), + .sdram_rcw[5] = U(0x00), + .err_disable = U(0x00), + .err_int_en = U(0x00), +}; + +const struct ddr_cfg_regs static_2900 = { + .cs[0].bnds = U(0x03FF), + .cs[1].bnds = U(0x03FF), + .cs[0].config = U(0x80050422), + .cs[1].config = U(0x80000422), + .cs[2].bnds = U(0x00), + .cs[3].bnds = U(0x00), + .cs[2].config = U(0x00), + .cs[3].config = U(0x00), + .timing_cfg[0] = U(0xFF990018), + .timing_cfg[1] = U(0x4F4A4844), + .timing_cfg[2] = U(0x0005601F), + .timing_cfg[3] = U(0x125F2100), + .timing_cfg[4] = U(0x02), + .timing_cfg[5] = U(0x07401400), + .timing_cfg[7] = U(0x3AA00000), + .timing_cfg[8] = U(0x09449B00), + .sdram_cfg[0] = U(0x65044008), + .sdram_cfg[1] = U(0x00401011), + .sdram_cfg[2] = U(0x00), + .sdram_mode[0] = U(0x06010C50), + .sdram_mode[1] = U(0x00280400), + .sdram_mode[2] = U(0x00), + .sdram_mode[3] = U(0x00), + .sdram_mode[4] = U(0x00), + .sdram_mode[5] = U(0x00), + .sdram_mode[6] = U(0x00), + .sdram_mode[7] = U(0x00), + .sdram_mode[8] = U(0x0500), + .sdram_mode[9] = U(0x10240000), + .sdram_mode[10] = U(0x00), + .sdram_mode[11] = U(0x00), + .sdram_mode[12] = U(0x00), + .sdram_mode[13] = U(0x00), + .sdram_mode[14] = U(0x00), + .sdram_mode[15] = U(0x00), + .md_cntl = U(0x00), + .interval = U(0x2C2E0000), + .data_init = U(0xDEADBEEF), + .init_addr = U(0x00), + .zq_cntl = U(0x8A090705), + .sdram_rcw[0] = U(0x00), + .sdram_rcw[1] = U(0x00), + .sdram_rcw[2] = U(0x00), + .sdram_rcw[3] = U(0x00), + .sdram_rcw[4] = U(0x00), + .sdram_rcw[5] = U(0x00), + .err_disable = U(0x00), + .err_int_en = U(0x00), +}; + +const struct ddr_cfg_regs static_2600 = { + .cs[0].bnds = U(0x03FF), + .cs[1].bnds = U(0x03FF), + .cs[0].config = U(0x80050422), + .cs[1].config = U(0x80000422), + .cs[2].bnds = U(0x00), + .cs[3].bnds = U(0x00), + .cs[2].config = U(0x00), + .cs[3].config = U(0x00), + .timing_cfg[0] = U(0xFF880018), + .timing_cfg[1] = U(0x2A24F444), + .timing_cfg[2] = U(0x007141DC), + .timing_cfg[3] = U(0x125B2100), + .timing_cfg[4] = U(0x02), + .timing_cfg[5] = U(0x06401400), + .timing_cfg[7] = U(0x28800000), + .timing_cfg[8] = U(0x07338A00), + .sdram_cfg[0] = U(0x65044008), + .sdram_cfg[1] = U(0x00401011), + .sdram_cfg[2] = U(0x00), + .sdram_mode[0] = U(0x06010A70), + .sdram_mode[1] = U(0x00200400), + .sdram_mode[2] = U(0x00), + .sdram_mode[3] = U(0x00), + .sdram_mode[4] = U(0x00), + .sdram_mode[5] = U(0x00), + .sdram_mode[6] = U(0x00), + .sdram_mode[7] = U(0x00), + .sdram_mode[8] = U(0x0500), + .sdram_mode[9] = U(0x0C240000), + .sdram_mode[10] = U(0x00), + .sdram_mode[11] = U(0x00), + .sdram_mode[12] = U(0x00), + .sdram_mode[13] = U(0x00), + .sdram_mode[14] = U(0x00), + .sdram_mode[15] = U(0x00), + .md_cntl = U(0x00), + .interval = U(0x279C0000), + .data_init = U(0xDEADBEEF), + .init_addr = U(0x00), + .zq_cntl = U(0x8A090705), + .sdram_rcw[0] = U(0x00), + .sdram_rcw[1] = U(0x00), + .sdram_rcw[2] = U(0x00), + .sdram_rcw[3] = U(0x00), + .sdram_rcw[4] = U(0x00), + .sdram_rcw[5] = U(0x00), + .err_disable = U(0x00), + .err_int_en = U(0x00), +}; + +const struct dimm_params static_dimm = { + .rdimm = 0U, + .primary_sdram_width = 64U, + .ec_sdram_width = 8U, + .n_ranks = 2U, + .device_width = 8U, + .mirrored_dimm = 1U, +}; + +/* Sample code using two UDIMM MT18ASF1G72AZ-2G6B1, on each DDR controller */ +unsigned long long board_static_ddr(struct ddr_info *priv) +{ + memcpy(&priv->ddr_reg, &static_2900, sizeof(static_2900)); + memcpy(&priv->dimm, &static_dimm, sizeof(static_dimm)); + priv->conf.cs_on_dimm[0] = 0x3; + ddr_board_options(priv); + compute_ddr_phy(priv); + + return ULL(0x400000000); +} + +#elif defined(CONFIG_DDR_NODIMM) +/* + * Sample code to bypass reading SPD. This is a sample, not recommended + * for boards with slots. DDR model number: UDIMM MT18ASF1G72AZ-2G6B1. + */ +struct dimm_params ddr_raw_timing = { + .n_ranks = 2U, + .rank_density = U(0x200000000), + .capacity = U(0x400000000), + .primary_sdram_width = 64U, + .ec_sdram_width = 8U, + .device_width = 8U, + .die_density = U(0x5), + .rdimm = 0U, + .mirrored_dimm = 1U, + .n_row_addr = 16U, + .n_col_addr = 10U, + .bank_addr_bits = 0U, + .bank_group_bits = 2U, + .edc_config = 2U, + .burst_lengths_bitmask = U(0x0c), + .tckmin_x_ps = 625, + .tckmax_ps = 1600, + .caslat_x = U(0x15FFFC00), + .taa_ps = 13750, + .trcd_ps = 13750, + .trp_ps = 13750, + .tras_ps = 32000, + .trc_ps = 457500, + .twr_ps = 15000, + .trfc1_ps = 350000, + .trfc2_ps = 260000, + .trfc4_ps = 160000, + .tfaw_ps = 21000, + .trrds_ps = 2500, + .trrdl_ps = 4900, + .tccdl_ps = 5000, + .refresh_rate_ps = 7800000U, +}; + +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; /* Modify accordingly */ + memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params)); + memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1); + + /* valid DIMM mask, change accordingly, together with dimm_on_ctlr. */ + return 0x5; +} +#endif /* CONFIG_DDR_NODIMM */ + +int ddr_board_options(struct ddr_info *priv) +{ + struct memctl_opt *popts = &priv->opt; + const struct ddr_conf *conf = &priv->conf; + + popts->vref_dimm = U(0x19); /* range 1, 83.4% */ + popts->rtt_override = 1U; + popts->rtt_override_value = 0x5U; /* RTT being used as 60 ohm */ + popts->rtt_park = 120U; + popts->otf_burst_chop_en = 0; + popts->burst_length = DDR_BL8; + popts->trwt_override = 1U; + popts->bstopre = 0U; /* auto precharge */ + popts->addr_hash = 1; + + /* Set ODT impedance on PHY side */ + switch (conf->cs_on_dimm[1]) { + case 0xc: /* Two slots dual rank */ + case 0x4: /* Two slots single rank, not valid for interleaving */ + popts->trwt = U(0xf); + popts->twrt = U(0x7); + popts->trrt = U(0x7); + popts->twwt = U(0x7); + popts->vref_phy = U(0x6B); /* 83.6% */ + popts->odt = 60U; + popts->phy_tx_impedance = 28U; + break; + case 0: /* Ont slot used */ + default: + popts->trwt = U(0x3); + popts->twrt = U(0x3); + popts->trrt = U(0x3); + popts->twwt = U(0x3); + popts->vref_phy = U(0x5D); /* 72% */ + popts->odt = 60U; + popts->phy_tx_impedance = 28U; + break; + } + + return 0; +} + +#ifdef NXP_WARM_BOOT +long long init_ddr(uint32_t wrm_bt_flg) +#else +long long init_ddr(void) +#endif +{ + int spd_addr[] = { 0x51, 0x52, 0x53, 0x54 }; + struct ddr_info info; + struct sysinfo sys; + long long dram_size; + + zeromem(&sys, sizeof(sys)); + if (get_clocks(&sys) != 0) { + ERROR("System clocks are not set\n"); + panic(); + } + 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(info)); + + /* Set two DDRC. Unused DDRC will be removed automatically. */ + info.num_ctlrs = NUM_OF_DDRC; + info.spd_addr = spd_addr; + info.ddr[0] = (void *)NXP_DDR_ADDR; + info.ddr[1] = (void *)NXP_DDR2_ADDR; + info.phy[0] = (void *)NXP_DDR_PHY1_ADDR; + info.phy[1] = (void *)NXP_DDR_PHY2_ADDR; + info.clk = get_ddr_freq(&sys, 0); + info.img_loadr = load_img; + info.phy_gen2_fw_img_buf = PHY_GEN2_FW_IMAGE_BUFFER; + if (info.clk == 0) { + info.clk = get_ddr_freq(&sys, 1); + } + info.dimm_on_ctlr = DDRC_NUM_DIMM; + + info.warm_boot_flag = DDR_WRM_BOOT_NT_SUPPORTED; +#ifdef NXP_WARM_BOOT + if (wrm_bt_flg != 0) { + info.warm_boot_flag = DDR_WARM_BOOT; + } else { + info.warm_boot_flag = DDR_COLD_BOOT; + } +#endif + + dram_size = dram_init(&info +#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) + , NXP_CCN_HN_F_0_ADDR +#endif + ); + + + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + + return dram_size; +} diff --git a/plat/nxp/soc-lx2160a/lx2162aqds/plat_def.h b/plat/nxp/soc-lx2160a/lx2162aqds/plat_def.h new file mode 100644 index 0000000..de2d244 --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2162aqds/plat_def.h @@ -0,0 +1,105 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include <arch.h> +#include <cortex_a72.h> +/* Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include <tbbr_img_def.h> + +#include <policy.h> +#include <soc.h> + +#if defined(IMAGE_BL31) +#define LS_SYS_TIMCTL_BASE 0x2890000 +#define PLAT_LS_NSTIMER_FRAME_ID 0 +#define LS_CONFIG_CNTACR 1 +#endif + +#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 (0x8000) +#define NXP_SD_BLOCK_BUF_ADDR (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \ + - NXP_SD_BLOCK_BUF_SIZE) + +#ifdef SD_BOOT +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \ + - NXP_SD_BLOCK_BUF_SIZE) +#else +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) +#endif + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES 4 +#define MAX_IO_BLOCK_DEVICES 1 +#define MAX_IO_HANDLES 4 + +#define PHY_GEN2_FW_IMAGE_BUFFER (NXP_OCRAM_ADDR + CSF_HDR_SZ) + +/* + * 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 3 +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 2 +#endif + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define BL32_IRQ_SEC_PHY_TIMER 29 + +#define BL31_WDOG_SEC 89 + +#define BL31_NS_WDOG_WS1 108 + +/* + * 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_EDGE) + +/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */ +#define NXP_IRQ_SEC_SGI_7 15 + +#define PLAT_LS_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(BL31_NS_WDOG_WS1, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(NXP_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) +#endif diff --git a/plat/nxp/soc-lx2160a/lx2162aqds/platform.c b/plat/nxp/soc-lx2160a/lx2162aqds/platform.c new file mode 100644 index 0000000..7622cf0 --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2162aqds/platform.c @@ -0,0 +1,29 @@ +/* + * Copyright 2020 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-lx2160a/lx2162aqds/platform.mk b/plat/nxp/soc-lx2160a/lx2162aqds/platform.mk new file mode 100644 index 0000000..2b4712c --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2162aqds/platform.mk @@ -0,0 +1,52 @@ +# +# Copyright 2018-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters + +BOOT_MODE ?= flexspi_nor +BOARD ?= lx2162aqds +POVDD_ENABLE := no +NXP_COINED_BB := no + + # DDR Compilation Configs +NUM_OF_DDRC := 1 +DDRC_NUM_DIMM := 1 +DDRC_NUM_CS := 2 +DDR_ECC_EN := yes + #enable address decoding feature +DDR_ADDR_DEC := yes +APPLY_MAX_CDD := yes + +# DDR Errata +ERRATA_DDR_A011396 := 1 +ERRATA_DDR_A050450 := 1 + + +# On-Board Flash Details +FLASH_TYPE := MT35XU512A +XSPI_FLASH_SZ := 0x10000000 +NXP_XSPI_NOR_UNIT_SIZE := 0x20000 +BL2_BIN_XSPI_NOR_END_ADDRESS := 0x100000 +# CONFIG_FSPI_ERASE_4K is required to erase 4K sector sizes. This +# config is enabled for future use cases. +FSPI_ERASE_4K := 0 + +# Platform specific features. +WARM_BOOT := yes + +# Adding Platform files build files +BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\ + ${BOARD_PATH}/platform.c + +SUPPORTED_BOOT_MODE := flexspi_nor \ + sd \ + emmc + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Adding SoC build info +include plat/nxp/soc-lx2160a/soc.mk diff --git a/plat/nxp/soc-lx2160a/lx2162aqds/platform_def.h b/plat/nxp/soc-lx2160a/lx2162aqds/platform_def.h new file mode 100644 index 0000000..5fa774e --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2162aqds/platform_def.h @@ -0,0 +1,14 @@ +/* + * Copyright 2018-2020 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 diff --git a/plat/nxp/soc-lx2160a/lx2162aqds/policy.h b/plat/nxp/soc-lx2160a/lx2162aqds/policy.h new file mode 100644 index 0000000..1095f38 --- /dev/null +++ b/plat/nxp/soc-lx2160a/lx2162aqds/policy.h @@ -0,0 +1,38 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef POLICY_H +#define POLICY_H + +/* Following defines affect the PLATFORM SECURITY POLICY */ + +/* set this to 0x0 if the platform is not using/responding to ECC errors + * set this to 0x1 if ECC is being used (we have to do some init) + */ +#define POLICY_USING_ECC 0x0 + +/* 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 + +/* + * POLICY_PERF_WRIOP = 0 : No Performance enhancement for WRIOP RN-I + * POLICY_PERF_WRIOP = 1 : No Performance enhancement for WRIOP RN-I = 7 + * POLICY_PERF_WRIOP = 2 : No Performance enhancement for WRIOP RN-I = 23 + */ +#define POLICY_PERF_WRIOP 0 + +/* + * set this to '1' if the debug clocks need to remain enabled during + * system entry to low-power (LPM20) - this should only be necessary + * for testing and NEVER set for normal production + */ +#define POLICY_DEBUG_ENABLE 0 + + +#endif /* POLICY_H */ diff --git a/plat/nxp/soc-lx2160a/soc.c b/plat/nxp/soc-lx2160a/soc.c new file mode 100644 index 0000000..427189d --- /dev/null +++ b/plat/nxp/soc-lx2160a/soc.c @@ -0,0 +1,542 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <assert.h> + +#include <arch.h> +#include <bl31/interrupt_mgmt.h> +#include <caam.h> +#include <cassert.h> +#include <ccn.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 +#include <nxp_smmu.h> +#include <nxp_timer.h> +#include <plat_console.h> +#include <plat_gic.h> +#include <plat_tzc400.h> +#include <pmu.h> +#if defined(NXP_SFP_ENABLED) +#include <sfp.h> +#endif + +#include <errata.h> +#include <ls_interrupt_mgmt.h> +#ifdef CONFIG_OCRAM_ECC_EN +#include <ocram.h> +#endif +#include "plat_common.h" +#ifdef NXP_NV_SW_MAINT_LAST_EXEC_DATA +#include <plat_nv_storage.h> +#endif +#ifdef NXP_WARM_BOOT +#include <plat_warm_rst.h> +#endif +#include "platform_def.h" +#include "soc.h" + +static struct soc_type soc_list[] = { + /* SoC LX2160A */ + SOC_ENTRY(LX2160A, LX2160A, 8, 2), + SOC_ENTRY(LX2160E, LX2160E, 8, 2), + SOC_ENTRY(LX2160C, LX2160C, 8, 2), + SOC_ENTRY(LX2160N, LX2160N, 8, 2), + SOC_ENTRY(LX2080A, LX2080A, 8, 1), + SOC_ENTRY(LX2080E, LX2080E, 8, 1), + SOC_ENTRY(LX2080C, LX2080C, 8, 1), + SOC_ENTRY(LX2080N, LX2080N, 8, 1), + SOC_ENTRY(LX2120A, LX2120A, 6, 2), + SOC_ENTRY(LX2120E, LX2120E, 6, 2), + SOC_ENTRY(LX2120C, LX2120C, 6, 2), + SOC_ENTRY(LX2120N, LX2120N, 6, 2), + /* SoC LX2162A */ + SOC_ENTRY(LX2162A, LX2162A, 8, 2), + SOC_ENTRY(LX2162E, LX2162E, 8, 2), + SOC_ENTRY(LX2162C, LX2162C, 8, 2), + SOC_ENTRY(LX2162N, LX2162N, 8, 2), + SOC_ENTRY(LX2082A, LX2082A, 8, 1), + SOC_ENTRY(LX2082E, LX2082E, 8, 1), + SOC_ENTRY(LX2082C, LX2082C, 8, 1), + SOC_ENTRY(LX2082N, LX2082N, 8, 1), + SOC_ENTRY(LX2122A, LX2122A, 6, 2), + SOC_ENTRY(LX2122E, LX2122E, 6, 2), + SOC_ENTRY(LX2122C, LX2122C, 6, 2), + SOC_ENTRY(LX2122N, LX2122N, 6, 2), +}; + +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, + }; +static const unsigned char master_to_6rn_id_map[] = { + PLAT_6CLUSTER_TO_CCN_ID_MAP +}; + +static const unsigned char master_to_rn_id_map[] = { + PLAT_CLUSTER_TO_CCN_ID_MAP +}; + +CASSERT(ARRAY_SIZE(master_to_rn_id_map) == NUMBER_OF_CLUSTERS, + assert_invalid_cluster_count_for_ccn_variant); + +static const ccn_desc_t plat_six_cluster_ccn_desc = { + .periphbase = NXP_CCN_ADDR, + .num_masters = ARRAY_SIZE(master_to_6rn_id_map), + .master_to_rn_id_map = master_to_6rn_id_map +}; + +static const ccn_desc_t plat_ccn_desc = { + .periphbase = NXP_CCN_ADDR, + .num_masters = ARRAY_SIZE(master_to_rn_id_map), + .master_to_rn_id_map = master_to_rn_id_map +}; + +/****************************************************************************** + * 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; +} + +#ifdef IMAGE_BL2 + +#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 + +static void soc_interconnect_config(void) +{ + unsigned long long val = 0x0U; + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), + &num_clusters, &cores_per_cluster); + + if (num_clusters == 6U) { + ccn_init(&plat_six_cluster_ccn_desc); + } else { + ccn_init(&plat_ccn_desc); + } + + /* + * Enable Interconnect coherency for the primary CPU's cluster. + */ + plat_ls_interconnect_enter_coherency(num_clusters); + + val = ccn_read_node_reg(NODE_TYPE_HNI, 13, PCIeRC_RN_I_NODE_ID_OFFSET); + val |= (1 << 17); + ccn_write_node_reg(NODE_TYPE_HNI, 13, PCIeRC_RN_I_NODE_ID_OFFSET, val); + + /* PCIe is Connected to RN-I 17 which is connected to HN-I 13. */ + val = ccn_read_node_reg(NODE_TYPE_HNI, 30, PCIeRC_RN_I_NODE_ID_OFFSET); + val |= (1 << 17); + ccn_write_node_reg(NODE_TYPE_HNI, 30, PCIeRC_RN_I_NODE_ID_OFFSET, val); + + val = ccn_read_node_reg(NODE_TYPE_HNI, 13, SA_AUX_CTRL_REG_OFFSET); + val |= SERIALIZE_DEV_nGnRnE_WRITES; + ccn_write_node_reg(NODE_TYPE_HNI, 13, SA_AUX_CTRL_REG_OFFSET, val); + + val = ccn_read_node_reg(NODE_TYPE_HNI, 30, SA_AUX_CTRL_REG_OFFSET); + val &= ~(ENABLE_RESERVE_BIT53); + val |= SERIALIZE_DEV_nGnRnE_WRITES; + ccn_write_node_reg(NODE_TYPE_HNI, 30, SA_AUX_CTRL_REG_OFFSET, val); + + val = ccn_read_node_reg(NODE_TYPE_HNI, 13, PoS_CONTROL_REG_OFFSET); + val &= ~(HNI_POS_EN); + ccn_write_node_reg(NODE_TYPE_HNI, 13, PoS_CONTROL_REG_OFFSET, val); + + val = ccn_read_node_reg(NODE_TYPE_HNI, 30, PoS_CONTROL_REG_OFFSET); + val &= ~(HNI_POS_EN); + ccn_write_node_reg(NODE_TYPE_HNI, 30, PoS_CONTROL_REG_OFFSET, val); + + val = ccn_read_node_reg(NODE_TYPE_HNI, 13, SA_AUX_CTRL_REG_OFFSET); + val &= ~(POS_EARLY_WR_COMP_EN); + ccn_write_node_reg(NODE_TYPE_HNI, 13, SA_AUX_CTRL_REG_OFFSET, val); + + val = ccn_read_node_reg(NODE_TYPE_HNI, 30, SA_AUX_CTRL_REG_OFFSET); + val &= ~(POS_EARLY_WR_COMP_EN); + ccn_write_node_reg(NODE_TYPE_HNI, 30, SA_AUX_CTRL_REG_OFFSET, val); + +#if POLICY_PERF_WRIOP + uint16_t wriop_rni = 0U; + + if (POLICY_PERF_WRIOP == 1) { + wriop_rni = 7U; + } else if (POLICY_PERF_WRIOP == 2) { + wriop_rni = 23U; + } else { + ERROR("Incorrect WRIOP selected.\n"); + panic(); + } + + val = ccn_read_node_reg(NODE_TYPE_RNI, wriop_rni, + SA_AUX_CTRL_REG_OFFSET); + val |= ENABLE_WUO; + ccn_write_node_reg(NODE_TYPE_HNI, wriop_rni, SA_AUX_CTRL_REG_OFFSET, + val); +#else + val = ccn_read_node_reg(NODE_TYPE_RNI, 17, SA_AUX_CTRL_REG_OFFSET); + val |= ENABLE_WUO; + ccn_write_node_reg(NODE_TYPE_RNI, 17, SA_AUX_CTRL_REG_OFFSET, val); +#endif +} + + +void soc_preload_setup(void) +{ + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); +#if defined(NXP_WARM_BOOT) + bool warm_reset = is_warm_boot(); +#endif + info_dram_regions->total_dram_size = +#if defined(NXP_WARM_BOOT) + init_ddr(warm_reset); +#else + init_ddr(); +#endif +} + +/******************************************************************************* + * This function implements soc specific erratas + * This is called before DDR is initialized or MMU is enabled + ******************************************************************************/ +void soc_early_init(void) +{ +#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 + + enable_timer_base_to_cluster(NXP_PMU_ADDR); + soc_interconnect_config(); + + enum boot_device dev = get_boot_dev(); + /* Mark the buffer for SD in OCRAM as non secure. + * The buffer is assumed to be at end of OCRAM for + * the logic below to calculate TZPC programming + */ + if (dev == BOOT_DEVICE_EMMC || dev == BOOT_DEVICE_SDHC2_EMMC) { + /* Calculate the region in OCRAM which is secure + * The buffer for SD needs to be marked non-secure + * to allow SD to do DMA operations on it + */ + uint32_t secure_region = (NXP_OCRAM_SIZE + - NXP_SD_BLOCK_BUF_SIZE); + uint32_t mask = secure_region/TZPC_BLOCK_SIZE; + + mmio_write_32(NXP_OCRAM_TZPC_ADDR, mask); + + /* Add the entry for buffer in MMU Table */ + mmap_add_region(NXP_SD_BLOCK_BUF_ADDR, NXP_SD_BLOCK_BUF_ADDR, + NXP_SD_BLOCK_BUF_SIZE, + MT_DEVICE | MT_RW | MT_NS); + } + + soc_errata(); + +#if (TRUSTED_BOARD_BOOT) || defined(POLICY_FUSE_PROVISION) + sfp_init(NXP_SFP_ADDR); +#endif + + /* + * Unlock write access for SMMU SMMU_CBn_ACTLR in all Non-secure contexts. + */ + smmu_cache_unlock(NXP_SMMU_ADDR); + INFO("SMMU Cache Unlocking is Configured.\n"); + +#if TRUSTED_BOARD_BOOT + uint32_t mode; + + /* 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 + + /* + * Initialize system level generic timer for Layerscape Socs. + */ + delay_timer_init(NXP_TIMER_ADDR); + i2c_init(NXP_I2C_ADDR); +} + +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; + + porsr1 = read_reg_porsr1(); + + rcw_src = (porsr1 & PORSR1_RCW_MASK) >> PORSR1_RCW_SHIFT; + + switch (rcw_src) { + case FLEXSPI_NOR: + src = BOOT_DEVICE_FLEXSPI_NOR; + INFO("RCW BOOT SRC is FLEXSPI NOR\n"); + break; + case FLEXSPI_NAND2K_VAL: + case FLEXSPI_NAND4K_VAL: + INFO("RCW BOOT SRC is FLEXSPI NAND\n"); + src = BOOT_DEVICE_FLEXSPI_NAND; + break; + case SDHC1_VAL: + src = BOOT_DEVICE_EMMC; + INFO("RCW BOOT SRC is SD\n"); + break; + case SDHC2_VAL: + src = BOOT_DEVICE_SDHC2_EMMC; + INFO("RCW BOOT SRC is EMMC\n"); + break; + default: + break; + } + + return src; +} + + +void soc_mem_access(void) +{ + const devdisr5_info_t *devdisr5_info = get_devdisr5_info(); + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); + struct tzc400_reg tzc400_reg_list[MAX_NUM_TZC_REGION]; + int dram_idx, index = 0U; + + 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_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); + } + + if (devdisr5_info->ddrc1_present != 0) { + INFO("DDR Controller 1.\n"); + mem_access_setup(NXP_TZC_ADDR, index, + tzc400_reg_list); + mem_access_setup(NXP_TZC3_ADDR, index, + tzc400_reg_list); + } + if (devdisr5_info->ddrc2_present != 0) { + INFO("DDR Controller 2.\n"); + mem_access_setup(NXP_TZC2_ADDR, index, + tzc400_reg_list); + mem_access_setup(NXP_TZC4_ADDR, index, + tzc400_reg_list); + } +} + +#else +const unsigned char _power_domain_tree_desc[] = {1, 8, 2, 2, 2, 2, 2, 2, 2, 2}; + +CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256, + assert_invalid_lx2160a_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 +} + +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(); +#ifdef LS_SYS_TIMCTL_BASE + ls_configure_sys_timer(LS_SYS_TIMCTL_BASE, + LS_CONFIG_CNTACR, + PLAT_LS_NSTIMER_FRAME_ID); +#endif +} + +/******************************************************************************* + * This function initializes the soc from the BL31 module + ******************************************************************************/ +void soc_init(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), + &num_clusters, &cores_per_cluster); + + /* low-level init of the soc */ + soc_init_start(); + _init_global_data(); + soc_init_percpu(); + _initialize_psci(); + + if (ccn_get_part0_id(NXP_CCN_ADDR) != CCN_508_PART0_ID) { + ERROR("Unrecognized CCN variant detected."); + ERROR("Only CCN-508 is supported\n"); + panic(); + } + + if (num_clusters == 6U) { + ccn_init(&plat_six_cluster_ccn_desc); + } else { + ccn_init(&plat_ccn_desc); + } + + plat_ls_interconnect_enter_coherency(num_clusters); + + /* Set platform security policies */ + _set_platform_security(); + + /* make sure any parallel init tasks are finished */ + soc_init_finish(); + + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled() == false) { + INFO("SEC is disabled.\n"); + } else { + sec_init(NXP_CAAM_ADDR); + } + +} + +#ifdef NXP_WDOG_RESTART +static uint64_t wdog_interrupt_handler(uint32_t id, uint32_t flags, + void *handle, void *cookie) +{ + uint8_t data = WDOG_RESET_FLAG; + + wr_nv_app_data(WDT_RESET_FLAG_OFFSET, + (uint8_t *)&data, sizeof(data)); + + mmio_write_32(NXP_RST_ADDR + RSTCNTL_OFFSET, SW_RST_REQ_INIT); + + return 0; +} +#endif + +void soc_runtime_setup(void) +{ + +#ifdef NXP_WDOG_RESTART + request_intr_type_el3(BL31_NS_WDOG_WS1, wdog_interrupt_handler); +#endif +} +#endif diff --git a/plat/nxp/soc-lx2160a/soc.def b/plat/nxp/soc-lx2160a/soc.def new file mode 100644 index 0000000..0442962 --- /dev/null +++ b/plat/nxp/soc-lx2160a/soc.def @@ -0,0 +1,119 @@ +# +# Copyright (c) 2015, 2016 Freescale Semiconductor, Inc. +# Copyright 2017-2022 NXP Semiconductors +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# This file contains the basic architecture definitions that drive the build +# +# ----------------------------------------------------------------------------- + +CORE_TYPE := a72 + +CACHE_LINE := 6 + +# set to GIC400 or GIC500 +GIC := GIC500 + +# set to CCI400 or CCN504 or CCN508 +INTERCONNECT := CCN508 + +# indicate layerscape chassis level - set to 3=LSCH3 or 2=LSCH2 +CHASSIS := 3_2 + +# TZC IP Details TZC used is TZC380 or TZC400 +TZC_ID := TZC400 + +# CONSOLE Details available is NS16550 or PL011 +CONSOLE := PL011 + +# Select the DDR PHY generation to be used +PLAT_DDR_PHY := PHY_GEN2 + +PHYS_SYS := 64 + +# Area of OCRAM reserved by ROM code +NXP_ROM_RSVD := 0xa000 + +# 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 + +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 + +# Defining the endianness for NXP ESDHC +NXP_ESDHC_ENDIANNESS := LE + +# Defining the endianness for NXP SFP +NXP_SFP_ENDIANNESS := LE + +# Defining the endianness for NXP GPIO +NXP_GPIO_ENDIANNESS := LE + +# Defining the endianness for NXP SNVS +NXP_SNVS_ENDIANNESS := LE + +# Defining the endianness for NXP CCSR GUR register +NXP_GUR_ENDIANNESS := LE + +# Defining the endianness for NXP FSPI register +NXP_FSPI_ENDIANNESS := LE + +# Defining the endianness for NXP SEC +NXP_SEC_ENDIANNESS := LE + +# Defining the endianness for NXP DDR +NXP_DDR_ENDIANNESS := LE + +NXP_DDR_INTLV_256B := 1 + +# OCRAM MAP for BL2 +# Before BL2 +# 0x18000000 - 0x18009fff -> Used by ROM code +# 0x1800a000 - 0x1800dfff -> CSF header for BL2 +# (The above area i.e 0x18000000 - 0x1800dfff is available +# for DDR PHY images scratch pad region during BL2 run time) +# For FlexSPI boot +# 0x1800e000 - 0x18040000 -> Reserved for BL2 binary +# For SD boot +# 0x1800e000 - 0x18030000 -> Reserved for BL2 binary +# 0x18030000 - 0x18040000 -> Reserved for SD buffer +OCRAM_START_ADDR := 0x18000000 +OCRAM_SIZE := 0x40000 + +# Location of BL2 on OCRAM +BL2_BASE_ADDR := $(shell echo $$(( $(OCRAM_START_ADDR) + $(NXP_ROM_RSVD) + $(CSF_HDR_SZ) ))) +# Covert to HEX to be used by create_pbl.mk +BL2_BASE := $(shell echo "0x"$$(echo "obase=16; ${BL2_BASE_ADDR}" | bc)) + +# BL2_HDR_LOC is at (OCRAM_ADDR + NXP_ROM_RSVD) +# This value BL2_HDR_LOC + CSF_HDR_SZ should not overalp with BL2_BASE +BL2_HDR_LOC_HDR ?= $(shell echo $$(( $(OCRAM_START_ADDR) + $(NXP_ROM_RSVD) ))) +# Covert to HEX to be used by create_pbl.mk +BL2_HDR_LOC := $$(echo "obase=16; ${BL2_HDR_LOC_HDR}" | bc) + +# SoC ERRATAS to be enabled +# +# Core Errata +ERRATA_A72_859971 := 1 + +# SoC Errata +ERRATA_SOC_A050426 := 1 + +# DDR Errata +ERRATA_DDR_A011396 := 1 +ERRATA_DDR_A050450 := 1 +ERRATA_DDR_A050958 := 1 + +# enable dynamic memory mapping +PLAT_XLAT_TABLES_DYNAMIC := 1 + +# OCRAM ECC Enabled +OCRAM_ECC_EN := yes diff --git a/plat/nxp/soc-lx2160a/soc.mk b/plat/nxp/soc-lx2160a/soc.mk new file mode 100644 index 0000000..239442c --- /dev/null +++ b/plat/nxp/soc-lx2160a/soc.mk @@ -0,0 +1,174 @@ +# +# Copyright 2018-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + + + # SoC-specific build parameters +SOC := lx2160a +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 + + # SoC-specific +NXP_WDOG_RESTART := yes + + + # Selecting dependent module, + # Selecting dependent drivers, and + # Adding defines. + + # for features enabled above. +ifeq (${NXP_WDOG_RESTART}, yes) +NXP_NV_SW_MAINT_LAST_EXEC_DATA := yes +LS_EL3_INTERRUPT_HANDLER := yes +$(eval $(call add_define, NXP_WDOG_RESTART)) +endif + + + # For Security Features +DISABLE_FUSE_WRITE := 1 +$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2)) +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,SFP_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2)) +# Used by create_pbl tool to +# create bl2_<boot_mode>_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)) + + + # Selecting Boot Source for the TFA images. +ifeq (${BOOT_MODE}, flexspi_nor) +$(eval $(call SET_NXP_MAKE_FLAG,XSPI_NEEDED,BL2)) +$(eval $(call add_define,FLEXSPI_NOR_BOOT)) +else +ifeq (${BOOT_MODE}, sd) +$(eval $(call SET_NXP_MAKE_FLAG,SD_MMC_NEEDED,BL2)) +$(eval $(call add_define,SD_BOOT)) +else +ifeq (${BOOT_MODE}, emmc) +$(eval $(call SET_NXP_MAKE_FLAG,SD_MMC_NEEDED,BL2)) +$(eval $(call add_define,EMMC_BOOT)) +else +$(error Un-supported Boot Mode = ${BOOT_MODE}) +endif +endif +endif + + + # Separate DDR-FIP image to be loaded. +$(eval $(call SET_NXP_MAKE_FLAG,DDR_FIP_IO_NEEDED,BL2)) + + +# 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 + +ifeq (${DDR_FIP_IO_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/fip_handler/ddr_fip/ddr_fip_io.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 + + + # Adding source files to generate separate DDR FIP image +include ${PLAT_SOC_PATH}/ddr_fip.mk |