1/* 2 * Copyright (c) 2014, STMicroelectronics International N.V. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28/* 29 * Entry points for the A9 inits, A9 revision specific or not. 30 * It is assume no stack is available when these routines are called. 31 * It is assume each routine is called with return address in LR 32 * and with ARM registers R0, R1, R2, R3 being scratchable. 33 */ 34#include <kernel/tz_ssvce_def.h> 35#include <arm32_macros.S> 36#include <asm.S> 37#include <kernel/unwind.h> 38 39#define CPUID_A9_R2P2_H 0x412f 40#define CPUID_A9_R2P2_L 0xc092 41 42#define CPUID_A9_R3P0_H 0x413f 43#define CPUID_A9_R3P0_L 0xc090 44 45.section .text 46.balign 4 47.code 32 48 49/* 50 * arm_secboot_identify_cpu - identify and save CPU version 51 * 52 * Use scratables registers R0-R3. 53 * No stack usage. 54 * LR store return address. 55 * Trap CPU in case of error. 56 */ 57FUNC arm_secboot_identify_cpu , : 58UNWIND( .fnstart) 59 60 mrc p15, 0, r0, c0, c0, 0 /* read A9 ID */ 61 movw r1, #CPUID_A9_R2P2_L 62 movt r1, #CPUID_A9_R2P2_H 63 cmp r0, r1 64 beq _ident_a9_r2p2 65 movw r1, #CPUID_A9_R3P0_L 66 movt r1, #CPUID_A9_R3P0_H 67 cmp r0, r1 68 beq _ident_a9_r3p0 69 b . /* TODO: unknown id: reset? log? */ 70 71_ident_a9_r2p2: 72 /* unsupported version. TODO: needs to be supported */ 73 b . /* TODO: unknown id: reset? log? */ 74 75_ident_a9_r3p0: 76 mov pc, lr /* back to tzinit */ 77UNWIND( .fnend) 78END_FUNC arm_secboot_identify_cpu 79 80/* 81 * Memory Cache Level2 Configuration Function 82 * 83 * Use scratables registers R0-R3. 84 * No stack usage. 85 * LR store return address. 86 * Trap CPU in case of error. 87 */ 88FUNC arm_cl2_config , : 89UNWIND( .fnstart) 90 91 mrc p15, 0, r0, c0, c0, 0 /* read A9 ID */ 92 movw r1, #CPUID_A9_R3P0_L 93 movt r1, #CPUID_A9_R3P0_H 94 cmp r0, r1 95 beq _config_l2cc_r3p0 96 b . /* TODO: unknown id: reset? log? */ 97 98_config_l2cc_r3p0: 99 /* 100 * TAG RAM Control Register 101 * 102 * bit[10:8]:1 - 2 cycle of write accesses latency 103 * bit[6:4]:1 - 2 cycle of read accesses latency 104 * bit[2:0]:1 - 2 cycle of setup latency 105 */ 106 movw r0, #PL310_TAG_RAM_CTRL 107 movt r0, #PL310_BASE_H 108 ldr r2, [r0] 109 movw r1, #0xf888 110 movt r1, #0xffff 111 and r2,r2,r1 112 movw r1, #0xf999 113 movt r1, #0xffff 114 orr r2,r2,r1 115 str r2, [r0] 116 117 /* 118 * DATA RAM Control Register 119 * 120 * bit[10:8]:2 - 3 cycle of write accesses latency 121 * bit[6:4]:2 - 3 cycle of read accesses latency 122 * bit[2:0]:2 - 3 cycle of setup latency 123 */ 124 movw r0, #PL310_DATA_RAM_CTRL 125 movt r0, #PL310_BASE_H 126 ldr r2, [r0] 127 movw r1, #0xf888 128 movt r1, #0xffff 129 and r2,r2,r1 130 movw r1, #0xfaaa 131 movt r1, #0xffff 132 orr r2,r2,r1 133 str r2, [r0] 134 135 /* 136 * Auxiliary Control Register = 0x3C480800 137 * 138 * I/Dcache prefetch enabled (bit29:28=2b11) 139 * NS can access interrupts (bit27=1) 140 * NS can lockown cache lines (bit26=1) 141 * Pseudo-random replacement policy (bit25=0) 142 * Force write allocated (default) 143 * Shared attribute internally ignored (bit22=1, bit13=0) 144 * Parity disabled (bit21=0) 145 * Event monitor disabled (bit20=0) 146 * 128kB ways, 8-way associativity (bit19:17=3b100 bit16=0) 147 * Store buffer device limitation enabled (bit11=1) 148 * Cacheable accesses have high prio (bit10=0) 149 * Full Line Zero (FLZ) disabled (bit0=0) 150 */ 151 movw r0, #PL310_AUX_CTRL 152 movt r0, #PL310_BASE_H 153 movw r1, #0x0800 154 movt r1, #0x3C48 155 str r1, [r0] 156 157 /* 158 * Prefetch Control Register = 0x31000007 159 * 160 * Double linefill disabled (bit30=0) 161 * I/D prefetch enabled (bit29:28=2b11) 162 * Prefetch drop enabled (bit24=1) 163 * Incr double linefill disable (bit23=0) 164 * Prefetch offset = 7 (bit4:0) 165 */ 166 movw r0, #PL310_PREFETCH_CTRL 167 movt r0, #PL310_BASE_H 168 movw r1, #0x0007 169 movt r1, #0x3100 170 str r1, [r0] 171 172 /* 173 * Power Register = 0x00000003 174 * 175 * Dynamic clock gating enabled 176 * Standby mode enabled 177 */ 178 movw r0, #PL310_POWER_CTRL 179 movt r0, #PL310_BASE_H 180 movw r1, #0x0003 181 movt r1, #0x0000 182 str r1, [r0] 183 184 /* invalidate all cache ways */ 185 movw r0, #PL310_INV_BY_WAY 186 movt r0, #PL310_BASE_H 187 movw r1, #0x00FF 188 movt r1, #0x0000 189 str r1, [r0] 190 191 mov pc, lr 192UNWIND( .fnend) 193END_FUNC arm_cl2_config 194/* End of arm_cl2_config */ 195 196 197/* 198 * Memory Cache Level2 Enable Function 199 * 200 * If PL310 supports FZLW, enable also FZL in A9 core 201 * 202 * Use scratables registers R0-R3. 203 * No stack usage. 204 * LR store return address. 205 * Trap CPU in case of error. 206 * TODO: to be moved to PL310 code (tz_svce_pl310.S ?) 207 */ 208FUNC arm_cl2_enable , : 209UNWIND( .fnstart) 210 211 212 /* Enable PL310 ctrl -> only set lsb bit */ 213 movw r0, #PL310_CTRL 214 movt r0, #PL310_BASE_H 215 mov r1, #0x1 216 str r1, [r0] 217 218 /* if L2 FLZW enable, enable in L1 */ 219 movw r0, #PL310_AUX_CTRL 220 movt r0, #PL310_BASE_H 221 ldr r1, [r0] 222 tst r1, #(1 << 0) /* test AUX_CTRL[FLZ] */ 223 mrc p15, 0, r0, c1, c0, 1 224 orrne r0, r0, #(1 << 3) /* enable ACTLR[FLZW] */ 225 mcr p15, 0, r0, c1, c0, 1 226 227 mov pc, lr 228UNWIND( .fnend) 229END_FUNC arm_cl2_enable 230 231/* 232 * Cortex A9 configuration early configuration 233 * 234 * Use scratables registers R0-R3. 235 * No stack usage. 236 * LR store return address. 237 * Trap CPU in case of error. 238 */ 239FUNC plat_cpu_reset_early , : 240UNWIND( .fnstart) 241 242 /* only r3p0 is supported */ 243 mrc p15, 0, r0, c0, c0, 0 /* read A9 ID */ 244 movw r1, #CPUID_A9_R3P0_L 245 movt r1, #CPUID_A9_R3P0_H 246 cmp r0, r1 247 beq _early_a9_r3p0 248 b . /* TODO: unknown id: reset? log? */ 249 250_early_a9_r3p0: 251 /* 252 * Mandated HW config loaded 253 * 254 * SCTLR = 0x00004000 255 * - Round-Robin replac. for icache, btac, i/duTLB (bit14: RoundRobin) 256 * 257 * ACTRL = 0x00000041 258 * - core always in full SMP (FW bit0=1, SMP bit6=1) 259 * - L2 write full line of zero disabled (bit3=0) 260 * (keep WFLZ low. Will be set once outer L2 is ready) 261 * 262 * NSACR = 0x00020C00 263 * - NSec cannot change ACTRL.SMP (NS_SMP bit18=0) 264 * - Nsec can lockdown TLB (TL bit17=1) 265 * - NSec cannot access PLE (PLE bit16=0) 266 * - NSec can use SIMD/VFP (CP10/CP11) (bit15:14=2b00, bit11:10=2b11) 267 * 268 * PCR = 0x00000001 269 * - no change latency, enable clk gating 270 */ 271 movw r0, #0x4000 272 movt r0, #0x0000 273 write_sctlr r0 274 275 movw r0, #0x0041 276 movt r0, #0x0000 277 write_actlr r0 278 279 movw r0, #0x0C00 280 movt r0, #0x0002 281 write_nsacr r0 282 283 movw r0, #0x0000 284 movt r0, #0x0001 285 write_pcr r0 286 287 /* 288 * GIC configuration 289 * 290 * Register ICDISR0 = 0xFFFFFFFF 291 * - All local interrupts are NonSecure. 292 * 293 * Register ICCPMR = 0xFFFFFFFF 294 */ 295 296 movw r0, #GIC_DIST_ISR0 297 movt r0, #GIC_DIST_BASE_H 298 mov r1, #0xFFFFFFFF 299 str r1, [r0] 300 301 movw r0, #CORE_ICC_ICCPMR 302 movt r0, #GIC_CPU_BASE_H 303 mov r1, #0xFFFFFFFF 304 str r1, [r0] 305 306 mov pc, lr /* back to tzinit */ 307UNWIND( .fnend) 308END_FUNC plat_cpu_reset_early 309 310/* 311 * arm_secboot_errata - arm errata, specific per core revision 312 * 313 * Use scratables registers R0-R3. 314 * No stack usage. 315 * LR store return address. 316 * Trap CPU in case of error. 317 */ 318FUNC arm_secboot_errata , : 319UNWIND( .fnstart) 320 321 mrc p15, 0, r0, c0, c0, 0 /* read A9 ID */ 322 movw r1, #CPUID_A9_R2P2_L 323 movt r1, #CPUID_A9_R2P2_H 324 cmp r0, r1 325 beq _errata_a9_r2p2 326 movw r1, #CPUID_A9_R3P0_L 327 movt r1, #CPUID_A9_R3P0_H 328 cmp r0, r1 329 beq _errata_a9_r3p0 330 b . /* TODO: unknown id: reset? log? */ 331 332_errata_a9_r2p2: 333 /* unsupported version. TODO: needs to be supported */ 334 b . /* TODO: unknown id: reset? log? */ 335 336_errata_a9_r3p0: 337 mov pc, lr 338UNWIND( .fnend) 339END_FUNC arm_secboot_errata 340 341/* 342 * A9 secured config, needed only from a single core 343 * 344 * Use scratables registers R0-R3. 345 * No stack usage. 346 * LR store return address. 347 * Trap CPU in case of error. 348 * 349 * TODO: size optim in code 350 */ 351FUNC plat_cpu_reset_late , : 352UNWIND( .fnstart) 353 354 mrc p15, 0, r0, c0, c0, 5 355 ands r0, #3 356 beq _boot_late_primary_cpu 357 358_boot_late_secondary_cpu: 359 mov pc, lr 360 361_boot_late_primary_cpu: 362 /* 363 * Snoop Control Unit configuration 364 * 365 * SCU is enabled with filtering off. 366 * Both Secure/Unsecure can access SCU and timers 367 * 368 * 0x00 SCUControl = 0x00000060 !!! should be 0x5 ! A NETTOYER !!!!!!!!!!!!!!!!!!!!!!!!! 369 * 0x04 SCUConfiguration = ??? A NETTOYER !!!!!!!!!!!!!!!!!!!!!!!!! 370 * 0x0C SCUInvalidateAll (Secure cfg) 371 * 0x40 FilteringStartAddress = 0x40000000 372 * 0x44 FilteeringEndAddress - 0x80000000 373 * 0x50 SCUAccessControl 374 * 0x54 SCUSecureAccessControl 375 */ 376 377 /* 378 * SCU Access Register : SAC = 0x00000003 379 * - both secure CPU access SCU 380 */ 381 movw r0, #SCU_SAC /* LSB */ 382 movt r0, #SCU_BASE_H /* MSB */ 383 movw r1, #0x0003 384 movt r1, #0x0000 385 str r1, [r0] 386 387 /* 388 * SCU NonSecure Access Register : SNSAC : 0x00000333 389 * - both nonsec cpu access SCU, private and global timer 390 */ 391 movw r0, #SCU_NSAC /* LSB */ 392 movt r0, #SCU_BASE_H /* MSB */ 393 movw r1, #0x0333 394 movt r1, #0x0000 395 str r1, [r0] 396 397 /* 398 * SCU Filtering End Address register: SFEA 399 */ 400 movw r0, #SCU_FILT_EA /* LSB */ 401 movt r0, #SCU_BASE_H /* MSB */ 402 movw r1, #(CPU_PORT_FILT_END & 0xFFFF) 403 movt r1, #(CPU_PORT_FILT_END >> 16) 404 str r1, [r0] 405 406 /* 407 * SCU Filtering Start Address register: SFSA 408 */ 409 movw r0, #SCU_FILT_SA /* LSB */ 410 movt r0, #SCU_BASE_H /* MSB */ 411 movw r1, #(CPU_PORT_FILT_START & 0xFFFF) 412 movt r1, #(CPU_PORT_FILT_START >> 16) 413 str r1, [r0] 414 415 /* 416 * SCU Control Register : CTRL = 0x00000065 417 * - ic stanby enable=1 418 * - scu standby enable=1 419 * - scu enable=1 420 */ 421 movw r0, #SCU_CTRL /* LSB */ 422 movt r0, #SCU_BASE_H /* MSB */ 423 movw r1, #0x0065 424 movt r1, #0x0000 425 str r1, [r0] 426 427 /*- GIC secure configuration ---*/ 428 429 /* 430 * Register ICDISR[1-31] = 0xFFFFFFFF 431 * - All external interrupts are NonSecure. 432 */ 433 movw r0, #GIC_DIST_ISR1 434 movt r0, #GIC_DIST_BASE_H 435 mov r2, #0xFFFFFFFF 436 mov r1, #31 /* Nb of loop rounds */ 437loop_1: 438 str r2, [r0] 439 add r0, #4 440 sub r1, r1, #1 441 cmp r1, #0 442 bne loop_1 443 444 445 /*- PL310 Memory Controller (Note: should be done with NS=1) ---*/ 446 447 /* 448 * reg12_addr_filtering_end 449 */ 450 movw r0, #PL310_ADDR_FILT_END 451 movt r0, #PL310_BASE_H 452 movw r1, #(CPU_PORT_FILT_END & 0xFFFF) 453 movt r1, #(CPU_PORT_FILT_END >> 16) 454 str r1, [r0] 455 456 /* 457 * reg12_addr_filtering_start 458 */ 459 movw r0, #PL310_ADDR_FILT_START 460 movt r0, #PL310_BASE_H 461 movw r1, #((CPU_PORT_FILT_START & 0xFFFF) | 1) 462 movt r1, #(CPU_PORT_FILT_START >> 16) 463 str r1, [r0] 464 465 /* Allow NSec to manage FIQ/Imprecise abort */ 466 mrc p15, 0, r0, c1, c1, 0 /* read Secure Configuration Register */ 467 orr r0, r0, #0x30 /* SCR[FW]=1, SCR[AW]=1 */ 468 mcr p15, 0, r0, c1, c1, 0 /* write updated value in Secure Configuration Register */ 469 470 mov pc, lr 471UNWIND( .fnend) 472END_FUNC plat_cpu_reset_late 473