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