1/* SPDX-License-Identifier: BSD-2-Clause */ 2/* 3 * Copyright 2017 NXP 4 */ 5 6#include <arm.h> 7#include <arm32_macros.S> 8#include <asm.S> 9#include <generated/imx_pm_asm_defines.h> 10#include <imx-regs.h> 11#include <kernel/cache_helpers.h> 12#include <kernel/tz_proc_def.h> 13#include <kernel/tz_ssvce_def.h> 14#include <platform_config.h> 15 16#define MX7_SRC_GPR1 0x74 17#define MX7_SRC_GPR2 0x78 18#define GPC_PGC_C0 0x800 19#define GPC_PGC_FM 0xa00 20#define ANADIG_SNVS_MISC_CTRL 0x380 21#define ANADIG_SNVS_MISC_CTRL_SET 0x384 22#define ANADIG_SNVS_MISC_CTRL_CLR 0x388 23#define ANADIG_DIGPROG 0x800 24#define DDRC_STAT 0x4 25#define DDRC_PWRCTL 0x30 26#define DDRC_PSTAT 0x3fc 27#define DDRC_PCTRL_0 0x490 28#define DDRC_DFIMISC 0x1b0 29#define DDRC_SWCTL 0x320 30#define DDRC_SWSTAT 0x324 31#define DDRPHY_LP_CON0 0x18 32 33#define CCM_SNVS_LPCG 0x250 34#define MX7D_GPC_IMR1 0x30 35#define MX7D_GPC_IMR2 0x34 36#define MX7D_GPC_IMR3 0x38 37#define MX7D_GPC_IMR4 0x3c 38 39/* 40 * The code in this file is copied to coherent on-chip ram memory, 41 * without any dependency on code/data in tee memory(DDR). 42 */ 43 .section .text.psci.suspend 44 .align 3 45 46 .macro disable_l1_dcache 47 48 /* 49 * flush L1 data cache before clearing SCTLR.C bit. 50 */ 51 push {r0 - r10, lr} 52 ldr r1, =dcache_op_all 53 mov r0, #DCACHE_OP_CLEAN_INV 54 mov lr, pc 55 bx r1 56 pop {r0 - r10, lr} 57 58 /* disable d-cache */ 59 read_sctlr r7 60 bic r7, r7, #SCTLR_C 61 write_sctlr r7 62 dsb 63 isb 64 65 push {r0 - r10, lr} 66 ldr r1, =dcache_op_all 67 mov r0, #DCACHE_OP_CLEAN_INV 68 mov lr, pc 69 bx r1 70 pop {r0 - r10, lr} 71 72 .endm 73 74 .macro store_ttbr 75 76 /* Store TTBR1 to pm_info->ttbr1 */ 77 read_ttbr1 r7 78 str r7, [r0, #PM_INFO_MX7_TTBR1_OFF] 79 80 /* Store TTBR0 to pm_info->ttbr1 */ 81 read_ttbr0 r7 82 str r7, [r0, #PM_INFO_MX7_TTBR0_OFF] 83 84 /* Disable Branch Prediction */ 85 read_sctlr r6 86 bic r6, r6, #SCTLR_Z 87 write_sctlr r6 88 89 /* Flush the BTAC. */ 90 write_bpiallis 91 92 ldr r6, =iram_tbl_phys_addr 93 ldr r6, [r6] 94 dsb 95 isb 96 97 /* Store the IRAM table in TTBR1/0 */ 98 write_ttbr1 r6 99 write_ttbr0 r6 100 101 /* Read TTBCR and set PD0=1 */ 102 read_ttbcr r6 103 orr r6, r6, #TTBCR_PD0 104 write_ttbcr r6 105 106 dsb 107 isb 108 109 /* flush the TLB */ 110 write_tlbiallis 111 isb 112 write_tlbiall 113 isb 114 115 .endm 116 117 .macro restore_ttbr 118 119 /* Enable L1 data cache. */ 120 read_sctlr r6 121 orr r6, r6, #SCTLR_C 122 write_sctlr r6 123 124 dsb 125 isb 126 127 /* Restore TTBCR */ 128 /* Read TTBCR and set PD0=0 */ 129 read_ttbcr r6 130 bic r6, r6, #TTBCR_PD0 131 write_ttbcr r6 132 dsb 133 isb 134 135 /* flush the TLB */ 136 write_tlbiallis 137 138 /* Enable Branch Prediction */ 139 read_sctlr r6 140 orr r6, r6, #SCTLR_Z 141 write_sctlr r6 142 143 /* Flush the Branch Target Address Cache (BTAC) */ 144 write_bpiallis 145 146 /* Restore TTBR1/0, get the origin ttbr1/0 from pm info */ 147 ldr r7, [r0, #PM_INFO_MX7_TTBR1_OFF] 148 write_ttbr1 r7 149 ldr r7, [r0, #PM_INFO_MX7_TTBR0_OFF] 150 write_ttbr0 r7 151 isb 152 153 .endm 154 155 .macro ddrc_enter_self_refresh 156 157 ldr r11, [r0, #PM_INFO_MX7_DDRC_V_OFF] 158 159 /* let DDR out of self-refresh */ 160 ldr r7, =0x0 161 str r7, [r11, #DDRC_PWRCTL] 162 163 /* wait rw port_busy clear */ 164 ldr r6, =BIT32(16) 165 orr r6, r6, #0x1 1661: 167 ldr r7, [r11, #DDRC_PSTAT] 168 ands r7, r7, r6 169 bne 1b 170 171 /* enter self-refresh bit 5 */ 172 ldr r7, =BIT32(5) 173 str r7, [r11, #DDRC_PWRCTL] 174 175 /* wait until self-refresh mode entered */ 1762: 177 ldr r7, [r11, #DDRC_STAT] 178 and r7, r7, #0x3 179 cmp r7, #0x3 180 bne 2b 1813: 182 ldr r7, [r11, #DDRC_STAT] 183 ands r7, r7, #0x20 184 beq 3b 185 186 /* disable dram clk */ 187 ldr r7, [r11, #DDRC_PWRCTL] 188 orr r7, r7, #BIT32(3) 189 str r7, [r11, #DDRC_PWRCTL] 190 191 .endm 192 193 .macro ddrc_exit_self_refresh 194 195 cmp r5, #0x0 196 ldreq r11, [r0, #PM_INFO_MX7_DDRC_V_OFF] 197 ldrne r11, [r0, #PM_INFO_MX7_DDRC_P_OFF] 198 199 /* let DDR out of self-refresh */ 200 ldr r7, =0x0 201 str r7, [r11, #DDRC_PWRCTL] 202 203 /* wait until self-refresh mode entered */ 2044: 205 ldr r7, [r11, #DDRC_STAT] 206 and r7, r7, #0x3 207 cmp r7, #0x3 208 beq 4b 209 210 /* enable auto self-refresh */ 211 ldr r7, [r11, #DDRC_PWRCTL] 212 orr r7, r7, #BIT32(0) 213 str r7, [r11, #DDRC_PWRCTL] 214 215 .endm 216 217 .macro wait_delay 2185: 219 subs r6, r6, #0x1 220 bne 5b 221 222 .endm 223 224 .macro ddr_enter_retention 225 226 ldr r11, [r0, #PM_INFO_MX7_DDRC_V_OFF] 227 228 /* let DDR out of self-refresh */ 229 ldr r7, =0x0 230 str r7, [r11, #DDRC_PCTRL_0] 231 232 /* wait rw port_busy clear */ 233 ldr r6, =BIT32(16) 234 orr r6, r6, #0x1 2356: 236 ldr r7, [r11, #DDRC_PSTAT] 237 ands r7, r7, r6 238 bne 6b 239 240 ldr r11, [r0, #PM_INFO_MX7_DDRC_V_OFF] 241 /* enter self-refresh bit 5 */ 242 ldr r7, =BIT32(5) 243 str r7, [r11, #DDRC_PWRCTL] 244 245 /* wait until self-refresh mode entered */ 2467: 247 ldr r7, [r11, #DDRC_STAT] 248 and r7, r7, #0x3 249 cmp r7, #0x3 250 bne 7b 2518: 252 ldr r7, [r11, #DDRC_STAT] 253 ands r7, r7, #0x20 254 beq 8b 255 256 /* disable dram clk */ 257 ldr r7, =BIT32(5) 258 orr r7, r7, #BIT32(3) 259 str r7, [r11, #DDRC_PWRCTL] 260 261 ldr r11, [r0, #PM_INFO_MX7_ANATOP_V_OFF] 262 ldr r7, [r11, #ANADIG_DIGPROG] 263 and r7, r7, #0xff 264 cmp r7, #0x11 265 bne 10f 266 267 /* TO 1.1 */ 268 ldr r11, [r0, #PM_INFO_MX7_IOMUXC_GPR_V_OFF] 269 ldr r7, =0x38000000 270 str r7, [r11] 271 272 /* LPSR mode need to use TO1.0 flow as IOMUX lost power */ 273 ldr r10, [r0, #PM_INFO_MX7_LPSR_V_OFF] 274 ldr r7, [r10] 275 cmp r7, #0x0 276 beq 11f 27710: 278 /* reset ddr_phy */ 279 ldr r11, [r0, #PM_INFO_MX7_ANATOP_V_OFF] 280 ldr r7, =0x0 281 str r7, [r11, #ANADIG_SNVS_MISC_CTRL] 282 283 /* delay 7 us */ 284 ldr r6, =6000 285 wait_delay 286 287 ldr r11, [r0, #PM_INFO_MX7_SRC_V_OFF] 288 ldr r6, =0x1000 289 ldr r7, [r11, r6] 290 orr r7, r7, #0x1 291 str r7, [r11, r6] 29211: 293 /* turn off ddr power */ 294 ldr r11, [r0, #PM_INFO_MX7_ANATOP_V_OFF] 295 ldr r7, =(0x1 << 29) 296 str r7, [r11, #ANADIG_SNVS_MISC_CTRL_SET] 297 298 ldr r11, [r0, #PM_INFO_MX7_SRC_V_OFF] 299 ldr r6, =0x1000 300 ldr r7, [r11, r6] 301 orr r7, r7, #0x1 302 str r7, [r11, r6] 303 304 .endm 305 306 .macro ddr_exit_retention 307 308 cmp r5, #0x0 309 ldreq r1, [r0, #PM_INFO_MX7_ANATOP_V_OFF] 310 ldrne r1, [r0, #PM_INFO_MX7_ANATOP_P_OFF] 311 ldreq r2, [r0, #PM_INFO_MX7_SRC_V_OFF] 312 ldrne r2, [r0, #PM_INFO_MX7_SRC_P_OFF] 313 ldreq r3, [r0, #PM_INFO_MX7_DDRC_V_OFF] 314 ldrne r3, [r0, #PM_INFO_MX7_DDRC_P_OFF] 315 ldreq r4, [r0, #PM_INFO_MX7_DDRC_PHY_V_OFF] 316 ldrne r4, [r0, #PM_INFO_MX7_DDRC_PHY_P_OFF] 317 ldreq r10, [r0, #PM_INFO_MX7_CCM_V_OFF] 318 ldrne r10, [r0, #PM_INFO_MX7_CCM_P_OFF] 319 ldreq r11, [r0, #PM_INFO_MX7_IOMUXC_GPR_V_OFF] 320 ldrne r11, [r0, #PM_INFO_MX7_IOMUXC_GPR_P_OFF] 321 322 /* turn on ddr power */ 323 ldr r7, =BIT32(29) 324 str r7, [r1, #ANADIG_SNVS_MISC_CTRL_CLR] 325 326 ldr r6, =50 327 wait_delay 328 329 /* clear ddr_phy reset */ 330 ldr r6, =0x1000 331 ldr r7, [r2, r6] 332 orr r7, r7, #0x3 333 str r7, [r2, r6] 334 ldr r7, [r2, r6] 335 bic r7, r7, #0x1 336 str r7, [r2, r6] 33713: 338 ldr r6, [r0, #PM_INFO_MX7_DDRC_REG_NUM_OFF] 339 ldr r7, =PM_INFO_MX7_DDRC_REG_OFF 340 add r7, r7, r0 34114: 342 ldr r8, [r7], #0x4 343 ldr r9, [r7], #0x4 344 str r9, [r3, r8] 345 subs r6, r6, #0x1 346 bne 14b 347 ldr r7, =0x20 348 str r7, [r3, #DDRC_PWRCTL] 349 ldr r7, =0x0 350 str r7, [r3, #DDRC_DFIMISC] 351 352 /* do PHY, clear ddr_phy reset */ 353 ldr r6, =0x1000 354 ldr r7, [r2, r6] 355 bic r7, r7, #0x2 356 str r7, [r2, r6] 357 358 ldr r7, [r1, #ANADIG_DIGPROG] 359 and r7, r7, #0xff 360 cmp r7, #0x11 361 bne 12f 362 363 /* 364 * TKT262940: 365 * System hang when press RST for DDR PAD is 366 * in retention mode, fixed on TO1.1 367 */ 368 ldr r7, [r11] 369 bic r7, r7, #BIT32(27) 370 str r7, [r11] 371 ldr r7, [r11] 372 bic r7, r7, #BIT32(29) 373 str r7, [r11] 37412: 375 ldr r7, =BIT32(30) 376 str r7, [r1, #ANADIG_SNVS_MISC_CTRL_SET] 377 378 /* need to delay ~5mS */ 379 ldr r6, =0x100000 380 wait_delay 381 382 ldr r6, [r0, #PM_INFO_MX7_DDRC_PHY_REG_NUM_OFF] 383 ldr r7, =PM_INFO_MX7_DDRC_PHY_REG_OFF 384 add r7, r7, r0 385 38615: 387 ldr r8, [r7], #0x4 388 ldr r9, [r7], #0x4 389 str r9, [r4, r8] 390 subs r6, r6, #0x1 391 bne 15b 392 393 ldr r7, =0x0 394 add r9, r10, #0x4000 395 str r7, [r9, #0x130] 396 397 ldr r7, =0x170 398 orr r7, r7, #0x8 399 str r7, [r11, #0x20] 400 401 ldr r7, =0x2 402 add r9, r10, #0x4000 403 str r7, [r9, #0x130] 404 405 ldr r7, =0xf 406 str r7, [r4, #DDRPHY_LP_CON0] 407 408 /* wait until self-refresh mode entered */ 40916: 410 ldr r7, [r3, #DDRC_STAT] 411 and r7, r7, #0x3 412 cmp r7, #0x3 413 bne 16b 414 ldr r7, =0x0 415 str r7, [r3, #DDRC_SWCTL] 416 ldr r7, =0x1 417 str r7, [r3, #DDRC_DFIMISC] 418 ldr r7, =0x1 419 str r7, [r3, #DDRC_SWCTL] 42017: 421 ldr r7, [r3, #DDRC_SWSTAT] 422 and r7, r7, #0x1 423 cmp r7, #0x1 424 bne 17b 42518: 426 ldr r7, [r3, #DDRC_STAT] 427 and r7, r7, #0x20 428 cmp r7, #0x20 429 bne 18b 430 431 /* let DDR out of self-refresh */ 432 ldr r7, =0x0 433 str r7, [r3, #DDRC_PWRCTL] 43419: 435 ldr r7, [r3, #DDRC_STAT] 436 and r7, r7, #0x30 437 cmp r7, #0x0 438 bne 19b 439 44020: 441 ldr r7, [r3, #DDRC_STAT] 442 and r7, r7, #0x3 443 cmp r7, #0x1 444 bne 20b 445 446 /* enable port */ 447 ldr r7, =0x1 448 str r7, [r3, #DDRC_PCTRL_0] 449 450 /* enable auto self-refresh */ 451 ldr r7, [r3, #DDRC_PWRCTL] 452 orr r7, r7, #(1 << 0) 453 str r7, [r3, #DDRC_PWRCTL] 454 455 .endm 456 457FUNC imx7_suspend, : 458UNWIND( .cantunwind) 459 push {r4-r12} 460 461 /* make sure SNVS clk is enabled */ 462 ldr r11, [r0, #PM_INFO_MX7_CCM_V_OFF] 463 add r11, r11, #0x4000 464 ldr r7, =0x3 465 str r7, [r11, #CCM_SNVS_LPCG] 466 467 /* check whether it is a standby mode */ 468 ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFF] 469 ldr r7, [r11, #GPC_PGC_C0] 470 cmp r7, #0 471 beq ddr_only_self_refresh 472 473 /* 474 * The value of r0 is mapped the same in origin table and IRAM table, 475 * thus no need to care r0 here. 476 */ 477 ldr r1, [r0, #PM_INFO_MX7_PBASE_OFF] 478 ldr r4, [r0, #PM_INFO_MX7_SIZE_OFF] 479 480 /* 481 * counting the resume address in iram 482 * to set it in SRC register. 483 */ 484 ldr r6, =imx7_suspend 485 ldr r7, =resume 486 sub r7, r7, r6 487 add r8, r1, r4 488 add r9, r8, r7 489 490 ldr r11, [r0, #PM_INFO_MX7_SRC_V_OFF] 491 /* store physical resume addr and pm_info address. */ 492 str r9, [r11, #MX7_SRC_GPR1] 493 str r1, [r11, #MX7_SRC_GPR2] 494 495 disable_l1_dcache 496 497 store_ttbr 498 499 ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFF] 500 ldr r7, [r11, #GPC_PGC_FM] 501 cmp r7, #0 502 beq ddr_only_self_refresh 503 504 ddr_enter_retention 505 /* enter LPSR mode if resume addr is valid */ 506 ldr r11, [r0, #PM_INFO_MX7_LPSR_V_OFF] 507 ldr r7, [r11] 508 cmp r7, #0x0 509 beq ddr_retention_enter_out 510 511 /* disable STOP mode before entering LPSR */ 512 ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFF] 513 ldr r7, [r11] 514 bic r7, #0xf 515 str r7, [r11] 516 517 /* shut down vddsoc to enter lpsr mode */ 518 ldr r11, [r0, #PM_INFO_MX7_SNVS_V_OFF] 519 ldr r7, [r11, #0x38] 520 orr r7, r7, #0x60 521 str r7, [r11, #0x38] 522 dsb 523wait_shutdown: 524 wfi 525 b wait_shutdown 526 527ddr_only_self_refresh: 528 ddrc_enter_self_refresh 529 b wfi 530ddr_retention_enter_out: 531 ldr r11, [r0, #PM_INFO_MX7_GIC_DIST_V_OFF] 532 ldr r7, =0x0 533 ldr r8, =0x1000 534 str r7, [r11, r8] 535 536 ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFF] 537 ldr r4, [r11, #MX7D_GPC_IMR1] 538 ldr r5, [r11, #MX7D_GPC_IMR2] 539 ldr r6, [r11, #MX7D_GPC_IMR3] 540 ldr r7, [r11, #MX7D_GPC_IMR4] 541 542 ldr r8, =0xffffffff 543 str r8, [r11, #MX7D_GPC_IMR1] 544 str r8, [r11, #MX7D_GPC_IMR2] 545 str r8, [r11, #MX7D_GPC_IMR3] 546 str r8, [r11, #MX7D_GPC_IMR4] 547 548 /* 549 * enable the RBC bypass counter here 550 * to hold off the interrupts. RBC counter 551 * = 8 (240us). With this setting, the latency 552 * from wakeup interrupt to ARM power up 553 * is ~250uS. 554 */ 555 ldr r8, [r11, #0x14] 556 bic r8, r8, #(0x3f << 24) 557 orr r8, r8, #(0x8 << 24) 558 str r8, [r11, #0x14] 559 560 /* enable the counter. */ 561 ldr r8, [r11, #0x14] 562 orr r8, r8, #(0x1 << 30) 563 str r8, [r11, #0x14] 564 565 /* unmask all the GPC interrupts. */ 566 str r4, [r11, #MX7D_GPC_IMR1] 567 str r5, [r11, #MX7D_GPC_IMR2] 568 str r6, [r11, #MX7D_GPC_IMR3] 569 str r7, [r11, #MX7D_GPC_IMR4] 570 571 /* 572 * now delay for a short while (3usec) 573 * ARM is at 1GHz at this point 574 * so a short loop should be enough. 575 * this delay is required to ensure that 576 * the RBC counter can start counting in 577 * case an interrupt is already pending 578 * or in case an interrupt arrives just 579 * as ARM is about to assert DSM_request. 580 */ 581 ldr r7, =2000 582rbc_loop: 583 subs r7, r7, #0x1 584 bne rbc_loop 585wfi: 586 dsb 587 /* Enter stop mode */ 588 wfi 589 590 mov r5, #0x0 591 592 ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFF] 593 ldr r7, [r11, #GPC_PGC_FM] 594 cmp r7, #0 595 beq wfi_ddr_self_refresh_out 596 597 ddr_exit_retention 598 b wfi_ddr_retention_out 599wfi_ddr_self_refresh_out: 600 ddrc_exit_self_refresh 601wfi_ddr_retention_out: 602 603 /* check whether it is a standby mode */ 604 ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFF] 605 ldr r7, [r11, #GPC_PGC_C0] 606 cmp r7, #0 607 beq standby_out 608 609 ldr r11, [r0, #PM_INFO_MX7_GIC_DIST_V_OFF] 610 ldr r7, =0x1 611 ldr r8, =0x1000 612 str r7, [r11, r8] 613 614 restore_ttbr 615standby_out: 616 pop {r4-r12} 617 /* return to suspend finish */ 618 bx lr 619 620resume: 621 write_iciallu 622 write_bpiall 623 dsb 624 isb 625 626 mov r6, #(SCTLR_I | SCTLR_Z) 627 write_sctlr r6 628 isb 629 630 /* 631 * After resume back, rom run in SVC mode, 632 * so we need to switch to monitor mode. 633 */ 634 cps #CPSR_MODE_MON 635 636 /* get physical resume address from pm_info. */ 637 ldr lr, [r0, #PM_INFO_MX7_RESUME_ADDR_OFF] 638 /* clear core0's entry and parameter */ 639 ldr r11, [r0, #PM_INFO_MX7_SRC_P_OFF] 640 mov r7, #0x0 641 str r7, [r11, #MX7_SRC_GPR1] 642 str r7, [r11, #MX7_SRC_GPR2] 643 644 mov r5, #0x1 645 646 ldr r11, [r0, #PM_INFO_MX7_GPC_P_OFF] 647 ldr r7, [r11, #GPC_PGC_FM] 648 cmp r7, #0 649 beq dsm_ddr_self_refresh_out 650 651 ddr_exit_retention 652 b dsm_ddr_retention_out 653dsm_ddr_self_refresh_out: 654 ddrc_exit_self_refresh 655dsm_ddr_retention_out: 656 657 bx lr 658END_FUNC imx7_suspend 659 660FUNC ca7_cpu_resume, : 661UNWIND( .cantunwind) 662 mov r0, #0 @ ; write the cache size selection register to be 663 write_csselr r0 @ ; sure we address the data cache 664 isb @ ; isb to sync the change to the cachesizeid reg 665 666_inv_dcache_off: 667 mov r0, #0 @ ; set way number to 0 668_inv_nextway: 669 mov r1, #0 @ ; set line number (=index) to 0 670_inv_nextline: 671 orr r2, r0, r1 @ ; construct way/index value 672 write_dcisw r2 @ ; invalidate data or unified cache line by set/way 673 add r1, r1, #1 << LINE_FIELD_OFFSET @ ; increment the index 674 cmp r1, #1 << LINE_FIELD_OVERFLOW @ ; overflow out of set field? 675 bne _inv_nextline 676 add r0, r0, #1 << WAY_FIELD_OFFSET @ ; increment the way number 677 cmp r0, #0 @ ; overflow out of way field? 678 bne _inv_nextway 679 680 dsb @ ; synchronise 681 isb 682 683 /* 684 * No stack, scratch r0-r3 685 * TODO: Need to use specific configure, but not plat_xxx. 686 * Because plat_xx maybe changed in future, we can not rely on it. 687 * Need handle sp carefully. 688 */ 689 blx plat_cpu_reset_early 690 691 b sm_pm_cpu_resume 692END_FUNC ca7_cpu_resume 693