Jiafei Pan | b4ccced | 2022-01-20 17:40:16 +0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2020-2022 NXP |
| 3 | * |
| 4 | * SPDX-License-Identifier: BSD-3-Clause |
| 5 | * |
| 6 | */ |
| 7 | |
| 8 | #include <asm_macros.S> |
| 9 | #include <dcfg_lsch2.h> |
| 10 | #include <nxp_timer.h> |
| 11 | #include <plat_gic.h> |
| 12 | #include <scfg.h> |
| 13 | |
| 14 | #include <bl31_data.h> |
| 15 | #include <plat_psci.h> |
| 16 | #include <platform_def.h> |
| 17 | |
| 18 | #define DAIF_DATA AUX_01_DATA |
| 19 | #define TIMER_CNTRL_DATA AUX_02_DATA |
| 20 | |
| 21 | .global soc_init_lowlevel |
| 22 | .global soc_init_percpu |
| 23 | .global _soc_core_release |
| 24 | .global _soc_core_restart |
| 25 | .global _soc_ck_disabled |
| 26 | .global _soc_sys_reset |
| 27 | .global _soc_sys_off |
| 28 | .global _soc_set_start_addr |
| 29 | .global _getGICC_BaseAddr |
| 30 | .global _getGICD_BaseAddr |
| 31 | .global _soc_core_prep_off |
| 32 | .global _soc_core_entr_off |
| 33 | .global _soc_core_exit_off |
| 34 | .global _soc_core_prep_stdby |
| 35 | .global _soc_core_entr_stdby |
| 36 | .global _soc_core_exit_stdby |
| 37 | .global _soc_core_prep_pwrdn |
| 38 | .global _soc_core_entr_pwrdn |
| 39 | .global _soc_core_exit_pwrdn |
| 40 | .global _soc_clstr_prep_stdby |
| 41 | .global _soc_clstr_exit_stdby |
| 42 | .global _soc_clstr_prep_pwrdn |
| 43 | .global _soc_clstr_exit_pwrdn |
| 44 | .global _soc_sys_prep_stdby |
| 45 | .global _soc_sys_exit_stdby |
| 46 | .global _soc_sys_prep_pwrdn |
| 47 | .global _soc_sys_pwrdn_wfi |
| 48 | .global _soc_sys_exit_pwrdn |
| 49 | |
| 50 | |
| 51 | /* This function initialize the soc |
| 52 | * in: void |
| 53 | * out: void |
| 54 | */ |
| 55 | func soc_init_lowlevel |
| 56 | ret |
| 57 | endfunc soc_init_lowlevel |
| 58 | |
| 59 | |
| 60 | /* void soc_init_percpu(void) |
| 61 | * this function performs any soc-specific initialization that is needed on |
| 62 | * a per-core basis |
| 63 | * in: none |
| 64 | * out: none |
| 65 | * uses x0, x1, x2, x3 |
| 66 | */ |
| 67 | func soc_init_percpu |
| 68 | mov x3, x30 |
| 69 | |
| 70 | bl plat_my_core_mask |
| 71 | mov x2, x0 |
| 72 | |
| 73 | /* see if this core is marked for prefetch disable */ |
| 74 | mov x0, #PREFETCH_DIS_OFFSET |
| 75 | bl _get_global_data /* 0-1 */ |
| 76 | tst x0, x2 |
| 77 | b.eq 1f |
| 78 | bl _disable_ldstr_pfetch_A72 /* 0 */ |
| 79 | 1: |
| 80 | mov x30, x3 |
| 81 | ret |
| 82 | endfunc soc_init_percpu |
| 83 | |
| 84 | /* part of CPU_ON |
| 85 | * this function releases a secondary core from reset |
| 86 | * in: x0 = core_mask_lsb |
| 87 | * out: none |
| 88 | * uses: x0, x1, x2, x3 |
| 89 | */ |
| 90 | func _soc_core_release |
| 91 | |
| 92 | #if (TEST_BL31) |
| 93 | rbit w2, w0 |
| 94 | /* x2 = core mask msb */ |
| 95 | #else |
| 96 | mov x2, x0 |
| 97 | #endif |
| 98 | /* write COREBCR */ |
| 99 | mov x1, #NXP_SCFG_ADDR |
| 100 | rev w3, w2 |
| 101 | str w3, [x1, #SCFG_COREBCR_OFFSET] |
| 102 | isb |
| 103 | |
| 104 | /* read-modify-write BRR */ |
| 105 | mov x1, #NXP_DCFG_ADDR |
| 106 | ldr w2, [x1, #DCFG_BRR_OFFSET] |
| 107 | rev w3, w2 |
| 108 | orr w3, w3, w0 |
| 109 | rev w2, w3 |
| 110 | str w2, [x1, #DCFG_BRR_OFFSET] |
| 111 | isb |
| 112 | |
| 113 | /* send event */ |
| 114 | sev |
| 115 | isb |
| 116 | ret |
| 117 | endfunc _soc_core_release |
| 118 | |
| 119 | |
| 120 | /* part of CPU_ON |
| 121 | * this function restarts a core shutdown via _soc_core_entr_off |
| 122 | * in: x0 = core mask lsb (of the target cpu) |
| 123 | * out: x0 == 0, on success |
| 124 | * x0 != 0, on failure |
| 125 | * uses x0, x1, x2, x3, x4, x5 |
| 126 | */ |
| 127 | func _soc_core_restart |
| 128 | mov x5, x30 |
| 129 | mov x3, x0 |
| 130 | |
| 131 | /* |
| 132 | * unset ph20 request in RCPM_PCPH20CLEARR |
| 133 | * this is an lsb-0 register |
| 134 | */ |
| 135 | ldr x1, =NXP_RCPM_ADDR |
| 136 | rev w2, w3 |
| 137 | str w2, [x1, #RCPM_PCPH20CLRR_OFFSET] |
| 138 | dsb sy |
| 139 | isb |
| 140 | |
| 141 | bl _getGICD_BaseAddr |
| 142 | mov x4, x0 |
| 143 | |
| 144 | /* enable forwarding of group 0 interrupts by setting GICD_CTLR[0] = 1 */ |
| 145 | ldr w1, [x4, #GICD_CTLR_OFFSET] |
| 146 | orr w1, w1, #GICD_CTLR_EN_GRP0 |
| 147 | str w1, [x4, #GICD_CTLR_OFFSET] |
| 148 | dsb sy |
| 149 | isb |
| 150 | |
| 151 | |
| 152 | /* |
| 153 | * fire SGI by writing to GICD_SGIR the following values: |
| 154 | * [25:24] = 0x0 (forward interrupt to the CPU interfaces |
| 155 | * specified in CPUTargetList field) |
| 156 | * [23:16] = core mask lsb[7:0] (forward interrupt to target cpu) |
| 157 | * [15] = 0 (forward SGI only if it is configured as group 0 interrupt) |
| 158 | * [3:0] = 0xF (interrupt ID = 15) |
| 159 | */ |
| 160 | lsl w1, w3, #16 |
| 161 | orr w1, w1, #0xF |
| 162 | str w1, [x4, #GICD_SGIR_OFFSET] |
| 163 | dsb sy |
| 164 | isb |
| 165 | |
| 166 | /* load '0' on success */ |
| 167 | mov x0, xzr |
| 168 | |
| 169 | mov x30, x5 |
| 170 | ret |
| 171 | endfunc _soc_core_restart |
| 172 | |
| 173 | /* |
| 174 | * This function determines if a core is disabled via COREDISR |
| 175 | * in: w0 = core_mask_lsb |
| 176 | * out: w0 = 0, core not disabled |
| 177 | * w0 != 0, core disabled |
| 178 | * uses x0, x1, x2 |
| 179 | */ |
| 180 | func _soc_ck_disabled |
| 181 | /* get base addr of dcfg block */ |
| 182 | mov x1, #NXP_DCFG_ADDR |
| 183 | |
| 184 | /* read COREDISR */ |
| 185 | ldr w1, [x1, #DCFG_COREDISR_OFFSET] |
| 186 | rev w2, w1 |
| 187 | |
| 188 | /* test core bit */ |
| 189 | and w0, w2, w0 |
| 190 | ret |
| 191 | endfunc _soc_ck_disabled |
| 192 | |
| 193 | /* |
| 194 | *This function resets the system via SoC-specific methods |
| 195 | * in: none |
| 196 | * out: none |
| 197 | * uses x0, x1, x2, x3 |
| 198 | */ |
| 199 | func _soc_sys_reset |
| 200 | ldr x2, =NXP_DCFG_ADDR |
| 201 | |
| 202 | /* make sure the mask is cleared in the reset request mask register */ |
| 203 | mov w1, wzr |
| 204 | str w1, [x2, #DCFG_RSTRQMR1_OFFSET] |
| 205 | |
| 206 | /* set the reset request */ |
| 207 | ldr w1, =RSTCR_RESET_REQ |
| 208 | ldr x3, =DCFG_RSTCR_OFFSET |
| 209 | rev w0, w1 |
| 210 | str w0, [x2, x3] |
| 211 | |
| 212 | /* |
| 213 | * just in case this address range is mapped as cacheable, |
| 214 | * flush the write out of the dcaches |
| 215 | */ |
| 216 | add x3, x2, x3 |
| 217 | dc cvac, x3 |
| 218 | dsb st |
| 219 | isb |
| 220 | |
| 221 | /* Note: this function does not return */ |
| 222 | 1: |
| 223 | wfi |
| 224 | b 1b |
| 225 | endfunc _soc_sys_reset |
| 226 | |
| 227 | /* |
| 228 | * Part of SYSTEM_OFF |
| 229 | * this function turns off the SoC clocks |
| 230 | * Note: this function is not intended to return, and the only allowable |
| 231 | * recovery is POR |
| 232 | * in: none |
| 233 | * out: none |
| 234 | * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9 |
| 235 | */ |
| 236 | func _soc_sys_off |
| 237 | |
| 238 | /* mask interrupts at the core */ |
| 239 | mrs x1, DAIF |
| 240 | mov x0, #DAIF_SET_MASK |
| 241 | orr x0, x1, x0 |
| 242 | msr DAIF, x0 |
| 243 | |
| 244 | /* disable icache, dcache, mmu @ EL1 */ |
| 245 | mov x1, #SCTLR_I_C_M_MASK |
| 246 | mrs x0, sctlr_el1 |
| 247 | bic x0, x0, x1 |
| 248 | msr sctlr_el1, x0 |
| 249 | |
| 250 | /* disable dcache for EL3 */ |
| 251 | mrs x1, SCTLR_EL3 |
| 252 | bic x1, x1, #SCTLR_C_MASK |
| 253 | /* make sure icache is enabled */ |
| 254 | orr x1, x1, #SCTLR_I_MASK |
| 255 | msr SCTLR_EL3, x1 |
| 256 | isb |
| 257 | |
| 258 | /* Enable dynamic retention ctrl (CPUECTLR[2:0]) and SMP (CPUECTLR[6]) */ |
| 259 | mrs x0, CORTEX_A72_ECTLR_EL1 |
| 260 | orr x0, x0, #CPUECTLR_TIMER_8TICKS |
| 261 | orr x0, x0, #CPUECTLR_SMPEN_EN |
| 262 | msr CORTEX_A72_ECTLR_EL1, x0 |
| 263 | |
| 264 | /* set WFIL2EN in SCFG_CLUSTERPMCR */ |
| 265 | ldr x0, =SCFG_COREPMCR_OFFSET |
| 266 | ldr x1, =COREPMCR_WFIL2 |
| 267 | bl write_reg_scfg |
| 268 | |
| 269 | /* request LPM20 */ |
| 270 | mov x0, #RCPM_POWMGTCSR_OFFSET |
| 271 | bl read_reg_rcpm |
| 272 | orr x1, x0, #RCPM_POWMGTCSR_LPM20_REQ |
| 273 | mov x0, #RCPM_POWMGTCSR_OFFSET |
| 274 | bl write_reg_rcpm |
| 275 | |
| 276 | dsb sy |
| 277 | isb |
| 278 | 1: |
| 279 | wfi |
| 280 | b 1b |
| 281 | endfunc _soc_sys_off |
| 282 | |
| 283 | /* |
| 284 | * Write a register in the RCPM block |
| 285 | * in: x0 = offset |
| 286 | * in: w1 = value to write |
| 287 | * uses x0, x1, x2, x3 |
| 288 | */ |
| 289 | func write_reg_rcpm |
| 290 | ldr x2, =NXP_RCPM_ADDR |
| 291 | /* swap for BE */ |
| 292 | rev w3, w1 |
| 293 | str w3, [x2, x0] |
| 294 | ret |
| 295 | endfunc write_reg_rcpm |
| 296 | |
| 297 | /* |
| 298 | * Read a register in the RCPM block |
| 299 | * in: x0 = offset |
| 300 | * out: w0 = value read |
| 301 | * uses x0, x1, x2 |
| 302 | */ |
| 303 | func read_reg_rcpm |
| 304 | ldr x2, =NXP_RCPM_ADDR |
| 305 | ldr w1, [x2, x0] |
| 306 | /* swap for BE */ |
| 307 | rev w0, w1 |
| 308 | ret |
| 309 | endfunc read_reg_rcpm |
| 310 | |
| 311 | /* |
| 312 | * Write a register in the SCFG block |
| 313 | * in: x0 = offset |
| 314 | * in: w1 = value to write |
| 315 | * uses x0, x1, x2, x3 |
| 316 | */ |
| 317 | func write_reg_scfg |
| 318 | mov x2, #NXP_SCFG_ADDR |
| 319 | /* swap for BE */ |
| 320 | rev w3, w1 |
| 321 | str w3, [x2, x0] |
| 322 | ret |
| 323 | endfunc write_reg_scfg |
| 324 | |
| 325 | /* |
| 326 | * Read a register in the SCFG block |
| 327 | * in: x0 = offset |
| 328 | * out: w0 = value read |
| 329 | * uses x0, x1, x2 |
| 330 | */ |
| 331 | func read_reg_scfg |
| 332 | mov x2, #NXP_SCFG_ADDR |
| 333 | ldr w1, [x2, x0] |
| 334 | /* swap for BE */ |
| 335 | rev w0, w1 |
| 336 | ret |
| 337 | endfunc read_reg_scfg |
| 338 | |
| 339 | /* |
| 340 | * Part of CPU_OFF |
| 341 | * this function programs SoC & GIC registers in preparation for shutting down |
| 342 | * the core |
| 343 | * in: x0 = core mask lsb |
| 344 | * out: none |
| 345 | * uses x0, x1, x2, x3, x4, x5, x6, x7 |
| 346 | */ |
| 347 | func _soc_core_prep_off |
| 348 | mov x7, x30 |
| 349 | mov x6, x0 |
| 350 | |
| 351 | /* Set retention control in CPUECTLR make sure smpen bit is set */ |
| 352 | mrs x4, CORTEX_A72_ECTLR_EL1 |
| 353 | bic x4, x4, #CPUECTLR_RET_MASK |
| 354 | orr x4, x4, #CPUECTLR_TIMER_8TICKS |
| 355 | orr x4, x4, #CPUECTLR_SMPEN_EN |
| 356 | msr CORTEX_A72_ECTLR_EL1, x4 |
| 357 | |
| 358 | /* save timer control current value */ |
| 359 | mov x5, #NXP_TIMER_ADDR |
| 360 | ldr w4, [x5, #SYS_COUNTER_CNTCR_OFFSET] |
| 361 | mov w2, w4 |
| 362 | mov x0, x6 |
| 363 | mov x1, #TIMER_CNTRL_DATA |
| 364 | bl _setCoreData |
| 365 | |
| 366 | /* enable the timer */ |
| 367 | orr w4, w4, #CNTCR_EN_MASK |
| 368 | str w4, [x5, #SYS_COUNTER_CNTCR_OFFSET] |
| 369 | |
| 370 | bl _getGICC_BaseAddr |
| 371 | mov x5, x0 |
| 372 | |
| 373 | /* disable signaling of ints */ |
| 374 | ldr w3, [x5, #GICC_CTLR_OFFSET] |
| 375 | bic w3, w3, #GICC_CTLR_EN_GRP0 |
| 376 | bic w3, w3, #GICC_CTLR_EN_GRP1 |
| 377 | str w3, [x5, #GICC_CTLR_OFFSET] |
| 378 | dsb sy |
| 379 | isb |
| 380 | |
| 381 | |
| 382 | /* |
| 383 | * set retention control in SCFG_RETREQCR |
| 384 | * Note: this register is msb 0 |
| 385 | */ |
| 386 | ldr x4, =SCFG_RETREQCR_OFFSET |
| 387 | mov x0, x4 |
| 388 | bl read_reg_scfg |
| 389 | rbit w1, w6 |
| 390 | orr w1, w0, w1 |
| 391 | mov x0, x4 |
| 392 | bl write_reg_scfg |
| 393 | |
| 394 | /* set the priority filter */ |
| 395 | ldr w2, [x5, #GICC_PMR_OFFSET] |
| 396 | orr w2, w2, #GICC_PMR_FILTER |
| 397 | str w2, [x5, #GICC_PMR_OFFSET] |
| 398 | |
| 399 | /* setup GICC_CTLR */ |
| 400 | bic w3, w3, #GICC_CTLR_ACKCTL_MASK |
| 401 | orr w3, w3, #GICC_CTLR_FIQ_EN_MASK |
| 402 | orr w3, w3, #GICC_CTLR_EOImodeS_MASK |
| 403 | orr w3, w3, #GICC_CTLR_CBPR_MASK |
| 404 | str w3, [x5, #GICC_CTLR_OFFSET] |
| 405 | |
| 406 | /* setup the banked-per-core GICD registers */ |
| 407 | bl _getGICD_BaseAddr |
| 408 | mov x5, x0 |
| 409 | |
| 410 | /* define SGI15 as Grp0 */ |
| 411 | ldr w2, [x5, #GICD_IGROUPR0_OFFSET] |
| 412 | bic w2, w2, #GICD_IGROUP0_SGI15 |
| 413 | str w2, [x5, #GICD_IGROUPR0_OFFSET] |
| 414 | |
| 415 | /* set priority of SGI 15 to highest... */ |
| 416 | ldr w2, [x5, #GICD_IPRIORITYR3_OFFSET] |
| 417 | bic w2, w2, #GICD_IPRIORITY_SGI15_MASK |
| 418 | str w2, [x5, #GICD_IPRIORITYR3_OFFSET] |
| 419 | |
| 420 | /* enable SGI 15 */ |
| 421 | ldr w2, [x5, #GICD_ISENABLER0_OFFSET] |
| 422 | orr w2, w2, #GICD_ISENABLE0_SGI15 |
| 423 | str w2, [x5, #GICD_ISENABLER0_OFFSET] |
| 424 | |
| 425 | /* enable the cpu interface */ |
| 426 | bl _getGICC_BaseAddr |
| 427 | mov x2, x0 |
| 428 | orr w3, w3, #GICC_CTLR_EN_GRP0 |
| 429 | str w3, [x2, #GICC_CTLR_OFFSET] |
| 430 | |
| 431 | |
| 432 | /* clear any pending SGIs */ |
| 433 | ldr x2, =GICD_CPENDSGIR_CLR_MASK |
| 434 | add x0, x5, #GICD_CPENDSGIR3_OFFSET |
| 435 | str w2, [x0] |
| 436 | |
| 437 | /* |
| 438 | * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR |
| 439 | * this is an lsb-0 register |
| 440 | */ |
| 441 | mov x1, x6 |
| 442 | mov x0, #RCPM_PCPH20SETR_OFFSET |
| 443 | bl write_reg_rcpm |
| 444 | |
| 445 | dsb sy |
| 446 | isb |
| 447 | mov x30, x7 |
| 448 | ret |
| 449 | endfunc _soc_core_prep_off |
| 450 | |
| 451 | /* |
| 452 | * Part of CPU_OFF |
| 453 | * this function performs the final steps to shutdown the core |
| 454 | * in: x0 = core mask lsb |
| 455 | * out: none |
| 456 | * uses x0, x1, x2, x3, x4, x5 |
| 457 | */ |
| 458 | func _soc_core_entr_off |
| 459 | mov x5, x30 |
| 460 | mov x4, x0 |
| 461 | |
| 462 | bl _getGICD_BaseAddr |
| 463 | mov x3, x0 |
| 464 | |
| 465 | 3: |
| 466 | /* enter low-power state by executing wfi */ |
| 467 | wfi |
| 468 | |
| 469 | /* see if we got hit by SGI 15 */ |
| 470 | add x0, x3, #GICD_SPENDSGIR3_OFFSET |
| 471 | ldr w2, [x0] |
| 472 | and w2, w2, #GICD_SPENDSGIR3_SGI15_MASK |
| 473 | cbz w2, 4f |
| 474 | |
| 475 | /* clear the pending SGI */ |
| 476 | ldr x2, =GICD_CPENDSGIR_CLR_MASK |
| 477 | add x0, x3, #GICD_CPENDSGIR3_OFFSET |
| 478 | str w2, [x0] |
| 479 | 4: |
| 480 | /* check if core has been turned on */ |
| 481 | mov x0, x4 |
| 482 | bl _getCoreState |
| 483 | |
| 484 | cmp x0, #CORE_WAKEUP |
| 485 | b.ne 3b |
| 486 | |
| 487 | /* if we get here, then we have exited the wfi */ |
| 488 | dsb sy |
| 489 | isb |
| 490 | mov x30, x5 |
| 491 | ret |
| 492 | endfunc _soc_core_entr_off |
| 493 | |
| 494 | /* |
| 495 | * Part of CPU_OFF |
| 496 | * this function starts the process of starting a core back up |
| 497 | * in: x0 = core mask lsb |
| 498 | * out: none |
| 499 | * uses x0, x1, x2, x3, x4, x5, x6 |
| 500 | */ |
| 501 | func _soc_core_exit_off |
| 502 | mov x6, x30 |
| 503 | mov x5, x0 |
| 504 | |
| 505 | /* |
| 506 | * Clear ph20 request in RCPM_PCPH20CLRR - no need |
| 507 | * to do that here, it has been done in _soc_core_restart |
| 508 | */ |
| 509 | bl _getGICC_BaseAddr |
| 510 | mov x1, x0 |
| 511 | |
| 512 | /* read GICC_IAR */ |
| 513 | ldr w0, [x1, #GICC_IAR_OFFSET] |
| 514 | |
| 515 | /* write GICC_EIOR - signal end-of-interrupt */ |
| 516 | str w0, [x1, #GICC_EOIR_OFFSET] |
| 517 | |
| 518 | /* write GICC_DIR - disable interrupt */ |
| 519 | str w0, [x1, #GICC_DIR_OFFSET] |
| 520 | |
| 521 | /* disable signaling of grp0 ints */ |
| 522 | ldr w3, [x1, #GICC_CTLR_OFFSET] |
| 523 | bic w3, w3, #GICC_CTLR_EN_GRP0 |
| 524 | str w3, [x1, #GICC_CTLR_OFFSET] |
| 525 | |
| 526 | /* |
| 527 | * Unset retention request in SCFG_RETREQCR |
| 528 | * Note: this register is msb-0 |
| 529 | */ |
| 530 | ldr x4, =SCFG_RETREQCR_OFFSET |
| 531 | mov x0, x4 |
| 532 | bl read_reg_scfg |
| 533 | rbit w1, w5 |
| 534 | bic w1, w0, w1 |
| 535 | mov x0, x4 |
| 536 | bl write_reg_scfg |
| 537 | |
| 538 | /* restore timer ctrl */ |
| 539 | mov x0, x5 |
| 540 | mov x1, #TIMER_CNTRL_DATA |
| 541 | bl _getCoreData |
| 542 | /* w0 = timer ctrl saved value */ |
| 543 | mov x2, #NXP_TIMER_ADDR |
| 544 | str w0, [x2, #SYS_COUNTER_CNTCR_OFFSET] |
| 545 | |
| 546 | dsb sy |
| 547 | isb |
| 548 | mov x30, x6 |
| 549 | ret |
| 550 | endfunc _soc_core_exit_off |
| 551 | |
| 552 | /* |
| 553 | * Function loads a 64-bit execution address of the core in the soc registers |
| 554 | * BOOTLOCPTRL/H |
| 555 | * in: x0, 64-bit address to write to BOOTLOCPTRL/H |
| 556 | * uses x0, x1, x2, x3 |
| 557 | */ |
| 558 | func _soc_set_start_addr |
| 559 | /* get the 64-bit base address of the scfg block */ |
| 560 | ldr x2, =NXP_SCFG_ADDR |
| 561 | |
| 562 | /* write the 32-bit BOOTLOCPTRL register */ |
| 563 | mov x1, x0 |
| 564 | rev w3, w1 |
| 565 | str w3, [x2, #SCFG_BOOTLOCPTRL_OFFSET] |
| 566 | |
| 567 | /* write the 32-bit BOOTLOCPTRH register */ |
| 568 | lsr x1, x0, #32 |
| 569 | rev w3, w1 |
| 570 | str w3, [x2, #SCFG_BOOTLOCPTRH_OFFSET] |
| 571 | ret |
| 572 | endfunc _soc_set_start_addr |
| 573 | |
| 574 | /* |
| 575 | * This function returns the base address of the gic distributor |
| 576 | * in: none |
| 577 | * out: x0 = base address of gic distributor |
| 578 | * uses x0 |
| 579 | */ |
| 580 | func _getGICD_BaseAddr |
| 581 | #if (TEST_BL31) |
| 582 | /* defect in simulator - gic base addresses are on 4Kb boundary */ |
| 583 | ldr x0, =NXP_GICD_4K_ADDR |
| 584 | #else |
| 585 | ldr x0, =NXP_GICD_64K_ADDR |
| 586 | #endif |
| 587 | ret |
| 588 | endfunc _getGICD_BaseAddr |
| 589 | |
| 590 | /* |
| 591 | * This function returns the base address of the gic controller |
| 592 | * in: none |
| 593 | * out: x0 = base address of gic controller |
| 594 | * uses x0 |
| 595 | */ |
| 596 | func _getGICC_BaseAddr |
| 597 | #if (TEST_BL31) |
| 598 | /* defect in simulator - gic base addresses are on 4Kb boundary */ |
| 599 | ldr x0, =NXP_GICC_4K_ADDR |
| 600 | #else |
| 601 | ldr x0, =NXP_GICC_64K_ADDR |
| 602 | #endif |
| 603 | ret |
| 604 | endfunc _getGICC_BaseAddr |
| 605 | |
| 606 | /* |
| 607 | * Part of CPU_SUSPEND |
| 608 | * this function puts the calling core into standby state |
| 609 | * in: x0 = core mask lsb |
| 610 | * out: none |
| 611 | * uses x0 |
| 612 | */ |
| 613 | func _soc_core_entr_stdby |
| 614 | dsb sy |
| 615 | isb |
| 616 | wfi |
| 617 | |
| 618 | ret |
| 619 | endfunc _soc_core_entr_stdby |
| 620 | |
| 621 | |
| 622 | /* |
| 623 | * Part of CPU_SUSPEND |
| 624 | * this function performs SoC-specific programming prior to standby |
| 625 | * in: x0 = core mask lsb |
| 626 | * out: none |
| 627 | * uses x0, x1 |
| 628 | */ |
| 629 | func _soc_core_prep_stdby |
| 630 | /* clear CORTEX_A72_ECTLR_EL1[2:0] */ |
| 631 | mrs x1, CORTEX_A72_ECTLR_EL1 |
| 632 | bic x1, x1, #CPUECTLR_TIMER_MASK |
| 633 | msr CORTEX_A72_ECTLR_EL1, x1 |
| 634 | |
| 635 | ret |
| 636 | endfunc _soc_core_prep_stdby |
| 637 | |
| 638 | /* |
| 639 | * Part of CPU_SUSPEND |
| 640 | * this function performs any SoC-specific cleanup after standby state |
| 641 | * in: x0 = core mask lsb |
| 642 | * out: none |
| 643 | * uses none |
| 644 | */ |
| 645 | func _soc_core_exit_stdby |
| 646 | ret |
| 647 | endfunc _soc_core_exit_stdby |
| 648 | |
| 649 | /* |
| 650 | * Part of CPU_SUSPEND |
| 651 | * this function performs SoC-specific programming prior to power-down |
| 652 | * in: x0 = core mask lsb |
| 653 | * out: none |
| 654 | * uses x0, x1, x2, x3, x4, x5 |
| 655 | */ |
| 656 | func _soc_core_prep_pwrdn |
| 657 | mov x5, x30 |
| 658 | mov x4, x0 |
| 659 | |
| 660 | /* enable CPU retention + set smp */ |
| 661 | mrs x1, CORTEX_A72_ECTLR_EL1 |
| 662 | orr x1, x1, #0x1 |
| 663 | orr x1, x1, #CPUECTLR_SMPEN_MASK |
| 664 | msr CORTEX_A72_ECTLR_EL1, x1 |
| 665 | |
| 666 | /* |
| 667 | * set the retention request in SCFG_RETREQCR |
| 668 | * this is an msb-0 register |
| 669 | */ |
| 670 | ldr x3, =SCFG_RETREQCR_OFFSET |
| 671 | mov x0, x3 |
| 672 | bl read_reg_scfg |
| 673 | rbit w1, w4 |
| 674 | orr w1, w0, w1 |
| 675 | mov x0, x3 |
| 676 | bl write_reg_scfg |
| 677 | |
| 678 | /* |
| 679 | * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR |
| 680 | * this is an lsb-0 register |
| 681 | */ |
| 682 | mov x1, x4 |
| 683 | mov x0, #RCPM_PCPH20SETR_OFFSET |
| 684 | bl write_reg_rcpm |
| 685 | |
| 686 | mov x30, x5 |
| 687 | ret |
| 688 | endfunc _soc_core_prep_pwrdn |
| 689 | |
| 690 | /* |
| 691 | * Part of CPU_SUSPEND |
| 692 | * this function puts the calling core into a power-down state |
| 693 | * in: x0 = core mask lsb |
| 694 | * out: none |
| 695 | * uses x0 |
| 696 | */ |
| 697 | func _soc_core_entr_pwrdn |
| 698 | dsb sy |
| 699 | isb |
| 700 | wfi |
| 701 | |
| 702 | ret |
| 703 | endfunc _soc_core_entr_pwrdn |
| 704 | |
| 705 | /* |
| 706 | * Part of CPU_SUSPEND |
| 707 | * this function cleans up after a core exits power-down |
| 708 | * in: x0 = core mask lsb |
| 709 | * out: none |
| 710 | * uses x0, x1, x2, x3, x4, x5 |
| 711 | */ |
| 712 | func _soc_core_exit_pwrdn |
| 713 | mov x5, x30 |
| 714 | mov x4, x0 |
| 715 | |
| 716 | /* |
| 717 | * Set the PC_PH20_REQ bit in RCPM_PCPH20CLRR |
| 718 | * this is an lsb-0 register |
| 719 | */ |
| 720 | mov x1, x4 |
| 721 | mov x0, #RCPM_PCPH20CLRR_OFFSET |
| 722 | bl write_reg_rcpm |
| 723 | |
| 724 | /* |
| 725 | * Unset the retention request in SCFG_RETREQCR |
| 726 | * this is an msb-0 register |
| 727 | */ |
| 728 | ldr x3, =SCFG_RETREQCR_OFFSET |
| 729 | mov x0, x3 |
| 730 | bl read_reg_scfg |
| 731 | rbit w1, w4 |
| 732 | bic w1, w0, w1 |
| 733 | mov x0, x3 |
| 734 | bl write_reg_scfg |
| 735 | |
| 736 | mov x30, x5 |
| 737 | ret |
| 738 | endfunc _soc_core_exit_pwrdn |
| 739 | |
| 740 | /* |
| 741 | * Part of CPU_SUSPEND |
| 742 | * this function performs SoC-specific programming prior to standby |
| 743 | * in: x0 = core mask lsb |
| 744 | * out: none |
| 745 | * uses none |
| 746 | */ |
| 747 | func _soc_clstr_prep_stdby |
| 748 | /* clear CORTEX_A72_ECTLR_EL1[2:0] */ |
| 749 | mrs x1, CORTEX_A72_ECTLR_EL1 |
| 750 | bic x1, x1, #CPUECTLR_TIMER_MASK |
| 751 | msr CORTEX_A72_ECTLR_EL1, x1 |
| 752 | |
| 753 | ret |
| 754 | endfunc _soc_clstr_prep_stdby |
| 755 | |
| 756 | /* |
| 757 | * Part of CPU_SUSPEND |
| 758 | * this function performs any SoC-specific cleanup after standby state |
| 759 | * in: x0 = core mask lsb |
| 760 | * out: none |
| 761 | * uses none |
| 762 | */ |
| 763 | func _soc_clstr_exit_stdby |
| 764 | ret |
| 765 | endfunc _soc_clstr_exit_stdby |
| 766 | |
| 767 | /* |
| 768 | * Part of CPU_SUSPEND |
| 769 | * this function performs SoC-specific programming prior to power-down |
| 770 | * in: x0 = core mask lsb |
| 771 | * out: none |
| 772 | * uses x0, x1, x2, x3, x4, x5 |
| 773 | */ |
| 774 | func _soc_clstr_prep_pwrdn |
| 775 | mov x5, x30 |
| 776 | mov x4, x0 |
| 777 | |
| 778 | /* enable CPU retention + set smp */ |
| 779 | mrs x1, CORTEX_A72_ECTLR_EL1 |
| 780 | orr x1, x1, #0x1 |
| 781 | orr x1, x1, #CPUECTLR_SMPEN_MASK |
| 782 | msr CORTEX_A72_ECTLR_EL1, x1 |
| 783 | |
| 784 | /* |
| 785 | * Set the retention request in SCFG_RETREQCR |
| 786 | * this is an msb-0 register. |
| 787 | */ |
| 788 | ldr x3, =SCFG_RETREQCR_OFFSET |
| 789 | mov x0, x3 |
| 790 | bl read_reg_scfg |
| 791 | rbit w1, w4 |
| 792 | orr w1, w0, w1 |
| 793 | mov x0, x3 |
| 794 | bl write_reg_scfg |
| 795 | |
| 796 | /* |
| 797 | * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR |
| 798 | * this is an lsb-0 register. |
| 799 | */ |
| 800 | mov x1, x4 |
| 801 | mov x0, #RCPM_PCPH20SETR_OFFSET |
| 802 | bl write_reg_rcpm |
| 803 | |
| 804 | mov x30, x5 |
| 805 | ret |
| 806 | endfunc _soc_clstr_prep_pwrdn |
| 807 | |
| 808 | /* |
| 809 | * Part of CPU_SUSPEND |
| 810 | * this function cleans up after a core exits power-down |
| 811 | * in: x0 = core mask lsb |
| 812 | * out: none |
| 813 | * uses x0, x1, x2, x3, x4, x5 |
| 814 | */ |
| 815 | func _soc_clstr_exit_pwrdn |
| 816 | mov x5, x30 |
| 817 | mov x4, x0 |
| 818 | |
| 819 | /* |
| 820 | * Set the PC_PH20_REQ bit in RCPM_PCPH20CLRR |
| 821 | * this is an lsb-0 register. |
| 822 | */ |
| 823 | mov x1, x4 |
| 824 | mov x0, #RCPM_PCPH20CLRR_OFFSET |
| 825 | bl write_reg_rcpm |
| 826 | |
| 827 | /* |
| 828 | * Unset the retention request in SCFG_RETREQCR |
| 829 | * this is an msb-0 register. |
| 830 | */ |
| 831 | ldr x3, =SCFG_RETREQCR_OFFSET |
| 832 | mov x0, x3 |
| 833 | bl read_reg_scfg |
| 834 | rbit w1, w4 |
| 835 | bic w1, w0, w1 |
| 836 | mov x0, x3 |
| 837 | bl write_reg_scfg |
| 838 | |
| 839 | mov x30, x5 |
| 840 | ret |
| 841 | endfunc _soc_clstr_exit_pwrdn |
| 842 | |
| 843 | /* |
| 844 | * Part of CPU_SUSPEND |
| 845 | * this function performs SoC-specific programming prior to standby |
| 846 | * in: x0 = core mask lsb |
| 847 | * out: none |
| 848 | * uses none |
| 849 | */ |
| 850 | func _soc_sys_prep_stdby |
| 851 | /* clear CORTEX_A72_ECTLR_EL1[2:0] */ |
| 852 | mrs x1, CORTEX_A72_ECTLR_EL1 |
| 853 | bic x1, x1, #CPUECTLR_TIMER_MASK |
| 854 | msr CORTEX_A72_ECTLR_EL1, x1 |
| 855 | |
| 856 | ret |
| 857 | endfunc _soc_sys_prep_stdby |
| 858 | |
| 859 | /* Part of CPU_SUSPEND |
| 860 | * this function performs any SoC-specific cleanup after standby state |
| 861 | * in: x0 = core mask lsb |
| 862 | * out: none |
| 863 | * uses none |
| 864 | */ |
| 865 | func _soc_sys_exit_stdby |
| 866 | ret |
| 867 | endfunc _soc_sys_exit_stdby |
| 868 | |
| 869 | /* |
| 870 | * Part of CPU_SUSPEND |
| 871 | * this function performs SoC-specific programming prior to |
| 872 | * suspend-to-power-down |
| 873 | * in: x0 = core mask lsb |
| 874 | * out: none |
| 875 | * uses x0, x1, x2, x3, x4 |
| 876 | */ |
| 877 | func _soc_sys_prep_pwrdn |
| 878 | mov x4, x30 |
| 879 | |
| 880 | /* Enable dynamic retention contrl (CPUECTLR[2:0]) and SMP (CPUECTLR[6]) */ |
| 881 | mrs x0, CORTEX_A72_ECTLR_EL1 |
| 882 | bic x0, x0, #CPUECTLR_TIMER_MASK |
| 883 | orr x0, x0, #CPUECTLR_TIMER_8TICKS |
| 884 | orr x0, x0, #CPUECTLR_SMPEN_EN |
| 885 | msr CORTEX_A72_ECTLR_EL1, x0 |
| 886 | |
| 887 | /* Set WFIL2EN in SCFG_CLUSTERPMCR */ |
| 888 | ldr x0, =SCFG_COREPMCR_OFFSET |
| 889 | ldr x1, =COREPMCR_WFIL2 |
| 890 | bl write_reg_scfg |
| 891 | |
| 892 | isb |
| 893 | mov x30, x4 |
| 894 | ret |
| 895 | endfunc _soc_sys_prep_pwrdn |
| 896 | |
| 897 | /* |
| 898 | * Part of CPU_SUSPEND |
| 899 | * this function puts the calling core, and potentially the soc, into a |
| 900 | * low-power state |
| 901 | * in: x0 = core mask lsb |
| 902 | * out: x0 = 0, success |
| 903 | * x0 < 0, failure |
| 904 | * uses x0, x1, x2, x3, x4 |
| 905 | */ |
| 906 | func _soc_sys_pwrdn_wfi |
| 907 | mov x4, x30 |
| 908 | |
| 909 | /* request LPM20 */ |
| 910 | mov x0, #RCPM_POWMGTCSR_OFFSET |
| 911 | bl read_reg_rcpm |
| 912 | orr x1, x0, #RCPM_POWMGTCSR_LPM20_REQ |
| 913 | mov x0, #RCPM_POWMGTCSR_OFFSET |
| 914 | bl write_reg_rcpm |
| 915 | |
| 916 | dsb sy |
| 917 | isb |
| 918 | wfi |
| 919 | |
| 920 | mov x30, x4 |
| 921 | ret |
| 922 | endfunc _soc_sys_pwrdn_wfi |
| 923 | |
| 924 | /* |
| 925 | * Part of CPU_SUSPEND |
| 926 | * this function performs any SoC-specific cleanup after power-down |
| 927 | * in: x0 = core mask lsb |
| 928 | * out: none |
| 929 | * uses x0, x1 |
| 930 | */ |
| 931 | func _soc_sys_exit_pwrdn |
| 932 | /* clear WFIL2_EN in SCFG_COREPMCR */ |
| 933 | mov x1, #NXP_SCFG_ADDR |
| 934 | str wzr, [x1, #SCFG_COREPMCR_OFFSET] |
| 935 | |
| 936 | ret |
| 937 | endfunc _soc_sys_exit_pwrdn |