diff options
Diffstat (limited to '')
-rw-r--r-- | plat/nxp/common/aarch64/bl31_data.S | 558 | ||||
-rw-r--r-- | plat/nxp/common/aarch64/ls_helpers.S | 220 |
2 files changed, 778 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 |