1*91f16700Schasinglulu/* 2*91f16700Schasinglulu * Copyright (c) 2015-2020, 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 <assert_macros.S> 10*91f16700Schasinglulu#include <platform_def.h> 11*91f16700Schasinglulu#include <cortex_a72.h> 12*91f16700Schasinglulu 13*91f16700Schasinglulu .globl plat_crash_console_flush 14*91f16700Schasinglulu .globl plat_crash_console_init 15*91f16700Schasinglulu .globl plat_crash_console_putc 16*91f16700Schasinglulu .globl platform_mem_init 17*91f16700Schasinglulu .globl plat_get_my_entrypoint 18*91f16700Schasinglulu .globl plat_is_my_cpu_primary 19*91f16700Schasinglulu .globl plat_my_core_pos 20*91f16700Schasinglulu .globl plat_reset_handler 21*91f16700Schasinglulu .globl plat_rpi3_calc_core_pos 22*91f16700Schasinglulu .globl plat_secondary_cold_boot_setup 23*91f16700Schasinglulu .globl plat_rpi_get_model 24*91f16700Schasinglulu 25*91f16700Schasinglulu /* ----------------------------------------------------- 26*91f16700Schasinglulu * unsigned int plat_my_core_pos(void) 27*91f16700Schasinglulu * 28*91f16700Schasinglulu * This function uses the plat_rpi3_calc_core_pos() 29*91f16700Schasinglulu * definition to get the index of the calling CPU. 30*91f16700Schasinglulu * ----------------------------------------------------- 31*91f16700Schasinglulu */ 32*91f16700Schasinglulufunc plat_my_core_pos 33*91f16700Schasinglulu mrs x0, mpidr_el1 34*91f16700Schasinglulu b plat_rpi3_calc_core_pos 35*91f16700Schasingluluendfunc plat_my_core_pos 36*91f16700Schasinglulu 37*91f16700Schasinglulu /* ----------------------------------------------------- 38*91f16700Schasinglulu * unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr); 39*91f16700Schasinglulu * 40*91f16700Schasinglulu * CorePos = (ClusterId * 4) + CoreId 41*91f16700Schasinglulu * ----------------------------------------------------- 42*91f16700Schasinglulu */ 43*91f16700Schasinglulufunc plat_rpi3_calc_core_pos 44*91f16700Schasinglulu and x1, x0, #MPIDR_CPU_MASK 45*91f16700Schasinglulu and x0, x0, #MPIDR_CLUSTER_MASK 46*91f16700Schasinglulu add x0, x1, x0, LSR #6 47*91f16700Schasinglulu ret 48*91f16700Schasingluluendfunc plat_rpi3_calc_core_pos 49*91f16700Schasinglulu 50*91f16700Schasinglulu /* ----------------------------------------------------- 51*91f16700Schasinglulu * unsigned int plat_is_my_cpu_primary (void); 52*91f16700Schasinglulu * 53*91f16700Schasinglulu * Find out whether the current cpu is the primary 54*91f16700Schasinglulu * cpu. 55*91f16700Schasinglulu * ----------------------------------------------------- 56*91f16700Schasinglulu */ 57*91f16700Schasinglulufunc plat_is_my_cpu_primary 58*91f16700Schasinglulu mrs x0, mpidr_el1 59*91f16700Schasinglulu and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) 60*91f16700Schasinglulu cmp x0, #RPI_PRIMARY_CPU 61*91f16700Schasinglulu cset w0, eq 62*91f16700Schasinglulu ret 63*91f16700Schasingluluendfunc plat_is_my_cpu_primary 64*91f16700Schasinglulu 65*91f16700Schasinglulu /* ----------------------------------------------------- 66*91f16700Schasinglulu * void plat_wait_for_warm_boot (void); 67*91f16700Schasinglulu * 68*91f16700Schasinglulu * This function performs any platform specific actions 69*91f16700Schasinglulu * needed for a CPU to be put into holding pen to wait 70*91f16700Schasinglulu * for a warm boot request. 71*91f16700Schasinglulu * The function will never return. 72*91f16700Schasinglulu * ----------------------------------------------------- 73*91f16700Schasinglulu */ 74*91f16700Schasinglulufunc plat_wait_for_warm_boot 75*91f16700Schasinglulu /* 76*91f16700Schasinglulu * Calculate address of our hold entry. 77*91f16700Schasinglulu * As the function will never return, there is no need to save LR. 78*91f16700Schasinglulu */ 79*91f16700Schasinglulu bl plat_my_core_pos 80*91f16700Schasinglulu lsl x0, x0, #3 81*91f16700Schasinglulu mov_imm x2, PLAT_RPI3_TM_HOLD_BASE 82*91f16700Schasinglulu add x0, x0, x2 83*91f16700Schasinglulu /* 84*91f16700Schasinglulu * This code runs way before requesting the warmboot of this core, 85*91f16700Schasinglulu * so it is possible to clear the mailbox before getting a request 86*91f16700Schasinglulu * to boot. 87*91f16700Schasinglulu */ 88*91f16700Schasinglulu mov x1, PLAT_RPI3_TM_HOLD_STATE_WAIT 89*91f16700Schasinglulu str x1,[x0] 90*91f16700Schasinglulu 91*91f16700Schasinglulu /* Wait until we have a go */ 92*91f16700Schasinglulupoll_mailbox: 93*91f16700Schasinglulu wfe 94*91f16700Schasinglulu ldr x1, [x0] 95*91f16700Schasinglulu cmp x1, PLAT_RPI3_TM_HOLD_STATE_GO 96*91f16700Schasinglulu bne poll_mailbox 97*91f16700Schasinglulu 98*91f16700Schasinglulu /* Jump to the provided entrypoint */ 99*91f16700Schasinglulu mov_imm x0, PLAT_RPI3_TM_ENTRYPOINT 100*91f16700Schasinglulu ldr x1, [x0] 101*91f16700Schasinglulu br x1 102*91f16700Schasingluluendfunc plat_wait_for_warm_boot 103*91f16700Schasinglulu 104*91f16700Schasinglulu /* ----------------------------------------------------- 105*91f16700Schasinglulu * void plat_secondary_cold_boot_setup (void); 106*91f16700Schasinglulu * 107*91f16700Schasinglulu * This function performs any platform specific actions 108*91f16700Schasinglulu * needed for a secondary cpu after a cold reset e.g 109*91f16700Schasinglulu * mark the cpu's presence, mechanism to place it in a 110*91f16700Schasinglulu * holding pen etc. 111*91f16700Schasinglulu * ----------------------------------------------------- 112*91f16700Schasinglulu */ 113*91f16700Schasinglulufunc plat_secondary_cold_boot_setup 114*91f16700Schasinglulu b plat_wait_for_warm_boot 115*91f16700Schasingluluendfunc plat_secondary_cold_boot_setup 116*91f16700Schasinglulu 117*91f16700Schasinglulu /* --------------------------------------------------------------------- 118*91f16700Schasinglulu * uintptr_t plat_get_my_entrypoint (void); 119*91f16700Schasinglulu * 120*91f16700Schasinglulu * Main job of this routine is to distinguish between a cold and a warm 121*91f16700Schasinglulu * boot. 122*91f16700Schasinglulu * 123*91f16700Schasinglulu * This functions returns: 124*91f16700Schasinglulu * - 0 for a cold boot. 125*91f16700Schasinglulu * - Any other value for a warm boot. 126*91f16700Schasinglulu * --------------------------------------------------------------------- 127*91f16700Schasinglulu */ 128*91f16700Schasinglulufunc plat_get_my_entrypoint 129*91f16700Schasinglulu mov x1, x30 130*91f16700Schasinglulu bl plat_is_my_cpu_primary 131*91f16700Schasinglulu /* 132*91f16700Schasinglulu * Secondaries always cold boot. 133*91f16700Schasinglulu */ 134*91f16700Schasinglulu cbz w0, 1f 135*91f16700Schasinglulu /* 136*91f16700Schasinglulu * Primaries warm boot if they are requested 137*91f16700Schasinglulu * to power off. 138*91f16700Schasinglulu */ 139*91f16700Schasinglulu mov_imm x0, PLAT_RPI3_TM_HOLD_BASE 140*91f16700Schasinglulu ldr x0, [x0] 141*91f16700Schasinglulu cmp x0, PLAT_RPI3_TM_HOLD_STATE_BSP_OFF 142*91f16700Schasinglulu adr x0, plat_wait_for_warm_boot 143*91f16700Schasinglulu csel x0, x0, xzr, eq 144*91f16700Schasinglulu ret x1 145*91f16700Schasinglulu1: mov x0, #0 146*91f16700Schasinglulu ret x1 147*91f16700Schasingluluendfunc plat_get_my_entrypoint 148*91f16700Schasinglulu 149*91f16700Schasinglulu /* --------------------------------------------- 150*91f16700Schasinglulu * void platform_mem_init (void); 151*91f16700Schasinglulu * 152*91f16700Schasinglulu * No need to carry out any memory initialization. 153*91f16700Schasinglulu * --------------------------------------------- 154*91f16700Schasinglulu */ 155*91f16700Schasinglulufunc platform_mem_init 156*91f16700Schasinglulu ret 157*91f16700Schasingluluendfunc platform_mem_init 158*91f16700Schasinglulu 159*91f16700Schasinglulu /* --------------------------------------------- 160*91f16700Schasinglulu * int plat_crash_console_init(void) 161*91f16700Schasinglulu * Function to initialize the crash console 162*91f16700Schasinglulu * without a C Runtime to print crash report. 163*91f16700Schasinglulu * Clobber list : x0 - x3 164*91f16700Schasinglulu * --------------------------------------------- 165*91f16700Schasinglulu */ 166*91f16700Schasinglulufunc plat_crash_console_init 167*91f16700Schasinglulu mov_imm x0, PLAT_RPI_MINI_UART_BASE 168*91f16700Schasinglulu mov x1, xzr 169*91f16700Schasinglulu mov x2, xzr 170*91f16700Schasinglulu b console_16550_core_init 171*91f16700Schasingluluendfunc plat_crash_console_init 172*91f16700Schasinglulu 173*91f16700Schasinglulu /* --------------------------------------------- 174*91f16700Schasinglulu * int plat_crash_console_putc(int c) 175*91f16700Schasinglulu * Function to print a character on the crash 176*91f16700Schasinglulu * console without a C Runtime. 177*91f16700Schasinglulu * Clobber list : x1, x2 178*91f16700Schasinglulu * --------------------------------------------- 179*91f16700Schasinglulu */ 180*91f16700Schasinglulufunc plat_crash_console_putc 181*91f16700Schasinglulu mov_imm x1, PLAT_RPI_MINI_UART_BASE 182*91f16700Schasinglulu b console_16550_core_putc 183*91f16700Schasingluluendfunc plat_crash_console_putc 184*91f16700Schasinglulu 185*91f16700Schasinglulu /* --------------------------------------------- 186*91f16700Schasinglulu * void plat_crash_console_flush() 187*91f16700Schasinglulu * Function to force a write of all buffered 188*91f16700Schasinglulu * data that hasn't been output. 189*91f16700Schasinglulu * Out : void. 190*91f16700Schasinglulu * Clobber list : x0, x1 191*91f16700Schasinglulu * --------------------------------------------- 192*91f16700Schasinglulu */ 193*91f16700Schasinglulufunc plat_crash_console_flush 194*91f16700Schasinglulu mov_imm x0, PLAT_RPI_MINI_UART_BASE 195*91f16700Schasinglulu b console_16550_core_flush 196*91f16700Schasingluluendfunc plat_crash_console_flush 197*91f16700Schasinglulu 198*91f16700Schasinglulu /* --------------------------------------------- 199*91f16700Schasinglulu * int plat_rpi_get_model() 200*91f16700Schasinglulu * Macro to determine whether we are running on 201*91f16700Schasinglulu * a Raspberry Pi 3 or 4. Just checks the MIDR for 202*91f16700Schasinglulu * being either a Cortex-A72 or a Cortex-A53. 203*91f16700Schasinglulu * Out : return 4 if RPi4, 3 otherwise. 204*91f16700Schasinglulu * Clobber list : x0 205*91f16700Schasinglulu * --------------------------------------------- 206*91f16700Schasinglulu */ 207*91f16700Schasinglulu .macro _plat_rpi_get_model 208*91f16700Schasinglulu mrs x0, midr_el1 209*91f16700Schasinglulu and x0, x0, #0xf0 /* Isolate low byte of part number */ 210*91f16700Schasinglulu cmp w0, #0x80 /* Cortex-A72 (RPi4) is 0xd08, A53 is 0xd03 */ 211*91f16700Schasinglulu mov w0, #3 212*91f16700Schasinglulu csinc w0, w0, w0, ne 213*91f16700Schasinglulu .endm 214*91f16700Schasinglulu 215*91f16700Schasinglulu func plat_rpi_get_model 216*91f16700Schasinglulu _plat_rpi_get_model 217*91f16700Schasinglulu ret 218*91f16700Schasinglulu endfunc plat_rpi_get_model 219*91f16700Schasinglulu 220*91f16700Schasinglulu /* --------------------------------------------- 221*91f16700Schasinglulu * void plat_reset_handler(void); 222*91f16700Schasinglulu * --------------------------------------------- 223*91f16700Schasinglulu */ 224*91f16700Schasinglulufunc plat_reset_handler 225*91f16700Schasinglulu /* L2 cache setup only needed on RPi4 */ 226*91f16700Schasinglulu _plat_rpi_get_model 227*91f16700Schasinglulu cmp w0, #4 228*91f16700Schasinglulu b.ne 1f 229*91f16700Schasinglulu 230*91f16700Schasinglulu /* ------------------------------------------------ 231*91f16700Schasinglulu * Set L2 read/write cache latency: 232*91f16700Schasinglulu * - L2 Data RAM latency: 3 cycles (0b010) 233*91f16700Schasinglulu * - L2 Data RAM setup: 1 cycle (bit 5) 234*91f16700Schasinglulu * ------------------------------------------------ 235*91f16700Schasinglulu */ 236*91f16700Schasinglulu mrs x0, CORTEX_A72_L2CTLR_EL1 237*91f16700Schasinglulu mov x1, #0x22 238*91f16700Schasinglulu orr x0, x0, x1 239*91f16700Schasinglulu msr CORTEX_A72_L2CTLR_EL1, x0 240*91f16700Schasinglulu isb 241*91f16700Schasinglulu 242*91f16700Schasinglulu1: 243*91f16700Schasinglulu ret 244*91f16700Schasingluluendfunc plat_reset_handler 245