1*91f16700Schasinglulu/* 2*91f16700Schasinglulu * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. 4*91f16700Schasinglulu * 5*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu#include <arch.h> 9*91f16700Schasinglulu#include <asm_macros.S> 10*91f16700Schasinglulu#include <common/bl_common.h> 11*91f16700Schasinglulu#include <common/runtime_svc.h> 12*91f16700Schasinglulu#include <cortex_a57.h> 13*91f16700Schasinglulu#include <platform_def.h> 14*91f16700Schasinglulu 15*91f16700Schasinglulu#include "rcar_def.h" 16*91f16700Schasinglulu 17*91f16700Schasinglulu .globl plat_get_my_entrypoint 18*91f16700Schasinglulu .extern plat_set_my_stack 19*91f16700Schasinglulu .globl platform_mem_init 20*91f16700Schasinglulu 21*91f16700Schasinglulu .globl plat_crash_console_init 22*91f16700Schasinglulu .globl plat_crash_console_putc 23*91f16700Schasinglulu .globl plat_crash_console_flush 24*91f16700Schasinglulu .globl plat_invalidate_icache 25*91f16700Schasinglulu .globl plat_report_exception 26*91f16700Schasinglulu .globl plat_secondary_reset 27*91f16700Schasinglulu .globl plat_reset_handler 28*91f16700Schasinglulu .globl plat_my_core_pos 29*91f16700Schasinglulu .extern rcar_log_init 30*91f16700Schasinglulu 31*91f16700Schasinglulu .extern console_rcar_init 32*91f16700Schasinglulu .extern console_rcar_putc 33*91f16700Schasinglulu .extern console_rcar_flush 34*91f16700Schasinglulu 35*91f16700Schasinglulu#if IMAGE_BL2 36*91f16700Schasinglulu #define INT_ID_MASK (0x3ff) 37*91f16700Schasinglulu .extern bl2_interrupt_error_type 38*91f16700Schasinglulu .extern bl2_interrupt_error_id 39*91f16700Schasinglulu .globl bl2_enter_bl31 40*91f16700Schasinglulu .extern gicv2_acknowledge_interrupt 41*91f16700Schasinglulu .extern rcar_swdt_exec 42*91f16700Schasinglulu#endif 43*91f16700Schasinglulu 44*91f16700Schasinglulu /* ----------------------------------------------------- 45*91f16700Schasinglulu * void platform_get_core_pos (mpidr) 46*91f16700Schasinglulu * ----------------------------------------------------- 47*91f16700Schasinglulu */ 48*91f16700Schasinglulufunc platform_get_core_pos 49*91f16700Schasinglulu and x1, x0, #MPIDR_CPU_MASK 50*91f16700Schasinglulu and x0, x0, #MPIDR_CLUSTER_MASK 51*91f16700Schasinglulu add x0, x1, x0, LSR #6 52*91f16700Schasinglulu ret 53*91f16700Schasingluluendfunc platform_get_core_pos 54*91f16700Schasinglulu 55*91f16700Schasinglulu /* ----------------------------------------------------- 56*91f16700Schasinglulu * void platform_my_core_pos 57*91f16700Schasinglulu * ----------------------------------------------------- 58*91f16700Schasinglulu */ 59*91f16700Schasinglulufunc plat_my_core_pos 60*91f16700Schasinglulu mrs x0, mpidr_el1 61*91f16700Schasinglulu b platform_get_core_pos 62*91f16700Schasingluluendfunc plat_my_core_pos 63*91f16700Schasinglulu 64*91f16700Schasinglulu /* ----------------------------------------------------- 65*91f16700Schasinglulu * void platform_get_my_entrypoint (unsigned int mpid); 66*91f16700Schasinglulu * 67*91f16700Schasinglulu * Main job of this routine is to distinguish between 68*91f16700Schasinglulu * a cold and warm boot. 69*91f16700Schasinglulu * On a cold boot the secondaries first wait for the 70*91f16700Schasinglulu * platform to be initialized after which they are 71*91f16700Schasinglulu * hotplugged in. The primary proceeds to perform the 72*91f16700Schasinglulu * platform initialization. 73*91f16700Schasinglulu * On a warm boot, each cpu jumps to the address in its 74*91f16700Schasinglulu * mailbox. 75*91f16700Schasinglulu * 76*91f16700Schasinglulu * TODO: Not a good idea to save lr in a temp reg 77*91f16700Schasinglulu * ----------------------------------------------------- 78*91f16700Schasinglulu */ 79*91f16700Schasinglulufunc plat_get_my_entrypoint 80*91f16700Schasinglulu mrs x0, mpidr_el1 81*91f16700Schasinglulu mov x9, x30 /* lr */ 82*91f16700Schasinglulu 83*91f16700Schasinglulu#if defined(IMAGE_BL2) 84*91f16700Schasinglulu /* always cold boot on bl2 */ 85*91f16700Schasinglulu mov x0, #0 86*91f16700Schasinglulu ret x9 87*91f16700Schasinglulu#else 88*91f16700Schasinglulu ldr x1, =BOOT_KIND_BASE 89*91f16700Schasinglulu ldr x21, [x1] 90*91f16700Schasinglulu 91*91f16700Schasinglulu /* Check the reset info */ 92*91f16700Schasinglulu and x1, x21, #0x000c 93*91f16700Schasinglulu cmp x1, #0x0008 94*91f16700Schasinglulu beq el3_panic 95*91f16700Schasinglulu cmp x1, #0x000c 96*91f16700Schasinglulu beq el3_panic 97*91f16700Schasinglulu 98*91f16700Schasinglulu /* Check the boot kind */ 99*91f16700Schasinglulu and x1, x21, #0x0003 100*91f16700Schasinglulu cmp x1, #0x0002 101*91f16700Schasinglulu beq el3_panic 102*91f16700Schasinglulu cmp x1, #0x0003 103*91f16700Schasinglulu beq el3_panic 104*91f16700Schasinglulu 105*91f16700Schasinglulu /* warm boot or cold boot */ 106*91f16700Schasinglulu and x1, x21, #1 107*91f16700Schasinglulu cmp x1, #0 108*91f16700Schasinglulu bne warm_reset 109*91f16700Schasinglulu 110*91f16700Schasinglulu /* Cold boot */ 111*91f16700Schasinglulu mov x0, #0 112*91f16700Schasinglulu b exit 113*91f16700Schasinglulu 114*91f16700Schasingluluwarm_reset: 115*91f16700Schasinglulu /* -------------------------------------------------------------------- 116*91f16700Schasinglulu * A per-cpu mailbox is maintained in the trusted SDRAM. Its flushed out 117*91f16700Schasinglulu * of the caches after every update using normal memory so its safe to 118*91f16700Schasinglulu * read it here with SO attributes 119*91f16700Schasinglulu * --------------------------------------------------------------------- 120*91f16700Schasinglulu */ 121*91f16700Schasinglulu ldr x10, =MBOX_BASE 122*91f16700Schasinglulu bl platform_get_core_pos 123*91f16700Schasinglulu lsl x0, x0, #CACHE_WRITEBACK_SHIFT 124*91f16700Schasinglulu ldr x0, [x10, x0] 125*91f16700Schasinglulu cbz x0, _panic 126*91f16700Schasingluluexit: 127*91f16700Schasinglulu ret x9 128*91f16700Schasinglulu_panic: 129*91f16700Schasinglulu b el3_panic 130*91f16700Schasinglulu#endif 131*91f16700Schasinglulu 132*91f16700Schasingluluendfunc plat_get_my_entrypoint 133*91f16700Schasinglulu 134*91f16700Schasinglulu /* --------------------------------------------- 135*91f16700Schasinglulu * plat_secondary_reset 136*91f16700Schasinglulu * 137*91f16700Schasinglulu * --------------------------------------------- 138*91f16700Schasinglulu */ 139*91f16700Schasinglulufunc plat_secondary_reset 140*91f16700Schasinglulu mrs x0, sctlr_el3 141*91f16700Schasinglulu bic x0, x0, #SCTLR_EE_BIT 142*91f16700Schasinglulu msr sctlr_el3, x0 143*91f16700Schasinglulu isb 144*91f16700Schasinglulu 145*91f16700Schasinglulu mrs x0, cptr_el3 146*91f16700Schasinglulu bic w0, w0, #TCPAC_BIT 147*91f16700Schasinglulu bic w0, w0, #TTA_BIT 148*91f16700Schasinglulu bic w0, w0, #TFP_BIT 149*91f16700Schasinglulu msr cptr_el3, x0 150*91f16700Schasinglulu 151*91f16700Schasinglulu mov_imm x0, PARAMS_BASE 152*91f16700Schasinglulu mov_imm x2, BL31_BASE 153*91f16700Schasinglulu ldr x3, =BOOT_KIND_BASE 154*91f16700Schasinglulu mov x1, #0x1 155*91f16700Schasinglulu str x1, [x3] 156*91f16700Schasinglulu br x2 /* jump to BL31 */ 157*91f16700Schasinglulu nop 158*91f16700Schasinglulu nop 159*91f16700Schasinglulu nop 160*91f16700Schasingluluendfunc plat_secondary_reset 161*91f16700Schasinglulu 162*91f16700Schasinglulu /* --------------------------------------------- 163*91f16700Schasinglulu * plat_enter_bl31 164*91f16700Schasinglulu * 165*91f16700Schasinglulu * --------------------------------------------- 166*91f16700Schasinglulu */ 167*91f16700Schasinglulufunc bl2_enter_bl31 168*91f16700Schasinglulu mov x20, x0 169*91f16700Schasinglulu /* 170*91f16700Schasinglulu * MMU needs to be disabled because both BL2 and BL31 execute 171*91f16700Schasinglulu * in EL3, and therefore share the same address space. 172*91f16700Schasinglulu * BL31 will initialize the address space according to its 173*91f16700Schasinglulu * own requirement. 174*91f16700Schasinglulu */ 175*91f16700Schasinglulu#if RCAR_BL2_DCACHE == 1 176*91f16700Schasinglulu /* Disable mmu and data cache */ 177*91f16700Schasinglulu bl disable_mmu_el3 178*91f16700Schasinglulu /* Data cache clean and invalidate */ 179*91f16700Schasinglulu mov x0, #DCCISW 180*91f16700Schasinglulu bl dcsw_op_all 181*91f16700Schasinglulu /* TLB invalidate all, EL3 */ 182*91f16700Schasinglulu tlbi alle3 183*91f16700Schasinglulu#endif /* RCAR_BL2_DCACHE == 1 */ 184*91f16700Schasinglulu bl disable_mmu_icache_el3 185*91f16700Schasinglulu /* Invalidate instruction cache */ 186*91f16700Schasinglulu ic iallu 187*91f16700Schasinglulu dsb sy 188*91f16700Schasinglulu isb 189*91f16700Schasinglulu ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET] 190*91f16700Schasinglulu msr elr_el3, x0 191*91f16700Schasinglulu msr spsr_el3, x1 192*91f16700Schasinglulu exception_return 193*91f16700Schasingluluendfunc bl2_enter_bl31 194*91f16700Schasinglulu 195*91f16700Schasinglulu /* ----------------------------------------------------- 196*91f16700Schasinglulu * void platform_mem_init (void); 197*91f16700Schasinglulu * 198*91f16700Schasinglulu * Zero out the mailbox registers in the shared memory 199*91f16700Schasinglulu * and set the rcar_boot_kind_flag. 200*91f16700Schasinglulu * The mmu is turned off right now and only the primary can 201*91f16700Schasinglulu * ever execute this code. Secondaries will read the 202*91f16700Schasinglulu * mailboxes using SO accesses. 203*91f16700Schasinglulu * ----------------------------------------------------- 204*91f16700Schasinglulu */ 205*91f16700Schasinglulufunc platform_mem_init 206*91f16700Schasinglulu#if !IMAGE_BL2 207*91f16700Schasinglulu ldr x0, =MBOX_BASE 208*91f16700Schasinglulu mov w1, #PLATFORM_CORE_COUNT 209*91f16700Schasinglululoop: 210*91f16700Schasinglulu str xzr, [x0], #CACHE_WRITEBACK_GRANULE 211*91f16700Schasinglulu subs w1, w1, #1 212*91f16700Schasinglulu b.gt loop 213*91f16700Schasinglulu#endif 214*91f16700Schasinglulu ret 215*91f16700Schasingluluendfunc platform_mem_init 216*91f16700Schasinglulu 217*91f16700Schasinglulu /* --------------------------------------------- 218*91f16700Schasinglulu * void plat_report_exception(unsigned int type) 219*91f16700Schasinglulu * Function to report an unhandled exception 220*91f16700Schasinglulu * with platform-specific means. 221*91f16700Schasinglulu * --------------------------------------------- 222*91f16700Schasinglulu */ 223*91f16700Schasinglulufunc plat_report_exception 224*91f16700Schasinglulu /* Switch to SP_EL0 */ 225*91f16700Schasinglulu msr spsel, #0 226*91f16700Schasinglulu#if IMAGE_BL2 227*91f16700Schasinglulu mov w1, #FIQ_SP_EL0 228*91f16700Schasinglulu cmp w0, w1 229*91f16700Schasinglulu beq rep_exec_fiq_elx 230*91f16700Schasinglulu b rep_exec_panic_type 231*91f16700Schasinglulurep_exec_fiq_elx: 232*91f16700Schasinglulu bl gicv2_acknowledge_interrupt 233*91f16700Schasinglulu mov x2, #INT_ID_MASK 234*91f16700Schasinglulu and x0, x0, x2 235*91f16700Schasinglulu mov x1, #ARM_IRQ_SEC_WDT 236*91f16700Schasinglulu cmp x0, x1 237*91f16700Schasinglulu bne rep_exec_panic_id 238*91f16700Schasinglulu mrs x0, ELR_EL3 239*91f16700Schasinglulu b rcar_swdt_exec 240*91f16700Schasinglulurep_exec_panic_type: 241*91f16700Schasinglulu /* x0 is interrupt TYPE */ 242*91f16700Schasinglulu b bl2_interrupt_error_type 243*91f16700Schasinglulurep_exec_panic_id: 244*91f16700Schasinglulu /* x0 is interrupt ID */ 245*91f16700Schasinglulu b bl2_interrupt_error_id 246*91f16700Schasinglulurep_exec_end: 247*91f16700Schasinglulu#endif 248*91f16700Schasinglulu ret 249*91f16700Schasingluluendfunc plat_report_exception 250*91f16700Schasinglulu 251*91f16700Schasinglulu /* --------------------------------------------- 252*91f16700Schasinglulu * int plat_crash_console_init(void) 253*91f16700Schasinglulu * Function to initialize log area 254*91f16700Schasinglulu * --------------------------------------------- 255*91f16700Schasinglulu */ 256*91f16700Schasinglulufunc plat_crash_console_init 257*91f16700Schasinglulu#if IMAGE_BL2 258*91f16700Schasinglulu mov x0, #0 259*91f16700Schasinglulu#else 260*91f16700Schasinglulu mov x1, sp 261*91f16700Schasinglulu mov_imm x2, RCAR_CRASH_STACK 262*91f16700Schasinglulu mov sp, x2 263*91f16700Schasinglulu str x1, [sp, #-16]! 264*91f16700Schasinglulu str x30, [sp, #-16]! 265*91f16700Schasinglulu bl console_rcar_init 266*91f16700Schasinglulu ldr x30, [sp], #16 267*91f16700Schasinglulu ldr x1, [sp], #16 268*91f16700Schasinglulu mov sp, x1 269*91f16700Schasinglulu#endif 270*91f16700Schasinglulu ret 271*91f16700Schasingluluendfunc plat_crash_console_init 272*91f16700Schasinglulu 273*91f16700Schasinglulu /* --------------------------------------------- 274*91f16700Schasinglulu * int plat_crash_console_putc(int c) 275*91f16700Schasinglulu * Function to store a character to log area 276*91f16700Schasinglulu * --------------------------------------------- 277*91f16700Schasinglulu */ 278*91f16700Schasinglulufunc plat_crash_console_putc 279*91f16700Schasinglulu mov x1, sp 280*91f16700Schasinglulu mov_imm x2, RCAR_CRASH_STACK 281*91f16700Schasinglulu mov sp, x2 282*91f16700Schasinglulu str x1, [sp, #-16]! 283*91f16700Schasinglulu str x30, [sp, #-16]! 284*91f16700Schasinglulu str x3, [sp, #-16]! 285*91f16700Schasinglulu str x4, [sp, #-16]! 286*91f16700Schasinglulu str x5, [sp, #-16]! 287*91f16700Schasinglulu str x6, [sp, #-16]! 288*91f16700Schasinglulu str x7, [sp, #-16]! 289*91f16700Schasinglulu bl console_rcar_putc 290*91f16700Schasinglulu ldr x7, [sp], #16 291*91f16700Schasinglulu ldr x6, [sp], #16 292*91f16700Schasinglulu ldr x5, [sp], #16 293*91f16700Schasinglulu ldr x4, [sp], #16 294*91f16700Schasinglulu ldr x3, [sp], #16 295*91f16700Schasinglulu ldr x30, [sp], #16 296*91f16700Schasinglulu ldr x1, [sp], #16 297*91f16700Schasinglulu mov sp, x1 298*91f16700Schasinglulu ret 299*91f16700Schasingluluendfunc plat_crash_console_putc 300*91f16700Schasinglulu 301*91f16700Schasinglulu /* --------------------------------------------- 302*91f16700Schasinglulu * void plat_crash_console_flush() 303*91f16700Schasinglulu * --------------------------------------------- 304*91f16700Schasinglulu */ 305*91f16700Schasinglulufunc plat_crash_console_flush 306*91f16700Schasinglulu b console_rcar_flush 307*91f16700Schasingluluendfunc plat_crash_console_flush 308*91f16700Schasinglulu 309*91f16700Schasinglulu /* -------------------------------------------------------------------- 310*91f16700Schasinglulu * void plat_reset_handler(void); 311*91f16700Schasinglulu * 312*91f16700Schasinglulu * Before adding code in this function, refer to the guidelines in 313*91f16700Schasinglulu * docs/firmware-design.md to determine whether the code should reside 314*91f16700Schasinglulu * within the FIRST_RESET_HANDLER_CALL block or not. 315*91f16700Schasinglulu * 316*91f16700Schasinglulu * For R-Car H3: 317*91f16700Schasinglulu * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 318*91f16700Schasinglulu * - Set the L2 Data setup latency to 1 (i.e. 1 cycles) for Cortex-A57 319*91f16700Schasinglulu * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57 320*91f16700Schasinglulu * For R-Car M3/M3N: 321*91f16700Schasinglulu * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57 322*91f16700Schasinglulu * - Set the L2 Data setup latency to 0 (i.e. 0 cycles) for Cortex-A57 323*91f16700Schasinglulu * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57 324*91f16700Schasinglulu * 325*91f16700Schasinglulu * -------------------------------------------------------------------- 326*91f16700Schasinglulu */ 327*91f16700Schasinglulufunc plat_reset_handler 328*91f16700Schasinglulu /* 329*91f16700Schasinglulu * On R-Car H3 : x2 := 0 330*91f16700Schasinglulu * On R-Car M3/M3N: x2 := 1 331*91f16700Schasinglulu */ 332*91f16700Schasinglulu /* read PRR */ 333*91f16700Schasinglulu ldr x0, =0xFFF00044 334*91f16700Schasinglulu ldr w0, [x0] 335*91f16700Schasinglulu ubfx w0, w0, 8, 8 336*91f16700Schasinglulu /* H3? */ 337*91f16700Schasinglulu cmp w0, #0x4F 338*91f16700Schasinglulu b.eq RCARH3 339*91f16700Schasinglulu /* set R-Car M3/M3N */ 340*91f16700Schasinglulu mov x2, #1 341*91f16700Schasinglulu b CHK_A5x 342*91f16700SchasingluluRCARH3: 343*91f16700Schasinglulu /* set R-Car H3 */ 344*91f16700Schasinglulu mov x2, #0 345*91f16700Schasinglulu /* -------------------------------------------------------------------- 346*91f16700Schasinglulu * Determine whether this code is executed on a Cortex-A53 or on a 347*91f16700Schasinglulu * Cortex-A57 core. 348*91f16700Schasinglulu * -------------------------------------------------------------------- 349*91f16700Schasinglulu */ 350*91f16700SchasingluluCHK_A5x: 351*91f16700Schasinglulu mrs x0, midr_el1 352*91f16700Schasinglulu ubfx x1, x0, MIDR_PN_SHIFT, #12 353*91f16700Schasinglulu cmp w1, #((CORTEX_A57_MIDR >> MIDR_PN_SHIFT) & MIDR_PN_MASK) 354*91f16700Schasinglulu b.eq A57 355*91f16700Schasinglulu ret 356*91f16700SchasingluluA57: 357*91f16700Schasinglulu /* Get data from CORTEX_A57_L2CTLR_EL1 */ 358*91f16700Schasinglulu mrs x0, CORTEX_A57_L2CTLR_EL1 359*91f16700Schasinglulu /* 360*91f16700Schasinglulu * On R-Car H3/M3/M3N 361*91f16700Schasinglulu * 362*91f16700Schasinglulu * L2 Tag RAM latency is bit8-6 of CORTEX_A57_L2CTLR_EL1 363*91f16700Schasinglulu * L2 Data RAM setup is bit5 of CORTEX_A57_L2CTLR_EL1 364*91f16700Schasinglulu * L2 Data RAM latency is bit2-0 of CORTEX_A57_L2CTLR_EL1 365*91f16700Schasinglulu */ 366*91f16700Schasinglulu /* clear bit of L2 RAM */ 367*91f16700Schasinglulu /* ~(0x1e7) -> x1 */ 368*91f16700Schasinglulu mov x1, #0x1e7 369*91f16700Schasinglulu neg x1, x1 370*91f16700Schasinglulu /* clear bit of L2 RAM -> x0 */ 371*91f16700Schasinglulu and x0, x0, x1 372*91f16700Schasinglulu /* L2 Tag RAM latency (3 cycles) */ 373*91f16700Schasinglulu orr x0, x0, #0x2 << 6 374*91f16700Schasinglulu /* If M3/M3N then L2 RAM setup is 0 */ 375*91f16700Schasinglulu cbnz x2, M3_L2 376*91f16700Schasinglulu /* L2 Data RAM setup (1 cycle) */ 377*91f16700Schasinglulu orr x0, x0, #0x1 << 5 378*91f16700SchasingluluM3_L2: 379*91f16700Schasinglulu /* L2 Data RAM latency (4 cycles) */ 380*91f16700Schasinglulu orr x0, x0, #0x3 381*91f16700Schasinglulu /* Store data to L2CTLR_EL1 */ 382*91f16700Schasinglulu msr CORTEX_A57_L2CTLR_EL1, x0 383*91f16700Schasingluluapply_l2_ram_latencies: 384*91f16700Schasinglulu ret 385*91f16700Schasingluluendfunc plat_reset_handler 386*91f16700Schasinglulu 387*91f16700Schasinglulu /* --------------------------------------------- 388*91f16700Schasinglulu * void plat_invalidate_icache(void) 389*91f16700Schasinglulu * Instruction Cache Invalidate All to PoU 390*91f16700Schasinglulu * --------------------------------------------- 391*91f16700Schasinglulu */ 392*91f16700Schasinglulufunc plat_invalidate_icache 393*91f16700Schasinglulu ic iallu 394*91f16700Schasinglulu 395*91f16700Schasinglulu ret 396*91f16700Schasingluluendfunc plat_invalidate_icache 397