From 102b0d2daa97dae68d3eed54d8fe37a9cc38a892 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 11:13:47 +0200 Subject: Adding upstream version 2.8.0+dfsg. Signed-off-by: Daniel Baumann --- plat/arm/board/fvp/aarch32/fvp_helpers.S | 143 +++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 plat/arm/board/fvp/aarch32/fvp_helpers.S (limited to 'plat/arm/board/fvp/aarch32') diff --git a/plat/arm/board/fvp/aarch32/fvp_helpers.S b/plat/arm/board/fvp/aarch32/fvp_helpers.S new file mode 100644 index 0000000..9985c1d --- /dev/null +++ b/plat/arm/board/fvp/aarch32/fvp_helpers.S @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + .globl plat_arm_calc_core_pos + + /* -------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * For AArch32, cold-booting secondary CPUs is not yet + * implemented and they panic. + * -------------------------------------------------------------------- + */ +func plat_secondary_cold_boot_setup +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * unsigned long plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and warm + * boot. On FVP, this information can be queried from the power + * controller. The Power Control SYS Status Register (PSYSR) indicates + * the wake-up reason for the CPU. + * + * For a cold boot, return 0. + * For a warm boot, read the mailbox and return the address it contains. + * + * TODO: PSYSR is a common register and should be + * accessed using locks. Since it is not possible + * to use locks immediately after a cold reset + * we are relying on the fact that after a cold + * reset all cpus will read the same WK field + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* --------------------------------------------------------------------- + * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC + * WakeRequest signal" then it is a warm boot. + * --------------------------------------------------------------------- + */ + ldcopr r2, MPIDR + ldr r1, =PWRC_BASE + str r2, [r1, #PSYSR_OFF] + ldr r2, [r1, #PSYSR_OFF] + ubfx r2, r2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH + cmp r2, #WKUP_PPONR + beq warm_reset + cmp r2, #WKUP_GICREQ + beq warm_reset + + /* Cold reset */ + mov r0, #0 + bx lr + +warm_reset: + /* --------------------------------------------------------------------- + * A mailbox is maintained in the trusted SRAM. It is flushed out of the + * caches after every update using normal memory so it is safe to read + * it here with SO attributes. + * --------------------------------------------------------------------- + */ + ldr r0, =PLAT_ARM_TRUSTED_MAILBOX_BASE + ldr r0, [r0] + cmp r0, #0 + beq _panic + bx lr + + /* --------------------------------------------------------------------- + * The power controller indicates this is a warm reset but the mailbox + * is empty. This should never happen! + * --------------------------------------------------------------------- + */ +_panic: + b _panic +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + ldcopr r0, MPIDR + ldr r1, =MPIDR_AFFINITY_MASK + and r0, r1 + cmp r0, #FVP_PRIMARY_CPU + moveq r0, #1 + movne r0, #0 + bx lr +endfunc plat_is_my_cpu_primary + + /* --------------------------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Function to calculate the core position on FVP. + * + * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) + + * (CPUId * FVP_MAX_PE_PER_CPU) + + * ThreadId + * + * which can be simplified as: + * + * ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU) + * + ThreadId + * --------------------------------------------------------------------- + */ +func plat_arm_calc_core_pos + mov r3, r0 + + /* + * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it + * look as if in a multi-threaded implementation + */ + tst r0, #MPIDR_MT_MASK + lsleq r3, r0, #MPIDR_AFFINITY_BITS + + /* Extract individual affinity fields from MPIDR */ + ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov r3, #FVP_MAX_CPUS_PER_CLUSTER + mla r1, r2, r3, r1 + mov r3, #FVP_MAX_PE_PER_CPU + mla r0, r1, r3, r0 + + bx lr +endfunc plat_arm_calc_core_pos -- cgit v1.2.3