1*91f16700Schasinglulu/* 2*91f16700Schasinglulu * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu#include <arch.h> 8*91f16700Schasinglulu#include <asm_macros.S> 9*91f16700Schasinglulu#include <drivers/arm/fvp/fvp_pwrc.h> 10*91f16700Schasinglulu#include <drivers/arm/gicv2.h> 11*91f16700Schasinglulu#include <drivers/arm/gicv3.h> 12*91f16700Schasinglulu 13*91f16700Schasinglulu#include <platform_def.h> 14*91f16700Schasinglulu 15*91f16700Schasinglulu 16*91f16700Schasinglulu .globl plat_secondary_cold_boot_setup 17*91f16700Schasinglulu .globl plat_get_my_entrypoint 18*91f16700Schasinglulu .globl plat_is_my_cpu_primary 19*91f16700Schasinglulu 20*91f16700Schasinglulu /* ----------------------------------------------------- 21*91f16700Schasinglulu * void plat_secondary_cold_boot_setup (void); 22*91f16700Schasinglulu * 23*91f16700Schasinglulu * This function performs any platform specific actions 24*91f16700Schasinglulu * needed for a secondary cpu after a cold reset e.g 25*91f16700Schasinglulu * mark the cpu's presence, mechanism to place it in a 26*91f16700Schasinglulu * holding pen etc. 27*91f16700Schasinglulu * TODO: Should we read the PSYS register to make sure 28*91f16700Schasinglulu * that the request has gone through. 29*91f16700Schasinglulu * ----------------------------------------------------- 30*91f16700Schasinglulu */ 31*91f16700Schasinglulufunc plat_secondary_cold_boot_setup 32*91f16700Schasinglulu /* --------------------------------------------- 33*91f16700Schasinglulu * Power down this cpu. 34*91f16700Schasinglulu * TODO: Do we need to worry about powering the 35*91f16700Schasinglulu * cluster down as well here? That will need 36*91f16700Schasinglulu * locks which we won't have unless an elf- 37*91f16700Schasinglulu * loader zeroes out the zi section. 38*91f16700Schasinglulu * --------------------------------------------- 39*91f16700Schasinglulu */ 40*91f16700Schasinglulu mrs x0, mpidr_el1 41*91f16700Schasinglulu mov_imm x1, PWRC_BASE 42*91f16700Schasinglulu str w0, [x1, #PPOFFR_OFF] 43*91f16700Schasinglulu 44*91f16700Schasinglulu /* --------------------------------------------- 45*91f16700Schasinglulu * There is no sane reason to come out of this 46*91f16700Schasinglulu * wfi so panic if we do. This cpu will be pow- 47*91f16700Schasinglulu * ered on and reset by the cpu_on pm api 48*91f16700Schasinglulu * --------------------------------------------- 49*91f16700Schasinglulu */ 50*91f16700Schasinglulu dsb sy 51*91f16700Schasinglulu wfi 52*91f16700Schasinglulu no_ret plat_panic_handler 53*91f16700Schasingluluendfunc plat_secondary_cold_boot_setup 54*91f16700Schasinglulu 55*91f16700Schasinglulu /* --------------------------------------------------------------------- 56*91f16700Schasinglulu * uintptr_t plat_get_my_entrypoint (void); 57*91f16700Schasinglulu * 58*91f16700Schasinglulu * Main job of this routine is to distinguish between a cold and warm 59*91f16700Schasinglulu * boot. On FVP_R, this information can be queried from the power 60*91f16700Schasinglulu * controller. The Power Control SYS Status Register (PSYSR) indicates 61*91f16700Schasinglulu * the wake-up reason for the CPU. 62*91f16700Schasinglulu * 63*91f16700Schasinglulu * For a cold boot, return 0. 64*91f16700Schasinglulu * For a warm boot, read the mailbox and return the address it contains. 65*91f16700Schasinglulu * 66*91f16700Schasinglulu * TODO: PSYSR is a common register and should be 67*91f16700Schasinglulu * accessed using locks. Since it is not possible 68*91f16700Schasinglulu * to use locks immediately after a cold reset 69*91f16700Schasinglulu * we are relying on the fact that after a cold 70*91f16700Schasinglulu * reset all cpus will read the same WK field 71*91f16700Schasinglulu * --------------------------------------------------------------------- 72*91f16700Schasinglulu */ 73*91f16700Schasinglulufunc plat_get_my_entrypoint 74*91f16700Schasinglulu /* --------------------------------------------------------------------- 75*91f16700Schasinglulu * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC 76*91f16700Schasinglulu * WakeRequest signal" then it is a warm boot. 77*91f16700Schasinglulu * --------------------------------------------------------------------- 78*91f16700Schasinglulu */ 79*91f16700Schasinglulu mrs x2, mpidr_el1 80*91f16700Schasinglulu mov_imm x1, PWRC_BASE 81*91f16700Schasinglulu str w2, [x1, #PSYSR_OFF] 82*91f16700Schasinglulu ldr w2, [x1, #PSYSR_OFF] 83*91f16700Schasinglulu ubfx w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH 84*91f16700Schasinglulu cmp w2, #WKUP_PPONR 85*91f16700Schasinglulu beq warm_reset 86*91f16700Schasinglulu cmp w2, #WKUP_GICREQ 87*91f16700Schasinglulu beq warm_reset 88*91f16700Schasinglulu 89*91f16700Schasinglulu /* Cold reset */ 90*91f16700Schasinglulu mov x0, #0 91*91f16700Schasinglulu ret 92*91f16700Schasinglulu 93*91f16700Schasingluluwarm_reset: 94*91f16700Schasinglulu /* --------------------------------------------------------------------- 95*91f16700Schasinglulu * A mailbox is maintained in the trusted SRAM. It is flushed out of the 96*91f16700Schasinglulu * caches after every update using normal memory so it is safe to read 97*91f16700Schasinglulu * it here with SO attributes. 98*91f16700Schasinglulu * --------------------------------------------------------------------- 99*91f16700Schasinglulu */ 100*91f16700Schasinglulu mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE 101*91f16700Schasinglulu ldr x0, [x0] 102*91f16700Schasinglulu cbz x0, _panic_handler 103*91f16700Schasinglulu ret 104*91f16700Schasinglulu 105*91f16700Schasinglulu /* --------------------------------------------------------------------- 106*91f16700Schasinglulu * The power controller indicates this is a warm reset but the mailbox 107*91f16700Schasinglulu * is empty. This should never happen! 108*91f16700Schasinglulu * --------------------------------------------------------------------- 109*91f16700Schasinglulu */ 110*91f16700Schasinglulu_panic_handler: 111*91f16700Schasinglulu no_ret plat_panic_handler 112*91f16700Schasingluluendfunc plat_get_my_entrypoint 113*91f16700Schasinglulu 114*91f16700Schasinglulu /* ----------------------------------------------------- 115*91f16700Schasinglulu * unsigned int plat_is_my_cpu_primary (void); 116*91f16700Schasinglulu * 117*91f16700Schasinglulu * Find out whether the current cpu is the primary 118*91f16700Schasinglulu * cpu. 119*91f16700Schasinglulu * ----------------------------------------------------- 120*91f16700Schasinglulu */ 121*91f16700Schasinglulufunc plat_is_my_cpu_primary 122*91f16700Schasinglulu mrs x0, mpidr_el1 123*91f16700Schasinglulu mov_imm x1, MPIDR_AFFINITY_MASK 124*91f16700Schasinglulu and x0, x0, x1 125*91f16700Schasinglulu cmp x0, #FVP_R_PRIMARY_CPU 126*91f16700Schasinglulu cset w0, eq 127*91f16700Schasinglulu ret 128*91f16700Schasingluluendfunc plat_is_my_cpu_primary 129