100c7d5acSUsama Arif/* 200c7d5acSUsama Arif * Copyright (c) 2019, Arm Limited. All rights reserved. 300c7d5acSUsama Arif * 400c7d5acSUsama Arif * SPDX-License-Identifier: BSD-3-Clause 500c7d5acSUsama Arif */ 600c7d5acSUsama Arif 700c7d5acSUsama Arif#include <arch.h> 800c7d5acSUsama Arif#include <asm_macros.S> 900c7d5acSUsama Arif#include <platform_def.h> 1000c7d5acSUsama Arif 1100c7d5acSUsama Arif .globl plat_secondary_cold_boot_setup 1200c7d5acSUsama Arif .globl plat_get_my_entrypoint 1300c7d5acSUsama Arif .globl plat_is_my_cpu_primary 1400c7d5acSUsama Arif 15*e231f3a5SUsama Arif /* ----------------------------------------------------- 1600c7d5acSUsama Arif * void plat_secondary_cold_boot_setup (void); 1700c7d5acSUsama Arif * 18*e231f3a5SUsama Arif * This function performs any platform specific actions 19*e231f3a5SUsama Arif * needed for a secondary cpu after a cold reset e.g 20*e231f3a5SUsama Arif * mark the cpu's presence, mechanism to place it in a 21*e231f3a5SUsama Arif * holding pen etc. 22*e231f3a5SUsama Arif * ----------------------------------------------------- 2300c7d5acSUsama Arif */ 2400c7d5acSUsama Ariffunc plat_secondary_cold_boot_setup 25*e231f3a5SUsama Arif /* Calculate address of our hold entry */ 26*e231f3a5SUsama Arif bl plat_my_core_pos 27*e231f3a5SUsama Arif lsl r0, r0, #A5DS_HOLD_ENTRY_SHIFT 28*e231f3a5SUsama Arif mov_imm r2, A5DS_HOLD_BASE 29*e231f3a5SUsama Arif /* Clear the value stored in the hold address for the specific core */ 30*e231f3a5SUsama Arif mov_imm r3, A5DS_HOLD_STATE_WAIT 31*e231f3a5SUsama Arif str r3, [r2, r0] 32*e231f3a5SUsama Arif dmb ish 33*e231f3a5SUsama Arif 34*e231f3a5SUsama Arif /* Wait until we have a go */ 35*e231f3a5SUsama Arifpoll_mailbox: 36*e231f3a5SUsama Arif ldr r1, [r2, r0] 37*e231f3a5SUsama Arif cmp r1, #A5DS_HOLD_STATE_WAIT 38*e231f3a5SUsama Arif beq 1f 39*e231f3a5SUsama Arif mov_imm r0, A5DS_TRUSTED_MAILBOX_BASE 40*e231f3a5SUsama Arif ldr r1, [r0] 41*e231f3a5SUsama Arif bx r1 42*e231f3a5SUsama Arif1: 43*e231f3a5SUsama Arif wfe 44*e231f3a5SUsama Arif b poll_mailbox 4500c7d5acSUsama Arifendfunc plat_secondary_cold_boot_setup 4600c7d5acSUsama Arif 4700c7d5acSUsama Arif /* --------------------------------------------------------------------- 4800c7d5acSUsama Arif * unsigned long plat_get_my_entrypoint (void); 4900c7d5acSUsama Arif * 5000c7d5acSUsama Arif * Main job of this routine is to distinguish between a cold and warm 5100c7d5acSUsama Arif * boot. 5200c7d5acSUsama Arif * --------------------------------------------------------------------- 5300c7d5acSUsama Arif */ 5400c7d5acSUsama Ariffunc plat_get_my_entrypoint 5500c7d5acSUsama Arif /* TODO support warm boot */ 5600c7d5acSUsama Arif /* Cold reset */ 5700c7d5acSUsama Arif mov r0, #0 5800c7d5acSUsama Arif bx lr 5900c7d5acSUsama Arif 6000c7d5acSUsama Arifendfunc plat_get_my_entrypoint 6100c7d5acSUsama Arif 6200c7d5acSUsama Arif /* ----------------------------------------------------- 6300c7d5acSUsama Arif * unsigned int plat_is_my_cpu_primary (void); 6400c7d5acSUsama Arif * 6500c7d5acSUsama Arif * Find out whether the current cpu is the primary 6600c7d5acSUsama Arif * cpu. 6700c7d5acSUsama Arif * ----------------------------------------------------- 6800c7d5acSUsama Arif */ 6900c7d5acSUsama Ariffunc plat_is_my_cpu_primary 7000c7d5acSUsama Arif ldcopr r0, MPIDR 7100c7d5acSUsama Arif ldr r1, =MPIDR_AFFINITY_MASK 7200c7d5acSUsama Arif and r0, r1 7300c7d5acSUsama Arif cmp r0, #0 7400c7d5acSUsama Arif moveq r0, #1 7500c7d5acSUsama Arif movne r0, #0 7600c7d5acSUsama Arif bx lr 7700c7d5acSUsama Arifendfunc plat_is_my_cpu_primary 78*e231f3a5SUsama Arif 79*e231f3a5SUsama Arif /* --------------------------------------------------------------------- 80*e231f3a5SUsama Arif * Loads MPIDR in r0 and calls plat_arm_calc_core_pos 81*e231f3a5SUsama Arif * --------------------------------------------------------------------- 82*e231f3a5SUsama Arif */ 83*e231f3a5SUsama Ariffunc plat_my_core_pos 84*e231f3a5SUsama Arif ldcopr r0, MPIDR 85*e231f3a5SUsama Arif b plat_arm_calc_core_pos 86*e231f3a5SUsama Arif 87*e231f3a5SUsama Arifendfunc plat_my_core_pos 88*e231f3a5SUsama Arif 89*e231f3a5SUsama Arif /* --------------------------------------------------------------------- 90*e231f3a5SUsama Arif * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) 91*e231f3a5SUsama Arif * 92*e231f3a5SUsama Arif * Function to calculate the core position on A5DS. 93*e231f3a5SUsama Arif * 94*e231f3a5SUsama Arif * (ClusterId * A5DS_MAX_CPUS_PER_CLUSTER * A5DS_MAX_PE_PER_CPU) + 95*e231f3a5SUsama Arif * (CPUId * A5DS_MAX_PE_PER_CPU) + 96*e231f3a5SUsama Arif * ThreadId 97*e231f3a5SUsama Arif * 98*e231f3a5SUsama Arif * which can be simplified as: 99*e231f3a5SUsama Arif * 100*e231f3a5SUsama Arif * ((ClusterId * A5DS_MAX_CPUS_PER_CLUSTER + CPUId) * A5DS_MAX_PE_PER_CPU) 101*e231f3a5SUsama Arif * + ThreadId 102*e231f3a5SUsama Arif * --------------------------------------------------------------------- 103*e231f3a5SUsama Arif */ 104*e231f3a5SUsama Ariffunc plat_arm_calc_core_pos 105*e231f3a5SUsama Arif mov r3, r0 106*e231f3a5SUsama Arif 107*e231f3a5SUsama Arif /* 108*e231f3a5SUsama Arif * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it 109*e231f3a5SUsama Arif * look as if in a multi-threaded implementation 110*e231f3a5SUsama Arif */ 111*e231f3a5SUsama Arif tst r0, #MPIDR_MT_MASK 112*e231f3a5SUsama Arif lsleq r3, r0, #MPIDR_AFFINITY_BITS 113*e231f3a5SUsama Arif 114*e231f3a5SUsama Arif /* Extract individual affinity fields from MPIDR */ 115*e231f3a5SUsama Arif ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS 116*e231f3a5SUsama Arif ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS 117*e231f3a5SUsama Arif ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS 118*e231f3a5SUsama Arif 119*e231f3a5SUsama Arif /* Compute linear position */ 120*e231f3a5SUsama Arif mov r3, #A5DS_MAX_CPUS_PER_CLUSTER 121*e231f3a5SUsama Arif mla r1, r2, r3, r1 122*e231f3a5SUsama Arif mov r3, #A5DS_MAX_PE_PER_CPU 123*e231f3a5SUsama Arif mla r0, r1, r3, r0 124*e231f3a5SUsama Arif 125*e231f3a5SUsama Arif bx lr 126*e231f3a5SUsama Arifendfunc plat_arm_calc_core_pos 127