1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. 4 * Copyright (c) 2011, Google, Inc. 5 * 6 * Author: Colin Cross <ccross@android.com> 7 * Gary King <gking@nvidia.com> 8 */ 9 10#include <linux/linkage.h> 11 12#include <soc/tegra/flowctrl.h> 13 14#include <asm/assembler.h> 15#include <asm/proc-fns.h> 16#include <asm/cp15.h> 17#include <asm/cache.h> 18 19#include "irammap.h" 20#include "reset.h" 21#include "sleep.h" 22 23#define EMC_CFG 0xc 24#define EMC_ADR_CFG 0x10 25#define EMC_NOP 0xdc 26#define EMC_SELF_REF 0xe0 27#define EMC_REQ_CTRL 0x2b0 28#define EMC_EMC_STATUS 0x2b4 29 30#define CLK_RESET_CCLK_BURST 0x20 31#define CLK_RESET_CCLK_DIVIDER 0x24 32#define CLK_RESET_SCLK_BURST 0x28 33#define CLK_RESET_SCLK_DIVIDER 0x2c 34#define CLK_RESET_PLLC_BASE 0x80 35#define CLK_RESET_PLLM_BASE 0x90 36#define CLK_RESET_PLLP_BASE 0xa0 37 38#define APB_MISC_XM2CFGCPADCTRL 0x8c8 39#define APB_MISC_XM2CFGDPADCTRL 0x8cc 40#define APB_MISC_XM2CLKCFGPADCTRL 0x8d0 41#define APB_MISC_XM2COMPPADCTRL 0x8d4 42#define APB_MISC_XM2VTTGENPADCTRL 0x8d8 43#define APB_MISC_XM2CFGCPADCTRL2 0x8e4 44#define APB_MISC_XM2CFGDPADCTRL2 0x8e8 45 46#define __tegra20_cpu1_resettable_status_offset \ 47 (__tegra_cpu_reset_handler_data_offset + RESET_DATA(RESETTABLE_STATUS)) 48 49.macro pll_enable, rd, r_car_base, pll_base 50 ldr \rd, [\r_car_base, #\pll_base] 51 tst \rd, #(1 << 30) 52 orreq \rd, \rd, #(1 << 30) 53 streq \rd, [\r_car_base, #\pll_base] 54.endm 55 56.macro emc_device_mask, rd, base 57 ldr \rd, [\base, #EMC_ADR_CFG] 58 tst \rd, #(0x3 << 24) 59 moveq \rd, #(0x1 << 8) @ just 1 device 60 movne \rd, #(0x3 << 8) @ 2 devices 61.endm 62 63#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP) 64/* 65 * tegra20_hotplug_shutdown(void) 66 * 67 * puts the current cpu in reset 68 * should never return 69 */ 70ENTRY(tegra20_hotplug_shutdown) 71 /* Put this CPU down */ 72 cpu_id r0 73 bl tegra20_cpu_shutdown 74 ret lr @ should never get here 75ENDPROC(tegra20_hotplug_shutdown) 76 77/* 78 * tegra20_cpu_shutdown(int cpu) 79 * 80 * r0 is cpu to reset 81 * 82 * puts the specified CPU in wait-for-event mode on the flow controller 83 * and puts the CPU in reset 84 * can be called on the current cpu or another cpu 85 * if called on the current cpu, does not return 86 * MUST NOT BE CALLED FOR CPU 0. 87 * 88 * corrupts r0-r3, r12 89 */ 90ENTRY(tegra20_cpu_shutdown) 91 cmp r0, #0 92 reteq lr @ must not be called for CPU 0 93 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT 94 ldr r2, =__tegra20_cpu1_resettable_status_offset 95 mov r12, #CPU_RESETTABLE 96 strb r12, [r1, r2] 97 98 cpu_to_halt_reg r1, r0 99 ldr r3, =TEGRA_FLOW_CTRL_VIRT 100 mov r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME 101 str r2, [r3, r1] @ put flow controller in wait event mode 102 ldr r2, [r3, r1] 103 isb 104 dsb 105 movw r1, 0x1011 106 mov r1, r1, lsl r0 107 ldr r3, =TEGRA_CLK_RESET_VIRT 108 str r1, [r3, #0x340] @ put slave CPU in reset 109 isb 110 dsb 111 cpu_id r3 112 cmp r3, r0 113 beq . 114 ret lr 115ENDPROC(tegra20_cpu_shutdown) 116#endif 117 118#ifdef CONFIG_PM_SLEEP 119/* 120 * tegra_pen_lock 121 * 122 * spinlock implementation with no atomic test-and-set and no coherence 123 * using Peterson's algorithm on strongly-ordered registers 124 * used to synchronize a cpu waking up from wfi with entering lp2 on idle 125 * 126 * The reference link of Peterson's algorithm: 127 * http://en.wikipedia.org/wiki/Peterson's_algorithm 128 * 129 * SCRATCH37 = r1 = !turn (inverted from Peterson's algorithm) 130 * on cpu 0: 131 * r2 = flag[0] (in SCRATCH38) 132 * r3 = flag[1] (in SCRATCH39) 133 * on cpu1: 134 * r2 = flag[1] (in SCRATCH39) 135 * r3 = flag[0] (in SCRATCH38) 136 * 137 * must be called with MMU on 138 * corrupts r0-r3, r12 139 */ 140ENTRY(tegra_pen_lock) 141 mov32 r3, TEGRA_PMC_VIRT 142 cpu_id r0 143 add r1, r3, #PMC_SCRATCH37 144 cmp r0, #0 145 addeq r2, r3, #PMC_SCRATCH38 146 addeq r3, r3, #PMC_SCRATCH39 147 addne r2, r3, #PMC_SCRATCH39 148 addne r3, r3, #PMC_SCRATCH38 149 150 mov r12, #1 151 str r12, [r2] @ flag[cpu] = 1 152 dsb 153 str r12, [r1] @ !turn = cpu 1541: dsb 155 ldr r12, [r3] 156 cmp r12, #1 @ flag[!cpu] == 1? 157 ldreq r12, [r1] 158 cmpeq r12, r0 @ !turn == cpu? 159 beq 1b @ while !turn == cpu && flag[!cpu] == 1 160 161 ret lr @ locked 162ENDPROC(tegra_pen_lock) 163 164ENTRY(tegra_pen_unlock) 165 dsb 166 mov32 r3, TEGRA_PMC_VIRT 167 cpu_id r0 168 cmp r0, #0 169 addeq r2, r3, #PMC_SCRATCH38 170 addne r2, r3, #PMC_SCRATCH39 171 mov r12, #0 172 str r12, [r2] 173 ret lr 174ENDPROC(tegra_pen_unlock) 175 176/* 177 * tegra20_cpu_clear_resettable(void) 178 * 179 * Called to clear the "resettable soon" flag in IRAM variable when 180 * it is expected that the secondary CPU will be idle soon. 181 */ 182ENTRY(tegra20_cpu_clear_resettable) 183 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT 184 ldr r2, =__tegra20_cpu1_resettable_status_offset 185 mov r12, #CPU_NOT_RESETTABLE 186 strb r12, [r1, r2] 187 ret lr 188ENDPROC(tegra20_cpu_clear_resettable) 189 190/* 191 * tegra20_cpu_set_resettable_soon(void) 192 * 193 * Called to set the "resettable soon" flag in IRAM variable when 194 * it is expected that the secondary CPU will be idle soon. 195 */ 196ENTRY(tegra20_cpu_set_resettable_soon) 197 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT 198 ldr r2, =__tegra20_cpu1_resettable_status_offset 199 mov r12, #CPU_RESETTABLE_SOON 200 strb r12, [r1, r2] 201 ret lr 202ENDPROC(tegra20_cpu_set_resettable_soon) 203 204/* 205 * tegra20_cpu_is_resettable_soon(void) 206 * 207 * Returns true if the "resettable soon" flag in IRAM variable has been 208 * set because it is expected that the secondary CPU will be idle soon. 209 */ 210ENTRY(tegra20_cpu_is_resettable_soon) 211 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT 212 ldr r2, =__tegra20_cpu1_resettable_status_offset 213 ldrb r12, [r1, r2] 214 cmp r12, #CPU_RESETTABLE_SOON 215 moveq r0, #1 216 movne r0, #0 217 ret lr 218ENDPROC(tegra20_cpu_is_resettable_soon) 219 220/* 221 * tegra20_sleep_core_finish(unsigned long v2p) 222 * 223 * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to 224 * tegra20_tear_down_core in IRAM 225 */ 226ENTRY(tegra20_sleep_core_finish) 227 mov r4, r0 228 /* Flush, disable the L1 data cache and exit SMP */ 229 mov r0, #TEGRA_FLUSH_CACHE_ALL 230 bl tegra_disable_clean_inv_dcache 231 mov r0, r4 232 233 mov32 r3, tegra_shut_off_mmu 234 add r3, r3, r0 235 236 mov32 r0, tegra20_tear_down_core 237 mov32 r1, tegra20_iram_start 238 sub r0, r0, r1 239 mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA 240 add r0, r0, r1 241 242 ret r3 243ENDPROC(tegra20_sleep_core_finish) 244 245/* 246 * tegra20_sleep_cpu_secondary_finish(unsigned long v2p) 247 * 248 * Enters WFI on secondary CPU by exiting coherency. 249 */ 250ENTRY(tegra20_sleep_cpu_secondary_finish) 251 stmfd sp!, {r4-r11, lr} 252 253 mrc p15, 0, r11, c1, c0, 1 @ save actlr before exiting coherency 254 255 /* Flush and disable the L1 data cache */ 256 mov r0, #TEGRA_FLUSH_CACHE_LOUIS 257 bl tegra_disable_clean_inv_dcache 258 259 mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT 260 ldr r4, =__tegra20_cpu1_resettable_status_offset 261 mov r3, #CPU_RESETTABLE 262 strb r3, [r0, r4] 263 264 bl tegra_cpu_do_idle 265 266 /* 267 * cpu may be reset while in wfi, which will return through 268 * tegra_resume to cpu_resume 269 * or interrupt may wake wfi, which will return here 270 * cpu state is unchanged - MMU is on, cache is on, coherency 271 * is off, and the data cache is off 272 * 273 * r11 contains the original actlr 274 */ 275 276 bl tegra_pen_lock 277 278 mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT 279 ldr r4, =__tegra20_cpu1_resettable_status_offset 280 mov r3, #CPU_NOT_RESETTABLE 281 strb r3, [r0, r4] 282 283 bl tegra_pen_unlock 284 285 /* Re-enable the data cache */ 286 mrc p15, 0, r10, c1, c0, 0 287 orr r10, r10, #CR_C 288 mcr p15, 0, r10, c1, c0, 0 289 isb 290 291 mcr p15, 0, r11, c1, c0, 1 @ reenable coherency 292 293 /* Invalidate the TLBs & BTAC */ 294 mov r1, #0 295 mcr p15, 0, r1, c8, c3, 0 @ invalidate shared TLBs 296 mcr p15, 0, r1, c7, c1, 6 @ invalidate shared BTAC 297 dsb 298 isb 299 300 /* the cpu was running with coherency disabled, 301 * caches may be out of date */ 302 bl v7_flush_kern_cache_louis 303 304 ldmfd sp!, {r4 - r11, pc} 305ENDPROC(tegra20_sleep_cpu_secondary_finish) 306 307/* 308 * tegra20_tear_down_cpu 309 * 310 * Switches the CPU cluster to PLL-P and enters sleep. 311 */ 312ENTRY(tegra20_tear_down_cpu) 313 bl tegra_switch_cpu_to_pllp 314 b tegra20_enter_sleep 315ENDPROC(tegra20_tear_down_cpu) 316 317/* START OF ROUTINES COPIED TO IRAM */ 318 .align L1_CACHE_SHIFT 319 .globl tegra20_iram_start 320tegra20_iram_start: 321 322/* 323 * tegra20_lp1_reset 324 * 325 * reset vector for LP1 restore; copied into IRAM during suspend. 326 * Brings the system back up to a safe staring point (SDRAM out of 327 * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP, 328 * system clock running on the same PLL that it suspended at), and 329 * jumps to tegra_resume to restore virtual addressing and PLLX. 330 * The physical address of tegra_resume expected to be stored in 331 * PMC_SCRATCH41. 332 * 333 * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA. 334 */ 335ENTRY(tegra20_lp1_reset) 336 /* 337 * The CPU and system bus are running at 32KHz and executing from 338 * IRAM when this code is executed; immediately switch to CLKM and 339 * enable PLLM, PLLP, PLLC. 340 */ 341 mov32 r0, TEGRA_CLK_RESET_BASE 342 343 mov r1, #(1 << 28) 344 str r1, [r0, #CLK_RESET_SCLK_BURST] 345 str r1, [r0, #CLK_RESET_CCLK_BURST] 346 mov r1, #0 347 str r1, [r0, #CLK_RESET_CCLK_DIVIDER] 348 str r1, [r0, #CLK_RESET_SCLK_DIVIDER] 349 350 pll_enable r1, r0, CLK_RESET_PLLM_BASE 351 pll_enable r1, r0, CLK_RESET_PLLP_BASE 352 pll_enable r1, r0, CLK_RESET_PLLC_BASE 353 354 adr r2, tegra20_sdram_pad_address 355 adr r4, tegra20_sdram_pad_save 356 mov r5, #0 357 358 ldr r6, tegra20_sdram_pad_size 359padload: 360 ldr r7, [r2, r5] @ r7 is the addr in the pad_address 361 362 ldr r1, [r4, r5] 363 str r1, [r7] @ restore the value in pad_save 364 365 add r5, r5, #4 366 cmp r6, r5 367 bne padload 368 369padload_done: 370 /* 255uS delay for PLL stabilization */ 371 mov32 r7, TEGRA_TMRUS_BASE 372 ldr r1, [r7] 373 add r1, r1, #0xff 374 wait_until r1, r7, r9 375 376 adr r4, tegra20_sclk_save 377 ldr r4, [r4] 378 str r4, [r0, #CLK_RESET_SCLK_BURST] 379 mov32 r4, ((1 << 28) | (4)) @ burst policy is PLLP 380 str r4, [r0, #CLK_RESET_CCLK_BURST] 381 382 mov32 r0, TEGRA_EMC_BASE 383 ldr r1, [r0, #EMC_CFG] 384 bic r1, r1, #(1 << 31) @ disable DRAM_CLK_STOP 385 str r1, [r0, #EMC_CFG] 386 387 mov r1, #0 388 str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh 389 mov r1, #1 390 str r1, [r0, #EMC_NOP] 391 str r1, [r0, #EMC_NOP] 392 393 emc_device_mask r1, r0 394 395exit_selfrefresh_loop: 396 ldr r2, [r0, #EMC_EMC_STATUS] 397 ands r2, r2, r1 398 bne exit_selfrefresh_loop 399 400 mov r1, #0 @ unstall all transactions 401 str r1, [r0, #EMC_REQ_CTRL] 402 403 mov32 r0, TEGRA_PMC_BASE 404 ldr r0, [r0, #PMC_SCRATCH41] 405 ret r0 @ jump to tegra_resume 406ENDPROC(tegra20_lp1_reset) 407 408/* 409 * tegra20_tear_down_core 410 * 411 * copied into and executed from IRAM 412 * puts memory in self-refresh for LP0 and LP1 413 */ 414tegra20_tear_down_core: 415 bl tegra20_sdram_self_refresh 416 bl tegra20_switch_cpu_to_clk32k 417 b tegra20_enter_sleep 418 419/* 420 * tegra20_switch_cpu_to_clk32k 421 * 422 * In LP0 and LP1 all PLLs will be turned off. Switch the CPU and system clock 423 * to the 32KHz clock. 424 */ 425tegra20_switch_cpu_to_clk32k: 426 /* 427 * start by switching to CLKM to safely disable PLLs, then switch to 428 * CLKS. 429 */ 430 mov r0, #(1 << 28) 431 str r0, [r5, #CLK_RESET_SCLK_BURST] 432 str r0, [r5, #CLK_RESET_CCLK_BURST] 433 mov r0, #0 434 str r0, [r5, #CLK_RESET_CCLK_DIVIDER] 435 str r0, [r5, #CLK_RESET_SCLK_DIVIDER] 436 437 /* 2uS delay delay between changing SCLK and disabling PLLs */ 438 mov32 r7, TEGRA_TMRUS_BASE 439 ldr r1, [r7] 440 add r1, r1, #2 441 wait_until r1, r7, r9 442 443 /* disable PLLM, PLLP and PLLC */ 444 ldr r0, [r5, #CLK_RESET_PLLM_BASE] 445 bic r0, r0, #(1 << 30) 446 str r0, [r5, #CLK_RESET_PLLM_BASE] 447 ldr r0, [r5, #CLK_RESET_PLLP_BASE] 448 bic r0, r0, #(1 << 30) 449 str r0, [r5, #CLK_RESET_PLLP_BASE] 450 ldr r0, [r5, #CLK_RESET_PLLC_BASE] 451 bic r0, r0, #(1 << 30) 452 str r0, [r5, #CLK_RESET_PLLC_BASE] 453 454 /* switch to CLKS */ 455 mov r0, #0 /* brust policy = 32KHz */ 456 str r0, [r5, #CLK_RESET_SCLK_BURST] 457 458 ret lr 459 460/* 461 * tegra20_enter_sleep 462 * 463 * uses flow controller to enter sleep state 464 * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1 465 * executes from SDRAM with target state is LP2 466 */ 467tegra20_enter_sleep: 468 mov32 r6, TEGRA_FLOW_CTRL_BASE 469 470 mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT 471 orr r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ 472 cpu_id r1 473 cpu_to_halt_reg r1, r1 474 str r0, [r6, r1] 475 dsb 476 ldr r0, [r6, r1] /* memory barrier */ 477 478halted: 479 dsb 480 wfe /* CPU should be power gated here */ 481 isb 482 b halted 483 484/* 485 * tegra20_sdram_self_refresh 486 * 487 * called with MMU off and caches disabled 488 * puts sdram in self refresh 489 * must be executed from IRAM 490 */ 491tegra20_sdram_self_refresh: 492 mov32 r1, TEGRA_EMC_BASE @ r1 reserved for emc base addr 493 494 mov r2, #3 495 str r2, [r1, #EMC_REQ_CTRL] @ stall incoming DRAM requests 496 497emcidle: 498 ldr r2, [r1, #EMC_EMC_STATUS] 499 tst r2, #4 500 beq emcidle 501 502 mov r2, #1 503 str r2, [r1, #EMC_SELF_REF] 504 505 emc_device_mask r2, r1 506 507emcself: 508 ldr r3, [r1, #EMC_EMC_STATUS] 509 and r3, r3, r2 510 cmp r3, r2 511 bne emcself @ loop until DDR in self-refresh 512 513 adr r2, tegra20_sdram_pad_address 514 adr r3, tegra20_sdram_pad_safe 515 adr r4, tegra20_sdram_pad_save 516 mov r5, #0 517 518 ldr r6, tegra20_sdram_pad_size 519padsave: 520 ldr r0, [r2, r5] @ r0 is the addr in the pad_address 521 522 ldr r1, [r0] 523 str r1, [r4, r5] @ save the content of the addr 524 525 ldr r1, [r3, r5] 526 str r1, [r0] @ set the save val to the addr 527 528 add r5, r5, #4 529 cmp r6, r5 530 bne padsave 531padsave_done: 532 533 mov32 r5, TEGRA_CLK_RESET_BASE 534 ldr r0, [r5, #CLK_RESET_SCLK_BURST] 535 adr r2, tegra20_sclk_save 536 str r0, [r2] 537 dsb 538 ret lr 539 540tegra20_sdram_pad_address: 541 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL 542 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL 543 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CLKCFGPADCTRL 544 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2COMPPADCTRL 545 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2VTTGENPADCTRL 546 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL2 547 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL2 548 549tegra20_sdram_pad_size: 550 .word tegra20_sdram_pad_size - tegra20_sdram_pad_address 551 552tegra20_sdram_pad_safe: 553 .word 0x8 554 .word 0x8 555 .word 0x0 556 .word 0x8 557 .word 0x5500 558 .word 0x08080040 559 .word 0x0 560 561tegra20_sclk_save: 562 .word 0x0 563 564tegra20_sdram_pad_save: 565 .rept (tegra20_sdram_pad_size - tegra20_sdram_pad_address) / 4 566 .long 0 567 .endr 568 569 .ltorg 570/* dummy symbol for end of IRAM */ 571 .align L1_CACHE_SHIFT 572 .globl tegra20_iram_end 573tegra20_iram_end: 574 b . 575#endif 576