1/* 2 * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. 3 * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7#include <arch.h> 8#include <asm_macros.S> 9#include <assert_macros.S> 10#include <cpu_macros.S> 11#include <cortex_a53.h> 12#include <cortex_a57.h> 13#include <platform_def.h> 14#include <tegra_def.h> 15#include <tegra_platform.h> 16 17#define MIDR_PN_CORTEX_A57 0xD07 18 19/******************************************************************************* 20 * Implementation defined ACTLR_EL3 bit definitions 21 ******************************************************************************/ 22#define ACTLR_ELx_L2ACTLR_BIT (U(1) << 6) 23#define ACTLR_ELx_L2ECTLR_BIT (U(1) << 5) 24#define ACTLR_ELx_L2CTLR_BIT (U(1) << 4) 25#define ACTLR_ELx_CPUECTLR_BIT (U(1) << 1) 26#define ACTLR_ELx_CPUACTLR_BIT (U(1) << 0) 27#define ACTLR_ELx_ENABLE_ALL_ACCESS (ACTLR_ELx_L2ACTLR_BIT | \ 28 ACTLR_ELx_L2ECTLR_BIT | \ 29 ACTLR_ELx_L2CTLR_BIT | \ 30 ACTLR_ELx_CPUECTLR_BIT | \ 31 ACTLR_ELx_CPUACTLR_BIT) 32 33 /* Global functions */ 34 .globl plat_is_my_cpu_primary 35 .globl plat_my_core_pos 36 .globl plat_get_my_entrypoint 37 .globl plat_secondary_cold_boot_setup 38 .globl platform_mem_init 39 .globl plat_crash_console_init 40 .globl plat_crash_console_putc 41 .globl plat_crash_console_flush 42 .weak plat_core_pos_by_mpidr 43 .globl tegra_secure_entrypoint 44 .globl plat_reset_handler 45 46 /* Global variables */ 47 .globl tegra_sec_entry_point 48 .globl ns_image_entrypoint 49 .globl tegra_bl31_phys_base 50 .globl tegra_console_base 51 52 /* --------------------- 53 * Common CPU init code 54 * --------------------- 55 */ 56.macro cpu_init_common 57 58 /* ------------------------------------------------ 59 * We enable procesor retention, L2/CPUECTLR NS 60 * access and ECC/Parity protection for A57 CPUs 61 * ------------------------------------------------ 62 */ 63 mrs x0, midr_el1 64 mov x1, #(MIDR_PN_MASK << MIDR_PN_SHIFT) 65 and x0, x0, x1 66 lsr x0, x0, #MIDR_PN_SHIFT 67 cmp x0, #MIDR_PN_CORTEX_A57 68 b.ne 1f 69 70 /* --------------------------- 71 * Enable processor retention 72 * --------------------------- 73 */ 74 mrs x0, CORTEX_A57_L2ECTLR_EL1 75 mov x1, #RETENTION_ENTRY_TICKS_512 76 bic x0, x0, #CORTEX_A57_L2ECTLR_RET_CTRL_MASK 77 orr x0, x0, x1 78 msr CORTEX_A57_L2ECTLR_EL1, x0 79 isb 80 81 mrs x0, CORTEX_A57_ECTLR_EL1 82 mov x1, #RETENTION_ENTRY_TICKS_512 83 bic x0, x0, #CORTEX_A57_ECTLR_CPU_RET_CTRL_MASK 84 orr x0, x0, x1 85 msr CORTEX_A57_ECTLR_EL1, x0 86 isb 87 88 /* ------------------------------------------------------- 89 * Enable L2 and CPU ECTLR RW access from non-secure world 90 * ------------------------------------------------------- 91 */ 92 mrs x0, actlr_el3 93 mov x1, #ACTLR_ELx_ENABLE_ALL_ACCESS 94 orr x0, x0, x1 95 msr actlr_el3, x0 96 mrs x0, actlr_el2 97 mov x1, #ACTLR_ELx_ENABLE_ALL_ACCESS 98 orr x0, x0, x1 99 msr actlr_el2, x0 100 isb 101 102 /* -------------------------------- 103 * Enable the cycle count register 104 * -------------------------------- 105 */ 1061: mrs x0, pmcr_el0 107 ubfx x0, x0, #11, #5 // read PMCR.N field 108 mov x1, #1 109 lsl x0, x1, x0 110 sub x0, x0, #1 // mask of event counters 111 orr x0, x0, #0x80000000 // disable overflow intrs 112 msr pmintenclr_el1, x0 113 msr pmuserenr_el0, x1 // enable user mode access 114 115 /* ---------------------------------------------------------------- 116 * Allow non-privileged access to CNTVCT: Set CNTKCTL (Kernel Count 117 * register), bit 1 (EL0VCTEN) to enable access to CNTVCT/CNTFRQ 118 * registers from EL0. 119 * ---------------------------------------------------------------- 120 */ 121 mrs x0, cntkctl_el1 122 orr x0, x0, #EL0VCTEN_BIT 123 msr cntkctl_el1, x0 124.endm 125 126 /* ----------------------------------------------------- 127 * unsigned int plat_is_my_cpu_primary(void); 128 * 129 * This function checks if this is the Primary CPU 130 * ----------------------------------------------------- 131 */ 132func plat_is_my_cpu_primary 133 mrs x0, mpidr_el1 134 and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) 135 cmp x0, #TEGRA_PRIMARY_CPU 136 cset x0, eq 137 ret 138endfunc plat_is_my_cpu_primary 139 140 /* ---------------------------------------------------------- 141 * unsigned int plat_my_core_pos(void); 142 * 143 * result: CorePos = CoreId + (ClusterId * cpus per cluster) 144 * Registers clobbered: x0, x8 145 * ---------------------------------------------------------- 146 */ 147func plat_my_core_pos 148 mov x8, x30 149 mrs x0, mpidr_el1 150 bl plat_core_pos_by_mpidr 151 ret x8 152endfunc plat_my_core_pos 153 154 /* ----------------------------------------------------- 155 * unsigned long plat_get_my_entrypoint (void); 156 * 157 * Main job of this routine is to distinguish between 158 * a cold and warm boot. If the tegra_sec_entry_point for 159 * this CPU is present, then it's a warm boot. 160 * 161 * ----------------------------------------------------- 162 */ 163func plat_get_my_entrypoint 164 adr x1, tegra_sec_entry_point 165 ldr x0, [x1] 166 ret 167endfunc plat_get_my_entrypoint 168 169 /* ----------------------------------------------------- 170 * int platform_get_core_pos(int mpidr); 171 * 172 * result: CorePos = (ClusterId * cpus per cluster) + 173 * CoreId 174 * ----------------------------------------------------- 175 */ 176func platform_get_core_pos 177 and x1, x0, #MPIDR_CPU_MASK 178 and x0, x0, #MPIDR_CLUSTER_MASK 179 lsr x0, x0, #MPIDR_AFFINITY_BITS 180 mov x2, #PLATFORM_MAX_CPUS_PER_CLUSTER 181 mul x0, x0, x2 182 add x0, x1, x0 183 ret 184endfunc platform_get_core_pos 185 186 /* ----------------------------------------------------- 187 * void plat_secondary_cold_boot_setup (void); 188 * 189 * This function performs any platform specific actions 190 * needed for a secondary cpu after a cold reset. Right 191 * now this is a stub function. 192 * ----------------------------------------------------- 193 */ 194func plat_secondary_cold_boot_setup 195 mov x0, #0 196 ret 197endfunc plat_secondary_cold_boot_setup 198 199 /* -------------------------------------------------------- 200 * void platform_mem_init (void); 201 * 202 * Any memory init, relocation to be done before the 203 * platform boots. Called very early in the boot process. 204 * -------------------------------------------------------- 205 */ 206func platform_mem_init 207 mov x0, #0 208 ret 209endfunc platform_mem_init 210 211 /* --------------------------------------------------- 212 * Function to handle a platform reset and store 213 * input parameters passed by BL2. 214 * --------------------------------------------------- 215 */ 216func plat_reset_handler 217 218 /* ---------------------------------------------------- 219 * Verify if we are running from BL31_BASE address 220 * ---------------------------------------------------- 221 */ 222 adr x18, bl31_entrypoint 223 mov x17, #BL31_BASE 224 cmp x18, x17 225 b.eq 1f 226 227 /* ---------------------------------------------------- 228 * Copy the entire BL31 code to BL31_BASE if we are not 229 * running from it already 230 * ---------------------------------------------------- 231 */ 232 mov x0, x17 233 mov x1, x18 234 mov x2, #BL31_SIZE 235_loop16: 236 cmp x2, #16 237 b.lo _loop1 238 ldp x3, x4, [x1], #16 239 stp x3, x4, [x0], #16 240 sub x2, x2, #16 241 b _loop16 242 /* copy byte per byte */ 243_loop1: 244 cbz x2, _end 245 ldrb w3, [x1], #1 246 strb w3, [x0], #1 247 subs x2, x2, #1 248 b.ne _loop1 249 250 /* ---------------------------------------------------- 251 * Jump to BL31_BASE and start execution again 252 * ---------------------------------------------------- 253 */ 254_end: mov x0, x20 255 mov x1, x21 256 br x17 2571: 258 259 /* ----------------------------------- 260 * derive and save the phys_base addr 261 * ----------------------------------- 262 */ 263 adr x17, tegra_bl31_phys_base 264 ldr x18, [x17] 265 cbnz x18, 1f 266 adr x18, bl31_entrypoint 267 str x18, [x17] 268 2691: cpu_init_common 270 271 ret 272endfunc plat_reset_handler 273 274 /* ------------------------------------------------------ 275 * int32_t plat_core_pos_by_mpidr(u_register_t mpidr) 276 * 277 * This function implements a part of the critical 278 * interface between the psci generic layer and the 279 * platform that allows the former to query the platform 280 * to convert an MPIDR to a unique linear index. An error 281 * code (-1) is returned in case the MPIDR is invalid. 282 * 283 * Clobbers: x0-x3 284 * ------------------------------------------------------ 285 */ 286func plat_core_pos_by_mpidr 287 lsr x1, x0, #MPIDR_AFF0_SHIFT 288 and x1, x1, #MPIDR_AFFLVL_MASK /* core id */ 289 lsr x2, x0, #MPIDR_AFF1_SHIFT 290 and x2, x2, #MPIDR_AFFLVL_MASK /* cluster id */ 291 292 /* core_id >= PLATFORM_MAX_CPUS_PER_CLUSTER */ 293 mov x0, #-1 294 cmp x1, #(PLATFORM_MAX_CPUS_PER_CLUSTER - 1) 295 b.gt 1f 296 297 /* cluster_id >= PLATFORM_CLUSTER_COUNT */ 298 cmp x2, #(PLATFORM_CLUSTER_COUNT - 1) 299 b.gt 1f 300 301 /* CorePos = CoreId + (ClusterId * cpus per cluster) */ 302 mov x3, #PLATFORM_MAX_CPUS_PER_CLUSTER 303 mul x3, x3, x2 304 add x0, x1, x3 305 3061: 307 ret 308endfunc plat_core_pos_by_mpidr 309 310 /* ---------------------------------------- 311 * Secure entrypoint function for CPU boot 312 * ---------------------------------------- 313 */ 314func tegra_secure_entrypoint _align=6 315 316#if ERRATA_TEGRA_INVALIDATE_BTB_AT_BOOT 317 318 /* -------------------------------------------------------- 319 * Skip the invalidate BTB workaround for Tegra210B01 SKUs. 320 * -------------------------------------------------------- 321 */ 322 mov x0, #TEGRA_MISC_BASE 323 add x0, x0, #HARDWARE_REVISION_OFFSET 324 ldr w1, [x0] 325 lsr w1, w1, #CHIP_ID_SHIFT 326 and w1, w1, #CHIP_ID_MASK 327 cmp w1, #TEGRA_CHIPID_TEGRA21 /* T210? */ 328 b.ne 2f 329 ldr w1, [x0] 330 lsr w1, w1, #MAJOR_VERSION_SHIFT 331 and w1, w1, #MAJOR_VERSION_MASK 332 cmp w1, #0x02 /* T210 B01? */ 333 b.eq 2f 334 335 /* ------------------------------------------------------- 336 * Invalidate BTB along with I$ to remove any stale 337 * entries from the branch predictor array. 338 * ------------------------------------------------------- 339 */ 340 mrs x0, CORTEX_A57_CPUACTLR_EL1 341 orr x0, x0, #1 342 msr CORTEX_A57_CPUACTLR_EL1, x0 /* invalidate BTB and I$ together */ 343 dsb sy 344 isb 345 ic iallu /* actual invalidate */ 346 dsb sy 347 isb 348 349 mrs x0, CORTEX_A57_CPUACTLR_EL1 350 bic x0, x0, #1 351 msr CORTEX_A57_CPUACTLR_EL1, X0 /* restore original CPUACTLR_EL1 */ 352 dsb sy 353 isb 354 355 .rept 7 356 nop /* wait */ 357 .endr 358 359 /* ----------------------------------------------- 360 * Extract OSLK bit and check if it is '1'. This 361 * bit remains '0' for A53 on warm-resets. If '1', 362 * turn off regional clock gating and request warm 363 * reset. 364 * ----------------------------------------------- 365 */ 366 mrs x0, oslsr_el1 367 and x0, x0, #2 368 mrs x1, mpidr_el1 369 bics xzr, x0, x1, lsr #7 /* 0 = slow cluster or warm reset */ 370 b.eq restore_oslock 371 mov x0, xzr 372 msr oslar_el1, x0 /* os lock stays 0 across warm reset */ 373 mov x3, #3 374 movz x4, #0x8000, lsl #48 375 msr CORTEX_A57_CPUACTLR_EL1, x4 /* turn off RCG */ 376 isb 377 msr rmr_el3, x3 /* request warm reset */ 378 isb 379 dsb sy 3801: wfi 381 b 1b 382 383 /* -------------------------------------------------- 384 * These nops are here so that speculative execution 385 * won't harm us before we are done with warm reset. 386 * -------------------------------------------------- 387 */ 388 .rept 65 389 nop 390 .endr 3912: 392 /* -------------------------------------------------- 393 * Do not insert instructions here 394 * -------------------------------------------------- 395 */ 396#endif 397 398 /* -------------------------------------------------- 399 * Restore OS Lock bit 400 * -------------------------------------------------- 401 */ 402restore_oslock: 403 mov x0, #1 404 msr oslar_el1, x0 405 406 /* -------------------------------------------------- 407 * Get secure world's entry point and jump to it 408 * -------------------------------------------------- 409 */ 410 bl plat_get_my_entrypoint 411 br x0 412endfunc tegra_secure_entrypoint 413 414 .data 415 .align 3 416 417 /* -------------------------------------------------- 418 * CPU Secure entry point - resume from suspend 419 * -------------------------------------------------- 420 */ 421tegra_sec_entry_point: 422 .quad 0 423 424 /* -------------------------------------------------- 425 * NS world's cold boot entry point 426 * -------------------------------------------------- 427 */ 428ns_image_entrypoint: 429 .quad 0 430 431 /* -------------------------------------------------- 432 * BL31's physical base address 433 * -------------------------------------------------- 434 */ 435tegra_bl31_phys_base: 436 .quad 0 437 438 /* -------------------------------------------------- 439 * UART controller base for console init 440 * -------------------------------------------------- 441 */ 442tegra_console_base: 443 .quad 0 444