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