diff options
Diffstat (limited to 'plat/nxp')
165 files changed, 25002 insertions, 0 deletions
diff --git a/plat/nxp/common/aarch64/bl31_data.S b/plat/nxp/common/aarch64/bl31_data.S new file mode 100644 index 0000000..cc91540 --- /dev/null +++ b/plat/nxp/common/aarch64/bl31_data.S @@ -0,0 +1,558 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <asm_macros.S> + +#include "bl31_data.h" +#include "plat_psci.h" +#include "platform_def.h" + +.global _getCoreData +.global _setCoreData +.global _getCoreState +.global _setCoreState +.global _init_global_data +.global _get_global_data +.global _set_global_data +.global _initialize_psci +.global _init_task_flags +.global _set_task1_start +.global _set_task1_done + + +/* Function returns the specified data field value from the specified cpu + * core data area + * in: x0 = core mask lsb + * x1 = data field name/offset + * out: x0 = data value + * uses x0, x1, x2, [x13, x14, x15] + */ +func _getCoreData + + /* generate a 0-based core number from the input mask */ + clz x2, x0 + mov x0, #63 + sub x0, x0, x2 + + /* x0 = core number (0-based) */ + /* x1 = field offset */ + + /* determine if this is bootcore or secondary core */ + cbnz x0, 1f + + /* get base address for bootcore data */ + ldr x2, =BC_PSCI_BASE + add x2, x2, x1 + b 2f + +1: /* get base address for secondary core data */ + + /* x0 = core number (0-based) */ + /* x1 = field offset */ + + /* generate number of regions to offset */ + mov x2, #SEC_REGION_SIZE + mul x2, x2, x0 + + /* x1 = field offset */ + /* x2 = region offset */ + + /* generate the total offset to data element */ + sub x1, x2, x1 + + /* x1 = total offset to data element */ + + /* get the base address */ + ldr x2, =SECONDARY_TOP + + /* apply offset to base addr */ + sub x2, x2, x1 +2: + /* x2 = data element address */ + + dc ivac, x2 + dsb sy + isb + /* read data */ + ldr x0, [x2] + + ret +endfunc _getCoreData + + +/* Function returns the SoC-specific state of the specified cpu + * in: x0 = core mask lsb + * out: x0 = data value + * uses x0, x1, x2, [x13, x14, x15] + */ +func _getCoreState + + mov x1, #CORE_STATE_DATA + + /* generate a 0-based core number from the input mask */ + clz x2, x0 + mov x0, #63 + sub x0, x0, x2 + + /* x0 = core number (0-based) */ + /* x1 = field offset */ + + /* determine if this is bootcore or secondary core */ + cbnz x0, 1f + + /* get base address for bootcore data */ + ldr x2, =BC_PSCI_BASE + add x2, x2, x1 + b 2f + +1: /* get base address for secondary core data */ + + /* x0 = core number (0-based) */ + /* x1 = field offset */ + + /* generate number of regions to offset */ + mov x2, #SEC_REGION_SIZE + mul x2, x2, x0 + + /* x1 = field offset */ + /* x2 = region offset */ + + /* generate the total offset to data element */ + sub x1, x2, x1 + + /* x1 = total offset to data element */ + + /* get the base address */ + ldr x2, =SECONDARY_TOP + + /* apply offset to base addr */ + sub x2, x2, x1 +2: + /* x2 = data element address */ + + dc ivac, x2 + dsb sy + isb + + /* read data */ + ldr x0, [x2] + + ret +endfunc _getCoreState + + +/* Function writes the specified data value into the specified cpu + * core data area + * in: x0 = core mask lsb + * x1 = data field offset + * x2 = data value to write/store + * out: none + * uses x0, x1, x2, x3, [x13, x14, x15] + */ +func _setCoreData + /* x0 = core mask */ + /* x1 = field offset */ + /* x2 = data value */ + + clz x3, x0 + mov x0, #63 + sub x0, x0, x3 + + /* x0 = core number (0-based) */ + /* x1 = field offset */ + /* x2 = data value */ + + /* determine if this is bootcore or secondary core */ + cbnz x0, 1f + + /* get base address for bootcore data */ + ldr x3, =BC_PSCI_BASE + add x3, x3, x1 + b 2f + +1: /* get base address for secondary core data */ + + /* x0 = core number (0-based) */ + /* x1 = field offset */ + /* x2 = data value */ + + /* generate number of regions to offset */ + mov x3, #SEC_REGION_SIZE + mul x3, x3, x0 + + /* x1 = field offset */ + /* x2 = data value */ + /* x3 = region offset */ + + /* generate the total offset to data element */ + sub x1, x3, x1 + + /* x1 = total offset to data element */ + /* x2 = data value */ + + ldr x3, =SECONDARY_TOP + + /* apply offset to base addr */ + sub x3, x3, x1 + +2: + /* x2 = data value */ + /* x3 = data element address */ + + str x2, [x3] + + dc cvac, x3 + dsb sy + isb + ret +endfunc _setCoreData + + +/* Function stores the specified core state + * in: x0 = core mask lsb + * x1 = data value to write/store + * out: none + * uses x0, x1, x2, x3, [x13, x14, x15] + */ +func _setCoreState + mov x2, #CORE_STATE_DATA + + clz x3, x0 + mov x0, #63 + sub x0, x0, x3 + + /* x0 = core number (0-based) */ + /* x1 = data value */ + /* x2 = field offset */ + + /* determine if this is bootcore or secondary core */ + cbnz x0, 1f + + /* get base address for bootcore data */ + ldr x3, =BC_PSCI_BASE + add x3, x3, x2 + b 2f + +1: /* get base address for secondary core data */ + + /* x0 = core number (0-based) */ + /* x1 = data value */ + /* x2 = field offset */ + + /* generate number of regions to offset */ + mov x3, #SEC_REGION_SIZE + mul x3, x3, x0 + + /* x1 = data value */ + /* x2 = field offset */ + /* x3 = region offset */ + + /* generate the total offset to data element */ + sub x2, x3, x2 + + /* x1 = data value */ + /* x2 = total offset to data element */ + + ldr x3, =SECONDARY_TOP + + /* apply offset to base addr */ + sub x3, x3, x2 + +2: + /* x1 = data value */ + /* x3 = data element address */ + + str x1, [x3] + + dc civac, x3 + dsb sy + isb + ret +endfunc _setCoreState + + +/* Function sets the task1 start + * in: w0 = value to set flag to + * out: none + * uses x0, x1 + */ +func _set_task1_start + + ldr x1, =SMC_TASK1_BASE + + add x1, x1, #TSK_START_OFFSET + str w0, [x1] + dc cvac, x1 + dsb sy + isb + ret +endfunc _set_task1_start + + +/* Function sets the state of the task 1 done flag + * in: w0 = value to set flag to + * out: none + * uses x0, x1 + */ +func _set_task1_done + + ldr x1, =SMC_TASK1_BASE + + add x1, x1, #TSK_DONE_OFFSET + str w0, [x1] + dc cvac, x1 + dsb sy + isb + ret +endfunc _set_task1_done + + +/* Function initializes the smc global data entries + * Note: the constant LAST_SMC_GLBL_OFFSET must reference the last entry in the + * smc global region + * in: none + * out: none + * uses x0, x1, x2 + */ +func _init_global_data + + ldr x1, =SMC_GLBL_BASE + + /* x1 = SMC_GLBL_BASE */ + + mov x2, #LAST_SMC_GLBL_OFFSET + add x2, x2, x1 +1: + str xzr, [x1] + dc cvac, x1 + cmp x2, x1 + add x1, x1, #8 + b.hi 1b + + dsb sy + isb + ret +endfunc _init_global_data + + +/* Function gets the value of the specified global data element + * in: x0 = offset of data element + * out: x0 = requested data element + * uses x0, x1 + */ +func _get_global_data + + ldr x1, =SMC_GLBL_BASE + add x1, x1, x0 + dc ivac, x1 + isb + + ldr x0, [x1] + ret +endfunc _get_global_data + + +/* Function sets the value of the specified global data element + * in: x0 = offset of data element + * x1 = value to write + * out: none + * uses x0, x1, x2 + */ +func _set_global_data + + ldr x2, =SMC_GLBL_BASE + add x0, x0, x2 + str x1, [x0] + dc cvac, x0 + + dsb sy + isb + ret +endfunc _set_global_data + + +/* Function initializes the core data areas + * only executed by the boot core + * in: none + * out: none + * uses: x0, x1, x2, x3, x4, x5, x6, x7, [x13, x14, x15] + */ +func _initialize_psci + mov x7, x30 + + /* initialize the bootcore psci data */ + ldr x5, =BC_PSCI_BASE + mov x6, #CORE_RELEASED + + str x6, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5], #8 + dc cvac, x5 + str xzr, [x5] + dc cvac, x5 + dsb sy + isb + + /* see if we have any secondary cores */ + mov x4, #PLATFORM_CORE_COUNT + sub x4, x4, #1 + cbz x4, 3f + + /* initialize the secondary core's psci data */ + ldr x5, =SECONDARY_TOP + /* core mask lsb for core 1 */ + mov x3, #2 + sub x5, x5, #SEC_REGION_SIZE + + /* x3 = core1 mask lsb */ + /* x4 = number of secondary cores */ + /* x5 = core1 psci data base address */ +2: + /* set core state in x6 */ + mov x0, x3 + mov x6, #CORE_IN_RESET + bl _soc_ck_disabled + cbz x0, 1f + mov x6, #CORE_DISABLED +1: + add x2, x5, #CORE_STATE_DATA + str x6, [x2] + dc cvac, x2 + add x2, x5, #SPSR_EL3_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #CNTXT_ID_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #START_ADDR_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #LINK_REG_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #GICC_CTLR_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #ABORT_FLAG_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #SCTLR_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #CPUECTLR_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #AUX_01_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #AUX_02_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #AUX_03_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #AUX_04_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #AUX_05_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #SCR_EL3_DATA + str xzr, [x2] + dc cvac, x2 + add x2, x5, #HCR_EL2_DATA + str xzr, [x2] + dc cvac, x2 + dsb sy + isb + + sub x4, x4, #1 + cbz x4, 3f + + /* generate next core mask */ + lsl x3, x3, #1 + + /* decrement base address to next data area */ + sub x5, x5, #SEC_REGION_SIZE + b 2b +3: + mov x30, x7 + ret +endfunc _initialize_psci + + +/* Function initializes the soc init task flags + * in: none + * out: none + * uses x0, x1, [x13, x14, x15] + */ +func _init_task_flags + + /* get the base address of the first task structure */ + ldr x0, =SMC_TASK1_BASE + + /* x0 = task1 base address */ + + str wzr, [x0, #TSK_START_OFFSET] + str wzr, [x0, #TSK_DONE_OFFSET] + str wzr, [x0, #TSK_CORE_OFFSET] + dc cvac, x0 + + /* move to task2 structure */ + add x0, x0, #SMC_TASK_OFFSET + + str wzr, [x0, #TSK_START_OFFSET] + str wzr, [x0, #TSK_DONE_OFFSET] + str wzr, [x0, #TSK_CORE_OFFSET] + dc cvac, x0 + + /* move to task3 structure */ + add x0, x0, #SMC_TASK_OFFSET + + str wzr, [x0, #TSK_START_OFFSET] + str wzr, [x0, #TSK_DONE_OFFSET] + str wzr, [x0, #TSK_CORE_OFFSET] + dc cvac, x0 + + /* move to task4 structure */ + add x0, x0, #SMC_TASK_OFFSET + + str wzr, [x0, #TSK_START_OFFSET] + str wzr, [x0, #TSK_DONE_OFFSET] + str wzr, [x0, #TSK_CORE_OFFSET] + dc cvac, x0 + + dsb sy + isb + ret +endfunc _init_task_flags diff --git a/plat/nxp/common/aarch64/ls_helpers.S b/plat/nxp/common/aarch64/ls_helpers.S new file mode 100644 index 0000000..311dce1 --- /dev/null +++ b/plat/nxp/common/aarch64/ls_helpers.S @@ -0,0 +1,220 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <asm_macros.S> +#include <cortex_a53.h> +#include <drivers/console.h> +#include <lib/cpus/aarch64/cortex_a72.h> + +#include <platform_def.h> + + + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_core_pos + .globl plat_my_core_pos + .globl plat_core_mask + .globl plat_my_core_mask + .globl plat_core_pos_by_mpidr + .globl _disable_ldstr_pfetch_A53 + .globl _disable_ldstr_pfetch_A72 + .global _set_smmu_pagesz_64 + + /* int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0 - x4 + */ + + /* int plat_crash_console_init(void) + * Use normal console by default. Switch it to crash + * mode so serial consoles become active again. + * NOTE: This default implementation will only work for + * crashes that occur after a normal console (marked + * valid for the crash state) has been registered with + * the console framework. To debug crashes that occur + * earlier, the platform has to override these functions + * with an implementation that initializes a console + * driver with hardcoded parameters. See + * docs/porting-guide.rst for more information. + */ +func plat_crash_console_init + mov x3, x30 + mov x0, #CONSOLE_FLAG_CRASH + bl console_switch_state + mov x0, #1 + ret x3 +endfunc plat_crash_console_init + + /* void plat_crash_console_putc(int character) + * Output through the normal console by default. + */ +func plat_crash_console_putc + b console_putc +endfunc plat_crash_console_putc + + /* void plat_crash_console_flush(void) + * Flush normal console by default. + */ +func plat_crash_console_flush + b console_flush +endfunc plat_crash_console_flush + +/* This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + */ +func plat_core_pos_by_mpidr + + b plat_core_pos + +endfunc plat_core_pos_by_mpidr + +#if (SYMMETRICAL_CLUSTERS) +/* unsigned int plat_my_core_mask(void) + * generate a mask bit for this core + */ +func plat_my_core_mask + mrs x0, MPIDR_EL1 + b plat_core_mask +endfunc plat_my_core_mask + +/* unsigned int plat_core_mask(u_register_t mpidr) + * generate a lsb-based mask bit for the core specified by mpidr in x0. + * + * SoC core = ((cluster * cpu_per_cluster) + core) + * mask = (1 << SoC core) + */ +func plat_core_mask + mov w1, wzr + mov w2, wzr + + /* extract cluster */ + bfxil w1, w0, #8, #8 + /* extract cpu # */ + bfxil w2, w0, #0, #8 + + mov w0, wzr + + /* error checking */ + cmp w1, #NUMBER_OF_CLUSTERS + b.ge 1f + cmp w2, #CORES_PER_CLUSTER + b.ge 1f + + mov w0, #CORES_PER_CLUSTER + mul w1, w1, w0 + add w1, w1, w2 + mov w2, #0x1 + lsl w0, w2, w1 +1: + ret +endfunc plat_core_mask + +/* + * unsigned int plat_my_core_pos(void) + * generate a linear core number for this core + */ +func plat_my_core_pos + mrs x0, MPIDR_EL1 + b plat_core_pos +endfunc plat_my_core_pos + +/* + * unsigned int plat_core_pos(u_register_t mpidr) + * Generate a linear core number for the core specified by mpidr. + * + * SoC core = ((cluster * cpu_per_cluster) + core) + * Returns -1 if mpidr invalid + */ +func plat_core_pos + mov w1, wzr + mov w2, wzr + bfxil w1, w0, #8, #8 /* extract cluster */ + bfxil w2, w0, #0, #8 /* extract cpu # */ + + mov w0, #-1 + + /* error checking */ + cmp w1, #NUMBER_OF_CLUSTERS + b.ge 1f + cmp w2, #CORES_PER_CLUSTER + b.ge 1f + + mov w0, #CORES_PER_CLUSTER + mul w1, w1, w0 + add w0, w1, w2 +1: + ret +endfunc plat_core_pos + +#endif + +/* this function disables the load-store prefetch of the calling core + * Note: this function is for A53 cores ONLY + * in: none + * out: none + * uses x0 + */ +func _disable_ldstr_pfetch_A53 + mrs x0, CORTEX_A53_CPUACTLR_EL1 + tst x0, #CORTEX_A53_CPUACTLR_EL1_L1PCTL + b.ne 1f + b 2f + +.align 6 +1: + dsb sy + isb + bic x0, x0, #CORTEX_A53_CPUACTLR_EL1_L1PCTL + msr CORTEX_A53_CPUACTLR_EL1, x0 + isb + +2: + ret +endfunc _disable_ldstr_pfetch_A53 + + +/* this function disables the load-store prefetch of the calling core + * Note: this function is for A72 cores ONLY + * in: none + * out: none + * uses x0 + */ +func _disable_ldstr_pfetch_A72 + + mrs x0, CORTEX_A72_CPUACTLR_EL1 + tst x0, #CORTEX_A72_CPUACTLR_EL1_DISABLE_L1_DCACHE_HW_PFTCH + b.eq 1f + b 2f + +.align 6 +1: + dsb sy + isb + orr x0, x0, #CORTEX_A72_CPUACTLR_EL1_DISABLE_L1_DCACHE_HW_PFTCH + msr CORTEX_A72_CPUACTLR_EL1, x0 + isb + +2: + ret +endfunc _disable_ldstr_pfetch_A72 + +/* + * Function sets the SACR pagesize to 64k + */ +func _set_smmu_pagesz_64 + + ldr x1, =NXP_SMMU_ADDR + ldr w0, [x1, #0x10] + orr w0, w0, #1 << 16 /* setting to 64K page */ + str w0, [x1, #0x10] + + ret +endfunc _set_smmu_pagesz_64 diff --git a/plat/nxp/common/fip_handler/common/plat_def_fip_uuid.h b/plat/nxp/common/fip_handler/common/plat_def_fip_uuid.h new file mode 100644 index 0000000..65aef14 --- /dev/null +++ b/plat/nxp/common/fip_handler/common/plat_def_fip_uuid.h @@ -0,0 +1,51 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_DEF_FIP_UUID_H +#define PLAT_DEF_FIP_UUID_H + +/* PHy images configs */ +#define UUID_DDR_IMEM_UDIMM_1D \ + {{0x5b, 0xdb, 0xe3, 0x83}, {0xd1, 0x9f}, {0xc7, 0x06}, 0xd4, 0x91, {0x76, 0x4f, 0x9d, 0x23, 0x2d, 0x2d} } + +#define UUID_DDR_IMEM_UDIMM_2D \ + {{0xfa, 0x0e, 0xeb, 0x21}, {0xe0, 0x7f}, {0x8e, 0x65}, 0x95, 0xd8, {0x2b, 0x94, 0xf6, 0xb8, 0x28, 0x0a} } + +#define UUID_DDR_DMEM_UDIMM_1D \ + {{0xba, 0xbb, 0xfd, 0x7e}, {0x5b, 0xf0}, {0xeb, 0xb8}, 0xeb, 0x71, {0xb1, 0x85, 0x07, 0xdd, 0xe1, 0x32} } + +#define UUID_DDR_DMEM_UDIMM_2D \ + {{0xb6, 0x99, 0x61, 0xda}, {0xf9, 0x92}, {0x4b, 0x9e}, 0x0c, 0x49, {0x74, 0xa5, 0xe0, 0x5c, 0xbe, 0xc3} } + +#define UUID_DDR_IMEM_RDIMM_1D \ + {{0x42, 0x33, 0x66, 0x52}, {0xd8, 0x94}, {0x4d, 0xc1}, 0x91, 0xcc, {0x26, 0x8f, 0x7a, 0x67, 0xf1, 0xa2} } + +#define UUID_DDR_IMEM_RDIMM_2D \ + {{0x2e, 0x95, 0x73, 0xba}, {0xb5, 0xca}, {0x7c, 0xc7}, 0xef, 0xc9, {0x5e, 0xb0, 0x42, 0xec, 0x08, 0x7a} } + +#define UUID_DDR_DMEM_RDIMM_1D \ + {{0x1c, 0x51, 0x17, 0xed}, {0x30, 0x0d}, {0xae, 0xba}, 0x87, 0x03, {0x1f, 0x37, 0x85, 0xec, 0xe1, 0x44} } + +#define UUID_DDR_DMEM_RDIMM_2D \ + {{0xe9, 0x0a, 0x90, 0x78}, {0x11, 0xd6}, {0x8b, 0xba}, 0x24, 0x35, {0xec, 0x10, 0x75, 0x4f, 0x56, 0xa5} } + +#define UUID_DDR_FW_KEY_CERT \ + {{0xac, 0x4b, 0xb8, 0x9c}, {0x8f, 0xb9}, {0x11, 0xea}, 0xbc, 0x55, {0x02, 0x42, 0xac, 0x12, 0x00, 0x03} } + +#define UUID_DDR_UDIMM_FW_CONTENT_CERT \ + {{0x2c, 0x7f, 0x52, 0x54}, {0x70, 0x92}, {0x48, 0x40}, 0x8c, 0x34, {0x87, 0x4b, 0xbf, 0xbd, 0x9d, 0x89} } + +#define UUID_DDR_RDIMM_FW_CONTENT_CERT \ + {{0x94, 0xc3, 0x63, 0x30}, {0x7c, 0xf7}, {0x4f, 0x1d}, 0xaa, 0xcd, {0xb5, 0x80, 0xb2, 0xc2, 0x40, 0xa5} } + +#define UUID_FUSE_PROV \ + {{0xec, 0x45, 0x90, 0x42}, {0x30, 0x0d}, {0xae, 0xba}, 0x87, 0x03, {0x1f, 0x37, 0x85, 0xec, 0xe1, 0x44} } + +#define UUID_FUSE_UP \ + {{0x89, 0x46, 0xef, 0x78}, {0x11, 0xd6}, {0x8b, 0xba}, 0x24, 0x35, {0xec, 0x10, 0x75, 0x4f, 0x56, 0xa5} } + +#endif /* PLAT_DEF_FIP_UUID_H */ diff --git a/plat/nxp/common/fip_handler/common/plat_tbbr_img_def.h b/plat/nxp/common/fip_handler/common/plat_tbbr_img_def.h new file mode 100644 index 0000000..9856f70 --- /dev/null +++ b/plat/nxp/common/fip_handler/common/plat_tbbr_img_def.h @@ -0,0 +1,53 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef NXP_IMG_DEF_H +#define NXP_IMG_DEF_H + +#include <export/common/tbbr/tbbr_img_def_exp.h> + +#ifdef CONFIG_DDR_FIP_IMAGE +/* DDR FIP IMAGE ID */ +#define DDR_FIP_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + +#define DDR_IMEM_UDIMM_1D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 1 +#define DDR_IMEM_UDIMM_2D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 2 + +#define DDR_DMEM_UDIMM_1D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 3 +#define DDR_DMEM_UDIMM_2D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 4 + +#define DDR_IMEM_RDIMM_1D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 5 +#define DDR_IMEM_RDIMM_2D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 6 + +#define DDR_DMEM_RDIMM_1D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 7 +#define DDR_DMEM_RDIMM_2D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 8 + +#define DDR_FW_KEY_CERT_ID MAX_IMG_IDS_WITH_SPMDS + 9 +#define DDR_UDIMM_FW_CONTENT_CERT_ID MAX_IMG_IDS_WITH_SPMDS + 10 +#define DDR_RDIMM_FW_CONTENT_CERT_ID MAX_IMG_IDS_WITH_SPMDS + 11 +/* Max Images */ +#define MAX_IMG_WITH_DDR_IDS MAX_IMG_IDS_WITH_SPMDS + 12 +#else +#define MAX_IMG_WITH_DDR_IDS MAX_IMG_IDS_WITH_SPMDS +#endif + +#ifdef POLICY_FUSE_PROVISION +/* FUSE FIP IMAGE ID */ +#define FUSE_FIP_IMAGE_ID MAX_IMG_WITH_DDR_IDS + +#define FUSE_PROV_IMAGE_ID MAX_IMG_WITH_DDR_IDS + 1 + +#define FUSE_UP_IMAGE_ID MAX_IMG_WITH_DDR_IDS + 2 + +#define MAX_IMG_WITH_FIMG_IDS MAX_IMG_WITH_DDR_IDS + 3 +#else +#define MAX_IMG_WITH_FIMG_IDS MAX_IMG_WITH_DDR_IDS +#endif + +#define MAX_NUMBER_IDS MAX_IMG_WITH_FIMG_IDS + +#endif /* NXP_IMG_DEF_H */ diff --git a/plat/nxp/common/fip_handler/common/platform_oid.h b/plat/nxp/common/fip_handler/common/platform_oid.h new file mode 100644 index 0000000..bbd6041 --- /dev/null +++ b/plat/nxp/common/fip_handler/common/platform_oid.h @@ -0,0 +1,16 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#define DDR_FW_CONTENT_CERT_PK_OID "1.3.6.1.4.1.4128.2200.1" +#define DDR_IMEM_UDIMM_1D_HASH_OID "1.3.6.1.4.1.4128.2200.2" +#define DDR_IMEM_UDIMM_2D_HASH_OID "1.3.6.1.4.1.4128.2200.3" +#define DDR_DMEM_UDIMM_1D_HASH_OID "1.3.6.1.4.1.4128.2200.4" +#define DDR_DMEM_UDIMM_2D_HASH_OID "1.3.6.1.4.1.4128.2200.5" +#define DDR_IMEM_RDIMM_1D_HASH_OID "1.3.6.1.4.1.4128.2200.6" +#define DDR_IMEM_RDIMM_2D_HASH_OID "1.3.6.1.4.1.4128.2200.7" +#define DDR_DMEM_RDIMM_1D_HASH_OID "1.3.6.1.4.1.4128.2200.8" +#define DDR_DMEM_RDIMM_2D_HASH_OID "1.3.6.1.4.1.4128.2200.9" diff --git a/plat/nxp/common/fip_handler/ddr_fip/ddr_fip_io.mk b/plat/nxp/common/fip_handler/ddr_fip/ddr_fip_io.mk new file mode 100644 index 0000000..7d673ba --- /dev/null +++ b/plat/nxp/common/fip_handler/ddr_fip/ddr_fip_io.mk @@ -0,0 +1,38 @@ +# +# Copyright 2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +#----------------------------------------------------------------------------- +ifeq (${DDR_FIP_IO_STORAGE_ADDED},) + +$(eval $(call add_define, PLAT_DEF_FIP_UUID)) +$(eval $(call add_define, PLAT_TBBR_IMG_DEF)) +$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2)) + +DDR_FIP_IO_STORAGE_ADDED := 1 +$(eval $(call add_define,CONFIG_DDR_FIP_IMAGE)) + +FIP_HANDLER_PATH := ${PLAT_COMMON_PATH}/fip_handler +FIP_HANDLER_COMMON_PATH := ${FIP_HANDLER_PATH}/common +DDR_FIP_IO_STORAGE_PATH := ${FIP_HANDLER_PATH}/ddr_fip + +PLAT_INCLUDES += -I${FIP_HANDLER_COMMON_PATH}\ + -I$(DDR_FIP_IO_STORAGE_PATH) + +DDR_FIP_IO_SOURCES += $(DDR_FIP_IO_STORAGE_PATH)/ddr_io_storage.c + +$(shell cp tools/nxp/plat_fiptool/plat_fiptool.mk ${PLAT_DIR}) + +ifeq (${BL_COMM_DDR_FIP_IO_NEEDED},yes) +BL_COMMON_SOURCES += ${DDR_FIP_IO_SOURCES} +else +ifeq (${BL2_DDR_FIP_IO_NEEDED},yes) +BL2_SOURCES += ${DDR_FIP_IO_SOURCES} +endif +ifeq (${BL31_DDR_FIP_IO_NEEDED},yes) +BL31_SOURCES += ${DDR_FIP_IO_SOURCES} +endif +endif +endif +#------------------------------------------------ diff --git a/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.c b/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.c new file mode 100644 index 0000000..fc3c4a4 --- /dev/null +++ b/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.c @@ -0,0 +1,232 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <assert.h> +#include <string.h> + +#include <io_block.h> +#include <io_driver.h> +#include <io_fip.h> +#include <io_memmap.h> +#include <io_storage.h> +#include <lib/utils.h> +#include <tools_share/firmware_image_package.h> +#include "ddr_io_storage.h" +#include "plat_common.h" +#include "platform_def.h" + + +/* TBD - Move these defined to the platform_def.h file. + * Keeping them for reference here + */ +extern uintptr_t backend_dev_handle; + +static uint32_t ddr_fip; + +static uintptr_t ddr_fip_dev_handle; + +static io_block_spec_t ddr_fip_block_spec = { + .offset = PLAT_DDR_FIP_OFFSET, + .length = PLAT_DDR_FIP_MAX_SIZE +}; + +static const io_uuid_spec_t ddr_imem_udimm_1d_uuid_spec = { + .uuid = UUID_DDR_IMEM_UDIMM_1D, +}; + +static const io_uuid_spec_t ddr_imem_udimm_2d_uuid_spec = { + .uuid = UUID_DDR_IMEM_UDIMM_2D, +}; + +static const io_uuid_spec_t ddr_dmem_udimm_1d_uuid_spec = { + .uuid = UUID_DDR_DMEM_UDIMM_1D, +}; + +static const io_uuid_spec_t ddr_dmem_udimm_2d_uuid_spec = { + .uuid = UUID_DDR_DMEM_UDIMM_2D, +}; + +static const io_uuid_spec_t ddr_imem_rdimm_1d_uuid_spec = { + .uuid = UUID_DDR_IMEM_RDIMM_1D, +}; + +static const io_uuid_spec_t ddr_imem_rdimm_2d_uuid_spec = { + .uuid = UUID_DDR_IMEM_RDIMM_2D, +}; + +static const io_uuid_spec_t ddr_dmem_rdimm_1d_uuid_spec = { + .uuid = UUID_DDR_DMEM_RDIMM_1D, +}; + +static const io_uuid_spec_t ddr_dmem_rdimm_2d_uuid_spec = { + .uuid = UUID_DDR_DMEM_RDIMM_2D, +}; + +#if TRUSTED_BOARD_BOOT +static const io_uuid_spec_t ddr_fw_key_cert_uuid_spec = { + .uuid = UUID_DDR_FW_KEY_CERT, +}; +static const io_uuid_spec_t ddr_udimm_fw_cert_uuid_spec = { + .uuid = UUID_DDR_UDIMM_FW_CONTENT_CERT, +}; +static const io_uuid_spec_t ddr_rdimm_fw_cert_uuid_spec = { + .uuid = UUID_DDR_RDIMM_FW_CONTENT_CERT, +}; +#endif + +static int open_ddr_fip(const uintptr_t spec); + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +/* By default, ARM platforms load images from the FIP */ +static const struct plat_io_policy ddr_policies[] = { + [DDR_FIP_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &backend_dev_handle, + (uintptr_t)&ddr_fip_block_spec, + NULL + }, + [DDR_IMEM_UDIMM_1D_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_imem_udimm_1d_uuid_spec, + open_ddr_fip + }, + [DDR_IMEM_UDIMM_2D_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_imem_udimm_2d_uuid_spec, + open_ddr_fip + }, + [DDR_DMEM_UDIMM_1D_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_dmem_udimm_1d_uuid_spec, + open_ddr_fip + }, + [DDR_DMEM_UDIMM_2D_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_dmem_udimm_2d_uuid_spec, + open_ddr_fip + }, + [DDR_IMEM_RDIMM_1D_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_imem_rdimm_1d_uuid_spec, + open_ddr_fip + }, + [DDR_IMEM_RDIMM_2D_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_imem_rdimm_2d_uuid_spec, + open_ddr_fip + }, + [DDR_DMEM_RDIMM_1D_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_dmem_rdimm_1d_uuid_spec, + open_ddr_fip + }, + [DDR_DMEM_RDIMM_2D_IMAGE_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_dmem_rdimm_2d_uuid_spec, + open_ddr_fip + }, +#if TRUSTED_BOARD_BOOT + [DDR_FW_KEY_CERT_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_fw_key_cert_uuid_spec, + open_ddr_fip + }, + [DDR_UDIMM_FW_CONTENT_CERT_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_udimm_fw_cert_uuid_spec, + open_ddr_fip + }, + [DDR_RDIMM_FW_CONTENT_CERT_ID - DDR_FIP_IMAGE_ID] = { + &ddr_fip_dev_handle, + (uintptr_t)&ddr_rdimm_fw_cert_uuid_spec, + open_ddr_fip + }, +#endif +}; + +static int open_ddr_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(ddr_fip_dev_handle, (uintptr_t)DDR_FIP_IMAGE_ID); + if (result == 0) { + result = io_open(ddr_fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + +/* The image can be one of the DDR PHY images, which can be sleected via DDR + * policies + */ +int plat_get_ddr_fip_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec, + int (*check)(const uintptr_t spec)) +{ + int result = -1; + const struct plat_io_policy *policy; + + if (image_id >= (DDR_FIP_IMAGE_ID + ARRAY_SIZE(ddr_policies))) { + return result; + } + + policy = &ddr_policies[image_id - DDR_FIP_IMAGE_ID]; + if (image_id == DDR_FIP_IMAGE_ID) { + result = check(policy->image_spec); + } else { + result = policy->check(policy->image_spec); + } + if (result == 0) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + } + return result; +} + +int ddr_fip_setup(const io_dev_connector_t *fip_dev_con, unsigned int boot_dev) +{ + int io_result; + size_t ddr_fip_offset = PLAT_DDR_FIP_OFFSET; + + /* Open connections to ddr fip and cache the handles */ + io_result = io_dev_open(fip_dev_con, (uintptr_t)&ddr_fip, + &ddr_fip_dev_handle); + assert(io_result == 0); + + switch (boot_dev) { +#if QSPI_BOOT + case BOOT_DEVICE_QSPI: + ddr_fip_offset += NXP_QSPI_FLASH_ADDR; + break; +#endif +#if NOR_BOOT + case BOOT_DEVICE_IFC_NOR: + ddr_fip_offset += NXP_NOR_FLASH_ADDR; + break; +#endif +#if FLEXSPI_NOR_BOOT + case BOOT_DEVICE_FLEXSPI_NOR: + ddr_fip_offset += NXP_FLEXSPI_FLASH_ADDR; + break; +#endif + default: + break; + } + + ddr_fip_block_spec.offset = ddr_fip_offset; + + return io_result; +} diff --git a/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.h b/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.h new file mode 100644 index 0000000..6df3902 --- /dev/null +++ b/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.h @@ -0,0 +1,26 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DDR_IO_STORAGE_H +#define DDR_IO_STORAGE_H + +#include <drivers/io/io_driver.h> + +#ifndef PLAT_DDR_FIP_OFFSET +#define PLAT_DDR_FIP_OFFSET 0x800000 +#endif + +#ifndef PLAT_DDR_FIP_MAX_SIZE +#define PLAT_DDR_FIP_MAX_SIZE 0x32000 +#endif + +int ddr_fip_setup(const io_dev_connector_t *fip_dev_con, unsigned int boot_dev); +int plat_get_ddr_fip_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec, + int (*check)(const uintptr_t spec)); + +#endif /* DDR_IO_STORAGE_H */ diff --git a/plat/nxp/common/fip_handler/fuse_fip/fuse.mk b/plat/nxp/common/fip_handler/fuse_fip/fuse.mk new file mode 100644 index 0000000..d8f5ae6 --- /dev/null +++ b/plat/nxp/common/fip_handler/fuse_fip/fuse.mk @@ -0,0 +1,100 @@ +# +# Copyright 2018-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +NEED_FUSE := yes + +$(eval $(call add_define, PLAT_DEF_FIP_UUID)) +$(eval $(call add_define, POLICY_FUSE_PROVISION)) +$(eval $(call add_define, PLAT_TBBR_IMG_DEF)) + +$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,GPIO_NEEDED,BL2)) + +FIP_HANDLER_PATH := ${PLAT_COMMON_PATH}/fip_handler +FIP_HANDLER_COMMON_PATH := ${FIP_HANDLER_PATH}/common + +FUSE_SOURCES := ${FIP_HANDLER_PATH}/fuse_fip/fuse_io_storage.c + +PLAT_INCLUDES += -I${FIP_HANDLER_COMMON_PATH}\ + -I${FIP_HANDLER_PATH}/fuse_fip + +FUSE_FIP_NAME := fuse_fip.bin + +fip_fuse: ${BUILD_PLAT}/${FUSE_FIP_NAME} + +ifeq (${FUSE_PROV_FILE},) + +$(shell cp tools/nxp/plat_fiptool/plat_fiptool.mk ${PLAT_DIR}) + +else +ifeq (${TRUSTED_BOARD_BOOT},1) +FUSE_PROV_FILE_SB = $(notdir ${FUSE_PROV_FILE})_prov.sb +FUSE_FIP_ARGS += --fuse-prov ${BUILD_PLAT}/${FUSE_PROV_FILE_SB} +FUSE_FIP_DEPS += ${BUILD_PLAT}/${FUSE_PROV_FILE_SB} +else +FUSE_FIP_ARGS += --fuse-prov ${FUSE_PROV_FILE} +FUSE_FIP_DEPS += ${FUSE_PROV_FILE} +endif +endif + +ifeq (${FUSE_UP_FILE},) +else +ifeq (${TRUSTED_BOARD_BOOT},1) +FUSE_UP_FILE_SB = $(notdir ${FUSE_UP_FILE})_up.sb +FUSE_FIP_ARGS += --fuse-up ${BUILD_PLAT}/${FUSE_UP_FILE_SB} +FUSE_FIP_DEPS += ${BUILD_PLAT}/${FUSE_UP_FILE_SB} +else +FUSE_FIP_ARGS += --fuse-up ${FUSE_UP_FILE} +FUSE_FIP_DEPS += ${FUSE_UP_FILE} +endif +endif + +ifeq (${TRUSTED_BOARD_BOOT},1) + +ifeq (${MBEDTLS_DIR},) +else + $(error Error: Trusted Board Boot with X509 certificates not supported with FUSE_PROG build option) +endif + +# 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 (${FUSE_INPUT_FILE},) +FUSE_INPUT_FILE := $(PLAT_DRIVERS_PATH)/auth/csf_hdr_parser/${CSF_FILE} +endif + +ifeq (${FUSE_PROV_FILE},) +else +${BUILD_PLAT}/${FUSE_PROV_FILE_SB}: ${FUSE_PROV_FILE} + @echo " Generating CSF Header for $@ $<" + $(CST_DIR)/create_hdr_esbc --in $< --out $@ --app_off ${CSF_HDR_SZ} \ + --app $< ${FUSE_INPUT_FILE} +endif + +ifeq (${FUSE_UP_FILE},) +else +${BUILD_PLAT}/${FUSE_UP_FILE_SB}: ${FUSE_UP_FILE} + @echo " Generating CSF Header for $@ $<" + $(CST_DIR)/create_hdr_esbc --in $< --out $@ --app_off ${CSF_HDR_SZ} \ + --app $< ${FUSE_INPUT_FILE} +endif + +endif + +${BUILD_PLAT}/${FUSE_FIP_NAME}: fiptool ${FUSE_FIP_DEPS} +ifeq (${FUSE_FIP_DEPS},) + $(error "Error: FUSE_PROV_FILE or/and FUSE_UP_FILE needs to point to the right file") +endif + ${FIPTOOL} create ${FUSE_FIP_ARGS} $@ + ${FIPTOOL} info $@ + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} diff --git a/plat/nxp/common/fip_handler/fuse_fip/fuse_io.h b/plat/nxp/common/fip_handler/fuse_fip/fuse_io.h new file mode 100644 index 0000000..e8775d0 --- /dev/null +++ b/plat/nxp/common/fip_handler/fuse_fip/fuse_io.h @@ -0,0 +1,27 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#ifndef FUSE_IO_H +#define FUSE_IO_H + +#include <drivers/io/io_driver.h> + +/* Can be overridden from platform_def.h file. + */ +#ifndef PLAT_FUSE_FIP_OFFSET +#define PLAT_FUSE_FIP_OFFSET 0x880000 +#endif +#ifndef PLAT_FUSE_FIP_MAX_SIZE +#define PLAT_FUSE_FIP_MAX_SIZE 0x80000 +#endif + +int fip_fuse_provisioning(uintptr_t image_buf, uint32_t size); +int fuse_fip_setup(const io_dev_connector_t *fip_dev_con, unsigned int boot_dev); +int plat_get_fuse_image_source(unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec, + int (*check)(const uintptr_t spec)); +#endif /* FUSE_IO_H */ diff --git a/plat/nxp/common/fip_handler/fuse_fip/fuse_io_storage.c b/plat/nxp/common/fip_handler/fuse_fip/fuse_io_storage.c new file mode 100644 index 0000000..017ffcf --- /dev/null +++ b/plat/nxp/common/fip_handler/fuse_fip/fuse_io_storage.c @@ -0,0 +1,223 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <assert.h> +#include <string.h> + +#include <common/debug.h> +#include <dcfg.h> +#include <drivers/delay_timer.h> +#include <fuse_prov.h> +#include <io_block.h> +#include <io_driver.h> +#include <io_fip.h> +#include <io_memmap.h> +#include <io_storage.h> +#include <lib/utils.h> +#include <nxp_gpio.h> +#include <sfp.h> +#include <sfp_error_codes.h> +#include <tools_share/firmware_image_package.h> + +#include "fuse_io.h" +#include <load_img.h> +#include <plat/common/platform.h> +#include "plat_common.h" +#include "platform_def.h" + +extern uintptr_t backend_dev_handle; + +static uint32_t fuse_fip; + +static uintptr_t fuse_fip_dev_handle; + +static io_block_spec_t fuse_fip_block_spec = { + .offset = PLAT_FUSE_FIP_OFFSET, + .length = PLAT_FUSE_FIP_MAX_SIZE +}; + +static const io_uuid_spec_t fuse_prov_uuid_spec = { + .uuid = UUID_FUSE_PROV, +}; + +static const io_uuid_spec_t fuse_up_uuid_spec = { + .uuid = UUID_FUSE_UP, +}; + +static int open_fuse_fip(const uintptr_t spec); + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +/* By default, ARM platforms load images from the FIP */ +static const struct plat_io_policy fuse_policies[] = { + [FUSE_FIP_IMAGE_ID - FUSE_FIP_IMAGE_ID] = { + &backend_dev_handle, + (uintptr_t)&fuse_fip_block_spec, + NULL + }, + [FUSE_PROV_IMAGE_ID - FUSE_FIP_IMAGE_ID] = { + &fuse_fip_dev_handle, + (uintptr_t)&fuse_prov_uuid_spec, + open_fuse_fip + }, + [FUSE_UP_IMAGE_ID - FUSE_FIP_IMAGE_ID] = { + &fuse_fip_dev_handle, + (uintptr_t)&fuse_up_uuid_spec, + open_fuse_fip + } +}; + +static int open_fuse_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(fuse_fip_dev_handle, (uintptr_t)FUSE_FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fuse_fip_dev_handle, + spec, + &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + +/* The image can be one of the DDR PHY images, which can be sleected via DDR + * policies + */ +int plat_get_fuse_image_source(unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec, + int (*check)(const uintptr_t spec)) +{ + int result; + const struct plat_io_policy *policy; + + assert(image_id < (FUSE_FIP_IMAGE_ID + ARRAY_SIZE(fuse_policies))); + + policy = &fuse_policies[image_id - FUSE_FIP_IMAGE_ID]; + + if (image_id == FUSE_FIP_IMAGE_ID) { + result = check(policy->image_spec); + } else { + result = policy->check(policy->image_spec); + } + + if (result == 0) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + } + return result; +} + +int fuse_fip_setup(const io_dev_connector_t *fip_dev_con, unsigned int boot_dev) +{ + int io_result; + size_t fuse_fip_offset = PLAT_FUSE_FIP_OFFSET; + + /* Open connections to fuse fip and cache the handles */ + io_result = io_dev_open(fip_dev_con, (uintptr_t)&fuse_fip, + &fuse_fip_dev_handle); + + assert(io_result == 0); + + switch (boot_dev) { +#if QSPI_BOOT + case BOOT_DEVICE_QSPI: + fuse_fip_offset += NXP_QSPI_FLASH_ADDR; + break; +#endif +#if NOR_BOOT + case BOOT_DEVICE_IFC_NOR: + fuse_fip_offset += NXP_NOR_FLASH_ADDR; + break; +#endif +#if FLEXSPI_NOR_BOOT + case BOOT_DEVICE_FLEXSPI_NOR: + fuse_fip_offset += NXP_FLEXSPI_FLASH_ADDR; + break; +#endif + default: + break; + } + + fuse_fip_block_spec.offset = fuse_fip_offset; + + return io_result; +} + +int fip_fuse_provisioning(uintptr_t image_buf, uint32_t size) +{ + uint32_t bit_num; + uint32_t *gpio_base_addr = NULL; + struct fuse_hdr_t *fuse_hdr = NULL; + uint8_t barker[] = {0x68U, 0x39U, 0x27U, 0x81U}; + int ret = -1; + + if (sfp_check_oem_wp() == 0) { + ret = load_img(FUSE_PROV_IMAGE_ID, &image_buf, &size); + if (ret != 0) { + ERROR("Failed to load FUSE PRIV image\n"); + assert(ret == 0); + } + fuse_hdr = (struct fuse_hdr_t *)image_buf; + + /* Check barker code */ + if (memcmp(fuse_hdr->barker, barker, sizeof(barker)) != 0) { + ERROR("FUSE Barker code mismatch.\n"); + error_handler(ERROR_FUSE_BARKER); + return 1; + } + + /* Check if GPIO pin to be set for POVDD */ + if (((fuse_hdr->flags >> FLAG_POVDD_SHIFT) & 0x1) != 0) { + gpio_base_addr = + select_gpio_n_bitnum(fuse_hdr->povdd_gpio, + &bit_num); + /* + * Add delay so that Efuse gets the power + * when GPIO is enabled. + */ + ret = set_gpio_bit(gpio_base_addr, bit_num); + mdelay(EFUSE_POWERUP_DELAY_mSec); + } else { + ret = (board_enable_povdd() == true) ? 0 : PLAT_ERROR_ENABLE_POVDD; + } + if (ret != 0) { + ERROR("Error enabling board POVDD: %d\n", ret); + ERROR("Only SFP mirror register will be set.\n"); + } + + provision_fuses(image_buf, ret == 0); + + /* Check if GPIO pin to be reset for POVDD */ + if (((fuse_hdr->flags >> FLAG_POVDD_SHIFT) & 0x1) != 0) { + if (gpio_base_addr == NULL) { + gpio_base_addr = + select_gpio_n_bitnum( + fuse_hdr->povdd_gpio, + &bit_num); + } + ret = clr_gpio_bit(gpio_base_addr, bit_num); + } else { + ret = board_disable_povdd() ? 0 : PLAT_ERROR_DISABLE_POVDD; + } + + if (ret != 0) { + ERROR("Error disabling board POVDD: %d\n", ret); + } + } + return 0; +} diff --git a/plat/nxp/common/img_loadr/img_loadr.mk b/plat/nxp/common/img_loadr/img_loadr.mk new file mode 100644 index 0000000..f64b1fa --- /dev/null +++ b/plat/nxp/common/img_loadr/img_loadr.mk @@ -0,0 +1,21 @@ +# +# Copyright 2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +IMG_LOADR_DRIVERS_PATH := ${PLAT_COMMON_PATH}/img_loadr + +IMG_LOADR_SOURCES := $(IMG_LOADR_DRIVERS_PATH)/load_img.c +PLAT_INCLUDES += -I$(IMG_LOADR_DRIVERS_PATH) + +ifeq (${BL_COMM_IMG_LOADR_NEEDED},yes) +BL_COMMON_SOURCES += ${IMG_LOADR_SOURCES} +else +ifeq (${BL2_IMG_LOADR_NEEDED},yes) +BL2_SOURCES += ${IMG_LOADR_SOURCES} +endif +ifeq (${BL31_IMG_LOADR_NEEDED},yes) +BL31_SOURCES += ${IMG_LOADR_SOURCES} +endif +endif diff --git a/plat/nxp/common/img_loadr/load_img.c b/plat/nxp/common/img_loadr/load_img.c new file mode 100644 index 0000000..51011e4 --- /dev/null +++ b/plat/nxp/common/img_loadr/load_img.c @@ -0,0 +1,83 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <assert.h> + +#include <common/bl_common.h> +#include <common/desc_image_load.h> +#include <lib/xlat_tables/xlat_tables_v2.h> + +#include "load_img.h" + +/****************************************************************************** + * This function can be used to load DDR PHY/FUSE Images + * + * @param [in] image_id Image ID to be loaded + * + * @param [in,out] image_base Location at which the image should be loaded + * In case image is prepended by a CSF header, + * image_base is pointer to actual image after + * the header + * + * @param [in,out] image_size User should pass the maximum size of the image + * possible.(Buffer size starting from image_base) + * Actual size of the image loaded is returned + * back. + *****************************************************************************/ +int load_img(unsigned int image_id, uintptr_t *image_base, + uint32_t *image_size) +{ + int err = 0; + + image_desc_t img_info = { + .image_id = image_id, + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, 0), +#ifdef CSF_HEADER_PREPENDED + .image_info.image_base = *image_base - CSF_HDR_SZ, + .image_info.image_max_size = *image_size + CSF_HDR_SZ, +#else + .image_info.image_base = *image_base, + .image_info.image_max_size = *image_size, +#endif + }; + + /* Create MMU entry for the CSF header */ +#if PLAT_XLAT_TABLES_DYNAMIC +#ifdef CSF_HEADER_PREPENDED + err = mmap_add_dynamic_region(img_info.image_info.image_base, + img_info.image_info.image_base, + CSF_HDR_SZ, + MT_MEMORY | MT_RW | MT_SECURE); + if (err != 0) { + ERROR("Failed to add dynamic memory region.\n"); + return err; + } +#endif +#endif + + VERBOSE("BL2: Loading IMG %d\n", image_id); + err = load_auth_image(image_id, &img_info.image_info); + if (err != 0) { + VERBOSE("Failed to load IMG %d\n", image_id); + return err; + } + +#ifdef CSF_HEADER_PREPENDED + *image_base = img_info.image_info.image_base + CSF_HDR_SZ; + *image_size = img_info.image_info.image_size - CSF_HDR_SZ; +#if PLAT_XLAT_TABLES_DYNAMIC + mmap_remove_dynamic_region(img_info.image_info.image_base, + CSF_HDR_SZ); +#endif +#else + *image_base = img_info.image_info.image_base; + *image_size = img_info.image_info.image_size; +#endif + + return err; +} diff --git a/plat/nxp/common/img_loadr/load_img.h b/plat/nxp/common/img_loadr/load_img.h new file mode 100644 index 0000000..6f9de32 --- /dev/null +++ b/plat/nxp/common/img_loadr/load_img.h @@ -0,0 +1,14 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef LOAD_IMAGE_H +#define LOAD_IMAGE_H + +int load_img(unsigned int image_id, uintptr_t *image_base, + uint32_t *image_size); + +#endif /* LOAD_IMAGE_H */ diff --git a/plat/nxp/common/include/default/ch_2/soc_default_base_addr.h b/plat/nxp/common/include/default/ch_2/soc_default_base_addr.h new file mode 100644 index 0000000..6296aef --- /dev/null +++ b/plat/nxp/common/include/default/ch_2/soc_default_base_addr.h @@ -0,0 +1,70 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SOC_DEFAULT_BASE_ADDR_H +#define SOC_DEFAULT_BASE_ADDR_H + +/* CCSR mmu_def.h */ +#define NXP_CCSR_ADDR 0x01000000 +#define NXP_CCSR_SIZE 0x0F000000 + +#define NXP_DCSR_ADDR 0x20000000 +#define NXP_DCSR_SIZE 0x4000000 + +/* Flex-SPI controller address */ +#define NXP_FLEXSPI_ADDR 0x020C0000 +/* QSPI Flash Start address */ +#define NXP_QSPI_FLASH_ADDR 0x40000000 +/* NOR Flash Start address */ +#define NXP_IFC_REGION_ADDR 0x60000000 +#define NXP_NOR_FLASH_ADDR NXP_IFC_REGION_ADDR + +/* MMU 500 soc.c*/ +#define NXP_SMMU_ADDR 0x09000000 + +#define NXP_SNVS_ADDR 0x01E90000 + +#define NXP_DCFG_ADDR 0x01EE0000 +#define NXP_SFP_ADDR 0x01E80000 +#define NXP_RCPM_ADDR 0x01EE2000 +#define NXP_CSU_ADDR 0x01510000 +#define NXP_IFC_ADDR 0x01530000 +#define NXP_SCFG_ADDR 0x01570000 +#define NXP_DCSR_ADDR 0x20000000 +#define NXP_DCSR_DCFG_ADDR (NXP_DCSR_ADDR + 0x00140000) +#define NXP_I2C_ADDR 0x02180000 +#define NXP_ESDHC_ADDR 0x01560000 +#define NXP_UART_ADDR 0x021C0500 +#define NXP_UART1_ADDR 0x021C0600 + +#define NXP_GPIO1_ADDR 0x02300000 +#define NXP_GPIO2_ADDR 0x02310000 +#define NXP_GPIO3_ADDR 0x02320000 +#define NXP_GPIO4_ADDR 0x02330000 + +#define NXP_WDOG1_NS_ADDR 0x02390000 +#define NXP_WDOG2_NS_ADDR 0x023A0000 +#define NXP_WDOG1_TZ_ADDR 0x023B0000 +#define NXP_WDOG2_TZ_ADDR 0x023C0000 + +#define NXP_TIMER_STATUS_ADDR 0x023F0000 + +#define NXP_GICD_4K_ADDR 0x01401000 +#define NXP_GICC_4K_ADDR 0x01402000 +#define NXP_GICD_64K_ADDR 0x01410000 +#define NXP_GICC_64K_ADDR 0x01420000 + +#define NXP_CAAM_ADDR 0x01700000 + +#define NXP_TZC_ADDR 0x01500000 +#define NXP_DDR_ADDR 0x01080000 + +#define NXP_TIMER_ADDR 0x02B00000 +#define NXP_CCI_ADDR 0x01180000 +#define NXP_RESET_ADDR 0x01E60000 +#define NXP_SEC_REGFILE_ADDR 0x01E88000 +#endif /* SOC_DEFAULT_BASE_ADDR_H */ diff --git a/plat/nxp/common/include/default/ch_2/soc_default_helper_macros.h b/plat/nxp/common/include/default/ch_2/soc_default_helper_macros.h new file mode 100644 index 0000000..928ac05 --- /dev/null +++ b/plat/nxp/common/include/default/ch_2/soc_default_helper_macros.h @@ -0,0 +1,83 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SOC_DEFAULT_HELPER_MACROS_H +#define SOC_DEFAULT_HELPER_MACROS_H + +#ifdef NXP_OCRAM_TZPC_ADDR + +/* 0x1: means 4 KB + * 0x2: means 8 KB + */ +#define TZPC_BLOCK_SIZE 0x1000 +#endif + +/* DDR controller offsets and defines */ +#ifdef NXP_DDR_ADDR + +#define DDR_CFG_2_OFFSET 0x114 +#define CFG_2_FORCE_REFRESH 0x80000000 + +#endif /* NXP_DDR_ADDR */ + + /* Reset block register offsets */ +#ifdef NXP_RESET_ADDR + +/* Register Offset */ +#define RST_RSTCR_OFFSET 0x0 +#define RST_RSTRQMR1_OFFSET 0x10 +#define RST_RSTRQSR1_OFFSET 0x18 +#define BRR_OFFSET 0x60 + +/* helper macros */ +#define RSTRQSR1_SWRR 0x800 +#define RSTRQMR_RPTOE_MASK (1 << 19) + +#endif /* NXP_RESET_ADDR */ + +/* Secure-Register-File register offsets and bit masks */ +#ifdef NXP_RST_ADDR +/* Register Offset */ +#define CORE_HOLD_OFFSET 0x140 +#define RSTCNTL_OFFSET 0x180 + +/* Helper macros */ +#define SW_RST_REQ_INIT 0x1 +#endif + +#ifdef NXP_RCPM_ADDR +/* RCPM Register Offsets */ +#define RCPM_PCPH20SETR_OFFSET 0x0D4 +#define RCPM_PCPH20CLRR_OFFSET 0x0D8 +#define RCPM_POWMGTCSR_OFFSET 0x130 +#define RCPM_IPPDEXPCR0_OFFSET 0x140 +#define RCPM_POWMGTCSR_LPM20_REQ 0x00100000 + +#define RCPM2_IPSTPCR0_OFFSET 0x8 +#define RCPM2_IPSTPCR1_OFFSET 0xC +#define RCPM2_IPSTPCR2_OFFSET 0x10 +#define RCPM2_IPSTPCR3_OFFSET 0x14 +#define RCPM2_IPSTPCR4_OFFSET 0x28 + +#define RCPM2_IPSTPACKR0_OFFSET 0x18 +#define RCPM2_IPSTPACKR1_OFFSET 0x1C +#define RCPM2_IPSTPACKR2_OFFSET 0x20 +#define RCPM2_IPSTPACKR3_OFFSET 0x24 +#define RCPM2_IPSTPACKR4_OFFSET 0x2C +#define RCPM2_POWMGTDCR_OFFSET 0x0 + +/* bitfield masks */ +#define POWMGTDCR_OVRD_EN 0x80000000 + +#endif /* NXP_RCPM_ADDR */ + +#define DCFG_SBEESR2_ADDR 0x20140534 +#define DCFG_MBEESR2_ADDR 0x20140544 +/* SBEESR and MBEESR bit mask */ +#define OCRAM_EESR_MASK 0x00000060 + +#endif /* SOC_DEFAULT_HELPER_MACROS_H */ diff --git a/plat/nxp/common/include/default/ch_3/soc_default_base_addr.h b/plat/nxp/common/include/default/ch_3/soc_default_base_addr.h new file mode 100644 index 0000000..8d64f04 --- /dev/null +++ b/plat/nxp/common/include/default/ch_3/soc_default_base_addr.h @@ -0,0 +1,100 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SOC_DEFAULT_BASE_ADDR_H +#define SOC_DEFAULT_BASE_ADDR_H + +/* CCSR mmu_def.h */ +#define NXP_CCSR_ADDR 0x1000000 +#define NXP_CCSR_SIZE 0xF000000 + +#define NXP_DCSR_ADDR 0x700000000 +#define NXP_DCSR_SIZE 0x40000000 + +/* Quad SPI Region #1 base address */ +#define NXP_QSPI_FLASH_ADDR 0x20000000 + +/* IFC Region #1 base address */ +#define NXP_NOR_FLASH_ADDR 0x30000000 + +/* MMU 500 */ +#define NXP_SMMU_ADDR 0x05000000 + +#define NXP_SNVS_ADDR 0x01E90000 + +#define NXP_DCFG_ADDR 0x01E00000 +#define NXP_PMU_CCSR_ADDR 0x01E30000 +#define NXP_PMU_DCSR_ADDR 0x700123000 +#define NXP_PMU_ADDR NXP_PMU_CCSR_ADDR +#define NXP_SFP_ADDR 0x01E80000 +#define NXP_SCFG_ADDR 0x01FC0000 +#define NXP_I2C_ADDR 0x02000000 +#define NXP_ESDHC_ADDR 0x02140000 +#define NXP_ESDHC2_ADDR 0x02150000 +#ifndef NXP_UART_ADDR +#define NXP_UART_ADDR 0x021C0500 +#endif +#ifndef NXP_UART1_ADDR +#define NXP_UART1_ADDR 0x021C0600 +#endif + +#define NXP_GPIO1_ADDR 0x02300000 +#define NXP_GPIO2_ADDR 0x02310000 +#define NXP_GPIO3_ADDR 0x02320000 +#define NXP_GPIO4_ADDR 0x02330000 + +#define NXP_WDOG1_NS_ADDR 0x02390000 +#define NXP_WDOG2_NS_ADDR 0x023A0000 +#define NXP_WDOG1_TZ_ADDR 0x023B0000 +#define NXP_WDOG2_TZ_ADDR 0x023C0000 + +#define NXP_TIMER_STATUS_ADDR 0x023F0000 + +#define NXP_GICD_ADDR 0x06000000 +#define NXP_GICR_ADDR 0x06100000 +#define NXP_GICR_SGI_ADDR 0x06110000 + +#define NXP_CAAM_ADDR 0x08000000 + +#define NXP_TZC_ADDR 0x01100000 +#define NXP_TZC2_ADDR 0x01110000 +#define NXP_TZC3_ADDR 0x01120000 + +#define NXP_RESET_ADDR 0x01E60000 +#define NXP_SEC_REGFILE_ADDR 0x01E88000 + +#define NXP_RST_ADDR 0x01E88000 + +/* DDR memory Map */ +#define NXP_DDR_ADDR 0x01080000 +#define NXP_DDR2_ADDR 0x01090000 +#define NXP_DDR3_ADDR 0x08210000 + +/* QuadSPI base address */ +#define NXP_QSPI_ADDR 0x020C0000 +/* IFC base address */ +#define NXP_IFC_ADDR 0x02240000 + +/* CCI400 base address */ +#define NXP_CCI_ADDR 0x04090000 + +/* Global Generic Reference Timer base address */ +#define NXP_TIMER_ADDR 0x023E0000 + +/* OCRAM TZPC base address */ +#define NXP_OCRAM_TZPC_ADDR 0x02200000 + +#define NXP_EPU_ADDR 0x700060000 + +#define NXP_CCN_ADDR 0x04000000 +#define NXP_CCN_HNI_ADDR 0x04080000 +#define NXP_CCN_HN_F_0_ADDR 0x04200000 +#define NXP_CCN_HN_F_1_ADDR 0x04210000 + +#define TPMWAKEMR0_ADDR 0x700123c50 + +#endif /* SOC_DEFAULT_BASE_ADDR_H */ diff --git a/plat/nxp/common/include/default/ch_3/soc_default_helper_macros.h b/plat/nxp/common/include/default/ch_3/soc_default_helper_macros.h new file mode 100644 index 0000000..8e68367 --- /dev/null +++ b/plat/nxp/common/include/default/ch_3/soc_default_helper_macros.h @@ -0,0 +1,98 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef SOC_DEFAULT_HELPER_MACROS_H +#define SOC_DEFAULT_HELPER_MACROS_H + +#ifdef NXP_OCRAM_TZPC_ADDR +#define TZPC_BLOCK_SIZE 0x1000 +#endif + +/* Reset block register offsets */ +#ifdef NXP_RESET_ADDR + +/* Register Offset */ +#define RST_RSTCR_OFFSET 0x0 +#define RST_RSTRQMR1_OFFSET 0x10 +#define RST_RSTRQSR1_OFFSET 0x18 +#define BRR_OFFSET 0x60 + +/* helper macros */ +#define RSTRQMR_RPTOE_MASK (1 << 19) +#endif /* NXP_RESET_ADDR */ + +#define PCIeRC_RN_I_NODE_ID_OFFSET 0x8 +#define PoS_CONTROL_REG_OFFSET 0x0 +#define POS_EARLY_WR_COMP_EN 0x20 +#define HNI_POS_EN 0x01 +#define POS_TERMINATE_BARRIERS 0x10 +#define SERIALIZE_DEV_nGnRnE_WRITES 0x200 +#define ENABLE_ERR_SIGNAL_TO_MN 0x4 +#define ENABLE_RESERVE_BIT53 0x400 +#define ENABLE_WUO 0x10 + +#define PORT_S0_CTRL_REG_RNI 0x010 +#define PORT_S1_CTRL_REG_RNI 0x110 +#define PORT_S2_CTRL_REG_RNI 0x210 +#define ENABLE_FORCE_RD_QUO 0x20 +#define QOS_SETTING 0x00FF000C + +/* epu register offsets and values */ +#define EPU_EPGCR_OFFSET 0x0 +#define EPU_EPIMCR10_OFFSET 0x128 +#define EPU_EPCTR10_OFFSET 0xa28 +#define EPU_EPCCR10_OFFSET 0x828 +#ifndef EPU_EPCCR10_VAL +#define EPU_EPCCR10_VAL 0xb2800000 +#endif +#define EPU_EPIMCR10_VAL 0xba000000 +#define EPU_EPCTR10_VAL 0x0 +#define EPU_EPGCR_VAL (1 << 31) + +#ifdef NXP_CCN_ADDR +#define NXP_CCN_HN_F_1_ADDR 0x04210000 + +#define CCN_HN_F_SAM_NODEID_MASK 0x7f +#define CCN_HN_F_SNP_DMN_CTL_OFFSET 0x200 +#define CCN_HN_F_SNP_DMN_CTL_SET_OFFSET 0x210 +#define CCN_HN_F_SNP_DMN_CTL_CLR_OFFSET 0x220 +#define CCN_HN_F_SNP_DMN_CTL_MASK 0x80a00 +#define CCN_HNF_NODE_COUNT 8 +#define CCN_HNF_OFFSET 0x10000 + +#define SA_AUX_CTRL_REG_OFFSET 0x500 +#define NUM_HNI_NODE 2 +#define CCN_HNI_MEMORY_MAP_SIZE 0x10000 + +#define PCIeRC_RN_I_NODE_ID_OFFSET 0x8 +#define PoS_CONTROL_REG_OFFSET 0x0 +#define POS_EARLY_WR_COMP_EN 0x20 +#define HNI_POS_EN 0x01 +#define POS_TERMINATE_BARRIERS 0x10 +#define SERIALIZE_DEV_nGnRnE_WRITES 0x200 +#define ENABLE_ERR_SIGNAL_TO_MN 0x4 +#define ENABLE_RESERVE_BIT53 0x400 +#define ENABLE_WUO 0x10 +#endif + +/* reset register bit */ +#define RSTRQMR_RPTOE_MASK (1 << 19) + +/* secmon register offsets and bitfields */ +#define SECMON_HPCOMR_OFFSET 0x4 +#define SECMON_HPCOMR_NPSWAEN 0x80000000 + +/* Secure-Register-File register offsets and bit masks */ +#ifdef NXP_RST_ADDR +/* Register Offset */ +#define CORE_HOLD_OFFSET 0x140 +#endif + +#define DCFG_SBEESR2_ADDR 0x00100534 +#define DCFG_MBEESR2_ADDR 0x00100544 +/* SBEESR and MBEESR bit mask */ +#define OCRAM_EESR_MASK 0x00000008 + +#endif /* SOC_DEFAULT_HELPER_MACROS_H */ diff --git a/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h b/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h new file mode 100644 index 0000000..0a4228b --- /dev/null +++ b/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h @@ -0,0 +1,88 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SOC_DEFAULT_BASE_ADDR_H +#define SOC_DEFAULT_BASE_ADDR_H + +/* CCSR mmu_def.h */ +#define NXP_CCSR_ADDR 0x1000000 +#define NXP_CCSR_SIZE 0xF000000 + +#define NXP_DCSR_ADDR 0x700000000 +#define NXP_DCSR_SIZE 0x40000000 + +/* Flex-SPI controller address */ +#define NXP_FLEXSPI_ADDR 0x020C0000 +/* Flex-SPI Flash Start address */ +#define NXP_FLEXSPI_FLASH_ADDR 0x20000000 + +/* MMU 500 soc.c*/ +#define NXP_SMMU_ADDR 0x05000000 + +/* CCI400 base address */ +#define NXP_CCI_ADDR 0x04090000 + +#define NXP_SNVS_ADDR 0x01E90000 + +#define NXP_DCFG_ADDR 0x01E00000 +#define NXP_PMU_CCSR_ADDR 0x01E30000 +#define NXP_PMU_DCSR_ADDR 0x700123000 +#define NXP_PMU_ADDR NXP_PMU_CCSR_ADDR +#define NXP_SFP_ADDR 0x01E80000 +#define NXP_SCFG_ADDR 0x01FC0000 +#define NXP_I2C_ADDR 0x02000000 +#define NXP_ESDHC_ADDR 0x02140000 +#define NXP_ESDHC2_ADDR 0x02150000 +#define NXP_UART_ADDR 0x021C0000 +#define NXP_UART1_ADDR 0x021D0000 + +#define NXP_GPIO1_ADDR 0x02300000 +#define NXP_GPIO2_ADDR 0x02310000 +#define NXP_GPIO3_ADDR 0x02320000 +#define NXP_GPIO4_ADDR 0x02330000 + +#define NXP_WDOG1_NS_ADDR 0x02390000 +#define NXP_WDOG2_NS_ADDR 0x023A0000 +#define NXP_WDOG1_TZ_ADDR 0x023B0000 +#define NXP_WDOG2_TZ_ADDR 0x023C0000 + +#define NXP_TIMER_STATUS_ADDR 0x023F0000 + +#define NXP_GICD_ADDR 0x06000000 +#define NXP_GICR_ADDR 0x06200000 +#define NXP_GICR_SGI_ADDR 0x06210000 + +#define NXP_CAAM_ADDR 0x08000000 + +#define NXP_TZC_ADDR 0x01100000 +#define NXP_TZC2_ADDR 0x01110000 +#define NXP_TZC3_ADDR 0x01120000 + +#define NXP_TIMER_ADDR 0x023E0000 + +#define NXP_RESET_ADDR 0x01E60000 +#define NXP_SEC_REGFILE_ADDR 0x01E88000 +#define NXP_RST_ADDR 0x01E88000 + +#define TPMWAKEMR0_ADDR 0x700123c50 +#define TZPC_BLOCK_SIZE 0x1000 + +#define NXP_TZC_ADDR 0x01100000 +#define NXP_TZC2_ADDR 0x01110000 +#define NXP_TZC3_ADDR 0x01120000 +#define NXP_TZC4_ADDR 0x01130000 +#define NXP_DDR_ADDR 0x01080000 +#define NXP_DDR2_ADDR 0x01090000 + +#define NXP_OCRAM_TZPC_ADDR 0x02200000 + +#define NXP_CCN_ADDR 0x04000000 +#define NXP_CCN_HNI_ADDR 0x04080000 +#define NXP_CCN_HN_F_0_ADDR 0x04200000 + +#define NXP_EPU_ADDR 0x700060000 +#endif /* SOC_DEFAULT_BASE_ADDR_H */ diff --git a/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h b/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h new file mode 100644 index 0000000..1edd28d --- /dev/null +++ b/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h @@ -0,0 +1,87 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SOC_DEFAULT_HELPER_MACROS_H +#define SOC_DEFAULT_HELPER_MACROS_H + +#ifdef NXP_OCRAM_TZPC_ADDR + +/* 0x1: means 4 KB + * 0x2: means 8 KB + */ +#define TZPC_BLOCK_SIZE 0x1000 +#endif + +/* DDR controller offsets and defines */ +#ifdef NXP_DDR_ADDR + +#define DDR_CFG_2_OFFSET 0x114 +#define CFG_2_FORCE_REFRESH 0x80000000 + +#endif /* NXP_DDR_ADDR */ + + /* Reset block register offsets */ +#ifdef NXP_RESET_ADDR + +/* Register Offset */ +#define RST_RSTCR_OFFSET 0x0 +#define RST_RSTRQMR1_OFFSET 0x10 +#define RST_RSTRQSR1_OFFSET 0x18 +#define BRR_OFFSET 0x60 + +/* helper macros */ +#define RSTRQSR1_SWRR 0x800 +#define RSTRQMR_RPTOE_MASK (1 << 19) + +#endif /* NXP_RESET_ADDR */ + +/* secmon register offsets and bitfields */ +#define SECMON_HPCOMR_OFFSET 0x4 +#define SECMON_HPCOMR_NPSWAEN 0x80000000 + +/* Secure-Register-File register offsets and bit masks */ +#ifdef NXP_RST_ADDR +/* Register Offset */ +#define CORE_HOLD_OFFSET 0x140 +#define RSTCNTL_OFFSET 0x180 + +/* Helper macros */ +#define SW_RST_REQ_INIT 0x1 +#endif + +#ifdef NXP_CCN_ADDR +#define NXP_CCN_HN_F_1_ADDR 0x04210000 + +#define CCN_HN_F_SAM_NODEID_MASK 0x7f +#define CCN_HN_F_SNP_DMN_CTL_OFFSET 0x200 +#define CCN_HN_F_SNP_DMN_CTL_SET_OFFSET 0x210 +#define CCN_HN_F_SNP_DMN_CTL_CLR_OFFSET 0x220 +#define CCN_HN_F_SNP_DMN_CTL_MASK 0x80a00 +#define CCN_HNF_NODE_COUNT 8 +#define CCN_HNF_OFFSET 0x10000 + +#define SA_AUX_CTRL_REG_OFFSET 0x500 +#define NUM_HNI_NODE 2 +#define CCN_HNI_MEMORY_MAP_SIZE 0x10000 + +#define PCIeRC_RN_I_NODE_ID_OFFSET 0x8 +#define PoS_CONTROL_REG_OFFSET 0x0 +#define POS_EARLY_WR_COMP_EN 0x20 +#define HNI_POS_EN 0x01 +#define POS_TERMINATE_BARRIERS 0x10 +#define SERIALIZE_DEV_nGnRnE_WRITES 0x200 +#define ENABLE_ERR_SIGNAL_TO_MN 0x4 +#define ENABLE_RESERVE_BIT53 0x400 +#define ENABLE_WUO 0x10 +#endif /* NXP_CCN_ADDR */ + +#define DCFG_SBEESR2_ADDR 0x00100534 +#define DCFG_MBEESR2_ADDR 0x00100544 +/* SBEESR and MBEESR bit mask */ +#define OCRAM_EESR_MASK 0x00000008 + +#endif /* SOC_DEFAULT_HELPER_MACROS_H */ diff --git a/plat/nxp/common/include/default/plat_default_def.h b/plat/nxp/common/include/default/plat_default_def.h new file mode 100644 index 0000000..43320bb --- /dev/null +++ b/plat/nxp/common/include/default/plat_default_def.h @@ -0,0 +1,172 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_DEFAULT_DEF_H +#define PLAT_DEFAULT_DEF_H + +/* + * Platform binary types for linking + */ +#ifdef __aarch64__ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 +#else +#define PLATFORM_LINKER_FORMAT "elf32-littlearm" +#define PLATFORM_LINKER_ARCH arm +#endif /* __aarch64__ */ + +#define LS_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +/* NXP Platforms have DRAM divided into banks. + * DRAM0 Bank: Maximum size of this bank is fixed to 2GB + * DRAM1 Bank: Greater than 2GB belongs to bank1 and size of bank1 varies from + * one platform to other platform. + * DRAMn Bank: + * + * Except a few, all the platforms have 2GB size as DRAM0 BANK. + * Hence common for all the platforms. + * For platforms where DRAM0 Size is < 2GB, it is defined in platform_def.h + */ +#ifndef PLAT_DEF_DRAM0_SIZE +#define PLAT_DEF_DRAM0_SIZE 0x80000000 /* 2G */ +#endif + +/* This is common for all platforms where: */ +#ifndef NXP_NS_DRAM_ADDR +#define NXP_NS_DRAM_ADDR NXP_DRAM0_ADDR +#endif + +/* 1 MB is reserved for dma of sd */ +#ifndef NXP_SD_BLOCK_BUF_SIZE +#define NXP_SD_BLOCK_BUF_SIZE (1 * 1024 * 1024) +#endif + +/* 64MB is reserved for Secure memory */ +#ifndef NXP_SECURE_DRAM_SIZE +#define NXP_SECURE_DRAM_SIZE (64 * 1024 * 1024) +#endif + +/* 2M Secure EL1 Payload Shared Memory */ +#ifndef NXP_SP_SHRD_DRAM_SIZE +#define NXP_SP_SHRD_DRAM_SIZE (2 * 1024 * 1024) +#endif + +#ifndef NXP_NS_DRAM_SIZE +/* Non secure memory */ +#define NXP_NS_DRAM_SIZE (PLAT_DEF_DRAM0_SIZE - \ + (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE)) +#endif + +#ifndef NXP_SD_BLOCK_BUF_ADDR +#define NXP_SD_BLOCK_BUF_ADDR (NXP_NS_DRAM_ADDR) +#endif + +#ifndef NXP_SECURE_DRAM_ADDR +#ifdef TEST_BL31 +#define NXP_SECURE_DRAM_ADDR 0 +#else +#define NXP_SECURE_DRAM_ADDR (NXP_NS_DRAM_ADDR + PLAT_DEF_DRAM0_SIZE - \ + (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE)) +#endif +#endif + +#ifndef NXP_SP_SHRD_DRAM_ADDR +#define NXP_SP_SHRD_DRAM_ADDR (NXP_NS_DRAM_ADDR + PLAT_DEF_DRAM0_SIZE - \ + NXP_SP_SHRD_DRAM_SIZE) +#endif + +#ifndef BL31_BASE +/* 2 MB reserved in secure memory for DDR */ +#define BL31_BASE NXP_SECURE_DRAM_ADDR +#endif + +#ifndef BL31_SIZE +#define BL31_SIZE (0x200000) +#endif + +#ifndef BL31_LIMIT +#define BL31_LIMIT (BL31_BASE + BL31_SIZE) +#endif + +/* Put BL32 in secure memory */ +#ifndef BL32_BASE +#define BL32_BASE (NXP_SECURE_DRAM_ADDR + BL31_SIZE) +#endif + +#ifndef BL32_LIMIT +#define BL32_LIMIT (NXP_SECURE_DRAM_ADDR + \ + NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE) +#endif + +/* BL33 memory region */ +/* Hardcoded based on current address in u-boot */ +#ifndef BL33_BASE +#define BL33_BASE 0x82000000 +#endif + +#ifndef BL33_LIMIT +#define BL33_LIMIT (NXP_NS_DRAM_ADDR + NXP_NS_DRAM_SIZE) +#endif + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#ifndef FUSE_BUF +#define FUSE_BUF ULL(0x81000000) +#endif + +#ifndef FUSE_SZ +#define FUSE_SZ 0x80000 +#endif +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 2 +#endif + +#ifndef PLAT_FIP_OFFSET +#define PLAT_FIP_OFFSET 0x100000 +#endif + +#ifndef PLAT_FIP_MAX_SIZE +#define PLAT_FIP_MAX_SIZE 0x400000 +#endif + +/* Check if this size can be determined from array size */ +#if defined(IMAGE_BL2) +#ifndef MAX_MMAP_REGIONS +#define MAX_MMAP_REGIONS 8 +#endif +#ifndef MAX_XLAT_TABLES +#define MAX_XLAT_TABLES 6 +#endif +#elif defined(IMAGE_BL31) +#ifndef MAX_MMAP_REGIONS +#define MAX_MMAP_REGIONS 9 +#endif +#ifndef MAX_XLAT_TABLES +#define MAX_XLAT_TABLES 9 +#endif +#elif defined(IMAGE_BL32) +#ifndef MAX_MMAP_REGIONS +#define MAX_MMAP_REGIONS 8 +#endif +#ifndef MAX_XLAT_TABLES +#define MAX_XLAT_TABLES 9 +#endif +#endif + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#ifndef BL32_IRQ_SEC_PHY_TIMER +#define BL32_IRQ_SEC_PHY_TIMER 29 +#endif + +#endif /* PLAT_DEFAULT_DEF_H */ diff --git a/plat/nxp/common/nv_storage/nv_storage.mk b/plat/nxp/common/nv_storage/nv_storage.mk new file mode 100644 index 0000000..dddba5f --- /dev/null +++ b/plat/nxp/common/nv_storage/nv_storage.mk @@ -0,0 +1,29 @@ +# +# Copyright 2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# NXP Non-Volatile data flag storage used and then cleared by SW on boot-up + +$(eval $(call add_define,NXP_NV_SW_MAINT_LAST_EXEC_DATA)) + +ifeq ($(NXP_COINED_BB),yes) +$(eval $(call add_define,NXP_COINED_BB)) +# BL2 : To read the reset cause from LP SECMON GPR register +# BL31: To write the reset cause to LP SECMON GPR register +$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL_COMM)) + +# BL2: DDR training data is stored on Flexspi NOR. +ifneq (${BOOT_MODE},flexspi_nor) +$(eval $(call SET_NXP_MAKE_FLAG,XSPI_NEEDED,BL2)) +endif + +else +$(eval $(call add_define_val,DEFAULT_NV_STORAGE_BASE_ADDR,'${BL2_BIN_XSPI_NOR_END_ADDRESS} - 2 * ${NXP_XSPI_NOR_UNIT_SIZE}')) +$(eval $(call SET_NXP_MAKE_FLAG,XSPI_NEEDED,BL_COMM)) +endif + +NV_STORAGE_INCLUDES += -I${PLAT_COMMON_PATH}/nv_storage + +NV_STORAGE_SOURCES += ${PLAT_COMMON_PATH}/nv_storage/plat_nv_storage.c diff --git a/plat/nxp/common/nv_storage/plat_nv_storage.c b/plat/nxp/common/nv_storage/plat_nv_storage.c new file mode 100644 index 0000000..af3b966 --- /dev/null +++ b/plat/nxp/common/nv_storage/plat_nv_storage.c @@ -0,0 +1,121 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <assert.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <platform_def.h> +#include <common/debug.h> +#ifndef NXP_COINED_BB +#include <flash_info.h> +#include <fspi.h> +#include <fspi_api.h> +#endif +#include <lib/mmio.h> +#ifdef NXP_COINED_BB +#include <snvs.h> +#else +#include <xspi_error_codes.h> +#endif + +#include <plat_nv_storage.h> + +/*This structure will be a static structure and + * will be populated as first step of BL2 booting-up. + * fspi_strorage.c . To be located in the fspi driver folder. + */ + +static nv_app_data_t nv_app_data; + +int read_nv_app_data(void) +{ + int ret = 0; + +#ifdef NXP_COINED_BB + uint8_t *nv_app_data_array = (uint8_t *) &nv_app_data; + uint8_t offset = 0U; + + ret = snvs_read_app_data(); + do { + nv_app_data_array[offset] = snvs_read_app_data_bit(offset); + offset++; + + } while (offset < APP_DATA_MAX_OFFSET); + snvs_clear_app_data(); +#else + uintptr_t nv_base_addr = NV_STORAGE_BASE_ADDR; + + ret = fspi_init(NXP_FLEXSPI_ADDR, NXP_FLEXSPI_FLASH_ADDR); + + if (ret != XSPI_SUCCESS) { + ERROR("Failed to initialized driver flexspi-nor.\n"); + ERROR("exiting warm-reset request.\n"); + return -ENODEV; + } + + xspi_read(nv_base_addr, + (uint32_t *)&nv_app_data, sizeof(nv_app_data_t)); + xspi_sector_erase((uint32_t) nv_base_addr, + F_SECTOR_ERASE_SZ); +#endif + return ret; +} + +int wr_nv_app_data(int data_offset, + uint8_t *data, + int data_size) +{ + int ret = 0; +#ifdef NXP_COINED_BB +#if !TRUSTED_BOARD_BOOT + snvs_disable_zeroize_lp_gpr(); +#endif + /* In case LP SecMon General purpose register, + * only 1 bit flags can be saved. + */ + if ((data_size > 1) || (*data != DEFAULT_SET_VALUE)) { + ERROR("Only binary value is allowed to be written.\n"); + ERROR("Use flash instead of SNVS GPR as NV location.\n"); + return -ENODEV; + } + snvs_write_app_data_bit(data_offset); +#else + uint8_t read_val[sizeof(nv_app_data_t)]; + uint8_t ready_to_write_val[sizeof(nv_app_data_t)]; + uintptr_t nv_base_addr = NV_STORAGE_BASE_ADDR; + + assert((nv_base_addr + data_offset + data_size) > (nv_base_addr + F_SECTOR_ERASE_SZ)); + + ret = fspi_init(NXP_FLEXSPI_ADDR, NXP_FLEXSPI_FLASH_ADDR); + + if (ret != XSPI_SUCCESS) { + ERROR("Failed to initialized driver flexspi-nor.\n"); + ERROR("exiting warm-reset request.\n"); + return -ENODEV; + } + + ret = xspi_read(nv_base_addr + data_offset, (uint32_t *)read_val, data_size); + + memset(ready_to_write_val, READY_TO_WRITE_VALUE, ARRAY_SIZE(ready_to_write_val)); + + if (memcmp(read_val, ready_to_write_val, data_size) == 0) { + xspi_write(nv_base_addr + data_offset, data, data_size); + } +#endif + + return ret; +} + +const nv_app_data_t *get_nv_data(void) +{ + return (const nv_app_data_t *) &nv_app_data; +} diff --git a/plat/nxp/common/nv_storage/plat_nv_storage.h b/plat/nxp/common/nv_storage/plat_nv_storage.h new file mode 100644 index 0000000..1f5264a --- /dev/null +++ b/plat/nxp/common/nv_storage/plat_nv_storage.h @@ -0,0 +1,40 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_NV_STRG_H +#define PLAT_NV_STRG_H + +#define DEFAULT_SET_VALUE 0xA1 +#define READY_TO_WRITE_VALUE 0xFF + +#ifndef NV_STORAGE_BASE_ADDR +#define NV_STORAGE_BASE_ADDR DEFAULT_NV_STORAGE_BASE_ADDR +#endif + +typedef struct { +uint8_t warm_rst_flag; +uint8_t wdt_rst_flag; +uint8_t dummy[2]; +} nv_app_data_t; + + +/*below enum and above structure should be in-sync. */ +enum app_data_offset { + WARM_RESET_FLAG_OFFSET, + WDT_RESET_FLAG_OFFSET, + APP_DATA_MAX_OFFSET, +}; + +int read_nv_app_data(void); + +int wr_nv_app_data(int data_offset, + uint8_t *data, + int data_size); + +const nv_app_data_t *get_nv_data(void); + +#endif /* PLAT_NV_STRG_H */ diff --git a/plat/nxp/common/ocram/aarch64/ocram.S b/plat/nxp/common/ocram/aarch64/ocram.S new file mode 100644 index 0000000..ec53341 --- /dev/null +++ b/plat/nxp/common/ocram/aarch64/ocram.S @@ -0,0 +1,71 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <asm_macros.S> + +#include <soc_default_base_addr.h> +#include <soc_default_helper_macros.h> + +.global ocram_init + +/* + * void ocram_init(uintptr_t start_addr, size_t size) + * + * This function will do OCRAM ECC. + * OCRAM is initialized with 64-bit writes and then a write + * performed to address 0x0010_0534 with the value 0x0000_0008. + * + * x0: start_addr + * x1: size in bytes + * Called from C + */ + +func ocram_init + /* save the aarch32/64 non-volatile registers */ + 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]! + + /* convert bytes to 64-byte chunks */ + lsr x1, x1, #6 +1: + /* for each location, read and write-back */ + dc ivac, x0 + dsb sy + ldp x4, x5, [x0] + ldp x6, x7, [x0, #16] + ldp x8, x9, [x0, #32] + ldp x10, x11, [x0, #48] + stp x4, x5, [x0] + stp x6, x7, [x0, #16] + stp x8, x9, [x0, #32] + stp x10, x11, [x0, #48] + dc cvac, x0 + + sub x1, x1, #1 + cbz x1, 2f + add x0, x0, #64 + b 1b +2: + /* Clear OCRAM ECC status bit in SBEESR2 and MBEESR2 */ + ldr w1, =OCRAM_EESR_MASK + ldr x0, =DCFG_SBEESR2_ADDR + str w1, [x0] + ldr x0, =DCFG_MBEESR2_ADDR + str w1, [x0] + + /* 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 ocram_init diff --git a/plat/nxp/common/ocram/ocram.h b/plat/nxp/common/ocram/ocram.h new file mode 100644 index 0000000..479de61 --- /dev/null +++ b/plat/nxp/common/ocram/ocram.h @@ -0,0 +1,13 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef OCRAM_H +#define OCRAM_H + +void ocram_init(uintptr_t start_addr, size_t size); + +#endif /* OCRAM_H */ diff --git a/plat/nxp/common/ocram/ocram.mk b/plat/nxp/common/ocram/ocram.mk new file mode 100644 index 0000000..c77bd4a --- /dev/null +++ b/plat/nxp/common/ocram/ocram.mk @@ -0,0 +1,14 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +PLAT_OCRAM_PATH := $(PLAT_COMMON_PATH)/ocram + +OCRAM_SOURCES := ${PLAT_OCRAM_PATH}/$(ARCH)/ocram.S + +BL2_SOURCES += ${OCRAM_SOURCES} + +PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/ocram diff --git a/plat/nxp/common/plat_make_helper/plat_build_macros.mk b/plat/nxp/common/plat_make_helper/plat_build_macros.mk new file mode 100644 index 0000000..bba5e36 --- /dev/null +++ b/plat/nxp/common/plat_make_helper/plat_build_macros.mk @@ -0,0 +1,11 @@ +# +# Copyright (c) 2020, NXP. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +define SET_NXP_MAKE_FLAG +$1 := yes +$2_$1 := yes +endef diff --git a/plat/nxp/common/plat_make_helper/plat_common_def.mk b/plat/nxp/common/plat_make_helper/plat_common_def.mk new file mode 100644 index 0000000..86dacf8 --- /dev/null +++ b/plat/nxp/common/plat_make_helper/plat_common_def.mk @@ -0,0 +1,103 @@ +# Copyright 2020-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Include build macros, for example: SET_NXP_MAKE_FLAG +include plat/nxp/common/plat_make_helper/plat_build_macros.mk + +# Adding platform specific defines + +$(eval $(call add_define_val,BOARD,'"${BOARD}"')) + +ifeq (${POVDD_ENABLE},yes) +$(eval $(call add_define,CONFIG_POVDD_ENABLE)) +endif + +ifneq (${FLASH_TYPE},) +$(eval $(call add_define,CONFIG_${FLASH_TYPE})) +endif + +ifneq (${XSPI_FLASH_SZ},) +$(eval $(call add_define_val,NXP_FLEXSPI_FLASH_SIZE,${XSPI_FLASH_SZ})) +endif + +ifneq (${QSPI_FLASH_SZ},) +$(eval $(call add_define_val,NXP_QSPI_FLASH_SIZE,${QSPI_FLASH_SZ})) +endif + +ifneq (${NOR_FLASH_SZ},) +$(eval $(call add_define_val,NXP_NOR_FLASH_SIZE,${NOR_FLASH_SZ})) +endif + + +ifneq (${FSPI_ERASE_4K},) +$(eval $(call add_define_val,CONFIG_FSPI_ERASE_4K,${FSPI_ERASE_4K})) +endif + +ifneq (${NUM_OF_DDRC},) +$(eval $(call add_define_val,NUM_OF_DDRC,${NUM_OF_DDRC})) +endif + +ifeq (${CONFIG_DDR_NODIMM},1) +$(eval $(call add_define,CONFIG_DDR_NODIMM)) +DDRC_NUM_DIMM := 1 +endif + +ifneq (${DDRC_NUM_DIMM},) +$(eval $(call add_define_val,DDRC_NUM_DIMM,${DDRC_NUM_DIMM})) +endif + +ifneq (${DDRC_NUM_CS},) +$(eval $(call add_define_val,DDRC_NUM_CS,${DDRC_NUM_CS})) +endif + +ifeq (${DDR_ADDR_DEC},yes) +$(eval $(call add_define,CONFIG_DDR_ADDR_DEC)) +endif + +ifeq (${DDR_ECC_EN},yes) +$(eval $(call add_define,CONFIG_DDR_ECC_EN)) +endif + +ifeq (${CONFIG_STATIC_DDR},1) +$(eval $(call add_define,CONFIG_STATIC_DDR)) +endif + +# Platform can control the base address for non-volatile storage. +#$(eval $(call add_define_val,NV_STORAGE_BASE_ADDR,'${BL2_BIN_XSPI_NOR_END_ADDRESS} - 2 * ${NXP_XSPI_NOR_UNIT_SIZE}')) + +ifeq (${WARM_BOOT},yes) +$(eval $(call add_define_val,PHY_TRAINING_REGS_ON_FLASH,'${BL2_BIN_XSPI_NOR_END_ADDRESS} - ${NXP_XSPI_NOR_UNIT_SIZE}')) +endif + +# Selecting Boot Source for the TFA images. +define add_boot_mode_define + ifeq ($(1),qspi) + $$(eval $$(call SET_NXP_MAKE_FLAG,QSPI_NEEDED,BL2)) + $$(eval $$(call add_define,QSPI_BOOT)) + else ifeq ($(1),sd) + $$(eval $$(call SET_NXP_MAKE_FLAG,SD_MMC_NEEDED,BL2)) + $$(eval $$(call add_define,SD_BOOT)) + else ifeq ($(1),emmc) + $$(eval $$(call SET_NXP_MAKE_FLAG,SD_MMC_NEEDED,BL2)) + $$(eval $$(call add_define,EMMC_BOOT)) + else ifeq ($(1),nor) + $$(eval $$(call SET_NXP_MAKE_FLAG,IFC_NOR_NEEDED,BL2)) + $$(eval $$(call add_define,NOR_BOOT)) + else ifeq ($(1),nand) + $$(eval $$(call SET_NXP_MAKE_FLAG,IFC_NAND_NEEDED,BL2)) + $$(eval $$(call add_define,NAND_BOOT)) + else ifeq ($(1),flexspi_nor) + $$(eval $$(call SET_NXP_MAKE_FLAG,XSPI_NEEDED,BL2)) + $$(eval $$(call add_define,FLEXSPI_NOR_BOOT)) + else + $$(error $(PLAT) Cannot Support Boot Mode: $(BOOT_MODE)) + endif +endef + +ifneq (,$(findstring $(BOOT_MODE),$(SUPPORTED_BOOT_MODE))) + $(eval $(call add_boot_mode_define,$(strip $(BOOT_MODE)))) +else + $(error $(PLAT) Un-supported Boot Mode = $(BOOT_MODE)) +endif diff --git a/plat/nxp/common/plat_make_helper/soc_common_def.mk b/plat/nxp/common/plat_make_helper/soc_common_def.mk new file mode 100644 index 0000000..52f2867 --- /dev/null +++ b/plat/nxp/common/plat_make_helper/soc_common_def.mk @@ -0,0 +1,117 @@ +# Copyright 2020-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Adding SoC specific defines + +ifneq (${CACHE_LINE},) +$(eval $(call add_define_val,PLATFORM_CACHE_LINE_SHIFT,${CACHE_LINE})) +$(eval CACHE_WRITEBACK_GRANULE=$(shell echo $$((1 << $(CACHE_LINE))))) +$(eval $(call add_define_val,CACHE_WRITEBACK_GRANULE,$(CACHE_WRITEBACK_GRANULE))) +endif + +ifneq (${INTERCONNECT},) +$(eval $(call add_define,NXP_HAS_${INTERCONNECT})) +ifeq (${INTERCONNECT}, CCI400) +ICNNCT_ID := 0x420 +$(eval $(call add_define,ICNNCT_ID)) +endif +endif + +ifneq (${CHASSIS},) +$(eval $(call add_define,CONFIG_CHASSIS_${CHASSIS})) +endif + +ifneq (${PLAT_DDR_PHY},) +$(eval $(call add_define,NXP_DDR_${PLAT_DDR_PHY})) +endif + +ifneq (${PHYS_SYS},) +$(eval $(call add_define,CONFIG_PHYS_64BIT)) +endif + +ifneq (${CSF_HDR_SZ},) +$(eval $(call add_define_val,CSF_HDR_SZ,${CSF_HDR_SZ})) +endif + +ifneq (${OCRAM_START_ADDR},) +$(eval $(call add_define_val,NXP_OCRAM_ADDR,${OCRAM_START_ADDR})) +endif + +ifneq (${OCRAM_SIZE},) +$(eval $(call add_define_val,NXP_OCRAM_SIZE,${OCRAM_SIZE})) +endif + +ifneq (${NXP_ROM_RSVD},) +$(eval $(call add_define_val,NXP_ROM_RSVD,${NXP_ROM_RSVD})) +endif + +ifneq (${BL2_BASE},) +$(eval $(call add_define_val,BL2_BASE,${BL2_BASE})) +endif + +ifeq (${SEC_MEM_NON_COHERENT},yes) +$(eval $(call add_define,SEC_MEM_NON_COHERENT)) +endif + +ifneq (${NXP_ESDHC_ENDIANNESS},) +$(eval $(call add_define,NXP_ESDHC_${NXP_ESDHC_ENDIANNESS})) +endif + +ifneq (${NXP_SFP_VER},) +$(eval $(call add_define,NXP_SFP_VER_${NXP_SFP_VER})) +endif + +ifneq (${NXP_SFP_ENDIANNESS},) +$(eval $(call add_define,NXP_SFP_${NXP_SFP_ENDIANNESS})) +endif + +ifneq (${NXP_GPIO_ENDIANNESS},) +$(eval $(call add_define,NXP_GPIO_${NXP_GPIO_ENDIANNESS})) +endif + +ifneq (${NXP_SNVS_ENDIANNESS},) +$(eval $(call add_define,NXP_SNVS_${NXP_SNVS_ENDIANNESS})) +endif + +ifneq (${NXP_GUR_ENDIANNESS},) +$(eval $(call add_define,NXP_GUR_${NXP_GUR_ENDIANNESS})) +endif + +ifneq (${NXP_FSPI_ENDIANNESS},) +$(eval $(call add_define,NXP_FSPI_${NXP_FSPI_ENDIANNESS})) +endif + +ifneq (${NXP_SEC_ENDIANNESS},) +$(eval $(call add_define,NXP_SEC_${NXP_SEC_ENDIANNESS})) +endif + +ifneq (${NXP_DDR_ENDIANNESS},) +$(eval $(call add_define,NXP_DDR_${NXP_DDR_ENDIANNESS})) +endif + +ifneq (${NXP_QSPI_ENDIANNESS},) +$(eval $(call add_define,NXP_QSPI_${NXP_QSPI_ENDIANNESS})) +endif + +ifneq (${NXP_SCFG_ENDIANNESS},) +$(eval $(call add_define,NXP_SCFG_${NXP_SCFG_ENDIANNESS})) +endif + +ifneq (${NXP_IFC_ENDIANNESS},) +$(eval $(call add_define,NXP_IFC_${NXP_IFC_ENDIANNESS})) +endif + +ifneq (${NXP_DDR_INTLV_256B},) +$(eval $(call add_define,NXP_DDR_INTLV_256B)) +endif + +ifneq (${PLAT_XLAT_TABLES_DYNAMIC},) +$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC)) +endif + +ifeq (${OCRAM_ECC_EN},yes) +$(eval $(call add_define,CONFIG_OCRAM_ECC_EN)) +include ${PLAT_COMMON_PATH}/ocram/ocram.mk +endif diff --git a/plat/nxp/common/psci/aarch64/psci_utils.S b/plat/nxp/common/psci/aarch64/psci_utils.S new file mode 100644 index 0000000..ec69aea --- /dev/null +++ b/plat/nxp/common/psci/aarch64/psci_utils.S @@ -0,0 +1,1155 @@ + +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <asm_macros.S> +#include <assert_macros.S> + +#include <lib/psci/psci.h> + +#include <bl31_data.h> +#include <plat_psci.h> + + +#define RESET_RETRY_CNT 800 +#define PSCI_ABORT_CNT 100 + +#if (SOC_CORE_RELEASE) + +.global _psci_cpu_on + +/* + * int _psci_cpu_on(u_register_t core_mask) + * x0 = target cpu core mask + * + * Called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + * + */ + +func _psci_cpu_on + 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 x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x6, x0 + + /* x0 = core mask (lsb) + * x6 = core mask (lsb) + */ + + /* check if core disabled */ + bl _soc_ck_disabled /* 0-2 */ + cbnz w0, psci_disabled + + /* check core data area to see if core cannot be turned on + * read the core state + */ + mov x0, x6 + bl _getCoreState /* 0-5 */ + mov x9, x0 + + /* x6 = core mask (lsb) + * x9 = core state (from data area) + */ + + cmp x9, #CORE_DISABLED + mov x0, #PSCI_E_DISABLED + b.eq cpu_on_done + + cmp x9, #CORE_PENDING + mov x0, #PSCI_E_ON_PENDING + b.eq cpu_on_done + + cmp x9, #CORE_RELEASED + mov x0, #PSCI_E_ALREADY_ON + b.eq cpu_on_done + +8: + /* x6 = core mask (lsb) + * x9 = core state (from data area) + */ + + cmp x9, #CORE_WFE + b.eq core_in_wfe + cmp x9, #CORE_IN_RESET + b.eq core_in_reset + cmp x9, #CORE_OFF + b.eq core_is_off + cmp x9, #CORE_OFF_PENDING + + /* if state == CORE_OFF_PENDING, set abort */ + mov x0, x6 + mov x1, #ABORT_FLAG_DATA + mov x2, #CORE_ABORT_OP + bl _setCoreData /* 0-3, [13-15] */ + + ldr x3, =PSCI_ABORT_CNT +7: + /* watch for abort to take effect */ + mov x0, x6 + bl _getCoreState /* 0-5 */ + cmp x0, #CORE_OFF + b.eq core_is_off + cmp x0, #CORE_PENDING + mov x0, #PSCI_E_SUCCESS + b.eq cpu_on_done + + /* loop til finished */ + sub x3, x3, #1 + cbnz x3, 7b + + /* if we didn't see either CORE_OFF or CORE_PENDING, then this + * core is in CORE_OFF_PENDING - exit with success, as the core will + * respond to the abort request + */ + mov x0, #PSCI_E_SUCCESS + b cpu_on_done + +/* this is where we start up a core out of reset */ +core_in_reset: + /* see if the soc-specific module supports this op */ + ldr x7, =SOC_CORE_RELEASE + cbnz x7, 3f + + mov x0, #PSCI_E_NOT_SUPPORTED + b cpu_on_done + + /* x6 = core mask (lsb) */ +3: + /* set core state in data area */ + mov x0, x6 + mov x1, #CORE_PENDING + bl _setCoreState /* 0-3, [13-15] */ + + /* release the core from reset */ + mov x0, x6 + bl _soc_core_release /* 0-3 */ + mov x0, #PSCI_E_SUCCESS + b cpu_on_done + + /* Start up the core that has been powered-down via CPU_OFF + */ +core_is_off: + /* see if the soc-specific module supports this op + */ + ldr x7, =SOC_CORE_RESTART + cbnz x7, 2f + + mov x0, #PSCI_E_NOT_SUPPORTED + b cpu_on_done + + /* x6 = core mask (lsb) */ +2: + /* set core state in data area */ + mov x0, x6 + mov x1, #CORE_WAKEUP + bl _setCoreState /* 0-3, [13-15] */ + + /* put the core back into service */ + mov x0, x6 +#if (SOC_CORE_RESTART) + bl _soc_core_restart /* 0-5 */ +#endif + mov x0, #PSCI_E_SUCCESS + b cpu_on_done + +/* this is where we release a core that is being held in wfe */ +core_in_wfe: + /* x6 = core mask (lsb) */ + + /* set core state in data area */ + mov x0, x6 + mov x1, #CORE_PENDING + bl _setCoreState /* 0-3, [13-15] */ + dsb sy + isb + + /* put the core back into service */ + sev + sev + isb + mov x0, #PSCI_E_SUCCESS + +cpu_on_done: + /* restore the aarch32/64 non-volatile registers */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [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 + b psci_completed +endfunc _psci_cpu_on + +#endif + + +#if (SOC_CORE_OFF) + +.global _psci_cpu_prep_off +.global _psci_cpu_off_wfi + +/* + * void _psci_cpu_prep_off(u_register_t core_mask) + * this function performs the SoC-specific programming prior + * to shutting the core down + * x0 = core_mask + * + * called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + +func _psci_cpu_prep_off + + 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 x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x10, x0 /* x10 = core_mask */ + + /* the core does not return from cpu_off, so no need + * to save/restore non-volatile registers + */ + + /* mask interrupts by setting DAIF[7:4] to 'b1111 */ + msr DAIFSet, #0xF + + /* read cpuectlr and save current value */ + mrs x4, CPUECTLR_EL1 + mov x1, #CPUECTLR_DATA + mov x2, x4 + mov x0, x10 + bl _setCoreData + + /* remove the core from coherency */ + bic x4, x4, #CPUECTLR_SMPEN_MASK + msr CPUECTLR_EL1, x4 + + /* save scr_el3 */ + mov x0, x10 + mrs x4, SCR_EL3 + mov x2, x4 + mov x1, #SCR_EL3_DATA + bl _setCoreData + + /* x4 = scr_el3 */ + + /* secure SGI (FIQ) taken to EL3, set SCR_EL3[FIQ] */ + orr x4, x4, #SCR_FIQ_MASK + msr scr_el3, x4 + + /* x10 = core_mask */ + + /* prep the core for shutdown */ + mov x0, x10 + bl _soc_core_prep_off + + /* restore the aarch32/64 non-volatile registers */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [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 + b psci_completed +endfunc _psci_cpu_prep_off + +/* + * void _psci_cpu_off_wfi(u_register_t core_mask, u_register_t resume_addr) + * - this function shuts down the core + * - this function does not return!! + */ + +func _psci_cpu_off_wfi + /* save the wakeup address */ + mov x29, x1 + + /* x0 = core_mask */ + + /* shutdown the core */ + bl _soc_core_entr_off + + /* branch to resume execution */ + br x29 +endfunc _psci_cpu_off_wfi + +#endif + + +#if (SOC_CORE_RESTART) + +.global _psci_wakeup + +/* + * void _psci_wakeup(u_register_t core_mask) + * this function performs the SoC-specific programming + * after a core wakes up from OFF + * x0 = core mask + * + * called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + +func _psci_wakeup + + 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 x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x4, x0 /* x4 = core mask */ + + /* restore scr_el3 */ + mov x0, x4 + mov x1, #SCR_EL3_DATA + bl _getCoreData + /* x0 = saved scr_el3 */ + msr SCR_EL3, x0 + + /* x4 = core mask */ + + /* restore CPUECTLR */ + mov x0, x4 + mov x1, #CPUECTLR_DATA + bl _getCoreData + orr x0, x0, #CPUECTLR_SMPEN_MASK + msr CPUECTLR_EL1, x0 + + /* x4 = core mask */ + + /* start the core back up */ + mov x0, x4 + bl _soc_core_exit_off + + /* restore the aarch32/64 non-volatile registers + */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [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 + b psci_completed +endfunc _psci_wakeup + +#endif + + +#if (SOC_SYSTEM_RESET) + +.global _psci_system_reset + +func _psci_system_reset + + /* system reset is mandatory + * system reset is soc-specific + * Note: under no circumstances do we return from this call + */ + bl _soc_sys_reset +endfunc _psci_system_reset + +#endif + + +#if (SOC_SYSTEM_OFF) + +.global _psci_system_off + +func _psci_system_off + + /* system off is mandatory + * system off is soc-specific + * Note: under no circumstances do we return from this call */ + b _soc_sys_off +endfunc _psci_system_off + +#endif + + +#if (SOC_CORE_STANDBY) + +.global _psci_core_entr_stdby +.global _psci_core_prep_stdby +.global _psci_core_exit_stdby + +/* + * void _psci_core_entr_stdby(u_register_t core_mask) - this + * is the fast-path for simple core standby + */ + +func _psci_core_entr_stdby + stp x4, x5, [sp, #-16]! + stp x6, x30, [sp, #-16]! + + mov x5, x0 /* x5 = core mask */ + + /* save scr_el3 */ + mov x0, x5 + mrs x4, SCR_EL3 + mov x2, x4 + mov x1, #SCR_EL3_DATA + bl _setCoreData + + /* x4 = SCR_EL3 + * x5 = core mask + */ + + /* allow interrupts @ EL3 */ + orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK) + msr SCR_EL3, x4 + + /* x5 = core mask */ + + /* put the core into standby */ + mov x0, x5 + bl _soc_core_entr_stdby + + /* restore scr_el3 */ + mov x0, x5 + mov x1, #SCR_EL3_DATA + bl _getCoreData + /* x0 = saved scr_el3 */ + msr SCR_EL3, x0 + + ldp x6, x30, [sp], #16 + ldp x4, x5, [sp], #16 + isb + ret +endfunc _psci_core_entr_stdby + +/* + * void _psci_core_prep_stdby(u_register_t core_mask) - this + * sets up the core to enter standby state thru the normal path + */ + +func _psci_core_prep_stdby + stp x4, x5, [sp, #-16]! + stp x6, x30, [sp, #-16]! + + mov x5, x0 + + /* x5 = core mask */ + + /* save scr_el3 */ + mov x0, x5 + mrs x4, SCR_EL3 + mov x2, x4 + mov x1, #SCR_EL3_DATA + bl _setCoreData + + /* allow interrupts @ EL3 */ + orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK) + msr SCR_EL3, x4 + + /* x5 = core mask */ + + /* call for any SoC-specific programming */ + mov x0, x5 + bl _soc_core_prep_stdby + + ldp x6, x30, [sp], #16 + ldp x4, x5, [sp], #16 + isb + ret +endfunc _psci_core_prep_stdby + +/* + * void _psci_core_exit_stdby(u_register_t core_mask) - this + * exits the core from standby state thru the normal path + */ + +func _psci_core_exit_stdby + stp x4, x5, [sp, #-16]! + stp x6, x30, [sp, #-16]! + + mov x5, x0 + + /* x5 = core mask */ + + /* restore scr_el3 */ + mov x0, x5 + mov x1, #SCR_EL3_DATA + bl _getCoreData + /* x0 = saved scr_el3 */ + msr SCR_EL3, x0 + + /* x5 = core mask */ + + /* perform any SoC-specific programming after standby state */ + mov x0, x5 + bl _soc_core_exit_stdby + + ldp x6, x30, [sp], #16 + ldp x4, x5, [sp], #16 + isb + ret +endfunc _psci_core_exit_stdby + +#endif + + +#if (SOC_CORE_PWR_DWN) + +.global _psci_core_prep_pwrdn +.global _psci_cpu_pwrdn_wfi +.global _psci_core_exit_pwrdn + +/* + * void _psci_core_prep_pwrdn_(u_register_t core_mask) + * this function prepares the core for power-down + * x0 = core mask + * + * called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + +func _psci_core_prep_pwrdn + 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 x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x6, x0 + + /* x6 = core mask */ + + /* mask interrupts by setting DAIF[7:4] to 'b1111 */ + msr DAIFSet, #0xF + + /* save scr_el3 */ + mov x0, x6 + mrs x4, SCR_EL3 + mov x2, x4 + mov x1, #SCR_EL3_DATA + bl _setCoreData + + /* allow interrupts @ EL3 */ + orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK) + msr SCR_EL3, x4 + + /* save cpuectlr */ + mov x0, x6 + mov x1, #CPUECTLR_DATA + mrs x2, CPUECTLR_EL1 + bl _setCoreData + + /* x6 = core mask */ + + /* SoC-specific programming for power-down */ + mov x0, x6 + bl _soc_core_prep_pwrdn + + /* restore the aarch32/64 non-volatile registers + */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [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 + b psci_completed +endfunc _psci_core_prep_pwrdn + +/* + * void _psci_cpu_pwrdn_wfi(u_register_t core_mask, u_register_t resume_addr) + * this function powers down the core + */ + +func _psci_cpu_pwrdn_wfi + /* save the wakeup address */ + mov x29, x1 + + /* x0 = core mask */ + + /* shutdown the core */ + bl _soc_core_entr_pwrdn + + /* branch to resume execution */ + br x29 +endfunc _psci_cpu_pwrdn_wfi + +/* + * void _psci_core_exit_pwrdn_(u_register_t core_mask) + * this function cleans up after a core power-down + * x0 = core mask + * + * called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + +func _psci_core_exit_pwrdn + 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 x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x5, x0 /* x5 = core mask */ + + /* restore scr_el3 */ + mov x0, x5 + mov x1, #SCR_EL3_DATA + bl _getCoreData + /* x0 = saved scr_el3 */ + msr SCR_EL3, x0 + + /* x5 = core mask */ + + /* restore cpuectlr */ + mov x0, x5 + mov x1, #CPUECTLR_DATA + bl _getCoreData + /* make sure smp is set */ + orr x0, x0, #CPUECTLR_SMPEN_MASK + msr CPUECTLR_EL1, x0 + + /* x5 = core mask */ + + /* SoC-specific cleanup */ + mov x0, x5 + bl _soc_core_exit_pwrdn + + /* restore the aarch32/64 non-volatile registers + */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [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 + b psci_completed +endfunc _psci_core_exit_pwrdn + +#endif + +#if (SOC_CLUSTER_STANDBY) + +.global _psci_clstr_prep_stdby +.global _psci_clstr_exit_stdby + +/* + * void _psci_clstr_prep_stdby(u_register_t core_mask) - this + * sets up the clstr to enter standby state thru the normal path + */ + +func _psci_clstr_prep_stdby + stp x4, x5, [sp, #-16]! + stp x6, x30, [sp, #-16]! + + mov x5, x0 + + /* x5 = core mask */ + + /* save scr_el3 */ + mov x0, x5 + mrs x4, SCR_EL3 + mov x2, x4 + mov x1, #SCR_EL3_DATA + bl _setCoreData + + /* allow interrupts @ EL3 */ + orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK) + msr SCR_EL3, x4 + + /* x5 = core mask */ + + /* call for any SoC-specific programming */ + mov x0, x5 + bl _soc_clstr_prep_stdby + + ldp x6, x30, [sp], #16 + ldp x4, x5, [sp], #16 + isb + ret +endfunc _psci_clstr_prep_stdby + +/* + * void _psci_clstr_exit_stdby(u_register_t core_mask) - this + * exits the clstr from standby state thru the normal path + */ + +func _psci_clstr_exit_stdby + stp x4, x5, [sp, #-16]! + stp x6, x30, [sp, #-16]! + + mov x5, x0 /* x5 = core mask */ + + /* restore scr_el3 */ + mov x0, x5 + mov x1, #SCR_EL3_DATA + bl _getCoreData + /* x0 = saved scr_el3 */ + msr SCR_EL3, x0 + + /* x5 = core mask */ + + /* perform any SoC-specific programming after standby state */ + mov x0, x5 + bl _soc_clstr_exit_stdby + + ldp x6, x30, [sp], #16 + ldp x4, x5, [sp], #16 + isb + ret +endfunc _psci_clstr_exit_stdby + +#endif + +#if (SOC_CLUSTER_PWR_DWN) + +.global _psci_clstr_prep_pwrdn +.global _psci_clstr_exit_pwrdn + +/* + * void _psci_clstr_prep_pwrdn_(u_register_t core_mask) + * this function prepares the cluster+core for power-down + * x0 = core mask + * + * called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + +func _psci_clstr_prep_pwrdn + 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 x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x6, x0 /* x6 = core mask */ + + /* mask interrupts by setting DAIF[7:4] to 'b1111 */ + msr DAIFSet, #0xF + + /* save scr_el3 */ + mov x0, x6 + mrs x4, SCR_EL3 + mov x2, x4 + mov x1, #SCR_EL3_DATA + bl _setCoreData + + /* allow interrupts @ EL3 */ + orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK) + msr SCR_EL3, x4 + + /* save cpuectlr */ + mov x0, x6 + mov x1, #CPUECTLR_DATA + mrs x2, CPUECTLR_EL1 + mov x4, x2 + bl _setCoreData + + /* remove core from coherency */ + bic x4, x4, #CPUECTLR_SMPEN_MASK + msr CPUECTLR_EL1, x4 + + /* x6 = core mask */ + + /* SoC-specific programming for power-down */ + mov x0, x6 + bl _soc_clstr_prep_pwrdn + + /* restore the aarch32/64 non-volatile registers + */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [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 + b psci_completed +endfunc _psci_clstr_prep_pwrdn + +/* + * void _psci_clstr_exit_pwrdn_(u_register_t core_mask) + * this function cleans up after a cluster power-down + * x0 = core mask + * + * called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + +func _psci_clstr_exit_pwrdn + 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 x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x4, x0 /* x4 = core mask */ + + /* restore scr_el3 */ + mov x0, x4 + mov x1, #SCR_EL3_DATA + bl _getCoreData + /* x0 = saved scr_el3 */ + msr SCR_EL3, x0 + + /* x4 = core mask */ + + /* restore cpuectlr */ + mov x0, x4 + mov x1, #CPUECTLR_DATA + bl _getCoreData + /* make sure smp is set */ + orr x0, x0, #CPUECTLR_SMPEN_MASK + msr CPUECTLR_EL1, x0 + + /* x4 = core mask */ + + /* SoC-specific cleanup */ + mov x0, x4 + bl _soc_clstr_exit_pwrdn + + /* restore the aarch32/64 non-volatile registers + */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [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 + b psci_completed +endfunc _psci_clstr_exit_pwrdn + +#endif + +#if (SOC_SYSTEM_STANDBY) + +.global _psci_sys_prep_stdby +.global _psci_sys_exit_stdby + +/* + * void _psci_sys_prep_stdby(u_register_t core_mask) - this + * sets up the system to enter standby state thru the normal path + */ + +func _psci_sys_prep_stdby + stp x4, x5, [sp, #-16]! + stp x6, x30, [sp, #-16]! + + mov x5, x0 /* x5 = core mask */ + + /* save scr_el3 */ + mov x0, x5 + mrs x4, SCR_EL3 + mov x2, x4 + mov x1, #SCR_EL3_DATA + bl _setCoreData + + /* allow interrupts @ EL3 */ + orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK) + msr SCR_EL3, x4 + + /* x5 = core mask */ + + /* call for any SoC-specific programming */ + mov x0, x5 + bl _soc_sys_prep_stdby + + ldp x6, x30, [sp], #16 + ldp x4, x5, [sp], #16 + isb + ret +endfunc _psci_sys_prep_stdby + +/* + * void _psci_sys_exit_stdby(u_register_t core_mask) - this + * exits the system from standby state thru the normal path + */ + +func _psci_sys_exit_stdby + stp x4, x5, [sp, #-16]! + stp x6, x30, [sp, #-16]! + + mov x5, x0 + + /* x5 = core mask */ + + /* restore scr_el3 */ + mov x0, x5 + mov x1, #SCR_EL3_DATA + bl _getCoreData + /* x0 = saved scr_el3 */ + msr SCR_EL3, x0 + + /* x5 = core mask */ + + /* perform any SoC-specific programming after standby state */ + mov x0, x5 + bl _soc_sys_exit_stdby + + ldp x6, x30, [sp], #16 + ldp x4, x5, [sp], #16 + isb + ret +endfunc _psci_sys_exit_stdby + +#endif + +#if (SOC_SYSTEM_PWR_DWN) + +.global _psci_sys_prep_pwrdn +.global _psci_sys_pwrdn_wfi +.global _psci_sys_exit_pwrdn + +/* + * void _psci_sys_prep_pwrdn_(u_register_t core_mask) + * this function prepares the system+core for power-down + * x0 = core mask + * + * called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + +func _psci_sys_prep_pwrdn + 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 x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x6, x0 /* x6 = core mask */ + + /* mask interrupts by setting DAIF[7:4] to 'b1111 */ + msr DAIFSet, #0xF + + /* save scr_el3 */ + mov x0, x6 + mrs x4, SCR_EL3 + mov x2, x4 + mov x1, #SCR_EL3_DATA + bl _setCoreData + + /* allow interrupts @ EL3 */ + orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK) + msr SCR_EL3, x4 + + /* save cpuectlr */ + mov x0, x6 + mov x1, #CPUECTLR_DATA + mrs x2, CPUECTLR_EL1 + mov x4, x2 + bl _setCoreData + + /* remove core from coherency */ + bic x4, x4, #CPUECTLR_SMPEN_MASK + msr CPUECTLR_EL1, x4 + + /* x6 = core mask */ + + /* SoC-specific programming for power-down */ + mov x0, x6 + bl _soc_sys_prep_pwrdn + + /* restore the aarch32/64 non-volatile registers + */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [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 + b psci_completed +endfunc _psci_sys_prep_pwrdn + + +/* + * void _psci_sys_pwrdn_wfi(u_register_t core_mask, u_register_t resume_addr) + * this function powers down the system + */ + +func _psci_sys_pwrdn_wfi + /* save the wakeup address */ + mov x29, x1 + + /* x0 = core mask */ + + /* shutdown the system */ + bl _soc_sys_pwrdn_wfi + + /* branch to resume execution */ + br x29 +endfunc _psci_sys_pwrdn_wfi + +/* + * void _psci_sys_exit_pwrdn_(u_register_t core_mask) + * this function cleans up after a system power-down + * x0 = core mask + * + * Called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + +func _psci_sys_exit_pwrdn + + 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 x14, x15, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + mov x4, x0 /* x4 = core mask */ + + /* restore scr_el3 */ + mov x0, x4 + mov x1, #SCR_EL3_DATA + bl _getCoreData + + /* x0 = saved scr_el3 */ + msr SCR_EL3, x0 + + /* x4 = core mask */ + + /* restore cpuectlr */ + mov x0, x4 + mov x1, #CPUECTLR_DATA + bl _getCoreData + + /* make sure smp is set */ + orr x0, x0, #CPUECTLR_SMPEN_MASK + msr CPUECTLR_EL1, x0 + + /* x4 = core mask */ + + /* SoC-specific cleanup */ + mov x0, x4 + bl _soc_sys_exit_pwrdn + + /* restore the aarch32/64 non-volatile registers + */ + ldp x18, x30, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x14, x15, [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 + b psci_completed +endfunc _psci_sys_exit_pwrdn + +#endif + + +/* psci std returns */ +func psci_disabled + ldr w0, =PSCI_E_DISABLED + b psci_completed +endfunc psci_disabled + + +func psci_not_present + ldr w0, =PSCI_E_NOT_PRESENT + b psci_completed +endfunc psci_not_present + + +func psci_on_pending + ldr w0, =PSCI_E_ON_PENDING + b psci_completed +endfunc psci_on_pending + + +func psci_already_on + ldr w0, =PSCI_E_ALREADY_ON + b psci_completed +endfunc psci_already_on + + +func psci_failure + ldr w0, =PSCI_E_INTERN_FAIL + b psci_completed +endfunc psci_failure + + +func psci_unimplemented + ldr w0, =PSCI_E_NOT_SUPPORTED + b psci_completed +endfunc psci_unimplemented + + +func psci_denied + ldr w0, =PSCI_E_DENIED + b psci_completed +endfunc psci_denied + + +func psci_invalid + ldr w0, =PSCI_E_INVALID_PARAMS + b psci_completed +endfunc psci_invalid + + +func psci_success + mov x0, #PSCI_E_SUCCESS +endfunc psci_success + + +func psci_completed + /* x0 = status code */ + ret +endfunc psci_completed diff --git a/plat/nxp/common/psci/include/plat_psci.h b/plat/nxp/common/psci/include/plat_psci.h new file mode 100644 index 0000000..7fc48fb --- /dev/null +++ b/plat/nxp/common/psci/include/plat_psci.h @@ -0,0 +1,145 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_PSCI_H +#define PLAT_PSCI_H +#include <cortex_a53.h> +#include <cortex_a72.h> + + /* core abort current op */ +#define CORE_ABORT_OP 0x1 + + /* psci power levels - these are actually affinity levels + * in the psci_power_state_t array + */ +#define PLAT_CORE_LVL PSCI_CPU_PWR_LVL +#define PLAT_CLSTR_LVL U(1) +#define PLAT_SYS_LVL U(2) +#define PLAT_MAX_LVL PLAT_SYS_LVL + + /* core state */ + /* OFF states 0x0 - 0xF */ +#define CORE_IN_RESET 0x0 +#define CORE_DISABLED 0x1 +#define CORE_OFF 0x2 +#define CORE_STANDBY 0x3 +#define CORE_PWR_DOWN 0x4 +#define CORE_WFE 0x6 +#define CORE_WFI 0x7 +#define CORE_LAST 0x8 +#define CORE_OFF_PENDING 0x9 +#define CORE_WORKING_INIT 0xA +#define SYS_OFF_PENDING 0xB +#define SYS_OFF 0xC + + /* ON states 0x10 - 0x1F */ +#define CORE_PENDING 0x10 +#define CORE_RELEASED 0x11 +#define CORE_WAKEUP 0x12 + /* highest off state */ +#define CORE_OFF_MAX 0xF + /* lowest on state */ +#define CORE_ON_MIN CORE_PENDING + +#define DAIF_SET_MASK 0x3C0 +#define SCTLR_I_C_M_MASK 0x00001005 +#define SCTLR_C_MASK 0x00000004 +#define SCTLR_I_MASK 0x00001000 +#define CPUACTLR_L1PCTL_MASK 0x0000E000 +#define DCSR_RCPM2_BASE 0x20170000 +#define CPUECTLR_SMPEN_MASK 0x40 +#define CPUECTLR_SMPEN_EN 0x40 +#define CPUECTLR_RET_MASK 0x7 +#define CPUECTLR_RET_SET 0x2 +#define CPUECTLR_TIMER_MASK 0x7 +#define CPUECTLR_TIMER_8TICKS 0x2 +#define CPUECTLR_TIMER_2TICKS 0x1 +#define SCR_IRQ_MASK 0x2 +#define SCR_FIQ_MASK 0x4 + +/* pwr mgmt features supported in the soc-specific code: + * value == 0x0, the soc code does not support this feature + * value != 0x0, the soc code supports this feature + */ +#ifndef SOC_CORE_RELEASE +#define SOC_CORE_RELEASE 0x1 +#endif + +#ifndef SOC_CORE_RESTART +#define SOC_CORE_RESTART 0x1 +#endif + +#ifndef SOC_CORE_OFF +#define SOC_CORE_OFF 0x1 +#endif + +#ifndef SOC_CORE_STANDBY +#define SOC_CORE_STANDBY 0x1 +#endif + +#ifndef SOC_CORE_PWR_DWN +#define SOC_CORE_PWR_DWN 0x1 +#endif + +#ifndef SOC_CLUSTER_STANDBY +#define SOC_CLUSTER_STANDBY 0x1 +#endif + +#ifndef SOC_CLUSTER_PWR_DWN +#define SOC_CLUSTER_PWR_DWN 0x1 +#endif + +#ifndef SOC_SYSTEM_STANDBY +#define SOC_SYSTEM_STANDBY 0x1 +#endif + +#ifndef SOC_SYSTEM_PWR_DWN +#define SOC_SYSTEM_PWR_DWN 0x1 +#endif + +#ifndef SOC_SYSTEM_OFF +#define SOC_SYSTEM_OFF 0x1 +#endif + +#ifndef SOC_SYSTEM_RESET +#define SOC_SYSTEM_RESET 0x1 +#endif + +#ifndef SOC_SYSTEM_RESET2 +#define SOC_SYSTEM_RESET2 0x1 +#endif + +#ifndef __ASSEMBLER__ + +void __dead2 _psci_system_reset(void); +void __dead2 _psci_system_off(void); +int _psci_cpu_on(u_register_t core_mask); +void _psci_cpu_prep_off(u_register_t core_mask); +void __dead2 _psci_cpu_off_wfi(u_register_t core_mask, + u_register_t wakeup_address); +void __dead2 _psci_cpu_pwrdn_wfi(u_register_t core_mask, + u_register_t wakeup_address); +void __dead2 _psci_sys_pwrdn_wfi(u_register_t core_mask, + u_register_t wakeup_address); +void _psci_wakeup(u_register_t core_mask); +void _psci_core_entr_stdby(u_register_t core_mask); +void _psci_core_prep_stdby(u_register_t core_mask); +void _psci_core_exit_stdby(u_register_t core_mask); +void _psci_core_prep_pwrdn(u_register_t core_mask); +void _psci_core_exit_pwrdn(u_register_t core_mask); +void _psci_clstr_prep_stdby(u_register_t core_mask); +void _psci_clstr_exit_stdby(u_register_t core_mask); +void _psci_clstr_prep_pwrdn(u_register_t core_mask); +void _psci_clstr_exit_pwrdn(u_register_t core_mask); +void _psci_sys_prep_stdby(u_register_t core_mask); +void _psci_sys_exit_stdby(u_register_t core_mask); +void _psci_sys_prep_pwrdn(u_register_t core_mask); +void _psci_sys_exit_pwrdn(u_register_t core_mask); + +#endif + +#endif /* __PLAT_PSCI_H__ */ diff --git a/plat/nxp/common/psci/plat_psci.c b/plat/nxp/common/psci/plat_psci.c new file mode 100644 index 0000000..9281e97 --- /dev/null +++ b/plat/nxp/common/psci/plat_psci.c @@ -0,0 +1,475 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <common/debug.h> + +#include <plat_gic.h> +#include <plat_common.h> +#include <plat_psci.h> +#ifdef NXP_WARM_BOOT +#include <plat_warm_rst.h> +#endif + +#include <platform_def.h> + +#if (SOC_CORE_OFF || SOC_CORE_PWR_DWN) +static void __dead2 _no_return_wfi(void) +{ +_bl31_dead_wfi: + wfi(); + goto _bl31_dead_wfi; +} +#endif + +#if (SOC_CORE_RELEASE || SOC_CORE_PWR_DWN) + /* the entry for core warm boot */ +static uintptr_t warmboot_entry = (uintptr_t) NULL; +#endif + +#if (SOC_CORE_RELEASE) +static int _pwr_domain_on(u_register_t mpidr) +{ + int core_pos = plat_core_pos(mpidr); + int rc = PSCI_E_INVALID_PARAMS; + u_register_t core_mask; + + if (core_pos >= 0 && core_pos < PLATFORM_CORE_COUNT) { + + _soc_set_start_addr(warmboot_entry); + + dsb(); + isb(); + + core_mask = (1 << core_pos); + rc = _psci_cpu_on(core_mask); + } + + return (rc); +} +#endif + +#if (SOC_CORE_OFF) +static void _pwr_domain_off(const psci_power_state_t *target_state) +{ + u_register_t core_mask = plat_my_core_mask(); + u_register_t core_state = _getCoreState(core_mask); + + /* set core state in internal data */ + core_state = CORE_OFF_PENDING; + _setCoreState(core_mask, core_state); + + _psci_cpu_prep_off(core_mask); +} +#endif + +#if (SOC_CORE_OFF || SOC_CORE_PWR_DWN) +static void __dead2 _pwr_down_wfi(const psci_power_state_t *target_state) +{ + u_register_t core_mask = plat_my_core_mask(); + u_register_t core_state = _getCoreState(core_mask); + + switch (core_state) { +#if (SOC_CORE_OFF) + case CORE_OFF_PENDING: + /* set core state in internal data */ + core_state = CORE_OFF; + _setCoreState(core_mask, core_state); + + /* turn the core off */ + _psci_cpu_off_wfi(core_mask, warmboot_entry); + break; +#endif +#if (SOC_CORE_PWR_DWN) + case CORE_PWR_DOWN: + /* power-down the core */ + _psci_cpu_pwrdn_wfi(core_mask, warmboot_entry); + break; +#endif +#if (SOC_SYSTEM_PWR_DWN) + case SYS_OFF_PENDING: + /* set core state in internal data */ + core_state = SYS_OFF; + _setCoreState(core_mask, core_state); + + /* power-down the system */ + _psci_sys_pwrdn_wfi(core_mask, warmboot_entry); + break; +#endif + default: + _no_return_wfi(); + break; + } +} +#endif + +#if (SOC_CORE_RELEASE || SOC_CORE_RESTART) +static void _pwr_domain_wakeup(const psci_power_state_t *target_state) +{ + u_register_t core_mask = plat_my_core_mask(); + u_register_t core_state = _getCoreState(core_mask); + + switch (core_state) { + case CORE_PENDING: /* this core is coming out of reset */ + + /* soc per cpu setup */ + soc_init_percpu(); + + /* gic per cpu setup */ + plat_gic_pcpu_init(); + + /* set core state in internal data */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); + break; + +#if (SOC_CORE_RESTART) + case CORE_WAKEUP: + + /* this core is waking up from OFF */ + _psci_wakeup(core_mask); + + /* set core state in internal data */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); + + break; +#endif + } +} +#endif + +#if (SOC_CORE_STANDBY) +static void _pwr_cpu_standby(plat_local_state_t cpu_state) +{ + u_register_t core_mask = plat_my_core_mask(); + u_register_t core_state; + + if (cpu_state == PLAT_MAX_RET_STATE) { + + /* set core state to standby */ + core_state = CORE_STANDBY; + _setCoreState(core_mask, core_state); + + _psci_core_entr_stdby(core_mask); + + /* when we are here, the core is waking up + * set core state to released + */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); + } +} +#endif + +#if (SOC_CORE_PWR_DWN) +static void _pwr_suspend(const psci_power_state_t *state) +{ + + u_register_t core_mask = plat_my_core_mask(); + u_register_t core_state; + + if (state->pwr_domain_state[PLAT_MAX_LVL] == PLAT_MAX_OFF_STATE) { +#if (SOC_SYSTEM_PWR_DWN) + _psci_sys_prep_pwrdn(core_mask); + + /* set core state */ + core_state = SYS_OFF_PENDING; + _setCoreState(core_mask, core_state); +#endif + } else if (state->pwr_domain_state[PLAT_MAX_LVL] + == PLAT_MAX_RET_STATE) { +#if (SOC_SYSTEM_STANDBY) + _psci_sys_prep_stdby(core_mask); + + /* set core state */ + core_state = CORE_STANDBY; + _setCoreState(core_mask, core_state); +#endif + } + + else if (state->pwr_domain_state[PLAT_CLSTR_LVL] == + PLAT_MAX_OFF_STATE) { +#if (SOC_CLUSTER_PWR_DWN) + _psci_clstr_prep_pwrdn(core_mask); + + /* set core state */ + core_state = CORE_PWR_DOWN; + _setCoreState(core_mask, core_state); +#endif + } + + else if (state->pwr_domain_state[PLAT_CLSTR_LVL] == + PLAT_MAX_RET_STATE) { +#if (SOC_CLUSTER_STANDBY) + _psci_clstr_prep_stdby(core_mask); + + /* set core state */ + core_state = CORE_STANDBY; + _setCoreState(core_mask, core_state); +#endif + } + + else if (state->pwr_domain_state[PLAT_CORE_LVL] == PLAT_MAX_OFF_STATE) { +#if (SOC_CORE_PWR_DWN) + /* prep the core for power-down */ + _psci_core_prep_pwrdn(core_mask); + + /* set core state */ + core_state = CORE_PWR_DOWN; + _setCoreState(core_mask, core_state); +#endif + } + + else if (state->pwr_domain_state[PLAT_CORE_LVL] == PLAT_MAX_RET_STATE) { +#if (SOC_CORE_STANDBY) + _psci_core_prep_stdby(core_mask); + + /* set core state */ + core_state = CORE_STANDBY; + _setCoreState(core_mask, core_state); +#endif + } + +} +#endif + +#if (SOC_CORE_PWR_DWN) +static void _pwr_suspend_finish(const psci_power_state_t *state) +{ + + u_register_t core_mask = plat_my_core_mask(); + u_register_t core_state; + + + if (state->pwr_domain_state[PLAT_MAX_LVL] == PLAT_MAX_OFF_STATE) { +#if (SOC_SYSTEM_PWR_DWN) + _psci_sys_exit_pwrdn(core_mask); + + /* when we are here, the core is back up + * set core state to released + */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); +#endif + } else if (state->pwr_domain_state[PLAT_MAX_LVL] + == PLAT_MAX_RET_STATE) { +#if (SOC_SYSTEM_STANDBY) + _psci_sys_exit_stdby(core_mask); + + /* when we are here, the core is waking up + * set core state to released + */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); +#endif + } + + else if (state->pwr_domain_state[PLAT_CLSTR_LVL] == + PLAT_MAX_OFF_STATE) { +#if (SOC_CLUSTER_PWR_DWN) + _psci_clstr_exit_pwrdn(core_mask); + + /* when we are here, the core is waking up + * set core state to released + */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); +#endif + } + + else if (state->pwr_domain_state[PLAT_CLSTR_LVL] == + PLAT_MAX_RET_STATE) { +#if (SOC_CLUSTER_STANDBY) + _psci_clstr_exit_stdby(core_mask); + + /* when we are here, the core is waking up + * set core state to released + */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); +#endif + } + + else if (state->pwr_domain_state[PLAT_CORE_LVL] == PLAT_MAX_OFF_STATE) { +#if (SOC_CORE_PWR_DWN) + _psci_core_exit_pwrdn(core_mask); + + /* when we are here, the core is back up + * set core state to released + */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); +#endif + } + + else if (state->pwr_domain_state[PLAT_CORE_LVL] == PLAT_MAX_RET_STATE) { +#if (SOC_CORE_STANDBY) + _psci_core_exit_stdby(core_mask); + + /* when we are here, the core is waking up + * set core state to released + */ + core_state = CORE_RELEASED; + _setCoreState(core_mask, core_state); +#endif + } + +} +#endif + +#if (SOC_CORE_STANDBY || SOC_CORE_PWR_DWN) + +#define PWR_STATE_TYPE_MASK 0x00010000 +#define PWR_STATE_TYPE_STNDBY 0x0 +#define PWR_STATE_TYPE_PWRDWN 0x00010000 +#define PWR_STATE_LVL_MASK 0x03000000 +#define PWR_STATE_LVL_CORE 0x0 +#define PWR_STATE_LVL_CLSTR 0x01000000 +#define PWR_STATE_LVL_SYS 0x02000000 +#define PWR_STATE_LVL_MAX 0x03000000 + + /* turns a requested power state into a target power state + * based on SoC capabilities + */ +static int _pwr_state_validate(uint32_t pwr_state, + psci_power_state_t *state) +{ + int stat = PSCI_E_INVALID_PARAMS; + int pwrdn = (pwr_state & PWR_STATE_TYPE_MASK); + int lvl = (pwr_state & PWR_STATE_LVL_MASK); + + switch (lvl) { + case PWR_STATE_LVL_MAX: + if (pwrdn && SOC_SYSTEM_PWR_DWN) + state->pwr_domain_state[PLAT_MAX_LVL] = + PLAT_MAX_OFF_STATE; + else if (SOC_SYSTEM_STANDBY) + state->pwr_domain_state[PLAT_MAX_LVL] = + PLAT_MAX_RET_STATE; + /* intentional fall-thru condition */ + case PWR_STATE_LVL_SYS: + if (pwrdn && SOC_SYSTEM_PWR_DWN) + state->pwr_domain_state[PLAT_SYS_LVL] = + PLAT_MAX_OFF_STATE; + else if (SOC_SYSTEM_STANDBY) + state->pwr_domain_state[PLAT_SYS_LVL] = + PLAT_MAX_RET_STATE; + /* intentional fall-thru condition */ + case PWR_STATE_LVL_CLSTR: + if (pwrdn && SOC_CLUSTER_PWR_DWN) + state->pwr_domain_state[PLAT_CLSTR_LVL] = + PLAT_MAX_OFF_STATE; + else if (SOC_CLUSTER_STANDBY) + state->pwr_domain_state[PLAT_CLSTR_LVL] = + PLAT_MAX_RET_STATE; + /* intentional fall-thru condition */ + case PWR_STATE_LVL_CORE: + stat = PSCI_E_SUCCESS; + + if (pwrdn && SOC_CORE_PWR_DWN) + state->pwr_domain_state[PLAT_CORE_LVL] = + PLAT_MAX_OFF_STATE; + else if (SOC_CORE_STANDBY) + state->pwr_domain_state[PLAT_CORE_LVL] = + PLAT_MAX_RET_STATE; + break; + } + return (stat); +} + +#endif + +#if (SOC_SYSTEM_PWR_DWN) +static void _pwr_state_sys_suspend(psci_power_state_t *req_state) +{ + + /* if we need to have per-SoC settings, then we need to + * extend this by calling into psci_utils.S and from there + * on down to the SoC.S files + */ + + req_state->pwr_domain_state[PLAT_MAX_LVL] = PLAT_MAX_OFF_STATE; + req_state->pwr_domain_state[PLAT_SYS_LVL] = PLAT_MAX_OFF_STATE; + req_state->pwr_domain_state[PLAT_CLSTR_LVL] = PLAT_MAX_OFF_STATE; + req_state->pwr_domain_state[PLAT_CORE_LVL] = PLAT_MAX_OFF_STATE; + +} +#endif + +#if defined(NXP_WARM_BOOT) && (SOC_SYSTEM_RESET2) +static int psci_system_reset2(int is_vendor, + int reset_type, + u_register_t cookie) +{ + int ret = 0; + + INFO("Executing the sequence of warm reset.\n"); + ret = prep_n_execute_warm_reset(); + + return ret; +} +#endif + +static plat_psci_ops_t _psci_pm_ops = { +#if (SOC_SYSTEM_OFF) + .system_off = _psci_system_off, +#endif +#if (SOC_SYSTEM_RESET) + .system_reset = _psci_system_reset, +#endif +#if defined(NXP_WARM_BOOT) && (SOC_SYSTEM_RESET2) + .system_reset2 = psci_system_reset2, +#endif +#if (SOC_CORE_RELEASE || SOC_CORE_RESTART) + /* core released or restarted */ + .pwr_domain_on_finish = _pwr_domain_wakeup, +#endif +#if (SOC_CORE_OFF) + /* core shutting down */ + .pwr_domain_off = _pwr_domain_off, +#endif +#if (SOC_CORE_OFF || SOC_CORE_PWR_DWN) + .pwr_domain_pwr_down_wfi = _pwr_down_wfi, +#endif +#if (SOC_CORE_STANDBY || SOC_CORE_PWR_DWN) + /* cpu_suspend */ + .validate_power_state = _pwr_state_validate, +#if (SOC_CORE_STANDBY) + .cpu_standby = _pwr_cpu_standby, +#endif +#if (SOC_CORE_PWR_DWN) + .pwr_domain_suspend = _pwr_suspend, + .pwr_domain_suspend_finish = _pwr_suspend_finish, +#endif +#endif +#if (SOC_SYSTEM_PWR_DWN) + .get_sys_suspend_power_state = _pwr_state_sys_suspend, +#endif +#if (SOC_CORE_RELEASE) + /* core executing psci_cpu_on */ + .pwr_domain_on = _pwr_domain_on +#endif +}; + +#if (SOC_CORE_RELEASE || SOC_CORE_PWR_DWN) +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + warmboot_entry = sec_entrypoint; + *psci_ops = &_psci_pm_ops; + return 0; +} + +#else + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &_psci_pm_ops; + return 0; +} +#endif diff --git a/plat/nxp/common/psci/psci.mk b/plat/nxp/common/psci/psci.mk new file mode 100644 index 0000000..a2791c2 --- /dev/null +++ b/plat/nxp/common/psci/psci.mk @@ -0,0 +1,35 @@ +# +# Copyright 2018-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# Select the PSCI files +# +# ----------------------------------------------------------------------------- + +ifeq (${ADD_PSCI},) + +ADD_PSCI := 1 +PLAT_PSCI_PATH := $(PLAT_COMMON_PATH)/psci + +PSCI_SOURCES := ${PLAT_PSCI_PATH}/plat_psci.c \ + ${PLAT_PSCI_PATH}/$(ARCH)/psci_utils.S \ + plat/common/plat_psci_common.c + +PLAT_INCLUDES += -I${PLAT_PSCI_PATH}/include + +ifeq (${BL_COMM_PSCI_NEEDED},yes) +BL_COMMON_SOURCES += ${PSCI_SOURCES} +else +ifeq (${BL2_PSCI_NEEDED},yes) +BL2_SOURCES += ${PSCI_SOURCES} +endif +ifeq (${BL31_PSCI_NEEDED},yes) +BL31_SOURCES += ${PSCI_SOURCES} +endif +endif +endif +# ----------------------------------------------------------------------------- diff --git a/plat/nxp/common/setup/aarch64/ls_bl2_mem_params_desc.c b/plat/nxp/common/setup/aarch64/ls_bl2_mem_params_desc.c new file mode 100644 index 0000000..7463d47 --- /dev/null +++ b/plat/nxp/common/setup/aarch64/ls_bl2_mem_params_desc.c @@ -0,0 +1,103 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <common/bl_common.h> +#include <common/desc_image_load.h> +#ifdef CSF_HEADER_PREPENDED +#include <csf_hdr.h> +#endif +#include <plat/common/platform.h> +#include <platform_def.h> + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { + /* Fill BL31 related information */ + { + .image_id = BL31_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), +#if DEBUG + .ep_info.args.arg1 = LS_BL31_PLAT_PARAM_VAL, +#endif + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), +#ifdef CSF_HEADER_PREPENDED + .image_info.image_base = BL31_BASE - CSF_HDR_SZ, + .image_info.image_max_size = (BL31_LIMIT - BL31_BASE) + + CSF_HDR_SZ, +#else + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = (BL31_LIMIT - BL31_BASE), +#endif + +# ifdef NXP_LOAD_BL32 + .next_handoff_image_id = BL32_IMAGE_ID, +# else + .next_handoff_image_id = BL33_IMAGE_ID, +# endif + }, +# ifdef NXP_LOAD_BL32 + /* Fill BL32 related information */ + { + .image_id = BL32_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, SECURE | EXECUTABLE), + .ep_info.pc = BL32_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), +#ifdef CSF_HEADER_PREPENDED + .image_info.image_base = BL32_BASE - CSF_HDR_SZ, + .image_info.image_max_size = (BL32_LIMIT - BL32_BASE) + + CSF_HDR_SZ, +#else + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = (BL32_LIMIT - BL32_BASE), +#endif + .next_handoff_image_id = BL33_IMAGE_ID, + }, +# endif /* BL32_BASE */ + + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE), + .ep_info.pc = BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), +#ifdef CSF_HEADER_PREPENDED + .image_info.image_base = BL33_BASE - CSF_HDR_SZ, + .image_info.image_max_size = (BL33_LIMIT - BL33_BASE) + + CSF_HDR_SZ, +#else + .image_info.image_base = BL33_BASE, + .image_info.image_max_size = BL33_LIMIT - BL33_BASE, +#endif + .ep_info.spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/plat/nxp/common/setup/common.mk b/plat/nxp/common/setup/common.mk new file mode 100644 index 0000000..1fcf1d0 --- /dev/null +++ b/plat/nxp/common/setup/common.mk @@ -0,0 +1,105 @@ +# +# Copyright 2018-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +############################################################################### +# Flow begins in BL2 at EL3 mode +BL2_AT_EL3 := 1 + +# Though one core is powered up by default, there are +# platform specific ways to release more than one core +COLD_BOOT_SINGLE_CPU := 0 + +PROGRAMMABLE_RESET_ADDRESS := 1 + +USE_COHERENT_MEM := 0 + +# Use generic OID definition (tbbr_oid.h) +USE_TBBR_DEFS := 1 + +PLAT_XLAT_TABLES_DYNAMIC := 0 + +ENABLE_SVE_FOR_NS := 0 + +ENABLE_STACK_PROTECTOR := 0 + +ERROR_DEPRECATED := 0 + +LS_DISABLE_TRUSTED_WDOG := 1 + +# On ARM platforms, separate the code and read-only data sections to allow +# mapping the former as executable and the latter as execute-never. +SEPARATE_CODE_AND_RODATA := 1 + +# Enable new version of image loading on ARM platforms +LOAD_IMAGE_V2 := 1 + +RCW := "" + +ifneq (${SPD},none) +$(eval $(call add_define, NXP_LOAD_BL32)) +endif + +############################################################################### + +PLAT_TOOL_PATH := tools/nxp +CREATE_PBL_TOOL_PATH := ${PLAT_TOOL_PATH}/create_pbl +PLAT_SETUP_PATH := ${PLAT_PATH}/common/setup + +PLAT_INCLUDES += -I${PLAT_SETUP_PATH}/include \ + -Iinclude/plat/arm/common \ + -Iinclude/drivers/arm \ + -Iinclude/lib \ + -Iinclude/drivers/io \ + -Ilib/psci + +# Required without TBBR. +# To include the defines for DDR PHY Images. +PLAT_INCLUDES += -Iinclude/common/tbbr + +include ${PLAT_SETUP_PATH}/core.mk +PLAT_BL_COMMON_SOURCES += ${CPU_LIBS} \ + plat/nxp/common/setup/ls_err.c \ + plat/nxp/common/setup/ls_common.c + +ifneq (${ENABLE_STACK_PROTECTOR},0) +PLAT_BL_COMMON_SOURCES += ${PLAT_SETUP_PATH}/ls_stack_protector.c +endif + +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} + +BL2_SOURCES += drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + common/desc_image_load.c \ + plat/nxp/common/setup/ls_image_load.c \ + plat/nxp/common/setup/ls_io_storage.c \ + plat/nxp/common/setup/ls_bl2_el3_setup.c \ + plat/nxp/common/setup/${ARCH}/ls_bl2_mem_params_desc.c + +BL31_SOURCES += plat/nxp/common/setup/ls_bl31_setup.c \ + +ifeq (${LS_EL3_INTERRUPT_HANDLER}, yes) +$(eval $(call add_define, LS_EL3_INTERRUPT_HANDLER)) +BL31_SOURCES += plat/nxp/common/setup/ls_interrupt_mgmt.c +endif + +ifeq (${TEST_BL31}, 1) +BL31_SOURCES += ${TEST_SOURCES} +endif + +# Verify build config +# ------------------- + +ifneq (${LOAD_IMAGE_V2}, 1) + $(error Error: Layerscape needs LOAD_IMAGE_V2=1) +else +$(eval $(call add_define,LOAD_IMAGE_V2)) +endif + +include $(CREATE_PBL_TOOL_PATH)/create_pbl.mk diff --git a/plat/nxp/common/setup/core.mk b/plat/nxp/common/setup/core.mk new file mode 100644 index 0000000..82ce30e --- /dev/null +++ b/plat/nxp/common/setup/core.mk @@ -0,0 +1,22 @@ +# Copyright 2018-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# Select the CORE files +# +# ----------------------------------------------------------------------------- + +CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S + +ifeq (,$(filter $(CORE_TYPE),a53 a72)) +$(error "CORE_TYPE not specified or incorrect") +else +UPPER_CORE_TYPE=$(shell echo $(CORE_TYPE) | tr a-z A-Z) +$(eval $(call add_define_val,CPUECTLR_EL1,CORTEX_$(UPPER_CORE_TYPE)_ECTLR_EL1)) +CPU_LIBS += lib/cpus/${ARCH}/cortex_$(CORE_TYPE).S +endif + +# ----------------------------------------------------------------------------- diff --git a/plat/nxp/common/setup/include/bl31_data.h b/plat/nxp/common/setup/include/bl31_data.h new file mode 100644 index 0000000..dd20d43 --- /dev/null +++ b/plat/nxp/common/setup/include/bl31_data.h @@ -0,0 +1,61 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef BL31_DATA_H +#define BL31_DATA_H + +#define SECURE_DATA_BASE NXP_OCRAM_ADDR +#define SECURE_DATA_SIZE NXP_OCRAM_SIZE +#define SECURE_DATA_TOP (SECURE_DATA_BASE + SECURE_DATA_SIZE) +#define SMC_REGION_SIZE 0x80 +#define SMC_GLBL_BASE (SECURE_DATA_TOP - SMC_REGION_SIZE) +#define BC_PSCI_DATA_SIZE 0xC0 +#define BC_PSCI_BASE (SMC_GLBL_BASE - BC_PSCI_DATA_SIZE) +#define SECONDARY_TOP BC_PSCI_BASE + +#define SEC_PSCI_DATA_SIZE 0xC0 +#define SEC_REGION_SIZE SEC_PSCI_DATA_SIZE + +/* SMC global data */ +#define BOOTLOC_OFFSET 0x0 +#define BOOT_SVCS_OSET 0x8 + +/* offset to prefetch disable mask */ +#define PREFETCH_DIS_OFFSET 0x10 +/* must reference last smc global entry */ +#define LAST_SMC_GLBL_OFFSET 0x18 + +#define SMC_TASK_OFFSET 0xC +#define TSK_START_OFFSET 0x0 +#define TSK_DONE_OFFSET 0x4 +#define TSK_CORE_OFFSET 0x8 +#define SMC_TASK1_BASE (SMC_GLBL_BASE + 32) +#define SMC_TASK2_BASE (SMC_TASK1_BASE + SMC_TASK_OFFSET) +#define SMC_TASK3_BASE (SMC_TASK2_BASE + SMC_TASK_OFFSET) +#define SMC_TASK4_BASE (SMC_TASK3_BASE + SMC_TASK_OFFSET) + +/* psci data area offsets */ +#define CORE_STATE_DATA 0x0 +#define SPSR_EL3_DATA 0x8 +#define CNTXT_ID_DATA 0x10 +#define START_ADDR_DATA 0x18 +#define LINK_REG_DATA 0x20 +#define GICC_CTLR_DATA 0x28 +#define ABORT_FLAG_DATA 0x30 +#define SCTLR_DATA 0x38 +#define CPUECTLR_DATA 0x40 +#define AUX_01_DATA 0x48 /* usage defined per SoC */ +#define AUX_02_DATA 0x50 /* usage defined per SoC */ +#define AUX_03_DATA 0x58 /* usage defined per SoC */ +#define AUX_04_DATA 0x60 /* usage defined per SoC */ +#define AUX_05_DATA 0x68 /* usage defined per SoC */ +#define AUX_06_DATA 0x70 /* usage defined per SoC */ +#define AUX_07_DATA 0x78 /* usage defined per SoC */ +#define SCR_EL3_DATA 0x80 +#define HCR_EL2_DATA 0x88 + +#endif /* BL31_DATA_H */ diff --git a/plat/nxp/common/setup/include/ls_interrupt_mgmt.h b/plat/nxp/common/setup/include/ls_interrupt_mgmt.h new file mode 100644 index 0000000..7dbddfb --- /dev/null +++ b/plat/nxp/common/setup/include/ls_interrupt_mgmt.h @@ -0,0 +1,23 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef LS_EL3_INTRPT_MGMT_H +#define LS_EL3_INTRPT_MGMT_H + +#include <bl31/interrupt_mgmt.h> + +#define MAX_INTR_EL3 128 + +/* + * Register handler to specific GIC entrance + * for INTR_TYPE_EL3 type of interrupt + */ +int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler); + +void ls_el3_interrupt_config(void); + +#endif /* LS_EL3_INTRPT_MGMT_H */ diff --git a/plat/nxp/common/setup/include/mmu_def.h b/plat/nxp/common/setup/include/mmu_def.h new file mode 100644 index 0000000..2a7771b --- /dev/null +++ b/plat/nxp/common/setup/include/mmu_def.h @@ -0,0 +1,34 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef MMU_MAP_DEF_H +#define MMU_MAP_DEF_H + +#include <lib/xlat_tables/xlat_tables_defs.h> + +#include <platform_def.h> + + +#define LS_MAP_CCSR MAP_REGION_FLAT(NXP_CCSR_ADDR, \ + NXP_CCSR_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#ifdef NXP_DCSR_ADDR +#define LS_MAP_DCSR MAP_REGION_FLAT(NXP_DCSR_ADDR, \ + NXP_DCSR_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +#define LS_MAP_CONSOLE MAP_REGION_FLAT(NXP_DUART1_ADDR, \ + NXP_DUART_SIZE, \ + MT_DEVICE | MT_RW | MT_NS) + +#define LS_MAP_OCRAM MAP_REGION_FLAT(NXP_OCRAM_ADDR, \ + NXP_OCRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#endif /* MMU_MAP_DEF_H */ diff --git a/plat/nxp/common/setup/include/plat_common.h b/plat/nxp/common/setup/include/plat_common.h new file mode 100644 index 0000000..e13f45c --- /dev/null +++ b/plat/nxp/common/setup/include/plat_common.h @@ -0,0 +1,152 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_COMMON_H +#define PLAT_COMMON_H + +#include <stdbool.h> + +#include <dcfg.h> +#include <lib/el3_runtime/cpu_data.h> + +#include <platform_def.h> + +#ifdef IMAGE_BL31 + +#define BL31_END (uintptr_t)(&__BL31_END__) + +/******************************************************************************* + * This structure represents the superset of information that can be passed to + * BL31 e.g. while passing control to it from BL2. The BL32 parameters will be + * populated only if BL2 detects its presence. A pointer to a structure of this + * type should be passed in X0 to BL31's cold boot entrypoint. + * + * Use of this structure and the X0 parameter is not mandatory: the BL31 + * platform code can use other mechanisms to provide the necessary information + * about BL32 and BL33 to the common and SPD code. + * + * BL31 image information is mandatory if this structure is used. If either of + * the optional BL32 and BL33 image information is not provided, this is + * indicated by the respective image_info pointers being zero. + ******************************************************************************/ +typedef struct bl31_params { + param_header_t h; + image_info_t *bl31_image_info; + entry_point_info_t *bl32_ep_info; + image_info_t *bl32_image_info; + entry_point_info_t *bl33_ep_info; + image_info_t *bl33_image_info; +} bl31_params_t; + +/* BL3 utility functions */ +void ls_bl31_early_platform_setup(void *from_bl2, + void *plat_params_from_bl2); +/* LS Helper functions */ +unsigned int plat_my_core_mask(void); +unsigned int plat_core_mask(u_register_t mpidr); +unsigned int plat_core_pos(u_register_t mpidr); +//unsigned int plat_my_core_pos(void); + +/* BL31 Data API(s) */ +void _init_global_data(void); +void _initialize_psci(void); +uint32_t _getCoreState(u_register_t core_mask); +void _setCoreState(u_register_t core_mask, u_register_t core_state); + +/* SoC defined structure and API(s) */ +void soc_runtime_setup(void); +void soc_init(void); +void soc_platform_setup(void); +void soc_early_platform_setup2(void); +#endif /* IMAGE_BL31 */ + +#ifdef IMAGE_BL2 +void soc_early_init(void); +void soc_mem_access(void); +void soc_preload_setup(void); +void soc_bl2_prepare_exit(void); + +/* IO storage utility functions */ +int plat_io_setup(void); +int open_backend(const uintptr_t spec); + +void ls_bl2_plat_arch_setup(void); +void ls_bl2_el3_plat_arch_setup(void); + +enum boot_device { + BOOT_DEVICE_IFC_NOR, + BOOT_DEVICE_IFC_NAND, + BOOT_DEVICE_QSPI, + BOOT_DEVICE_EMMC, + BOOT_DEVICE_SDHC2_EMMC, + BOOT_DEVICE_FLEXSPI_NOR, + BOOT_DEVICE_FLEXSPI_NAND, + BOOT_DEVICE_NONE +}; + +enum boot_device get_boot_dev(void); + +/* DDR Related functions */ +#if DDR_INIT +#ifdef NXP_WARM_BOOT +long long init_ddr(uint32_t wrm_bt_flg); +#else +long long init_ddr(void); +#endif +#endif + +/* Board specific weak functions */ +bool board_enable_povdd(void); +bool board_disable_povdd(void); + +void mmap_add_ddr_region_dynamically(void); +#endif /* IMAGE_BL2 */ + +typedef struct { + uint64_t addr; + uint64_t size; +} region_info_t; + +typedef struct { + uint64_t num_dram_regions; + int64_t total_dram_size; + region_info_t region[NUM_DRAM_REGIONS]; +} dram_regions_info_t; + +dram_regions_info_t *get_dram_regions_info(void); + +void ls_setup_page_tables(uintptr_t total_base, + size_t total_size, + uintptr_t code_start, + uintptr_t code_limit, + uintptr_t rodata_start, + uintptr_t rodata_limit +#if USE_COHERENT_MEM + , uintptr_t coh_start, + uintptr_t coh_limit +#endif +); + +#define SOC_NAME_MAX_LEN (20) + +/* Structure to define SoC personality */ +struct soc_type { + char name[SOC_NAME_MAX_LEN]; + uint32_t version; + uint8_t num_clusters; + uint8_t cores_per_cluster; +}; +void get_cluster_info(const struct soc_type *soc_list, uint8_t ps_count, + uint8_t *num_clusters, uint8_t *cores_per_cluster); + +#define SOC_ENTRY(n, v, ncl, nc) { \ + .name = #n, \ + .version = SVR_##v, \ + .num_clusters = (ncl), \ + .cores_per_cluster = (nc)} + +#endif /* PLAT_COMMON_H */ diff --git a/plat/nxp/common/setup/include/plat_macros.S b/plat/nxp/common/setup/include/plat_macros.S new file mode 100644 index 0000000..69a3b08 --- /dev/null +++ b/plat/nxp/common/setup/include/plat_macros.S @@ -0,0 +1,22 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant GIC and CCI registers + * whenever an unhandled exception is taken in + * BL31. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/plat/nxp/common/setup/ls_bl2_el3_setup.c b/plat/nxp/common/setup/ls_bl2_el3_setup.c new file mode 100644 index 0000000..a4cbaef --- /dev/null +++ b/plat/nxp/common/setup/ls_bl2_el3_setup.c @@ -0,0 +1,303 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <assert.h> + +#include <common/desc_image_load.h> +#include <dcfg.h> +#ifdef POLICY_FUSE_PROVISION +#include <fuse_io.h> +#endif +#include <mmu_def.h> +#include <plat_common.h> +#ifdef NXP_NV_SW_MAINT_LAST_EXEC_DATA +#include <plat_nv_storage.h> +#endif + +#pragma weak bl2_el3_early_platform_setup +#pragma weak bl2_el3_plat_arch_setup +#pragma weak bl2_el3_plat_prepare_exit + +static dram_regions_info_t dram_regions_info = {0}; + +/******************************************************************************* + * Return the pointer to the 'dram_regions_info structure of the DRAM. + * This structure is populated after init_ddr(). + ******************************************************************************/ +dram_regions_info_t *get_dram_regions_info(void) +{ + return &dram_regions_info; +} + +#ifdef DDR_INIT +static void populate_dram_regions_info(void) +{ + long long dram_remain_size = dram_regions_info.total_dram_size; + uint8_t reg_id = 0U; + + dram_regions_info.region[reg_id].addr = NXP_DRAM0_ADDR; + dram_regions_info.region[reg_id].size = + dram_remain_size > NXP_DRAM0_MAX_SIZE ? + NXP_DRAM0_MAX_SIZE : dram_remain_size; + + if (dram_regions_info.region[reg_id].size != NXP_DRAM0_SIZE) { + ERROR("Incorrect DRAM0 size is defined in platform_def.h\n"); + } + + dram_remain_size -= dram_regions_info.region[reg_id].size; + dram_regions_info.region[reg_id].size -= (NXP_SECURE_DRAM_SIZE + + NXP_SP_SHRD_DRAM_SIZE); + + assert(dram_regions_info.region[reg_id].size > 0); + + /* Reducing total dram size by 66MB */ + dram_regions_info.total_dram_size -= (NXP_SECURE_DRAM_SIZE + + NXP_SP_SHRD_DRAM_SIZE); + +#if defined(NXP_DRAM1_ADDR) && defined(NXP_DRAM1_MAX_SIZE) + if (dram_remain_size > 0) { + reg_id++; + dram_regions_info.region[reg_id].addr = NXP_DRAM1_ADDR; + dram_regions_info.region[reg_id].size = + dram_remain_size > NXP_DRAM1_MAX_SIZE ? + NXP_DRAM1_MAX_SIZE : dram_remain_size; + dram_remain_size -= dram_regions_info.region[reg_id].size; + } +#endif +#if defined(NXP_DRAM2_ADDR) && defined(NXP_DRAM2_MAX_SIZE) + if (dram_remain_size > 0) { + reg_id++; + dram_regions_info.region[reg_id].addr = NXP_DRAM1_ADDR; + dram_regions_info.region[reg_id].size = + dram_remain_size > NXP_DRAM1_MAX_SIZE ? + NXP_DRAM1_MAX_SIZE : dram_remain_size; + dram_remain_size -= dram_regions_info.region[reg_id].size; + } +#endif + reg_id++; + dram_regions_info.num_dram_regions = reg_id; +} +#endif + +#ifdef IMAGE_BL32 +/******************************************************************************* + * Gets SPSR for BL32 entry + ******************************************************************************/ +static uint32_t ls_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL32 image. + */ + return 0U; +} +#endif + +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +#ifndef AARCH32 +static uint32_t ls_get_spsr_for_bl33_entry(void) +{ + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#else +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +static uint32_t ls_get_spsr_for_bl33_entry(void) +{ + unsigned int hyp_status, mode, spsr; + + hyp_status = GET_VIRT_EXT(read_id_pfr1()); + + mode = (hyp_status) ? MODE32_hyp : MODE32_svc; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1, + SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); + return spsr; +} +#endif /* AARCH32 */ + +void bl2_el3_early_platform_setup(u_register_t arg0 __unused, + u_register_t arg1 __unused, + u_register_t arg2 __unused, + u_register_t arg3 __unused) +{ + /* + * SoC specific early init + * Any errata handling or SoC specific early initialization can + * be done here + * Set Counter Base Frequency in CNTFID0 and in cntfrq_el0. + * Initialize the interconnect. + * Enable coherency for primary CPU cluster + */ + soc_early_init(); + + /* Initialise the IO layer and register platform IO devices */ + plat_io_setup(); + + if (dram_regions_info.total_dram_size > 0) { + populate_dram_regions_info(); + } + +#ifdef NXP_NV_SW_MAINT_LAST_EXEC_DATA + read_nv_app_data(); +#if DEBUG + const nv_app_data_t *nv_app_data = get_nv_data(); + + INFO("Value of warm_reset flag = 0x%x\n", nv_app_data->warm_rst_flag); + INFO("Value of WDT flag = 0x%x\n", nv_app_data->wdt_rst_flag); +#endif +#endif +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only initializes the mmu in a quick and dirty way. + ******************************************************************************/ +void ls_bl2_el3_plat_arch_setup(void) +{ + unsigned int flags = 0U; + /* Initialise the IO layer and register platform IO devices */ + ls_setup_page_tables( +#if SEPARATE_BL2_NOLOAD_REGION + BL2_START, + BL2_LIMIT - BL2_START, +#else + BL2_BASE, + (unsigned long)(&__BL2_END__) - BL2_BASE, +#endif + BL_CODE_BASE, + BL_CODE_END, + BL_RO_DATA_BASE, + BL_RO_DATA_END +#if USE_COHERENT_MEM + , BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END +#endif + ); + + if ((dram_regions_info.region[0].addr == 0) + && (dram_regions_info.total_dram_size == 0)) { + flags = XLAT_TABLE_NC; + } + +#ifdef AARCH32 + enable_mmu_secure(0); +#else + enable_mmu_el3(flags); +#endif +} + +void bl2_el3_plat_arch_setup(void) +{ + ls_bl2_el3_plat_arch_setup(); +} + +void bl2_platform_setup(void) +{ + /* + * Perform platform setup before loading the image. + */ +} + +/* Handling image information by platform. */ +int ls_bl2_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + + assert(bl_mem_params); + + switch (image_id) { + case BL31_IMAGE_ID: + bl_mem_params->ep_info.args.arg3 = + (u_register_t) &dram_regions_info; + + /* Pass the value of PORSR1 register in Argument 4 */ + bl_mem_params->ep_info.args.arg4 = + (u_register_t)read_reg_porsr1(); + flush_dcache_range((uintptr_t)&dram_regions_info, + sizeof(dram_regions_info)); + break; +#if defined(AARCH64) && defined(IMAGE_BL32) + case BL32_IMAGE_ID: + bl_mem_params->ep_info.spsr = ls_get_spsr_for_bl32_entry(); + break; +#endif + case BL33_IMAGE_ID: + /* BL33 expects to receive the primary CPU MPID (through r0) */ + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = ls_get_spsr_for_bl33_entry(); + break; + } + + return err; +} + +/******************************************************************************* + * This function can be used by the platforms to update/use image + * information for given `image_id`. + ******************************************************************************/ +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + return ls_bl2_handle_post_image_load(image_id); +} + +void bl2_el3_plat_prepare_exit(void) +{ + return soc_bl2_prepare_exit(); +} + +/* Called to do the dynamic initialization required + * before loading the next image. + */ +void bl2_plat_preload_setup(void) +{ + + soc_preload_setup(); + +#ifdef DDR_INIT + if (dram_regions_info.total_dram_size <= 0) { + ERROR("Asserting as the DDR is not initialized yet."); + assert(false); + } +#endif + + if ((dram_regions_info.region[0].addr == 0) + && (dram_regions_info.total_dram_size > 0)) { + populate_dram_regions_info(); +#ifdef PLAT_XLAT_TABLES_DYNAMIC + mmap_add_ddr_region_dynamically(); +#endif + } + + /* setup the memory region access permissions */ + soc_mem_access(); + +#ifdef POLICY_FUSE_PROVISION + fip_fuse_provisioning((uintptr_t)FUSE_BUF, FUSE_SZ); +#endif +} diff --git a/plat/nxp/common/setup/ls_bl31_setup.c b/plat/nxp/common/setup/ls_bl31_setup.c new file mode 100644 index 0000000..bd0ab4f --- /dev/null +++ b/plat/nxp/common/setup/ls_bl31_setup.c @@ -0,0 +1,212 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <assert.h> +#include <inttypes.h> +#include <stdint.h> + +#ifdef LS_EL3_INTERRUPT_HANDLER +#include <ls_interrupt_mgmt.h> +#endif +#include <mmu_def.h> +#include <plat_common.h> + +/* + * Placeholder variables for copying the arguments that have been passed to + * BL31 from BL2. + */ +#ifdef TEST_BL31 +#define SPSR_FOR_EL2H 0x3C9 +#define SPSR_FOR_EL1H 0x3C5 +#else +static entry_point_info_t bl31_image_ep_info; +#endif + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +static dram_regions_info_t dram_regions_info = {0}; +static uint64_t rcw_porsr1; + +/* Return the pointer to the 'dram_regions_info structure of the DRAM. + * This structure is populated after init_ddr(). + */ +dram_regions_info_t *get_dram_regions_info(void) +{ + return &dram_regions_info; +} + +/* Return the RCW.PORSR1 value which was passed in from BL2 + */ +uint64_t bl31_get_porsr1(void) +{ + return rcw_porsr1; +} + +/* + * Return pointer to the 'entry_point_info' structure of the next image for the + * security state specified: + * - BL33 corresponds to the non-secure image type; while + * - BL32 corresponds to the secure image type. + * - A NULL pointer is returned, if the image does not exist. + */ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(sec_state_is_valid(type)); + next_image_info = (type == NON_SECURE) + ? &bl33_image_ep_info : &bl32_image_ep_info; + +#ifdef TEST_BL31 + next_image_info->pc = _get_test_entry(); + next_image_info->spsr = SPSR_FOR_EL2H; + next_image_info->h.attr = NON_SECURE; +#endif + + if (next_image_info->pc != 0U) { + return next_image_info; + } else { + return NULL; + } +} + +/* + * Perform any BL31 early platform setup common to NXP platforms. + * - Here is an opportunity to copy parameters passed by the calling EL (S-EL1 + * in BL2 & S-EL3 in BL1) before they are lost (potentially). + * - This needs to be done before the MMU is initialized so that the + * memory layout can be used while creating page tables. + * - BL2 has flushed this information to memory, in order to fetch latest data. + */ + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ +#ifndef TEST_BL31 + int i = 0; + void *from_bl2 = (void *)arg0; +#endif + soc_early_platform_setup2(); + +#ifdef TEST_BL31 + dram_regions_info.num_dram_regions = 2; + dram_regions_info.total_dram_size = 0x100000000; + dram_regions_info.region[0].addr = 0x80000000; + dram_regions_info.region[0].size = 0x80000000; + dram_regions_info.region[1].addr = 0x880000000; + dram_regions_info.region[1].size = 0x80000000; + + bl33_image_ep_info.pc = _get_test_entry(); +#else + /* + * Check params passed from BL2 should not be NULL, + */ + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33 and BL32 (if present), entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params != NULL) { + if (bl_params->image_id == BL31_IMAGE_ID) { + bl31_image_ep_info = *bl_params->ep_info; + dram_regions_info_t *loc_dram_regions_info = + (dram_regions_info_t *) bl31_image_ep_info.args.arg3; + + dram_regions_info.num_dram_regions = + loc_dram_regions_info->num_dram_regions; + dram_regions_info.total_dram_size = + loc_dram_regions_info->total_dram_size; + VERBOSE("Number of DRAM Regions = %" PRIx64 "\n", + dram_regions_info.num_dram_regions); + + for (i = 0; i < dram_regions_info.num_dram_regions; + i++) { + dram_regions_info.region[i].addr = + loc_dram_regions_info->region[i].addr; + dram_regions_info.region[i].size = + loc_dram_regions_info->region[i].size; + VERBOSE("DRAM%d Size = %" PRIx64 "\n", i, + dram_regions_info.region[i].size); + } + rcw_porsr1 = bl31_image_ep_info.args.arg4; + } + + if (bl_params->image_id == BL32_IMAGE_ID) { + bl32_image_ep_info = *bl_params->ep_info; + } + + if (bl_params->image_id == BL33_IMAGE_ID) { + bl33_image_ep_info = *bl_params->ep_info; + } + + bl_params = bl_params->next_params_info; + } +#endif /* TEST_BL31 */ + + if (bl33_image_ep_info.pc == 0) { + panic(); + } + + /* + * perform basic initialization on the soc + */ + soc_init(); +} + +/******************************************************************************* + * Perform any BL31 platform setup common to ARM standard platforms + ******************************************************************************/ +void bl31_platform_setup(void) +{ + NOTICE("Welcome to %s BL31 Phase\n", BOARD); + soc_platform_setup(); + + /* Console logs gone missing as part going to + * EL1 for initilizing Bl32 if present. + * console flush is necessary to avoid it. + */ + (void)console_flush(); +} + +void bl31_plat_runtime_setup(void) +{ +#ifdef LS_EL3_INTERRUPT_HANDLER + ls_el3_interrupt_config(); +#endif + soc_runtime_setup(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup shared between + * ARM standard platforms. This only does basic initialization. Later + * architectural setup (bl31_arch_setup()) does not do anything platform + * specific. + ******************************************************************************/ +void bl31_plat_arch_setup(void) +{ + + ls_setup_page_tables(BL31_BASE, + BL31_END - BL31_BASE, + BL_CODE_BASE, + BL_CODE_END, + BL_RO_DATA_BASE, + BL_RO_DATA_END +#if USE_COHERENT_MEM + , BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END +#endif + ); + enable_mmu_el3(0); +} diff --git a/plat/nxp/common/setup/ls_common.c b/plat/nxp/common/setup/ls_common.c new file mode 100644 index 0000000..28d6b72 --- /dev/null +++ b/plat/nxp/common/setup/ls_common.c @@ -0,0 +1,277 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <assert.h> + +#include <arch.h> +#include <arch_helpers.h> +#include <common/debug.h> +#include <lib/mmio.h> +#include <lib/xlat_tables/xlat_tables_v2.h> +#include <mmu_def.h> +#include <plat/common/platform.h> + +#include "plat_common.h" +#include "platform_def.h" + +const mmap_region_t *plat_ls_get_mmap(void); + +/* + * Table of memory regions for various BL stages to map using the MMU. + * This doesn't include Trusted SRAM as arm_setup_page_tables() already + * takes care of mapping it. + * + * The flash needs to be mapped as writable in order to erase the FIP's Table of + * Contents in case of unrecoverable error (see plat_error_handler()). + */ +#ifdef IMAGE_BL2 +const mmap_region_t plat_ls_mmap[] = { + LS_MAP_CCSR, + {0} +}; +#endif + +#ifdef IMAGE_BL31 +const mmap_region_t plat_ls_mmap[] = { + LS_MAP_CCSR, +#ifdef NXP_DCSR_ADDR + LS_MAP_DCSR, +#endif + LS_MAP_OCRAM, + {0} +}; +#endif +#ifdef IMAGE_BL32 +const mmap_region_t plat_ls_mmap[] = { + LS_MAP_CCSR, + LS_MAP_BL32_SEC_MEM, + {0} +}; +#endif + +/* Weak definitions may be overridden in specific NXP SoC */ +#pragma weak plat_get_ns_image_entrypoint +#pragma weak plat_ls_get_mmap + +#if defined(IMAGE_BL31) || !defined(CONFIG_DDR_FIP_IMAGE) +static void mmap_add_ddr_regions_statically(void) +{ + int i = 0; + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); + /* MMU map for Non-Secure DRAM Regions */ + VERBOSE("DRAM Region %d: %p - %p\n", i, + (void *) info_dram_regions->region[i].addr, + (void *) (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size + - 1)); + mmap_add_region(info_dram_regions->region[i].addr, + info_dram_regions->region[i].addr, + info_dram_regions->region[i].size, + MT_MEMORY | MT_RW | MT_NS); + + /* MMU map for Secure DDR Region on DRAM-0 */ + if (info_dram_regions->region[i].size > + (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE)) { + VERBOSE("Secure DRAM Region %d: %p - %p\n", i, + (void *) (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size), + (void *) (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size + + NXP_SECURE_DRAM_SIZE + + NXP_SP_SHRD_DRAM_SIZE + - 1)); + mmap_add_region((info_dram_regions->region[i].addr + + info_dram_regions->region[i].size), + (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size), + (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE), + MT_MEMORY | MT_RW | MT_SECURE); + } + +#ifdef IMAGE_BL31 + for (i = 1; i < info_dram_regions->num_dram_regions; i++) { + if (info_dram_regions->region[i].size == 0) + break; + VERBOSE("DRAM Region %d: %p - %p\n", i, + (void *) info_dram_regions->region[i].addr, + (void *) (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size + - 1)); + mmap_add_region(info_dram_regions->region[i].addr, + info_dram_regions->region[i].addr, + info_dram_regions->region[i].size, + MT_MEMORY | MT_RW | MT_NS); + } +#endif +} +#endif + +#if defined(PLAT_XLAT_TABLES_DYNAMIC) +void mmap_add_ddr_region_dynamically(void) +{ + int ret, i = 0; + + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); + /* MMU map for Non-Secure DRAM Regions */ + VERBOSE("DRAM Region %d: %p - %p\n", i, + (void *) info_dram_regions->region[i].addr, + (void *) (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size + - 1)); + ret = mmap_add_dynamic_region(info_dram_regions->region[i].addr, + info_dram_regions->region[i].addr, + info_dram_regions->region[i].size, + MT_MEMORY | MT_RW | MT_NS); + if (ret != 0) { + ERROR("Failed to add dynamic memory region\n"); + panic(); + } + + /* MMU map for Secure DDR Region on DRAM-0 */ + if (info_dram_regions->region[i].size > + (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE)) { + VERBOSE("Secure DRAM Region %d: %p - %p\n", i, + (void *) (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size), + (void *) (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size + + NXP_SECURE_DRAM_SIZE + + NXP_SP_SHRD_DRAM_SIZE + - 1)); + ret = mmap_add_dynamic_region((info_dram_regions->region[i].addr + + info_dram_regions->region[i].size), + (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size), + (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE), + MT_MEMORY | MT_RW | MT_SECURE); + if (ret != 0) { + ERROR("Failed to add dynamic memory region\n"); + panic(); + } + } + +#ifdef IMAGE_BL31 + for (i = 1; i < info_dram_regions->num_dram_regions; i++) { + if (info_dram_regions->region[i].size == 0) { + break; + } + VERBOSE("DRAM Region %d: %p - %p\n", i, + (void *) info_dram_regions->region[i].addr, + (void *) (info_dram_regions->region[i].addr + + info_dram_regions->region[i].size + - 1)); + ret = mmap_add_dynamic_region(info_dram_regions->region[i].addr, + info_dram_regions->region[i].addr, + info_dram_regions->region[i].size, + MT_MEMORY | MT_RW | MT_NS); + if (ret != 0) { + ERROR("Failed to add dynamic memory region\n"); + panic(); + } + } +#endif +} +#endif + +/* + * Set up the page tables for the generic and platform-specific memory regions. + * The extents of the generic memory regions are specified by the function + * arguments and consist of: + * - Trusted SRAM seen by the BL image; + * - Code section; + * - Read-only data section; + * - Coherent memory region, if applicable. + */ +void ls_setup_page_tables(uintptr_t total_base, + size_t total_size, + uintptr_t code_start, + uintptr_t code_limit, + uintptr_t rodata_start, + uintptr_t rodata_limit +#if USE_COHERENT_MEM + , + uintptr_t coh_start, + uintptr_t coh_limit +#endif + ) +{ + /* + * Map the Trusted SRAM with appropriate memory attributes. + * Subsequent mappings will adjust the attributes for specific regions. + */ + VERBOSE("Memory seen by this BL image: %p - %p\n", + (void *) total_base, (void *) (total_base + total_size)); + mmap_add_region(total_base, total_base, + total_size, + MT_MEMORY | MT_RW | MT_SECURE); + + /* Re-map the code section */ + VERBOSE("Code region: %p - %p\n", + (void *) code_start, (void *) code_limit); + mmap_add_region(code_start, code_start, + code_limit - code_start, + MT_CODE | MT_SECURE); + + /* Re-map the read-only data section */ + VERBOSE("Read-only data region: %p - %p\n", + (void *) rodata_start, (void *) rodata_limit); + mmap_add_region(rodata_start, rodata_start, + rodata_limit - rodata_start, + MT_RO_DATA | MT_SECURE); + +#if USE_COHERENT_MEM + /* Re-map the coherent memory region */ + VERBOSE("Coherent region: %p - %p\n", + (void *) coh_start, (void *) coh_limit); + mmap_add_region(coh_start, coh_start, + coh_limit - coh_start, + MT_DEVICE | MT_RW | MT_SECURE); +#endif + + /* Now (re-)map the platform-specific memory regions */ + mmap_add(plat_ls_get_mmap()); + + +#if defined(IMAGE_BL31) || !defined(CONFIG_DDR_FIP_IMAGE) + mmap_add_ddr_regions_statically(); +#endif + + /* Create the page tables to reflect the above mappings */ + init_xlat_tables(); +} + +/******************************************************************************* + * Returns NXP platform specific memory map regions. + ******************************************************************************/ +const mmap_region_t *plat_ls_get_mmap(void) +{ + return plat_ls_mmap; +} + +/* + * This function get the number of clusters and cores count per cluster + * in the SoC. + */ +void get_cluster_info(const struct soc_type *soc_list, uint8_t ps_count, + uint8_t *num_clusters, uint8_t *cores_per_cluster) +{ + const soc_info_t *soc_info = get_soc_info(); + *num_clusters = NUMBER_OF_CLUSTERS; + *cores_per_cluster = CORES_PER_CLUSTER; + unsigned int i; + + for (i = 0U; i < ps_count; i++) { + if (soc_list[i].version == soc_info->svr_reg.bf_ver.version) { + *num_clusters = soc_list[i].num_clusters; + *cores_per_cluster = soc_list[i].cores_per_cluster; + break; + } + } + + VERBOSE("NUM of cluster = 0x%x, Cores per cluster = 0x%x\n", + *num_clusters, *cores_per_cluster); +} diff --git a/plat/nxp/common/setup/ls_err.c b/plat/nxp/common/setup/ls_err.c new file mode 100644 index 0000000..845cd15 --- /dev/null +++ b/plat/nxp/common/setup/ls_err.c @@ -0,0 +1,55 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <errno.h> +#include <stdbool.h> +#include <stdint.h> + +#include <arch_helpers.h> +#include <common/debug.h> + +#if TRUSTED_BOARD_BOOT +#include <dcfg.h> +#include <snvs.h> +#endif + +#include "plat_common.h" + +/* + * Error handler + */ +void plat_error_handler(int err) +{ +#if TRUSTED_BOARD_BOOT + uint32_t mode; + bool sb = check_boot_mode_secure(&mode); +#endif + + switch (err) { + case -ENOENT: + case -EAUTH: + printf("Authentication failure\n"); +#if TRUSTED_BOARD_BOOT + /* For SB production mode i.e ITS = 1 */ + if (sb == true) { + if (mode == 1U) { + transition_snvs_soft_fail(); + } else { + transition_snvs_non_secure(); + } + } +#endif + break; + default: + /* Unexpected error */ + break; + } + + /* Loop until the watchdog resets the system */ + for (;;) + wfi(); +} diff --git a/plat/nxp/common/setup/ls_image_load.c b/plat/nxp/common/setup/ls_image_load.c new file mode 100644 index 0000000..259ab31 --- /dev/null +++ b/plat/nxp/common/setup/ls_image_load.c @@ -0,0 +1,33 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <common/desc_image_load.h> + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +bl_load_info_t *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + return get_next_bl_params_from_mem_params_desc(); +} diff --git a/plat/nxp/common/setup/ls_interrupt_mgmt.c b/plat/nxp/common/setup/ls_interrupt_mgmt.c new file mode 100644 index 0000000..a81cb2b --- /dev/null +++ b/plat/nxp/common/setup/ls_interrupt_mgmt.c @@ -0,0 +1,66 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <bl31/interrupt_mgmt.h> +#include <common/debug.h> +#include <ls_interrupt_mgmt.h> +#include <plat/common/platform.h> + +static interrupt_type_handler_t type_el3_interrupt_table[MAX_INTR_EL3]; + +int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler) +{ + /* Validate 'handler' and 'id' parameters */ + if (!handler || id >= MAX_INTR_EL3) { + return -EINVAL; + } + + /* Check if a handler has already been registered */ + if (type_el3_interrupt_table[id] != NULL) { + return -EALREADY; + } + + type_el3_interrupt_table[id] = handler; + + return 0; +} + +static uint64_t ls_el3_interrupt_handler(uint32_t id, uint32_t flags, + void *handle, void *cookie) +{ + uint32_t intr_id; + interrupt_type_handler_t handler; + + intr_id = plat_ic_get_pending_interrupt_id(); + + INFO("Interrupt recvd is %d\n", intr_id); + + handler = type_el3_interrupt_table[intr_id]; + if (handler != NULL) { + handler(intr_id, flags, handle, cookie); + } + + /* + * Mark this interrupt as complete to avoid a interrupt storm. + */ + plat_ic_end_of_interrupt(intr_id); + + return 0U; +} + +void ls_el3_interrupt_config(void) +{ + uint64_t flags = 0U; + uint64_t rc; + + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_EL3, + ls_el3_interrupt_handler, flags); + if (rc != 0U) { + panic(); + } +} diff --git a/plat/nxp/common/setup/ls_io_storage.c b/plat/nxp/common/setup/ls_io_storage.c new file mode 100644 index 0000000..7f01e72 --- /dev/null +++ b/plat/nxp/common/setup/ls_io_storage.c @@ -0,0 +1,556 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <assert.h> +#include <endian.h> +#include <string.h> + +#include <common/debug.h> +#include <common/tbbr/tbbr_img_def.h> +#include <drivers/io/io_block.h> +#include <drivers/io/io_driver.h> +#include <drivers/io/io_fip.h> +#include <drivers/io/io_memmap.h> +#include <drivers/io/io_storage.h> +#ifdef FLEXSPI_NOR_BOOT +#include <flexspi_nor.h> +#endif +#if defined(NAND_BOOT) +#include <ifc_nand.h> +#endif +#if defined(NOR_BOOT) +#include <ifc_nor.h> +#endif +#if defined(QSPI_BOOT) +#include <qspi.h> +#endif +#if defined(SD_BOOT) || defined(EMMC_BOOT) +#include <sd_mmc.h> +#endif +#include <tools_share/firmware_image_package.h> + +#ifdef CONFIG_DDR_FIP_IMAGE +#include <ddr_io_storage.h> +#endif +#ifdef POLICY_FUSE_PROVISION +#include <fuse_io.h> +#endif +#include "plat_common.h" +#include "platform_def.h" + +uint32_t fip_device; +/* IO devices */ +uintptr_t backend_dev_handle; + +static const io_dev_connector_t *fip_dev_con; +static uintptr_t fip_dev_handle; +static const io_dev_connector_t *backend_dev_con; + +static io_block_spec_t fip_block_spec = { + .offset = PLAT_FIP_OFFSET, + .length = PLAT_FIP_MAX_SIZE +}; + +static const io_uuid_spec_t bl2_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, +}; + +static const io_uuid_spec_t fuse_bl2_uuid_spec = { + .uuid = UUID_SCP_FIRMWARE_SCP_BL2, +}; + +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t bl32_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +static const io_uuid_spec_t tb_fw_config_uuid_spec = { + .uuid = UUID_TB_FW_CONFIG, +}; + +static const io_uuid_spec_t hw_config_uuid_spec = { + .uuid = UUID_HW_CONFIG, +}; + +#if TRUSTED_BOARD_BOOT +static const io_uuid_spec_t tb_fw_cert_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FW_CERT, +}; + +static const io_uuid_spec_t trusted_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_KEY_CERT, +}; + +static const io_uuid_spec_t fuse_key_cert_uuid_spec = { + .uuid = UUID_SCP_FW_KEY_CERT, +}; + +static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = { + .uuid = UUID_SOC_FW_KEY_CERT, +}; + +static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_KEY_CERT, +}; + +static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_KEY_CERT, +}; + +static const io_uuid_spec_t fuse_cert_uuid_spec = { + .uuid = UUID_SCP_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t soc_fw_cert_uuid_spec = { + .uuid = UUID_SOC_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t tos_fw_cert_uuid_spec = { + .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t nt_fw_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT, +}; +#endif /* TRUSTED_BOARD_BOOT */ + +static int open_fip(const uintptr_t spec); + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +/* By default, ARM platforms load images from the FIP */ +static const struct plat_io_policy policies[] = { + [FIP_IMAGE_ID] = { + &backend_dev_handle, + (uintptr_t)&fip_block_spec, + open_backend + }, + [BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl2_uuid_spec, + open_fip + }, + [SCP_BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&fuse_bl2_uuid_spec, + open_fip + }, + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_uuid_spec, + open_fip + }, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_uuid_spec, + open_fip + }, + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_uuid_spec, + open_fip + }, + [TB_FW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&tb_fw_config_uuid_spec, + open_fip + }, + [HW_CONFIG_ID] = { + &fip_dev_handle, + (uintptr_t)&hw_config_uuid_spec, + open_fip + }, +#if TRUSTED_BOARD_BOOT + [TRUSTED_BOOT_FW_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tb_fw_cert_uuid_spec, + open_fip + }, + [TRUSTED_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&trusted_key_cert_uuid_spec, + open_fip + }, + [SCP_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&fuse_key_cert_uuid_spec, + open_fip + }, + [SOC_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_key_cert_uuid_spec, + open_fip + }, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_key_cert_uuid_spec, + open_fip + }, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_key_cert_uuid_spec, + open_fip + }, + [SCP_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&fuse_cert_uuid_spec, + open_fip + }, + [SOC_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&soc_fw_cert_uuid_spec, + open_fip + }, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&tos_fw_cert_uuid_spec, + open_fip + }, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&nt_fw_cert_uuid_spec, + open_fip + }, +#endif /* TRUSTED_BOARD_BOOT */ +}; + + +/* Weak definitions may be overridden in specific ARM standard platform */ +#pragma weak plat_io_setup + +/* + * Return an IO device handle and specification which can be used to access + */ +static int open_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + + +int open_backend(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + result = io_dev_init(backend_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(backend_dev_handle, spec, &local_image_handle); + if (result == 0) { + io_close(local_image_handle); + } + } + return result; +} + +#if defined(SD_BOOT) || defined(EMMC_BOOT) || defined(NAND_BOOT) +static int plat_io_block_setup(size_t fip_offset, uintptr_t block_dev_spec) +{ + int io_result; + + fip_block_spec.offset = fip_offset; + + io_result = register_io_dev_block(&backend_dev_con); + assert(io_result == 0); + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(backend_dev_con, block_dev_spec, + &backend_dev_handle); + assert(io_result == 0); + + return io_result; +} +#endif + +#if defined(FLEXSPI_NOR_BOOT) || defined(QSPI_BOOT) || defined(NOR_BOOT) +static int plat_io_memmap_setup(size_t fip_offset) +{ + int io_result; + + fip_block_spec.offset = fip_offset; + + io_result = register_io_dev_memmap(&backend_dev_con); + assert(io_result == 0); + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(backend_dev_con, (uintptr_t)NULL, + &backend_dev_handle); + assert(io_result == 0); + + return io_result; +} +#endif + +static int ls_io_fip_setup(unsigned int boot_dev) +{ + int io_result; + + io_result = register_io_dev_fip(&fip_dev_con); + assert(io_result == 0); + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(fip_dev_con, (uintptr_t)&fip_device, + &fip_dev_handle); + assert(io_result == 0); + +#ifdef CONFIG_DDR_FIP_IMAGE + /* Open connection to DDR FIP image if available */ + io_result = ddr_fip_setup(fip_dev_con, boot_dev); + + assert(io_result == 0); +#endif + +#ifdef POLICY_FUSE_PROVISION + /* Open connection to FUSE FIP image if available */ + io_result = fuse_fip_setup(fip_dev_con, boot_dev); + + assert(io_result == 0); +#endif + + return io_result; +} + +int ls_qspi_io_setup(void) +{ +#ifdef QSPI_BOOT + qspi_io_setup(NXP_QSPI_FLASH_ADDR, + NXP_QSPI_FLASH_SIZE, + PLAT_FIP_OFFSET); + return plat_io_memmap_setup(NXP_QSPI_FLASH_ADDR + PLAT_FIP_OFFSET); +#else + ERROR("QSPI driver not present. Check your BUILD\n"); + + /* Should never reach here */ + assert(false); + return -1; +#endif +} + +int emmc_sdhc2_io_setup(void) +{ +#if defined(EMMC_BOOT) && defined(NXP_ESDHC2_ADDR) + uintptr_t block_dev_spec; + int ret; + + ret = sd_emmc_init(&block_dev_spec, + NXP_ESDHC2_ADDR, + NXP_SD_BLOCK_BUF_ADDR, + NXP_SD_BLOCK_BUF_SIZE, + false); + if (ret != 0) { + return ret; + } + + return plat_io_block_setup(PLAT_FIP_OFFSET, block_dev_spec); +#else + ERROR("EMMC driver not present. Check your BUILD\n"); + + /* Should never reach here */ + assert(false); + return -1; +#endif +} + +int emmc_io_setup(void) +{ +/* On the platforms which only has one ESDHC controller, + * eMMC-boot will use the first ESDHC controller. + */ +#if defined(SD_BOOT) || defined(EMMC_BOOT) + uintptr_t block_dev_spec; + int ret; + + ret = sd_emmc_init(&block_dev_spec, + NXP_ESDHC_ADDR, + NXP_SD_BLOCK_BUF_ADDR, + NXP_SD_BLOCK_BUF_SIZE, + true); + if (ret != 0) { + return ret; + } + + return plat_io_block_setup(PLAT_FIP_OFFSET, block_dev_spec); +#else + ERROR("SD driver not present. Check your BUILD\n"); + + /* Should never reach here */ + assert(false); + return -1; +#endif +} + +int ifc_nor_io_setup(void) +{ +#if defined(NOR_BOOT) + int ret; + + ret = ifc_nor_init(NXP_NOR_FLASH_ADDR, + NXP_NOR_FLASH_SIZE); + + if (ret != 0) { + return ret; + } + + return plat_io_memmap_setup(NXP_NOR_FLASH_ADDR + PLAT_FIP_OFFSET); +#else + ERROR("NOR driver not present. Check your BUILD\n"); + + /* Should never reach here */ + assert(false); + return -1; +#endif +} + +int ifc_nand_io_setup(void) +{ +#if defined(NAND_BOOT) + uintptr_t block_dev_spec; + int ret; + + ret = ifc_nand_init(&block_dev_spec, + NXP_IFC_REGION_ADDR, + NXP_IFC_ADDR, + NXP_IFC_SRAM_BUFFER_SIZE, + NXP_SD_BLOCK_BUF_ADDR, + NXP_SD_BLOCK_BUF_SIZE); + if (ret != 0) { + return ret; + } + + return plat_io_block_setup(PLAT_FIP_OFFSET, block_dev_spec); +#else + + ERROR("NAND driver not present. Check your BUILD\n"); + + /* Should never reach here */ + assert(false); + return -1; +#endif +} + +int ls_flexspi_nor_io_setup(void) +{ +#ifdef FLEXSPI_NOR_BOOT + int ret = 0; + + ret = flexspi_nor_io_setup(NXP_FLEXSPI_FLASH_ADDR, + NXP_FLEXSPI_FLASH_SIZE, + NXP_FLEXSPI_ADDR); + + if (ret != 0) { + ERROR("FlexSPI NOR driver initialization error.\n"); + /* Should never reach here */ + assert(0); + panic(); + return -1; + } + + return plat_io_memmap_setup(NXP_FLEXSPI_FLASH_ADDR + PLAT_FIP_OFFSET); +#else + ERROR("FlexSPI NOR driver not present. Check your BUILD\n"); + + /* Should never reach here */ + assert(false); + return -1; +#endif +} + +static int (* const ls_io_setup_table[])(void) = { + [BOOT_DEVICE_IFC_NOR] = ifc_nor_io_setup, + [BOOT_DEVICE_IFC_NAND] = ifc_nand_io_setup, + [BOOT_DEVICE_QSPI] = ls_qspi_io_setup, + [BOOT_DEVICE_EMMC] = emmc_io_setup, + [BOOT_DEVICE_SDHC2_EMMC] = emmc_sdhc2_io_setup, + [BOOT_DEVICE_FLEXSPI_NOR] = ls_flexspi_nor_io_setup, + [BOOT_DEVICE_FLEXSPI_NAND] = ls_flexspi_nor_io_setup, +}; + + +int plat_io_setup(void) +{ + int (*io_setup)(void); + unsigned int boot_dev = BOOT_DEVICE_NONE; + int ret; + + boot_dev = get_boot_dev(); + if (boot_dev == BOOT_DEVICE_NONE) { + ERROR("Boot Device detection failed, Check RCW_SRC\n"); + return -EINVAL; + } + + io_setup = ls_io_setup_table[boot_dev]; + ret = io_setup(); + if (ret != 0) { + return ret; + } + + ret = ls_io_fip_setup(boot_dev); + if (ret != 0) { + return ret; + } + + return 0; +} + + +/* Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy + */ +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result = -1; + const struct plat_io_policy *policy; + + if (image_id < ARRAY_SIZE(policies)) { + + policy = &policies[image_id]; + result = policy->check(policy->image_spec); + if (result == 0) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + } + } +#ifdef CONFIG_DDR_FIP_IMAGE + else { + VERBOSE("Trying alternative IO\n"); + result = plat_get_ddr_fip_image_source(image_id, dev_handle, + image_spec, open_backend); + } +#endif +#ifdef POLICY_FUSE_PROVISION + if (result != 0) { + VERBOSE("Trying FUSE IO\n"); + result = plat_get_fuse_image_source(image_id, dev_handle, + image_spec, open_backend); + } +#endif + + return result; +} diff --git a/plat/nxp/common/setup/ls_stack_protector.c b/plat/nxp/common/setup/ls_stack_protector.c new file mode 100644 index 0000000..ab78f88 --- /dev/null +++ b/plat/nxp/common/setup/ls_stack_protector.c @@ -0,0 +1,22 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <stdint.h> + +#include <arch_helpers.h> + +#include <plat/common/platform.h> + +#define RANDOM_CANARY_VALUE ((u_register_t) 3288484550995823360ULL) + +u_register_t plat_get_stack_protector_canary(void) +{ + /* + * TBD: Generate Random Number from NXP CAAM Block. + */ + return RANDOM_CANARY_VALUE ^ read_cntpct_el0(); +} diff --git a/plat/nxp/common/sip_svc/aarch64/sipsvc.S b/plat/nxp/common/sip_svc/aarch64/sipsvc.S new file mode 100644 index 0000000..6a47cbf --- /dev/null +++ b/plat/nxp/common/sip_svc/aarch64/sipsvc.S @@ -0,0 +1,152 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <asm_macros.S> +#include <bl31_data.h> + +.global el2_2_aarch32 +.global prefetch_disable + +#define SPSR_EL3_M4 0x10 +#define SPSR_EL_MASK 0xC +#define SPSR_EL2 0x8 +#define SCR_EL3_4_EL2_AARCH32 0x131 +#define SPSR32_EL2_LE 0x1DA + +#define MIDR_PARTNUM_START 4 +#define MIDR_PARTNUM_WIDTH 12 +#define MIDR_PARTNUM_A53 0xD03 +#define MIDR_PARTNUM_A57 0xD07 +#define MIDR_PARTNUM_A72 0xD08 + +/* + * uint64_t el2_2_aarch32(u_register_t smc_id, + * u_register_t start_addr, + * u_register_t parm1, + * u_register_t parm2) + * this function allows changing the execution width of EL2 from Aarch64 + * to Aarch32 + * Note: MUST be called from EL2 @ Aarch64 + * in: x0 = smc function id + * x1 = start address for EL2 @ Aarch32 + * x2 = first parameter to pass to EL2 @ Aarch32 + * x3 = second parameter to pass to EL2 @ Aarch32 + * out: x0 = 0, on success + * x0 = -1, on failure + * uses x0, x1, x2, x3 + */ +func el2_2_aarch32 + + /* check that caller is EL2 @ Aarch64 - err return if not */ + mrs x0, spsr_el3 + /* see if we were called from Aarch32 */ + tst x0, #SPSR_EL3_M4 + b.ne 2f + + /* see if we were called from EL2 */ + and x0, x0, SPSR_EL_MASK + cmp x0, SPSR_EL2 + b.ne 2f + + /* set ELR_EL3 */ + msr elr_el3, x1 + + /* set scr_el3 */ + mov x0, #SCR_EL3_4_EL2_AARCH32 + msr scr_el3, x0 + + /* set sctlr_el2 */ + ldr x1, =SCTLR_EL2_RES1 + msr sctlr_el2, x1 + + /* set spsr_el3 */ + ldr x0, =SPSR32_EL2_LE + msr spsr_el3, x0 + + /* x2 = parm 1 + * x3 = parm2 + */ + + /* set the parameters to be passed-thru to EL2 @ Aarch32 */ + mov x1, x2 + mov x2, x3 + + /* x1 = parm 1 + * x2 = parm2 + */ + + mov x0, xzr + /* invalidate the icache */ + ic iallu + dsb sy + isb + b 1f +2: + /* error return */ + mvn x0, xzr + ret +1: + eret +endfunc el2_2_aarch32 + +/* + * int prefetch_disable(u_register_t smc_id, u_register_t mask) + * this function marks cores which need to have the prefetch disabled - + * secondary cores have prefetch disabled when they are released from reset - + * the bootcore has prefetch disabled when this call is made + * in: x0 = function id + * x1 = core mask, where bit[0]=core0, bit[1]=core1, etc + * if a bit in the mask is set, then prefetch is disabled for that + * core + * out: x0 = SMC_SUCCESS + */ +func prefetch_disable + stp x4, x30, [sp, #-16]! + + mov x3, x1 + + /* x1 = core prefetch disable mask */ + /* x3 = core prefetch disable mask */ + + /* store the mask */ + mov x0, #PREFETCH_DIS_OFFSET + bl _set_global_data + + /* x3 = core prefetch disable mask */ + + /* see if we need to disable prefetch on THIS core */ + bl plat_my_core_mask + + /* x0 = core mask lsb */ + /* x3 = core prefetch disable mask */ + + tst x3, x0 + b.eq 1f + + /* read midr_el1 */ + mrs x1, midr_el1 + + /* x1 = midr_el1 */ + + mov x0, xzr + bfxil x0, x1, #MIDR_PARTNUM_START, #MIDR_PARTNUM_WIDTH + + /* x0 = part number (a53, a57, a72, etc) */ + + /* branch on cpu-specific */ + cmp x0, #MIDR_PARTNUM_A57 + b.eq 1f + cmp x0, #MIDR_PARTNUM_A72 + b.ne 1f + + bl _disable_ldstr_pfetch_A72 + b 1f +1: + ldp x4, x30, [sp], #16 + mov x0, xzr + ret +endfunc prefetch_disable diff --git a/plat/nxp/common/sip_svc/include/sipsvc.h b/plat/nxp/common/sip_svc/include/sipsvc.h new file mode 100644 index 0000000..d9e61e9 --- /dev/null +++ b/plat/nxp/common/sip_svc/include/sipsvc.h @@ -0,0 +1,80 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SIPSVC_H +#define SIPSVC_H + +#include <stdint.h> + +#define SMC_FUNC_MASK 0x0000ffff +#define SMC32_PARAM_MASK 0xffffffff + +/* SMC function IDs for SiP Service queries */ +#define SIP_SVC_CALL_COUNT 0xff00 +#define SIP_SVC_UID 0xff01 +#define SIP_SVC_VERSION 0xff03 +#define SIP_SVC_PRNG 0xff10 +#define SIP_SVC_RNG 0xff11 +#define SIP_SVC_MEM_BANK 0xff12 +#define SIP_SVC_PREFETCH_DIS 0xff13 +#define SIP_SVC_HUK 0xff14 +#define SIP_SVC_ALLOW_L1L2_ERR 0xff15 +#define SIP_SVC_ALLOW_L2_CLR 0xff16 +#define SIP_SVC_2_AARCH32 0xff17 +#define SIP_SVC_PORSR1 0xff18 + +/* Layerscape SiP Service Calls version numbers */ +#define LS_SIP_SVC_VERSION_MAJOR 0x0 +#define LS_SIP_SVC_VERSION_MINOR 0x1 + +/* Number of Layerscape SiP Calls implemented */ +#define LS_COMMON_SIP_NUM_CALLS 10 + +/* Parameter Type Constants */ +#define SIP_PARAM_TYPE_NONE 0x0 +#define SIP_PARAM_TYPE_VALUE_INPUT 0x1 +#define SIP_PARAM_TYPE_VALUE_OUTPUT 0x2 +#define SIP_PARAM_TYPE_VALUE_INOUT 0x3 +#define SIP_PARAM_TYPE_MEMREF_INPUT 0x5 +#define SIP_PARAM_TYPE_MEMREF_OUTPUT 0x6 +#define SIP_PARAM_TYPE_MEMREF_INOUT 0x7 + +#define SIP_PARAM_TYPE_MASK 0xF + +/* + * The macro SIP_PARAM_TYPES can be used to construct a value that you can + * compare against an incoming paramTypes to check the type of all the + * parameters in one comparison. + */ +#define SIP_PARAM_TYPES(t0, t1, t2, t3) \ + ((t0) | ((t1) << 4) | ((t2) << 8) | ((t3) << 12)) + +/* + * The macro SIP_PARAM_TYPE_GET can be used to extract the type of a given + * parameter from paramTypes if you need more fine-grained type checking. + */ +#define SIP_PARAM_TYPE_GET(t, i) ((((uint32_t)(t)) >> ((i) * 4)) & 0xF) + +/* + * The macro SIP_PARAM_TYPE_SET can be used to load the type of a given + * parameter from paramTypes without specifying all types (SIP_PARAM_TYPES) + */ +#define SIP_PARAM_TYPE_SET(t, i) (((uint32_t)(t) & 0xF) << ((i) * 4)) + +#define SIP_SVC_RNG_PARAMS (SIP_PARAM_TYPE_VALUE_INPUT, \ + SIP_PARAM_TYPE_MEMREF_OUTPUT, \ + SIP_PARAM_TYPE_NONE, \ + SIP_PARAM_TYPE_NONE) + +/* Layerscape SiP Calls error code */ +enum { + LS_SIP_SUCCESS = 0, + LS_SIP_INVALID_PARAM = -1, + LS_SIP_NOT_SUPPORTED = -2, +}; + +#endif /* SIPSVC_H */ diff --git a/plat/nxp/common/sip_svc/sip_svc.c b/plat/nxp/common/sip_svc/sip_svc.c new file mode 100644 index 0000000..1c8668e --- /dev/null +++ b/plat/nxp/common/sip_svc/sip_svc.c @@ -0,0 +1,194 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <assert.h> +#include <string.h> + +#include <caam.h> +#include <common/runtime_svc.h> +#include <dcfg.h> +#include <lib/mmio.h> +#include <tools_share/uuid.h> + +#include <plat_common.h> +#include <sipsvc.h> + +/* Layerscape SiP Service UUID */ +DEFINE_SVC_UUID2(nxp_sip_svc_uid, + 0x871de4ef, 0xedfc, 0x4209, 0xa4, 0x23, + 0x8d, 0x23, 0x75, 0x9d, 0x3b, 0x9f); + +#pragma weak nxp_plat_sip_handler +static uintptr_t nxp_plat_sip_handler(unsigned int smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); +} + +uint64_t el2_2_aarch32(u_register_t smc_id, u_register_t start_addr, + u_register_t parm1, u_register_t parm2); + +uint64_t prefetch_disable(u_register_t smc_id, u_register_t mask); +uint64_t bl31_get_porsr1(void); + +static void clean_top_32b_of_param(uint32_t smc_fid, + u_register_t *px1, + u_register_t *px2, + u_register_t *px3, + u_register_t *px4) +{ + /* if parameters from SMC32. Clean top 32 bits */ + if (GET_SMC_CC(smc_fid) == SMC_32) { + *px1 = *px1 & SMC32_PARAM_MASK; + *px2 = *px2 & SMC32_PARAM_MASK; + *px3 = *px3 & SMC32_PARAM_MASK; + *px4 = *px4 & SMC32_PARAM_MASK; + } +} + +/* This function handles Layerscape defined SiP Calls */ +static uintptr_t nxp_sip_handler(unsigned int smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + uint32_t ns; + uint64_t ret; + dram_regions_info_t *info_dram_regions; + + /* if parameter is sent from SMC32. Clean top 32 bits */ + clean_top_32b_of_param(smc_fid, &x1, &x2, &x3, &x4); + + /* Determine which security state this SMC originated from */ + ns = is_caller_non_secure(flags); + if (ns == 0) { + /* SiP SMC service secure world's call */ + ; + } else { + /* SiP SMC service normal world's call */ + ; + } + + switch (smc_fid & SMC_FUNC_MASK) { + case SIP_SVC_RNG: + if (is_sec_enabled() == false) { + NOTICE("SEC is disabled.\n"); + SMC_RET1(handle, SMC_UNK); + } + + /* Return zero on failure */ + ret = get_random((int)x1); + if (ret != 0) { + SMC_RET2(handle, SMC_OK, ret); + } else { + SMC_RET1(handle, SMC_UNK); + } + /* break is not required as SMC_RETx return */ + case SIP_SVC_HUK: + if (is_sec_enabled() == false) { + NOTICE("SEC is disabled.\n"); + SMC_RET1(handle, SMC_UNK); + } + ret = get_hw_unq_key_blob_hw((uint8_t *) x1, (uint32_t) x2); + + if (ret == SMC_OK) { + SMC_RET1(handle, SMC_OK); + } else { + SMC_RET1(handle, SMC_UNK); + } + /* break is not required as SMC_RETx return */ + case SIP_SVC_MEM_BANK: + VERBOSE("Handling SMC SIP_SVC_MEM_BANK.\n"); + info_dram_regions = get_dram_regions_info(); + + if (x1 == -1) { + SMC_RET2(handle, SMC_OK, + info_dram_regions->total_dram_size); + } else if (x1 >= info_dram_regions->num_dram_regions) { + SMC_RET1(handle, SMC_UNK); + } else { + SMC_RET3(handle, SMC_OK, + info_dram_regions->region[x1].addr, + info_dram_regions->region[x1].size); + } + /* break is not required as SMC_RETx return */ + case SIP_SVC_PREFETCH_DIS: + VERBOSE("In SIP_SVC_PREFETCH_DIS call\n"); + ret = prefetch_disable(smc_fid, x1); + if (ret == SMC_OK) { + SMC_RET1(handle, SMC_OK); + } else { + SMC_RET1(handle, SMC_UNK); + } + /* break is not required as SMC_RETx return */ + case SIP_SVC_2_AARCH32: + ret = el2_2_aarch32(smc_fid, x1, x2, x3); + + /* In success case, control should not reach here. */ + NOTICE("SMC: SIP_SVC_2_AARCH32 Failed.\n"); + SMC_RET1(handle, SMC_UNK); + /* break is not required as SMC_RETx return */ + case SIP_SVC_PORSR1: + ret = bl31_get_porsr1(); + SMC_RET2(handle, SMC_OK, ret); + /* break is not required as SMC_RETx return */ + default: + return nxp_plat_sip_handler(smc_fid, x1, x2, x3, x4, + cookie, handle, flags); + } +} + +/* This function is responsible for handling all SiP calls */ +static uintptr_t sip_smc_handler(unsigned int smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + switch (smc_fid & SMC_FUNC_MASK) { + case SIP_SVC_CALL_COUNT: + /* Return the number of Layerscape SiP Service Calls. */ + SMC_RET1(handle, LS_COMMON_SIP_NUM_CALLS); + break; + case SIP_SVC_UID: + /* Return UID to the caller */ + SMC_UUID_RET(handle, nxp_sip_svc_uid); + break; + case SIP_SVC_VERSION: + /* Return the version of current implementation */ + SMC_RET2(handle, LS_SIP_SVC_VERSION_MAJOR, + LS_SIP_SVC_VERSION_MINOR); + break; + default: + return nxp_sip_handler(smc_fid, x1, x2, x3, x4, + cookie, handle, flags); + } +} + +/* Define a runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + nxp_sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + NULL, + sip_smc_handler +); diff --git a/plat/nxp/common/sip_svc/sipsvc.mk b/plat/nxp/common/sip_svc/sipsvc.mk new file mode 100644 index 0000000..c3a57de --- /dev/null +++ b/plat/nxp/common/sip_svc/sipsvc.mk @@ -0,0 +1,35 @@ +# +# Copyright 2018-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# Select the SIP SVC files +# +# ----------------------------------------------------------------------------- + +ifeq (${ADD_SIPSVC},) + +ADD_SIPSVC := 1 + +PLAT_SIPSVC_PATH := $(PLAT_COMMON_PATH)/sip_svc + +SIPSVC_SOURCES := ${PLAT_SIPSVC_PATH}/sip_svc.c \ + ${PLAT_SIPSVC_PATH}/$(ARCH)/sipsvc.S + +PLAT_INCLUDES += -I${PLAT_SIPSVC_PATH}/include + +ifeq (${BL_COMM_SIPSVC_NEEDED},yes) +BL_COMMON_SOURCES += ${SIPSVC_SOURCES} +else +ifeq (${BL2_SIPSVC_NEEDED},yes) +BL2_SOURCES += ${SIPSVC_SOURCES} +endif +ifeq (${BL31_SIPSVC_NEEDED},yes) +BL31_SOURCES += ${SIPSVC_SOURCES} +endif +endif +endif +# ----------------------------------------------------------------------------- diff --git a/plat/nxp/common/soc_errata/errata.c b/plat/nxp/common/soc_errata/errata.c new file mode 100644 index 0000000..55ef604 --- /dev/null +++ b/plat/nxp/common/soc_errata/errata.c @@ -0,0 +1,59 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <common/debug.h> + +#include "errata_list.h" + +void soc_errata(void) +{ +#ifdef ERRATA_SOC_A050426 + INFO("SoC workaround for Errata A050426 was applied\n"); + erratum_a050426(); +#endif +#ifdef ERRATA_SOC_A008850 + INFO("SoC workaround for Errata A008850 Early-Phase was applied\n"); + erratum_a008850_early(); +#endif +#if ERRATA_SOC_A009660 + INFO("SoC workaround for Errata A009660 was applied\n"); + erratum_a009660(); +#endif +#if ERRATA_SOC_A010539 + INFO("SoC workaround for Errata A010539 was applied\n"); + erratum_a010539(); +#endif + + /* + * The following DDR Erratas workaround are implemented in DDR driver, + * but print information here. + */ +#if ERRATA_DDR_A011396 + INFO("SoC workaround for DDR Errata A011396 was applied\n"); +#endif +#if ERRATA_DDR_A050450 + INFO("SoC workaround for DDR Errata A050450 was applied\n"); +#endif +#if ERRATA_DDR_A050958 + INFO("SoC workaround for DDR Errata A050958 was applied\n"); +#endif +#if ERRATA_DDR_A008511 + INFO("SoC workaround for DDR Errata A008511 was applied\n"); +#endif +#if ERRATA_DDR_A009803 + INFO("SoC workaround for DDR Errata A009803 was applied\n"); +#endif +#if ERRATA_DDR_A009942 + INFO("SoC workaround for DDR Errata A009942 was applied\n"); +#endif +#if ERRATA_DDR_A010165 + INFO("SoC workaround for DDR Errata A010165 was applied\n"); +#endif +#if ERRATA_DDR_A009663 + INFO("SoC workaround for DDR Errata A009663 was applied\n"); +#endif +} diff --git a/plat/nxp/common/soc_errata/errata.h b/plat/nxp/common/soc_errata/errata.h new file mode 100644 index 0000000..ab67995 --- /dev/null +++ b/plat/nxp/common/soc_errata/errata.h @@ -0,0 +1,15 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef ERRATA_H +#define ERRATA_H + +#include "errata_list.h" + +void soc_errata(void); + +#endif /* ERRATA_H */ diff --git a/plat/nxp/common/soc_errata/errata.mk b/plat/nxp/common/soc_errata/errata.mk new file mode 100644 index 0000000..3deef3d --- /dev/null +++ b/plat/nxp/common/soc_errata/errata.mk @@ -0,0 +1,26 @@ +# +# Copyright 2021-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Platform Errata Build flags. +# These should be enabled by the platform if the erratum workaround needs to be +# applied. + +ERRATA := \ + ERRATA_SOC_A050426 \ + ERRATA_SOC_A008850 \ + ERRATA_SOC_A009660 \ + ERRATA_SOC_A010539 + +define enable_errata + $(1) ?= 0 + ifeq ($$($(1)),1) + $$(eval $$(call add_define,$(1))) + BL2_SOURCES += $(PLAT_COMMON_PATH)/soc_errata/errata_a$(shell echo $(1)|awk -F '_A' '{print $$NF}').c + endif +endef + +$(foreach e,$(ERRATA),$(eval $(call enable_errata,$(strip $(e))))) + +BL2_SOURCES += $(PLAT_COMMON_PATH)/soc_errata/errata.c diff --git a/plat/nxp/common/soc_errata/errata_a008850.c b/plat/nxp/common/soc_errata/errata_a008850.c new file mode 100644 index 0000000..e8c0f64 --- /dev/null +++ b/plat/nxp/common/soc_errata/errata_a008850.c @@ -0,0 +1,42 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#include <cci.h> +#include <common/debug.h> +#include <ls_interconnect.h> +#include <mmio.h> + +#include <platform_def.h> + +void erratum_a008850_early(void) +{ + /* part 1 of 2 */ + uintptr_t cci_base = NXP_CCI_ADDR; + uint32_t val = mmio_read_32(cci_base + CTRL_OVERRIDE_REG); + + /* enabling forced barrier termination on CCI400 */ + mmio_write_32(cci_base + CTRL_OVERRIDE_REG, + (val | CCI_TERMINATE_BARRIER_TX)); + +} + +void erratum_a008850_post(void) +{ + /* part 2 of 2 */ + uintptr_t cci_base = NXP_CCI_ADDR; + uint32_t val = mmio_read_32(cci_base + CTRL_OVERRIDE_REG); + + /* Clear the BARRIER_TX bit */ + val = val & ~(CCI_TERMINATE_BARRIER_TX); + + /* + * Disable barrier termination on CCI400, allowing + * barriers to propagate across CCI + */ + mmio_write_32(cci_base + CTRL_OVERRIDE_REG, val); + + INFO("SoC workaround for Errata A008850 Post-Phase was applied\n"); +} diff --git a/plat/nxp/common/soc_errata/errata_a009660.c b/plat/nxp/common/soc_errata/errata_a009660.c new file mode 100644 index 0000000..d31a4d7 --- /dev/null +++ b/plat/nxp/common/soc_errata/errata_a009660.c @@ -0,0 +1,14 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <mmio.h> +#include <soc_default_base_addr.h> + +void erratum_a009660(void) +{ + mmio_write_32(NXP_SCFG_ADDR + 0x20c, 0x63b20042); +} diff --git a/plat/nxp/common/soc_errata/errata_a010539.c b/plat/nxp/common/soc_errata/errata_a010539.c new file mode 100644 index 0000000..3dcbdc8 --- /dev/null +++ b/plat/nxp/common/soc_errata/errata_a010539.c @@ -0,0 +1,26 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <mmio.h> + +#include <plat_common.h> + +void erratum_a010539(void) +{ + if (get_boot_dev() == BOOT_DEVICE_QSPI) { + unsigned int *porsr1 = (void *)(NXP_DCFG_ADDR + + DCFG_PORSR1_OFFSET); + uint32_t val; + + val = (gur_in32(porsr1) & ~PORSR1_RCW_MASK); + mmio_write_32((uint32_t)(NXP_DCSR_DCFG_ADDR + + DCFG_DCSR_PORCR1_OFFSET), htobe32(val)); + /* Erratum need to set '1' to all bits for reserved SCFG register 0x1a8 */ + mmio_write_32((uint32_t)(NXP_SCFG_ADDR + 0x1a8), + htobe32(0xffffffff)); + } +} diff --git a/plat/nxp/common/soc_errata/errata_a050426.c b/plat/nxp/common/soc_errata/errata_a050426.c new file mode 100644 index 0000000..ba4f71f --- /dev/null +++ b/plat/nxp/common/soc_errata/errata_a050426.c @@ -0,0 +1,201 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <common/debug.h> +#include <mmio.h> + +void erratum_a050426(void) +{ + uint32_t i, val3, val4; + + /* + * Part of this Errata is implemented in RCW and SCRATCHRW5 + * register is updated to hold Errata number. + * Validate whether RCW has already included required changes + */ + if (mmio_read_32(0x01e00210) != 0x00050426) { + ERROR("%s: Invalid RCW : ERR050426 not implemented\n", __func__); + } + + /* Enable BIST to access Internal memory locations */ + val3 = mmio_read_32(0x700117E60); + mmio_write_32(0x700117E60, (val3 | 0x80000001)); + val4 = mmio_read_32(0x700117E90); + mmio_write_32(0x700117E90, (val4 & 0xFFDFFFFF)); + + /* wriop Internal Memory.*/ + for (i = 0U; i < 4U; i++) { + mmio_write_32(0x706312000 + (i * 4), 0x55555555); + mmio_write_32(0x706312400 + (i * 4), 0x55555555); + mmio_write_32(0x706312800 + (i * 4), 0x55555555); + mmio_write_32(0x706314000 + (i * 4), 0x55555555); + mmio_write_32(0x706314400 + (i * 4), 0x55555555); + mmio_write_32(0x706314800 + (i * 4), 0x55555555); + mmio_write_32(0x706314c00 + (i * 4), 0x55555555); + } + for (i = 0U; i < 3U; i++) { + mmio_write_32(0x706316000 + (i * 4), 0x55555555); + mmio_write_32(0x706320000 + (i * 4), 0x55555555); + mmio_write_32(0x706320400 + (i * 4), 0x55555555); + } + for (i = 0U; i < 2U; i++) { + mmio_write_32(0x70640a000 + (i * 4), 0x55555555); + } + for (i = 0U; i < 3U; i++) { + mmio_write_32(0x706518000 + (i * 4), 0x55555555); + mmio_write_32(0x706519000 + (i * 4), 0x55555555); + } + for (i = 0U; i < 4U; i++) { + mmio_write_32(0x706522000 + (i * 4), 0x55555555); + mmio_write_32(0x706522800 + (i * 4), 0x55555555); + mmio_write_32(0x706523000 + (i * 4), 0x55555555); + mmio_write_32(0x706523800 + (i * 4), 0x55555555); + mmio_write_32(0x706524000 + (i * 4), 0x55555555); + mmio_write_32(0x706524800 + (i * 4), 0x55555555); + mmio_write_32(0x706608000 + (i * 4), 0x55555555); + mmio_write_32(0x706608800 + (i * 4), 0x55555555); + mmio_write_32(0x706609000 + (i * 4), 0x55555555); + mmio_write_32(0x706609800 + (i * 4), 0x55555555); + mmio_write_32(0x70660a000 + (i * 4), 0x55555555); + mmio_write_32(0x70660a800 + (i * 4), 0x55555555); + mmio_write_32(0x70660b000 + (i * 4), 0x55555555); + mmio_write_32(0x70660b800 + (i * 4), 0x55555555); + } + for (i = 0U; i < 3U; i++) { + mmio_write_32(0x70660c000 + (i * 4), 0x55555555); + mmio_write_32(0x70660c800 + (i * 4), 0x55555555); + } + for (i = 0U; i < 2U; i++) { + mmio_write_32(0x706718000 + (i * 4), 0x55555555); + mmio_write_32(0x706718800 + (i * 4), 0x55555555); + } + mmio_write_32(0x706b0a000, 0x55555555); + + for (i = 0U; i < 4U; i++) { + mmio_write_32(0x706b0e000 + (i * 4), 0x55555555); + mmio_write_32(0x706b0e800 + (i * 4), 0x55555555); + } + for (i = 0U; i < 2U; i++) { + mmio_write_32(0x706b10000 + (i * 4), 0x55555555); + mmio_write_32(0x706b10400 + (i * 4), 0x55555555); + } + for (i = 0U; i < 4U; i++) { + mmio_write_32(0x706b14000 + (i * 4), 0x55555555); + mmio_write_32(0x706b14800 + (i * 4), 0x55555555); + mmio_write_32(0x706b15000 + (i * 4), 0x55555555); + mmio_write_32(0x706b15800 + (i * 4), 0x55555555); + } + mmio_write_32(0x706e12000, 0x55555555); + + for (i = 0U; i < 4U; i++) { + mmio_write_32(0x706e14000 + (i * 4), 0x55555555); + mmio_write_32(0x706e14800 + (i * 4), 0x55555555); + } + for (i = 0U; i < 2U; i++) { + mmio_write_32(0x706e16000 + (i * 4), 0x55555555); + mmio_write_32(0x706e16400 + (i * 4), 0x55555555); + } + for (i = 0U; i < 3U; i++) { + mmio_write_32(0x706e1a000 + (i * 4), 0x55555555); + mmio_write_32(0x706e1a800 + (i * 4), 0x55555555); + mmio_write_32(0x706e1b000 + (i * 4), 0x55555555); + mmio_write_32(0x706e1b800 + (i * 4), 0x55555555); + mmio_write_32(0x706e1c000 + (i * 4), 0x55555555); + mmio_write_32(0x706e1c800 + (i * 4), 0x55555555); + mmio_write_32(0x706e1e000 + (i * 4), 0x55555555); + mmio_write_32(0x706e1e800 + (i * 4), 0x55555555); + mmio_write_32(0x706e1f000 + (i * 4), 0x55555555); + mmio_write_32(0x706e1f800 + (i * 4), 0x55555555); + mmio_write_32(0x706e20000 + (i * 4), 0x55555555); + mmio_write_32(0x706e20800 + (i * 4), 0x55555555); + } + for (i = 0U; i < 4U; i++) { + mmio_write_32(0x707108000 + (i * 4), 0x55555555); + mmio_write_32(0x707109000 + (i * 4), 0x55555555); + mmio_write_32(0x70710a000 + (i * 4), 0x55555555); + } + for (i = 0U; i < 2U; i++) { + mmio_write_32(0x70711c000 + (i * 4), 0x55555555); + mmio_write_32(0x70711c800 + (i * 4), 0x55555555); + mmio_write_32(0x70711d000 + (i * 4), 0x55555555); + mmio_write_32(0x70711d800 + (i * 4), 0x55555555); + mmio_write_32(0x70711e000 + (i * 4), 0x55555555); + } + for (i = 0U; i < 4U; i++) { + mmio_write_32(0x707120000 + (i * 4), 0x55555555); + mmio_write_32(0x707121000 + (i * 4), 0x55555555); + } + for (i = 0U; i < 3U; i++) { + mmio_write_32(0x707122000 + (i * 4), 0x55555555); + mmio_write_32(0x70725a000 + (i * 4), 0x55555555); + mmio_write_32(0x70725b000 + (i * 4), 0x55555555); + mmio_write_32(0x70725c000 + (i * 4), 0x55555555); + mmio_write_32(0x70725e000 + (i * 4), 0x55555555); + mmio_write_32(0x70725e400 + (i * 4), 0x55555555); + mmio_write_32(0x70725e800 + (i * 4), 0x55555555); + mmio_write_32(0x70725ec00 + (i * 4), 0x55555555); + mmio_write_32(0x70725f000 + (i * 4), 0x55555555); + mmio_write_32(0x70725f400 + (i * 4), 0x55555555); + mmio_write_32(0x707340000 + (i * 4), 0x55555555); + mmio_write_32(0x707346000 + (i * 4), 0x55555555); + mmio_write_32(0x707484000 + (i * 4), 0x55555555); + mmio_write_32(0x70748a000 + (i * 4), 0x55555555); + mmio_write_32(0x70748b000 + (i * 4), 0x55555555); + mmio_write_32(0x70748c000 + (i * 4), 0x55555555); + mmio_write_32(0x70748d000 + (i * 4), 0x55555555); + } + + /* EDMA Internal Memory.*/ + for (i = 0U; i < 5U; i++) { + mmio_write_32(0x70a208000 + (i * 4), 0x55555555); + mmio_write_32(0x70a208800 + (i * 4), 0x55555555); + mmio_write_32(0x70a209000 + (i * 4), 0x55555555); + mmio_write_32(0x70a209800 + (i * 4), 0x55555555); + } + + /* QDMA Internal Memory.*/ + for (i = 0U; i < 5U; i++) { + mmio_write_32(0x70b008000 + (i * 4), 0x55555555); + mmio_write_32(0x70b00c000 + (i * 4), 0x55555555); + mmio_write_32(0x70b010000 + (i * 4), 0x55555555); + mmio_write_32(0x70b014000 + (i * 4), 0x55555555); + mmio_write_32(0x70b018000 + (i * 4), 0x55555555); + mmio_write_32(0x70b018400 + (i * 4), 0x55555555); + mmio_write_32(0x70b01a000 + (i * 4), 0x55555555); + mmio_write_32(0x70b01a400 + (i * 4), 0x55555555); + mmio_write_32(0x70b01c000 + (i * 4), 0x55555555); + mmio_write_32(0x70b01d000 + (i * 4), 0x55555555); + mmio_write_32(0x70b01e000 + (i * 4), 0x55555555); + mmio_write_32(0x70b01e800 + (i * 4), 0x55555555); + mmio_write_32(0x70b01f000 + (i * 4), 0x55555555); + mmio_write_32(0x70b01f800 + (i * 4), 0x55555555); + mmio_write_32(0x70b020000 + (i * 4), 0x55555555); + mmio_write_32(0x70b020400 + (i * 4), 0x55555555); + mmio_write_32(0x70b020800 + (i * 4), 0x55555555); + mmio_write_32(0x70b020c00 + (i * 4), 0x55555555); + mmio_write_32(0x70b022000 + (i * 4), 0x55555555); + mmio_write_32(0x70b022400 + (i * 4), 0x55555555); + mmio_write_32(0x70b024000 + (i * 4), 0x55555555); + mmio_write_32(0x70b024800 + (i * 4), 0x55555555); + mmio_write_32(0x70b025000 + (i * 4), 0x55555555); + mmio_write_32(0x70b025800 + (i * 4), 0x55555555); + } + for (i = 0U; i < 4U; i++) { + mmio_write_32(0x70b026000 + (i * 4), 0x55555555); + mmio_write_32(0x70b026200 + (i * 4), 0x55555555); + } + for (i = 0U; i < 5U; i++) { + mmio_write_32(0x70b028000 + (i * 4), 0x55555555); + mmio_write_32(0x70b028800 + (i * 4), 0x55555555); + mmio_write_32(0x70b029000 + (i * 4), 0x55555555); + mmio_write_32(0x70b029800 + (i * 4), 0x55555555); + } + + /* Disable BIST */ + mmio_write_32(0x700117E60, val3); + mmio_write_32(0x700117E90, val4); +} diff --git a/plat/nxp/common/soc_errata/errata_list.h b/plat/nxp/common/soc_errata/errata_list.h new file mode 100644 index 0000000..f6741e2 --- /dev/null +++ b/plat/nxp/common/soc_errata/errata_list.h @@ -0,0 +1,28 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef ERRATA_LIST_H +#define ERRATA_LIST_H + +#ifdef ERRATA_SOC_A050426 +void erratum_a050426(void); +#endif + +#ifdef ERRATA_SOC_A008850 +void erratum_a008850_early(void); +void erratum_a008850_post(void); +#endif + +#ifdef ERRATA_SOC_A009660 +void erratum_a009660(void); +#endif + +#ifdef ERRATA_SOC_A010539 +void erratum_a010539(void); +#endif + +#endif /* ERRATA_LIST_H */ diff --git a/plat/nxp/common/tbbr/csf_tbbr.c b/plat/nxp/common/tbbr/csf_tbbr.c new file mode 100644 index 0000000..8f38f3e --- /dev/null +++ b/plat/nxp/common/tbbr/csf_tbbr.c @@ -0,0 +1,81 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + * + */ + +#include <errno.h> + +#include <common/debug.h> +#include <csf_hdr.h> +#include <dcfg.h> +#include <drivers/auth/crypto_mod.h> +#include <snvs.h> + +#include <plat/common/platform.h> +#include "plat_common.h" + +extern bool rotpk_not_dpld; +extern uint8_t rotpk_hash_table[MAX_KEY_ENTRIES][SHA256_BYTES]; +extern uint32_t num_rotpk_hash_entries; + +/* + * In case of secure boot, return ptr of rotpk_hash table in key_ptr and + * number of hashes in key_len + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + uint32_t mode = 0U; + *flags = ROTPK_NOT_DEPLOYED; + + /* ROTPK hash table must be available for secure boot */ + if (rotpk_not_dpld == true) { + if (check_boot_mode_secure(&mode) == true) { + /* Production mode, don;t continue further */ + if (mode == 1U) { + return -EAUTH; + } + + /* For development mode, rotpk flag false + * indicates that SRK hash comparison might + * have failed. This is not fatal error. + * Continue in this case but transition SNVS + * to non-secure state + */ + transition_snvs_non_secure(); + return 0; + } else { + return 0; + } + } + + /* + * We return the complete hash table and number of entries in + * table for NXP platform specific implementation. + * Here hash is always assume as SHA-256 + */ + *key_ptr = rotpk_hash_table; + *key_len = num_rotpk_hash_entries; + *flags = ROTPK_IS_HASH; + + return 0; +} + +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + /* + * No support for non-volatile counter. Update the ROT key to protect + * the system against rollback. + */ + *nv_ctr = 0U; + + return 0; +} + +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + return 0; +} diff --git a/plat/nxp/common/tbbr/nxp_rotpk.S b/plat/nxp/common/tbbr/nxp_rotpk.S new file mode 100644 index 0000000..8e084d1 --- /dev/null +++ b/plat/nxp/common/tbbr/nxp_rotpk.S @@ -0,0 +1,21 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + * + */ + +#ifndef _CSF_HDR_H_ + + .global nxp_rotpk_hash + .global nxp_rotpk_hash_end + .section .rodata.nxp_rotpk_hash, "a" +nxp_rotpk_hash: + /* DER header */ + .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48 + .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 + /* SHA256 */ + .incbin ROTPK_HASH +nxp_rotpk_hash_end: +#endif diff --git a/plat/nxp/common/tbbr/tbbr.mk b/plat/nxp/common/tbbr/tbbr.mk new file mode 100644 index 0000000..4aac9d6 --- /dev/null +++ b/plat/nxp/common/tbbr/tbbr.mk @@ -0,0 +1,162 @@ +# +# Copyright 2020-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# For TRUSTED_BOARD_BOOT platforms need to include this makefile +# Following definations are to be provided by platform.mk file or +# by user - BL33_INPUT_FILE, BL32_INPUT_FILE, BL31_INPUT_FILE + +ifeq ($(CHASSIS), 2) +include $(PLAT_DRIVERS_PATH)/csu/csu.mk +CSF_FILE := input_blx_ch${CHASSIS} +BL2_CSF_FILE := input_bl2_ch${CHASSIS} +else +ifeq ($(CHASSIS), 3) +CSF_FILE := input_blx_ch${CHASSIS} +BL2_CSF_FILE := input_bl2_ch${CHASSIS} +PBI_CSF_FILE := input_pbi_ch${CHASSIS} +$(eval $(call add_define, CSF_HDR_CH3)) +else +ifeq ($(CHASSIS), 3_2) +CSF_FILE := input_blx_ch3 +BL2_CSF_FILE := input_bl2_ch${CHASSIS} +PBI_CSF_FILE := input_pbi_ch${CHASSIS} +$(eval $(call add_define, CSF_HDR_CH3)) +else + $(error -> CHASSIS not set!) +endif +endif +endif + +PLAT_AUTH_PATH := $(PLAT_DRIVERS_PATH)/auth + + +ifeq (${BL2_INPUT_FILE},) + BL2_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${BL2_CSF_FILE} +endif + +ifeq (${PBI_INPUT_FILE},) + PBI_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${PBI_CSF_FILE} +endif + +# If MBEDTLS_DIR is not specified, use CSF Header option +ifeq (${MBEDTLS_DIR},) + # Generic image processing filters to prepend CSF header + ifeq (${BL33_INPUT_FILE},) + BL33_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${CSF_FILE} + endif + + ifeq (${BL31_INPUT_FILE},) + BL31_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${CSF_FILE} + endif + + ifeq (${BL32_INPUT_FILE},) + BL32_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${CSF_FILE} + endif + + ifeq (${FUSE_INPUT_FILE},) + FUSE_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${CSF_FILE} + endif + + PLAT_INCLUDES += -I$(PLAT_DRIVERS_PATH)/sfp + PLAT_TBBR_SOURCES += $(PLAT_AUTH_PATH)/csf_hdr_parser/cot.c \ + $(PLAT_COMMON_PATH)/tbbr/csf_tbbr.c + # IMG PARSER here is CSF header parser + include $(PLAT_DRIVERS_PATH)/auth/csf_hdr_parser/csf_hdr.mk + PLAT_TBBR_SOURCES += $(CSF_HDR_SOURCES) + + SCP_BL2_PRE_TOOL_FILTER := CST_SCP_BL2 + BL31_PRE_TOOL_FILTER := CST_BL31 + BL32_PRE_TOOL_FILTER := CST_BL32 + BL33_PRE_TOOL_FILTER := CST_BL33 +else + + ifeq (${DISABLE_FUSE_WRITE}, 1) + $(eval $(call add_define,DISABLE_FUSE_WRITE)) + endif + + # For Mbedtls currently crypto is not supported via CAAM + # enable it when that support is there + CAAM_INTEG := 0 + KEY_ALG := rsa + KEY_SIZE := 2048 + + $(eval $(call add_define,MBEDTLS_X509)) + ifeq (${PLAT_DDR_PHY},PHY_GEN2) + $(eval $(call add_define,PLAT_DEF_OID)) + endif + include drivers/auth/mbedtls/mbedtls_x509.mk + + + PLAT_TBBR_SOURCES += $(PLAT_AUTH_PATH)/tbbr/tbbr_cot.c \ + $(PLAT_COMMON_PATH)/tbbr/nxp_rotpk.S \ + $(PLAT_COMMON_PATH)/tbbr/x509_tbbr.c + + #ROTPK key is embedded in BL2 image + ifeq (${ROT_KEY},) + ROT_KEY = $(BUILD_PLAT)/rot_key.pem + endif + + ifeq (${SAVE_KEYS},1) + + ifeq (${TRUSTED_WORLD_KEY},) + TRUSTED_WORLD_KEY = ${BUILD_PLAT}/trusted.pem + endif + + ifeq (${NON_TRUSTED_WORLD_KEY},) + NON_TRUSTED_WORLD_KEY = ${BUILD_PLAT}/non-trusted.pem + endif + + ifeq (${BL31_KEY},) + BL31_KEY = ${BUILD_PLAT}/soc.pem + endif + + ifeq (${BL32_KEY},) + BL32_KEY = ${BUILD_PLAT}/trusted_os.pem + endif + + ifeq (${BL33_KEY},) + BL33_KEY = ${BUILD_PLAT}/non-trusted_os.pem + endif + + endif + + ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin + + $(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"')) + + $(BUILD_PLAT)/bl2/nxp_rotpk.o: $(ROTPK_HASH) + + certificates: $(ROT_KEY) + $(ROT_KEY): | $(BUILD_PLAT) + @echo " OPENSSL $@" + @if [ ! -f $(ROT_KEY) ]; then \ + ${OPENSSL_BIN_PATH}/openssl genrsa 2048 > $@ 2>/dev/null; \ + fi + + $(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)${OPENSSL_BIN_PATH}/openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + ${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@ 2>/dev/null + +endif #MBEDTLS_DIR + +PLAT_INCLUDES += -Iinclude/common/tbbr + +# Generic files for authentication framework +TBBR_SOURCES += drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + plat/common/tbbr/plat_tbbr.c \ + ${PLAT_TBBR_SOURCES} + +# If CAAM_INTEG is not defined (would be scenario with MBED TLS) +# include mbedtls_crypto +ifeq (${CAAM_INTEG},0) + include drivers/auth/mbedtls/mbedtls_crypto.mk +else + include $(PLAT_DRIVERS_PATH)/crypto/caam/src/auth/auth.mk + TBBR_SOURCES += ${AUTH_SOURCES} +endif diff --git a/plat/nxp/common/tbbr/x509_tbbr.c b/plat/nxp/common/tbbr/x509_tbbr.c new file mode 100644 index 0000000..ec87674 --- /dev/null +++ b/plat/nxp/common/tbbr/x509_tbbr.c @@ -0,0 +1,105 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <assert.h> +#include <stdint.h> +#include <string.h> + +#include <common/debug.h> +#include <lib/cassert.h> +#include <sfp.h> +#include <tools_share/tbbr_oid.h> + +#include <plat/common/platform.h> +#include "plat_common.h" + +extern char nxp_rotpk_hash[], nxp_rotpk_hash_end[]; + +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + *key_ptr = nxp_rotpk_hash; + *key_len = nxp_rotpk_hash_end - nxp_rotpk_hash; + *flags = ROTPK_IS_HASH; + + return 0; +} + +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + const char *oid; + uint32_t uid_num; + uint32_t val = 0U; + + assert(cookie != NULL); + assert(nv_ctr != NULL); + + oid = (const char *)cookie; + if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) { + uid_num = 3U; + } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + uid_num = 4U; + } else { + return 1; + } + + val = sfp_read_oem_uid(uid_num); + + INFO("SFP Value read is %x from UID %d\n", val, uid_num); + if (val == 0U) { + *nv_ctr = 0U; + } else { + *nv_ctr = (32U - __builtin_clz(val)); + } + + INFO("NV Counter value for UID %d is %d\n", uid_num, *nv_ctr); + return 0; + +} + +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + const char *oid; + uint32_t uid_num, sfp_val; + + assert(cookie != NULL); + + /* Counter values upto 32 are supported */ + if (nv_ctr > 32U) { + return 1; + } + + oid = (const char *)cookie; + if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) { + uid_num = 3U; + } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + uid_num = 4U; + } else { + return 1; + } + sfp_val = (1U << (nv_ctr - 1)); + + if (sfp_write_oem_uid(uid_num, sfp_val) == 1) { + /* Enable POVDD on board */ + if (board_enable_povdd()) { + sfp_program_fuses(); + } + + /* Disable POVDD on board */ + board_disable_povdd(); + } else { + ERROR("Invalid OEM UID sent.\n"); + return 1; + } + + return 0; +} + +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + return get_mbedtls_heap_helper(heap_addr, heap_size); +} diff --git a/plat/nxp/common/warm_reset/plat_warm_reset.c b/plat/nxp/common/warm_reset/plat_warm_reset.c new file mode 100644 index 0000000..966a73c --- /dev/null +++ b/plat/nxp/common/warm_reset/plat_warm_reset.c @@ -0,0 +1,121 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <errno.h> + +#include <common/debug.h> +#include <ddr.h> +#ifndef NXP_COINED_BB +#include <flash_info.h> +#include <fspi.h> +#include <fspi_api.h> +#endif +#include <lib/mmio.h> +#include <lib/psci/psci.h> +#ifdef NXP_COINED_BB +#include <snvs.h> +#endif + +#include <plat_nv_storage.h> +#include "plat_warm_rst.h" +#include "platform_def.h" + +#if defined(IMAGE_BL2) + +uint32_t is_warm_boot(void) +{ + uint32_t ret = mmio_read_32(NXP_RESET_ADDR + RST_RSTRQSR1_OFFSET) + & ~(RSTRQSR1_SWRR); + + const nv_app_data_t *nv_app_data = get_nv_data(); + + if (ret == 0U) { + INFO("Not a SW(Warm) triggered reset.\n"); + return 0U; + } + + ret = (nv_app_data->warm_rst_flag == WARM_BOOT_SUCCESS) ? 1 : 0; + + if (ret != 0U) { + INFO("Warm Reset was triggered..\n"); + } else { + INFO("Warm Reset was not triggered..\n"); + } + + return ret; +} + +#endif + +#if defined(IMAGE_BL31) +int prep_n_execute_warm_reset(void) +{ +#ifdef NXP_COINED_BB +#if !TRUSTED_BOARD_BOOT + snvs_disable_zeroize_lp_gpr(); +#endif +#else + int ret; + uint8_t warm_reset = WARM_BOOT_SUCCESS; + + ret = fspi_init(NXP_FLEXSPI_ADDR, NXP_FLEXSPI_FLASH_ADDR); + + if (ret != 0) { + ERROR("Failed to initialized driver flexspi-nor.\n"); + ERROR("exiting warm-reset request.\n"); + return PSCI_E_INTERN_FAIL; + } + + /* Sector starting from NV_STORAGE_BASE_ADDR is already + * erased for writing. + */ + +#if (ERLY_WRM_RST_FLG_FLSH_UPDT) + ret = xspi_write((uint32_t)NV_STORAGE_BASE_ADDR, + &warm_reset, + sizeof(warm_reset)); +#else + /* Preparation for writing the Warm reset flag. */ + ret = xspi_wren((uint32_t)NV_STORAGE_BASE_ADDR); + + /* IP Control Register0 - SF Address to be read */ + fspi_out32((NXP_FLEXSPI_ADDR + FSPI_IPCR0), + (uint32_t) NV_STORAGE_BASE_ADDR); + + while ((fspi_in32(NXP_FLEXSPI_ADDR + FSPI_INTR) & + FSPI_INTR_IPTXWE_MASK) == 0) { + ; + } + /* Write TX FIFO Data Register */ + fspi_out32(NXP_FLEXSPI_ADDR + FSPI_TFDR, (uint32_t) warm_reset); + + fspi_out32(NXP_FLEXSPI_ADDR + FSPI_INTR, FSPI_INTR_IPTXWE); + + /* IP Control Register1 - SEQID_WRITE operation, Size = 1 Byte */ + fspi_out32(NXP_FLEXSPI_ADDR + FSPI_IPCR1, + (uint32_t)(FSPI_WRITE_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) | + (uint16_t) sizeof(warm_reset)); + + /* Trigger XSPI-IP-Write cmd only if: + * - Putting DDR in-self refresh mode is successfully. + * to complete the writing of the warm-reset flag + * to flash. + * + * This code is as part of assembly. + */ +#endif +#endif + INFO("Doing DDR Self refresh.\n"); + _soc_sys_warm_reset(); + + /* Expected behaviour is to do the power cycle */ + while (1 != 0) + ; + + return -1; +} +#endif diff --git a/plat/nxp/common/warm_reset/plat_warm_rst.h b/plat/nxp/common/warm_reset/plat_warm_rst.h new file mode 100644 index 0000000..e0c39c5 --- /dev/null +++ b/plat/nxp/common/warm_reset/plat_warm_rst.h @@ -0,0 +1,28 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_WARM_RST_H +#define PLAT_WARM_RST_H + +#ifndef NXP_COINED_BB +#define ERLY_WRM_RST_FLG_FLSH_UPDT 0 +#endif + +#ifndef __ASSEMBLER__ + +#if defined(IMAGE_BL2) +uint32_t is_warm_boot(void); +#endif + +#if defined(IMAGE_BL31) +int prep_n_execute_warm_reset(void); +int _soc_sys_warm_reset(void); +#endif + +#endif /* __ASSEMBLER__ */ + +#endif /* PLAT_WARM_RST_H */ diff --git a/plat/nxp/common/warm_reset/warm_reset.mk b/plat/nxp/common/warm_reset/warm_reset.mk new file mode 100644 index 0000000..236004f --- /dev/null +++ b/plat/nxp/common/warm_reset/warm_reset.mk @@ -0,0 +1,20 @@ +# +# Copyright 2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +#----------------------------------------------------------------------------- +ifeq (${WARM_RST_ADDED},) + +WARM_RST_ADDED := 1 +NXP_NV_SW_MAINT_LAST_EXEC_DATA := yes + +$(eval $(call add_define,NXP_WARM_BOOT)) + + +WARM_RST_INCLUDES += -I${PLAT_COMMON_PATH}/warm_reset +WARM_RST_BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}_warm_rst.S + +WARM_RST_BL_COMM_SOURCES += ${PLAT_COMMON_PATH}/warm_reset/plat_warm_reset.c + +endif diff --git a/plat/nxp/soc-ls1028a/aarch64/ls1028a.S b/plat/nxp/soc-ls1028a/aarch64/ls1028a.S new file mode 100644 index 0000000..404c39e --- /dev/null +++ b/plat/nxp/soc-ls1028a/aarch64/ls1028a.S @@ -0,0 +1,1387 @@ +/* + * Copyright 2018-2021 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_lowlevel + .global soc_init_percpu + .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 TZPCDECPROT_0_SET_BASE, 0x02200804 + .equ TZPCDECPROT_1_SET_BASE, 0x02200810 + .equ TZPCDECPROT_2_SET_BASE, 0x0220081C + + .equ TZASC_REGION_ATTRIBUTES_0_0, 0x01100110 + +/* + * This function initialize the soc. + * in: void + * out: void + * uses x0 - x11 + */ +func soc_init_lowlevel + /* + * Called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + /* + * Make sure the personality has been established by releasing cores + * that are marked "to-be-disabled" from reset + */ + bl release_disabled /* 0-8 */ + + /* Set SCRATCHRW7 to 0x0 */ + ldr x0, =DCFG_SCRATCHRW7_OFFSET + mov x1, xzr + bl _write_reg_dcfg + + /* Restore the aarch32/64 non-volatile registers */ + ldp x18, x30, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + ret +endfunc soc_init_lowlevel + +/* + * void soc_init_percpu(void) + * + * This function performs any soc-specific initialization that is needed on + * a per-core basis + * in: none + * out: none + * uses x0 - x3 + */ +func soc_init_percpu + stp x4, x30, [sp, #-16]! + + bl plat_my_core_mask + mov x2, x0 + + /* x2 = core mask */ + + /* see if this core is marked for prefetch disable */ + mov x0, #PREFETCH_DIS_OFFSET + bl _get_global_data /* 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 + +/* + * This function determines if a core is disabled via COREDISABLEDSR + * in: w0 = core_mask_lsb + * out: w0 = 0, core not disabled + * w0 != 0, core disabled + * uses x0, x1 + */ +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 + +/* + * This function sets the security mechanisms in the SoC to implement the + * Platform Security Policy + */ +func _set_platform_security + mov x3, x30 + +#if (!SUPPRESS_TZC) + /* initialize the tzpc */ + bl init_tzpc +#endif + +#if (!SUPPRESS_SEC) + /* initialize secmon */ + bl initSecMon +#endif + + mov x30, x3 + ret +endfunc _set_platform_security + +/* + * Part of CPU_ON + * + * This function releases a secondary core from reset + * in: x0 = core_mask_lsb + * out: none + * uses: x0 - x3 + */ +_soc_core_release: + mov x3, x30 + + /* + * Write to CORE_HOLD to tell the bootrom that we want this core + * to run + */ + ldr x1, =NXP_SEC_REGFILE_ADDR + str w0, [x1, #CORE_HOLD_OFFSET] + + /* Read-modify-write BRRL to release core */ + mov x1, #NXP_RESET_ADDR + ldr w2, [x1, #BRR_OFFSET] + orr w2, w2, w0 + str w2, [x1, #BRR_OFFSET] + dsb sy + isb + + /* Send event */ + sev + isb + + mov x30, x3 + ret + +/* + * This function 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 + +/* + * Part of CPU_ON + * + * This function restarts a core shutdown via _soc_core_entr_off + * in: x0 = core mask lsb (of the target cpu) + * out: x0 == 0, on success + * x0 != 0, on failure + * uses x0 - x6 + */ +_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 + + /* Generate target list bit */ + and x1, x0, #MPIDR_AFFINITY0_MASK + mov x2, #1 + lsl x2, x2, x1 + + /* Get the affinity1 field */ + and x1, x0, #MPIDR_AFFINITY1_MASK + lsl x1, x1, #8 + orr x2, x2, x1 + + /* Insert the INTID for SGI15 */ + orr x2, x2, #ICC_SGI0R_EL1_INTID + + /* Fire the SGI */ + msr ICC_SGI0R_EL1, x2 + dsb sy + isb + + /* Load '0' on success */ + mov x0, xzr + + mov x30, x6 + ret + +/* + * Part of CPU_OFF + * + * This function programs SoC & GIC registers in preparation for shutting down + * the core + * in: x0 = core mask lsb + * out: none + * uses x0 - x7 + */ +_soc_core_prep_off: + mov x8, x30 + mov x7, x0 + + /* x7 = core mask lsb */ + + mrs x1, CPUECTLR_EL1 + + /* Set smp and disable L2 snoops in cpuectlr */ + orr x1, x1, #CPUECTLR_SMPEN_EN + orr x1, x1, #CPUECTLR_DISABLE_TWALK_PREFETCH + bic x1, x1, #CPUECTLR_INS_PREFETCH_MASK + bic x1, x1, #CPUECTLR_DAT_PREFETCH_MASK + + /* Set retention control in cpuectlr */ + bic x1, x1, #CPUECTLR_TIMER_MASK + orr x1, x1, #CPUECTLR_TIMER_2TICKS + msr CPUECTLR_EL1, x1 + + /* Get redistributor rd base addr for this core */ + mov x0, x7 + bl get_gic_rd_base + mov x6, x0 + + /* Get redistributor sgi base addr for this core */ + mov x0, x7 + bl get_gic_sgi_base + mov x5, x0 + + /* + * x5 = gicr sgi base addr + * x6 = gicr rd base addr + * x7 = core mask lsb + */ + + /* Disable SGI 15 at redistributor - GICR_ICENABLER0 */ + mov w3, #GICR_ICENABLER0_SGI15 + str w3, [x5, #GICR_ICENABLER0_OFFSET] +2: + /* Poll on rwp bit in GICR_CTLR */ + ldr w4, [x6, #GICR_CTLR_OFFSET] + tst w4, #GICR_CTLR_RWP + b.ne 2b + + /* Disable GRP1 interrupts at cpu interface */ + msr ICC_IGRPEN1_EL3, xzr + + /* Disable GRP0 ints at cpu interface */ + msr ICC_IGRPEN0_EL1, xzr + + /* Program the redistributor - poll on GICR_CTLR.RWP as needed */ + + /* Define SGI 15 as Grp0 - GICR_IGROUPR0 */ + ldr w4, [x5, #GICR_IGROUPR0_OFFSET] + bic w4, w4, #GICR_IGROUPR0_SGI15 + str w4, [x5, #GICR_IGROUPR0_OFFSET] + + /* Define SGI 15 as Grp0 - GICR_IGRPMODR0 */ + ldr w3, [x5, #GICR_IGRPMODR0_OFFSET] + bic w3, w3, #GICR_IGRPMODR0_SGI15 + str w3, [x5, #GICR_IGRPMODR0_OFFSET] + + /* Set priority of SGI 15 to highest (0x0) - GICR_IPRIORITYR3 */ + ldr w4, [x5, #GICR_IPRIORITYR3_OFFSET] + bic w4, w4, #GICR_IPRIORITYR3_SGI15_MASK + str w4, [x5, #GICR_IPRIORITYR3_OFFSET] + + /* Enable SGI 15 at redistributor - GICR_ISENABLER0 */ + mov w3, #GICR_ISENABLER0_SGI15 + str w3, [x5, #GICR_ISENABLER0_OFFSET] + dsb sy + isb +3: + /* Poll on rwp bit in GICR_CTLR */ + ldr w4, [x6, #GICR_CTLR_OFFSET] + tst w4, #GICR_CTLR_RWP + b.ne 3b + + /* Quiesce the debug interfaces */ + mrs x3, osdlr_el1 + orr x3, x3, #OSDLR_EL1_DLK_LOCK + msr osdlr_el1, x3 + isb + + /* Enable grp0 ints */ + mov x3, #ICC_IGRPEN0_EL1_EN + msr ICC_IGRPEN0_EL1, x3 + + /* + * x5 = gicr sgi base addr + * x6 = gicr rd base addr + * x7 = core mask lsb + */ + + /* Clear any pending interrupts */ + mvn w1, wzr + str w1, [x5, #GICR_ICPENDR0_OFFSET] + + /* Make sure system counter is enabled */ + ldr x3, =NXP_TIMER_ADDR + ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 4f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] +4: + /* Enable the core timer and mask timer interrupt */ + mov x1, #CNTP_CTL_EL0_EN + orr x1, x1, #CNTP_CTL_EL0_IMASK + msr cntp_ctl_el0, x1 + + isb + mov x30, x8 + ret + +/* + * Part of CPU_OFF + * + * This function performs the final steps to shutdown the core + * in: x0 = core mask lsb + * out: none + * uses x0 - x5 + */ +_soc_core_entr_off: + mov x5, x30 + mov x4, x0 + + /* x4 = core mask */ +1: + /* Enter low-power state by executing wfi */ + wfi + + /* See if SGI15 woke us up */ + mrs x2, ICC_IAR0_EL1 + mov x3, #ICC_IAR0_EL1_SGI15 + cmp x2, x3 + b.ne 1b + + /* Deactivate the int */ + msr ICC_EOIR0_EL1, x2 + + /* x4 = core mask */ +2: + /* Check if core has been turned on */ + mov x0, x4 + bl _getCoreState + + /* x0 = core state */ + + cmp x0, #CORE_WAKEUP + b.ne 1b + + /* If we get here, then we have exited the wfi */ + mov x30, x5 + ret + +/* + * Part of CPU_OFF + * + * This function starts the process of starting a core back up + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5, x6 + */ +_soc_core_exit_off: + mov x6, x30 + mov x5, x0 + + /* Disable forwarding of GRP0 ints at cpu interface */ + msr ICC_IGRPEN0_EL1, xzr + + /* Get redistributor sgi base addr for this core */ + mov x0, x5 + bl get_gic_sgi_base + mov x4, x0 + + /* x4 = gicr sgi base addr */ + /* x5 = core mask */ + + /* Disable SGI 15 at redistributor - GICR_ICENABLER0 */ + mov w1, #GICR_ICENABLER0_SGI15 + str w1, [x4, #GICR_ICENABLER0_OFFSET] + + /* Get redistributor rd base addr for this core */ + mov x0, x5 + bl get_gic_rd_base + mov x4, x0 + + /* x4 = gicr rd base addr */ +2: + /* Poll on rwp bit in GICR_CTLR */ + ldr w2, [x4, #GICR_CTLR_OFFSET] + tst w2, #GICR_CTLR_RWP + b.ne 2b + + /* x4 = gicr rd base addr */ + + /* Unlock the debug interfaces */ + mrs x3, osdlr_el1 + bic x3, x3, #OSDLR_EL1_DLK_LOCK + msr osdlr_el1, x3 + isb + + dsb sy + isb + mov x30, x6 + ret + +/* + * This function requests a reset of the entire SOC + * in: none + * out: none + * uses: x0, x1, x2, x3, x4, x5, x6 + */ +_soc_sys_reset: + mov x3, x30 + + /* Make sure the mask is cleared in the reset request mask register */ + mov x0, #RST_RSTRQMR1_OFFSET + mov w1, wzr + bl _write_reg_reset + + /* Set the reset request */ + mov x4, #RST_RSTCR_OFFSET + mov x0, x4 + mov w1, #RSTCR_RESET_REQ + bl _write_reg_reset + + /* x4 = RST_RSTCR_OFFSET */ + + /* + * Just in case this address range is mapped as cacheable, + * flush the write out of the dcaches + */ + mov x2, #NXP_RESET_ADDR + add x2, x2, x4 + dc cvac, x2 + dsb st + isb + + /* This function does not return */ +1: + wfi + b 1b + +/* + * Part of SYSTEM_OFF + * + * This function turns off the SoC clocks + * Note: this function is not intended to return, and the only allowable + * recovery is POR + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +_soc_sys_off: + /* + * Disable sec, spi and flexspi + * TBD - Check if eNETC needs to be disabled + */ + ldr x2, =NXP_DCFG_ADDR + ldr x0, =DCFG_DEVDISR1_OFFSET + ldr w1, =DCFG_DEVDISR1_SEC + str w1, [x2, x0] + ldr x0, =DCFG_DEVDISR4_OFFSET + ldr w1, =DCFG_DEVDISR4_SPI_QSPI + str w1, [x2, x0] + + /* Set TPMWAKEMR0 */ + ldr x0, =TPMWAKEMR0_ADDR + mov w1, #0x1 + str w1, [x0] + + /* Disable icache, dcache, mmu @ EL1 */ + mov x1, #SCTLR_I_C_M_MASK + mrs x0, sctlr_el1 + bic x0, x0, x1 + msr sctlr_el1, x0 + + /* Disable L2 prefetches */ + mrs x0, CPUECTLR_EL1 + orr x0, x0, #CPUECTLR_SMPEN_EN + bic x0, x0, #CPUECTLR_TIMER_MASK + orr x0, x0, #CPUECTLR_TIMER_2TICKS + msr CPUECTLR_EL1, x0 + dsb sy + isb + + /* Disable CCI snoop domain */ + ldr x0, =NXP_CCI_ADDR + mov w1, #0x1 + str w1, [x0] + + bl get_pmu_idle_core_mask + + /* x3 = pmu base addr */ + mov x3, #NXP_PMU_ADDR +4: + ldr w1, [x3, #PMU_PCPW20SR_OFFSET] + cmp w1, w0 + b.ne 4b + + bl get_pmu_idle_cluster_mask + mov x3, #NXP_PMU_ADDR + str w0, [x3, #PMU_CLAINACTSETR_OFFSET] + + bl get_pmu_idle_core_mask + mov x3, #NXP_PMU_ADDR +1: + ldr w1, [x3, #PMU_PCPW20SR_OFFSET] + cmp w1, w0 + b.ne 1b + + bl get_pmu_flush_cluster_mask + mov x3, #NXP_PMU_ADDR + str w0, [x3, #PMU_CLL2FLUSHSETR_OFFSET] +2: + ldr w1, [x3, #PMU_CLL2FLUSHSR_OFFSET] + cmp w1, w0 + b.ne 2b + + str w0, [x3, #PMU_CLSL2FLUSHCLRR_OFFSET] + + str w0, [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] + isb + dsb sy +5: + wfe + b.eq 5b + +/* + * Part of CPU_SUSPEND + * + * This function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_core_prep_stdby: + /* Clear CPUECTLR_EL1[2:0] */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CPUECTLR_EL1, x1 + + ret + +/* + * Part of CPU_SUSPEND + * + * This function puts the calling core into standby state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +_soc_core_entr_stdby: + /* X0 = core mask lsb */ + dsb sy + isb + wfi + + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_core_exit_stdby: + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2 + */ +_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, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_RET_MASK + orr x1, x1, #CPUECTLR_TIMER_2TICKS + orr x1, x1, #CPUECTLR_SMPEN_EN + msr CPUECTLR_EL1, x1 + + isb + ret + +/* + * Part of CPU_SUSPEND + * + * This function puts the calling core into a power-down state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +_soc_core_entr_pwrdn: + /* X0 = core mask lsb */ + dsb sy + isb + wfi + + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs any SoC-specific cleanup after power-down state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_core_exit_pwrdn: + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_clstr_prep_stdby: + /* Clear CPUECTLR_EL1[2:0] */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CPUECTLR_EL1, x1 + + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_clstr_exit_stdby: + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2 + */ +_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, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_RET_MASK + orr x1, x1, #CPUECTLR_TIMER_2TICKS + orr x1, x1, #CPUECTLR_SMPEN_EN + msr CPUECTLR_EL1, x1 + + isb + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs any SoC-specific cleanup after power-down state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_clstr_exit_pwrdn: + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_sys_prep_stdby: + /* Clear CPUECTLR_EL1[2:0] */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CPUECTLR_EL1, x1 + + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_sys_exit_stdby: + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs SoC-specific programming prior to + * suspend-to-power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4 + */ +_soc_sys_prep_pwrdn: + /* Set retention control */ + mrs x0, CPUECTLR_EL1 + bic x0, x0, #CPUECTLR_TIMER_MASK + orr x0, x0, #CPUECTLR_TIMER_2TICKS + orr x0, x0, #CPUECTLR_SMPEN_EN + msr CPUECTLR_EL1, x0 + dsb sy + isb + ret + +/* + * Part of CPU_SUSPEND + * + * This function puts the calling core, and potentially the soc, into a + * low-power state + * in: x0 = core mask lsb + * out: x0 = 0, success + * x0 < 0, failure + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x13, x14, x15, + * x16, x17, x18 + */ +_soc_sys_pwrdn_wfi: + mov x18, x30 + + mov x3, #NXP_PMU_ADDR + + /* x3 = pmu base addr */ + + /* Backup epu registers to stack */ + ldr x2, =NXP_EPU_ADDR + ldr w4, [x2, #EPU_EPIMCR10_OFFSET] + ldr w5, [x2, #EPU_EPCCR10_OFFSET] + ldr w6, [x2, #EPU_EPCTR10_OFFSET] + ldr w7, [x2, #EPU_EPGCR_OFFSET] + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + + /* + * x2 = epu base addr + * x3 = pmu base addr + */ + + /* Set up EPU event to receive the wake signal from PMU */ + mov w4, #EPU_EPIMCR10_VAL + mov w5, #EPU_EPCCR10_VAL + mov w6, #EPU_EPCTR10_VAL + mov w7, #EPU_EPGCR_VAL + str w4, [x2, #EPU_EPIMCR10_OFFSET] + str w5, [x2, #EPU_EPCCR10_OFFSET] + str w6, [x2, #EPU_EPCTR10_OFFSET] + str w7, [x2, #EPU_EPGCR_OFFSET] + + ldr x2, =NXP_GICD_ADDR + + /* + * x2 = gicd base addr + * x3 = pmu base addr + */ + + /* Backup flextimer/mmc/usb interrupt router */ + ldr x0, =GICD_IROUTER60_OFFSET + ldr x1, =GICD_IROUTER76_OFFSET + ldr w4, [x2, x0] + ldr w5, [x2, x1] + ldr x0, =GICD_IROUTER112_OFFSET + ldr x1, =GICD_IROUTER113_OFFSET + ldr w6, [x2, x0] + ldr w7, [x2, x1] + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + + /* + * x2 = gicd base addr + * x3 = pmu base addr + * x0 = GICD_IROUTER112_OFFSET + * x1 = GICD_IROUTER113_OFFSET + */ + + /* Re-route interrupt to cluster 1 */ + ldr w4, =GICD_IROUTER_VALUE + str w4, [x2, x0] + str w4, [x2, x1] + ldr x0, =GICD_IROUTER60_OFFSET + ldr x1, =GICD_IROUTER76_OFFSET + str w4, [x2, x0] + str w4, [x2, x1] + dsb sy + isb + + /* x3 = pmu base addr */ + + /* Disable sec, Check for eNETC, 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_DEVDISR4_OFFSET + ldr w1, =DCFG_DEVDISR4_SPI_QSPI + str w1, [x2, x0] + + /* x3 = pmu base addr */ + + /* Set TPMWAKEMR0 */ + ldr x0, =TPMWAKEMR0_ADDR + mov w1, #0x1 + str w1, [x0] + + /* Disable CCI snoop domain */ + ldr x0, =NXP_CCI_ADDR + mov w1, #0x1 + str w1, [x0] + + /* Setup retention control */ + mrs x0, CPUECTLR_EL1 + orr x0, x0, #CPUECTLR_SMPEN_EN + orr x0, x0, #CPUECTLR_TIMER_2TICKS + msr CPUECTLR_EL1, x0 + dsb sy + isb + + bl get_pmu_idle_core_mask + mov x3, #NXP_PMU_ADDR +8: + ldr w1, [x3, #PMU_PCPW20SR_OFFSET] + cmp w1, w0 + b.ne 8b + + /* x3 = NXP_PMU_ADDR */ + /* 1 cluster SoC */ + + bl get_pmu_idle_cluster_mask + mov x3, #NXP_PMU_ADDR + + str w0, [x3, #PMU_CLAINACTSETR_OFFSET] + + bl get_pmu_idle_core_mask + /* x3 = NXP_PMU_ADDR */ + mov x3, #NXP_PMU_ADDR +1: + ldr w1, [x3, #PMU_PCPW20SR_OFFSET] + cmp w1, w0 + b.ne 1b + + /* x3 = NXP_PMU_ADDR */ + bl get_pmu_flush_cluster_mask + mov x3, #NXP_PMU_ADDR + + str w0, [x3, #PMU_CLL2FLUSHSETR_OFFSET] + + /* x3 = NXP_PMU_ADDR */ +2: + ldr w1, [x3, #PMU_CLL2FLUSHSR_OFFSET] + cmp w1, w0 + b.ne 2b + + /* x3 = NXP_PMU_ADDR */ + + str w0, [x3, #PMU_CLSL2FLUSHCLRR_OFFSET] + + str w0, [x3, #PMU_CLSINACTSETR_OFFSET] + + /* Force the debug interface to be quiescent */ + mrs x0, osdlr_el1 + orr x0, x0, #0x1 + msr osdlr_el1, x0 + + /* + * Enable the WakeRequest signal + * x3 is cpu mask starting from cpu1 to cpu0 + */ + bl get_tot_num_cores + sub x0, x0, #1 + mov x3, #0x1 + lsl x3, x3, x0 +2: + mov x0, x3 + bl get_gic_rd_base // 0-2 + ldr w1, [x0, #GICR_WAKER_OFFSET] + orr w1, w1, #GICR_WAKER_SLEEP_BIT + str w1, [x0, #GICR_WAKER_OFFSET] +1: + ldr w1, [x0, #GICR_WAKER_OFFSET] + cmp w1, #GICR_WAKER_ASLEEP + b.ne 1b + + lsr x3, x3, #1 + cbnz x3, 2b + + /* Invalidate all TLB entries at all 3 exception levels */ + tlbi alle1 + tlbi alle2 + tlbi alle3 + + /* Request lpm20 */ + mov x3, #NXP_PMU_ADDR + ldr x0, =PMU_POWMGTCSR_OFFSET + ldr w1, =PMU_POWMGTCSR_VAL + str w1, [x3, x0] + + ldr x5, =NXP_EPU_ADDR +4: + wfe + ldr w1, [x5, #EPU_EPCTR10_OFFSET] + cmp w1, #0 + b.eq 4b + + /* x3 = NXP_PMU_ADDR */ + + bl get_pmu_idle_cluster_mask + mov x3, NXP_PMU_ADDR + + /* Re-enable the GPP ACP */ + str w0, [x3, #PMU_CLAINACTCLRR_OFFSET] + str w0, [x3, #PMU_CLSINACTCLRR_OFFSET] + + /* x3 = NXP_PMU_ADDR */ +3: + ldr w1, [x3, #PMU_CLAINACTSETR_OFFSET] + cbnz w1, 3b +4: + ldr w1, [x3, #PMU_CLSINACTSETR_OFFSET] + cbnz w1, 4b + + /* + * Enable the WakeRequest signal on cpu 0-1 + * x3 is cpu mask starting from cpu1 + */ + bl get_tot_num_cores + sub x0, x0, #1 + mov x3, #0x1 + lsl x3, x3, x0 +2: + mov x0, x3 + bl get_gic_rd_base // 0-2 + ldr w1, [x0, #GICR_WAKER_OFFSET] + bic w1, w1, #GICR_WAKER_SLEEP_BIT + str w1, [x0, #GICR_WAKER_OFFSET] +1: + ldr w1, [x0, #GICR_WAKER_OFFSET] + cbnz w1, 1b + + lsr x3, x3, #1 + cbnz x3, 2b + + /* Enable CCI snoop domain */ + ldr x0, =NXP_CCI_ADDR + str wzr, [x0] + dsb sy + isb + + ldr x3, =NXP_EPU_ADDR + + /* x3 = epu base addr */ + + /* Enable sec, enetc, spi and qspi */ + ldr x2, =NXP_DCFG_ADDR + str wzr, [x2, #DCFG_DEVDISR1_OFFSET] + str wzr, [x2, #DCFG_DEVDISR2_OFFSET] + str wzr, [x2, #DCFG_DEVDISR4_OFFSET] + + /* Restore flextimer/mmc/usb interrupt router */ + ldr x3, =NXP_GICD_ADDR + ldp x0, x2, [sp], #16 + ldr x1, =GICD_IROUTER113_OFFSET + str w2, [x3, x1] + ldr x1, =GICD_IROUTER112_OFFSET + str w0, [x3, x1] + ldp x0, x2, [sp], #16 + ldr x1, =GICD_IROUTER76_OFFSET + str w2, [x3, x1] + ldr x1, =GICD_IROUTER60_OFFSET + str w0, [x3, x1] + + /* Restore EPU registers */ + ldr x3, =NXP_EPU_ADDR + ldp x0, x2, [sp], #16 + str w2, [x3, #EPU_EPGCR_OFFSET] + str w0, [x3, #EPU_EPCTR10_OFFSET] + ldp x2, x1, [sp], #16 + str w1, [x3, #EPU_EPCCR10_OFFSET] + str w2, [x3, #EPU_EPIMCR10_OFFSET] + + dsb sy + isb + mov x30, x18 + ret + +/* + * Part of CPU_SUSPEND + * + * This function performs any SoC-specific cleanup after power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_sys_exit_pwrdn: + /* Enable stack alignment checking */ + mrs x1, SCTLR_EL1 + orr x1, x1, #0x4 + msr SCTLR_EL1, x1 + + /* Enable debug interface */ + mrs x1, osdlr_el1 + bic x1, x1, #OSDLR_EL1_DLK_LOCK + msr osdlr_el1, x1 + + /* Enable i-cache */ + mrs x1, SCTLR_EL3 + orr x1, x1, #SCTLR_I_MASK + msr SCTLR_EL3, x1 + + isb + ret + +/* + * This function setc up the TrustZone Address Space Controller (TZASC) + * in: none + * out: none + * uses x0, x1 + */ +init_tzpc: + /* Set Non Secure access for all devices protected via TZPC */ + ldr x1, =TZPCDECPROT_0_SET_BASE /* decode Protection-0 Set Reg */ + mov w0, #0xFF /* set decode region to NS, Bits[7:0] */ + str w0, [x1] + + ldr x1, =TZPCDECPROT_1_SET_BASE /* decode Protection-1 Set Reg */ + mov w0, #0xFF /* set decode region to NS, Bits[7:0] */ + str w0, [x1] + + ldr x1, =TZPCDECPROT_2_SET_BASE /* decode Protection-2 Set Reg */ + mov w0, #0xFF /* set decode region to NS, Bits[7:0] */ + str w0, [x1] + + /* entire SRAM as NS */ + ldr x1, =NXP_OCRAM_TZPC_ADDR /* secure RAM region size Reg */ + mov w0, #0x00000000 /* 0x00000000 = no secure region */ + str w0, [x1] + + ret + +/* + * This function performs any needed initialization on SecMon for + * boot services + */ +initSecMon: + /* Read the register hpcomr */ + ldr x1, =NXP_SNVS_ADDR + ldr w0, [x1, #SECMON_HPCOMR_OFFSET] + /* Turn off secure access for the privileged registers */ + orr w0, w0, #SECMON_HPCOMR_NPSWAEN + /* Write back */ + str w0, [x1, #SECMON_HPCOMR_OFFSET] + + ret + +/* + * This function checks to see if cores which are to be disabled have been + * released from reset - if not, it releases them + * in: none + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8 + */ +release_disabled: + stp x18, x30, [sp, #-16]! + + /* + * Get the number of cpus on this device + * Calling the below c function. + * No need to Callee saved registers x9-x15, + * as these registers are not used by the callee + * prior to calling the below C-routine. + */ + bl get_tot_num_cores + mov x6, x0 + + /* Read COREDISABLESR */ + mov x0, #NXP_DCFG_ADDR + ldr w4, [x0, #DCFG_COREDISABLEDSR_OFFSET] + + mov x0, #NXP_RESET_ADDR + ldr w5, [x0, #BRR_OFFSET] + + /* Load the core mask for the first core */ + mov x7, #1 + + /* + * x4 = COREDISABLESR + * x5 = BRR + * x6 = loop count + * x7 = core mask bit + */ +2: + /* Check if the core is to be disabled */ + tst x4, x7 + b.eq 1f + + /* See if disabled cores have already been released from reset */ + tst x5, x7 + b.ne 1f + + /* If core has not been released, then release it (0-3) */ + mov x0, x7 + bl _soc_core_release + + /* Record the core state in the data area (0-3) */ + mov x0, x7 + mov x1, #CORE_DISABLED + bl _setCoreState +1: + /* Decrement the counter */ + subs x6, x6, #1 + b.le 3f + /* Shift the core mask to the next core */ + lsl x7, x7, #1 + /* Continue */ + b 2b +3: + ldp x18, x30, [sp], #16 + ret + +/* + * Write a register in the DCFG block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2 + */ +_write_reg_dcfg: + ldr x2, =NXP_DCFG_ADDR + str w1, [x2, x0] + ret + +/* + * Read a register in the DCFG block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +_read_reg_dcfg: + ldr x2, =NXP_DCFG_ADDR + ldr w1, [x2, x0] + mov w0, w1 + ret + +/* + * This function returns an mpidr value for a core, given a core_mask_lsb + * in: x0 = core mask lsb + * out: x0 = affinity2:affinity1:affinity0, where affinity is 8-bits + * uses x0, x1 + */ +get_mpidr_value: + /* Convert a core mask to an SoC core number */ + clz w0, w0 + mov w1, #31 + sub w0, w1, w0 + + /* 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 + +/* + * This function returns the redistributor base address for the core specified + * in x1 + * in: x0 - core mask lsb of specified core + * out: x0 = redistributor rd base address for specified core + * uses x0, x1, x2 + */ +get_gic_rd_base: + /* Get the 0-based core number */ + clz w1, w0 + mov w2, #0x20 + sub w2, w2, w1 + sub w2, w2, #1 + + /* x2 = core number / loop counter */ + ldr x0, =NXP_GICR_ADDR + mov x1, #GIC_RD_OFFSET +2: + cbz x2, 1f + add x0, x0, x1 + sub x2, x2, #1 + b 2b +1: + ret + +/* + * This function returns the redistributor base address for the core specified + * in x1 + * in: x0 - core mask lsb of specified core + * out: x0 = redistributor sgi base address for specified core + * uses x0, x1, x2 + */ +get_gic_sgi_base: + /* Get the 0-based core number */ + clz w1, w0 + mov w2, #0x20 + sub w2, w2, w1 + sub w2, w2, #1 + + /* x2 = core number / loop counter */ + ldr x0, =NXP_GICR_SGI_ADDR + mov x1, #GIC_SGI_OFFSET +2: + cbz x2, 1f + add x0, x0, x1 + sub x2, x2, #1 + b 2b +1: + ret + +/* + * Write a register in the RESET block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2 + */ +_write_reg_reset: + ldr x2, =NXP_RESET_ADDR + str w1, [x2, x0] + ret + +/* + * Read a register in the RESET block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1 + */ +_read_reg_reset: + ldr x1, =NXP_RESET_ADDR + ldr w0, [x1, x0] + ret diff --git a/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S b/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S new file mode 100644 index 0000000..ec67529 --- /dev/null +++ b/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S @@ -0,0 +1,70 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> + +#include <platform_def.h> + +.globl plat_secondary_cold_boot_setup +.globl plat_is_my_cpu_primary +.globl plat_reset_handler +.globl platform_mem_init + +func platform_mem1_init + ret +endfunc platform_mem1_init + +func platform_mem_init + ret +endfunc platform_mem_init + +func apply_platform_errata + ret +endfunc apply_platform_errata + +func plat_reset_handler + mov x29, x30 + bl apply_platform_errata + +#if defined(IMAGE_BL31) + ldr x0, =POLICY_SMMU_PAGESZ_64K + cbz x0, 1f + /* Set the SMMU page size in the sACR register */ + bl _set_smmu_pagesz_64 +#endif +1: + mov x30, x29 + ret +endfunc plat_reset_handler + +/* + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + */ +func plat_secondary_cold_boot_setup + /* ls1028a 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-ls1028a/include/soc.h b/plat/nxp/soc-ls1028a/include/soc.h new file mode 100644 index 0000000..b1d044a --- /dev/null +++ b/plat/nxp/soc-ls1028a/include/soc.h @@ -0,0 +1,149 @@ +/* + * 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> + +/* + * SVR Definition of LS1028A + * (not include major and minor rev) + * These info is listed in Table B-6. DCFG differences + * between LS1028A and LS1027A of LS1028ARM(Reference Manual) + */ +#define SVR_LS1017AN 0x870B25 +#define SVR_LS1017AE 0x870B24 +#define SVR_LS1018AN 0x870B21 +#define SVR_LS1018AE 0x870B20 +#define SVR_LS1027AN 0x870B05 +#define SVR_LS1027AE 0x870B04 +#define SVR_LS1028AN 0x870B01 +#define SVR_LS1028AE 0x870B00 + +/* Number of cores in platform */ +#define PLATFORM_CORE_COUNT 2 +#define NUMBER_OF_CLUSTERS 1 +#define CORES_PER_CLUSTER 2 + +/* Set to 0 if the clusters are not symmetrical */ +#define SYMMETRICAL_CLUSTERS 1 + +#define NUM_DRAM_REGIONS 3 + +#define NXP_DRAM0_ADDR 0x80000000 +#define NXP_DRAM0_MAX_SIZE 0x80000000 /* 2GB */ + +#define NXP_DRAM1_ADDR 0x2080000000 +#define NXP_DRAM1_MAX_SIZE 0x1F80000000 /* 126G */ + +#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 + +/* CCSR space memory Map */ +#undef NXP_UART_ADDR +#define NXP_UART_ADDR 0x021C0500 + +#undef NXP_UART1_ADDR +#define NXP_UART1_ADDR 0x021C0600 + +#undef NXP_WDOG1_TZ_ADDR +#define NXP_WDOG1_TZ_ADDR 0x023C0000 + +#undef NXP_GICR_ADDR +#define NXP_GICR_ADDR 0x06040000 + +#undef NXP_GICR_SGI_ADDR +#define NXP_GICR_SGI_ADDR 0x06050000 + +/* EPU register offsets and values */ +#define EPU_EPGCR_OFFSET 0x0 +#define EPU_EPIMCR10_OFFSET 0x128 +#define EPU_EPCTR10_OFFSET 0xa28 +#define EPU_EPCCR10_OFFSET 0x828 +#define EPU_EPCCR10_VAL 0xb2800000 +#define EPU_EPIMCR10_VAL 0xba000000 +#define EPU_EPCTR10_VAL 0x0 +#define EPU_EPGCR_VAL (1 << 31) + +/* PORSR1 */ +#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 + +/* + * Required LS standard platform porting definitions + * for CCI-400 + */ +#define NXP_CCI_CLUSTER0_SL_IFACE_IX 4 + +/* Defines required for using XLAT tables from ARM common code */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 40) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 40) + +/* Clock Divisors */ +#define NXP_PLATFORM_CLK_DIVIDER 1 +#define NXP_UART_CLK_DIVIDER 2 + +/* dcfg register offsets and values */ +#define DCFG_DEVDISR2_ENETC (1 << 31) + +#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 OSDLR_EL1_DLK_LOCK 0x1 +#define CNTP_CTL_EL0_EN 0x1 +#define CNTP_CTL_EL0_IMASK 0x2 + +#define SYSTEM_PWR_DOMAINS 1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + NUMBER_OF_CLUSTERS + \ + SYSTEM_PWR_DOMAINS) + +/* Power state coordination occurs at the system level */ +#define PLAT_PD_COORD_LVL MPIDR_AFFLVL2 +#define PLAT_MAX_PWR_LVL PLAT_PD_COORD_LVL + +/* Local power state for power domains in Run state */ +#define LS_LOCAL_STATE_RUN PSCI_LOCAL_STATE_RUN + +/* define retention state */ +#define PLAT_MAX_RET_STATE (PSCI_LOCAL_STATE_RUN + 1) +#define LS_LOCAL_STATE_RET PLAT_MAX_RET_STATE + +/* define power-down state */ +#define PLAT_MAX_OFF_STATE (PLAT_MAX_RET_STATE + 1) +#define LS_LOCAL_STATE_OFF PLAT_MAX_OFF_STATE + +/* One cache line needed for bakery locks on ARM platforms */ +#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE) + +#ifndef __ASSEMBLER__ +/* CCI slave interfaces */ +static const int cci_map[] = { + NXP_CCI_CLUSTER0_SL_IFACE_IX, +}; +void soc_init_lowlevel(void); +void soc_init_percpu(void); +void _soc_set_start_addr(unsigned long addr); +void _set_platform_security(void); +#endif + +#endif /* SOC_H */ diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c b/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c new file mode 100644 index 0000000..d82be51 --- /dev/null +++ b/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c @@ -0,0 +1,185 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include <string.h> + +#include <common/debug.h> +#include <ddr.h> +#include <lib/utils.h> + +#include <platform_def.h> + +#ifdef CONFIG_STATIC_DDR +const struct ddr_cfg_regs static_1600 = { + .cs[0].config = U(0x80040422), + .cs[0].bnds = U(0xFF), + .sdram_cfg[0] = U(0xE50C0004), + .sdram_cfg[1] = U(0x401100), + .timing_cfg[0] = U(0x91550018), + .timing_cfg[1] = U(0xBAB40C42), + .timing_cfg[2] = U(0x48C111), + .timing_cfg[3] = U(0x1111000), + .timing_cfg[4] = U(0x2), + .timing_cfg[5] = U(0x3401400), + .timing_cfg[7] = U(0x23300000), + .timing_cfg[8] = U(0x2114600), + .sdram_mode[0] = U(0x3010210), + .sdram_mode[9] = U(0x4000000), + .sdram_mode[8] = U(0x500), + .sdram_mode[2] = U(0x10210), + .sdram_mode[10] = U(0x400), + .sdram_mode[11] = U(0x4000000), + .sdram_mode[4] = U(0x10210), + .sdram_mode[12] = U(0x400), + .sdram_mode[13] = U(0x4000000), + .sdram_mode[6] = U(0x10210), + .sdram_mode[14] = U(0x400), + .sdram_mode[15] = U(0x4000000), + .interval = U(0x18600618), + .data_init = U(0xdeadbeef), + .zq_cntl = U(0x8A090705), + .clk_cntl = U(0x2000000), + .cdr[0] = U(0x80040000), + .cdr[1] = U(0xA181), + .wrlvl_cntl[0] = U(0x8675F605), + .wrlvl_cntl[1] = U(0x6070700), + .wrlvl_cntl[2] = U(0x0000008), + .dq_map[0] = U(0x5b65b658), + .dq_map[1] = U(0xd96d8000), + .dq_map[2] = U(0), + .dq_map[3] = U(0x1600000), + .debug[28] = U(0x00700046), +}; + +unsigned long long board_static_ddr(struct ddr_info *priv) +{ + memcpy(&priv->ddr_reg, &static_1600, sizeof(static_1600)); + return ULL(0x100000000); +} + +#else + +static const struct rc_timing rcz[] = { + {1600, 8, 5}, + {} +}; + +static const struct board_timing ram[] = { + {0x1f, rcz, 0x1020200, 0x00000003}, +}; + +int ddr_board_options(struct ddr_info *priv) +{ + int ret; + struct memctl_opt *popts = &priv->opt; + + ret = cal_board_params(priv, ram, ARRAY_SIZE(ram)); + if (ret != 0) { + return ret; + } + + popts->bstopre = U(0x40); /* precharge value */ + popts->half_strength_drive_en = 1; + popts->cpo_sample = U(0x46); + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | + DDR_CDR1_ODT(DDR_CDR_ODT_80ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) | + DDR_CDR2_VREF_OVRD(70); /* Vref = 70% */ + + popts->addr_hash = 1; /* address hashing */ + return 0; +} + +/* DDR model number: MT40A1G8SA-075:E */ +struct dimm_params ddr_raw_timing = { + .n_ranks = U(1), + .rank_density = ULL(4294967296), + .capacity = ULL(4294967296), + .primary_sdram_width = U(32), + .ec_sdram_width = U(4), + .rdimm = U(0), + .mirrored_dimm = U(0), + .n_row_addr = U(16), + .n_col_addr = U(10), + .bank_group_bits = U(2), + .edc_config = U(2), + .burst_lengths_bitmask = U(0x0c), + .tckmin_x_ps = 750, + .tckmax_ps = 1900, + .caslat_x = U(0x0001FFE00), + .taa_ps = 13500, + .trcd_ps = 13500, + .trp_ps = 13500, + .tras_ps = 32000, + .trc_ps = 45500, + .twr_ps = 15000, + .trfc1_ps = 350000, + .trfc2_ps = 260000, + .trfc4_ps = 160000, + .tfaw_ps = 21000, + .trrds_ps = 3000, + .trrdl_ps = 4900, + .tccdl_ps = 5000, + .refresh_rate_ps = U(7800000), + .dq_mapping[0] = U(0x16), + .dq_mapping[1] = U(0x36), + .dq_mapping[2] = U(0x16), + .dq_mapping[3] = U(0x36), + .dq_mapping[4] = U(0x16), + .dq_mapping[5] = U(0x36), + .dq_mapping[6] = U(0x16), + .dq_mapping[7] = U(0x36), + .dq_mapping[8] = U(0x16), + .dq_mapping[9] = U(0x0), + .dq_mapping[10] = U(0x0), + .dq_mapping[11] = U(0x0), + .dq_mapping[12] = U(0x0), + .dq_mapping[13] = U(0x0), + .dq_mapping[14] = U(0x0), + .dq_mapping[15] = U(0x0), + .dq_mapping[16] = U(0x0), + .dq_mapping[17] = U(0x0), + .dq_mapping_ors = U(0), + .rc = U(0x1f), +}; + +int ddr_get_ddr_params(struct dimm_params *pdimm, + struct ddr_conf *conf) +{ + static const char dimm_model[] = "Fixed DDR on board"; + + conf->dimm_in_use[0] = 1; + memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params)); + memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1); + + return 1; +} +#endif + +int64_t init_ddr(void) +{ + struct ddr_info info; + struct sysinfo sys; + int64_t dram_size; + + zeromem(&sys, sizeof(sys)); + get_clocks(&sys); + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0); + + zeromem(&info, sizeof(struct ddr_info)); + info.num_ctlrs = 1; + info.dimm_on_ctlr = 1; + info.clk = get_ddr_freq(&sys, 0); + info.ddr[0] = (void *)NXP_DDR_ADDR; + + dram_size = dram_init(&info); + + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + + return dram_size; +} diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h b/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h new file mode 100644 index 0000000..63c0219 --- /dev/null +++ b/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h @@ -0,0 +1,76 @@ +/* + * 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> + + +#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 + +#define NXP_SPD_EEPROM0 0x51 + +/* 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 (0xC000) + +#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 +#define BL2_TEXT_LIMIT (BL2_LIMIT) + +/* 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 BL31_WDOG_SEC 89 + +/* + * 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 PLAT_LS_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(15, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) +#endif /* PLAT_DEF_H */ diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/platform.c b/plat/nxp/soc-ls1028a/ls1028ardb/platform.c new file mode 100644 index 0000000..65d508c --- /dev/null +++ b/plat/nxp/soc-ls1028a/ls1028ardb/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat_common.h> + +#pragma weak board_enable_povdd +#pragma weak board_disable_povdd + +bool board_enable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} + +bool board_disable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/platform.mk b/plat/nxp/soc-ls1028a/ls1028ardb/platform.mk new file mode 100644 index 0000000..c455000 --- /dev/null +++ b/plat/nxp/soc-ls1028a/ls1028ardb/platform.mk @@ -0,0 +1,33 @@ +# +# Copyright 2020-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Board-specific build parameters +BOOT_MODE ?= flexspi_nor +BOARD := ls1028ardb +POVDD_ENABLE := no +WARM_BOOT := no + +# DDR build parameters +NUM_OF_DDRC := 1 +CONFIG_DDR_NODIMM := 1 +DDR_ECC_EN := yes + +# On-board flash +FLASH_TYPE := MT35XU02G +XSPI_FLASH_SZ := 0x10000000 + +BL2_SOURCES += ${BOARD_PATH}/ddr_init.c \ + ${BOARD_PATH}/platform.c + +SUPPORTED_BOOT_MODE := flexspi_nor \ + sd \ + emmc + +# Add platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Add SoC build info +include plat/nxp/soc-ls1028a/soc.mk diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h b/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h new file mode 100644 index 0000000..bbad293 --- /dev/null +++ b/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h @@ -0,0 +1,13 @@ +/* + * 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 /* PLATFORM_DEF_H */ diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/policy.h b/plat/nxp/soc-ls1028a/ls1028ardb/policy.h new file mode 100644 index 0000000..67a8b45 --- /dev/null +++ b/plat/nxp/soc-ls1028a/ls1028ardb/policy.h @@ -0,0 +1,16 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef POLICY_H +#define POLICY_H + +/* + * Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +#endif /* POLICY_H */ diff --git a/plat/nxp/soc-ls1028a/soc.c b/plat/nxp/soc-ls1028a/soc.c new file mode 100644 index 0000000..2fb353f --- /dev/null +++ b/plat/nxp/soc-ls1028a/soc.c @@ -0,0 +1,432 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <endian.h> + +#include <arch.h> +#include <caam.h> +#include <cassert.h> +#include <cci.h> +#include <common/debug.h> +#include <dcfg.h> +#include <i2c.h> +#include <lib/xlat_tables/xlat_tables_v2.h> +#include <ls_interconnect.h> +#include <mmio.h> +#ifdef POLICY_FUSE_PROVISION +#include <nxp_gpio.h> +#endif +#if TRUSTED_BOARD_BOOT +#include <nxp_smmu.h> +#endif +#include <nxp_timer.h> +#include <plat_console.h> +#include <plat_gic.h> +#include <plat_tzc400.h> +#include <pmu.h> +#include <scfg.h> +#if defined(NXP_SFP_ENABLED) +#include <sfp.h> +#endif + +#include <errata.h> +#ifdef CONFIG_OCRAM_ECC_EN +#include <ocram.h> +#endif +#include "plat_common.h" +#include "platform_def.h" +#include "soc.h" + +static dcfg_init_info_t dcfg_init_data = { + .g_nxp_dcfg_addr = NXP_DCFG_ADDR, + .nxp_sysclk_freq = NXP_SYSCLK_FREQ, + .nxp_ddrclk_freq = NXP_DDRCLK_FREQ, + .nxp_plat_clk_divider = NXP_PLATFORM_CLK_DIVIDER, +}; + +static struct soc_type soc_list[] = { + SOC_ENTRY(LS1017AN, LS1017AN, 1, 1), + SOC_ENTRY(LS1017AE, LS1017AE, 1, 1), + SOC_ENTRY(LS1018AN, LS1018AN, 1, 1), + SOC_ENTRY(LS1018AE, LS1018AE, 1, 1), + SOC_ENTRY(LS1027AN, LS1027AN, 1, 2), + SOC_ENTRY(LS1027AE, LS1027AE, 1, 2), + SOC_ENTRY(LS1028AN, LS1028AN, 1, 2), + SOC_ENTRY(LS1028AE, LS1028AE, 1, 2), +}; + +CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256, + assert_invalid_ls1028a_cluster_count); + +/* + * 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, +}; +#endif + +void soc_preload_setup(void) +{ +} + +void soc_early_init(void) +{ + uint8_t num_clusters, cores_per_cluster; + +#ifdef CONFIG_OCRAM_ECC_EN + ocram_init(NXP_OCRAM_ADDR, NXP_OCRAM_SIZE); +#endif + dcfg_init(&dcfg_init_data); + enable_timer_base_to_cluster(NXP_PMU_ADDR); + enable_core_tb(NXP_PMU_ADDR); + dram_regions_info_t *dram_regions_info = get_dram_regions_info(); + +#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 + 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); + } + +#if TRUSTED_BOARD_BOOT + uint32_t mode; + + sfp_init(NXP_SFP_ADDR); + + /* + * For secure boot disable SMMU. + * Later when platform security policy comes in picture, + * this might get modified based on the policy + */ + if (check_boot_mode_secure(&mode) == true) { + bypass_smmu(NXP_SMMU_ADDR); + } + + /* + * For Mbedtls currently crypto is not supported via CAAM + * enable it when that support is there. In tbbr.mk + * the CAAM_INTEG is set as 0. + */ +#ifndef MBEDTLS_X509 + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled()) { + sec_init(NXP_CAAM_ADDR); + } else { + INFO("SEC is disabled.\n"); + } +#endif +#endif + + /* Set eDDRTQ for DDR performance */ + scfg_setbits32((void *)(NXP_SCFG_ADDR + 0x210), 0x1f1f1f1f); + + soc_errata(); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map)); + + /* + * Enable Interconnect coherency for the primary CPU's cluster. + */ + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + plat_ls_interconnect_enter_coherency(num_clusters); + + delay_timer_init(NXP_TIMER_ADDR); + i2c_init(NXP_I2C_ADDR); + dram_regions_info->total_dram_size = init_ddr(); +} + +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; +} + +/* + * This function sets up access permissions on memory regions + ****************************************************************************/ +void soc_mem_access(void) +{ + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); + struct tzc400_reg tzc400_reg_list[MAX_NUM_TZC_REGION]; + int dram_idx = 0; + /* index 0 is reserved for region-0 */ + int index = 1; + + for (dram_idx = 0; 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); + } + + mem_access_setup(NXP_TZC_ADDR, index, tzc400_reg_list); +} + +#else + +static unsigned char _power_domain_tree_desc[NUMBER_OF_CLUSTERS + 2]; +/* + * This function dynamically constructs the topology according to + * SoC Flavor and returns it. + */ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + uint8_t num_clusters, cores_per_cluster; + unsigned int i; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + /* + * The highest level is the system level. The next level is constituted + * by clusters and then cores in clusters. + */ + _power_domain_tree_desc[0] = 1; + _power_domain_tree_desc[1] = num_clusters; + + for (i = 0; i < _power_domain_tree_desc[1]; i++) + _power_domain_tree_desc[i + 2] = cores_per_cluster; + + return _power_domain_tree_desc; +} + +/* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + */ +unsigned int plat_ls_get_cluster_core_count(u_register_t mpidr) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + return num_clusters; +} + +void soc_early_platform_setup2(void) +{ + dcfg_init(&dcfg_init_data); + /* Initialize system level generic timer for Socs */ + delay_timer_init(NXP_TIMER_ADDR); + +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif +} + +void soc_platform_setup(void) +{ + /* Initialize the GIC driver, cpu and distributor interfaces */ + static uintptr_t target_mask_array[PLATFORM_CORE_COUNT]; + static interrupt_prop_t ls_interrupt_props[] = { + PLAT_LS_G1S_IRQ_PROPS(INTR_GROUP1S), + PLAT_LS_G0_IRQ_PROPS(INTR_GROUP0) + }; + + plat_ls_gic_driver_init(NXP_GICD_ADDR, NXP_GICR_ADDR, + PLATFORM_CORE_COUNT, + ls_interrupt_props, + ARRAY_SIZE(ls_interrupt_props), + target_mask_array, + plat_core_pos); + + plat_ls_gic_init(); + enable_init_timer(); +} + +/* This function initializes the soc from the BL31 module */ +void soc_init(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + + /* Low-level init of the soc */ + soc_init_lowlevel(); + _init_global_data(); + soc_init_percpu(); + _initialize_psci(); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map)); + + /* Enable Interconnect coherency for the primary CPU's cluster. */ + plat_ls_interconnect_enter_coherency(num_clusters); + + /* Set platform security policies */ + _set_platform_security(); + + /* Init SEC Engine which will be used by SiP */ + if (is_sec_enabled()) { + sec_init(NXP_CAAM_ADDR); + } else { + INFO("SEC is disabled.\n"); + } +} + +#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 +} + +/* This function returns the total number of cores in the SoC. */ +unsigned int get_tot_num_cores(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + return (num_clusters * cores_per_cluster); +} + +/* This function returns the PMU IDLE Cluster mask. */ +unsigned int get_pmu_idle_cluster_mask(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + return ((1 << num_clusters) - 2); +} + +/* This function returns the PMU Flush Cluster mask. */ +unsigned int get_pmu_flush_cluster_mask(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + return ((1 << num_clusters) - 2); +} + +/* This function returns the PMU idle core mask. */ +unsigned int get_pmu_idle_core_mask(void) +{ + return ((1 << get_tot_num_cores()) - 2); +} + +/* Function to return the SoC SYS CLK */ +unsigned int get_sys_clk(void) +{ + return NXP_SYSCLK_FREQ; +} +#endif diff --git a/plat/nxp/soc-ls1028a/soc.def b/plat/nxp/soc-ls1028a/soc.def new file mode 100644 index 0000000..c23c1bb --- /dev/null +++ b/plat/nxp/soc-ls1028a/soc.def @@ -0,0 +1,97 @@ +# +# Copyright 2018-2021 NXP +# +# 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 := CCI400 + +# Layerscape chassis level - set to 3=LSCH3 or 2=LSCH2 +CHASSIS := 3_2 + +# TZC used is TZC380 or TZC400 +TZC_ID := TZC400 + +# CONSOLE is NS16550 or PL011 +CONSOLE := NS16550 + +# DDR PHY generation to be used +PLAT_DDR_PHY := PHY_GEN1 + +PHYS_SYS := 64 + +# Max Size of CSF header. Required to define BL2 TEXT LIMIT in soc.def +# Input to CST create_hdr_esbc tool +CSF_HDR_SZ := 0x3000 + +# In IMAGE_BL2, compile time flag for handling Cache coherency +# with CAAM for BL2 running from OCRAM +SEC_MEM_NON_COHERENT := yes + +# OCRAM MAP for BL2 +# Before BL2 +# 0x18000000 - 0x18009fff -> Used by ROM code +# 0x1800a000 - 0x1800dfff -> CSF header for BL2 +# For FlexSFlexSPI 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 + +# Area of OCRAM reserved by ROM code +NXP_ROM_RSVD := 0xa000 + +# 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 (BL2_BASE + NXP_ROM_RSVD) +# This value BL2_HDR_LOC + CSF_HDR_SZ should not +# overalp with BL2_BASE +# Input to CST create_hdr_isbc tool +BL2_HDR_LOC := 0x1800A000 + +# SoC ERRATAS to be enabled +ERRATA_SOC_A008850 := 1 + +ERRATA_DDR_A009803 := 1 +ERRATA_DDR_A009942 := 1 +ERRATA_DDR_A010165 := 1 + +# Enable dynamic memory mapping +PLAT_XLAT_TABLES_DYNAMIC := 1 + +# Define Endianness of each module +NXP_GUR_ENDIANNESS := LE +NXP_DDR_ENDIANNESS := LE +NXP_SEC_ENDIANNESS := LE +NXP_SFP_ENDIANNESS := LE +NXP_SNVS_ENDIANNESS := LE +NXP_ESDHC_ENDIANNESS := LE +NXP_QSPI_ENDIANNESS := LE +NXP_FSPI_ENDIANNESS := LE +NXP_SCFG_ENDIANNESS := LE +NXP_GPIO_ENDIANNESS := LE + +NXP_SFP_VER := 3_4 + +# OCRAM ECC Enabled +OCRAM_ECC_EN := yes diff --git a/plat/nxp/soc-ls1028a/soc.mk b/plat/nxp/soc-ls1028a/soc.mk new file mode 100644 index 0000000..92d8e98 --- /dev/null +++ b/plat/nxp/soc-ls1028a/soc.mk @@ -0,0 +1,113 @@ +# +# Copyright 2020-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SoC-specific build parameters +SOC := ls1028a +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 definitions +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 + +ifeq (${TRUSTED_BOARD_BOOT},1) +$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2)) +SECURE_BOOT := yes +endif +$(eval $(call SET_NXP_MAKE_FLAG,CRYPTO_NEEDED,BL_COMM)) + +$(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)) + +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 diff --git a/plat/nxp/soc-ls1043a/aarch64/ls1043a.S b/plat/nxp/soc-ls1043a/aarch64/ls1043a.S new file mode 100644 index 0000000..a1baf79 --- /dev/null +++ b/plat/nxp/soc-ls1043a/aarch64/ls1043a.S @@ -0,0 +1,1637 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <asm_macros.S> +#include <cortex_a53.h> +#include <dcfg_lsch2.h> +#include <plat_gic.h> +#include <scfg.h> + +#include <bl31_data.h> +#include <plat_psci.h> +#include <platform_def.h> + +/* the BASE address for these offsets is AUX_01_DATA in the */ +/* bootcore's psci data region */ +#define DEVDISR2_MASK_OFFSET 0x0 /* references AUX_01_DATA */ +#define DEVDISR5_MASK_OFFSET 0x8 /* references AUX_02_DATA */ +#define CPUACTLR_DATA_OFFSET 0x10 /* references AUX_03_DATA */ +/* the BASE address for these offsets is AUX_04_DATA in the */ +/* bootcore's psci data region */ +#define GICD_BASE_ADDR_OFFSET 0x0 /* references AUX_04_DATA */ +#define GICC_BASE_ADDR_OFFSET 0x8 /* references AUX_05_DATA */ + +#define DAIF_DATA AUX_06_DATA /* references AUX_06_DATA */ + +#define IPSTPACK_RETRY_CNT 0x10000 +#define DDR_SLEEP_RETRY_CNT 0x10000 +#define CPUACTLR_EL1 S3_1_C15_C2_0 +#define DDR_SDRAM_CFG_2_FRCSR 0x80000000 +#define DDR_SDRAM_CFG_2_OFFSET 0x114 +#define DDR_TIMING_CFG_4_OFFSET 0x160 +#define DDR_CNTRL_BASE_ADDR 0x01080000 + +#define DLL_LOCK_MASK 0x3 +#define DLL_LOCK_VALUE 0x2 + +#define ERROR_DDR_SLEEP -1 +#define ERROR_DDR_WAKE -2 +#define ERROR_NO_QUIESCE -3 + +#define CORE_RESTARTABLE 0 +#define CORE_NOT_RESTARTABLE 1 + +#define RESET_RETRY_CNT 800 + +.global soc_init_lowlevel +.global soc_init_percpu +.global _soc_core_release +.global _soc_core_restart +.global _soc_ck_disabled +.global _soc_sys_reset +.global _soc_sys_off +.global _getGICD_BaseAddr +.global _getGICC_BaseAddr +.global _soc_set_start_addr +.global _soc_core_prep_off +.global _soc_core_entr_off +.global _soc_core_exit_off +.global _soc_core_prep_stdby +.global _soc_core_entr_stdby +.global _soc_core_exit_stdby +.global _soc_core_prep_pwrdn +.global _soc_core_entr_pwrdn +.global _soc_core_exit_pwrdn +.global _soc_clstr_prep_stdby +.global _soc_clstr_exit_stdby +.global _soc_clstr_prep_pwrdn +.global _soc_clstr_exit_pwrdn +.global _soc_sys_prep_stdby +.global _soc_sys_exit_stdby +.global _soc_sys_prep_pwrdn +.global _soc_sys_pwrdn_wfi +.global _soc_sys_exit_pwrdn + +/* + * This function initialize the soc. + * in: void + * out: void + */ +func soc_init_lowlevel + ret +endfunc soc_init_lowlevel + +/* + * void soc_init_percpu(void) + * this function performs any soc-specific initialization that is needed on + * a per-core basis + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +func soc_init_percpu + mov x3, x30 + + bl plat_my_core_mask + mov x2, x0 + + /* see if this core is marked for prefetch disable */ + mov x0, #PREFETCH_DIS_OFFSET + bl _get_global_data /* 0-1 */ + tst x0, x2 + b.eq 1f + bl _disable_ldstr_pfetch_A53 /* 0 */ +1: + mov x30, x3 + ret +endfunc soc_init_percpu + +/* + * part of CPU_ON + * this function releases a secondary core from reset + * in: x0 = core_mask_lsb + * out: none + * uses: x0, x1, x2, x3 + */ +_soc_core_release: + +#if (TEST_BL31) + mov w2, w0 + CoreMaskMsb w2, w3 + /* x2 = core mask msb */ +#else + mov x2, x0 +#endif + /* write COREBCR */ + ldr x1, =NXP_SCFG_ADDR + rev w3, w2 + str w3, [x1, #SCFG_COREBCR_OFFSET] + isb + + /* read-modify-write BRR */ + mov x1, #NXP_DCFG_ADDR + ldr w2, [x1, #DCFG_BRR_OFFSET] + rev w3, w2 + orr w3, w3, w0 + rev w2, w3 + str w2, [x1, #DCFG_BRR_OFFSET] + isb + + /* send event */ + sev + isb + ret + + +/* + * part of CPU_ON + * this function restarts a core shutdown via _soc_core_entr_off + * in: x0 = core mask lsb (of the target cpu) + * out: x0 == 0, on success + * x0 != 0, on failure + * uses x0 ~ x5 + */ +_soc_core_restart: + mov x5, x30 + mov x3, x0 + + /* x3 = core mask lsb */ + bl _getGICD_BaseAddr + mov x4, x0 + + /* x4 = GICD_BASE_ADDR */ + /* enable forwarding of group 0 interrupts by setting GICD_CTLR[0] = 1 */ + ldr w1, [x4, #GICD_CTLR_OFFSET] + orr w1, w1, #GICD_CTLR_EN_GRP0 + str w1, [x4, #GICD_CTLR_OFFSET] + dsb sy + isb + + /* + * fire SGI by writing to GICD_SGIR the following values: + * [25:24] = 0x0 (forward interrupt to the CPU interfaces specified in CPUTargetList field) + * [23:16] = core mask lsb[7:0] (forward interrupt to target cpu) + * [15] = 0 (forward SGI only if it is configured as group 0 interrupt) + * [3:0] = 0xF (interrupt ID = 15) + */ + lsl w1, w3, #16 + orr w1, w1, #0xF + str w1, [x4, #GICD_SGIR_OFFSET] + dsb sy + isb + + /* load '0' on success */ + mov x0, xzr + + mov x30, x5 + ret + +/* + * this function determines if a core is disabled via COREDISR + * in: w0 = core_mask_lsb + * out: w0 = 0, core not disabled + * w0 != 0, core disabled + * uses x0, x1, x2 + */ +_soc_ck_disabled: + + /* get base addr of dcfg block */ + ldr x1, =NXP_DCFG_ADDR + + /* read COREDISR */ + ldr w1, [x1, #DCFG_COREDISR_OFFSET] + rev w2, w1 + + /* test core bit */ + and w0, w2, w0 + ret + +/* + * this function resets the system via SoC-specific methods + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +_soc_sys_reset: + + ldr x2, =NXP_DCFG_ADDR + + /* make sure the mask is cleared in the reset request mask register */ + mov w1, wzr + str w1, [x2, #DCFG_RSTRQMR1_OFFSET] + + /* x2 = NXP_DCFG_ADDR */ + + /* set the reset request */ + ldr w1, =RSTCR_RESET_REQ + ldr x3, =DCFG_RSTCR_OFFSET + rev w0, w1 + str w0, [x2, x3] + + /* x2 = NXP_DCFG_ADDR */ + /* x3 = DCFG_RSTCR_OFFSET */ + + /* just in case this address range is mapped as cacheable, + * flush the write out of the dcaches */ + add x3, x2, x3 + dc cvac, x3 + dsb st + isb + + /* Note: this function does not return */ +1: + wfi + b 1b + + +/* + * part of SYSTEM_OFF + * this function turns off the SoC clocks + * Note: this function is not intended to return, and the only allowable + * recovery is POR + * in: none + * out: none + * uses x0 ~ x8 + */ +_soc_sys_off: + + /* mask interrupts at the core */ + mrs x1, DAIF + mov x0, #DAIF_SET_MASK + orr x0, x1, x0 + msr DAIF, x0 + + /* disable icache, dcache, mmu @ EL1 */ + mov x1, #SCTLR_I_C_M_MASK + mrs x0, sctlr_el1 + bic x0, x0, x1 + msr sctlr_el1, x0 + + /* disable dcache for EL3 */ + mrs x1, SCTLR_EL3 + bic x1, x1, #SCTLR_C_MASK + /* make sure icache is enabled */ + orr x1, x1, #SCTLR_I_MASK + msr SCTLR_EL3, x1 + isb + + /* set WFIL2_EN in SCFG_COREPMCR */ + ldr x0, =SCFG_COREPMCR_OFFSET + ldr x1, =COREPMCR_WFIL2 + bl write_reg_scfg + + /* set OVRD_EN in RCPM2_POWMGTDCR */ + ldr x0, =RCPM2_POWMGTDCR_OFFSET + ldr x1, =POWMGTDCR_OVRD_EN + bl write_reg_rcpm2 + + /* read IPPDEXPCR0 @ RCPM_IPPDEXPCR0 */ + ldr x0, =RCPM_IPPDEXPCR0_OFFSET + bl read_reg_rcpm + mov x7, x0 + + /* build an override mask for IPSTPCR4/IPSTPACK4/DEVDISR5 */ + mov x5, xzr + ldr x6, =IPPDEXPCR_MASK2 + and x6, x6, x7 + cbz x6, 1f + + /* x5 = override mask + * x6 = IPPDEXPCR bits for DEVDISR5 + * x7 = IPPDEXPCR */ + + /* get the overrides */ + orr x4, x5, #DEVDISR5_I2C_1 + tst x6, #IPPDEXPCR_I2C1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_LPUART1 + tst x6, #IPPDEXPCR_LPUART1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_FLX_TMR + tst x6, #IPPDEXPCR_FLX_TMR1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_OCRAM1 + tst x6, #IPPDEXPCR_OCRAM1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_GPIO + tst x6, #IPPDEXPCR_GPIO1 + csel x5, x5, x4, EQ +1: + /* store the DEVDISR5 override mask */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + str w5, [x2, #DEVDISR5_MASK_OFFSET] + + /* build an override mask for IPSTPCR1/IPSTPACK1/DEVDISR2 */ + mov x5, xzr + ldr x6, =IPPDEXPCR_MASK1 + and x6, x6, x7 + cbz x6, 2f + + /* x5 = override mask */ + /* x6 = IPPDEXPCR bits for DEVDISR2 */ + + /* get the overrides */ + orr x4, x5, #DEVDISR2_FMAN1_MAC1 + tst x6, #IPPDEXPCR_MAC1_1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC2 + tst x6, #IPPDEXPCR_MAC1_2 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC3 + tst x6, #IPPDEXPCR_MAC1_3 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC4 + tst x6, #IPPDEXPCR_MAC1_4 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC5 + tst x6, #IPPDEXPCR_MAC1_5 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC6 + tst x6, #IPPDEXPCR_MAC1_6 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC9 + tst x6, #IPPDEXPCR_MAC1_9 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1 + tst x6, #IPPDEXPCR_FM1 + csel x5, x5, x4, EQ + +2: + /* store the DEVDISR2 override mask */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + str w5, [x2, #DEVDISR2_MASK_OFFSET] + + /* x5 = DEVDISR2 override mask */ + + /* write IPSTPCR0 - no overrides */ + ldr x0, =RCPM2_IPSTPCR0_OFFSET + ldr x1, =IPSTPCR0_VALUE + bl write_reg_rcpm2 + + /* x5 = DEVDISR2 override mask */ + + /* write IPSTPCR1 - overrides possible */ + ldr x0, =RCPM2_IPSTPCR1_OFFSET + ldr x1, =IPSTPCR1_VALUE + bic x1, x1, x5 + bl write_reg_rcpm2 + + /* write IPSTPCR2 - no overrides */ + ldr x0, =RCPM2_IPSTPCR2_OFFSET + ldr x1, =IPSTPCR2_VALUE + bl write_reg_rcpm2 + + /* write IPSTPCR3 - no overrides */ + ldr x0, =RCPM2_IPSTPCR3_OFFSET + ldr x1, =IPSTPCR3_VALUE + bl write_reg_rcpm2 + + /* write IPSTPCR4 - overrides possible */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + ldr w6, [x2, #DEVDISR5_MASK_OFFSET] + ldr x0, =RCPM2_IPSTPCR4_OFFSET + ldr x1, =IPSTPCR4_VALUE + bic x1, x1, x6 + bl write_reg_rcpm2 + + /* x5 = DEVDISR2 override mask */ + /* x6 = DEVDISR5 override mask */ + + /* poll on IPSTPACK0 */ + ldr x3, =RCPM2_IPSTPACKR0_OFFSET + ldr x4, =IPSTPCR0_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +3: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 14f + sub x7, x7, #1 + cbnz x7, 3b + +14: + /* poll on IPSTPACK1 */ + ldr x3, =IPSTPCR1_VALUE + ldr x7, =IPSTPACK_RETRY_CNT + bic x4, x3, x5 + ldr x3, =RCPM2_IPSTPACKR1_OFFSET +4: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 15f + sub x7, x7, #1 + cbnz x7, 4b + +15: + /* poll on IPSTPACK2 */ + ldr x3, =RCPM2_IPSTPACKR2_OFFSET + ldr x4, =IPSTPCR2_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +5: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 16f + sub x7, x7, #1 + cbnz x7, 5b + +16: + /* poll on IPSTPACK3 */ + ldr x3, =RCPM2_IPSTPACKR3_OFFSET + ldr x4, =IPSTPCR3_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +6: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 17f + sub x7, x7, #1 + cbnz x7, 6b + +17: + /* poll on IPSTPACK4 */ + ldr x3, =IPSTPCR4_VALUE + ldr x7, =IPSTPACK_RETRY_CNT + bic x4, x3, x6 + ldr x3, =RCPM2_IPSTPACKR4_OFFSET +7: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 18f + sub x7, x7, #1 + cbnz x7, 7b + +18: + ldr x7, =BC_PSCI_BASE + add x7, x7, #AUX_01_DATA + + /* x5 = DEVDISR2 override mask + * x6 = DEVDISR5 override mask + * x7 = [soc_data_area] */ + + /* DEVDISR1 - load new value */ + mov x0, #DCFG_DEVDISR1_OFFSET + bl read_reg_dcfg + mov x0, #DCFG_DEVDISR1_OFFSET + ldr x1, =DEVDISR1_VALUE + bl write_reg_dcfg + + /* DEVDISR2 - load new value */ + mov x0, #DCFG_DEVDISR2_OFFSET + bl read_reg_dcfg + mov x0, #DCFG_DEVDISR2_OFFSET + ldr x1, =DEVDISR2_VALUE + bic x1, x1, x5 + bl write_reg_dcfg + + /* x6 = DEVDISR5 override mask */ + /* x7 = [soc_data_area] */ + + /* DEVDISR3 - load new value */ + mov x0, #DCFG_DEVDISR3_OFFSET + bl read_reg_dcfg + mov x0, #DCFG_DEVDISR3_OFFSET + ldr x1, =DEVDISR3_VALUE + bl write_reg_dcfg + + /* DEVDISR4 - load new value */ + mov x0, #DCFG_DEVDISR4_OFFSET + bl read_reg_dcfg + mov x0, #DCFG_DEVDISR4_OFFSET + ldr x1, =DEVDISR4_VALUE + bl write_reg_dcfg + + /* DEVDISR5 - load new value */ + mov x0, #DCFG_DEVDISR5_OFFSET + bl read_reg_dcfg + mov x0, #DCFG_DEVDISR5_OFFSET + ldr x1, =DEVDISR5_VALUE + bic x1, x1, x6 + bl write_reg_dcfg + + /* x7 = [soc_data_area] */ + + /* disable data prefetch */ + mrs x0, CPUACTLR_EL1 + bic x0, x0, #CPUACTLR_L1PCTL_MASK + msr CPUACTLR_EL1, x0 + + /* x6 = DEVDISR5 override mask */ + + /* setup registers for cache-only execution */ + ldr x5, =IPSTPCR4_VALUE + bic x5, x5, x6 + mov x6, #DDR_CNTRL_BASE_ADDR + mov x7, #DCSR_RCPM2_BASE + mov x8, #NXP_DCFG_ADDR + dsb sy + isb + + /* set the DLL_LOCK cycle count */ + ldr w1, [x6, #DDR_TIMING_CFG_4_OFFSET] + rev w2, w1 + bic w2, w2, #DLL_LOCK_MASK + orr w2, w2, #DLL_LOCK_VALUE + rev w1, w2 + str w1, [x6, #DDR_TIMING_CFG_4_OFFSET] + + /* x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK) + * x6 = DDR_CNTRL_BASE_ADDR + * x7 = DCSR_RCPM2_BASE + * x8 = NXP_DCFG_ADDR */ + + /* enter the cache-only sequence - there is no return */ + b final_shutdown + + +/* + * part of CPU_OFF + * this function programs SoC & GIC registers in preparation for shutting down + * the core + * in: x0 = core mask lsb + * out: none + * uses x0 ~ x7 + */ +_soc_core_prep_off: + mov x7, x30 + mov x6, x0 + + /* make sure the smpen bit is set */ + mrs x2, CORTEX_A53_ECTLR_EL1 + orr x2, x2, #CPUECTLR_SMPEN_MASK + msr CORTEX_A53_ECTLR_EL1, x2 + isb + + /* configure the cpu interface */ + + /* disable signaling of ints */ + bl _getGICC_BaseAddr // 0-1 + mov x4, x0 + + ldr w3, [x4, #GICC_CTLR_OFFSET] + bic w3, w3, #GICC_CTLR_EN_GRP0 + bic w3, w3, #GICC_CTLR_EN_GRP1 + str w3, [x4, #GICC_CTLR_OFFSET] + dsb sy + isb + + /* + * x3 = GICC_CTRL + * x4 = GICC_BASE_ADDR + * x6 = core mask + */ + + /* set the priority filter */ + ldr w2, [x4, #GICC_PMR_OFFSET] + orr w2, w2, #GICC_PMR_FILTER + str w2, [x4, #GICC_PMR_OFFSET] + + /* setup GICC_CTLR */ + bic w3, w3, #GICC_CTLR_ACKCTL_MASK + orr w3, w3, #GICC_CTLR_FIQ_EN_MASK + orr w3, w3, #GICC_CTLR_EOImodeS_MASK + orr w3, w3, #GICC_CTLR_CBPR_MASK + str w3, [x4, #GICC_CTLR_OFFSET] + + /* x3 = GICC_CTRL */ + /* x4 = GICC_BASE_ADDR */ + + /* setup the banked-per-core GICD registers */ + bl _getGICD_BaseAddr + + /* + * x0 = GICD_BASE_ADDR + * x3 = GICC_CTRL + * x4 = GICC_BASE_ADDR + * x6 = core mask + */ + + /* define SGI15 as Grp0 */ + ldr w2, [x0, #GICD_IGROUPR0_OFFSET] + bic w2, w2, #GICD_IGROUP0_SGI15 + str w2, [x0, #GICD_IGROUPR0_OFFSET] + + /* set priority of SGI 15 to highest... */ + ldr w2, [x0, #GICD_IPRIORITYR3_OFFSET] + bic w2, w2, #GICD_IPRIORITY_SGI15_MASK + str w2, [x0, #GICD_IPRIORITYR3_OFFSET] + + /* enable SGI 15 */ + ldr w2, [x0, #GICD_ISENABLER0_OFFSET] + orr w2, w2, #GICD_ISENABLE0_SGI15 + str w2, [x0, #GICD_ISENABLER0_OFFSET] + + /* enable the cpu interface */ + orr w3, w3, #GICC_CTLR_EN_GRP0 + str w3, [x4, #GICC_CTLR_OFFSET] + + /* x0 = GICD_BASE_ADDR + * x6 = core mask */ + + /* clear any pending SGIs */ + add x0, x0, #GICD_CPENDSGIR3_OFFSET + ldr x2, =GICD_CPENDSGIR_CLR_MASK + str w2, [x0] + + dsb sy + isb + mov x30, x7 + ret + +/* + * part of CPU_OFF + * this function performs the final steps to shutdown the core + * in: x0 = core mask lsb + * out: none + * uses x0 ~ x5 + */ +_soc_core_entr_off: + mov x5, x30 + mov x4, x0 + + bl _getGICD_BaseAddr + mov x3, x0 + + /* x3 = GICD_BASE_ADDR */ + /* x4 = core mask (lsb) */ + +3: + /* enter low-power state by executing wfi */ + wfi + + /* x3 = GICD_BASE_ADDR */ + /* x4 = core mask (lsb) */ + + /* see if we got hit by SGI 15 */ + add x0, x3, #GICD_SPENDSGIR3_OFFSET + ldr w2, [x0] + and w2, w2, #GICD_SPENDSGIR3_SGI15_MASK + cbz w2, 4f + + /* clear the pending SGI */ + ldr x2, =GICD_CPENDSGIR_CLR_MASK + add x0, x3, #GICD_CPENDSGIR3_OFFSET + str w2, [x0] +4: + /* check if core has been turned on */ + mov x0, x4 + bl _getCoreState + + /* x0 = core state */ + cmp x0, #CORE_WAKEUP + b.ne 3b + + /* if we get here, then we have exited the wfi */ + dsb sy + isb + mov x30, x5 + ret + +/* + * part of CPU_OFF + * this function starts the process of starting a core back up + * in: x0 = core mask lsb + * out: none + * uses x0 ~ x5 + */ +_soc_core_exit_off: + mov x5, x30 + mov x4, x0 + + /* x4 = core mask */ + + bl _getGICC_BaseAddr + mov x2, x0 + + /* read GICC_IAR */ + ldr w0, [x2, #GICC_IAR_OFFSET] + + /* write GICC_EIOR - signal end-of-interrupt */ + str w0, [x2, #GICC_EOIR_OFFSET] + + /* write GICC_DIR - disable interrupt */ + str w0, [x2, #GICC_DIR_OFFSET] + + /* x2 = GICC_BASE_ADDR */ + + /* disable signaling of grp0 ints */ + ldr w1, [x2, #GICC_CTLR_OFFSET] + bic w1, w1, #GICC_CTLR_EN_GRP0 + str w1, [x2, #GICC_CTLR_OFFSET] + + dsb sy + isb + mov x30, x5 + ret + +/* + * this function loads a 64-bit execution address of the core in the soc registers + * BOOTLOCPTRL/H + * in: x0, 64-bit address to write to BOOTLOCPTRL/H + * uses x0, x1, x2, x3 + */ +_soc_set_start_addr: + /* get the 64-bit base address of the scfg block */ + ldr x2, =NXP_SCFG_ADDR + + /* write the 32-bit BOOTLOCPTRL register (offset 0x604 in the scfg block) */ + mov x1, x0 + rev w3, w1 + str w3, [x2, #SCFG_BOOTLOCPTRL_OFFSET] + + /* write the 32-bit BOOTLOCPTRH register (offset 0x600 in the scfg block) */ + lsr x1, x0, #32 + rev w3, w1 + str w3, [x2, #SCFG_BOOTLOCPTRH_OFFSET] + ret + +/* + * part of CPU_SUSPEND + * this function puts the calling core into standby state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +_soc_core_entr_stdby: + dsb sy + isb + wfi + + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_core_prep_stdby: + /* clear CORTEX_A53_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A53_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_core_exit_stdby: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_core_prep_pwrdn: + /* make sure the smp bit is set */ + mrs x1, CORTEX_A53_ECTLR_EL1 + orr x1, x1, #CPUECTLR_SMPEN_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + isb + + ret + +/* + * part of CPU_SUSPEND + * this function puts the calling core into a power-down state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +_soc_core_entr_pwrdn: + dsb sy + isb + wfi + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after power-down + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_core_exit_pwrdn: + ret + + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_clstr_prep_stdby: + /* clear CORTEX_A53_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A53_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_clstr_exit_stdby: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_clstr_prep_pwrdn: + /* make sure the smp bit is set */ + mrs x1, CORTEX_A53_ECTLR_EL1 + orr x1, x1, #CPUECTLR_SMPEN_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + isb + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after power-down + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_clstr_exit_pwrdn: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_sys_prep_stdby: + /* clear CORTEX_A53_ECTLR_EL1[2:0] */ + mrs x1, CORTEX_A53_ECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_sys_exit_stdby: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to + * suspend-to-power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4 + */ +_soc_sys_prep_pwrdn: + mov x4, x30 + /* make sure the smp bit is set */ + mrs x1, CORTEX_A53_ECTLR_EL1 + orr x1, x1, #CPUECTLR_SMPEN_MASK + msr CORTEX_A53_ECTLR_EL1, x1 + isb + + /* set WFIL2_EN in SCFG_COREPMCR */ + ldr x0, =SCFG_COREPMCR_OFFSET + ldr x1, =COREPMCR_WFIL2 + bl write_reg_scfg // 0-3 + + /* set OVRD_EN in RCPM2_POWMGTDCR */ + ldr x0, =RCPM2_POWMGTDCR_OFFSET + ldr x1, =POWMGTDCR_OVRD_EN + bl write_reg_rcpm2 // 0-3 + + mov x30, x4 + ret +/* + * part of CPU_SUSPEND + * this function puts the calling core, and potentially the soc, into a + * low-power state + * in: x0 = core mask lsb + * out: x0 = 0, success + * x0 < 0, failure + * uses x0 ~ x9 + */ +_soc_sys_pwrdn_wfi: + mov x18, x30 + + /* read IPPDEXPCR0 @ RCPM_IPPDEXPCR0 */ + ldr x0, =RCPM_IPPDEXPCR0_OFFSET + bl read_reg_rcpm + mov x7, x0 + + /* build an override mask for IPSTPCR4/IPSTPACK4/DEVDISR5 */ + mov x5, xzr + ldr x6, =IPPDEXPCR_MASK2 + and x6, x6, x7 + cbz x6, 1f + + /* x5 = override mask + * x6 = IPPDEXPCR bits for DEVDISR5 + * x7 = IPPDEXPCR */ + + /* get the overrides */ + orr x4, x5, #DEVDISR5_I2C_1 + tst x6, #IPPDEXPCR_I2C1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_LPUART1 + tst x6, #IPPDEXPCR_LPUART1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_FLX_TMR + tst x6, #IPPDEXPCR_FLX_TMR1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_OCRAM1 + tst x6, #IPPDEXPCR_OCRAM1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR5_GPIO + tst x6, #IPPDEXPCR_GPIO1 + csel x5, x5, x4, EQ +1: + /* store the DEVDISR5 override mask */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + str w5, [x2, #DEVDISR5_MASK_OFFSET] + + /* build an override mask for IPSTPCR1/IPSTPACK1/DEVDISR2 */ + mov x5, xzr + ldr x6, =IPPDEXPCR_MASK1 + and x6, x6, x7 + cbz x6, 2f + + /* x5 = override mask */ + /* x6 = IPPDEXPCR bits for DEVDISR2 */ + + /* get the overrides */ + orr x4, x5, #DEVDISR2_FMAN1_MAC1 + tst x6, #IPPDEXPCR_MAC1_1 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC2 + tst x6, #IPPDEXPCR_MAC1_2 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC3 + tst x6, #IPPDEXPCR_MAC1_3 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC4 + tst x6, #IPPDEXPCR_MAC1_4 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC5 + tst x6, #IPPDEXPCR_MAC1_5 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC6 + tst x6, #IPPDEXPCR_MAC1_6 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1_MAC9 + tst x6, #IPPDEXPCR_MAC1_9 + csel x5, x5, x4, EQ + + orr x4, x5, #DEVDISR2_FMAN1 + tst x6, #IPPDEXPCR_FM1 + csel x5, x5, x4, EQ + +2: + /* store the DEVDISR2 override mask */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + str w5, [x2, #DEVDISR2_MASK_OFFSET] + + /* x5 = DEVDISR2 override mask */ + + /* write IPSTPCR0 - no overrides */ + ldr x0, =RCPM2_IPSTPCR0_OFFSET + ldr x1, =IPSTPCR0_VALUE + bl write_reg_rcpm2 + + /* x5 = DEVDISR2 override mask */ + + /* write IPSTPCR1 - overrides possible */ + ldr x0, =RCPM2_IPSTPCR1_OFFSET + ldr x1, =IPSTPCR1_VALUE + bic x1, x1, x5 + bl write_reg_rcpm2 + + /* write IPSTPCR2 - no overrides */ + ldr x0, =RCPM2_IPSTPCR2_OFFSET + ldr x1, =IPSTPCR2_VALUE + bl write_reg_rcpm2 + + /* write IPSTPCR3 - no overrides */ + ldr x0, =RCPM2_IPSTPCR3_OFFSET + ldr x1, =IPSTPCR3_VALUE + bl write_reg_rcpm2 + + /* write IPSTPCR4 - overrides possible */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + ldr w6, [x2, #DEVDISR5_MASK_OFFSET] + ldr x0, =RCPM2_IPSTPCR4_OFFSET + ldr x1, =IPSTPCR4_VALUE + bic x1, x1, x6 + bl write_reg_rcpm2 + + /* x5 = DEVDISR2 override mask */ + /* x6 = DEVDISR5 override mask */ + + /* poll on IPSTPACK0 */ + ldr x3, =RCPM2_IPSTPACKR0_OFFSET + ldr x4, =IPSTPCR0_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +3: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 14f + sub x7, x7, #1 + cbnz x7, 3b + +14: + /* poll on IPSTPACK1 */ + ldr x3, =IPSTPCR1_VALUE + ldr x7, =IPSTPACK_RETRY_CNT + bic x4, x3, x5 + ldr x3, =RCPM2_IPSTPACKR1_OFFSET +4: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 15f + sub x7, x7, #1 + cbnz x7, 4b + +15: + /* poll on IPSTPACK2 */ + ldr x3, =RCPM2_IPSTPACKR2_OFFSET + ldr x4, =IPSTPCR2_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +5: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 16f + sub x7, x7, #1 + cbnz x7, 5b + +16: + /* poll on IPSTPACK3 */ + ldr x3, =RCPM2_IPSTPACKR3_OFFSET + ldr x4, =IPSTPCR3_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +6: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 17f + sub x7, x7, #1 + cbnz x7, 6b + +17: + /* poll on IPSTPACK4 */ + ldr x3, =IPSTPCR4_VALUE + ldr x7, =IPSTPACK_RETRY_CNT + bic x4, x3, x6 + ldr x3, =RCPM2_IPSTPACKR4_OFFSET +7: + mov x0, x3 + bl read_reg_rcpm2 + cmp x0, x4 + b.eq 18f + sub x7, x7, #1 + cbnz x7, 7b + +18: + ldr x7, =BC_PSCI_BASE + add x7, x7, #AUX_01_DATA + + /* x5 = DEVDISR2 override mask + * x6 = DEVDISR5 override mask + * x7 = [soc_data_area] */ + + /* save DEVDISR1 and load new value */ + mov x0, #DCFG_DEVDISR1_OFFSET + bl read_reg_dcfg + mov w13, w0 + mov x0, #DCFG_DEVDISR1_OFFSET + ldr x1, =DEVDISR1_VALUE + bl write_reg_dcfg + + /* save DEVDISR2 and load new value */ + mov x0, #DCFG_DEVDISR2_OFFSET + bl read_reg_dcfg + mov w14, w0 + mov x0, #DCFG_DEVDISR2_OFFSET + ldr x1, =DEVDISR2_VALUE + bic x1, x1, x5 + bl write_reg_dcfg + + /* x6 = DEVDISR5 override mask */ + /* x7 = [soc_data_area] */ + + /* save DEVDISR3 and load new value */ + mov x0, #DCFG_DEVDISR3_OFFSET + bl read_reg_dcfg + mov w15, w0 + mov x0, #DCFG_DEVDISR3_OFFSET + ldr x1, =DEVDISR3_VALUE + bl write_reg_dcfg + + /* save DEVDISR4 and load new value */ + mov x0, #DCFG_DEVDISR4_OFFSET + bl read_reg_dcfg + mov w16, w0 + mov x0, #DCFG_DEVDISR4_OFFSET + ldr x1, =DEVDISR4_VALUE + bl write_reg_dcfg + + /* save DEVDISR5 and load new value */ + mov x0, #DCFG_DEVDISR5_OFFSET + bl read_reg_dcfg + mov w17, w0 + mov x0, #DCFG_DEVDISR5_OFFSET + ldr x1, =DEVDISR5_VALUE + bic x1, x1, x6 + bl write_reg_dcfg + + /* x7 = [soc_data_area] */ + + /* save cpuactlr and disable data prefetch */ + mrs x0, CPUACTLR_EL1 + str w0, [x7, #CPUACTLR_DATA_OFFSET] + bic x0, x0, #CPUACTLR_L1PCTL_MASK + msr CPUACTLR_EL1, x0 + + /* x6 = DEVDISR5 override mask */ + + /* setup registers for cache-only execution */ + ldr x5, =IPSTPCR4_VALUE + bic x5, x5, x6 + mov x6, #DDR_CNTRL_BASE_ADDR + mov x7, #DCSR_RCPM2_BASE + mov x8, #NXP_DCFG_ADDR + dsb sy + isb + + /* set the DLL_LOCK cycle count */ + ldr w1, [x6, #DDR_TIMING_CFG_4_OFFSET] + rev w2, w1 + bic w2, w2, #DLL_LOCK_MASK + orr w2, w2, #DLL_LOCK_VALUE + rev w1, w2 + str w1, [x6, #DDR_TIMING_CFG_4_OFFSET] + + /* + * x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK) + * x6 = DDR_CNTRL_BASE_ADDR + * x7 = DCSR_RCPM2_BASE + * x8 = NXP_DCFG_ADDR + * w13 = DEVDISR1 saved value + * w14 = DEVDISR2 saved value + * w15 = DEVDISR3 saved value + * w16 = DEVDISR4 saved value + * w17 = DEVDISR5 saved value + */ + + /* enter the cache-only sequence */ + mov x9, #CORE_RESTARTABLE + bl final_pwrdown + + /* when we are here, the core has come out of wfi and the SoC is back up */ + + mov x30, x18 + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_sys_exit_pwrdn: + /* clear POWMGTDCR */ + mov x1, #DCSR_RCPM2_BASE + str wzr, [x1, #RCPM2_POWMGTDCR_OFFSET] + + /* clear WFIL2_EN in SCFG_COREPMCR */ + mov x1, #NXP_SCFG_ADDR + str wzr, [x1, #SCFG_COREPMCR_OFFSET] + + ret + +/* + * write a register in the SCFG block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2, x3 + */ +write_reg_scfg: + ldr x2, =NXP_SCFG_ADDR + /* swap for BE */ + rev w3, w1 + str w3, [x2, x0] + ret +/* + * read a register in the SCFG block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +read_reg_scfg: + ldr x2, =NXP_SCFG_ADDR + ldr w1, [x2, x0] + /* swap for BE */ + rev w0, w1 + ret + +/* + * write a register in the DCFG block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2, x3 + */ +write_reg_dcfg: + ldr x2, =NXP_DCFG_ADDR + /* swap for BE */ + rev w3, w1 + str w3, [x2, x0] + ret + +/* + * read a register in the DCFG block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +read_reg_dcfg: + ldr x2, =NXP_DCFG_ADDR + ldr w1, [x2, x0] + /* swap for BE */ + rev w0, w1 + ret + +/* + * write a register in the RCPM block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2, x3 + */ +write_reg_rcpm: + ldr x2, =NXP_RCPM_ADDR + /* swap for BE */ + rev w3, w1 + str w3, [x2, x0] + ret + +/* + * read a register in the RCPM block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +read_reg_rcpm: + ldr x2, =NXP_RCPM_ADDR + ldr w1, [x2, x0] + /* swap for BE */ + rev w0, w1 + ret + +/* + * write a register in the DCSR-RCPM2 block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2, x3 + */ +write_reg_rcpm2: + ldr x2, =DCSR_RCPM2_BASE + /* swap for BE */ + rev w3, w1 + str w3, [x2, x0] + ret + +/* + * read a register in the DCSR-RCPM2 block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +read_reg_rcpm2: + ldr x2, =DCSR_RCPM2_BASE + ldr w1, [x2, x0] + /* swap for BE */ + rev w0, w1 + ret + +/* + * this function returns the base address of the gic distributor + * in: none + * out: x0 = base address of gic distributor + * uses x0, x1 + */ +_getGICD_BaseAddr: + /* read SVR and get the SoC version */ + mov x0, #NXP_DCFG_ADDR + ldr w1, [x0, #DCFG_SVR_OFFSET] + rev w0, w1 + + /* x0 = svr */ + and w0, w0, #SVR_MIN_VER_MASK + cmp w0, #SVR_MINOR_VER_0 + b.ne 8f + + /* load the gic base addresses for rev 1.0 parts */ + ldr x0, =NXP_GICD_4K_ADDR + b 10f +8: + /* for rev 1.1 and later parts, the GIC base addresses */ + /* can be at 4k or 64k offsets */ + + /* read the scfg reg GIC400_ADDR_ALIGN */ + mov x0, #NXP_SCFG_ADDR + ldr w1, [x0, #SCFG_GIC400_ADDR_ALIGN_OFFSET] + rev w0, w1 + + /* x0 = GIC400_ADDR_ALIGN value */ + and x0, x0, #SCFG_GIC400_ADDR_ALIGN_4KMODE_MASK + mov x1, #SCFG_GIC400_ADDR_ALIGN_4KMODE_EN + cmp x0, x1 + b.ne 9f + + /* load the base addresses for 4k offsets */ + ldr x0, =NXP_GICD_4K_ADDR + b 10f +9: + /* load the base address for 64k offsets */ + ldr x0, =NXP_GICD_64K_ADDR +10: + ret + +/* + * this function returns the base address of the gic distributor + * in: none + * out: x0 = base address of gic controller + * uses x0, x1 + */ +_getGICC_BaseAddr: + /* read SVR and get the SoC version */ + mov x0, #NXP_DCFG_ADDR + ldr w1, [x0, #DCFG_SVR_OFFSET] + rev w0, w1 + + /* x0 = svr */ + and w0, w0, #SVR_MIN_VER_MASK + cmp w0, #SVR_MINOR_VER_0 + b.ne 8f + + /* load the gic base addresses for rev 1.0 parts */ + ldr x0, =NXP_GICC_4K_ADDR + b 10f +8: + /* for rev 1.1 and later parts, the GIC base addresses */ + /* can be at 4k or 64k offsets */ + + /* read the scfg reg GIC400_ADDR_ALIGN */ + mov x0, #NXP_SCFG_ADDR + ldr w1, [x0, #SCFG_GIC400_ADDR_ALIGN_OFFSET] + rev w0, w1 + + /* x0 = GIC400_ADDR_ALIGN value */ + and x0, x0, #SCFG_GIC400_ADDR_ALIGN_4KMODE_MASK + mov x1, #SCFG_GIC400_ADDR_ALIGN_4KMODE_EN + cmp x0, x1 + b.ne 9f + + /* load the base addresses for 4k offsets */ + ldr x0, =NXP_GICC_4K_ADDR + b 10f +9: + /* load the base address for 64k offsets */ + ldr x0, =NXP_GICC_64K_ADDR +10: + ret + +/* + * this function will pwrdown ddr and the final core - it will do this + * by loading itself into the icache and then executing from there + * in: x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK) + * x6 = DDR_CNTRL_BASE_ADDR + * x7 = DCSR_RCPM2_BASE + * x8 = NXP_DCFG_ADDR + * x9 = 0, restartable + * = 1, non-restartable + * w13 = DEVDISR1 saved value + * w14 = DEVDISR2 saved value + * w15 = DEVDISR3 saved value + * w16 = DEVDISR4 saved value + * w17 = DEVDISR5 saved value + * out: none + * uses x0 ~ x9 + */ + +/* 4Kb aligned */ +.align 12 +final_pwrdown: + mov x0, xzr + b touch_line_0 +start_line_0: + mov x0, #1 + mov x2, #DDR_SDRAM_CFG_2_FRCSR /* put ddr in self refresh - start */ + ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + rev w4, w3 + orr w4, w4, w2 + rev w3, w4 + str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] /* put ddr in self refresh - end */ + orr w3, w5, #DEVDISR5_MEM /* quiesce ddr clocks - start */ + rev w4, w3 + str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* quiesce ddr clocks - end */ + + mov w3, #DEVDISR5_MEM + rev w3, w3 /* polling mask */ + mov x2, #DDR_SLEEP_RETRY_CNT /* poll on ipstpack4 - start */ +touch_line_0: + cbz x0, touch_line_1 + +start_line_1: + ldr w1, [x7, #RCPM2_IPSTPACKR4_OFFSET] + tst w1, w3 + b.ne 1f + subs x2, x2, #1 + b.gt start_line_1 /* poll on ipstpack4 - end */ + + /* if we get here, we have a timeout err */ + rev w4, w5 + str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* re-enable ddr clks interface */ + mov x0, #ERROR_DDR_SLEEP /* load error code */ + b 2f +1: + str w4, [x8, #DCFG_DEVDISR5_OFFSET] /* disable ddr cntrlr clk in devdisr5 */ +5: + wfi /* stop the final core */ + + cbnz x9, 5b /* if non-restartable, keep in wfi */ + rev w4, w5 + str w4, [x8, #DCFG_DEVDISR5_OFFSET] /* re-enable ddr in devdisr5 */ + str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* re-enable ddr clk in ipstpcr4 */ +touch_line_1: + cbz x0, touch_line_2 + +start_line_2: + ldr w1, [x7, #RCPM2_IPSTPACKR4_OFFSET] /* poll on ipstpack4 - start */ + tst w1, w3 + b.eq 2f + nop + b start_line_2 /* poll on ipstpack4 - end */ +2: + mov x2, #DDR_SDRAM_CFG_2_FRCSR /* take ddr out-of self refresh - start */ + ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + rev w4, w3 + bic w4, w4, w2 + rev w3, w4 + mov x1, #DDR_SLEEP_RETRY_CNT /* wait for ddr cntrlr clock - start */ +3: + subs x1, x1, #1 + b.gt 3b /* wait for ddr cntrlr clock - end */ + str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] /* take ddr out-of self refresh - end */ + rev w1, w17 +touch_line_2: + cbz x0, touch_line_3 + +start_line_3: + str w1, [x8, #DCFG_DEVDISR5_OFFSET] /* reset devdisr5 */ + rev w1, w16 + str w1, [x8, #DCFG_DEVDISR4_OFFSET] /* reset devdisr4 */ + rev w1, w15 + str w1, [x8, #DCFG_DEVDISR3_OFFSET] /* reset devdisr3 */ + rev w1, w14 + str w1, [x8, #DCFG_DEVDISR2_OFFSET] /* reset devdisr2 */ + rev w1, w13 + str w1, [x8, #DCFG_DEVDISR1_OFFSET] /* reset devdisr1 */ + str wzr, [x7, #RCPM2_IPSTPCR4_OFFSET] /* reset ipstpcr4 */ + str wzr, [x7, #RCPM2_IPSTPCR3_OFFSET] /* reset ipstpcr3 */ + str wzr, [x7, #RCPM2_IPSTPCR2_OFFSET] /* reset ipstpcr2 */ + str wzr, [x7, #RCPM2_IPSTPCR1_OFFSET] /* reset ipstpcr1 */ + str wzr, [x7, #RCPM2_IPSTPCR0_OFFSET] /* reset ipstpcr0 */ + b continue_restart +touch_line_3: + cbz x0, start_line_0 + +/* execute here after ddr is back up */ +continue_restart: + /* + * if x0 = 1, all is well + * if x0 < 1, we had an error + */ + cmp x0, #1 + b.ne 4f + mov x0, #0 +4: + ret + +/* + * Note: there is no return from this function + * this function will shutdown ddr and the final core - it will do this + * by loading itself into the icache and then executing from there + * in: x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK) + * x6 = DDR_CNTRL_BASE_ADDR + * x7 = DCSR_RCPM2_BASE + * x8 = NXP_DCFG_ADDR + * out: none + * uses x0 ~ x8 + */ + +/* 4Kb aligned */ +.align 12 +final_shutdown: + + mov x0, xzr + b touch_line0 +start_line0: + mov x0, #1 + mov x2, #DDR_SDRAM_CFG_2_FRCSR /* put ddr in self refresh - start */ + ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + rev w4, w3 + orr w4, w4, w2 + rev w3, w4 + str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] /* put ddr in self refresh - end */ + orr w3, w5, #DEVDISR5_MEM /* quiesce ddr clocks - start */ + rev w4, w3 + str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* quiesce ddr clocks - end */ + + mov w3, #DEVDISR5_MEM + rev w3, w3 /* polling mask */ + mov x2, #DDR_SLEEP_RETRY_CNT /* poll on ipstpack4 - start */ +touch_line0: + cbz x0, touch_line1 + +start_line1: + ldr w1, [x7, #RCPM2_IPSTPACKR4_OFFSET] + tst w1, w3 + b.ne 1f + subs x2, x2, #1 + b.gt start_line1 /* poll on ipstpack4 - end */ + nop + nop + nop + nop +1: + str w4, [x8, #DCFG_DEVDISR5_OFFSET] /* disable ddr cntrlr clk in devdisr5 */ +5: + wfi /* stop the final core */ + b 5b /* stay here until POR */ + nop + nop + nop +touch_line1: + cbz x0, start_line0 diff --git a/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S b/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S new file mode 100644 index 0000000..bc88886 --- /dev/null +++ b/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S @@ -0,0 +1,70 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> + +#include <platform_def.h> + + .globl plat_secondary_cold_boot_setup + .globl plat_is_my_cpu_primary + .globl plat_reset_handler + .globl platform_mem_init + +func platform_mem1_init + ret +endfunc platform_mem1_init + +func platform_mem_init + ret +endfunc platform_mem_init + +func apply_platform_errata + ret +endfunc apply_platform_errata + +func plat_reset_handler + mov x29, x30 + bl apply_platform_errata + +#if defined(IMAGE_BL31) + ldr x0, =POLICY_SMMU_PAGESZ_64K + cbz x0, 1f + /* Set the SMMU page size in the sACR register */ + bl _set_smmu_pagesz_64 +#endif +1: + mov x30, x29 + ret +endfunc plat_reset_handler + +/* + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + */ +func plat_secondary_cold_boot_setup + /* ls1043a does not do cold boot for secondary CPU */ +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + +/* + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, 0x0 + cset w0, eq + ret +endfunc plat_is_my_cpu_primary diff --git a/plat/nxp/soc-ls1043a/include/ns_access.h b/plat/nxp/soc-ls1043a/include/ns_access.h new file mode 100644 index 0000000..423c454 --- /dev/null +++ b/plat/nxp/soc-ls1043a/include/ns_access.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2015, 2016 Freescale Semiconductor, Inc. + * Copyright 2017-2018, 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NS_ACCESS_H +#define NS_ACCESS_H + +#include <csu.h> + +enum csu_cslx_ind { + CSU_CSLX_PCIE2_IO = 0, + CSU_CSLX_PCIE1_IO, + CSU_CSLX_MG2TPR_IP, + CSU_CSLX_IFC_MEM, + CSU_CSLX_OCRAM, + CSU_CSLX_GIC, + CSU_CSLX_PCIE1, + CSU_CSLX_OCRAM2, + CSU_CSLX_QSPI_MEM, + CSU_CSLX_PCIE2, + CSU_CSLX_SATA, + CSU_CSLX_USB1, + CSU_CSLX_QM_BM_SWPORTAL, + CSU_CSLX_PCIE3 = 16, + CSU_CSLX_PCIE3_IO, + CSU_CSLX_USB3 = 20, + CSU_CSLX_USB2, + CSU_CSLX_PFE = 23, + CSU_CSLX_SERDES = 32, + CSU_CSLX_QDMA, + CSU_CSLX_LPUART2, + CSU_CSLX_LPUART1, + CSU_CSLX_LPUART4, + CSU_CSLX_LPUART3, + CSU_CSLX_LPUART6, + CSU_CSLX_LPUART5, + CSU_CSLX_DSPI1 = 41, + CSU_CSLX_QSPI, + CSU_CSLX_ESDHC, + CSU_CSLX_IFC = 45, + CSU_CSLX_I2C1, + CSU_CSLX_USB_2, + CSU_CSLX_I2C3 = 48, + CSU_CSLX_I2C2, + CSU_CSLX_DUART2 = 50, + CSU_CSLX_DUART1, + CSU_CSLX_WDT2, + CSU_CSLX_WDT1, + CSU_CSLX_EDMA, + CSU_CSLX_SYS_CNT, + CSU_CSLX_DMA_MUX2, + CSU_CSLX_DMA_MUX1, + CSU_CSLX_DDR, + CSU_CSLX_QUICC, + CSU_CSLX_DCFG_CCU_RCPM = 60, + CSU_CSLX_SECURE_BOOTROM, + CSU_CSLX_SFP, + CSU_CSLX_TMU, + CSU_CSLX_SECURE_MONITOR, + CSU_CSLX_SCFG, + CSU_CSLX_FM = 66, + CSU_CSLX_SEC5_5, + CSU_CSLX_BM, + CSU_CSLX_QM, + CSU_CSLX_GPIO2 = 70, + CSU_CSLX_GPIO1, + CSU_CSLX_GPIO4, + CSU_CSLX_GPIO3, + CSU_CSLX_PLATFORM_CONT, + CSU_CSLX_CSU, + CSU_CSLX_IIC4 = 77, + CSU_CSLX_WDT4, + CSU_CSLX_WDT3, + CSU_CSLX_ESDHC2 = 80, + CSU_CSLX_WDT5 = 81, + CSU_CSLX_SAI2, + CSU_CSLX_SAI1, + CSU_CSLX_SAI4, + CSU_CSLX_SAI3, + CSU_CSLX_FTM2 = 86, + CSU_CSLX_FTM1, + CSU_CSLX_FTM4, + CSU_CSLX_FTM3, + CSU_CSLX_FTM6 = 90, + CSU_CSLX_FTM5, + CSU_CSLX_FTM8, + CSU_CSLX_FTM7, + CSU_CSLX_DSCR = 121, +}; + +struct csu_ns_dev_st ns_dev[] = { + {CSU_CSLX_PCIE2_IO, CSU_ALL_RW}, + {CSU_CSLX_PCIE1_IO, CSU_ALL_RW}, + {CSU_CSLX_MG2TPR_IP, CSU_ALL_RW}, + {CSU_CSLX_IFC_MEM, CSU_ALL_RW}, + {CSU_CSLX_OCRAM, CSU_S_SUP_RW}, + {CSU_CSLX_GIC, CSU_ALL_RW}, + {CSU_CSLX_PCIE1, CSU_ALL_RW}, + {CSU_CSLX_OCRAM2, CSU_S_SUP_RW}, + {CSU_CSLX_QSPI_MEM, CSU_ALL_RW}, + {CSU_CSLX_PCIE2, CSU_ALL_RW}, + {CSU_CSLX_SATA, CSU_ALL_RW}, + {CSU_CSLX_USB1, CSU_ALL_RW}, + {CSU_CSLX_QM_BM_SWPORTAL, CSU_ALL_RW}, + {CSU_CSLX_PCIE3, CSU_ALL_RW}, + {CSU_CSLX_PCIE3_IO, CSU_ALL_RW}, + {CSU_CSLX_USB3, CSU_ALL_RW}, + {CSU_CSLX_USB2, CSU_ALL_RW}, + {CSU_CSLX_PFE, CSU_ALL_RW}, + {CSU_CSLX_SERDES, CSU_ALL_RW}, + {CSU_CSLX_QDMA, CSU_ALL_RW}, + {CSU_CSLX_LPUART2, CSU_ALL_RW}, + {CSU_CSLX_LPUART1, CSU_ALL_RW}, + {CSU_CSLX_LPUART4, CSU_ALL_RW}, + {CSU_CSLX_LPUART3, CSU_ALL_RW}, + {CSU_CSLX_LPUART6, CSU_ALL_RW}, + {CSU_CSLX_LPUART5, CSU_ALL_RW}, + {CSU_CSLX_DSPI1, CSU_ALL_RW}, + {CSU_CSLX_QSPI, CSU_ALL_RW}, + {CSU_CSLX_ESDHC, CSU_ALL_RW}, + {CSU_CSLX_IFC, CSU_ALL_RW}, + {CSU_CSLX_I2C1, CSU_ALL_RW}, + {CSU_CSLX_USB_2, CSU_ALL_RW}, + {CSU_CSLX_I2C3, CSU_ALL_RW}, + {CSU_CSLX_I2C2, CSU_ALL_RW}, + {CSU_CSLX_DUART2, CSU_ALL_RW}, + {CSU_CSLX_DUART1, CSU_ALL_RW}, + {CSU_CSLX_WDT2, CSU_ALL_RW}, + {CSU_CSLX_WDT1, CSU_ALL_RW}, + {CSU_CSLX_EDMA, CSU_ALL_RW}, + {CSU_CSLX_SYS_CNT, CSU_ALL_RW}, + {CSU_CSLX_DMA_MUX2, CSU_ALL_RW}, + {CSU_CSLX_DMA_MUX1, CSU_ALL_RW}, + {CSU_CSLX_DDR, CSU_ALL_RW}, + {CSU_CSLX_QUICC, CSU_ALL_RW}, + {CSU_CSLX_DCFG_CCU_RCPM, CSU_ALL_RW}, + {CSU_CSLX_SECURE_BOOTROM, CSU_ALL_RW}, + {CSU_CSLX_SFP, CSU_ALL_RW}, + {CSU_CSLX_TMU, CSU_ALL_RW}, + {CSU_CSLX_SECURE_MONITOR, CSU_ALL_RW}, + {CSU_CSLX_SCFG, CSU_ALL_RW}, + {CSU_CSLX_FM, CSU_ALL_RW}, + {CSU_CSLX_SEC5_5, CSU_ALL_RW}, + {CSU_CSLX_BM, CSU_ALL_RW}, + {CSU_CSLX_QM, CSU_ALL_RW}, + {CSU_CSLX_GPIO2, CSU_ALL_RW}, + {CSU_CSLX_GPIO1, CSU_ALL_RW}, + {CSU_CSLX_GPIO4, CSU_ALL_RW}, + {CSU_CSLX_GPIO3, CSU_ALL_RW}, + {CSU_CSLX_PLATFORM_CONT, CSU_ALL_RW}, + {CSU_CSLX_CSU, CSU_ALL_RW}, + {CSU_CSLX_IIC4, CSU_ALL_RW}, + {CSU_CSLX_WDT4, CSU_ALL_RW}, + {CSU_CSLX_WDT3, CSU_ALL_RW}, + {CSU_CSLX_ESDHC2, CSU_ALL_RW}, + {CSU_CSLX_WDT5, CSU_ALL_RW}, + {CSU_CSLX_SAI2, CSU_ALL_RW}, + {CSU_CSLX_SAI1, CSU_ALL_RW}, + {CSU_CSLX_SAI4, CSU_ALL_RW}, + {CSU_CSLX_SAI3, CSU_ALL_RW}, + {CSU_CSLX_FTM2, CSU_ALL_RW}, + {CSU_CSLX_FTM1, CSU_ALL_RW}, + {CSU_CSLX_FTM4, CSU_ALL_RW}, + {CSU_CSLX_FTM3, CSU_ALL_RW}, + {CSU_CSLX_FTM6, CSU_ALL_RW}, + {CSU_CSLX_FTM5, CSU_ALL_RW}, + {CSU_CSLX_FTM8, CSU_ALL_RW}, + {CSU_CSLX_FTM7, CSU_ALL_RW}, + {CSU_CSLX_DSCR, CSU_ALL_RW}, +}; + +#endif /* NS_ACCESS_H */ diff --git a/plat/nxp/soc-ls1043a/include/soc.h b/plat/nxp/soc-ls1043a/include/soc.h new file mode 100644 index 0000000..e018102 --- /dev/null +++ b/plat/nxp/soc-ls1043a/include/soc.h @@ -0,0 +1,234 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOC_H +#define SOC_H + +/* Chassis specific defines - common across SoC's of a particular platform */ +#include "dcfg_lsch2.h" +#include "soc_default_base_addr.h" +#include "soc_default_helper_macros.h" + +/* DDR Regions Info */ +#define NUM_DRAM_REGIONS 3 +#define NXP_DRAM0_ADDR 0x80000000 +#define NXP_DRAM0_MAX_SIZE 0x80000000 /* 2 GB */ + +#define NXP_DRAM1_ADDR 0x880000000 +#define NXP_DRAM1_MAX_SIZE 0x780000000 /* 30 GB */ + +#define NXP_DRAM2_ADDR 0x8800000000 +#define NXP_DRAM2_MAX_SIZE 0x7800000000 /* 480 GB */ +/* DRAM0 Size defined in platform_def.h */ +#define NXP_DRAM0_SIZE PLAT_DEF_DRAM0_SIZE + +/* + * P23: 23 x 23 package + * A: without security + * AE: with security + * SVR Definition (not include major and minor rev) + */ +#define SVR_LS1023A 0x879209 +#define SVR_LS1023AE 0x879208 +#define SVR_LS1023A_P23 0x87920B +#define SVR_LS1023AE_P23 0x87920A +#define SVR_LS1043A 0x879201 +#define SVR_LS1043AE 0x879200 +#define SVR_LS1043A_P23 0x879203 +#define SVR_LS1043AE_P23 0x879202 + +/* Number of cores in platform */ +#define PLATFORM_CORE_COUNT 4 +#define NUMBER_OF_CLUSTERS 1 +#define CORES_PER_CLUSTER 4 + +/* set to 0 if the clusters are not symmetrical */ +#define SYMMETRICAL_CLUSTERS 1 + +/* + * Required LS standard platform porting definitions + * for CCI-400 + */ +#define NXP_CCI_CLUSTER0_SL_IFACE_IX 4 + +/* ls1043 version info for GIC configuration */ +#define REV1_0 0x10 +#define REV1_1 0x11 +#define GIC_ADDR_BIT 31 + +/* Errata */ +#define NXP_ERRATUM_A009663 +#define NXP_ERRATUM_A009942 + +#define NUM_OF_DDRC 1 + +/* Defines required for using XLAT tables from ARM common code */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 40) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 40) + +/* Clock Divisors */ +#define NXP_PLATFORM_CLK_DIVIDER 1 +#define NXP_UART_CLK_DIVIDER 1 + +/* + * Set this switch to 1 if you need to keep the debug block + * clocked during system power-down. + */ +#define DEBUG_ACTIVE 0 + +#define IPPDEXPCR_MAC1_1 0x80000000 // DEVDISR2_FMAN1_MAC1 +#define IPPDEXPCR_MAC1_2 0x40000000 // DEVDISR2_FMAN1_MAC2 +#define IPPDEXPCR_MAC1_3 0x20000000 // DEVDISR2_FMAN1_MAC3 +#define IPPDEXPCR_MAC1_4 0x10000000 // DEVDISR2_FMAN1_MAC4 +#define IPPDEXPCR_MAC1_5 0x08000000 // DEVDISR2_FMAN1_MAC5 +#define IPPDEXPCR_MAC1_6 0x04000000 // DEVDISR2_FMAN1_MAC6 +#define IPPDEXPCR_MAC1_9 0x00800000 // DEVDISR2_FMAN1_MAC9 +#define IPPDEXPCR_I2C1 0x00080000 // DEVDISR5_I2C_1 +#define IPPDEXPCR_LPUART1 0x00040000 // DEVDISR5_LPUART1 +#define IPPDEXPCR_FLX_TMR1 0x00020000 // DEVDISR5_FLX_TMR +#define IPPDEXPCR_OCRAM1 0x00010000 // DEVDISR5_OCRAM1 +#define IPPDEXPCR_GPIO1 0x00000040 // DEVDISR5_GPIO +#define IPPDEXPCR_FM1 0x00000008 // DEVDISR2_FMAN1 + +#define IPPDEXPCR_MASK1 0xFC800008 // overrides for DEVDISR2 +#define IPPDEXPCR_MASK2 0x000F0040 // overriddes for DEVDISR5 + +#define IPSTPCR0_VALUE 0xA000C201 +#define IPSTPCR1_VALUE 0x00000080 +#define IPSTPCR2_VALUE 0x000C0000 +#define IPSTPCR3_VALUE 0x38000000 +#if (DEBUG_ACTIVE) + #define IPSTPCR4_VALUE 0x10833BFC +#else + #define IPSTPCR4_VALUE 0x10A33BFC +#endif + +#define DEVDISR1_QE 0x00000001 +#define DEVDISR1_SEC 0x00000200 +#define DEVDISR1_USB1 0x00004000 +#define DEVDISR1_SATA 0x00008000 +#define DEVDISR1_USB2 0x00010000 +#define DEVDISR1_USB3 0x00020000 +#define DEVDISR1_DMA2 0x00400000 +#define DEVDISR1_DMA1 0x00800000 +#define DEVDISR1_ESDHC 0x20000000 +#define DEVDISR1_PBL 0x80000000 + +#define DEVDISR2_FMAN1 0x00000080 +#define DEVDISR2_FMAN1_MAC9 0x00800000 +#define DEVDISR2_FMAN1_MAC6 0x04000000 +#define DEVDISR2_FMAN1_MAC5 0x08000000 +#define DEVDISR2_FMAN1_MAC4 0x10000000 +#define DEVDISR2_FMAN1_MAC3 0x20000000 +#define DEVDISR2_FMAN1_MAC2 0x40000000 +#define DEVDISR2_FMAN1_MAC1 0x80000000 + +#define DEVDISR3_BMAN 0x00040000 +#define DEVDISR3_QMAN 0x00080000 +#define DEVDISR3_PEX3 0x20000000 +#define DEVDISR3_PEX2 0x40000000 +#define DEVDISR3_PEX1 0x80000000 + +#define DEVDISR4_QSPI 0x08000000 +#define DEVDISR4_DUART2 0x10000000 +#define DEVDISR4_DUART1 0x20000000 + +#define DEVDISR5_ICMMU 0x00000001 +#define DEVDISR5_I2C_1 0x00000002 +#define DEVDISR5_I2C_2 0x00000004 +#define DEVDISR5_I2C_3 0x00000008 +#define DEVDISR5_I2C_4 0x00000010 +#define DEVDISR5_WDG_5 0x00000020 +#define DEVDISR5_WDG_4 0x00000040 +#define DEVDISR5_WDG_3 0x00000080 +#define DEVDISR5_DSPI1 0x00000100 +#define DEVDISR5_WDG_2 0x00000200 +#define DEVDISR5_FLX_TMR 0x00000400 +#define DEVDISR5_WDG_1 0x00000800 +#define DEVDISR5_LPUART6 0x00001000 +#define DEVDISR5_LPUART5 0x00002000 +#define DEVDISR5_LPUART3 0x00008000 +#define DEVDISR5_LPUART2 0x00010000 +#define DEVDISR5_LPUART1 0x00020000 +#define DEVDISR5_DBG 0x00200000 +#define DEVDISR5_GPIO 0x00400000 +#define DEVDISR5_IFC 0x00800000 +#define DEVDISR5_OCRAM2 0x01000000 +#define DEVDISR5_OCRAM1 0x02000000 +#define DEVDISR5_LPUART4 0x10000000 +#define DEVDISR5_DDR 0x80000000 +#define DEVDISR5_MEM 0x80000000 + +#define DEVDISR1_VALUE 0xA0C3C201 +#define DEVDISR2_VALUE 0xCC0C0080 +#define DEVDISR3_VALUE 0xE00C0000 +#define DEVDISR4_VALUE 0x38000000 +#if (DEBUG_ACTIVE) + #define DEVDISR5_VALUE 0x10833BFC +#else + #define DEVDISR5_VALUE 0x10A33BFC +#endif + +/* + * PWR mgmt features supported in the soc-specific code: + * value == 0x0 the soc code does not support this feature + * value != 0x0 the soc code supports this feature + */ +#define SOC_CORE_RELEASE 0x1 +#define SOC_CORE_RESTART 0x1 +#define SOC_CORE_OFF 0x1 +#define SOC_CORE_STANDBY 0x1 +#define SOC_CORE_PWR_DWN 0x1 +#define SOC_CLUSTER_STANDBY 0x1 +#define SOC_CLUSTER_PWR_DWN 0x1 +#define SOC_SYSTEM_STANDBY 0x1 +#define SOC_SYSTEM_PWR_DWN 0x1 +#define SOC_SYSTEM_OFF 0x1 +#define SOC_SYSTEM_RESET 0x1 + +/* PSCI-specific defines */ +#define SYSTEM_PWR_DOMAINS 1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + NUMBER_OF_CLUSTERS + \ + SYSTEM_PWR_DOMAINS) + +/* Power state coordination occurs at the system level */ +#define PLAT_PD_COORD_LVL MPIDR_AFFLVL2 +#define PLAT_MAX_PWR_LVL PLAT_PD_COORD_LVL + +/* Local power state for power domains in Run state */ +#define LS_LOCAL_STATE_RUN PSCI_LOCAL_STATE_RUN + +/* define retention state */ +#define PLAT_MAX_RET_STATE (PSCI_LOCAL_STATE_RUN + 1) +#define LS_LOCAL_STATE_RET PLAT_MAX_RET_STATE + +/* define power-down state */ +#define PLAT_MAX_OFF_STATE (PLAT_MAX_RET_STATE + 1) +#define LS_LOCAL_STATE_OFF PLAT_MAX_OFF_STATE + +/* + * Some data must be aligned on the biggest cache line size in the platform. + * This is known only to the platform as it might have a combination of + * integrated and external caches. + * CACHE_WRITEBACK_GRANULE is defined in soc.def + */ + +/* One cache line needed for bakery locks on ARM platforms */ +#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE) + +#ifndef __ASSEMBLER__ +/* CCI slave interfaces */ +static const int cci_map[] = { + NXP_CCI_CLUSTER0_SL_IFACE_IX, +}; +void soc_init_lowlevel(void); +void soc_init_percpu(void); +void _soc_set_start_addr(unsigned long addr); + +#endif + +#endif /* SOC_H */ diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c b/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c new file mode 100644 index 0000000..28e2dab --- /dev/null +++ b/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c @@ -0,0 +1,163 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <string.h> + +#include <common/debug.h> +#include <ddr.h> +#include <lib/utils.h> + +#include <errata.h> +#include <platform_def.h> + +#ifdef CONFIG_STATIC_DDR +const struct ddr_cfg_regs static_1600 = { + .cs[0].config = U(0x80040322), + .cs[0].bnds = U(0x7F), + .sdram_cfg[0] = U(0xC50C0000), + .sdram_cfg[1] = U(0x401100), + .timing_cfg[0] = U(0x91550018), + .timing_cfg[1] = U(0xBBB48C42), + .timing_cfg[2] = U(0x48C111), + .timing_cfg[3] = U(0x10C1000), + .timing_cfg[4] = U(0x2), + .timing_cfg[5] = U(0x3401400), + .timing_cfg[7] = U(0x13300000), + .timing_cfg[8] = U(0x2115600), + .sdram_mode[0] = U(0x3010210), + .sdram_mode[9] = U(0x4000000), + .sdram_mode[8] = U(0x500), + .sdram_mode[2] = U(0x10210), + .sdram_mode[10] = U(0x400), + .sdram_mode[11] = U(0x4000000), + .sdram_mode[4] = U(0x10210), + .sdram_mode[12] = U(0x400), + .sdram_mode[13] = U(0x4000000), + .sdram_mode[6] = U(0x10210), + .sdram_mode[14] = U(0x400), + .sdram_mode[15] = U(0x4000000), + .interval = U(0x18600618), + .zq_cntl = U(0x8A090705), + .clk_cntl = U(0x3000000), + .cdr[0] = U(0x80040000), + .cdr[1] = U(0xA181), + .wrlvl_cntl[0] = U(0x8675F607), + .wrlvl_cntl[1] = U(0x7090807, + .wrlvl_cntl[2] = U(0x7070707), + .debug[28] = U(0x00700046), +}; + +uint64_t board_static_ddr(struct ddr_info *priv) +{ + memcpy(&priv->ddr_reg, &static_1600, sizeof(static_1600)); + + return ULL(0x80000000); +} + +#else +static const struct rc_timing rcz[] = { + {1600, 12, 7}, + {} +}; + +static const struct board_timing ram[] = { + {0x1f, rcz, 0x00020100, 0}, +}; + +int ddr_board_options(struct ddr_info *priv) +{ + int ret; + struct memctl_opt *popts = &priv->opt; + + ret = cal_board_params(priv, ram, ARRAY_SIZE(ram)); + if (ret) + return ret; + + popts->cpo_sample = U(0x46); + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | + DDR_CDR1_ODT(DDR_CDR_ODT_80ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) | + DDR_CDR2_VREF_OVRD(70); /* Vref = 70% */ + + return 0; +} + +/* DDR model number: MT40A1G8SA-062E:R */ +struct dimm_params ddr_raw_timing = { + .n_ranks = U(1), + .rank_density = ULL(2147483648), + .capacity = ULL(2147483648), + .primary_sdram_width = U(32), + .ec_sdram_width = U(4), + .rdimm = U(0), + .mirrored_dimm = U(0), + .n_row_addr = U(16), + .n_col_addr = U(10), + .bank_group_bits = U(2), + .edc_config = U(2), + .burst_lengths_bitmask = U(0x0c), + .tckmin_x_ps = 625, + .tckmax_ps = 2200, + .caslat_x = U(0x0001FFE00), + .taa_ps = 13500, + .trcd_ps = 13500, + .trp_ps = 13500, + .tras_ps = 32000, + .trc_ps = 45500, + .twr_ps = 15000, + .trfc1_ps = 350000, + .trfc2_ps = 260000, + .trfc4_ps = 160000, + .tfaw_ps = 21000, + .trrds_ps = 3000, + .trrdl_ps = 4900, + .tccdl_ps = 5000, + .refresh_rate_ps = U(7800000), + .rc = U(0x1f), +}; + +int ddr_get_ddr_params(struct dimm_params *pdimm, + struct ddr_conf *conf) +{ + static const char dimm_model[] = "Fixed DDR on board"; + + conf->dimm_in_use[0] = 1; + memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params)); + memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1); + + return 1; +} +#endif + +int64_t init_ddr(void) +{ + struct ddr_info info; + struct sysinfo sys; + int64_t dram_size; + + zeromem(&sys, sizeof(sys)); + get_clocks(&sys); + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0); + debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1); + + zeromem(&info, sizeof(struct ddr_info)); + info.num_ctlrs = 1; + info.dimm_on_ctlr = 1; + info.clk = get_ddr_freq(&sys, 0); + info.ddr[0] = (void *)NXP_DDR_ADDR; + + dram_size = dram_init(&info); + + if (dram_size < 0) { + ERROR("DDR init failed\n"); + } + +#ifdef ERRATA_SOC_A008850 + erratum_a008850_post(); +#endif + return dram_size; +} diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h b/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h new file mode 100644 index 0000000..249f457 --- /dev/null +++ b/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h @@ -0,0 +1,79 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include <arch.h> +/* + * Required without TBBR. + * To include the defines for DDR PHY Images. + */ +#include <tbbr_img_def.h> + +#include "policy.h" +#include <soc.h> + +#define NXP_SPD_EEPROM0 0x51 + +#define NXP_SYSCLK_FREQ 100000000 +#define NXP_DDRCLK_FREQ 100000000 + +/* UART related definition */ +#define NXP_CONSOLE_ADDR NXP_UART_ADDR +#define NXP_CONSOLE_BAUDRATE 115200 + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL2) +#if defined(TRUSTED_BOARD_BOOT) +#define PLATFORM_STACK_SIZE 0x2000 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +/* SD block buffer */ +#define NXP_SD_BLOCK_BUF_SIZE (0x00100000) +#define NXP_SD_BLOCK_BUF_ADDR ULL(0x80000000) + +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES 3 +#define MAX_IO_BLOCK_DEVICES 1 +#define MAX_IO_HANDLES 4 + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#define MAX_FIP_DEVICES 2 +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 1 +#endif + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define BL32_IRQ_SEC_PHY_TIMER 29 + +/* + * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_LS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_LS_G0_IRQ_PROPS(grp) + +#endif /* PLAT_DEF_H */ diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/platform.c b/plat/nxp/soc-ls1043a/ls1043ardb/platform.c new file mode 100644 index 0000000..65d508c --- /dev/null +++ b/plat/nxp/soc-ls1043a/ls1043ardb/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat_common.h> + +#pragma weak board_enable_povdd +#pragma weak board_disable_povdd + +bool board_enable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} + +bool board_disable_povdd(void) +{ +#ifdef CONFIG_POVDD_ENABLE + return true; +#else + return false; +#endif +} diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/platform.mk b/plat/nxp/soc-ls1043a/ls1043ardb/platform.mk new file mode 100644 index 0000000..5d23356 --- /dev/null +++ b/plat/nxp/soc-ls1043a/ls1043ardb/platform.mk @@ -0,0 +1,40 @@ +# +# Copyright 2018-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters + +BOOT_MODE ?= nor +BOARD := ls1043ardb +POVDD_ENABLE := no + +# DDR Compilation Configs +CONFIG_DDR_NODIMM := 1 +NUM_OF_DDRC := 1 +DDRC_NUM_DIMM := 0 +DDRC_NUM_CS := 4 +DDR_ECC_EN := no +CONFIG_STATIC_DDR := 0 + +# On-Board Flash Details +# 128MB IFC NOR Flash +NOR_FLASH_SZ := 0x8000000 + +# Platform specific features. +WARM_BOOT := no + +# Adding Platform files build files +BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\ + ${BOARD_PATH}/platform.c + +SUPPORTED_BOOT_MODE := nor \ + sd \ + nand + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Adding SoC build info +include plat/nxp/soc-ls1043a/soc.mk diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h b/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h new file mode 100644 index 0000000..4721a32 --- /dev/null +++ b/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h @@ -0,0 +1,13 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <plat_def.h> +#include <plat_default_def.h> + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/policy.h b/plat/nxp/soc-ls1043a/ls1043ardb/policy.h new file mode 100644 index 0000000..843b5e2 --- /dev/null +++ b/plat/nxp/soc-ls1043a/ls1043ardb/policy.h @@ -0,0 +1,16 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef POLICY_H +#define POLICY_H + +/* + * Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +#endif /* POLICY_H */ diff --git a/plat/nxp/soc-ls1043a/soc.c b/plat/nxp/soc-ls1043a/soc.c new file mode 100644 index 0000000..7badf8c --- /dev/null +++ b/plat/nxp/soc-ls1043a/soc.c @@ -0,0 +1,435 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <arch.h> +#include <caam.h> +#include <cassert.h> +#include <cci.h> +#include <common/debug.h> +#include <dcfg.h> +#ifdef I2C_INIT +#include <i2c.h> +#endif +#include <lib/mmio.h> +#include <lib/xlat_tables/xlat_tables_v2.h> +#include <ls_interconnect.h> +#ifdef POLICY_FUSE_PROVISION +#include <nxp_gpio.h> +#endif +#if TRUSTED_BOARD_BOOT +#include <nxp_smmu.h> +#endif +#include <nxp_timer.h> +#include <plat_console.h> +#include <plat_gic.h> +#include <plat_tzc380.h> +#include <scfg.h> +#if defined(NXP_SFP_ENABLED) +#include <sfp.h> +#endif + +#include <errata.h> +#include <ns_access.h> +#ifdef CONFIG_OCRAM_ECC_EN +#include <ocram.h> +#endif +#include <plat_common.h> +#include <platform_def.h> +#include <soc.h> + +static dcfg_init_info_t dcfg_init_data = { + .g_nxp_dcfg_addr = NXP_DCFG_ADDR, + .nxp_sysclk_freq = NXP_SYSCLK_FREQ, + .nxp_ddrclk_freq = NXP_DDRCLK_FREQ, + .nxp_plat_clk_divider = NXP_PLATFORM_CLK_DIVIDER, + }; + + +/* Function to return the SoC SYS CLK */ +unsigned int get_sys_clk(void) +{ + return NXP_SYSCLK_FREQ; +} + +/* + * Function returns the base counter frequency + * after reading the first entry at CNTFID0 (0x20 offset). + * + * Function is used by: + * 1. ARM common code for PSCI management. + * 2. ARM Generic Timer init. + * + */ +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int counter_base_frequency; + + counter_base_frequency = get_sys_clk()/4; + + return counter_base_frequency; +} + +#ifdef IMAGE_BL2 + +static struct soc_type soc_list[] = { + SOC_ENTRY(LS1023A, LS1023A, 1, 2), + SOC_ENTRY(LS1023AE, LS1023AE, 1, 2), + SOC_ENTRY(LS1023A_P23, LS1023A_P23, 1, 2), + SOC_ENTRY(LS1023AE_P23, LS1023AE_P23, 1, 2), + SOC_ENTRY(LS1043A, LS1043A, 1, 4), + SOC_ENTRY(LS1043AE, LS1043AE, 1, 4), + SOC_ENTRY(LS1043A_P23, LS1043A_P23, 1, 4), + SOC_ENTRY(LS1043AE_P23, LS1043AE_P23, 1, 4), +}; + +#ifdef POLICY_FUSE_PROVISION +static gpio_init_info_t gpio_init_data = { + .gpio1_base_addr = NXP_GPIO1_ADDR, + .gpio2_base_addr = NXP_GPIO2_ADDR, + .gpio3_base_addr = NXP_GPIO3_ADDR, + .gpio4_base_addr = NXP_GPIO4_ADDR, +}; +#endif + +/* + * Function to set the base counter frequency at + * the first entry of the Frequency Mode Table, + * at CNTFID0 (0x20 offset). + * + * Set the value of the pirmary core register cntfrq_el0. + */ +static void set_base_freq_CNTFID0(void) +{ + /* + * Below register specifies the base frequency of the system counter. + * As per NXP Board Manuals: + * The system counter always works with SYS_REF_CLK/4 frequency clock. + * + */ + unsigned int counter_base_frequency = get_sys_clk()/4; + + /* + * Setting the frequency in the Frequency modes table. + * + * Note: The value for ls1046ardb board at this offset + * is not RW as stated. This offset have the + * fixed value of 100000400 Hz. + * + * The below code line has no effect. + * Keeping it for other platforms where it has effect. + */ + mmio_write_32(NXP_TIMER_ADDR + CNTFID_OFF, counter_base_frequency); + + write_cntfrq_el0(counter_base_frequency); +} + +void soc_preload_setup(void) +{ + +} + +/******************************************************************************* + * This function implements soc specific erratas + * This is called before DDR is initialized or MMU is enabled + ******************************************************************************/ +void soc_early_init(void) +{ + uint8_t num_clusters, cores_per_cluster; + dram_regions_info_t *dram_regions_info = get_dram_regions_info(); + +#ifdef CONFIG_OCRAM_ECC_EN + ocram_init(NXP_OCRAM_ADDR, NXP_OCRAM_SIZE); +#endif + dcfg_init(&dcfg_init_data); +#ifdef POLICY_FUSE_PROVISION + gpio_init(&gpio_init_data); + sec_init(NXP_CAAM_ADDR); +#endif +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif + set_base_freq_CNTFID0(); + + /* Enable snooping on SEC read and write transactions */ + scfg_setbits32((void *)(NXP_SCFG_ADDR + SCFG_SNPCNFGCR_OFFSET), + SCFG_SNPCNFGCR_SECRDSNP | SCFG_SNPCNFGCR_SECWRSNP); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map)); + + /* + * Enable Interconnect coherency for the primary CPU's cluster. + */ + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + plat_ls_interconnect_enter_coherency(num_clusters); + +#if TRUSTED_BOARD_BOOT + uint32_t mode; + + sfp_init(NXP_SFP_ADDR); + /* + * For secure boot disable SMMU. + * Later when platform security policy comes in picture, + * this might get modified based on the policy + */ + if (check_boot_mode_secure(&mode) == true) { + bypass_smmu(NXP_SMMU_ADDR); + } + + /* + * For Mbedtls currently crypto is not supported via CAAM + * enable it when that support is there. In tbbr.mk + * the CAAM_INTEG is set as 0. + */ + +#ifndef MBEDTLS_X509 + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled() == false) { + INFO("SEC is disabled.\n"); + } else { + sec_init(NXP_CAAM_ADDR); + } +#endif +#elif defined(POLICY_FUSE_PROVISION) + gpio_init(&gpio_init_data); + sfp_init(NXP_SFP_ADDR); + sec_init(NXP_CAAM_ADDR); +#endif + + soc_errata(); + + /* + * Initialize system level generic timer for Layerscape Socs. + */ + delay_timer_init(NXP_TIMER_ADDR); + +#ifdef DDR_INIT + i2c_init(NXP_I2C_ADDR); + dram_regions_info->total_dram_size = init_ddr(); +#endif +} + +void soc_bl2_prepare_exit(void) +{ +#if defined(NXP_SFP_ENABLED) && defined(DISABLE_FUSE_WRITE) + set_sfp_wr_disable(); +#endif +} + +/***************************************************************************** + * This function returns the boot device based on RCW_SRC + ****************************************************************************/ +enum boot_device get_boot_dev(void) +{ + enum boot_device src = BOOT_DEVICE_NONE; + uint32_t porsr1; + uint32_t rcw_src, val; + + porsr1 = read_reg_porsr1(); + + rcw_src = (porsr1 & PORSR1_RCW_MASK) >> PORSR1_RCW_SHIFT; + + val = rcw_src & RCW_SRC_NAND_MASK; + + if (val == RCW_SRC_NAND_VAL) { + val = rcw_src & NAND_RESERVED_MASK; + if ((val != NAND_RESERVED_1) && (val != NAND_RESERVED_2)) { + src = BOOT_DEVICE_IFC_NAND; + INFO("RCW BOOT SRC is IFC NAND\n"); + } + } else { + /* RCW SRC NOR */ + val = rcw_src & RCW_SRC_NOR_MASK; + if (val == NOR_8B_VAL || val == NOR_16B_VAL) { + src = BOOT_DEVICE_IFC_NOR; + INFO("RCW BOOT SRC is IFC NOR\n"); + } else { + switch (rcw_src) { + case QSPI_VAL1: + case QSPI_VAL2: + src = BOOT_DEVICE_QSPI; + INFO("RCW BOOT SRC is QSPI\n"); + break; + case SD_VAL: + src = BOOT_DEVICE_EMMC; + INFO("RCW BOOT SRC is SD/EMMC\n"); + break; + default: + src = BOOT_DEVICE_NONE; + } + } + } + + return src; +} + +/* This function sets up access permissions on memory regions */ +void soc_mem_access(void) +{ + struct tzc380_reg tzc380_reg_list[MAX_NUM_TZC_REGION]; + int dram_idx, index = 0U; + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); + + for (dram_idx = 0U; dram_idx < info_dram_regions->num_dram_regions; + dram_idx++) { + if (info_dram_regions->region[dram_idx].size == 0) { + ERROR("DDR init failure, or"); + ERROR("DRAM regions not populated correctly.\n"); + break; + } + + index = populate_tzc380_reg_list(tzc380_reg_list, + dram_idx, index, + info_dram_regions->region[dram_idx].addr, + info_dram_regions->region[dram_idx].size, + NXP_SECURE_DRAM_SIZE, NXP_SP_SHRD_DRAM_SIZE); + } + + mem_access_setup(NXP_TZC_ADDR, index, tzc380_reg_list); + + /* Configure CSU secure access register to disable TZASC bypass mux */ + mmio_write_32((uintptr_t)(NXP_CSU_ADDR + + CSU_SEC_ACCESS_REG_OFFSET), + bswap32(TZASC_BYPASS_MUX_DISABLE)); +} + + +#else +const unsigned char _power_domain_tree_desc[] = {1, 1, 4}; + +CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256, + assert_invalid_ls1043_cluster_count); + +/* This function returns the SoC topology */ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + + return _power_domain_tree_desc; +} + +/* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + */ +unsigned int plat_ls_get_cluster_core_count(u_register_t mpidr) +{ + return CORES_PER_CLUSTER; +} + +void soc_early_platform_setup2(void) +{ + dcfg_init(&dcfg_init_data); + /* Initialize system level generic timer for Socs */ + delay_timer_init(NXP_TIMER_ADDR); + +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif +} + +/* + * For LS1043a rev1.0, GIC base address align with 4k. + * For LS1043a rev1.1, if DCFG_GIC400_ALIGN[GIC_ADDR_BIT] + * is set, GIC base address align with 4K, or else align + * with 64k. + */ +void get_gic_offset(uint32_t *gicc_base, uint32_t *gicd_base) +{ + uint32_t *ccsr_svr = (uint32_t *)(NXP_DCFG_ADDR + DCFG_SVR_OFFSET); + uint32_t *gic_align = (uint32_t *)(NXP_SCFG_ADDR + + SCFG_GIC400_ADDR_ALIGN_OFFSET); + uint32_t val; + + val = be32toh(mmio_read_32((uintptr_t)ccsr_svr)); + + if ((val & 0xff) == REV1_1) { + val = be32toh(mmio_read_32((uintptr_t)gic_align)); + if (val & (1L << GIC_ADDR_BIT)) { + *gicc_base = NXP_GICC_4K_ADDR; + *gicd_base = NXP_GICD_4K_ADDR; + } else { + *gicc_base = NXP_GICC_64K_ADDR; + *gicd_base = NXP_GICD_64K_ADDR; + } + } else { + *gicc_base = NXP_GICC_4K_ADDR; + *gicd_base = NXP_GICD_4K_ADDR; + } +} + +void soc_platform_setup(void) +{ + /* Initialize the GIC driver, cpu and distributor interfaces */ + static uint32_t target_mask_array[PLATFORM_CORE_COUNT]; + /* + * On a GICv2 system, the Group 1 secure interrupts are treated + * as Group 0 interrupts. + */ + static interrupt_prop_t ls_interrupt_props[] = { + PLAT_LS_G1S_IRQ_PROPS(GICV2_INTR_GROUP0), + PLAT_LS_G0_IRQ_PROPS(GICV2_INTR_GROUP0) + }; + static uint32_t gicc_base, gicd_base; + + get_gic_offset(&gicc_base, &gicd_base); + plat_ls_gic_driver_init(gicd_base, gicc_base, + PLATFORM_CORE_COUNT, + ls_interrupt_props, + ARRAY_SIZE(ls_interrupt_props), + target_mask_array); + + plat_ls_gic_init(); + enable_init_timer(); +} + +/* This function initializes the soc from the BL31 module */ +void soc_init(void) +{ + /* low-level init of the soc */ + soc_init_lowlevel(); + _init_global_data(); + soc_init_percpu(); + _initialize_psci(); + + /* + * Initialize the interconnect during cold boot. + * No need for locks as no other CPU is active. + */ + cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map)); + + /* + * Enable coherency in interconnect for the primary CPU's cluster. + * Earlier bootloader stages might already do this but we can't + * assume so. No harm in executing this code twice. + */ + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr())); + + /* Init CSU to enable non-secure access to peripherals */ + enable_layerscape_ns_access(ns_dev, ARRAY_SIZE(ns_dev), NXP_CSU_ADDR); + + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled() == false) { + INFO("SEC is disabled.\n"); + } else { + sec_init(NXP_CAAM_ADDR); + } +} + +void soc_runtime_setup(void) +{ + +} +#endif diff --git a/plat/nxp/soc-ls1043a/soc.def b/plat/nxp/soc-ls1043a/soc.def new file mode 100644 index 0000000..b174bd6 --- /dev/null +++ b/plat/nxp/soc-ls1043a/soc.def @@ -0,0 +1,107 @@ +# +# Copyright 2017-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# This file contains the basic architecture definitions that drive the build +# +# ----------------------------------------------------------------------------- + +CORE_TYPE := a53 + +CACHE_LINE := 6 + +# set to GIC400 or GIC500 +GIC := GIC400 + +# set to CCI400 or CCN504 or CCN508 +INTERCONNECT := CCI400 + +# indicate layerscape chassis level - set to 3=LSCH3 or 2=LSCH2 +CHASSIS := 2 + +# TZC IP Details TZC used is TZC380 or TZC400 +TZC_ID := TZC380 + +# CONSOLE Details available is NS16550 or PL011 +CONSOLE := NS16550 + +# Select the DDR PHY generation to be used +PLAT_DDR_PHY := PHY_GEN1 + +PHYS_SYS := 64 + +# ddr controller - set to MMDC or NXP +DDRCNTLR := NXP + +# ddr phy - set to NXP or SNPS +DDRPHY := NXP + +# Area of OCRAM reserved by ROM code +NXP_ROM_RSVD := 0x5900 + +# Max Size of CSF header. Required to define BL2 TEXT LIMIT in soc.def +# Input to CST create_hdr_esbc tool +CSF_HDR_SZ := 0x3000 + +# In IMAGE_BL2, compile time flag for handling Cache coherency +# with CAAM for BL2 running from OCRAM +SEC_MEM_NON_COHERENT := yes + +# OCRAM MAP +OCRAM_START_ADDR := 0x10000000 +OCRAM_SIZE := 0x20000 + +# BL2 binary is placed at start of OCRAM. +# Also used by create_pbl.mk. +BL2_BASE := 0x10000000 + +# After BL2 bin, OCRAM is used by ROM Code: +# (OCRAM_START_ADDR + BL2_BIN_SIZE) -> (NXP_ROM_RSVD - 1) + +# After ROM Code, OCRAM is used by CSF header. +# (OCRAM_START_ADDR + BL2_TEXT_LIMIT + NXP_ROM_RSVD) -> (CSF_HDR_SZ - 1) + +# BL2_HDR_LOC has to be (OCRAM_START_ADDR + OCRAM_SIZE - NXP_ROM_RSVD - CSF_HDR_SZ) +# This value should be greater than BL2_TEXT_LIMIT +# Input to CST create_hdr_isbc tool +BL2_HDR_LOC_HDR ?= $(shell echo $$(( $(OCRAM_START_ADDR) + $(OCRAM_SIZE) - $(NXP_ROM_RSVD) - $(CSF_HDR_SZ)))) +# Covert to HEX to be used by create_pbl.mk +BL2_HDR_LOC := $$(echo "obase=16; ${BL2_HDR_LOC_HDR}" | bc) + +# Core Errata +ERRATA_A53_855873 := 1 +ERRATA_A53_1530924 := 1 + +# SoC ERRATAS to be enabled +ERRATA_SOC_A008850 := 1 +ERRATA_SOC_A010539 := 1 +ERRATA_SOC_A009660 := 1 + +# DDR Errata +ERRATA_DDR_A009663 := 1 +ERRATA_DDR_A009942 := 1 + +# enable dynamic memory mapping +PLAT_XLAT_TABLES_DYNAMIC := 1 + +# Define Endianness of each module +NXP_GUR_ENDIANNESS := BE +NXP_DDR_ENDIANNESS := BE +NXP_SEC_ENDIANNESS := BE +NXP_SFP_ENDIANNESS := BE +NXP_SNVS_ENDIANNESS := BE +NXP_ESDHC_ENDIANNESS := BE +NXP_QSPI_ENDIANNESS := BE +NXP_FSPI_ENDIANNESS := BE +NXP_SCFG_ENDIANNESS := BE +NXP_GPIO_ENDIANNESS := BE +NXP_IFC_ENDIANNESS := BE + +NXP_SFP_VER := 3_2 + +# OCRAM ECC Enabled +OCRAM_ECC_EN := yes diff --git a/plat/nxp/soc-ls1043a/soc.mk b/plat/nxp/soc-ls1043a/soc.mk new file mode 100644 index 0000000..b6ce14e --- /dev/null +++ b/plat/nxp/soc-ls1043a/soc.mk @@ -0,0 +1,114 @@ +# +# Copyright 2018-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SoC-specific build parameters +SOC := ls1043a +PLAT_PATH := plat/nxp +PLAT_COMMON_PATH := plat/nxp/common +PLAT_DRIVERS_PATH := drivers/nxp +PLAT_SOC_PATH := ${PLAT_PATH}/soc-${SOC} +BOARD_PATH := ${PLAT_SOC_PATH}/${BOARD} + +# get SoC-specific defnitions +include ${PLAT_SOC_PATH}/soc.def +include ${PLAT_COMMON_PATH}/plat_make_helper/soc_common_def.mk +include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk + +# For Security Features +DISABLE_FUSE_WRITE := 1 +ifeq (${TRUSTED_BOARD_BOOT}, 1) +$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2)) +SECURE_BOOT := yes +endif +$(eval $(call SET_NXP_MAKE_FLAG,CRYPTO_NEEDED,BL_COMM)) + +# Selecting Drivers for SoC +$(eval $(call SET_NXP_MAKE_FLAG,DCFG_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,CSU_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,TIMER_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,INTERCONNECT_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,GIC_NEEDED,BL31)) +$(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,PMU_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,DDR_DRIVER_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,TZASC_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,I2C_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2)) + +# Selecting PSCI & SIP_SVC support +$(eval $(call SET_NXP_MAKE_FLAG,PSCI_NEEDED,BL31)) +$(eval $(call SET_NXP_MAKE_FLAG,SIPSVC_NEEDED,BL31)) + +# Source File Addition +PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/include/default\ + -I${BOARD_PATH}\ + -I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\ + -I${PLAT_SOC_PATH}/include\ + -I${PLAT_COMMON_PATH}/soc_errata + +ifeq (${SECURE_BOOT},yes) +include ${PLAT_COMMON_PATH}/tbbr/tbbr.mk +endif + +ifeq ($(WARM_BOOT),yes) +include ${PLAT_COMMON_PATH}/warm_reset/warm_reset.mk +endif + +ifeq (${NXP_NV_SW_MAINT_LAST_EXEC_DATA}, yes) +include ${PLAT_COMMON_PATH}/nv_storage/nv_storage.mk +endif + +ifeq (${PSCI_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/psci/psci.mk +endif + +ifeq (${SIPSVC_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/sip_svc/sipsvc.mk +endif + +# for fuse-fip & fuse-programming +ifeq (${FUSE_PROG}, 1) +include ${PLAT_COMMON_PATH}/fip_handler/fuse_fip/fuse.mk +endif + +ifeq (${IMG_LOADR_NEEDED},yes) +include $(PLAT_COMMON_PATH)/img_loadr/img_loadr.mk +endif + +# Adding source files for the above selected drivers. +include ${PLAT_DRIVERS_PATH}/drivers.mk + +# Adding SoC specific files +include ${PLAT_COMMON_PATH}/soc_errata/errata.mk + +PLAT_INCLUDES += ${NV_STORAGE_INCLUDES}\ + ${WARM_RST_INCLUDES} + +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}.S\ + ${WARM_RST_BL31_SOURCES}\ + ${PSCI_SOURCES}\ + ${SIPSVC_SOURCES}\ + ${PLAT_COMMON_PATH}/$(ARCH)/bl31_data.S + +PLAT_BL_COMMON_SOURCES += ${PLAT_COMMON_PATH}/$(ARCH)/ls_helpers.S\ + ${PLAT_SOC_PATH}/aarch64/${SOC}_helpers.S\ + ${NV_STORAGE_SOURCES}\ + ${WARM_RST_BL_COMM_SOURCES}\ + ${PLAT_SOC_PATH}/soc.c + +ifeq (${TEST_BL31}, 1) +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/bootmain64.S\ + ${PLAT_SOC_PATH}/$(ARCH)/nonboot64.S +endif + +BL2_SOURCES += ${DDR_CNTLR_SOURCES}\ + ${TBBR_SOURCES}\ + ${FUSE_SOURCES} + +# Adding TFA setup files +include ${PLAT_PATH}/common/setup/common.mk diff --git a/plat/nxp/soc-ls1046a/aarch64/ls1046a.S b/plat/nxp/soc-ls1046a/aarch64/ls1046a.S new file mode 100644 index 0000000..daa0542 --- /dev/null +++ b/plat/nxp/soc-ls1046a/aarch64/ls1046a.S @@ -0,0 +1,937 @@ +/* + * Copyright 2020-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <asm_macros.S> +#include <dcfg_lsch2.h> +#include <nxp_timer.h> +#include <plat_gic.h> +#include <scfg.h> + +#include <bl31_data.h> +#include <plat_psci.h> +#include <platform_def.h> + +#define DAIF_DATA AUX_01_DATA +#define TIMER_CNTRL_DATA AUX_02_DATA + +.global soc_init_lowlevel +.global soc_init_percpu +.global _soc_core_release +.global _soc_core_restart +.global _soc_ck_disabled +.global _soc_sys_reset +.global _soc_sys_off +.global _soc_set_start_addr +.global _getGICC_BaseAddr +.global _getGICD_BaseAddr +.global _soc_core_prep_off +.global _soc_core_entr_off +.global _soc_core_exit_off +.global _soc_core_prep_stdby +.global _soc_core_entr_stdby +.global _soc_core_exit_stdby +.global _soc_core_prep_pwrdn +.global _soc_core_entr_pwrdn +.global _soc_core_exit_pwrdn +.global _soc_clstr_prep_stdby +.global _soc_clstr_exit_stdby +.global _soc_clstr_prep_pwrdn +.global _soc_clstr_exit_pwrdn +.global _soc_sys_prep_stdby +.global _soc_sys_exit_stdby +.global _soc_sys_prep_pwrdn +.global _soc_sys_pwrdn_wfi +.global _soc_sys_exit_pwrdn + + +/* This function initialize the soc + * in: void + * out: void + */ +func soc_init_lowlevel + ret +endfunc soc_init_lowlevel + + +/* void soc_init_percpu(void) + * this function performs any soc-specific initialization that is needed on + * a per-core basis + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +func soc_init_percpu + mov x3, x30 + + bl plat_my_core_mask + mov x2, x0 + + /* see if this core is marked for prefetch disable */ + mov x0, #PREFETCH_DIS_OFFSET + bl _get_global_data /* 0-1 */ + tst x0, x2 + b.eq 1f + bl _disable_ldstr_pfetch_A72 /* 0 */ +1: + mov x30, x3 + ret +endfunc soc_init_percpu + +/* part of CPU_ON + * this function releases a secondary core from reset + * in: x0 = core_mask_lsb + * out: none + * uses: x0, x1, x2, x3 + */ +func _soc_core_release + +#if (TEST_BL31) + rbit w2, w0 + /* x2 = core mask msb */ +#else + mov x2, x0 +#endif + /* write COREBCR */ + mov x1, #NXP_SCFG_ADDR + rev w3, w2 + str w3, [x1, #SCFG_COREBCR_OFFSET] + isb + + /* read-modify-write BRR */ + mov x1, #NXP_DCFG_ADDR + ldr w2, [x1, #DCFG_BRR_OFFSET] + rev w3, w2 + orr w3, w3, w0 + rev w2, w3 + str w2, [x1, #DCFG_BRR_OFFSET] + isb + + /* send event */ + sev + isb + ret +endfunc _soc_core_release + + +/* part of CPU_ON + * this function restarts a core shutdown via _soc_core_entr_off + * in: x0 = core mask lsb (of the target cpu) + * out: x0 == 0, on success + * x0 != 0, on failure + * uses x0, x1, x2, x3, x4, x5 + */ +func _soc_core_restart + mov x5, x30 + mov x3, x0 + + /* + * unset ph20 request in RCPM_PCPH20CLEARR + * this is an lsb-0 register + */ + ldr x1, =NXP_RCPM_ADDR + rev w2, w3 + str w2, [x1, #RCPM_PCPH20CLRR_OFFSET] + dsb sy + isb + + bl _getGICD_BaseAddr + mov x4, x0 + + /* enable forwarding of group 0 interrupts by setting GICD_CTLR[0] = 1 */ + ldr w1, [x4, #GICD_CTLR_OFFSET] + orr w1, w1, #GICD_CTLR_EN_GRP0 + str w1, [x4, #GICD_CTLR_OFFSET] + dsb sy + isb + + + /* + * fire SGI by writing to GICD_SGIR the following values: + * [25:24] = 0x0 (forward interrupt to the CPU interfaces + * specified in CPUTargetList field) + * [23:16] = core mask lsb[7:0] (forward interrupt to target cpu) + * [15] = 0 (forward SGI only if it is configured as group 0 interrupt) + * [3:0] = 0xF (interrupt ID = 15) + */ + lsl w1, w3, #16 + orr w1, w1, #0xF + str w1, [x4, #GICD_SGIR_OFFSET] + dsb sy + isb + + /* load '0' on success */ + mov x0, xzr + + mov x30, x5 + ret +endfunc _soc_core_restart + +/* + * This function determines if a core is disabled via COREDISR + * in: w0 = core_mask_lsb + * out: w0 = 0, core not disabled + * w0 != 0, core disabled + * uses x0, x1, x2 + */ +func _soc_ck_disabled + /* get base addr of dcfg block */ + mov x1, #NXP_DCFG_ADDR + + /* read COREDISR */ + ldr w1, [x1, #DCFG_COREDISR_OFFSET] + rev w2, w1 + + /* test core bit */ + and w0, w2, w0 + ret +endfunc _soc_ck_disabled + +/* + *This function resets the system via SoC-specific methods + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +func _soc_sys_reset + ldr x2, =NXP_DCFG_ADDR + + /* make sure the mask is cleared in the reset request mask register */ + mov w1, wzr + str w1, [x2, #DCFG_RSTRQMR1_OFFSET] + + /* set the reset request */ + ldr w1, =RSTCR_RESET_REQ + ldr x3, =DCFG_RSTCR_OFFSET + rev w0, w1 + str w0, [x2, x3] + + /* + * just in case this address range is mapped as cacheable, + * flush the write out of the dcaches + */ + add x3, x2, x3 + dc cvac, x3 + dsb st + isb + + /* Note: this function does not return */ +1: + wfi + b 1b +endfunc _soc_sys_reset + +/* + * Part of SYSTEM_OFF + * this function turns off the SoC clocks + * Note: this function is not intended to return, and the only allowable + * recovery is POR + * in: none + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9 + */ +func _soc_sys_off + + /* mask interrupts at the core */ + mrs x1, DAIF + mov x0, #DAIF_SET_MASK + orr x0, x1, x0 + msr DAIF, x0 + + /* disable icache, dcache, mmu @ EL1 */ + mov x1, #SCTLR_I_C_M_MASK + mrs x0, sctlr_el1 + bic x0, x0, x1 + msr sctlr_el1, x0 + + /* disable dcache for EL3 */ + mrs x1, SCTLR_EL3 + bic x1, x1, #SCTLR_C_MASK + /* make sure icache is enabled */ + orr x1, x1, #SCTLR_I_MASK + msr SCTLR_EL3, x1 + isb + + /* Enable dynamic retention ctrl (CPUECTLR[2:0]) and SMP (CPUECTLR[6]) */ + mrs x0, CORTEX_A72_ECTLR_EL1 + orr x0, x0, #CPUECTLR_TIMER_8TICKS + orr x0, x0, #CPUECTLR_SMPEN_EN + msr CORTEX_A72_ECTLR_EL1, x0 + + /* set WFIL2EN in SCFG_CLUSTERPMCR */ + ldr x0, =SCFG_COREPMCR_OFFSET + ldr x1, =COREPMCR_WFIL2 + bl write_reg_scfg + + /* request LPM20 */ + mov x0, #RCPM_POWMGTCSR_OFFSET + bl read_reg_rcpm + orr x1, x0, #RCPM_POWMGTCSR_LPM20_REQ + mov x0, #RCPM_POWMGTCSR_OFFSET + bl write_reg_rcpm + + dsb sy + isb +1: + wfi + b 1b +endfunc _soc_sys_off + +/* + * Write a register in the RCPM block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2, x3 + */ +func write_reg_rcpm + ldr x2, =NXP_RCPM_ADDR + /* swap for BE */ + rev w3, w1 + str w3, [x2, x0] + ret +endfunc write_reg_rcpm + +/* + * Read a register in the RCPM block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +func read_reg_rcpm + ldr x2, =NXP_RCPM_ADDR + ldr w1, [x2, x0] + /* swap for BE */ + rev w0, w1 + ret +endfunc read_reg_rcpm + +/* + * Write a register in the SCFG block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2, x3 + */ +func write_reg_scfg + mov x2, #NXP_SCFG_ADDR + /* swap for BE */ + rev w3, w1 + str w3, [x2, x0] + ret +endfunc write_reg_scfg + +/* + * Read a register in the SCFG block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1, x2 + */ +func read_reg_scfg + mov x2, #NXP_SCFG_ADDR + ldr w1, [x2, x0] + /* swap for BE */ + rev w0, w1 + ret +endfunc read_reg_scfg + +/* + * Part of CPU_OFF + * this function programs SoC & GIC registers in preparation for shutting down + * the core + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7 + */ +func _soc_core_prep_off + mov x7, x30 + mov x6, x0 + + /* Set retention control in CPUECTLR make sure smpen bit is set */ + mrs x4, CORTEX_A72_ECTLR_EL1 + bic x4, x4, #CPUECTLR_RET_MASK + orr x4, x4, #CPUECTLR_TIMER_8TICKS + orr x4, x4, #CPUECTLR_SMPEN_EN + msr CORTEX_A72_ECTLR_EL1, x4 + + /* save timer control current value */ + mov x5, #NXP_TIMER_ADDR + ldr w4, [x5, #SYS_COUNTER_CNTCR_OFFSET] + mov w2, w4 + mov x0, x6 + mov x1, #TIMER_CNTRL_DATA + bl _setCoreData + + /* enable the timer */ + orr w4, w4, #CNTCR_EN_MASK + str w4, [x5, #SYS_COUNTER_CNTCR_OFFSET] + + bl _getGICC_BaseAddr + mov x5, x0 + + /* disable signaling of ints */ + ldr w3, [x5, #GICC_CTLR_OFFSET] + bic w3, w3, #GICC_CTLR_EN_GRP0 + bic w3, w3, #GICC_CTLR_EN_GRP1 + str w3, [x5, #GICC_CTLR_OFFSET] + dsb sy + isb + + + /* + * set retention control in SCFG_RETREQCR + * Note: this register is msb 0 + */ + ldr x4, =SCFG_RETREQCR_OFFSET + mov x0, x4 + bl read_reg_scfg + rbit w1, w6 + orr w1, w0, w1 + mov x0, x4 + bl write_reg_scfg + + /* set the priority filter */ + ldr w2, [x5, #GICC_PMR_OFFSET] + orr w2, w2, #GICC_PMR_FILTER + str w2, [x5, #GICC_PMR_OFFSET] + + /* setup GICC_CTLR */ + bic w3, w3, #GICC_CTLR_ACKCTL_MASK + orr w3, w3, #GICC_CTLR_FIQ_EN_MASK + orr w3, w3, #GICC_CTLR_EOImodeS_MASK + orr w3, w3, #GICC_CTLR_CBPR_MASK + str w3, [x5, #GICC_CTLR_OFFSET] + + /* setup the banked-per-core GICD registers */ + bl _getGICD_BaseAddr + mov x5, x0 + + /* define SGI15 as Grp0 */ + ldr w2, [x5, #GICD_IGROUPR0_OFFSET] + bic w2, w2, #GICD_IGROUP0_SGI15 + str w2, [x5, #GICD_IGROUPR0_OFFSET] + + /* set priority of SGI 15 to highest... */ + ldr w2, [x5, #GICD_IPRIORITYR3_OFFSET] + bic w2, w2, #GICD_IPRIORITY_SGI15_MASK + str w2, [x5, #GICD_IPRIORITYR3_OFFSET] + + /* enable SGI 15 */ + ldr w2, [x5, #GICD_ISENABLER0_OFFSET] + orr w2, w2, #GICD_ISENABLE0_SGI15 + str w2, [x5, #GICD_ISENABLER0_OFFSET] + + /* enable the cpu interface */ + bl _getGICC_BaseAddr + mov x2, x0 + orr w3, w3, #GICC_CTLR_EN_GRP0 + str w3, [x2, #GICC_CTLR_OFFSET] + + + /* clear any pending SGIs */ + ldr x2, =GICD_CPENDSGIR_CLR_MASK + add x0, x5, #GICD_CPENDSGIR3_OFFSET + str w2, [x0] + + /* + * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR + * this is an lsb-0 register + */ + mov x1, x6 + mov x0, #RCPM_PCPH20SETR_OFFSET + bl write_reg_rcpm + + dsb sy + isb + mov x30, x7 + ret +endfunc _soc_core_prep_off + +/* + * Part of CPU_OFF + * this function performs the final steps to shutdown the core + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5 + */ +func _soc_core_entr_off + mov x5, x30 + mov x4, x0 + + bl _getGICD_BaseAddr + mov x3, x0 + +3: + /* enter low-power state by executing wfi */ + wfi + + /* see if we got hit by SGI 15 */ + add x0, x3, #GICD_SPENDSGIR3_OFFSET + ldr w2, [x0] + and w2, w2, #GICD_SPENDSGIR3_SGI15_MASK + cbz w2, 4f + + /* clear the pending SGI */ + ldr x2, =GICD_CPENDSGIR_CLR_MASK + add x0, x3, #GICD_CPENDSGIR3_OFFSET + str w2, [x0] +4: + /* check if core has been turned on */ + mov x0, x4 + bl _getCoreState + + cmp x0, #CORE_WAKEUP + b.ne 3b + + /* if we get here, then we have exited the wfi */ + dsb sy + isb + mov x30, x5 + ret +endfunc _soc_core_entr_off + +/* + * Part of CPU_OFF + * this function starts the process of starting a core back up + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5, x6 + */ +func _soc_core_exit_off + mov x6, x30 + mov x5, x0 + + /* + * Clear ph20 request in RCPM_PCPH20CLRR - no need + * to do that here, it has been done in _soc_core_restart + */ + bl _getGICC_BaseAddr + mov x1, x0 + + /* read GICC_IAR */ + ldr w0, [x1, #GICC_IAR_OFFSET] + + /* write GICC_EIOR - signal end-of-interrupt */ + str w0, [x1, #GICC_EOIR_OFFSET] + + /* write GICC_DIR - disable interrupt */ + str w0, [x1, #GICC_DIR_OFFSET] + + /* disable signaling of grp0 ints */ + ldr w3, [x1, #GICC_CTLR_OFFSET] + bic w3, w3, #GICC_CTLR_EN_GRP0 + str w3, [x1, #GICC_CTLR_OFFSET] + + /* + * Unset retention request in SCFG_RETREQCR + * Note: this register is msb-0 + */ + ldr x4, =SCFG_RETREQCR_OFFSET + mov x0, x4 + bl read_reg_scfg + rbit w1, w5 + bic w1, w0, w1 + mov x0, x4 + bl write_reg_scfg + + /* restore timer ctrl */ + mov x0, x5 + mov x1, #TIMER_CNTRL_DATA + bl _getCoreData + /* w0 = timer ctrl saved value */ + mov x2, #NXP_TIMER_ADDR + str w0, [x2, #SYS_COUNTER_CNTCR_OFFSET] + + dsb sy + isb + mov x30, x6 + ret +endfunc _soc_core_exit_off + +/* + * Function loads a 64-bit execution address of the core in the soc registers + * BOOTLOCPTRL/H + * in: x0, 64-bit address to write to BOOTLOCPTRL/H + * uses x0, x1, x2, x3 + */ +func _soc_set_start_addr + /* get the 64-bit base address of the scfg block */ + ldr x2, =NXP_SCFG_ADDR + + /* write the 32-bit BOOTLOCPTRL register */ + mov x1, x0 + rev w3, w1 + str w3, [x2, #SCFG_BOOTLOCPTRL_OFFSET] + + /* write the 32-bit BOOTLOCPTRH register */ + lsr x1, x0, #32 + rev w3, w1 + str w3, [x2, #SCFG_BOOTLOCPTRH_OFFSET] + ret +endfunc _soc_set_start_addr + +/* + * This function returns the base address of the gic distributor + * in: none + * out: x0 = base address of gic distributor + * uses x0 + */ +func _getGICD_BaseAddr +#if (TEST_BL31) + /* defect in simulator - gic base addresses are on 4Kb boundary */ + ldr x0, =NXP_GICD_4K_ADDR +#else + ldr x0, =NXP_GICD_64K_ADDR +#endif + ret +endfunc _getGICD_BaseAddr + +/* + * This function returns the base address of the gic controller + * in: none + * out: x0 = base address of gic controller + * uses x0 + */ +func _getGICC_BaseAddr +#if (TEST_BL31) + /* defect in simulator - gic base addresses are on 4Kb boundary */ + ldr x0, =NXP_GICC_4K_ADDR +#else + ldr x0, =NXP_GICC_64K_ADDR +#endif + ret +endfunc _getGICC_BaseAddr + +/* + * Part of CPU_SUSPEND + * this 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 + * this 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 + * this 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 + * this function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5 + */ +func _soc_core_prep_pwrdn + mov x5, x30 + mov x4, x0 + + /* enable CPU retention + set smp */ + mrs x1, CORTEX_A72_ECTLR_EL1 + orr x1, x1, #0x1 + orr x1, x1, #CPUECTLR_SMPEN_MASK + msr CORTEX_A72_ECTLR_EL1, x1 + + /* + * set the retention request in SCFG_RETREQCR + * this is an msb-0 register + */ + ldr x3, =SCFG_RETREQCR_OFFSET + mov x0, x3 + bl read_reg_scfg + rbit w1, w4 + orr w1, w0, w1 + mov x0, x3 + bl write_reg_scfg + + /* + * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR + * this is an lsb-0 register + */ + mov x1, x4 + mov x0, #RCPM_PCPH20SETR_OFFSET + bl write_reg_rcpm + + mov x30, x5 + ret +endfunc _soc_core_prep_pwrdn + +/* + * Part of CPU_SUSPEND + * this function puts the calling core into a power-down state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +func _soc_core_entr_pwrdn + dsb sy + isb + wfi + + ret +endfunc _soc_core_entr_pwrdn + +/* + * Part of CPU_SUSPEND + * this function cleans up after a core exits power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5 + */ +func _soc_core_exit_pwrdn + mov x5, x30 + mov x4, x0 + + /* + * Set the PC_PH20_REQ bit in RCPM_PCPH20CLRR + * this is an lsb-0 register + */ + mov x1, x4 + mov x0, #RCPM_PCPH20CLRR_OFFSET + bl write_reg_rcpm + + /* + * Unset the retention request in SCFG_RETREQCR + * this is an msb-0 register + */ + ldr x3, =SCFG_RETREQCR_OFFSET + mov x0, x3 + bl read_reg_scfg + rbit w1, w4 + bic w1, w0, w1 + mov x0, x3 + bl write_reg_scfg + + mov x30, x5 + ret +endfunc _soc_core_exit_pwrdn + +/* + * Part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses none + */ +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 + * this 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 + * this function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5 + */ +func _soc_clstr_prep_pwrdn + mov x5, x30 + mov x4, x0 + + /* enable CPU retention + set smp */ + mrs x1, CORTEX_A72_ECTLR_EL1 + orr x1, x1, #0x1 + orr x1, x1, #CPUECTLR_SMPEN_MASK + msr CORTEX_A72_ECTLR_EL1, x1 + + /* + * Set the retention request in SCFG_RETREQCR + * this is an msb-0 register. + */ + ldr x3, =SCFG_RETREQCR_OFFSET + mov x0, x3 + bl read_reg_scfg + rbit w1, w4 + orr w1, w0, w1 + mov x0, x3 + bl write_reg_scfg + + /* + * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR + * this is an lsb-0 register. + */ + mov x1, x4 + mov x0, #RCPM_PCPH20SETR_OFFSET + bl write_reg_rcpm + + mov x30, x5 + ret +endfunc _soc_clstr_prep_pwrdn + +/* + * Part of CPU_SUSPEND + * this function cleans up after a core exits power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5 + */ +func _soc_clstr_exit_pwrdn + mov x5, x30 + mov x4, x0 + + /* + * Set the PC_PH20_REQ bit in RCPM_PCPH20CLRR + * this is an lsb-0 register. + */ + mov x1, x4 + mov x0, #RCPM_PCPH20CLRR_OFFSET + bl write_reg_rcpm + + /* + * Unset the retention request in SCFG_RETREQCR + * this is an msb-0 register. + */ + ldr x3, =SCFG_RETREQCR_OFFSET + mov x0, x3 + bl read_reg_scfg + rbit w1, w4 + bic w1, w0, w1 + mov x0, x3 + bl write_reg_scfg + + mov x30, x5 + ret +endfunc _soc_clstr_exit_pwrdn + +/* + * Part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses none + */ +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 + * this 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 + * this function performs SoC-specific programming prior to + * suspend-to-power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4 + */ +func _soc_sys_prep_pwrdn + mov x4, x30 + + /* Enable dynamic retention contrl (CPUECTLR[2:0]) and SMP (CPUECTLR[6]) */ + mrs x0, CORTEX_A72_ECTLR_EL1 + bic x0, x0, #CPUECTLR_TIMER_MASK + orr x0, x0, #CPUECTLR_TIMER_8TICKS + orr x0, x0, #CPUECTLR_SMPEN_EN + msr CORTEX_A72_ECTLR_EL1, x0 + + /* Set WFIL2EN in SCFG_CLUSTERPMCR */ + ldr x0, =SCFG_COREPMCR_OFFSET + ldr x1, =COREPMCR_WFIL2 + bl write_reg_scfg + + isb + mov x30, x4 + ret +endfunc _soc_sys_prep_pwrdn + +/* + * Part of CPU_SUSPEND + * this function puts the calling core, and potentially the soc, into a + * low-power state + * in: x0 = core mask lsb + * out: x0 = 0, success + * x0 < 0, failure + * uses x0, x1, x2, x3, x4 + */ +func _soc_sys_pwrdn_wfi + mov x4, x30 + + /* request LPM20 */ + mov x0, #RCPM_POWMGTCSR_OFFSET + bl read_reg_rcpm + orr x1, x0, #RCPM_POWMGTCSR_LPM20_REQ + mov x0, #RCPM_POWMGTCSR_OFFSET + bl write_reg_rcpm + + dsb sy + isb + wfi + + mov x30, x4 + ret +endfunc _soc_sys_pwrdn_wfi + +/* + * Part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +func _soc_sys_exit_pwrdn + /* clear WFIL2_EN in SCFG_COREPMCR */ + mov x1, #NXP_SCFG_ADDR + str wzr, [x1, #SCFG_COREPMCR_OFFSET] + + ret +endfunc _soc_sys_exit_pwrdn diff --git a/plat/nxp/soc-ls1046a/aarch64/ls1046a_helpers.S b/plat/nxp/soc-ls1046a/aarch64/ls1046a_helpers.S new file mode 100644 index 0000000..d2a48ea --- /dev/null +++ b/plat/nxp/soc-ls1046a/aarch64/ls1046a_helpers.S @@ -0,0 +1,92 @@ +/* + * Copyright 2018-2022 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 l2_mem_init + /* Initialize the L2 RAM latency */ + mrs x1, S3_1_c11_c0_2 + mov x0, #0x1C7 + /* Clear L2 Tag RAM latency and L2 Data RAM latency */ + bic x1, x1, x0 + /* Set L2 data ram latency bits [2:0] */ + orr x1, x1, #0x2 + /* set L2 tag ram latency bits [8:6] */ + orr x1, x1, #0x80 + msr S3_1_c11_c0_2, x1 + isb + ret +endfunc l2_mem_init + +func apply_platform_errata + ret +endfunc apply_platform_errata + +func plat_reset_handler + mov x29, x30 +#if (defined(IMAGE_BL2) && BL2_AT_EL3) + bl l2_mem_init +#endif + 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: + /* + * May be cntfrq_el0 needs to be assigned + * the value COUNTER_FREQUENCY + */ + 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 + /* ls1046a 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-ls1046a/include/ns_access.h b/plat/nxp/soc-ls1046a/include/ns_access.h new file mode 100644 index 0000000..25c1964 --- /dev/null +++ b/plat/nxp/soc-ls1046a/include/ns_access.h @@ -0,0 +1,174 @@ +/* + * Copyright 2017-2018, 2020-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NS_ACCESS_H +#define NS_ACCESS_H + +#include <csu.h> + +enum csu_cslx_ind { + CSU_CSLX_PCIE2_IO = 0, + CSU_CSLX_PCIE1_IO, + CSU_CSLX_MG2TPR_IP, + CSU_CSLX_IFC_MEM, + CSU_CSLX_OCRAM, + CSU_CSLX_GIC, + CSU_CSLX_PCIE1, + CSU_CSLX_OCRAM2, + CSU_CSLX_QSPI_MEM, + CSU_CSLX_PCIE2, + CSU_CSLX_SATA, + CSU_CSLX_USB1, + CSU_CSLX_QM_BM_SWPORTAL, + CSU_CSLX_PCIE3 = 16, + CSU_CSLX_PCIE3_IO, + CSU_CSLX_USB3 = 20, + CSU_CSLX_USB2, + CSU_CSLX_PFE = 23, + CSU_CSLX_SERDES = 32, + CSU_CSLX_QDMA, + CSU_CSLX_LPUART2, + CSU_CSLX_LPUART1, + CSU_CSLX_LPUART4, + CSU_CSLX_LPUART3, + CSU_CSLX_LPUART6, + CSU_CSLX_LPUART5, + CSU_CSLX_DSPI1 = 41, + CSU_CSLX_QSPI, + CSU_CSLX_ESDHC, + CSU_CSLX_IFC = 45, + CSU_CSLX_I2C1, + CSU_CSLX_USB_2, + CSU_CSLX_I2C3 = 48, + CSU_CSLX_I2C2, + CSU_CSLX_DUART2 = 50, + CSU_CSLX_DUART1, + CSU_CSLX_WDT2, + CSU_CSLX_WDT1, + CSU_CSLX_EDMA, + CSU_CSLX_SYS_CNT, + CSU_CSLX_DMA_MUX2, + CSU_CSLX_DMA_MUX1, + CSU_CSLX_DDR, + CSU_CSLX_QUICC, + CSU_CSLX_DCFG_CCU_RCPM = 60, + CSU_CSLX_SECURE_BOOTROM, + CSU_CSLX_SFP, + CSU_CSLX_TMU, + CSU_CSLX_SECURE_MONITOR, + CSU_CSLX_SCFG, + CSU_CSLX_FM = 66, + CSU_CSLX_SEC5_5, + CSU_CSLX_BM, + CSU_CSLX_QM, + CSU_CSLX_GPIO2 = 70, + CSU_CSLX_GPIO1, + CSU_CSLX_GPIO4, + CSU_CSLX_GPIO3, + CSU_CSLX_PLATFORM_CONT, + CSU_CSLX_CSU, + CSU_CSLX_IIC4 = 77, + CSU_CSLX_WDT4, + CSU_CSLX_WDT3, + CSU_CSLX_ESDHC2 = 80, + CSU_CSLX_WDT5 = 81, + CSU_CSLX_SAI2, + CSU_CSLX_SAI1, + CSU_CSLX_SAI4, + CSU_CSLX_SAI3, + CSU_CSLX_FTM2 = 86, + CSU_CSLX_FTM1, + CSU_CSLX_FTM4, + CSU_CSLX_FTM3, + CSU_CSLX_FTM6 = 90, + CSU_CSLX_FTM5, + CSU_CSLX_FTM8, + CSU_CSLX_FTM7, + CSU_CSLX_DSCR = 121, +}; + +struct csu_ns_dev_st ns_dev[] = { + {CSU_CSLX_PCIE2_IO, CSU_ALL_RW}, + {CSU_CSLX_PCIE1_IO, CSU_ALL_RW}, + {CSU_CSLX_MG2TPR_IP, CSU_ALL_RW}, + {CSU_CSLX_IFC_MEM, CSU_ALL_RW}, + {CSU_CSLX_OCRAM, CSU_S_SUP_RW}, + {CSU_CSLX_GIC, CSU_ALL_RW}, + {CSU_CSLX_PCIE1, CSU_ALL_RW}, + {CSU_CSLX_OCRAM2, CSU_S_SUP_RW}, + {CSU_CSLX_QSPI_MEM, CSU_ALL_RW}, + {CSU_CSLX_PCIE2, CSU_ALL_RW}, + {CSU_CSLX_SATA, CSU_ALL_RW}, + {CSU_CSLX_USB1, CSU_ALL_RW}, + {CSU_CSLX_QM_BM_SWPORTAL, CSU_ALL_RW}, + {CSU_CSLX_PCIE3, CSU_ALL_RW}, + {CSU_CSLX_PCIE3_IO, CSU_ALL_RW}, + {CSU_CSLX_USB3, CSU_ALL_RW}, + {CSU_CSLX_USB2, CSU_ALL_RW}, + {CSU_CSLX_PFE, CSU_ALL_RW}, + {CSU_CSLX_SERDES, CSU_ALL_RW}, + {CSU_CSLX_QDMA, CSU_ALL_RW}, + {CSU_CSLX_LPUART2, CSU_ALL_RW}, + {CSU_CSLX_LPUART1, CSU_ALL_RW}, + {CSU_CSLX_LPUART4, CSU_ALL_RW}, + {CSU_CSLX_LPUART3, CSU_ALL_RW}, + {CSU_CSLX_LPUART6, CSU_ALL_RW}, + {CSU_CSLX_LPUART5, CSU_ALL_RW}, + {CSU_CSLX_DSPI1, CSU_ALL_RW}, + {CSU_CSLX_QSPI, CSU_ALL_RW}, + {CSU_CSLX_ESDHC, CSU_ALL_RW}, + {CSU_CSLX_IFC, CSU_ALL_RW}, + {CSU_CSLX_I2C1, CSU_ALL_RW}, + {CSU_CSLX_USB_2, CSU_ALL_RW}, + {CSU_CSLX_I2C3, CSU_ALL_RW}, + {CSU_CSLX_I2C2, CSU_ALL_RW}, + {CSU_CSLX_DUART2, CSU_ALL_RW}, + {CSU_CSLX_DUART1, CSU_ALL_RW}, + {CSU_CSLX_WDT2, CSU_ALL_RW}, + {CSU_CSLX_WDT1, CSU_ALL_RW}, + {CSU_CSLX_EDMA, CSU_ALL_RW}, + {CSU_CSLX_SYS_CNT, CSU_ALL_RW}, + {CSU_CSLX_DMA_MUX2, CSU_ALL_RW}, + {CSU_CSLX_DMA_MUX1, CSU_ALL_RW}, + {CSU_CSLX_DDR, CSU_ALL_RW}, + {CSU_CSLX_QUICC, CSU_ALL_RW}, + {CSU_CSLX_DCFG_CCU_RCPM, CSU_ALL_RW}, + {CSU_CSLX_SECURE_BOOTROM, CSU_ALL_RW}, + {CSU_CSLX_SFP, CSU_ALL_RW}, + {CSU_CSLX_TMU, CSU_ALL_RW}, + {CSU_CSLX_SECURE_MONITOR, CSU_ALL_RW}, + {CSU_CSLX_SCFG, CSU_ALL_RW}, + {CSU_CSLX_FM, CSU_ALL_RW}, + {CSU_CSLX_SEC5_5, CSU_ALL_RW}, + {CSU_CSLX_BM, CSU_ALL_RW}, + {CSU_CSLX_QM, CSU_ALL_RW}, + {CSU_CSLX_GPIO2, CSU_ALL_RW}, + {CSU_CSLX_GPIO1, CSU_ALL_RW}, + {CSU_CSLX_GPIO4, CSU_ALL_RW}, + {CSU_CSLX_GPIO3, CSU_ALL_RW}, + {CSU_CSLX_PLATFORM_CONT, CSU_ALL_RW}, + {CSU_CSLX_CSU, CSU_ALL_RW}, + {CSU_CSLX_IIC4, CSU_ALL_RW}, + {CSU_CSLX_WDT4, CSU_ALL_RW}, + {CSU_CSLX_WDT3, CSU_ALL_RW}, + {CSU_CSLX_ESDHC2, CSU_ALL_RW}, + {CSU_CSLX_WDT5, CSU_ALL_RW}, + {CSU_CSLX_SAI2, CSU_ALL_RW}, + {CSU_CSLX_SAI1, CSU_ALL_RW}, + {CSU_CSLX_SAI4, CSU_ALL_RW}, + {CSU_CSLX_SAI3, CSU_ALL_RW}, + {CSU_CSLX_FTM2, CSU_ALL_RW}, + {CSU_CSLX_FTM1, CSU_ALL_RW}, + {CSU_CSLX_FTM4, CSU_ALL_RW}, + {CSU_CSLX_FTM3, CSU_ALL_RW}, + {CSU_CSLX_FTM6, CSU_ALL_RW}, + {CSU_CSLX_FTM5, CSU_ALL_RW}, + {CSU_CSLX_FTM8, CSU_ALL_RW}, + {CSU_CSLX_FTM7, CSU_ALL_RW}, + {CSU_CSLX_DSCR, CSU_ALL_RW}, +}; + +#endif /* NS_ACCESS_H */ diff --git a/plat/nxp/soc-ls1046a/include/soc.h b/plat/nxp/soc-ls1046a/include/soc.h new file mode 100644 index 0000000..67810c3 --- /dev/null +++ b/plat/nxp/soc-ls1046a/include/soc.h @@ -0,0 +1,125 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SOC_H +#define SOC_H + +/* Chassis specific defines - common across SoC's of a particular platform */ +#include <dcfg_lsch2.h> + +#include <soc_default_base_addr.h> +#include <soc_default_helper_macros.h> + +/* DDR Regions Info */ +#define NUM_DRAM_REGIONS U(3) +#define NXP_DRAM0_ADDR ULL(0x80000000) +#define NXP_DRAM0_MAX_SIZE ULL(0x80000000) /* 2 GB */ + +#define NXP_DRAM1_ADDR ULL(0x880000000) +#define NXP_DRAM1_MAX_SIZE ULL(0x780000000) /* 30 GB */ + +#define NXP_DRAM2_ADDR ULL(0x8800000000) +#define NXP_DRAM2_MAX_SIZE ULL(0x7800000000) /* 480 GB */ + +/*DRAM0 Size defined in platform_def.h */ +#define NXP_DRAM0_SIZE PLAT_DEF_DRAM0_SIZE + +/* + * SVR Definition (not include major and minor rev) + * A: without security + * AE: with security + */ +#define SVR_LS1026A 0x870709 +#define SVR_LS1026AE 0x870708 +#define SVR_LS1046A 0x870701 +#define SVR_LS1046AE 0x870700 + +/* Number of cores in platform */ +/* Used by common code for array initialization */ +#define NUMBER_OF_CLUSTERS U(1) +#define CORES_PER_CLUSTER U(4) +#define PLATFORM_CORE_COUNT (NUMBER_OF_CLUSTERS * CORES_PER_CLUSTER) + +/* + * Required LS standard platform porting definitions + * for CCI-400 + */ +#define NXP_CCI_CLUSTER0_SL_IFACE_IX 4 + + +/* 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 U(1) +#define NXP_UART_CLK_DIVIDER U(2) + +/* set to 0 if the clusters are not symmetrical */ +#define SYMMETRICAL_CLUSTERS U(1) + + /* + * set this switch to 1 if you need to keep the debug block + * clocked during system power-down + */ +#define DEBUG_ACTIVE 0 + + /* + * pwr mgmt features supported in the soc-specific code: + * value == 0x0 the soc code does not support this feature + * value != 0x0 the soc code supports this feature + */ +#define SOC_CORE_RELEASE 0x1 +#define SOC_CORE_RESTART 0x1 +#define SOC_CORE_OFF 0x1 +#define SOC_CORE_STANDBY 0x1 +#define SOC_CORE_PWR_DWN 0x1 +#define SOC_CLUSTER_STANDBY 0x1 +#define SOC_CLUSTER_PWR_DWN 0x1 +#define SOC_SYSTEM_STANDBY 0x1 +#define SOC_SYSTEM_PWR_DWN 0x1 +#define SOC_SYSTEM_OFF 0x1 +#define SOC_SYSTEM_RESET 0x1 + +/* 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) + +/* + * Some data must be aligned on the biggest cache line size in the platform. + * This is known only to the platform as it might have a combination of + * integrated and external caches. + * + * CACHE_WRITEBACK_GRANULE is defined in soc.def + */ + + /* One cache line needed for bakery locks on ARM platforms */ +#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE) + +#ifndef __ASSEMBLER__ +/* CCI slave interfaces */ +static const int cci_map[] = { + NXP_CCI_CLUSTER0_SL_IFACE_IX, +}; + +void soc_init_lowlevel(void); +void soc_init_percpu(void); +void _soc_set_start_addr(unsigned long addr); +#endif + +#endif /* SOC_H */ diff --git a/plat/nxp/soc-ls1046a/ls1046afrwy/ddr_init.c b/plat/nxp/soc-ls1046a/ls1046afrwy/ddr_init.c new file mode 100644 index 0000000..3d561c7 --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046afrwy/ddr_init.c @@ -0,0 +1,177 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> +#include <string.h> + +#include <common/debug.h> +#include <ddr.h> +#include <lib/utils.h> + +#include <errata.h> +#include <platform_def.h> + +#ifdef CONFIG_STATIC_DDR +const struct ddr_cfg_regs static_1600 = { + .cs[0].config = U(0x80010412), + .cs[0].bnds = U(0x7F), + .sdram_cfg[0] = U(0xE50C0008), + .sdram_cfg[1] = U(0x00401010), + .sdram_cfg[2] = U(0x1), + .timing_cfg[0] = U(0xFA550018), + .timing_cfg[1] = U(0xBAB40C52), + .timing_cfg[2] = U(0x0048C11C), + .timing_cfg[3] = U(0x01111000), + .timing_cfg[4] = U(0x00000002), + .timing_cfg[5] = U(0x03401400), + .timing_cfg[6] = U(0x0), + .timing_cfg[7] = U(0x23300000), + .timing_cfg[8] = U(0x02116600), + .timing_cfg[9] = U(0x0), + .dq_map[0] = U(0x0), + .dq_map[1] = U(0x0), + .dq_map[2] = U(0x0), + .dq_map[3] = U(0x0), + .sdram_mode[0] = U(0x01010210), + .sdram_mode[1] = U(0x0), + .sdram_mode[8] = U(0x00000500), + .sdram_mode[9] = U(0x04000000), + .interval = U(0x18600618), + .zq_cntl = U(0x8A090705), + .ddr_sr_cntr = U(0x0), + .clk_cntl = U(0x2000000), + .cdr[0] = U(0x80040000), + .cdr[1] = U(0xC1), + .wrlvl_cntl[0] = U(0x86550607), + .wrlvl_cntl[1] = U(0x07070708), + .wrlvl_cntl[2] = U(0x0808088), +}; + +long long board_static_ddr(struct ddr_info *priv) +{ + memcpy(&priv->ddr_reg, &static_1600, sizeof(static_1600)); + + return 0x80000000ULL; +} +#else /* ifndef CONFIG_STATIC_DDR */ +static const struct rc_timing rcz[] = { + {U(1600), U(8), U(7)}, + {U(2100), U(8), U(7)}, + {} +}; + +static const struct board_timing ram[] = { + {U(0x1f), rcz, U(0x01010101), U(0x01010101)}, +}; + +int ddr_board_options(struct ddr_info *priv) +{ + int ret; + struct memctl_opt *popts = &priv->opt; + + ret = cal_board_params(priv, ram, ARRAY_SIZE(ram)); + if (ret != 0) { + return ret; + } + + popts->bstopre = 0; + popts->half_strength_drive_en = 1; + popts->cpo_sample = U(0x46); + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_50ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_50ohm) | + DDR_CDR2_VREF_TRAIN_EN; + popts->output_driver_impedance = 1; + + return 0; +} + +/* DDR model number: MT40A512M16JY-083E:B */ +struct dimm_params ddr_raw_timing = { + .n_ranks = U(1), + .rank_density = ULL(4294967296), + .capacity = ULL(4294967296), + .primary_sdram_width = U(64), + .ec_sdram_width = U(8), + .rdimm = U(0), + .mirrored_dimm = U(0), + .n_row_addr = U(16), + .n_col_addr = U(10), + .bank_group_bits = U(1), + .edc_config = U(2), + .burst_lengths_bitmask = U(0x0c), + .tckmin_x_ps = 750, + .tckmax_ps = 1900, + .caslat_x = U(0x0001FFE00), + .taa_ps = 13500, + .trcd_ps = 13500, + .trp_ps = 13500, + .tras_ps = 33000, + .trc_ps = 46500, + .twr_ps = 15000, + .trfc1_ps = 350000, + .trfc2_ps = 260000, + .trfc4_ps = 160000, + .tfaw_ps = 30000, + .trrds_ps = 5300, + .trrdl_ps = 6400, + .tccdl_ps = 5355, + .refresh_rate_ps = U(7800000), + .dq_mapping[0] = U(0x0), + .dq_mapping[1] = U(0x0), + .dq_mapping[2] = U(0x0), + .dq_mapping[3] = U(0x0), + .dq_mapping[4] = U(0x0), + .dq_mapping_ors = U(0), + .rc = U(0x1f), +}; + +int ddr_get_ddr_params(struct dimm_params *pdimm, struct ddr_conf *conf) +{ + static const char dimm_model[] = "Fixed DDR on board"; + + conf->dimm_in_use[0] = 1; + memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params)); + memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1); + + return 1; +} +#endif /* ifdef CONFIG_STATIC_DDR */ + +long long init_ddr(void) +{ + int spd_addr[] = {NXP_SPD_EEPROM0}; + struct ddr_info info; + struct sysinfo sys; + long long dram_size; + + zeromem(&sys, sizeof(sys)); + if (get_clocks(&sys)) { + ERROR("System clocks are not set\n"); + assert(0); + } + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0); + debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1); + + zeromem(&info, sizeof(struct ddr_info)); + info.num_ctlrs = 1; + info.dimm_on_ctlr = 1; + info.clk = get_ddr_freq(&sys, 0); + info.spd_addr = spd_addr; + info.ddr[0] = (void *)NXP_DDR_ADDR; + + dram_size = dram_init(&info); + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + +#ifdef ERRATA_SOC_A008850 + erratum_a008850_post(); +#endif + + return dram_size; +} diff --git a/plat/nxp/soc-ls1046a/ls1046afrwy/plat_def.h b/plat/nxp/soc-ls1046a/ls1046afrwy/plat_def.h new file mode 100644 index 0000000..5134a00 --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046afrwy/plat_def.h @@ -0,0 +1,79 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include <arch.h> +/* + * Required without TBBR. + * To include the defines for DDR PHY Images. + */ +#include <tbbr_img_def.h> + +#include "policy.h" +#include <soc.h> + +#define NXP_SPD_EEPROM0 0x51 + +#define NXP_SYSCLK_FREQ 100000000 +#define NXP_DDRCLK_FREQ 100000000 + +/* UART related definition */ +#define NXP_CONSOLE_ADDR NXP_UART_ADDR +#define NXP_CONSOLE_BAUDRATE 115200 + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL2) +#if defined(TRUSTED_BOARD_BOOT) +#define PLATFORM_STACK_SIZE 0x2000 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +/* SD block buffer */ +#define NXP_SD_BLOCK_BUF_SIZE (0x8000) +#define NXP_SD_BLOCK_BUF_ADDR ULL(0x80000000) + +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES U(3) +#define MAX_IO_BLOCK_DEVICES U(1) +#define MAX_IO_HANDLES U(4) + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#define MAX_FIP_DEVICES U(2) +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES U(1) +#endif + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define BL32_IRQ_SEC_PHY_TIMER 29 + +/* + * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_LS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_LS_G0_IRQ_PROPS(grp) + +#endif /* PLAT_DEF_H */ diff --git a/plat/nxp/soc-ls1046a/ls1046afrwy/platform.c b/plat/nxp/soc-ls1046a/ls1046afrwy/platform.c new file mode 100644 index 0000000..cef920f --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046afrwy/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2020-2022 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-ls1046a/ls1046afrwy/platform.mk b/plat/nxp/soc-ls1046a/ls1046afrwy/platform.mk new file mode 100644 index 0000000..1f7fad6 --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046afrwy/platform.mk @@ -0,0 +1,39 @@ +# +# Copyright 2018-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters + +BOOT_MODE ?= qspi +BOARD := ls1046afrwy +POVDD_ENABLE := no + +# DDR Compilation Configs +CONFIG_STATIC_DDR := 0 +CONFIG_DDR_NODIMM := 1 +DDRC_NUM_DIMM := 0 +NUM_OF_DDRC := 1 +DDRC_NUM_CS := 1 +DDR_ECC_EN := yes + +# On-Board Flash Details +QSPI_FLASH_SZ := 0x20000000 +NOR_FLASH_SZ := 0x20000000 + +# 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 := qspi \ + sd + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Adding SoC build info +include plat/nxp/soc-ls1046a/soc.mk diff --git a/plat/nxp/soc-ls1046a/ls1046afrwy/platform_def.h b/plat/nxp/soc-ls1046a/ls1046afrwy/platform_def.h new file mode 100644 index 0000000..7f98bb1 --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046afrwy/platform_def.h @@ -0,0 +1,13 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <plat_def.h> +#include <plat_default_def.h> + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/nxp/soc-ls1046a/ls1046afrwy/policy.h b/plat/nxp/soc-ls1046a/ls1046afrwy/policy.h new file mode 100644 index 0000000..c6c325f --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046afrwy/policy.h @@ -0,0 +1,16 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef POLICY_H +#define POLICY_H + +/* Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +#endif /* POLICY_H */ diff --git a/plat/nxp/soc-ls1046a/ls1046aqds/ddr_init.c b/plat/nxp/soc-ls1046a/ls1046aqds/ddr_init.c new file mode 100644 index 0000000..89c9c0a --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046aqds/ddr_init.c @@ -0,0 +1,91 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> + +#include <common/debug.h> +#include <ddr.h> +#include <lib/utils.h> + +#include <errata.h> +#include "platform_def.h" + +static const struct rc_timing rce[] = { + {U(1600), U(8), U(7)}, + {U(1867), U(8), U(7)}, + {U(2134), U(8), U(9)}, + {} +}; + +static const struct board_timing udimm[] = { + {U(0x04), rce, U(0x01020304), U(0x06070805)}, +}; + +int ddr_board_options(struct ddr_info *priv) +{ + int ret; + struct memctl_opt *popts = &priv->opt; + + if (popts->rdimm) { + debug("RDIMM parameters not set.\n"); + return -EINVAL; + } + + ret = cal_board_params(priv, udimm, ARRAY_SIZE(udimm)); + if (ret != 0) { + return ret; + } + + popts->wrlvl_override = U(1); + popts->wrlvl_sample = U(0x0); /* 32 clocks */ + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | + DDR_CDR1_ODT(DDR_CDR_ODT_80ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) | + DDR_CDR2_VREF_TRAIN_EN | + DDR_CDR2_VREF_RANGE_2; + + /* optimize cpo for erratum A-009942 */ + popts->cpo_sample = U(0x70); + + return 0; +} + +long long init_ddr(void) +{ + int spd_addr[] = { NXP_SPD_EEPROM0 }; + struct ddr_info info; + struct sysinfo sys; + long long dram_size; + + zeromem(&sys, sizeof(sys)); + if (get_clocks(&sys)) { + ERROR("System clocks are not set\n"); + assert(0); + } + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0); + debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1); + + zeromem(&info, sizeof(struct ddr_info)); + info.num_ctlrs = 1; + info.dimm_on_ctlr = 1; + info.clk = get_ddr_freq(&sys, 0); + info.spd_addr = spd_addr; + info.ddr[0] = (void *)NXP_DDR_ADDR; + + dram_size = dram_init(&info); + + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + +#ifdef ERRATA_SOC_A008850 + erratum_a008850_post(); +#endif + + return dram_size; +} diff --git a/plat/nxp/soc-ls1046a/ls1046aqds/plat_def.h b/plat/nxp/soc-ls1046a/ls1046aqds/plat_def.h new file mode 100644 index 0000000..aa69a66 --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046aqds/plat_def.h @@ -0,0 +1,79 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include <arch.h> +/* Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include <tbbr_img_def.h> + +#include <policy.h> +#include <soc.h> + +#define NXP_SPD_EEPROM0 0x51 + +#define NXP_SYSCLK_FREQ 100000000 +#define NXP_DDRCLK_FREQ 100000000 + +/* UART related definition */ +#define NXP_CONSOLE_ADDR NXP_UART_ADDR +#define NXP_CONSOLE_BAUDRATE 115200 + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL2) +#if defined(TRUSTED_BOARD_BOOT) +#define PLATFORM_STACK_SIZE 0x2000 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +/* SD block buffer */ +#define NXP_SD_BLOCK_BUF_SIZE (0x00100000) +#define NXP_SD_BLOCK_BUF_ADDR ULL(0x80000000) + +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES U(3) +#define MAX_IO_BLOCK_DEVICES U(1) +#define MAX_IO_HANDLES U(4) + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#define MAX_FIP_DEVICES U(2) +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES U(1) +#endif + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define BL32_IRQ_SEC_PHY_TIMER 29 + +/* + * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_LS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_LS_G0_IRQ_PROPS(grp) + +#endif diff --git a/plat/nxp/soc-ls1046a/ls1046aqds/platform.c b/plat/nxp/soc-ls1046a/ls1046aqds/platform.c new file mode 100644 index 0000000..cef920f --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046aqds/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2020-2022 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-ls1046a/ls1046aqds/platform.mk b/plat/nxp/soc-ls1046a/ls1046aqds/platform.mk new file mode 100644 index 0000000..9600b93 --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046aqds/platform.mk @@ -0,0 +1,39 @@ +# +# Copyright 2018-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters +BOOT_MODE ?= qspi +BOARD := ls1046aqds +POVDD_ENABLE := no + + # DDR Compilation Configs +NUM_OF_DDRC := 1 +DDRC_NUM_DIMM := 1 +DDRC_NUM_CS := 4 +DDR_ECC_EN := yes +CONFIG_STATIC_DDR := 0 + +# On-Board Flash Details +QSPI_FLASH_SZ := 0x20000000 +NOR_FLASH_SZ := 0x20000000 + +# 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 := qspi \ + sd \ + nor \ + nand + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Adding SoC build info +include plat/nxp/soc-ls1046a/soc.mk diff --git a/plat/nxp/soc-ls1046a/ls1046aqds/platform_def.h b/plat/nxp/soc-ls1046a/ls1046aqds/platform_def.h new file mode 100644 index 0000000..7f98bb1 --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046aqds/platform_def.h @@ -0,0 +1,13 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <plat_def.h> +#include <plat_default_def.h> + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/nxp/soc-ls1046a/ls1046aqds/policy.h b/plat/nxp/soc-ls1046a/ls1046aqds/policy.h new file mode 100644 index 0000000..c6c325f --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046aqds/policy.h @@ -0,0 +1,16 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef POLICY_H +#define POLICY_H + +/* Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +#endif /* POLICY_H */ diff --git a/plat/nxp/soc-ls1046a/ls1046ardb/ddr_init.c b/plat/nxp/soc-ls1046a/ls1046ardb/ddr_init.c new file mode 100644 index 0000000..b9940cf --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046ardb/ddr_init.c @@ -0,0 +1,267 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> +#include <string.h> + +#include <common/debug.h> +#include <ddr.h> +#include <lib/utils.h> + +#include <errata.h> +#include <platform_def.h> + +#ifdef CONFIG_STATIC_DDR +const struct ddr_cfg_regs static_2100 = { + .cs[0].config = U(0x80040322), + .cs[0].bnds = U(0x1FF), + .cs[1].config = U(0x80000322), + .cs[1].bnds = U(0x1FF), + .sdram_cfg[0] = U(0xE5004000), + .sdram_cfg[1] = U(0x401151), + .timing_cfg[0] = U(0xD1770018), + .timing_cfg[1] = U(0xF2FC9245), + .timing_cfg[2] = U(0x594197), + .timing_cfg[3] = U(0x2101100), + .timing_cfg[4] = U(0x220002), + .timing_cfg[5] = U(0x5401400), + .timing_cfg[7] = U(0x26600000), + .timing_cfg[8] = U(0x5446A00), + .dq_map[0] = U(0x32C57554), + .dq_map[1] = U(0xD4BB0BD4), + .dq_map[2] = U(0x2EC2F554), + .dq_map[3] = U(0xD95D4001), + .sdram_mode[0] = U(0x3010631), + .sdram_mode[1] = U(0x100200), + .sdram_mode[9] = U(0x8400000), + .sdram_mode[8] = U(0x500), + .sdram_mode[2] = U(0x10631), + .sdram_mode[3] = U(0x100200), + .sdram_mode[10] = U(0x400), + .sdram_mode[11] = U(0x8400000), + .sdram_mode[4] = U(0x10631), + .sdram_mode[5] = U(0x100200), + .sdram_mode[12] = U(0x400), + .sdram_mode[13] = U(0x8400000), + .sdram_mode[6] = U(0x10631), + .sdram_mode[7] = U(0x100200), + .sdram_mode[14] = U(0x400), + .sdram_mode[15] = U(0x8400000), + .interval = U(0x1FFE07FF), + .zq_cntl = U(0x8A090705), + .clk_cntl = U(0x2000000), + .cdr[0] = U(0x80040000), + .cdr[1] = U(0xC1), + .wrlvl_cntl[0] = U(0x86750609), + .wrlvl_cntl[1] = U(0xA0B0C0D), + .wrlvl_cntl[2] = U(0xF10110E), +}; + +const struct ddr_cfg_regs static_1800 = { + .cs[0].config = U(0x80040322), + .cs[0].bnds = U(0x1FF), + .cs[1].config = U(0x80000322), + .cs[1].bnds = U(0x1FF), + .sdram_cfg[0] = U(0xE5004000), + .sdram_cfg[1] = U(0x401151), + .timing_cfg[0] = U(0x91660018), + .timing_cfg[1] = U(0xDDD82045), + .timing_cfg[2] = U(0x512153), + .timing_cfg[3] = U(0x10E1100), + .timing_cfg[4] = U(0x220002), + .timing_cfg[5] = U(0x4401400), + .timing_cfg[7] = U(0x14400000), + .timing_cfg[8] = U(0x3335900), + .dq_map[0] = U(0x32C57554), + .dq_map[1] = U(0xD4BB0BD4), + .dq_map[2] = U(0x2EC2F554), + .dq_map[3] = U(0xD95D4001), + .sdram_mode[0] = U(0x3010421), + .sdram_mode[1] = U(0x80200), + .sdram_mode[9] = U(0x4400000), + .sdram_mode[8] = U(0x500), + .sdram_mode[2] = U(0x10421), + .sdram_mode[3] = U(0x80200), + .sdram_mode[10] = U(0x400), + .sdram_mode[11] = U(0x4400000), + .sdram_mode[4] = U(0x10421), + .sdram_mode[5] = U(0x80200), + .sdram_mode[12] = U(0x400), + .sdram_mode[13] = U(0x4400000), + .sdram_mode[6] = U(0x10421), + .sdram_mode[7] = U(0x80200), + .sdram_mode[14] = U(0x400), + .sdram_mode[15] = U(0x4400000), + .interval = U(0x1B6C06DB), + .zq_cntl = U(0x8A090705), + .clk_cntl = U(0x2000000), + .cdr[0] = U(0x80040000), + .cdr[1] = U(0xC1), + .wrlvl_cntl[0] = U(0x86750607), + .wrlvl_cntl[1] = U(0x8090A0B), + .wrlvl_cntl[2] = U(0xD0E0F0C), +}; + +const struct ddr_cfg_regs static_1600 = { + .cs[0].config = U(0x80040322), + .cs[0].bnds = U(0x1FF), + .cs[1].config = U(0x80000322), + .cs[1].bnds = U(0x1FF), + .sdram_cfg[0] = U(0xE5004000), + .sdram_cfg[1] = U(0x401151), + .sdram_cfg[2] = U(0x0), + .timing_cfg[0] = U(0x91550018), + .timing_cfg[1] = U(0xBAB48E44), + .timing_cfg[2] = U(0x490111), + .timing_cfg[3] = U(0x10C1000), + .timing_cfg[4] = U(0x220002), + .timing_cfg[5] = U(0x3401400), + .timing_cfg[6] = U(0x0), + .timing_cfg[7] = U(0x13300000), + .timing_cfg[8] = U(0x1224800), + .timing_cfg[9] = U(0x0), + .dq_map[0] = U(0x32C57554), + .dq_map[1] = U(0xD4BB0BD4), + .dq_map[2] = U(0x2EC2F554), + .dq_map[3] = U(0xD95D4001), + .sdram_mode[0] = U(0x3010211), + .sdram_mode[1] = U(0x0), + .sdram_mode[9] = U(0x400000), + .sdram_mode[8] = U(0x500), + .sdram_mode[2] = U(0x10211), + .sdram_mode[3] = U(0x0), + .sdram_mode[10] = U(0x400), + .sdram_mode[11] = U(0x400000), + .sdram_mode[4] = U(0x10211), + .sdram_mode[5] = U(0x0), + .sdram_mode[12] = U(0x400), + .sdram_mode[13] = U(0x400000), + .sdram_mode[6] = U(0x10211), + .sdram_mode[7] = U(0x0), + .sdram_mode[14] = U(0x400), + .sdram_mode[15] = U(0x400000), + .interval = U(0x18600618), + .zq_cntl = U(0x8A090705), + .ddr_sr_cntr = U(0x0), + .clk_cntl = U(0x2000000), + .cdr[0] = U(0x80040000), + .cdr[1] = U(0xC1), + .wrlvl_cntl[0] = U(0x86750607), + .wrlvl_cntl[1] = U(0x8090A0B), + .wrlvl_cntl[2] = U(0xD0E0F0C), +}; + +struct static_table { + unsigned long rate; + const struct ddr_cfg_regs *regs; +}; + +const struct static_table table[] = { + {1600, &static_1600}, + {1800, &static_1800}, + {2100, &static_2100}, +}; + +long long board_static_ddr(struct ddr_info *priv) +{ + const unsigned long clk = priv->clk / 1000000; + long long size = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(table); i++) { + if (table[i].rate >= clk) { + break; + } + } + if (i < ARRAY_SIZE(table)) { + VERBOSE("Found static setting for rate %ld\n", table[i].rate); + memcpy(&priv->ddr_reg, table[i].regs, + sizeof(struct ddr_cfg_regs)); + size = 0x200000000UL; + } else { + ERROR("Not static settings for rate %ld\n", clk); + } + + return size; +} +#else /* ifndef CONFIG_STATIC_DDR */ +static const struct rc_timing rce[] = { + {U(1600), U(8), U(7)}, + {U(1867), U(8), U(7)}, + {U(2134), U(8), U(9)}, + {} +}; + +static const struct board_timing udimm[] = { + {U(0x04), rce, U(0x01020304), U(0x06070805)}, + {U(0x1f), rce, U(0x01020304), U(0x06070805)}, +}; + +int ddr_board_options(struct ddr_info *priv) +{ + int ret; + struct memctl_opt *popts = &priv->opt; + + if (popts->rdimm) { + debug("RDIMM parameters not set.\n"); + return -EINVAL; + } + + ret = cal_board_params(priv, udimm, ARRAY_SIZE(udimm)); + if (ret != 0) { + return ret; + } + + popts->wrlvl_override = U(1); + popts->wrlvl_sample = U(0x0); /* 32 clocks */ + popts->cpo_sample = U(0x61); + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | + DDR_CDR1_ODT(DDR_CDR_ODT_80ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) | + DDR_CDR2_VREF_TRAIN_EN | + DDR_CDR2_VREF_RANGE_2; + popts->bstopre = U(0); + + return 0; +} +#endif /* ifdef CONFIG_STATIC_DDR */ + +long long init_ddr(void) +{ + int spd_addr[] = {NXP_SPD_EEPROM0}; + struct ddr_info info; + struct sysinfo sys; + long long dram_size; + + zeromem(&sys, sizeof(sys)); + if (get_clocks(&sys)) { + ERROR("System clocks are not set\n"); + assert(0); + } + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0); + debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1); + + zeromem(&info, sizeof(struct ddr_info)); + info.num_ctlrs = U(1); + info.dimm_on_ctlr = U(1); + info.clk = get_ddr_freq(&sys, 0); + info.spd_addr = spd_addr; + info.ddr[0] = (void *)NXP_DDR_ADDR; + + dram_size = dram_init(&info); + + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + +#ifdef ERRATA_SOC_A008850 + erratum_a008850_post(); +#endif + + return dram_size; +} diff --git a/plat/nxp/soc-ls1046a/ls1046ardb/plat_def.h b/plat/nxp/soc-ls1046a/ls1046ardb/plat_def.h new file mode 100644 index 0000000..b5e66ae --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046ardb/plat_def.h @@ -0,0 +1,79 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include <arch.h> +/* + * Required without TBBR. + * To include the defines for DDR PHY Images. + */ +#include <tbbr_img_def.h> + +#include "policy.h" +#include <soc.h> + +#define NXP_SPD_EEPROM0 0x51 + +#define NXP_SYSCLK_FREQ 100000000 +#define NXP_DDRCLK_FREQ 100000000 + +/* UART related definition */ +#define NXP_CONSOLE_ADDR NXP_UART_ADDR +#define NXP_CONSOLE_BAUDRATE 115200 + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL2) +#if defined(TRUSTED_BOARD_BOOT) +#define PLATFORM_STACK_SIZE 0x2000 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +/* SD block buffer */ +#define NXP_SD_BLOCK_BUF_SIZE (0x00100000) +#define NXP_SD_BLOCK_BUF_ADDR ULL(0x80000000) + +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES U(3) +#define MAX_IO_BLOCK_DEVICES U(1) +#define MAX_IO_HANDLES U(4) + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#define MAX_FIP_DEVICES U(2) +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES U(1) +#endif + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define BL32_IRQ_SEC_PHY_TIMER 29 + +/* + * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_LS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_LS_G0_IRQ_PROPS(grp) + +#endif /* PLAT_DEF_H */ diff --git a/plat/nxp/soc-ls1046a/ls1046ardb/platform.c b/plat/nxp/soc-ls1046a/ls1046ardb/platform.c new file mode 100644 index 0000000..cef920f --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046ardb/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2020-2022 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-ls1046a/ls1046ardb/platform.mk b/plat/nxp/soc-ls1046a/ls1046ardb/platform.mk new file mode 100644 index 0000000..32e6db5 --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046ardb/platform.mk @@ -0,0 +1,38 @@ +# +# Copyright 2018-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters +BOOT_MODE ?= qspi +BOARD := ls1046ardb +POVDD_ENABLE := no + +# DDR Compilation Configs +NUM_OF_DDRC := 1 +DDRC_NUM_DIMM := 1 +DDRC_NUM_CS := 4 +DDR_ECC_EN := yes +CONFIG_STATIC_DDR := 0 + +# On-Board Flash Details +QSPI_FLASH_SZ := 0x20000000 +NOR_FLASH_SZ := 0x20000000 + +# 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 := qspi \ + 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-ls1046a/soc.mk diff --git a/plat/nxp/soc-ls1046a/ls1046ardb/platform_def.h b/plat/nxp/soc-ls1046a/ls1046ardb/platform_def.h new file mode 100644 index 0000000..7f98bb1 --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046ardb/platform_def.h @@ -0,0 +1,13 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <plat_def.h> +#include <plat_default_def.h> + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/nxp/soc-ls1046a/ls1046ardb/policy.h b/plat/nxp/soc-ls1046a/ls1046ardb/policy.h new file mode 100644 index 0000000..c6c325f --- /dev/null +++ b/plat/nxp/soc-ls1046a/ls1046ardb/policy.h @@ -0,0 +1,16 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef POLICY_H +#define POLICY_H + +/* Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +#endif /* POLICY_H */ diff --git a/plat/nxp/soc-ls1046a/soc.c b/plat/nxp/soc-ls1046a/soc.c new file mode 100644 index 0000000..d17e672 --- /dev/null +++ b/plat/nxp/soc-ls1046a/soc.c @@ -0,0 +1,395 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <arch.h> +#include <caam.h> +#include <cassert.h> +#include <cci.h> +#include <common/debug.h> +#include <dcfg.h> +#ifdef I2C_INIT +#include <i2c.h> +#endif +#include <lib/mmio.h> +#include <lib/xlat_tables/xlat_tables_v2.h> +#include <ls_interconnect.h> +#ifdef POLICY_FUSE_PROVISION +#include <nxp_gpio.h> +#endif +#if TRUSTED_BOARD_BOOT +#include <nxp_smmu.h> +#endif +#include <nxp_timer.h> +#include <plat_console.h> +#include <plat_gic.h> +#include <plat_tzc400.h> +#include <scfg.h> +#if defined(NXP_SFP_ENABLED) +#include <sfp.h> +#endif + +#include <errata.h> +#include <ns_access.h> +#ifdef CONFIG_OCRAM_ECC_EN +#include <ocram.h> +#endif +#include <plat_common.h> +#include <platform_def.h> +#include <soc.h> + +static dcfg_init_info_t dcfg_init_data = { + .g_nxp_dcfg_addr = NXP_DCFG_ADDR, + .nxp_sysclk_freq = NXP_SYSCLK_FREQ, + .nxp_ddrclk_freq = NXP_DDRCLK_FREQ, + .nxp_plat_clk_divider = NXP_PLATFORM_CLK_DIVIDER, +}; + +/* Function to return the SoC SYS CLK */ +static unsigned int get_sys_clk(void) +{ + return NXP_SYSCLK_FREQ; +} + +/* + * Function returns the base counter frequency + * after reading the first entry at CNTFID0 (0x20 offset). + * + * Function is used by: + * 1. ARM common code for PSCI management. + * 2. ARM Generic Timer init. + * + */ +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int counter_base_frequency; + + counter_base_frequency = get_sys_clk() / 4; + + return counter_base_frequency; +} + +#ifdef IMAGE_BL2 +/* Functions for BL2 */ + +static struct soc_type soc_list[] = { + SOC_ENTRY(LS1046A, LS1046A, 1, 4), + SOC_ENTRY(LS1046AE, LS1046AE, 1, 4), + SOC_ENTRY(LS1026A, LS1026A, 1, 2), + SOC_ENTRY(LS1026AE, LS1026AE, 1, 2), +}; + +#ifdef POLICY_FUSE_PROVISION +static gpio_init_info_t gpio_init_data = { + .gpio1_base_addr = NXP_GPIO1_ADDR, + .gpio2_base_addr = NXP_GPIO2_ADDR, + .gpio3_base_addr = NXP_GPIO3_ADDR, + .gpio4_base_addr = NXP_GPIO4_ADDR, +}; +#endif + +/* + * Function to set the base counter frequency at + * the first entry of the Frequency Mode Table, + * at CNTFID0 (0x20 offset). + * + * Set the value of the pirmary core register cntfrq_el0. + */ +static void set_base_freq_CNTFID0(void) +{ + /* + * Below register specifies the base frequency of the system counter. + * As per NXP Board Manuals: + * The system counter always works with SYS_REF_CLK/4 frequency clock. + */ + unsigned int counter_base_frequency = get_sys_clk() / 4; + + /* Setting the frequency in the Frequency modes table. + * + * Note: The value for ls1046ardb board at this offset + * is not RW as stated. This offset have the + * fixed value of 100000400 Hz. + * + * The below code line has no effect. + * Keeping it for other platforms where it has effect. + */ + mmio_write_32(NXP_TIMER_ADDR + CNTFID_OFF, counter_base_frequency); + + write_cntfrq_el0(counter_base_frequency); +} + +void soc_preload_setup(void) +{ + +} + +/* + * This function implements soc specific erratas + * This is called before DDR is initialized or MMU is enabled + */ +void soc_early_init(void) +{ + uint8_t num_clusters, cores_per_cluster; + dram_regions_info_t *dram_regions_info = get_dram_regions_info(); + +#ifdef CONFIG_OCRAM_ECC_EN + ocram_init(NXP_OCRAM_ADDR, NXP_OCRAM_SIZE); +#endif + dcfg_init(&dcfg_init_data); +#ifdef POLICY_FUSE_PROVISION + gpio_init(&gpio_init_data); + sec_init(NXP_CAAM_ADDR); +#endif +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif + set_base_freq_CNTFID0(); + + /* Enable snooping on SEC read and write transactions */ + scfg_setbits32((void *)(NXP_SCFG_ADDR + SCFG_SNPCNFGCR_OFFSET), + SCFG_SNPCNFGCR_SECRDSNP | SCFG_SNPCNFGCR_SECWRSNP); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map)); + + /* + * Enable Interconnect coherency for the primary CPU's cluster. + */ + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + plat_ls_interconnect_enter_coherency(num_clusters); + +#if TRUSTED_BOARD_BOOT + uint32_t mode; + + sfp_init(NXP_SFP_ADDR); + /* + * For secure boot disable SMMU. + * Later when platform security policy comes in picture, + * this might get modified based on the policy + */ + if (check_boot_mode_secure(&mode) == true) { + bypass_smmu(NXP_SMMU_ADDR); + } + + /* + * For Mbedtls currently crypto is not supported via CAAM + * enable it when that support is there. In tbbr.mk + * the CAAM_INTEG is set as 0. + */ +#ifndef MBEDTLS_X509 + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled() == false) { + INFO("SEC is disabled.\n"); + } else { + sec_init(NXP_CAAM_ADDR); + } +#endif +#elif defined(POLICY_FUSE_PROVISION) + gpio_init(&gpio_init_data); + sfp_init(NXP_SFP_ADDR); + sec_init(NXP_CAAM_ADDR); +#endif + + soc_errata(); + + /* Initialize system level generic timer for Layerscape Socs. */ + delay_timer_init(NXP_TIMER_ADDR); + +#ifdef DDR_INIT + i2c_init(NXP_I2C_ADDR); + dram_regions_info->total_dram_size = init_ddr(); +#endif +} + +void soc_bl2_prepare_exit(void) +{ +#if defined(NXP_SFP_ENABLED) && defined(DISABLE_FUSE_WRITE) + set_sfp_wr_disable(); +#endif +} + +/* This function returns the boot device based on RCW_SRC */ +enum boot_device get_boot_dev(void) +{ + enum boot_device src = BOOT_DEVICE_NONE; + uint32_t porsr1; + uint32_t rcw_src, val; + + porsr1 = read_reg_porsr1(); + + rcw_src = (porsr1 & PORSR1_RCW_MASK) >> PORSR1_RCW_SHIFT; + + val = rcw_src & RCW_SRC_NAND_MASK; + + if (val == RCW_SRC_NAND_VAL) { + val = rcw_src & NAND_RESERVED_MASK; + if ((val != NAND_RESERVED_1) && (val != NAND_RESERVED_2)) { + src = BOOT_DEVICE_IFC_NAND; + INFO("RCW BOOT SRC is IFC NAND\n"); + } + } else { + /* RCW SRC NOR */ + val = rcw_src & RCW_SRC_NOR_MASK; + if (val == NOR_8B_VAL || val == NOR_16B_VAL) { + src = BOOT_DEVICE_IFC_NOR; + INFO("RCW BOOT SRC is IFC NOR\n"); + } else { + switch (rcw_src) { + case QSPI_VAL1: + case QSPI_VAL2: + src = BOOT_DEVICE_QSPI; + INFO("RCW BOOT SRC is QSPI\n"); + break; + case SD_VAL: + src = BOOT_DEVICE_EMMC; + INFO("RCW BOOT SRC is SD/EMMC\n"); + break; + default: + src = BOOT_DEVICE_NONE; + } + } + } + + return src; +} + +/* This function sets up access permissions on memory regions */ +void soc_mem_access(void) +{ + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); + struct tzc400_reg tzc400_reg_list[MAX_NUM_TZC_REGION]; + unsigned 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); + } + + mem_access_setup(NXP_TZC_ADDR, index, tzc400_reg_list); +} + +#else /* IMAGE_BL2 */ +/* Functions for BL31 */ + +const unsigned char _power_domain_tree_desc[] = {1, 1, 4}; + +CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256, + assert_invalid_ls1046_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) +{ + static uint32_t target_mask_array[PLATFORM_CORE_COUNT]; + /* + * On a GICv2 system, the Group 1 secure interrupts are treated + * as Group 0 interrupts. + */ + static interrupt_prop_t ls_interrupt_props[] = { + PLAT_LS_G1S_IRQ_PROPS(GICV2_INTR_GROUP0), + PLAT_LS_G0_IRQ_PROPS(GICV2_INTR_GROUP0) + }; + + plat_ls_gic_driver_init( +#if (TEST_BL31) + /* Defect in simulator - GIC base addresses (4Kb aligned) */ + NXP_GICD_4K_ADDR, + NXP_GICC_4K_ADDR, +#else + NXP_GICD_64K_ADDR, + NXP_GICC_64K_ADDR, +#endif + PLATFORM_CORE_COUNT, + ls_interrupt_props, + ARRAY_SIZE(ls_interrupt_props), + target_mask_array); + + plat_ls_gic_init(); + enable_init_timer(); +} + +/* This function initializes the soc from the BL31 module */ +void soc_init(void) +{ + /* low-level init of the soc */ + soc_init_lowlevel(); + _init_global_data(); + soc_init_percpu(); + _initialize_psci(); + + /* + * Initialize the interconnect during cold boot. + * No need for locks as no other CPU is active. + */ + cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map)); + + /* + * Enable coherency in interconnect for the primary CPU's cluster. + * Earlier bootloader stages might already do this but we can't + * assume so. No harm in executing this code twice. + */ + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr())); + + /* Init CSU to enable non-secure access to peripherals */ + enable_layerscape_ns_access(ns_dev, ARRAY_SIZE(ns_dev), NXP_CSU_ADDR); + + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled() == false) { + INFO("SEC is disabled.\n"); + } else { + sec_init(NXP_CAAM_ADDR); + } +} + +void soc_runtime_setup(void) +{ + +} + +#endif /* IMAGE_BL2 */ diff --git a/plat/nxp/soc-ls1046a/soc.def b/plat/nxp/soc-ls1046a/soc.def new file mode 100644 index 0000000..e6b37c0 --- /dev/null +++ b/plat/nxp/soc-ls1046a/soc.def @@ -0,0 +1,107 @@ +# +# Copyright 2022 NXP +# +# 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 := GIC400 + +# set to CCI400 or CCN504 or CCN508 +INTERCONNECT := CCI400 + +# indicate layerscape chassis level - set to 3=LSCH3 or 2=LSCH2 +CHASSIS := 2 + +# TZC IP Details TZC used is TZC380 or TZC400 +TZC_ID := TZC400 + +# CONSOLE Details available is NS16550 or PL011 +CONSOLE := NS16550 + + # Select the DDR PHY generation to be used +PLAT_DDR_PHY := PHY_GEN1 + +PHYS_SYS := 64 + +# ddr controller - set to MMDC or NXP +DDRCNTLR := NXP + +# ddr phy - set to NXP or SNPS +DDRPHY := NXP + +# Area of OCRAM reserved by ROM code +NXP_ROM_RSVD := 0x5900 + +# Max Size of CSF header. Required to define BL2 TEXT LIMIT in soc.def +# Input to CST create_hdr_esbc tool +CSF_HDR_SZ := 0x3000 + +# In IMAGE_BL2, compile time flag for handling Cache coherency +# with CAAM for BL2 running from OCRAM +SEC_MEM_NON_COHERENT := yes + +# OCRAM MAP +OCRAM_START_ADDR := 0x10000000 +OCRAM_SIZE := 0x20000 + +# BL2 binary is placed at start of OCRAM. +# Also used by create_pbl.mk. +BL2_BASE := 0x10000000 + +# After BL2 bin, OCRAM is used by ROM Code: +# (OCRAM_START_ADDR + BL2_BIN_SIZE) -> (NXP_ROM_RSVD - 1) + +# After ROM Code, OCRAM is used by CSF header. +# (OCRAM_START_ADDR + BL2_TEXT_LIMIT + NXP_ROM_RSVD) -> (CSF_HDR_SZ - 1) + +# BL2_HDR_LOC has to be (OCRAM_START_ADDR + OCRAM_SIZE - NXP_ROM_RSVD - CSF_HDR_SZ) +# This value should be greater than BL2_TEXT_LIMIT +# Input to CST create_hdr_isbc tool +BL2_HDR_LOC_HDR ?= $(shell echo $$(( $(OCRAM_START_ADDR) + $(OCRAM_SIZE) - $(NXP_ROM_RSVD) - $(CSF_HDR_SZ)))) +# Covert to HEX to be used by create_pbl.mk +BL2_HDR_LOC := $$(echo "obase=16; ${BL2_HDR_LOC_HDR}" | bc) + +# Core Errata +ERRATA_A72_859971 := 1 + +# SoC ERRATAS +ERRATA_SOC_A008850 := 1 +ERRATA_SOC_A010539 := 1 + +# DDR Errata +ERRATA_DDR_A008511 := 1 +ERRATA_DDR_A009803 := 1 +ERRATA_DDR_A009942 := 1 +ERRATA_DDR_A010165 := 1 + +# enable dynamic memory mapping +PLAT_XLAT_TABLES_DYNAMIC := 1 + +# Define Endianness of each module +NXP_GUR_ENDIANNESS := BE +NXP_DDR_ENDIANNESS := BE +NXP_SEC_ENDIANNESS := BE +NXP_SFP_ENDIANNESS := BE +NXP_SNVS_ENDIANNESS := BE +NXP_ESDHC_ENDIANNESS := BE +NXP_QSPI_ENDIANNESS := BE +NXP_FSPI_ENDIANNESS := BE +NXP_SCFG_ENDIANNESS := BE +NXP_GPIO_ENDIANNESS := BE +NXP_IFC_ENDIANNESS := BE + +NXP_SFP_VER := 3_2 + +# OCRAM ECC Enabled +OCRAM_ECC_EN := yes diff --git a/plat/nxp/soc-ls1046a/soc.mk b/plat/nxp/soc-ls1046a/soc.mk new file mode 100644 index 0000000..8207dcd --- /dev/null +++ b/plat/nxp/soc-ls1046a/soc.mk @@ -0,0 +1,114 @@ +# +# Copyright 2018-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SoC-specific build parameters +SOC := ls1046a +PLAT_PATH := plat/nxp +PLAT_COMMON_PATH:= plat/nxp/common +PLAT_DRIVERS_PATH:= drivers/nxp +PLAT_SOC_PATH := ${PLAT_PATH}/soc-${SOC} +BOARD_PATH := ${PLAT_SOC_PATH}/${BOARD} + +# Get SoC-specific defnitions +include ${PLAT_SOC_PATH}/soc.def +include ${PLAT_COMMON_PATH}/plat_make_helper/soc_common_def.mk +include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk + +# For Security Features +DISABLE_FUSE_WRITE := 1 +ifeq (${TRUSTED_BOARD_BOOT}, 1) +$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2)) +SECURE_BOOT := yes +endif +$(eval $(call SET_NXP_MAKE_FLAG,CRYPTO_NEEDED,BL_COMM)) + +# Selecting Drivers for SoC +$(eval $(call SET_NXP_MAKE_FLAG,DCFG_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,CSU_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,TIMER_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,INTERCONNECT_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,GIC_NEEDED,BL31)) +$(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,PMU_NEEDED,BL_COMM)) +$(eval $(call SET_NXP_MAKE_FLAG,DDR_DRIVER_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,TZASC_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,I2C_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2)) + +# Selecting PSCI & SIP_SVC support +$(eval $(call SET_NXP_MAKE_FLAG,PSCI_NEEDED,BL31)) +$(eval $(call SET_NXP_MAKE_FLAG,SIPSVC_NEEDED,BL31)) + +# Source File Addition +PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/include/default\ + -I${BOARD_PATH}\ + -I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\ + -I${PLAT_SOC_PATH}/include\ + -I${PLAT_COMMON_PATH}/soc_errata + +ifeq (${SECURE_BOOT},yes) +include ${PLAT_COMMON_PATH}/tbbr/tbbr.mk +endif + +ifeq ($(WARM_BOOT),yes) +include ${PLAT_COMMON_PATH}/warm_reset/warm_reset.mk +endif + +ifeq (${NXP_NV_SW_MAINT_LAST_EXEC_DATA}, yes) +include ${PLAT_COMMON_PATH}/nv_storage/nv_storage.mk +endif + +ifeq (${PSCI_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/psci/psci.mk +endif + +ifeq (${SIPSVC_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/sip_svc/sipsvc.mk +endif + +# For fuse-fip & fuse-programming +ifeq (${FUSE_PROG}, 1) +include ${PLAT_COMMON_PATH}/fip_handler/fuse_fip/fuse.mk +endif + +ifeq (${IMG_LOADR_NEEDED},yes) +include $(PLAT_COMMON_PATH)/img_loadr/img_loadr.mk +endif + +# Adding source files for the above selected drivers. +include ${PLAT_DRIVERS_PATH}/drivers.mk + +# Adding SoC specific files +include ${PLAT_COMMON_PATH}/soc_errata/errata.mk + +PLAT_INCLUDES += ${NV_STORAGE_INCLUDES}\ + ${WARM_RST_INCLUDES} + +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}.S\ + ${WARM_RST_BL31_SOURCES}\ + ${PSCI_SOURCES}\ + ${SIPSVC_SOURCES}\ + ${PLAT_COMMON_PATH}/$(ARCH)/bl31_data.S + +PLAT_BL_COMMON_SOURCES += ${PLAT_COMMON_PATH}/$(ARCH)/ls_helpers.S\ + ${PLAT_SOC_PATH}/aarch64/${SOC}_helpers.S\ + ${NV_STORAGE_SOURCES}\ + ${WARM_RST_BL_COMM_SOURCES}\ + ${PLAT_SOC_PATH}/soc.c + +ifeq (${TEST_BL31}, 1) +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/bootmain64.S\ + ${PLAT_SOC_PATH}/$(ARCH)/nonboot64.S +endif + +BL2_SOURCES += ${DDR_CNTLR_SOURCES}\ + ${TBBR_SOURCES}\ + ${FUSE_SOURCES} + +# Adding TFA setup files +include ${PLAT_PATH}/common/setup/common.mk diff --git a/plat/nxp/soc-ls1088a/aarch64/ls1088a.S b/plat/nxp/soc-ls1088a/aarch64/ls1088a.S new file mode 100644 index 0000000..0c6b7ea --- /dev/null +++ b/plat/nxp/soc-ls1088a/aarch64/ls1088a.S @@ -0,0 +1,1817 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +.section .text, "ax" + +#include <asm_macros.S> +#include <lib/psci/psci.h> +#include <nxp_timer.h> +#include <plat_gic.h> + +#include "bl31_data.h" +#include "plat_psci.h" +#include "platform_def.h" + +/* + * the BASE address for these offsets is AUX_01_DATA in the + * bootcore's psci data region + */ +#define DEVDISR2_MASK_OFFSET 0x0 /* references AUX_01_DATA */ +#define DEVDISR5_MASK_OFFSET 0x8 /* references AUX_02_DATA */ + +/* + * the BASE address for these offsets is AUX_04_DATA in the + * bootcore's psci data region + */ +#define GICD_BASE_ADDR_OFFSET 0x0 /* references AUX_04_DATA */ +#define GICC_BASE_ADDR_OFFSET 0x8 /* references AUX_05_DATA */ + +#define IPSTPACK_RETRY_CNT 0x10000 +#define DDR_SLEEP_RETRY_CNT 0x10000 +#define CPUACTLR_EL1 S3_1_C15_C2_0 +#define DDR_SDRAM_CFG_2_FRCSR 0x80000000 +#define DDR_SDRAM_CFG_2_OFFSET 0x114 +#define DDR_TIMING_CFG_4_OFFSET 0x160 +#define DDR_CNTRL_BASE_ADDR 0x01080000 + +#define DLL_LOCK_MASK 0x3 +#define DLL_LOCK_VALUE 0x2 + +#define ERROR_DDR_SLEEP -1 +#define ERROR_DDR_WAKE -2 +#define ERROR_NO_QUIESCE -3 + +#define CORE_RESTARTABLE 0 +#define CORE_NOT_RESTARTABLE 1 + +.global soc_init_lowlevel +.global soc_init_percpu + +.global _soc_core_release +.global _soc_core_restart +.global _soc_ck_disabled +.global _soc_sys_reset +.global _soc_sys_off + +.global _soc_core_prep_off +.global _soc_core_entr_off +.global _soc_core_exit_off + +.global _soc_core_prep_stdby +.global _soc_core_entr_stdby +.global _soc_core_exit_stdby +.global _soc_core_prep_pwrdn +.global _soc_core_entr_pwrdn +.global _soc_core_exit_pwrdn +.global _soc_clstr_prep_stdby +.global _soc_clstr_exit_stdby +.global _soc_clstr_prep_pwrdn +.global _soc_clstr_exit_pwrdn +.global _soc_sys_prep_stdby +.global _soc_sys_exit_stdby +.global _soc_sys_prep_pwrdn +.global _soc_sys_pwrdn_wfi +.global _soc_sys_exit_pwrdn + +.global _set_platform_security +.global _soc_set_start_addr + +.equ TZPCDECPROT_0_SET_BASE, 0x02200804 +.equ TZPCDECPROT_1_SET_BASE, 0x02200810 +.equ TZPCDECPROT_2_SET_BASE, 0x0220081C + +.equ TZASC_REGION_ATTRIBUTES_0_0, 0x01100110 + +.equ MPIDR_AFFINITY0_MASK, 0x00FF +.equ MPIDR_AFFINITY1_MASK, 0xFF00 +.equ CPUECTLR_DISABLE_TWALK_PREFETCH, 0x4000000000 +.equ CPUECTLR_INS_PREFETCH_MASK, 0x1800000000 +.equ CPUECTLR_DAT_PREFETCH_MASK, 0x0300000000 +.equ OSDLR_EL1_DLK_LOCK, 0x1 +.equ CNTP_CTL_EL0_EN, 0x1 +.equ CNTP_CTL_EL0_IMASK, 0x2 +/* shifted value for incrementing cluster count in mpidr */ +.equ MPIDR_CLUSTER, 0x100 + +/* + * This function initialize the soc, + * in: none + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11 + */ +func soc_init_lowlevel + /* + * called from C, so save the non-volatile regs + * save these as pairs of registers to maintain the + * required 16-byte alignment on the stack + */ + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x18, x30, [sp, #-16]! + + /* + * make sure the personality has been established by releasing cores + * that are marked "to-be-disabled" from reset + */ + bl release_disabled + + /* set SCRATCHRW7 to 0x0 */ + ldr x0, =DCFG_SCRATCHRW7_OFFSET + mov x1, xzr + bl _write_reg_dcfg + + /* restore the aarch32/64 non-volatile registers */ + ldp x18, x30, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x4, x5, [sp], #16 + ret +endfunc soc_init_lowlevel + +/* + * void soc_init_percpu(void) + * this function performs any soc-specific initialization that is needed on + * a per-core basis + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +func soc_init_percpu + stp x4, x30, [sp, #-16]! + + bl plat_my_core_mask + mov x2, x0 + + /* x2 = core mask */ + + /* see if this core is marked for prefetch disable */ + mov x0, #PREFETCH_DIS_OFFSET + bl _get_global_data + tst x0, x2 + b.eq 1f + bl _disable_ldstr_pfetch_A53 +1: + mov x0, #NXP_PMU_ADDR + bl enable_timer_base_to_cluster + ldp x4, x30, [sp], #16 + ret +endfunc soc_init_percpu + +/* + * this function sets the security mechanisms in the SoC to implement the + * Platform Security Policy + */ +func _set_platform_security + mov x3, x30 + +#if (!SUPPRESS_TZC) + /* initialize the tzpc */ + bl init_tzpc +#endif + +#if (!SUPPRESS_SEC) + /* initialize secmon */ + bl initSecMon +#endif + mov x30, x3 + ret +endfunc _set_platform_security + +/* + * this function writes a 64-bit address to bootlocptrh/l + * in: x0, 64-bit address to write to BOOTLOCPTRL/H + * out: none + * uses x0, x1, x2 + */ +func _soc_set_start_addr + /* get the 64-bit base address of the dcfg block */ + ldr x2, =NXP_DCFG_ADDR + + /* write the 32-bit BOOTLOCPTRL register */ + mov x1, x0 + str w1, [x2, #DCFG_BOOTLOCPTRL_OFFSET] + + /* write the 32-bit BOOTLOCPTRH register */ + lsr x1, x0, #32 + str w1, [x2, #DCFG_BOOTLOCPTRH_OFFSET] + ret +endfunc _soc_set_start_addr + +/* + * part of CPU_ON + * this function releases a secondary core from reset + * in: x0 = core_mask_lsb + * out: none + * uses: x0, x1, x2, x3 + */ +_soc_core_release: + mov x3, x30 + + /* x0 = core mask */ + + ldr x1, =NXP_SEC_REGFILE_ADDR + /* + * write to CORE_HOLD to tell the bootrom that we want this core + * to run + */ + str w0, [x1, #CORE_HOLD_OFFSET] + + /* x0 = core mask */ + + /* read-modify-write BRRL to release core */ + mov x1, #NXP_RESET_ADDR + ldr w2, [x1, #BRR_OFFSET] + orr w2, w2, w0 + str w2, [x1, #BRR_OFFSET] + dsb sy + isb + + /* send event */ + sev + isb + + mov x30, x3 + ret + +/* + * this function determines if a core is disabled via COREDISABLEDSR + * in: w0 = core_mask_lsb + * out: w0 = 0, core not disabled + * w0 != 0, core disabled + * uses x0, x1 + */ +_soc_ck_disabled: + /* get base addr of dcfg block */ + ldr x1, =NXP_DCFG_ADDR + + /* read COREDISABLEDSR */ + ldr w1, [x1, #DCFG_COREDISABLEDSR_OFFSET] + + /* test core bit */ + and w0, w1, w0 + + ret + +/* + * part of CPU_ON + * this function restarts a core shutdown via _soc_core_entr_off + * in: x0 = core mask lsb (of the target cpu) + * out: x0 == 0, on success + * x0 != 0, on failure + * uses x0, x1, x2, x3, x4, x5, x6 + */ +_soc_core_restart: + mov x6, x30 + mov x4, x0 + + /* x4 = core mask lsb */ + + /* pgm GICD_CTLR - enable secure grp0 */ + mov x5, #NXP_GICD_ADDR + ldr w2, [x5, #GICD_CTLR_OFFSET] + orr w2, w2, #GICD_CTLR_EN_GRP_0 + str w2, [x5, #GICD_CTLR_OFFSET] + dsb sy + isb + /* poll on RWP til write completes */ +4: + ldr w2, [x5, #GICD_CTLR_OFFSET] + tst w2, #GICD_CTLR_RWP + b.ne 4b + + /* + * x4 = core mask lsb + * x5 = gicd base addr + */ + + mov x0, x4 + bl get_mpidr_value + + /* + * x0 = mpidr of target core + * x4 = core mask lsb of target core + * x5 = gicd base addr + */ + + /* generate target list bit */ + and x1, x0, #MPIDR_AFFINITY0_MASK + mov x2, #1 + lsl x2, x2, x1 + /* get the affinity1 field */ + and x1, x0, #MPIDR_AFFINITY1_MASK + lsl x1, x1, #8 + orr x2, x2, x1 + /* insert the INTID for SGI15 */ + orr x2, x2, #ICC_SGI0R_EL1_INTID + /* fire the SGI */ + msr ICC_SGI0R_EL1, x2 + dsb sy + isb + + /* load '0' on success */ + mov x0, xzr + + mov x30, x6 + ret + +/* + * part of CPU_OFF + * this function programs SoC & GIC registers in preparation for shutting down + * the core + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7 + */ +_soc_core_prep_off: + mov x8, x30 + mov x7, x0 + + /* x7 = core mask lsb */ + + mrs x1, CPUECTLR_EL1 + /* set smp and disable L2 snoops in cpuectlr */ + orr x1, x1, #CPUECTLR_SMPEN_EN + orr x1, x1, #CPUECTLR_DISABLE_TWALK_PREFETCH + bic x1, x1, #CPUECTLR_INS_PREFETCH_MASK + bic x1, x1, #CPUECTLR_DAT_PREFETCH_MASK + /* set retention control in cpuectlr */ + bic x1, x1, #CPUECTLR_TIMER_MASK + orr x1, x1, #CPUECTLR_TIMER_8TICKS + msr CPUECTLR_EL1, x1 + + /* get redistributor rd base addr for this core */ + mov x0, x7 + bl get_gic_rd_base + mov x6, x0 + + /* get redistributor sgi base addr for this core */ + mov x0, x7 + bl get_gic_sgi_base + mov x5, x0 + + /* x5 = gicr sgi base addr + * x6 = gicr rd base addr + * x7 = core mask lsb + */ + + /* disable SGI 15 at redistributor - GICR_ICENABLER0 */ + mov w3, #GICR_ICENABLER0_SGI15 + str w3, [x5, #GICR_ICENABLER0_OFFSET] +2: + /* poll on rwp bit in GICR_CTLR */ + ldr w4, [x6, #GICR_CTLR_OFFSET] + tst w4, #GICR_CTLR_RWP + b.ne 2b + + /* disable GRP1 interrupts at cpu interface */ + msr ICC_IGRPEN1_EL3, xzr + + /* disable GRP0 ints at cpu interface */ + msr ICC_IGRPEN0_EL1, xzr + + /* program the redistributor - poll on GICR_CTLR.RWP as needed */ + + /* define SGI 15 as Grp0 - GICR_IGROUPR0 */ + ldr w4, [x5, #GICR_IGROUPR0_OFFSET] + bic w4, w4, #GICR_IGROUPR0_SGI15 + str w4, [x5, #GICR_IGROUPR0_OFFSET] + + /* define SGI 15 as Grp0 - GICR_IGRPMODR0 */ + ldr w3, [x5, #GICR_IGRPMODR0_OFFSET] + bic w3, w3, #GICR_IGRPMODR0_SGI15 + str w3, [x5, #GICR_IGRPMODR0_OFFSET] + + /* set priority of SGI 15 to highest (0x0) - GICR_IPRIORITYR3 */ + ldr w4, [x5, #GICR_IPRIORITYR3_OFFSET] + bic w4, w4, #GICR_IPRIORITYR3_SGI15_MASK + str w4, [x5, #GICR_IPRIORITYR3_OFFSET] + + /* enable SGI 15 at redistributor - GICR_ISENABLER0 */ + mov w3, #GICR_ISENABLER0_SGI15 + str w3, [x5, #GICR_ISENABLER0_OFFSET] + dsb sy + isb +3: + /* poll on rwp bit in GICR_CTLR */ + ldr w4, [x6, #GICR_CTLR_OFFSET] + tst w4, #GICR_CTLR_RWP + b.ne 3b + + /* quiesce the debug interfaces */ + mrs x3, osdlr_el1 + orr x3, x3, #OSDLR_EL1_DLK_LOCK + msr osdlr_el1, x3 + isb + + /* enable grp0 ints */ + mov x3, #ICC_IGRPEN0_EL1_EN + msr ICC_IGRPEN0_EL1, x3 + + /* + * x5 = gicr sgi base addr + * x6 = gicr rd base addr + * x7 = core mask lsb + */ + + /* clear any pending interrupts */ + mvn w1, wzr + str w1, [x5, #GICR_ICPENDR0_OFFSET] + + /* make sure system counter is enabled */ + ldr x3, =NXP_TIMER_ADDR + ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 4f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] +4: + /* enable the core timer and mask timer interrupt */ + mov x1, #CNTP_CTL_EL0_EN + orr x1, x1, #CNTP_CTL_EL0_IMASK + msr cntp_ctl_el0, x1 + + mov x30, x8 + ret + +/* + * part of CPU_OFF + * this function performs the final steps to shutdown the core + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5 + */ +_soc_core_entr_off: + mov x5, x30 + mov x4, x0 + + /* x4 = core mask */ +1: + /* enter low-power state by executing wfi */ + wfi + + /* see if SGI15 woke us up */ + mrs x2, ICC_IAR0_EL1 + mov x3, #ICC_IAR0_EL1_SGI15 + cmp x2, x3 + b.ne 2f + + /* deactivate the int */ + msr ICC_EOIR0_EL1, x2 + + /* x4 = core mask */ +2: + /* check if core has been turned on */ + mov x0, x4 + bl _getCoreState + + /* x0 = core state */ + + cmp x0, #CORE_WAKEUP + b.ne 1b + + /* if we get here, then we have exited the wfi */ + + mov x30, x5 + ret + +/* + * part of CPU_OFF + * this function starts the process of starting a core back up + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3, x4, x5, x6 + */ +_soc_core_exit_off: + mov x6, x30 + mov x5, x0 + + /* disable forwarding of GRP0 ints at cpu interface */ + msr ICC_IGRPEN0_EL1, xzr + + /* get redistributor sgi base addr for this core */ + mov x0, x5 + bl get_gic_sgi_base + mov x4, x0 + + /* + * x4 = gicr sgi base addr + * x5 = core mask + */ + + /* disable SGI 15 at redistributor - GICR_ICENABLER0 */ + mov w1, #GICR_ICENABLER0_SGI15 + str w1, [x4, #GICR_ICENABLER0_OFFSET] + + /* get redistributor rd base addr for this core */ + mov x0, x5 + bl get_gic_rd_base + mov x4, x0 + + /* x4 = gicr rd base addr */ +2: + /* poll on rwp bit in GICR_CTLR */ + ldr w2, [x4, #GICR_CTLR_OFFSET] + tst w2, #GICR_CTLR_RWP + b.ne 2b + + /* x4 = gicr rd base addr */ + + /* unlock the debug interfaces */ + mrs x3, osdlr_el1 + bic x3, x3, #OSDLR_EL1_DLK_LOCK + msr osdlr_el1, x3 + isb + + dsb sy + isb + mov x30, x6 + ret + +/* + * this function requests a reset of the entire SOC + * in: none + * out: none + * uses: x0, x1, x2, x3, x4, x5, x6 + */ +_soc_sys_reset: + mov x3, x30 + + /* make sure the mask is cleared in the reset request mask register */ + mov x0, #RST_RSTRQMR1_OFFSET + mov w1, wzr + bl _write_reg_reset + + /* set the reset request */ + mov x4, #RST_RSTCR_OFFSET + mov x0, x4 + mov w1, #RSTCR_RESET_REQ + bl _write_reg_reset + + /* x4 = RST_RSTCR_OFFSET */ + + /* + * just in case this address range is mapped as cacheable, + * flush the write out of the dcaches + */ + mov x2, #NXP_RESET_ADDR + add x2, x2, x4 + dc cvac, x2 + dsb st + isb + + /* this function does not return */ + b . + +/* + * this function turns off the SoC + * Note: this function is not intended to return, and the only allowable + * recovery is POR + * in: none + * out: none + * uses x0, x1, x2, x3 + */ +_soc_sys_off: + /* + * A-009810: LPM20 entry sequence might cause + * spurious timeout reset request + * workaround: MASK RESET REQ RPTOE + */ + ldr x0, =NXP_RESET_ADDR + ldr w1, [x0, #RST_RSTRQMR1_OFFSET] + orr w1, w1, #RSTRQMR_RPTOE_MASK + str w1, [x0, #RST_RSTRQMR1_OFFSET] + + /* disable SEC, QBman spi and qspi */ + ldr x2, =NXP_DCFG_ADDR + ldr x0, =DCFG_DEVDISR1_OFFSET + ldr w1, =DCFG_DEVDISR1_SEC + str w1, [x2, x0] + ldr x0, =DCFG_DEVDISR3_OFFSET + ldr w1, =DCFG_DEVDISR3_QBMAIN + str w1, [x2, x0] + ldr x0, =DCFG_DEVDISR4_OFFSET + ldr w1, =DCFG_DEVDISR4_SPI_QSPI + str w1, [x2, x0] + + /* set TPMWAKEMR0 */ + ldr x0, =TPMWAKEMR0_ADDR + mov w1, #0x1 + str w1, [x0] + + /* disable icache, dcache, mmu @ EL1 */ + mov x1, #SCTLR_I_C_M_MASK + mrs x0, sctlr_el1 + bic x0, x0, x1 + msr sctlr_el1, x0 + + /* disable L2 prefetches */ + mrs x0, CPUECTLR_EL1 + orr x0, x0, #CPUECTLR_SMPEN_EN + orr x0, x0, #CPUECTLR_TIMER_8TICKS + msr CPUECTLR_EL1, x0 + dsb sy + isb + + /* disable CCN snoop domain */ + ldr x0, =NXP_CCI_ADDR + mov w1, #0x1 + str w1, [x0] + + mov x2, #DAIF_SET_MASK + + mrs x1, spsr_el1 + orr x1, x1, x2 + msr spsr_el1, x1 + + mrs x1, spsr_el2 + orr x1, x1, x2 + msr spsr_el2, x1 + + bl get_pmu_idle_cluster_mask + mov x3, #NXP_PMU_ADDR + + /* x3 = pmu base addr */ + + /* idle the ACP interfaces */ + str w0, [x3, #PMU_CLAINACTSETR_OFFSET] + + /* force the debug interface to be quiescent */ + mrs x0, osdlr_el1 + orr x0, x0, #0x1 + msr osdlr_el1, x0 + + bl get_pmu_flush_cluster_mask + /* x3 = pmu base addr */ + mov x3, #NXP_PMU_ADDR + + /* clear flush request and status */ + ldr x2, =PMU_CLSL2FLUSHCLRR_OFFSET + str w0, [x3, x2] + + /* close the Skyros master port */ + ldr x2, =PMU_CLSINACTSETR_OFFSET + str w0, [x3, x2] + + /* request lpm20 */ + ldr x0, =PMU_POWMGTCSR_OFFSET + ldr w1, =PMU_POWMGTCSR_VAL + str w1, [x3, x0] + + /* this function does not return */ +1: + wfi + b 1b + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_core_prep_stdby: + /* clear CPUECTLR_EL1[2:0] */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CPUECTLR_EL1, x1 + + ret + +/* + * part of CPU_SUSPEND + * this function puts the calling core into standby state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +_soc_core_entr_stdby: + /* X0 = core mask lsb */ + dsb sy + isb + wfi + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_core_exit_stdby: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3 + */ +_soc_core_prep_pwrdn: + /* make sure system counter is enabled */ + ldr x3, =NXP_TIMER_ADDR + ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 1f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] +1: + /* + * enable dynamic retention control (CPUECTLR[2:0]) + * set the SMPEN bit (CPUECTLR[6]) + */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_RET_MASK + orr x1, x1, #CPUECTLR_TIMER_8TICKS + orr x1, x1, #CPUECTLR_SMPEN_EN + msr CPUECTLR_EL1, x1 + + isb + ret + +/* + * part of CPU_SUSPEND + * this function puts the calling core into a power-down state + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +_soc_core_entr_pwrdn: + /* X0 = core mask lsb */ + dsb sy + isb + wfi + + ret + +/* + * part of CPU_SUSPEND + * this function cleans up after a core exits power-down + * in: x0 = core mask lsb + * out: none + * uses + */ +_soc_core_exit_pwrdn: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_clstr_prep_stdby: + /* clear CPUECTLR_EL1[2:0] */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CPUECTLR_EL1, x1 + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_clstr_exit_stdby: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1, x2, x3 + */ +_soc_clstr_prep_pwrdn: + /* make sure system counter is enabled */ + ldr x3, =NXP_TIMER_ADDR + ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] + tst w0, #SYS_COUNTER_CNTCR_EN + b.ne 1f + orr w0, w0, #SYS_COUNTER_CNTCR_EN + str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET] +1: + /* + * enable dynamic retention control (CPUECTLR[2:0]) + * set the SMPEN bit (CPUECTLR[6]) + */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_RET_MASK + orr x1, x1, #CPUECTLR_TIMER_8TICKS + orr x1, x1, #CPUECTLR_SMPEN_EN + msr CPUECTLR_EL1, x1 + + isb + ret + +/* + * part of CPU_SUSPEND + * this function cleans up after a core exits power-down + * in: x0 = core mask lsb + * out: none + * uses + */ +_soc_clstr_exit_pwrdn: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to standby + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_sys_prep_stdby: + /* clear CPUECTLR_EL1[2:0] */ + mrs x1, CPUECTLR_EL1 + bic x1, x1, #CPUECTLR_TIMER_MASK + msr CPUECTLR_EL1, x1 + + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after standby state + * in: x0 = core mask lsb + * out: none + * uses none + */ +_soc_sys_exit_stdby: + ret + +/* + * part of CPU_SUSPEND + * this function performs SoC-specific programming prior to + * suspend-to-power-down + * in: x0 = core mask lsb + * out: none + * uses x0 + */ +_soc_sys_prep_pwrdn: + /* set retention control */ + mrs x0, CPUECTLR_EL1 + bic x0, x0, #CPUECTLR_TIMER_MASK + orr x0, x0, #CPUECTLR_TIMER_8TICKS + orr x0, x0, #CPUECTLR_SMPEN_EN + msr CPUECTLR_EL1, x0 + dsb sy + isb + + ret + +/* + * part of CPU_SUSPEND + * this function puts the calling core, and potentially the soc, into a + * low-power state + * in: x0 = core mask lsb + * out: x0 = 0, success + * x0 < 0, failure + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8 + */ +_soc_sys_pwrdn_wfi: + /* Save LR to stack */ + stp x18, x30, [sp, #-16]! + + /* Poll PCPW20SR for all secondary cores to be placed in PW20 */ + bl get_tot_num_cores + mov x3, #0x1 + lsl x3, x3, x0 + sub x3, x3, #2 +1: + mov x0, #NXP_PMU_ADDR + ldr w1, [x0, #PMU_PCPW20SR_OFFSET] + cmp w1, w3 + b.ne 1b + + /* backup EPU registers to stack */ + mov x3, #NXP_PMU_ADDR + ldr x2, =NXP_EPU_ADDR + ldr w4, [x2, #EPU_EPIMCR10_OFFSET] + ldr w5, [x2, #EPU_EPCCR10_OFFSET] + ldr w6, [x2, #EPU_EPCTR10_OFFSET] + ldr w7, [x2, #EPU_EPGCR_OFFSET] + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + + /* + * x2 = epu base addr + * x3 = pmu base addr + */ + + /* set up EPU event to receive the wake signal from PMU */ + mov w4, #EPU_EPIMCR10_VAL + mov w5, #EPU_EPCCR10_VAL + mov w6, #EPU_EPCTR10_VAL + mov w7, #EPU_EPGCR_VAL + str w4, [x2, #EPU_EPIMCR10_OFFSET] + str w5, [x2, #EPU_EPCCR10_OFFSET] + str w6, [x2, #EPU_EPCTR10_OFFSET] + str w7, [x2, #EPU_EPGCR_OFFSET] + + /* + * A-010194: There is logic problem + * in the path of GIC-to-PMU to issue + * wake request to core0 + * Workaround: Re-target the wakeup interrupts + * to a core other than the last active core0 + */ + ldr x2, =NXP_GICD_ADDR + + /* backup flextimer/mmc/usb interrupt router */ + ldr x0, =GICD_IROUTER60_OFFSET + ldr x1, =GICD_IROUTER76_OFFSET + ldr w4, [x2, x0] + ldr w5, [x2, x1] + ldr x0, =GICD_IROUTER112_OFFSET + ldr x1, =GICD_IROUTER113_OFFSET + ldr w6, [x2, x0] + ldr w7, [x2, x1] + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + + /* + * x2 = gicd base addr + * x0 = GICD_IROUTER112_OFFSET + * x1 = GICD_IROUTER113_OFFSET + */ + + /* re-route interrupt to cluster 1 */ + ldr w4, =GICD_IROUTER_VALUE + str w4, [x2, x0] + str w4, [x2, x1] + ldr x0, =GICD_IROUTER60_OFFSET + ldr x1, =GICD_IROUTER76_OFFSET + str w4, [x2, x0] + str w4, [x2, x1] + dsb sy + isb + + /* backup flextimer/mmc/usb interrupt enabler */ + ldr x0, =GICD_ISENABLER_1 + ldr w4, [x2, x0] + ldr x1, =GICD_ISENABLER_2 + ldr w5, [x2, x1] + stp x4, x5, [sp, #-16]! + + ldr x0, =GICD_ISENABLER_3 + ldr w4, [x2, x0] + ldr x1, =GICD_ICENABLER_1 + ldr w5, [x2, x1] + stp x4, x5, [sp, #-16]! + + ldr x0, =GICD_ICENABLER_2 + ldr w4, [x2, x0] + ldr x1, =GICD_ICENABLER_3 + ldr w5, [x2, x1] + stp x4, x5, [sp, #-16]! + + /* enable related interrupt routing */ + ldr w4, =GICD_ISENABLER_1_VALUE + ldr x0, =GICD_ISENABLER_1 + str w4, [x2, x0] + dsb sy + isb + + ldr w4, =GICD_ISENABLER_2_VALUE + ldr x0, =GICD_ISENABLER_2 + str w4, [x2, x0] + dsb sy + isb + + ldr w4, =GICD_ISENABLER_3_VALUE + ldr x0, =GICD_ISENABLER_3 + str w4, [x2, x0] + dsb sy + isb + + /* set POWMGTDCR [STP_PV_EN] = 1 */ + ldr x2, =NXP_POWMGTDCR + ldr w4, =0x01 + str w4, [x2] + + /* program IPSTPCR for override stop request (except DDR) */ + mov x3, #NXP_PMU_ADDR + + /* build an override mask for IPSTPCR4/IPSTPACK4/DEVDISR5 */ + ldr x2, =PMU_IPPDEXPCR4_OFFSET + ldr w7, [x3, x2] + + mov x5, xzr + ldr x6, =IPPDEXPCR4_MASK + and x6, x6, x7 + cbz x6, 1f + + /* + * x5 = override mask + * x6 = IPPDEXPCR bits for DEVDISR5 + * x7 = IPPDEXPCR + */ + + /* get the overrides */ + orr x4, x5, #DEVDISR5_FLX_TMR + tst x6, #IPPDEXPCR_FLX_TMR + csel x5, x5, x4, EQ +1: + /* store the DEVDISR5 override mask */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + str w5, [x2, #DEVDISR5_MASK_OFFSET] + + mov x3, #NXP_PMU_ADDR + + /* write IPSTPCR0 - no overrides */ + ldr x2, =PMU_IPSTPCR0_OFFSET + ldr w5, =IPSTPCR0_VALUE + str w5, [x3, x2] + + /* write IPSTPCR1 - no overrides */ + ldr x2, =PMU_IPSTPCR1_OFFSET + ldr w5, =IPSTPCR1_VALUE + str w5, [x3, x2] + + /* write IPSTPCR2 - no overrides */ + ldr x2, =PMU_IPSTPCR2_OFFSET + ldr w5, =IPSTPCR2_VALUE + str w5, [x3, x2] + + /* write IPSTPCR3 - no overrides */ + ldr x2, =PMU_IPSTPCR3_OFFSET + ldr w5, =IPSTPCR3_VALUE + str w5, [x3, x2] + + /* write IPSTPCR4 - overrides possible */ + ldr x2, =BC_PSCI_BASE + add x2, x2, #AUX_01_DATA + ldr w6, [x2, #DEVDISR5_MASK_OFFSET] + ldr x2, =PMU_IPSTPCR4_OFFSET + ldr w5, =IPSTPCR4_VALUE + bic x5, x5, x6 + str w5, [x3, x2] + + /* write IPSTPCR5 - no overrides */ + ldr x2, =PMU_IPSTPCR5_OFFSET + ldr w5, =IPSTPCR5_VALUE + str w5, [x3, x2] + + /* write IPSTPCR6 - no overrides */ + ldr x2, =PMU_IPSTPCR6_OFFSET + ldr w5, =IPSTPCR6_VALUE + str w5, [x3, x2] + + /* poll IPSTPACK for IP stop acknowledgment (except DDR) */ + mov x3, #NXP_PMU_ADDR + + /* poll on IPSTPACK0 */ + ldr x2, =PMU_IPSTPACK0_OFFSET + ldr x4, =IPSTPCR0_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +3: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 14f + sub x7, x7, #1 + cbnz x7, 3b + +14: + /* poll on IPSTPACK1 */ + ldr x2, =PMU_IPSTPACK1_OFFSET + ldr x4, =IPSTPCR1_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +4: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 15f + sub x7, x7, #1 + cbnz x7, 4b + +15: + /* poll on IPSTPACK2 */ + ldr x2, =PMU_IPSTPACK2_OFFSET + ldr x4, =IPSTPCR2_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +5: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 16f + sub x7, x7, #1 + cbnz x7, 5b + +16: + /* poll on IPSTPACK3 */ + ldr x2, =PMU_IPSTPACK3_OFFSET + ldr x4, =IPSTPCR3_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +6: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 17f + sub x7, x7, #1 + cbnz x7, 6b + +17: + /* poll on IPSTPACK4 */ + ldr x2, =PMU_IPSTPACK4_OFFSET + ldr x4, =IPSTPCR4_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +7: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 18f + sub x7, x7, #1 + cbnz x7, 7b + +18: + /* poll on IPSTPACK5 */ + ldr x2, =PMU_IPSTPACK5_OFFSET + ldr x4, =IPSTPCR5_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +8: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 19f + sub x7, x7, #1 + cbnz x7, 8b + +19: + /* poll on IPSTPACK6 */ + ldr x2, =PMU_IPSTPACK6_OFFSET + ldr x4, =IPSTPCR6_VALUE + ldr x7, =IPSTPACK_RETRY_CNT +9: + ldr w0, [x3, x2] + cmp x0, x4 + b.eq 20f + sub x7, x7, #1 + cbnz x7, 9b + +20: + /* save current DEVDISR states to DDR. */ + ldr x2, =NXP_DCFG_ADDR + + /* save DEVDISR1 and load new value */ + ldr x0, =DCFG_DEVDISR1_OFFSET + ldr w1, [x2, x0] + mov w13, w1 + ldr x1, =DEVDISR1_VALUE + str w1, [x2, x0] + /* save DEVDISR2 and load new value */ + ldr x0, =DCFG_DEVDISR2_OFFSET + ldr w1, [x2, x0] + mov w14, w1 + ldr x1, =DEVDISR2_VALUE + str w1, [x2, x0] + + /* x6 = DEVDISR5 override mask */ + + /* save DEVDISR3 and load new value */ + ldr x0, =DCFG_DEVDISR3_OFFSET + ldr w1, [x2, x0] + mov w15, w1 + ldr x1, =DEVDISR3_VALUE + str w1, [x2, x0] + + /* save DEVDISR4 and load new value */ + ldr x0, =DCFG_DEVDISR4_OFFSET + ldr w1, [x2, x0] + mov w16, w1 + /* not stop uart print */ + ldr x1, =0x0000332 + str w1, [x2, x0] + + /* save DEVDISR5 and load new value */ + ldr x0, =DCFG_DEVDISR5_OFFSET + ldr w1, [x2, x0] + mov w17, w1 + /* Enable this wakeup will fail, should enable OCRAM */ + ldr x1, =0x00102300 + str w1, [x2, x0] + + /* save DEVDISR6 and load new value */ + ldr x0, =DCFG_DEVDISR6_OFFSET + ldr w1, [x2, x0] + mov w18, w1 + ldr x1, =DEVDISR6_VALUE + str w1, [x2, x0] + + /* + * w13 = DEVDISR1 saved value + * w14 = DEVDISR2 saved value + * w15 = DEVDISR3 saved value + * w16 = DEVDISR4 saved value + * w17 = DEVDISR5 saved value + * w18 = DEVDISR6 saved value + */ + /* + * A-009810: LPM20 entry sequence might cause + * spurious timeout reset request + * workaround: MASK RESET REQ RPTOE + */ + ldr x0, =NXP_RESET_ADDR + ldr w1, =RSTRQMR_RPTOE_MASK + str w1, [x0, #RST_RSTRQMR1_OFFSET] + + /* disable SEC, QBman spi and qspi */ + ldr x2, =NXP_DCFG_ADDR + ldr x0, =DCFG_DEVDISR1_OFFSET + ldr w1, =DCFG_DEVDISR1_SEC + str w1, [x2, x0] + ldr x0, =DCFG_DEVDISR3_OFFSET + ldr w1, =DCFG_DEVDISR3_QBMAIN + str w1, [x2, x0] + ldr x0, =DCFG_DEVDISR4_OFFSET + ldr w1, =DCFG_DEVDISR4_SPI_QSPI + str w1, [x2, x0] + + /* + * write the GICR_WAKER.ProcessorSleep bits to 1 + * enable the WakeRequest signal + * x3 is cpu mask starting from cpu7 + */ + bl get_tot_num_cores + sub x0, x0, #1 + mov x3, #0x1 + lsl x3, x3, x0 +2: + mov x0, x3 + bl get_gic_rd_base + ldr w1, [x0, #GICR_WAKER_OFFSET] + orr w1, w1, #GICR_WAKER_SLEEP_BIT + str w1, [x0, #GICR_WAKER_OFFSET] +1: + ldr w1, [x0, #GICR_WAKER_OFFSET] + cmp w1, #GICR_WAKER_ASLEEP + b.ne 1b + + lsr x3, x3, #1 + cbnz x3, 2b + + /* x3 = pmu base addr */ + + /* perform Icache Warming Sequence */ + ldr x5, =IPSTPCR4_VALUE + mov x6, DDR_CNTRL_BASE_ADDR + mov x7, #NXP_PMU_ADDR + mov x8, #NXP_DCFG_ADDR + mov x10, #PMU_IPSTPCR4_OFFSET + mov x11, #PMU_IPSTPACK4_OFFSET + mov x12, #PMU_IPSTPCR3_OFFSET + mov x18, #PMU_IPSTPCR2_OFFSET + mov x19, #PMU_IPSTPCR1_OFFSET + mov x21, #PMU_IPSTPCR0_OFFSET + ldr x22, =DCFG_DEVDISR5_OFFSET + ldr x23, =NXP_EPU_ADDR + mov x9, #CORE_RESTARTABLE + bl final_pwrdown + + /* + * disable the WakeRequest signal on cpu 0-7 + * x3 is cpu mask starting from cpu7 + */ + bl get_tot_num_cores + sub x0, x0, #1 + mov x3, #0x1 + lsl x3, x3, x0 +2: + mov x0, x3 + bl get_gic_rd_base + ldr w1, [x0, #GICR_WAKER_OFFSET] + bic w1, w1, #GICR_WAKER_SLEEP_BIT + str w1, [x0, #GICR_WAKER_OFFSET] +1: + ldr w1, [x0, #GICR_WAKER_OFFSET] + cbnz w1, 1b + + lsr x3, x3, #1 + cbnz x3, 2b + + /* set SGI for secondary core wakeup */ + ldr x0, =0x1000002 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x2000004 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x3000008 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x4010001 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x5010002 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x6010004 + msr S3_0_C12_C11_7, x0 + isb + ldr x0, =0x7010008 + msr S3_0_C12_C11_7, x0 + + /* enable SEC, QBman spi and qspi */ + ldr x2, =NXP_DCFG_ADDR + str wzr, [x2, #DCFG_DEVDISR1_OFFSET] + str wzr, [x2, #DCFG_DEVDISR3_OFFSET] + str wzr, [x2, #DCFG_DEVDISR4_OFFSET] + + /* clear POWMGTDCR [STP_PV_EN] */ + ldr x2, =NXP_POWMGTDCR + ldr w4, [x2] + bic w4, w4, #0x01 + str w4, [x2] + + /* restore flextimer/mmc/usb interrupt enabler */ + ldr x3, =NXP_GICD_ADDR + ldp x0, x2, [sp], #16 + ldr x1, =GICD_ICENABLER_2 + mvn w0, w0 + str w0, [x3, x1] + ldr x1, =GICD_ICENABLER_3 + mvn w2, w2 + str w2, [x3, x1] + + ldp x0, x2, [sp], #16 + ldr x1, =GICD_ISENABLER_3 + str w0, [x3, x1] + ldr x1, =GICD_ICENABLER_1 + mvn w2, w2 + str w0, [x3, x1] + + ldp x0, x2, [sp], #16 + ldr x1, =GICD_ISENABLER_1 + str w0, [x3, x1] + ldr x1, =GICD_ISENABLER_2 + str w0, [x3, x1] + + /* restore flextimer/mmc/usb interrupt router */ + ldr x3, =NXP_GICD_ADDR + ldp x0, x2, [sp], #16 + ldr x1, =GICD_IROUTER113_OFFSET + str w2, [x3, x1] + ldr x1, =GICD_IROUTER112_OFFSET + str w0, [x3, x1] + ldp x0, x2, [sp], #16 + ldr x1, =GICD_IROUTER76_OFFSET + str w2, [x3, x1] + ldr x1, =GICD_IROUTER60_OFFSET + str w0, [x3, x1] + + /* restore EPU registers */ + ldr x3, =NXP_EPU_ADDR + ldp x0, x2, [sp], #16 + str w2, [x3, #EPU_EPGCR_OFFSET] + str w0, [x3, #EPU_EPCTR10_OFFSET] + ldp x2, x1, [sp], #16 + str w1, [x3, #EPU_EPCCR10_OFFSET] + str w2, [x3, #EPU_EPIMCR10_OFFSET] + + isb + /* Restor LR */ + ldp x18, x30, [sp], #16 + ret + +/* + * part of CPU_SUSPEND + * this function performs any SoC-specific cleanup after power-down + * in: x0 = core mask lsb + * out: none + * uses x0, x1 + */ +_soc_sys_exit_pwrdn: + mrs x1, SCTLR_EL1 + orr x1, x1, #SCTLR_I_MASK + msr SCTLR_EL1, x1 + isb + ret + +/* + * this function checks to see if cores which are to be disabled have been + * released from reset - if not, it releases them + * in: none + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8 + */ +release_disabled: + mov x8, x30 + + /* read COREDISABLESR */ + mov x0, #NXP_DCFG_ADDR + ldr w4, [x0, #DCFG_COREDISABLEDSR_OFFSET] + + /* get the number of cpus on this device */ + mov x6, #PLATFORM_CORE_COUNT + + mov x0, #NXP_RESET_ADDR + ldr w5, [x0, #BRR_OFFSET] + + /* load the core mask for the first core */ + mov x7, #1 + + /* + * x4 = COREDISABLESR + * x5 = BRR + * x6 = loop count + * x7 = core mask bit + */ +2: + /* check if the core is to be disabled */ + tst x4, x7 + b.eq 1f + + /* see if disabled cores have already been released from reset */ + tst x5, x7 + b.ne 1f + + /* if core has not been released, then release it (0-3) */ + mov x0, x7 + bl _soc_core_release + + /* record the core state in the data area (0-3) */ + mov x0, x7 + mov x1, #CORE_DISABLED + bl _setCoreState + +1: + /* decrement the counter */ + subs x6, x6, #1 + b.le 3f + + /* shift the core mask to the next core */ + lsl x7, x7, #1 + /* continue */ + b 2b +3: + mov x30, x8 + ret + +/* + * write a register in the DCFG block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2 + */ +_write_reg_dcfg: + ldr x2, =NXP_DCFG_ADDR + str w1, [x2, x0] + ret + +/* + * read a register in the DCFG block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1 + */ +_read_reg_dcfg: + ldr x1, =NXP_DCFG_ADDR + ldr w0, [x1, x0] + ret + +/* + * this function sets up the TrustZone Address Space Controller (TZASC) + * in: none + * out: none + * uses x0, x1 + */ +init_tzpc: + /* + * set Non Secure access for all devices protected via TZPC + * decode Protection-0 Set Reg + */ + ldr x1, =TZPCDECPROT_0_SET_BASE + /* set decode region to NS, Bits[7:0] */ + mov w0, #0xFF + str w0, [x1] + + /* decode Protection-1 Set Reg */ + ldr x1, =TZPCDECPROT_1_SET_BASE + /* set decode region to NS, Bits[7:0] */ + mov w0, #0xFF + str w0, [x1] + + /* decode Protection-2 Set Reg */ + ldr x1, =TZPCDECPROT_2_SET_BASE + /* set decode region to NS, Bits[7:0] */ + mov w0, #0xFF + str w0, [x1] + + /* + * entire SRAM as NS + * secure RAM region size Reg + */ + ldr x1, =NXP_OCRAM_TZPC_ADDR + /* 0x00000000 = no secure region */ + mov w0, #0x00000000 + str w0, [x1] + + ret + +/* this function performs initialization on SecMon for boot services */ +initSecMon: + /* read the register hpcomr */ + ldr x1, =NXP_SNVS_ADDR + ldr w0, [x1, #SECMON_HPCOMR_OFFSET] + /* turn off secure access for the privileged registers */ + orr w0, w0, #SECMON_HPCOMR_NPSWAEN + /* write back */ + str w0, [x1, #SECMON_HPCOMR_OFFSET] + + ret + +/* + * this function returns the redistributor base address for the core specified + * in x1 + * in: x0 - core mask lsb of specified core + * out: x0 = redistributor rd base address for specified core + * uses x0, x1, x2 + */ +get_gic_rd_base: + /* get the 0-based core number */ + clz w1, w0 + mov w2, #0x20 + sub w2, w2, w1 + sub w2, w2, #1 + + /* x2 = core number / loop counter */ + + ldr x0, =NXP_GICR_ADDR + mov x1, #GIC_RD_OFFSET +2: + cbz x2, 1f + add x0, x0, x1 + sub x2, x2, #1 + b 2b +1: + ret + +/* + * this function returns the redistributor base address for the core specified + * in x1 + * in: x0 - core mask lsb of specified core + * out: x0 = redistributor sgi base address for specified core + * uses x0, x1, x2 + */ +get_gic_sgi_base: + /* get the 0-based core number */ + clz w1, w0 + mov w2, #0x20 + sub w2, w2, w1 + sub w2, w2, #1 + + /* x2 = core number / loop counter */ + + ldr x0, =NXP_GICR_SGI_ADDR + mov x1, #GIC_SGI_OFFSET +2: + cbz x2, 1f + add x0, x0, x1 + sub x2, x2, #1 + b 2b +1: + ret + +/* + * this function returns an mpidr value for a core, given a core_mask_lsb + * in: x0 = core mask lsb + * out: x0 = affinity2:affinity1:affinity0, where affinity is 8-bits + * uses x0, x1 + */ +get_mpidr_value: + /* convert a core mask to an SoC core number */ + clz w0, w0 + mov w1, #31 + sub w0, w1, w0 + + /* w0 = SoC core number */ + + mov w1, wzr +2: + cmp w0, #CORES_PER_CLUSTER + b.lt 1f + sub w0, w0, #CORES_PER_CLUSTER + add w1, w1, #MPIDR_CLUSTER + b 2b + + /* insert the mpidr core number */ +1: + orr w0, w1, w0 + ret + +/* + * write a register in the RESET block + * in: x0 = offset + * in: w1 = value to write + * uses x0, x1, x2 + */ +_write_reg_reset: + ldr x2, =NXP_RESET_ADDR + str w1, [x2, x0] + ret + +/* + * read a register in the RESET block + * in: x0 = offset + * out: w0 = value read + * uses x0, x1 + */ +_read_reg_reset: + ldr x1, =NXP_RESET_ADDR + ldr w0, [x1, x0] + ret + +/* + * this function will pwrdown ddr and the final core - it will do this + * by loading itself into the icache and then executing from there + * in: x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK) + * x6 = DDR_CNTRL_BASE_ADDR + * x7 = NXP_PMU_ADDR + * x8 = NXP_DCFG_ADDR + * x9 = 0, restartable + * = 1, non-restartable + * x10 = PMU_IPSTPCR4_OFFSET + * x11 = PMU_IPSTPACK4_OFFSET + * x12 = PMU_IPSTPCR3_OFFSET + * x18 = PMU_IPSTPCR2_OFFSET + * x19 = PMU_IPSTPCR1_OFFSET + * x21 = PMU_IPSTPCR0_OFFSET + * w13 = DEVDISR1 saved value + * w14 = DEVDISR2 saved value + * w15 = DEVDISR3 saved value + * w16 = DEVDISR4 saved value + * w17 = DEVDISR5 saved value + * x22 = DCFG_DEVDISR5_OFFSET + * x23 = NXP_EPU_ADDR + * out: none + * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x13, x14, x15, x16, x17 + * x10, x11, x12, x18, x19, x21, x22, x23 + */ + +final_pwrdown: + /* delay */ + mov w4, #0xffffff +554: + sub w4, w4, #1 + cmp w4, #0 + b.ge 554b + + mov x0, xzr + b touch_line_0 + +/* 4Kb aligned */ +.align 12 +start_line_0: + mov x0, #1 + /* put ddr in self refresh - start */ + mov x2, #DDR_SDRAM_CFG_2_FRCSR + ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + orr w3, w3, w2 + /* put ddr in self refresh - end */ + str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + nop + nop +touch_line_0: + cbz x0, touch_line_1 + +start_line_1: + /* quiesce ddr clocks - start */ + orr w3, w5, #DCFG_DEVDISR5_MEM + mov w4, w3 + /* quiesce ddr clocks - end */ + str w4, [x7, x10] + mov w3, #DCFG_DEVDISR5_MEM + /* poll on ipstpack4 - start */ + mov x2, #DDR_SLEEP_RETRY_CNT + nop + nop +touch_line_1: + cbz x0, touch_line_2 + +start_line_2: + /* x11 = PMU_IPSTPACK4_OFFSET */ + ldr w1, [x7, x11] + tst w1, w3 + b.ne 5f + subs x2, x2, #1 + /* poll on ipstpack4 - end */ + b.gt start_line_2 + + /* if we get here, we have a timeout err */ + mov w4, w5 + /* x10 = PMU_IPSTPCR4_OFFSET re-enable ddr clks interface */ + str w4, [x7, x10] +touch_line_2: + cbz x0, touch_line_3 + +start_line_3: + /* load error code */ + mov x0, #ERROR_DDR_SLEEP + b 2f +5: + wfe + ldr w1, [x23, #EPU_EPCTR10_OFFSET] + cbz w1, 5b + + mov w4, w5 +touch_line_3: + cbz x0, touch_line_4 + +start_line_4: + /* re-enable ddr in devdisr5 */ + str w4, [x8, x22] + /* re-enable ddr clk in ipstpcr4 */ + str w4, [x7, x10] +13: + /* poll on ipstpack4 - start */ + ldr w1, [x7, x11] + tst w1, w3 + b.eq 2f + nop + b 13b + /* poll on ipstpack4 - end */ +2: +touch_line_4: + cbz x0, touch_line_5 + +start_line_5: + /* take ddr out-of self refresh - start */ + mov x2, #DDR_SDRAM_CFG_2_FRCSR + ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + mov w4, w3 + bic w4, w4, w2 + mov w3, w4 + /* wait for ddr cntrlr clock- start */ + mov x1, #DDR_SLEEP_RETRY_CNT +3: + subs x1, x1, #1 +touch_line_5: + cbz x0, touch_line_6 + +start_line_6: + /* wait for ddr cntrlr clock - end */ + b.gt 3b + /* take ddr out-of self refresh - end */ + str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] + mov w1, w17 + /* reset devdisr5 */ + str w1, [x8, #DCFG_DEVDISR5_OFFSET] + mov w1, w16 + /* reset devdisr4 */ + str w1, [x8, #DCFG_DEVDISR4_OFFSET] + mov w1, w15 +touch_line_6: + cbz x0, touch_line_7 + +start_line_7: + /* reset devdisr3 */ + str w1, [x8, #DCFG_DEVDISR3_OFFSET] + mov w1, w14 + /* reset devdisr2 */ + str w1, [x8, #DCFG_DEVDISR2_OFFSET] + mov w1, w13 + /* reset devdisr1 */ + str w1, [x8, #DCFG_DEVDISR1_OFFSET] + /* reset ipstpcr4 */ + str wzr, [x7, x10] + /* reset ipstpcr3 */ + str wzr, [x7, x12] +touch_line_7: + cbz x0, touch_line_8 + +start_line_8: + /* reset ipstpcr2 */ + str wzr, [x7, x18] + /* reset ipstpcr1 */ + str wzr, [x7, x19] + /* reset ipstpcr0 */ + str wzr, [x7, x21] + +touch_line_8: + cbz x0, touch_line_9 + +start_line_9: + b continue_restart +touch_line_9: + cbz x0, start_line_0 + +/* execute here after ddr is back up */ +continue_restart: + /* + * if x0 = 1, all is well + * if x0 < 1, we had an error + */ + cmp x0, #1 + b.ne 4f + mov x0, #0 +4: + ret diff --git a/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S b/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S new file mode 100644 index 0000000..890cf81 --- /dev/null +++ b/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S @@ -0,0 +1,69 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <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 + /* ls1088a does not do cold boot for secondary CPU */ +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + + /* + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, 0x0 + cset w0, eq + ret +endfunc plat_is_my_cpu_primary diff --git a/plat/nxp/soc-ls1088a/include/soc.h b/plat/nxp/soc-ls1088a/include/soc.h new file mode 100644 index 0000000..eb36c2e --- /dev/null +++ b/plat/nxp/soc-ls1088a/include/soc.h @@ -0,0 +1,229 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOC_H +#define SOC_H + +/* Chassis specific defines - common across SoC's of a particular platform */ +#include "dcfg_lsch3.h" +#include "soc_default_base_addr.h" +#include "soc_default_helper_macros.h" + +/* + * SVR Definition of LS1088A + * A: without security + * AE: with security + * (not include major and minor rev) + */ +#define SVR_LS1044A 0x870323 +#define SVR_LS1044AE 0x870322 +#define SVR_LS1048A 0x870321 +#define SVR_LS1048AE 0x870320 +#define SVR_LS1084A 0x870303 +#define SVR_LS1084AE 0x870302 +#define SVR_LS1088A 0x870301 +#define SVR_LS1088AE 0x870300 + +#define SVR_WO_E 0xFFFFFE + +/* Number of cores in platform */ +#define NUMBER_OF_CLUSTERS 2 +#define CORES_PER_CLUSTER 4 +#define PLATFORM_CORE_COUNT (NUMBER_OF_CLUSTERS * CORES_PER_CLUSTER) + +/* set to 0 if the clusters are not symmetrical */ +#define SYMMETRICAL_CLUSTERS 1 + + +#define NUM_DRAM_REGIONS 2 +#define NXP_DRAM0_ADDR 0x80000000 +#define NXP_DRAM0_MAX_SIZE 0x80000000 /* 2 GB */ + +#define NXP_DRAM1_ADDR 0x8080000000 +#define NXP_DRAM1_MAX_SIZE 0x7F80000000 /* 510 G */ + +/* DRAM0 Size defined in platform_def.h */ +#define NXP_DRAM0_SIZE PLAT_DEF_DRAM0_SIZE + +#define NXP_POWMGTDCR 0x700123C20 + +/* epu register offsets and values */ +#define EPU_EPGCR_OFFSET 0x0 +#define EPU_EPIMCR10_OFFSET 0x128 +#define EPU_EPCTR10_OFFSET 0xa28 +#define EPU_EPCCR10_OFFSET 0x828 + +#ifdef EPU_EPCCR10_VAL +#undef EPU_EPCCR10_VAL +#endif +#define EPU_EPCCR10_VAL 0xf2800000 + +#define EPU_EPIMCR10_VAL 0xba000000 +#define EPU_EPCTR10_VAL 0x0 +#define EPU_EPGCR_VAL (1 << 31) + +/* pmu register offsets and values */ +#define PMU_PCPW20SR_OFFSET 0x830 +#define PMU_CLAINACTSETR_OFFSET 0x1100 +#define PMU_CLAINACTCLRR_OFFSET 0x1104 +#define PMU_CLSINACTSETR_OFFSET 0x1108 +#define PMU_CLSINACTCLRR_OFFSET 0x110C +#define PMU_CLL2FLUSHSETR_OFFSET 0x1110 +#define PMU_CLSL2FLUSHCLRR_OFFSET 0x1114 +#define PMU_CLL2FLUSHSR_OFFSET 0x1118 +#define PMU_POWMGTCSR_OFFSET 0x4000 +#define PMU_IPPDEXPCR0_OFFSET 0x4040 +#define PMU_IPPDEXPCR1_OFFSET 0x4044 +#define PMU_IPPDEXPCR2_OFFSET 0x4048 +#define PMU_IPPDEXPCR3_OFFSET 0x404C +#define PMU_IPPDEXPCR4_OFFSET 0x4050 +#define PMU_IPPDEXPCR5_OFFSET 0x4054 +#define PMU_IPSTPCR0_OFFSET 0x4120 +#define PMU_IPSTPCR1_OFFSET 0x4124 +#define PMU_IPSTPCR2_OFFSET 0x4128 +#define PMU_IPSTPCR3_OFFSET 0x412C +#define PMU_IPSTPCR4_OFFSET 0x4130 +#define PMU_IPSTPCR5_OFFSET 0x4134 +#define PMU_IPSTPCR6_OFFSET 0x4138 +#define PMU_IPSTPACK0_OFFSET 0x4140 +#define PMU_IPSTPACK1_OFFSET 0x4144 +#define PMU_IPSTPACK2_OFFSET 0x4148 +#define PMU_IPSTPACK3_OFFSET 0x414C +#define PMU_IPSTPACK4_OFFSET 0x4150 +#define PMU_IPSTPACK5_OFFSET 0x4154 +#define PMU_IPSTPACK6_OFFSET 0x4158 +#define PMU_POWMGTCSR_VAL (1 << 20) + +#define IPPDEXPCR0_MASK 0xFFFFFFFF +#define IPPDEXPCR1_MASK 0xFFFFFFFF +#define IPPDEXPCR2_MASK 0xFFFFFFFF +#define IPPDEXPCR3_MASK 0xFFFFFFFF +#define IPPDEXPCR4_MASK 0xFFFFFFFF +#define IPPDEXPCR5_MASK 0xFFFFFFFF + +/* DEVDISR5_FLX_TMR */ +#define IPPDEXPCR_FLX_TMR 0x00004000 +#define DEVDISR5_FLX_TMR 0x00004000 + +#define IPSTPCR0_VALUE 0x0041310C +#define IPSTPCR1_VALUE 0x000003FF +#define IPSTPCR2_VALUE 0x00013006 + +/* Dont' stop UART */ +#define IPSTPCR3_VALUE 0x0000033A + +#define IPSTPCR4_VALUE 0x00103300 +#define IPSTPCR5_VALUE 0x00000001 +#define IPSTPCR6_VALUE 0x00000000 + + +#define TZPC_BLOCK_SIZE 0x1000 + +/* PORSR1 */ +#define PORSR1_RCW_MASK 0xFF800000 +#define PORSR1_RCW_SHIFT 23 + +/* CFG_RCW_SRC[6:0] */ +#define RCW_SRC_TYPE_MASK 0x70 + +/* RCW SRC NOR */ +#define NOR_16B_VAL 0x20 + +/* + * RCW SRC Serial Flash + * 1. SERAIL NOR (QSPI) + * 2. OTHERS (SD/MMC, SPI, I2C1) + */ +#define RCW_SRC_SERIAL_MASK 0x7F +#define QSPI_VAL 0x62 +#define SDHC_VAL 0x40 +#define EMMC_VAL 0x41 + +/* + * Required LS standard platform porting definitions + * for CCN-504 - Read from RN-F node ID register + */ +#define PLAT_CLUSTER_TO_CCN_ID_MAP 1, 9, 11, 19 + +/* Defines required for using XLAT tables from ARM common code */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 40) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 40) + +/* + * Clock Divisors + */ +#define NXP_PLATFORM_CLK_DIVIDER 1 +#define NXP_UART_CLK_DIVIDER 2 + +/* dcfg register offsets and values */ +#define DCFG_DEVDISR1_OFFSET 0x70 +#define DCFG_DEVDISR2_OFFSET 0x74 +#define DCFG_DEVDISR3_OFFSET 0x78 +#define DCFG_DEVDISR5_OFFSET 0x80 +#define DCFG_DEVDISR6_OFFSET 0x84 + +#define DCFG_DEVDISR1_SEC (1 << 22) +#define DCFG_DEVDISR3_QBMAIN (1 << 12) +#define DCFG_DEVDISR4_SPI_QSPI (1 << 4 | 1 << 5) +#define DCFG_DEVDISR5_MEM (1 << 0) + +#define DEVDISR1_VALUE 0x0041310c +#define DEVDISR2_VALUE 0x000003ff +#define DEVDISR3_VALUE 0x00013006 +#define DEVDISR4_VALUE 0x0000033e +#define DEVDISR5_VALUE 0x00103300 +#define DEVDISR6_VALUE 0x00000001 + +/* + * pwr mgmt features supported in the soc-specific code: + * value == 0x0, the soc code does not support this feature + * value != 0x0, the soc code supports this feature + */ +#define SOC_CORE_RELEASE 0x1 +#define SOC_CORE_RESTART 0x1 +#define SOC_CORE_OFF 0x1 +#define SOC_CORE_STANDBY 0x1 +#define SOC_CORE_PWR_DWN 0x1 +#define SOC_CLUSTER_STANDBY 0x1 +#define SOC_CLUSTER_PWR_DWN 0x1 +#define SOC_SYSTEM_STANDBY 0x1 +#define SOC_SYSTEM_PWR_DWN 0x1 +#define SOC_SYSTEM_OFF 0x1 +#define SOC_SYSTEM_RESET 0x1 + +#define SYSTEM_PWR_DOMAINS 1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + NUMBER_OF_CLUSTERS + \ + SYSTEM_PWR_DOMAINS) + +/* Power state coordination occurs at the system level */ +#define PLAT_PD_COORD_LVL MPIDR_AFFLVL2 +#define PLAT_MAX_PWR_LVL PLAT_PD_COORD_LVL + +/* Local power state for power domains in Run state */ +#define LS_LOCAL_STATE_RUN PSCI_LOCAL_STATE_RUN + +/* define retention state */ +#define PLAT_MAX_RET_STATE (PSCI_LOCAL_STATE_RUN + 1) +#define LS_LOCAL_STATE_RET PLAT_MAX_RET_STATE + +/* define power-down state */ +#define PLAT_MAX_OFF_STATE (PLAT_MAX_RET_STATE + 1) +#define LS_LOCAL_STATE_OFF PLAT_MAX_OFF_STATE + +#ifndef __ASSEMBLER__ +/* CCI slave interfaces */ +static const int cci_map[] = { + 3, + 4, +}; +void soc_init_lowlevel(void); +void soc_init_percpu(void); +void _soc_set_start_addr(unsigned long addr); +void _set_platform_security(void); +#endif + +#endif /* SOC_H */ diff --git a/plat/nxp/soc-ls1088a/ls1088aqds/ddr_init.c b/plat/nxp/soc-ls1088a/ls1088aqds/ddr_init.c new file mode 100644 index 0000000..b7397ba --- /dev/null +++ b/plat/nxp/soc-ls1088a/ls1088aqds/ddr_init.c @@ -0,0 +1,84 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <errno.h> + +#include <common/debug.h> +#include <ddr.h> +#include <utils.h> + +#include <errata.h> +#include <platform_def.h> + +#ifdef CONFIG_STATIC_DDR +#error No static value defined +#endif + +static const struct rc_timing rce[] = { + {U(1600), U(8), U(8)}, + {U(1867), U(8), U(8)}, + {U(2134), U(8), U(9)}, + {} +}; + +static const struct board_timing udimm[] = { + {U(0x04), rce, U(0x01020307), U(0x08090b06)}, +}; + +int ddr_board_options(struct ddr_info *priv) +{ + int ret; + struct memctl_opt *popts = &priv->opt; + + if (popts->rdimm != 0) { + debug("RDIMM parameters not set.\n"); + return -EINVAL; + } + + ret = cal_board_params(priv, udimm, ARRAY_SIZE(udimm)); + if (ret != 0) { + return ret; + } + + popts->addr_hash = 1; + popts->cpo_sample = U(0x7b); + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | + DDR_CDR1_ODT(DDR_CDR_ODT_60ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_60ohm) | + DDR_CDR2_VREF_TRAIN_EN | + DDR_CDR2_VREF_RANGE_2; + + return 0; +} + +long long init_ddr(void) +{ + int spd_addr[] = { NXP_SPD_EEPROM0 }; + struct ddr_info info; + struct sysinfo sys; + long long dram_size; + + zeromem(&sys, sizeof(sys)); + get_clocks(&sys); + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL %lu\n", sys.freq_ddr_pll0); + + zeromem(&info, sizeof(struct ddr_info)); + info.num_ctlrs = NUM_OF_DDRC; + info.dimm_on_ctlr = DDRC_NUM_DIMM; + info.clk = get_ddr_freq(&sys, 0); + info.spd_addr = spd_addr; + info.ddr[0] = (void *)NXP_DDR_ADDR; + + dram_size = dram_init(&info); + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + + erratum_a008850_post(); + + return dram_size; +} diff --git a/plat/nxp/soc-ls1088a/ls1088aqds/plat_def.h b/plat/nxp/soc-ls1088a/ls1088aqds/plat_def.h new file mode 100644 index 0000000..ebd3a26 --- /dev/null +++ b/plat/nxp/soc-ls1088a/ls1088aqds/plat_def.h @@ -0,0 +1,81 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include <arch.h> +/* + * Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include <tbbr_img_def.h> + +#include <policy.h> +#include <soc.h> + +#define NXP_SPD_EEPROM0 0x51 + +#define NXP_SYSCLK_FREQ 100000000 +#define NXP_DDRCLK_FREQ 100000000 + +/* UART related definition */ +#define NXP_CONSOLE_ADDR NXP_UART_ADDR +#define NXP_CONSOLE_BAUDRATE 115200 + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL2) +#if defined(TRUSTED_BOARD_BOOT) +#define PLATFORM_STACK_SIZE 0x2000 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +#define BL2_START NXP_OCRAM_ADDR +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) +#define BL2_NOLOAD_START NXP_OCRAM_ADDR +#define BL2_NOLOAD_LIMIT BL2_BASE + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES 4 +#define MAX_IO_BLOCK_DEVICES 1 +#define MAX_IO_HANDLES 4 + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#define MAX_FIP_DEVICES 2 +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 1 +#endif + +#define BL32_IRQ_SEC_PHY_TIMER 29 +#define BL31_WDOG_SEC 89 + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define PLAT_LS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */ +#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(15, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + + +#endif /* PLAT_DEF_H */ diff --git a/plat/nxp/soc-ls1088a/ls1088aqds/platform.c b/plat/nxp/soc-ls1088a/ls1088aqds/platform.c new file mode 100644 index 0000000..8b3eada --- /dev/null +++ b/plat/nxp/soc-ls1088a/ls1088aqds/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2022 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-ls1088a/ls1088aqds/platform.mk b/plat/nxp/soc-ls1088a/ls1088aqds/platform.mk new file mode 100644 index 0000000..97ccf26 --- /dev/null +++ b/plat/nxp/soc-ls1088a/ls1088aqds/platform.mk @@ -0,0 +1,31 @@ +# +# Copyright 2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters +BOOT_MODE ?= qspi +BOARD := ls1088aqds + +# DDR Compilation Configs +NUM_OF_DDRC := 1 +DDRC_NUM_DIMM := 1 +DDR_ECC_EN := yes + +# On-Board Flash Details +QSPI_FLASH_SZ := 0x4000000 +NOR_FLASH_SZ := 0x20000000 + +BL2_SOURCES += ${BOARD_PATH}/ddr_init.c \ + ${BOARD_PATH}/platform.c + +SUPPORTED_BOOT_MODE := qspi \ + sd \ + nor + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Adding SoC build info +include plat/nxp/soc-ls1088a/soc.mk diff --git a/plat/nxp/soc-ls1088a/ls1088aqds/platform_def.h b/plat/nxp/soc-ls1088a/ls1088aqds/platform_def.h new file mode 100644 index 0000000..7daf1c0 --- /dev/null +++ b/plat/nxp/soc-ls1088a/ls1088aqds/platform_def.h @@ -0,0 +1,13 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <plat_def.h> +#include <plat_default_def.h> + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/nxp/soc-ls1088a/ls1088aqds/policy.h b/plat/nxp/soc-ls1088a/ls1088aqds/policy.h new file mode 100644 index 0000000..0eaafae --- /dev/null +++ b/plat/nxp/soc-ls1088a/ls1088aqds/policy.h @@ -0,0 +1,16 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef POLICY_H +#define POLICY_H + +/* + * Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +#endif /* POLICY_H */ diff --git a/plat/nxp/soc-ls1088a/ls1088ardb/ddr_init.c b/plat/nxp/soc-ls1088a/ls1088ardb/ddr_init.c new file mode 100644 index 0000000..c88583f --- /dev/null +++ b/plat/nxp/soc-ls1088a/ls1088ardb/ddr_init.c @@ -0,0 +1,86 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <errno.h> + +#include <common/debug.h> +#include <ddr.h> +#include <utils.h> + +#include <errata.h> +#include <platform_def.h> + +#ifdef CONFIG_STATIC_DDR +#error No static value defined +#endif + +static const struct rc_timing rce[] = { + {U(1600), U(8), U(8)}, + {U(1867), U(8), U(8)}, + {U(2134), U(8), U(9)}, + {} +}; + +static const struct board_timing udimm[] = { + {U(0x04), rce, U(0x01030508), U(0x090b0d06)}, + {U(0x1f), rce, U(0x01030508), U(0x090b0d06)}, +}; + +int ddr_board_options(struct ddr_info *priv) +{ + int ret; + struct memctl_opt *popts = &priv->opt; + + if (popts->rdimm != 0) { + debug("RDIMM parameters not set.\n"); + return -EINVAL; + } + + ret = cal_board_params(priv, udimm, ARRAY_SIZE(udimm)); + if (ret != 0) { + return ret; + } + + popts->addr_hash = 1; + popts->cpo_sample = U(0x7b); + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | + DDR_CDR1_ODT(DDR_CDR_ODT_60ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_60ohm) | + DDR_CDR2_VREF_TRAIN_EN | + DDR_CDR2_VREF_RANGE_2; + + return 0; +} + +long long init_ddr(void) +{ + int spd_addr[] = { NXP_SPD_EEPROM0 }; + struct ddr_info info; + struct sysinfo sys; + long long dram_size; + + zeromem(&sys, sizeof(sys)); + get_clocks(&sys); + debug("platform clock %lu\n", sys.freq_platform); + debug("DDR PLL %lu\n", sys.freq_ddr_pll0); + + zeromem(&info, sizeof(struct ddr_info)); + info.num_ctlrs = NUM_OF_DDRC; + info.dimm_on_ctlr = DDRC_NUM_DIMM; + info.clk = get_ddr_freq(&sys, 0); + info.spd_addr = spd_addr; + info.ddr[0] = (void *)NXP_DDR_ADDR; + + dram_size = dram_init(&info); + + if (dram_size < 0) { + ERROR("DDR init failed.\n"); + } + + erratum_a008850_post(); + + return dram_size; +} diff --git a/plat/nxp/soc-ls1088a/ls1088ardb/plat_def.h b/plat/nxp/soc-ls1088a/ls1088ardb/plat_def.h new file mode 100644 index 0000000..a6b14fe --- /dev/null +++ b/plat/nxp/soc-ls1088a/ls1088ardb/plat_def.h @@ -0,0 +1,80 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DEF_H +#define PLAT_DEF_H + +#include <arch.h> +/* + * Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include <tbbr_img_def.h> + +#include <policy.h> +#include <soc.h> + +#define NXP_SPD_EEPROM0 0x51 + +#define NXP_SYSCLK_FREQ 100000000 +#define NXP_DDRCLK_FREQ 100000000 + +/* UART related definition */ +#define NXP_CONSOLE_ADDR NXP_UART_ADDR +#define NXP_CONSOLE_BAUDRATE 115200 + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL2) +#if defined(TRUSTED_BOARD_BOOT) +#define PLATFORM_STACK_SIZE 0x2000 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif +#elif defined(IMAGE_BL31) +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +#define BL2_START NXP_OCRAM_ADDR +#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE) +#define BL2_NOLOAD_START NXP_OCRAM_ADDR +#define BL2_NOLOAD_LIMIT BL2_BASE + +/* IO defines as needed by IO driver framework */ +#define MAX_IO_DEVICES 4 +#define MAX_IO_BLOCK_DEVICES 1 +#define MAX_IO_HANDLES 4 + +/* + * FIP image defines - Offset at which FIP Image would be present + * Image would include Bl31 , Bl33 and Bl32 (optional) + */ +#ifdef POLICY_FUSE_PROVISION +#define MAX_FIP_DEVICES 2 +#endif + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 1 +#endif + +#define BL32_IRQ_SEC_PHY_TIMER 29 +#define BL31_WDOG_SEC 89 + +/* + * ID of the secure physical generic timer interrupt used by the BL32. + */ +#define PLAT_LS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */ +#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(15, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#endif /* PLAT_DEF_H */ diff --git a/plat/nxp/soc-ls1088a/ls1088ardb/platform.c b/plat/nxp/soc-ls1088a/ls1088ardb/platform.c new file mode 100644 index 0000000..8b3eada --- /dev/null +++ b/plat/nxp/soc-ls1088a/ls1088ardb/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2022 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-ls1088a/ls1088ardb/platform.mk b/plat/nxp/soc-ls1088a/ls1088ardb/platform.mk new file mode 100644 index 0000000..6884faf --- /dev/null +++ b/plat/nxp/soc-ls1088a/ls1088ardb/platform.mk @@ -0,0 +1,30 @@ +# +# Copyright 2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# board-specific build parameters +BOOT_MODE ?= qspi +BOARD := ls1088ardb + +# DDR Compilation Configs +NUM_OF_DDRC := 1 +DDRC_NUM_DIMM := 1 +DDR_ECC_EN := yes + +# On-Board Flash Details +QSPI_FLASH_SZ := 0x4000000 + +# Adding Platform files build files +BL2_SOURCES += ${BOARD_PATH}/ddr_init.c \ + ${BOARD_PATH}/platform.c + +SUPPORTED_BOOT_MODE := qspi \ + sd + +# Adding platform board build info +include plat/nxp/common/plat_make_helper/plat_common_def.mk + +# Adding SoC build info +include plat/nxp/soc-ls1088a/soc.mk diff --git a/plat/nxp/soc-ls1088a/ls1088ardb/platform_def.h b/plat/nxp/soc-ls1088a/ls1088ardb/platform_def.h new file mode 100644 index 0000000..7daf1c0 --- /dev/null +++ b/plat/nxp/soc-ls1088a/ls1088ardb/platform_def.h @@ -0,0 +1,13 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <plat_def.h> +#include <plat_default_def.h> + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/nxp/soc-ls1088a/ls1088ardb/policy.h b/plat/nxp/soc-ls1088a/ls1088ardb/policy.h new file mode 100644 index 0000000..af206f9 --- /dev/null +++ b/plat/nxp/soc-ls1088a/ls1088ardb/policy.h @@ -0,0 +1,15 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef POLICY_H +#define POLICY_H + +/* Set this to 0x0 to leave the default SMMU page size in sACR + * Set this to 0x1 to change the SMMU page size to 64K + */ +#define POLICY_SMMU_PAGESZ_64K 0x1 + +#endif /* POLICY_H */ diff --git a/plat/nxp/soc-ls1088a/soc.c b/plat/nxp/soc-ls1088a/soc.c new file mode 100644 index 0000000..5f9f313 --- /dev/null +++ b/plat/nxp/soc-ls1088a/soc.c @@ -0,0 +1,397 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <arch.h> +#include <caam.h> +#include <cci.h> +#include <common/debug.h> +#include <dcfg.h> +#ifdef I2C_INIT +#include <i2c.h> +#endif +#include <lib/mmio.h> +#include <lib/xlat_tables/xlat_tables_v2.h> +#include <ls_interconnect.h> +#if TRUSTED_BOARD_BOOT +#include <nxp_smmu.h> +#endif +#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> +#ifdef CONFIG_OCRAM_ECC_EN +#include <ocram.h> +#endif +#include <plat_common.h> +#include <platform_def.h> +#include <soc.h> + +static unsigned char _power_domain_tree_desc[NUMBER_OF_CLUSTERS + 2]; +static struct soc_type soc_list[] = { + SOC_ENTRY(LS1044A, LS1044A, 1, 4), + SOC_ENTRY(LS1044AE, LS1044AE, 1, 4), + SOC_ENTRY(LS1048A, LS1048A, 1, 4), + SOC_ENTRY(LS1048AE, LS1048AE, 1, 4), + SOC_ENTRY(LS1084A, LS1084A, 2, 4), + SOC_ENTRY(LS1084AE, LS1084AE, 2, 4), + SOC_ENTRY(LS1088A, LS1088A, 2, 4), + SOC_ENTRY(LS1088AE, LS1088AE, 2, 4), +}; + +static dcfg_init_info_t dcfg_init_data = { + .g_nxp_dcfg_addr = NXP_DCFG_ADDR, + .nxp_sysclk_freq = NXP_SYSCLK_FREQ, + .nxp_ddrclk_freq = NXP_DDRCLK_FREQ, + .nxp_plat_clk_divider = NXP_PLATFORM_CLK_DIVIDER, +}; + +/* + * This function dynamically constructs the topology according to + * SoC Flavor and returns it. + */ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + unsigned int i; + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + + /* + * The highest level is the system level. The next level is constituted + * by clusters and then cores in clusters. + */ + _power_domain_tree_desc[0] = 1; + _power_domain_tree_desc[1] = num_clusters; + + for (i = 0; i < _power_domain_tree_desc[1]; i++) { + _power_domain_tree_desc[i + 2] = cores_per_cluster; + } + + + return _power_domain_tree_desc; +} + +CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256, + assert_invalid_ls1088a_cluster_count); + +/* + * This function returns the core count within the cluster corresponding to + * `mpidr`. + */ +unsigned int plat_ls_get_cluster_core_count(u_register_t mpidr) +{ + return CORES_PER_CLUSTER; +} + +/* + * This function returns the total number of cores in the SoC + */ +unsigned int get_tot_num_cores(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + + return (num_clusters * cores_per_cluster); +} + +/* + * This function returns the PMU IDLE Cluster mask. + */ +unsigned int get_pmu_idle_cluster_mask(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + + return ((1 << num_clusters) - 2); +} + +/* + * This function returns the PMU Flush Cluster mask. + */ +unsigned int get_pmu_flush_cluster_mask(void) +{ + uint8_t num_clusters, cores_per_cluster; + + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + + return ((1 << num_clusters) - 2); +} + +/* + * This function returns the PMU IDLE Core mask. + */ +unsigned int get_pmu_idle_core_mask(void) +{ + return ((1 << get_tot_num_cores()) - 2); +} + +#ifdef IMAGE_BL2 + +void soc_bl2_prepare_exit(void) +{ +#if defined(NXP_SFP_ENABLED) && defined(DISABLE_FUSE_WRITE) + set_sfp_wr_disable(); +#endif +} + +void soc_preload_setup(void) +{ + +} + +/* + * This function returns the boot device based on RCW_SRC + */ +enum boot_device get_boot_dev(void) +{ + enum boot_device src = BOOT_DEVICE_NONE; + uint32_t porsr1; + uint32_t rcw_src, val; + + porsr1 = read_reg_porsr1(); + + rcw_src = (porsr1 & PORSR1_RCW_MASK) >> PORSR1_RCW_SHIFT; + + /* RCW SRC NOR */ + val = rcw_src & RCW_SRC_TYPE_MASK; + if (val == NOR_16B_VAL) { + src = BOOT_DEVICE_IFC_NOR; + INFO("RCW BOOT SRC is IFC NOR\n"); + } else { + val = rcw_src & RCW_SRC_SERIAL_MASK; + switch (val) { + case QSPI_VAL: + src = BOOT_DEVICE_QSPI; + INFO("RCW BOOT SRC is QSPI\n"); + break; + case SDHC_VAL: + src = BOOT_DEVICE_EMMC; + INFO("RCW BOOT SRC is SD/EMMC\n"); + break; + case EMMC_VAL: + src = BOOT_DEVICE_EMMC; + INFO("RCW BOOT SRC is SD/EMMC\n"); + break; + default: + src = BOOT_DEVICE_NONE; + } + } + + return src; +} + +/* + * This function sets up access permissions on memory regions + */ +void soc_mem_access(void) +{ + dram_regions_info_t *info_dram_regions = get_dram_regions_info(); + int i = 0; + struct tzc400_reg tzc400_reg_list[MAX_NUM_TZC_REGION]; + int dram_idx, index = 1; + + for (dram_idx = 0; dram_idx < info_dram_regions->num_dram_regions; + dram_idx++) { + if (info_dram_regions->region[i].size == 0) { + ERROR("DDR init failure, or"); + ERROR("DRAM regions not populated correctly.\n"); + break; + } + + index = populate_tzc400_reg_list(tzc400_reg_list, + dram_idx, index, + info_dram_regions->region[dram_idx].addr, + info_dram_regions->region[dram_idx].size, + NXP_SECURE_DRAM_SIZE, NXP_SP_SHRD_DRAM_SIZE); + } + + mem_access_setup(NXP_TZC_ADDR, index, + tzc400_reg_list); +} + +/* + * This function implements soc specific erratum + * This is called before DDR is initialized or MMU is enabled + */ +void soc_early_init(void) +{ + enum boot_device dev; + dram_regions_info_t *dram_regions_info = get_dram_regions_info(); + +#ifdef CONFIG_OCRAM_ECC_EN + ocram_init(NXP_OCRAM_ADDR, NXP_OCRAM_SIZE); +#endif + dcfg_init(&dcfg_init_data); +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif + enable_timer_base_to_cluster(NXP_PMU_ADDR); + enable_core_tb(NXP_PMU_ADDR); + + /* + * Use the region(NXP_SD_BLOCK_BUF_ADDR + NXP_SD_BLOCK_BUF_SIZE) + * as dma of sd + */ + dev = get_boot_dev(); + if (dev == BOOT_DEVICE_EMMC) { + mmap_add_region(NXP_SD_BLOCK_BUF_ADDR, NXP_SD_BLOCK_BUF_ADDR, + NXP_SD_BLOCK_BUF_SIZE, + MT_DEVICE | MT_RW | MT_NS); + } + +#if TRUSTED_BOARD_BOOT + uint32_t mode; + + sfp_init(NXP_SFP_ADDR); + /* + * For secure boot disable SMMU. + * Later when platform security policy comes in picture, + * this might get modified based on the policy + */ + if (check_boot_mode_secure(&mode) == true) { + bypass_smmu(NXP_SMMU_ADDR); + } + + /* + * For Mbedtls currently crypto is not supported via CAAM + * enable it when that support is there. In tbbr.mk + * the CAAM_INTEG is set as 0. + */ +#ifndef MBEDTLS_X509 + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled() == false) { + INFO("SEC is disabled.\n"); + } else { + sec_init(NXP_CAAM_ADDR); + } +#endif +#endif + + soc_errata(); + + delay_timer_init(NXP_TIMER_ADDR); + i2c_init(NXP_I2C_ADDR); + dram_regions_info->total_dram_size = init_ddr(); +} +#else /* !IMAGE_BL2 */ + +void soc_early_platform_setup2(void) +{ + dcfg_init(&dcfg_init_data); + /* + * Initialize system level generic timer for Socs + */ + delay_timer_init(NXP_TIMER_ADDR); + +#if LOG_LEVEL > 0 + /* Initialize the console to provide early debug support */ + plat_console_init(NXP_CONSOLE_ADDR, + NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE); +#endif +} + +void soc_platform_setup(void) +{ + /* Initialize the GIC driver, cpu and distributor interfaces */ + static uintptr_t target_mask_array[PLATFORM_CORE_COUNT]; + static interrupt_prop_t ls_interrupt_props[] = { + PLAT_LS_G1S_IRQ_PROPS(INTR_GROUP1S), + PLAT_LS_G0_IRQ_PROPS(INTR_GROUP0) + }; + + plat_ls_gic_driver_init(NXP_GICD_ADDR, NXP_GICR_ADDR, + PLATFORM_CORE_COUNT, + ls_interrupt_props, + ARRAY_SIZE(ls_interrupt_props), + target_mask_array, + plat_core_pos); + + plat_ls_gic_init(); + enable_init_timer(); +} + +/* + * This function initializes the soc from the BL31 module + */ +void soc_init(void) +{ + uint8_t num_clusters, cores_per_cluster; + + /* low-level init of the soc */ + soc_init_lowlevel(); + _init_global_data(); + soc_init_percpu(); + _initialize_psci(); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map)); + + /* + * Enable Interconnect coherency for the primary CPU's cluster. + */ + get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster); + plat_ls_interconnect_enter_coherency(num_clusters); + + /* set platform security policies */ + _set_platform_security(); + + /* Initialize the crypto accelerator if enabled */ + if (is_sec_enabled() == false) { + INFO("SEC is disabled.\n"); + } else { + sec_init(NXP_CAAM_ADDR); + } +} + +void soc_runtime_setup(void) +{ + +} +#endif /* IMAGE_BL2 */ + +/* + * Function to return the SoC SYS CLK + */ +unsigned int get_sys_clk(void) +{ + return NXP_SYSCLK_FREQ; +} + +/* + * Function returns the base counter frequency + * after reading the first entry at CNTFID0 (0x20 offset). + * + * Function is used by: + * 1. ARM common code for PSCI management. + * 2. ARM Generic Timer init. + */ +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int counter_base_frequency; + /* + * Below register specifies the base frequency of the system counter. + * As per NXP Board Manuals: + * The system counter always works with SYS_REF_CLK/4 frequency clock. + */ + counter_base_frequency = mmio_read_32(NXP_TIMER_ADDR + CNTFID_OFF); + + return counter_base_frequency; +} diff --git a/plat/nxp/soc-ls1088a/soc.def b/plat/nxp/soc-ls1088a/soc.def new file mode 100644 index 0000000..25d0847 --- /dev/null +++ b/plat/nxp/soc-ls1088a/soc.def @@ -0,0 +1,87 @@ +# +# Copyright 2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# This file contains the basic architecture definitions that drive the build +# +# ----------------------------------------------------------------------------- + +CORE_TYPE := a53 + +CACHE_LINE := 6 + +# Set to GIC400 or GIC500 +GIC := GIC500 + +# Set to CCI400 or CCN504 or CCN508 +INTERCONNECT := CCI400 + +# Select the DDR PHY generation to be used +PLAT_DDR_PHY := PHY_GEN1 + +PHYS_SYS := 64 + +# Indicate layerscape chassis level - set to 3=LSCH3 or 2=LSCH2 +CHASSIS := 3 + +# TZC IP Details TZC used is TZC380 or TZC400 +TZC_ID := TZC400 + +# CONSOLE Details available is NS16550 or PL011 +CONSOLE := NS16550 + +NXP_SFP_VER := 3_4 + +# In IMAGE_BL2, compile time flag for handling Cache coherency +# with CAAM for BL2 running from OCRAM +SEC_MEM_NON_COHERENT := yes + + +# OCRAM MAP for BL2 +# Before BL2 +# 0x18000000 - 0x18009fff -> Used by ROM code, (TBD - can it be used for xlat tables) +# 0x1800a000 - 0x1801Cfff -> Reserved for BL2 binary (76 KB) +# 0x1801D000 - 0x1801ffff -> CSF header for BL2 (12 KB) +OCRAM_START_ADDR := 0x18000000 +OCRAM_SIZE := 0x20000 + +CSF_HDR_SZ := 0x3000 + +# Area of OCRAM reserved by ROM code +NXP_ROM_RSVD := 0xa000 + +# Input to CST create_hdr_isbc tool +BL2_HDR_LOC := 0x1801D000 + +# Location of BL2 on OCRAM +# BL2_BASE=OCRAM_START_ADDR+NXP_ROM_RSVD +BL2_BASE := 0x1800a000 + +# SoC ERRATUM to be enabled +ERRATA_SOC_A008850 := 1 + +# ARM Erratum +ERRATA_A53_855873 := 1 + +# DDR Erratum +ERRATA_DDR_A008511 := 1 +ERRATA_DDR_A009803 := 1 +ERRATA_DDR_A009942 := 1 +ERRATA_DDR_A010165 := 1 + +# Define Endianness of each module +NXP_ESDHC_ENDIANNESS := LE +NXP_SFP_ENDIANNESS := LE +NXP_GPIO_ENDIANNESS := LE +NXP_SNVS_ENDIANNESS := LE +NXP_GUR_ENDIANNESS := LE +NXP_SEC_ENDIANNESS := LE +NXP_DDR_ENDIANNESS := LE +NXP_QSPI_ENDIANNESS := LE + +# OCRAM ECC Enabled +OCRAM_ECC_EN := yes diff --git a/plat/nxp/soc-ls1088a/soc.mk b/plat/nxp/soc-ls1088a/soc.mk new file mode 100644 index 0000000..83ac9d0 --- /dev/null +++ b/plat/nxp/soc-ls1088a/soc.mk @@ -0,0 +1,110 @@ +# +# Copyright 2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SoC-specific build parameters +SOC := ls1088a +PLAT_PATH := plat/nxp +PLAT_COMMON_PATH:= plat/nxp/common +PLAT_DRIVERS_PATH:= drivers/nxp +PLAT_SOC_PATH := ${PLAT_PATH}/soc-${SOC} +BOARD_PATH := ${PLAT_SOC_PATH}/${BOARD} + +# Separate BL2 NOLOAD region (.bss, stack, page tables). need to +# define BL2_NOLOAD_START and BL2_NOLOAD_LIMIT +SEPARATE_BL2_NOLOAD_REGION := 1 + +# get SoC-specific defnitions +include ${PLAT_SOC_PATH}/soc.def +include ${PLAT_COMMON_PATH}/plat_make_helper/soc_common_def.mk +include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk + +# For Security Features +DISABLE_FUSE_WRITE := 1 +ifeq (${TRUSTED_BOARD_BOOT}, 1) +ifeq (${GENERATE_COT},1) +# Save Keys to be used by DDR FIP image +SAVE_KEYS=1 +endif +$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2)) +# Used by create_pbl tool to +# create bl2_<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)) + + +# Adding SoC specific files +include ${PLAT_COMMON_PATH}/soc_errata/errata.mk + +PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/include/default\ + -I${BOARD_PATH}\ + -I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\ + -I${PLAT_COMMON_PATH}/soc_errata\ + -I${PLAT_COMMON_PATH}/include\ + -I${PLAT_SOC_PATH}/include + +ifeq (${SECURE_BOOT},yes) +include ${PLAT_COMMON_PATH}/tbbr/tbbr.mk +endif + +ifeq (${PSCI_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/psci/psci.mk +endif + +ifeq (${SIPSVC_NEEDED}, yes) +include ${PLAT_COMMON_PATH}/sip_svc/sipsvc.mk +endif + +# for fuse-fip & fuse-programming +ifeq (${FUSE_PROG}, 1) +include ${PLAT_COMMON_PATH}/fip_handler/fuse_fip/fuse.mk +endif + +ifeq (${IMG_LOADR_NEEDED},yes) +include $(PLAT_COMMON_PATH)/img_loadr/img_loadr.mk +endif + +# Adding source files for the above selected drivers. +include ${PLAT_DRIVERS_PATH}/drivers.mk + +PLAT_BL_COMMON_SOURCES += ${PLAT_COMMON_PATH}/$(ARCH)/ls_helpers.S\ + ${PLAT_SOC_PATH}/${ARCH}/${SOC}_helpers.S\ + ${PLAT_SOC_PATH}/soc.c + +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}.S\ + ${PSCI_SOURCES}\ + ${SIPSVC_SOURCES}\ + ${PLAT_COMMON_PATH}/$(ARCH)/bl31_data.S + +ifeq (${TEST_BL31}, 1) +BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/bootmain64.S \ + ${PLAT_SOC_PATH}/$(ARCH)/nonboot64.S +endif + +BL2_SOURCES += ${DDR_CNTLR_SOURCES}\ + ${TBBR_SOURCES}\ + ${FUSE_SOURCES} + +# Adding TFA setup files +include ${PLAT_PATH}/common/setup/common.mk 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..7cc4a03 --- /dev/null +++ b/plat/nxp/soc-lx2160a/include/soc.h @@ -0,0 +1,141 @@ +/* + * 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_LX2120A 0x873621 +#define SVR_LX2080A 0x873603 + +/* 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..2209fda --- /dev/null +++ b/plat/nxp/soc-lx2160a/soc.c @@ -0,0 +1,509 @@ +/* + * 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 +#if TRUSTED_BOARD_BOOT +#include <nxp_smmu.h> +#endif +#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> +#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_ENTRY(LX2160A, LX2160A, 8, 2), + SOC_ENTRY(LX2080A, LX2080A, 8, 1), + SOC_ENTRY(LX2120A, LX2120A, 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) +{ + 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 + +#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(); + soc_init_percpu(); + _init_global_data(); + _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..81d6744 --- /dev/null +++ b/plat/nxp/soc-lx2160a/soc.def @@ -0,0 +1,116 @@ +# +# 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 diff --git a/plat/nxp/soc-lx2160a/soc.mk b/plat/nxp/soc-lx2160a/soc.mk new file mode 100644 index 0000000..75a3af2 --- /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 +ifeq (${TRUSTED_BOARD_BOOT}, 1) +ifeq (${GENERATE_COT},1) +# Save Keys to be used by DDR FIP image +SAVE_KEYS=1 +endif +$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2)) +$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2)) +# Used by create_pbl tool to +# create bl2_<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 |