1 /* 2 * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <arch.h> 8 #include <asm_macros.S> 9 #include <platform_def.h> 10 #include "../drivers/pwrc/fvp_pwrc.h" 11 #include "../fvp_def.h" 12 13 .globl plat_secondary_cold_boot_setup 14 .globl plat_get_my_entrypoint 15 .globl plat_is_my_cpu_primary 16 .globl plat_arm_calc_core_pos 17 18 /* -------------------------------------------------------------------- 19 * void plat_secondary_cold_boot_setup (void); 20 * 21 * For AArch32, cold-booting secondary CPUs is not yet 22 * implemented and they panic. 23 * -------------------------------------------------------------------- 24 */ 25 func plat_secondary_cold_boot_setup 26 cb_panic: 27 b cb_panic 28 endfunc plat_secondary_cold_boot_setup 29 30 /* --------------------------------------------------------------------- 31 * unsigned long plat_get_my_entrypoint (void); 32 * 33 * Main job of this routine is to distinguish between a cold and warm 34 * boot. On FVP, this information can be queried from the power 35 * controller. The Power Control SYS Status Register (PSYSR) indicates 36 * the wake-up reason for the CPU. 37 * 38 * For a cold boot, return 0. 39 * For a warm boot, read the mailbox and return the address it contains. 40 * 41 * TODO: PSYSR is a common register and should be 42 * accessed using locks. Since it is not possible 43 * to use locks immediately after a cold reset 44 * we are relying on the fact that after a cold 45 * reset all cpus will read the same WK field 46 * --------------------------------------------------------------------- 47 */ 48 func plat_get_my_entrypoint 49 /* --------------------------------------------------------------------- 50 * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC 51 * WakeRequest signal" then it is a warm boot. 52 * --------------------------------------------------------------------- 53 */ 54 ldcopr r2, MPIDR 55 ldr r1, =PWRC_BASE 56 str r2, [r1, #PSYSR_OFF] 57 ldr r2, [r1, #PSYSR_OFF] 58 ubfx r2, r2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH 59 cmp r2, #WKUP_PPONR 60 beq warm_reset 61 cmp r2, #WKUP_GICREQ 62 beq warm_reset 63 64 /* Cold reset */ 65 mov r0, #0 66 bx lr 67 68 warm_reset: 69 /* --------------------------------------------------------------------- 70 * A mailbox is maintained in the trusted SRAM. It is flushed out of the 71 * caches after every update using normal memory so it is safe to read 72 * it here with SO attributes. 73 * --------------------------------------------------------------------- 74 */ 75 ldr r0, =PLAT_ARM_TRUSTED_MAILBOX_BASE 76 ldr r0, [r0] 77 cmp r0, #0 78 beq _panic 79 bx lr 80 81 /* --------------------------------------------------------------------- 82 * The power controller indicates this is a warm reset but the mailbox 83 * is empty. This should never happen! 84 * --------------------------------------------------------------------- 85 */ 86 _panic: 87 b _panic 88 endfunc plat_get_my_entrypoint 89 90 /* ----------------------------------------------------- 91 * unsigned int plat_is_my_cpu_primary (void); 92 * 93 * Find out whether the current cpu is the primary 94 * cpu. 95 * ----------------------------------------------------- 96 */ 97 func plat_is_my_cpu_primary 98 ldcopr r0, MPIDR 99 ldr r1, =MPIDR_AFFINITY_MASK 100 and r0, r1 101 cmp r0, #FVP_PRIMARY_CPU 102 moveq r0, #1 103 movne r0, #0 104 bx lr 105 endfunc plat_is_my_cpu_primary 106 107 /* ----------------------------------------------------- 108 * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) 109 * 110 * Function to calculate the core position on FVP. 111 * 112 * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER) + 113 * (CPUId * FVP_MAX_PE_PER_CPU) + 114 * ThreadId 115 * ----------------------------------------------------- 116 */ 117 func plat_arm_calc_core_pos 118 mov r3, r0 119 120 /* 121 * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it 122 * look as if in a multi-threaded implementation 123 */ 124 tst r0, #MPIDR_MT_MASK 125 lsleq r3, r0, #MPIDR_AFFINITY_BITS 126 127 /* Extract individual affinity fields from MPIDR */ 128 mov r2, #FVP_MAX_PE_PER_CPU 129 ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS 130 ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS 131 mla r0, r1, r2, r0 132 133 mov r1, #FVP_MAX_CPUS_PER_CLUSTER 134 ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS 135 mla r0, r1, r2, r0 136 137 bx lr 138 endfunc plat_arm_calc_core_pos 139