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