1/* 2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of ARM nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30#include <arch.h> 31#include <asm_macros.S> 32#include <assert_macros.S> 33#include <cpu_macros.S> 34#include <cortex_a57.h> 35#include <cortex_a53.h> 36#include <platform_def.h> 37#include <tegra_def.h> 38 39#define MIDR_PN_CORTEX_A57 0xD07 40 41/******************************************************************************* 42 * Implementation defined ACTLR_EL3 bit definitions 43 ******************************************************************************/ 44#define ACTLR_EL3_L2ACTLR_BIT (1 << 6) 45#define ACTLR_EL3_L2ECTLR_BIT (1 << 5) 46#define ACTLR_EL3_L2CTLR_BIT (1 << 4) 47#define ACTLR_EL3_CPUECTLR_BIT (1 << 1) 48#define ACTLR_EL3_CPUACTLR_BIT (1 << 0) 49#define ACTLR_EL3_ENABLE_ALL_ACCESS (ACTLR_EL3_L2ACTLR_BIT | \ 50 ACTLR_EL3_L2ECTLR_BIT | \ 51 ACTLR_EL3_L2CTLR_BIT | \ 52 ACTLR_EL3_CPUECTLR_BIT | \ 53 ACTLR_EL3_CPUACTLR_BIT) 54 55 /* Global functions */ 56 .globl plat_is_my_cpu_primary 57 .globl plat_my_core_pos 58 .globl plat_get_my_entrypoint 59 .globl plat_secondary_cold_boot_setup 60 .globl platform_mem_init 61 .globl plat_crash_console_init 62 .globl plat_crash_console_putc 63 .globl tegra_secure_entrypoint 64 .globl plat_reset_handler 65 66 /* Global variables */ 67 .globl tegra_sec_entry_point 68 .globl ns_image_entrypoint 69 .globl tegra_bl31_phys_base 70 .globl tegra_console_base 71 72 /* --------------------- 73 * Common CPU init code 74 * --------------------- 75 */ 76.macro cpu_init_common 77 78 /* ------------------------------------------------ 79 * We enable procesor retention and L2/CPUECTLR NS 80 * access for A57 CPUs only. 81 * ------------------------------------------------ 82 */ 83 mrs x0, midr_el1 84 mov x1, #(MIDR_PN_MASK << MIDR_PN_SHIFT) 85 and x0, x0, x1 86 lsr x0, x0, #MIDR_PN_SHIFT 87 cmp x0, #MIDR_PN_CORTEX_A57 88 b.ne 1f 89 90 /* --------------------------- 91 * Enable processor retention 92 * --------------------------- 93 */ 94 mrs x0, L2ECTLR_EL1 95 mov x1, #RETENTION_ENTRY_TICKS_512 << L2ECTLR_RET_CTRL_SHIFT 96 bic x0, x0, #L2ECTLR_RET_CTRL_MASK 97 orr x0, x0, x1 98 msr L2ECTLR_EL1, x0 99 isb 100 101 mrs x0, CPUECTLR_EL1 102 mov x1, #RETENTION_ENTRY_TICKS_512 << CPUECTLR_CPU_RET_CTRL_SHIFT 103 bic x0, x0, #CPUECTLR_CPU_RET_CTRL_MASK 104 orr x0, x0, x1 105 msr CPUECTLR_EL1, x0 106 isb 107 108 /* ------------------------------------------------------- 109 * Enable L2 and CPU ECTLR RW access from non-secure world 110 * ------------------------------------------------------- 111 */ 112 mov x0, #ACTLR_EL3_ENABLE_ALL_ACCESS 113 msr actlr_el3, x0 114 msr actlr_el2, x0 115 isb 116 117 /* -------------------------------- 118 * Enable the cycle count register 119 * -------------------------------- 120 */ 1211: mrs x0, pmcr_el0 122 ubfx x0, x0, #11, #5 // read PMCR.N field 123 mov x1, #1 124 lsl x0, x1, x0 125 sub x0, x0, #1 // mask of event counters 126 orr x0, x0, #0x80000000 // disable overflow intrs 127 msr pmintenclr_el1, x0 128 msr pmuserenr_el0, x1 // enable user mode access 129 130 /* ---------------------------------------------------------------- 131 * Allow non-privileged access to CNTVCT: Set CNTKCTL (Kernel Count 132 * register), bit 1 (EL0VCTEN) to enable access to CNTVCT/CNTFRQ 133 * registers from EL0. 134 * ---------------------------------------------------------------- 135 */ 136 mrs x0, cntkctl_el1 137 orr x0, x0, #EL0VCTEN_BIT 138 msr cntkctl_el1, x0 139.endm 140 141 /* ----------------------------------------------------- 142 * unsigned int plat_is_my_cpu_primary(void); 143 * 144 * This function checks if this is the Primary CPU 145 * ----------------------------------------------------- 146 */ 147func plat_is_my_cpu_primary 148 mrs x0, mpidr_el1 149 and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) 150 cmp x0, #TEGRA_PRIMARY_CPU 151 cset x0, eq 152 ret 153endfunc plat_is_my_cpu_primary 154 155 /* ----------------------------------------------------- 156 * unsigned int plat_my_core_pos(void); 157 * 158 * result: CorePos = CoreId + (ClusterId << 2) 159 * ----------------------------------------------------- 160 */ 161func plat_my_core_pos 162 mrs x0, mpidr_el1 163 and x1, x0, #MPIDR_CPU_MASK 164 and x0, x0, #MPIDR_CLUSTER_MASK 165 add x0, x1, x0, LSR #6 166 ret 167endfunc plat_my_core_pos 168 169 /* ----------------------------------------------------- 170 * unsigned long plat_get_my_entrypoint (void); 171 * 172 * Main job of this routine is to distinguish between 173 * a cold and warm boot. If the tegra_sec_entry_point for 174 * this CPU is present, then it's a warm boot. 175 * 176 * ----------------------------------------------------- 177 */ 178func plat_get_my_entrypoint 179 adr x1, tegra_sec_entry_point 180 ldr x0, [x1] 181 ret 182endfunc plat_get_my_entrypoint 183 184 /* ----------------------------------------------------- 185 * int platform_get_core_pos(int mpidr); 186 * 187 * With this function: CorePos = (ClusterId * 4) + 188 * CoreId 189 * ----------------------------------------------------- 190 */ 191func platform_get_core_pos 192 and x1, x0, #MPIDR_CPU_MASK 193 and x0, x0, #MPIDR_CLUSTER_MASK 194 add x0, x1, x0, LSR #6 195 ret 196endfunc platform_get_core_pos 197 198 /* ----------------------------------------------------- 199 * void plat_secondary_cold_boot_setup (void); 200 * 201 * This function performs any platform specific actions 202 * needed for a secondary cpu after a cold reset. Right 203 * now this is a stub function. 204 * ----------------------------------------------------- 205 */ 206func plat_secondary_cold_boot_setup 207 mov x0, #0 208 ret 209endfunc plat_secondary_cold_boot_setup 210 211 /* -------------------------------------------------------- 212 * void platform_mem_init (void); 213 * 214 * Any memory init, relocation to be done before the 215 * platform boots. Called very early in the boot process. 216 * -------------------------------------------------------- 217 */ 218func platform_mem_init 219 mov x0, #0 220 ret 221endfunc platform_mem_init 222 223 /* --------------------------------------------- 224 * int plat_crash_console_init(void) 225 * Function to initialize the crash console 226 * without a C Runtime to print crash report. 227 * Clobber list : x0 - x4 228 * --------------------------------------------- 229 */ 230func plat_crash_console_init 231 adr x0, tegra_console_base 232 ldr x0, [x0] 233 mov_imm x1, TEGRA_BOOT_UART_CLK_IN_HZ 234 mov_imm x2, TEGRA_CONSOLE_BAUDRATE 235 b console_core_init 236endfunc plat_crash_console_init 237 238 /* --------------------------------------------- 239 * int plat_crash_console_putc(void) 240 * Function to print a character on the crash 241 * console without a C Runtime. 242 * Clobber list : x1, x2 243 * --------------------------------------------- 244 */ 245func plat_crash_console_putc 246 adr x1, tegra_console_base 247 ldr x1, [x1] 248 b console_core_putc 249endfunc plat_crash_console_putc 250 251 /* --------------------------------------------------- 252 * Function to handle a platform reset and store 253 * input parameters passed by BL2. 254 * --------------------------------------------------- 255 */ 256func plat_reset_handler 257 258 /* ---------------------------------------------------- 259 * Verify if we are running from BL31_BASE address 260 * ---------------------------------------------------- 261 */ 262 adr x18, bl31_entrypoint 263 mov x17, #BL31_BASE 264 cmp x18, x17 265 b.eq 1f 266 267 /* ---------------------------------------------------- 268 * Copy the entire BL31 code to BL31_BASE if we are not 269 * running from it already 270 * ---------------------------------------------------- 271 */ 272 mov x0, x17 273 mov x1, x18 274 mov x2, #BL31_SIZE 275_loop16: 276 cmp x2, #16 277 b.lt _loop1 278 ldp x3, x4, [x1], #16 279 stp x3, x4, [x0], #16 280 sub x2, x2, #16 281 b _loop16 282 /* copy byte per byte */ 283_loop1: 284 cbz x2, _end 285 ldrb w3, [x1], #1 286 strb w3, [x0], #1 287 subs x2, x2, #1 288 b.ne _loop1 289 290 /* ---------------------------------------------------- 291 * Jump to BL31_BASE and start execution again 292 * ---------------------------------------------------- 293 */ 294_end: mov x0, x20 295 mov x1, x21 296 br x17 2971: 298 299 /* ----------------------------------- 300 * derive and save the phys_base addr 301 * ----------------------------------- 302 */ 303 adr x17, tegra_bl31_phys_base 304 ldr x18, [x17] 305 cbnz x18, 1f 306 adr x18, bl31_entrypoint 307 str x18, [x17] 308 3091: cpu_init_common 310 311 ret 312endfunc plat_reset_handler 313 314 /* ---------------------------------------- 315 * Secure entrypoint function for CPU boot 316 * ---------------------------------------- 317 */ 318 .align 6 319func tegra_secure_entrypoint 320 321#if ERRATA_TEGRA_INVALIDATE_BTB_AT_BOOT 322 323 /* ------------------------------------------------------- 324 * Invalidate BTB along with I$ to remove any stale 325 * entries from the branch predictor array. 326 * ------------------------------------------------------- 327 */ 328 mrs x0, CPUACTLR_EL1 329 orr x0, x0, #1 330 msr CPUACTLR_EL1, x0 /* invalidate BTB and I$ together */ 331 dsb sy 332 isb 333 ic iallu /* actual invalidate */ 334 dsb sy 335 isb 336 337 mrs x0, CPUACTLR_EL1 338 bic x0, x0, #1 339 msr CPUACTLR_EL1, X0 /* restore original CPUACTLR_EL1 */ 340 dsb sy 341 isb 342 343 .rept 7 344 nop /* wait */ 345 .endr 346 347 /* ----------------------------------------------- 348 * Extract OSLK bit and check if it is '1'. This 349 * bit remains '0' for A53 on warm-resets. If '1', 350 * turn off regional clock gating and request warm 351 * reset. 352 * ----------------------------------------------- 353 */ 354 mrs x0, oslsr_el1 355 and x0, x0, #2 356 mrs x1, mpidr_el1 357 bics xzr, x0, x1, lsr #7 /* 0 = slow cluster or warm reset */ 358 b.eq restore_oslock 359 mov x0, xzr 360 msr oslar_el1, x0 /* os lock stays 0 across warm reset */ 361 mov x3, #3 362 movz x4, #0x8000, lsl #48 363 msr CPUACTLR_EL1, x4 /* turn off RCG */ 364 isb 365 msr rmr_el3, x3 /* request warm reset */ 366 isb 367 dsb sy 3681: wfi 369 b 1b 370 371 /* -------------------------------------------------- 372 * These nops are here so that speculative execution 373 * won't harm us before we are done with warm reset. 374 * -------------------------------------------------- 375 */ 376 .rept 65 377 nop 378 .endr 379 380 /* -------------------------------------------------- 381 * Do not insert instructions here 382 * -------------------------------------------------- 383 */ 384#endif 385 386 /* -------------------------------------------------- 387 * Restore OS Lock bit 388 * -------------------------------------------------- 389 */ 390restore_oslock: 391 mov x0, #1 392 msr oslar_el1, x0 393 394 cpu_init_common 395 396 /* --------------------------------------------------------------------- 397 * The initial state of the Architectural feature trap register 398 * (CPTR_EL3) is unknown and it must be set to a known state. All 399 * feature traps are disabled. Some bits in this register are marked as 400 * Reserved and should not be modified. 401 * 402 * CPTR_EL3.TCPAC: This causes a direct access to the CPACR_EL1 from EL1 403 * or the CPTR_EL2 from EL2 to trap to EL3 unless it is trapped at EL2. 404 * CPTR_EL3.TTA: This causes access to the Trace functionality to trap 405 * to EL3 when executed from EL0, EL1, EL2, or EL3. If system register 406 * access to trace functionality is not supported, this bit is RES0. 407 * CPTR_EL3.TFP: This causes instructions that access the registers 408 * associated with Floating Point and Advanced SIMD execution to trap 409 * to EL3 when executed from any exception level, unless trapped to EL1 410 * or EL2. 411 * --------------------------------------------------------------------- 412 */ 413 mrs x1, cptr_el3 414 bic w1, w1, #TCPAC_BIT 415 bic w1, w1, #TTA_BIT 416 bic w1, w1, #TFP_BIT 417 msr cptr_el3, x1 418 419 /* -------------------------------------------------- 420 * Get secure world's entry point and jump to it 421 * -------------------------------------------------- 422 */ 423 bl plat_get_my_entrypoint 424 br x0 425endfunc tegra_secure_entrypoint 426 427 .data 428 .align 3 429 430 /* -------------------------------------------------- 431 * CPU Secure entry point - resume from suspend 432 * -------------------------------------------------- 433 */ 434tegra_sec_entry_point: 435 .quad 0 436 437 /* -------------------------------------------------- 438 * NS world's cold boot entry point 439 * -------------------------------------------------- 440 */ 441ns_image_entrypoint: 442 .quad 0 443 444 /* -------------------------------------------------- 445 * BL31's physical base address 446 * -------------------------------------------------- 447 */ 448tegra_bl31_phys_base: 449 .quad 0 450 451 /* -------------------------------------------------- 452 * UART controller base for console init 453 * -------------------------------------------------- 454 */ 455tegra_console_base: 456 .quad 0 457