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