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 <asm/assembler.h> 24#include <asm/proc-fns.h> 25#include <asm/cp15.h> 26#include <asm/cache.h> 27 28#include "irammap.h" 29#include "sleep.h" 30#include "flowctrl.h" 31 32#define EMC_CFG 0xc 33#define EMC_ADR_CFG 0x10 34#define EMC_REFRESH 0x70 35#define EMC_NOP 0xdc 36#define EMC_SELF_REF 0xe0 37#define EMC_REQ_CTRL 0x2b0 38#define EMC_EMC_STATUS 0x2b4 39 40#define CLK_RESET_CCLK_BURST 0x20 41#define CLK_RESET_CCLK_DIVIDER 0x24 42#define CLK_RESET_SCLK_BURST 0x28 43#define CLK_RESET_SCLK_DIVIDER 0x2c 44#define CLK_RESET_PLLC_BASE 0x80 45#define CLK_RESET_PLLM_BASE 0x90 46#define CLK_RESET_PLLP_BASE 0xa0 47 48#define APB_MISC_XM2CFGCPADCTRL 0x8c8 49#define APB_MISC_XM2CFGDPADCTRL 0x8cc 50#define APB_MISC_XM2CLKCFGPADCTRL 0x8d0 51#define APB_MISC_XM2COMPPADCTRL 0x8d4 52#define APB_MISC_XM2VTTGENPADCTRL 0x8d8 53#define APB_MISC_XM2CFGCPADCTRL2 0x8e4 54#define APB_MISC_XM2CFGDPADCTRL2 0x8e8 55 56.macro pll_enable, rd, r_car_base, pll_base 57 ldr \rd, [\r_car_base, #\pll_base] 58 tst \rd, #(1 << 30) 59 orreq \rd, \rd, #(1 << 30) 60 streq \rd, [\r_car_base, #\pll_base] 61.endm 62 63.macro emc_device_mask, rd, base 64 ldr \rd, [\base, #EMC_ADR_CFG] 65 tst \rd, #(0x3 << 24) 66 moveq \rd, #(0x1 << 8) @ just 1 device 67 movne \rd, #(0x3 << 8) @ 2 devices 68.endm 69 70#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP) 71/* 72 * tegra20_hotplug_shutdown(void) 73 * 74 * puts the current cpu in reset 75 * should never return 76 */ 77ENTRY(tegra20_hotplug_shutdown) 78 /* Put this CPU down */ 79 cpu_id r0 80 bl tegra20_cpu_shutdown 81 mov pc, lr @ should never get here 82ENDPROC(tegra20_hotplug_shutdown) 83 84/* 85 * tegra20_cpu_shutdown(int cpu) 86 * 87 * r0 is cpu to reset 88 * 89 * puts the specified CPU in wait-for-event mode on the flow controller 90 * and puts the CPU in reset 91 * can be called on the current cpu or another cpu 92 * if called on the current cpu, does not return 93 * MUST NOT BE CALLED FOR CPU 0. 94 * 95 * corrupts r0-r3, r12 96 */ 97ENTRY(tegra20_cpu_shutdown) 98 cmp r0, #0 99 moveq pc, lr @ must not be called for CPU 0 100 mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 101 mov r12, #CPU_RESETTABLE 102 str r12, [r1] 103 104 cpu_to_halt_reg r1, r0 105 ldr r3, =TEGRA_FLOW_CTRL_VIRT 106 mov r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME 107 str r2, [r3, r1] @ put flow controller in wait event mode 108 ldr r2, [r3, r1] 109 isb 110 dsb 111 movw r1, 0x1011 112 mov r1, r1, lsl r0 113 ldr r3, =TEGRA_CLK_RESET_VIRT 114 str r1, [r3, #0x340] @ put slave CPU in reset 115 isb 116 dsb 117 cpu_id r3 118 cmp r3, r0 119 beq . 120 mov pc, lr 121ENDPROC(tegra20_cpu_shutdown) 122#endif 123 124#ifdef CONFIG_PM_SLEEP 125/* 126 * tegra_pen_lock 127 * 128 * spinlock implementation with no atomic test-and-set and no coherence 129 * using Peterson's algorithm on strongly-ordered registers 130 * used to synchronize a cpu waking up from wfi with entering lp2 on idle 131 * 132 * The reference link of Peterson's algorithm: 133 * http://en.wikipedia.org/wiki/Peterson's_algorithm 134 * 135 * SCRATCH37 = r1 = !turn (inverted from Peterson's algorithm) 136 * on cpu 0: 137 * r2 = flag[0] (in SCRATCH38) 138 * r3 = flag[1] (in SCRATCH39) 139 * on cpu1: 140 * r2 = flag[1] (in SCRATCH39) 141 * r3 = flag[0] (in SCRATCH38) 142 * 143 * must be called with MMU on 144 * corrupts r0-r3, r12 145 */ 146ENTRY(tegra_pen_lock) 147 mov32 r3, TEGRA_PMC_VIRT 148 cpu_id r0 149 add r1, r3, #PMC_SCRATCH37 150 cmp r0, #0 151 addeq r2, r3, #PMC_SCRATCH38 152 addeq r3, r3, #PMC_SCRATCH39 153 addne r2, r3, #PMC_SCRATCH39 154 addne r3, r3, #PMC_SCRATCH38 155 156 mov r12, #1 157 str r12, [r2] @ flag[cpu] = 1 158 dsb 159 str r12, [r1] @ !turn = cpu 1601: dsb 161 ldr r12, [r3] 162 cmp r12, #1 @ flag[!cpu] == 1? 163 ldreq r12, [r1] 164 cmpeq r12, r0 @ !turn == cpu? 165 beq 1b @ while !turn == cpu && flag[!cpu] == 1 166 167 mov pc, lr @ locked 168ENDPROC(tegra_pen_lock) 169 170ENTRY(tegra_pen_unlock) 171 dsb 172 mov32 r3, TEGRA_PMC_VIRT 173 cpu_id r0 174 cmp r0, #0 175 addeq r2, r3, #PMC_SCRATCH38 176 addne r2, r3, #PMC_SCRATCH39 177 mov r12, #0 178 str r12, [r2] 179 mov pc, lr 180ENDPROC(tegra_pen_unlock) 181 182/* 183 * tegra20_cpu_clear_resettable(void) 184 * 185 * Called to clear the "resettable soon" flag in PMC_SCRATCH41 when 186 * it is expected that the secondary CPU will be idle soon. 187 */ 188ENTRY(tegra20_cpu_clear_resettable) 189 mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 190 mov r12, #CPU_NOT_RESETTABLE 191 str r12, [r1] 192 mov pc, lr 193ENDPROC(tegra20_cpu_clear_resettable) 194 195/* 196 * tegra20_cpu_set_resettable_soon(void) 197 * 198 * Called to set the "resettable soon" flag in PMC_SCRATCH41 when 199 * it is expected that the secondary CPU will be idle soon. 200 */ 201ENTRY(tegra20_cpu_set_resettable_soon) 202 mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 203 mov r12, #CPU_RESETTABLE_SOON 204 str r12, [r1] 205 mov pc, lr 206ENDPROC(tegra20_cpu_set_resettable_soon) 207 208/* 209 * tegra20_cpu_is_resettable_soon(void) 210 * 211 * Returns true if the "resettable soon" flag in PMC_SCRATCH41 has been 212 * set because it is expected that the secondary CPU will be idle soon. 213 */ 214ENTRY(tegra20_cpu_is_resettable_soon) 215 mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 216 ldr r12, [r1] 217 cmp r12, #CPU_RESETTABLE_SOON 218 moveq r0, #1 219 movne r0, #0 220 mov pc, lr 221ENDPROC(tegra20_cpu_is_resettable_soon) 222 223/* 224 * tegra20_sleep_core_finish(unsigned long v2p) 225 * 226 * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to 227 * tegra20_tear_down_core in IRAM 228 */ 229ENTRY(tegra20_sleep_core_finish) 230 /* Flush, disable the L1 data cache and exit SMP */ 231 bl tegra_disable_clean_inv_dcache 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 mov pc, 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_PMC_VIRT + PMC_SCRATCH41 260 mov r3, #CPU_RESETTABLE 261 str r3, [r0] 262 263 bl tegra_cpu_do_idle 264 265 /* 266 * cpu may be reset while in wfi, which will return through 267 * tegra_resume to cpu_resume 268 * or interrupt may wake wfi, which will return here 269 * cpu state is unchanged - MMU is on, cache is on, coherency 270 * is off, and the data cache is off 271 * 272 * r11 contains the original actlr 273 */ 274 275 bl tegra_pen_lock 276 277 mov32 r3, TEGRA_PMC_VIRT 278 add r0, r3, #PMC_SCRATCH41 279 mov r3, #CPU_NOT_RESETTABLE 280 str r3, [r0] 281 282 bl tegra_pen_unlock 283 284 /* Re-enable the data cache */ 285 mrc p15, 0, r10, c1, c0, 0 286 orr r10, r10, #CR_C 287 mcr p15, 0, r10, c1, c0, 0 288 isb 289 290 mcr p15, 0, r11, c1, c0, 1 @ reenable coherency 291 292 /* Invalidate the TLBs & BTAC */ 293 mov r1, #0 294 mcr p15, 0, r1, c8, c3, 0 @ invalidate shared TLBs 295 mcr p15, 0, r1, c7, c1, 6 @ invalidate shared BTAC 296 dsb 297 isb 298 299 /* the cpu was running with coherency disabled, 300 * caches may be out of date */ 301 bl v7_flush_kern_cache_louis 302 303 ldmfd sp!, {r4 - r11, pc} 304ENDPROC(tegra20_sleep_cpu_secondary_finish) 305 306/* 307 * tegra20_tear_down_cpu 308 * 309 * Switches the CPU cluster to PLL-P and enters sleep. 310 */ 311ENTRY(tegra20_tear_down_cpu) 312 bl tegra_switch_cpu_to_pllp 313 b tegra20_enter_sleep 314ENDPROC(tegra20_tear_down_cpu) 315 316/* START OF ROUTINES COPIED TO IRAM */ 317 .align L1_CACHE_SHIFT 318 .globl tegra20_iram_start 319tegra20_iram_start: 320 321/* 322 * tegra20_lp1_reset 323 * 324 * reset vector for LP1 restore; copied into IRAM during suspend. 325 * Brings the system back up to a safe staring point (SDRAM out of 326 * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP, 327 * system clock running on the same PLL that it suspended at), and 328 * jumps to tegra_resume to restore virtual addressing and PLLX. 329 * The physical address of tegra_resume expected to be stored in 330 * PMC_SCRATCH41. 331 * 332 * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA. 333 */ 334ENTRY(tegra20_lp1_reset) 335 /* 336 * The CPU and system bus are running at 32KHz and executing from 337 * IRAM when this code is executed; immediately switch to CLKM and 338 * enable PLLM, PLLP, PLLC. 339 */ 340 mov32 r0, TEGRA_CLK_RESET_BASE 341 342 mov r1, #(1 << 28) 343 str r1, [r0, #CLK_RESET_SCLK_BURST] 344 str r1, [r0, #CLK_RESET_CCLK_BURST] 345 mov r1, #0 346 str r1, [r0, #CLK_RESET_CCLK_DIVIDER] 347 str r1, [r0, #CLK_RESET_SCLK_DIVIDER] 348 349 pll_enable r1, r0, CLK_RESET_PLLM_BASE 350 pll_enable r1, r0, CLK_RESET_PLLP_BASE 351 pll_enable r1, r0, CLK_RESET_PLLC_BASE 352 353 adr r2, tegra20_sdram_pad_address 354 adr r4, tegra20_sdram_pad_save 355 mov r5, #0 356 357 ldr r6, tegra20_sdram_pad_size 358padload: 359 ldr r7, [r2, r5] @ r7 is the addr in the pad_address 360 361 ldr r1, [r4, r5] 362 str r1, [r7] @ restore the value in pad_save 363 364 add r5, r5, #4 365 cmp r6, r5 366 bne padload 367 368padload_done: 369 /* 255uS delay for PLL stabilization */ 370 mov32 r7, TEGRA_TMRUS_BASE 371 ldr r1, [r7] 372 add r1, r1, #0xff 373 wait_until r1, r7, r9 374 375 adr r4, tegra20_sclk_save 376 ldr r4, [r4] 377 str r4, [r0, #CLK_RESET_SCLK_BURST] 378 mov32 r4, ((1 << 28) | (4)) @ burst policy is PLLP 379 str r4, [r0, #CLK_RESET_CCLK_BURST] 380 381 mov32 r0, TEGRA_EMC_BASE 382 ldr r1, [r0, #EMC_CFG] 383 bic r1, r1, #(1 << 31) @ disable DRAM_CLK_STOP 384 str r1, [r0, #EMC_CFG] 385 386 mov r1, #0 387 str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh 388 mov r1, #1 389 str r1, [r0, #EMC_NOP] 390 str r1, [r0, #EMC_NOP] 391 str r1, [r0, #EMC_REFRESH] 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 mov pc, 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 mov pc, 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 mov pc, 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