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