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 mov r4, r0 235 /* Flush, disable the L1 data cache and exit SMP */ 236 mov r0, #TEGRA_FLUSH_CACHE_ALL 237 bl tegra_disable_clean_inv_dcache 238 mov r0, r4 239 240 mov32 r3, tegra_shut_off_mmu 241 add r3, r3, r0 242 243 mov32 r0, tegra20_tear_down_core 244 mov32 r1, tegra20_iram_start 245 sub r0, r0, r1 246 mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA 247 add r0, r0, r1 248 249 ret r3 250ENDPROC(tegra20_sleep_core_finish) 251 252/* 253 * tegra20_sleep_cpu_secondary_finish(unsigned long v2p) 254 * 255 * Enters WFI on secondary CPU by exiting coherency. 256 */ 257ENTRY(tegra20_sleep_cpu_secondary_finish) 258 stmfd sp!, {r4-r11, lr} 259 260 mrc p15, 0, r11, c1, c0, 1 @ save actlr before exiting coherency 261 262 /* Flush and disable the L1 data cache */ 263 mov r0, #TEGRA_FLUSH_CACHE_LOUIS 264 bl tegra_disable_clean_inv_dcache 265 266 mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT 267 ldr r4, =__tegra20_cpu1_resettable_status_offset 268 mov r3, #CPU_RESETTABLE 269 strb r3, [r0, r4] 270 271 bl tegra_cpu_do_idle 272 273 /* 274 * cpu may be reset while in wfi, which will return through 275 * tegra_resume to cpu_resume 276 * or interrupt may wake wfi, which will return here 277 * cpu state is unchanged - MMU is on, cache is on, coherency 278 * is off, and the data cache is off 279 * 280 * r11 contains the original actlr 281 */ 282 283 bl tegra_pen_lock 284 285 mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT 286 ldr r4, =__tegra20_cpu1_resettable_status_offset 287 mov r3, #CPU_NOT_RESETTABLE 288 strb r3, [r0, r4] 289 290 bl tegra_pen_unlock 291 292 /* Re-enable the data cache */ 293 mrc p15, 0, r10, c1, c0, 0 294 orr r10, r10, #CR_C 295 mcr p15, 0, r10, c1, c0, 0 296 isb 297 298 mcr p15, 0, r11, c1, c0, 1 @ reenable coherency 299 300 /* Invalidate the TLBs & BTAC */ 301 mov r1, #0 302 mcr p15, 0, r1, c8, c3, 0 @ invalidate shared TLBs 303 mcr p15, 0, r1, c7, c1, 6 @ invalidate shared BTAC 304 dsb 305 isb 306 307 /* the cpu was running with coherency disabled, 308 * caches may be out of date */ 309 bl v7_flush_kern_cache_louis 310 311 ldmfd sp!, {r4 - r11, pc} 312ENDPROC(tegra20_sleep_cpu_secondary_finish) 313 314/* 315 * tegra20_tear_down_cpu 316 * 317 * Switches the CPU cluster to PLL-P and enters sleep. 318 */ 319ENTRY(tegra20_tear_down_cpu) 320 bl tegra_switch_cpu_to_pllp 321 b tegra20_enter_sleep 322ENDPROC(tegra20_tear_down_cpu) 323 324/* START OF ROUTINES COPIED TO IRAM */ 325 .align L1_CACHE_SHIFT 326 .globl tegra20_iram_start 327tegra20_iram_start: 328 329/* 330 * tegra20_lp1_reset 331 * 332 * reset vector for LP1 restore; copied into IRAM during suspend. 333 * Brings the system back up to a safe staring point (SDRAM out of 334 * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP, 335 * system clock running on the same PLL that it suspended at), and 336 * jumps to tegra_resume to restore virtual addressing and PLLX. 337 * The physical address of tegra_resume expected to be stored in 338 * PMC_SCRATCH41. 339 * 340 * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA. 341 */ 342ENTRY(tegra20_lp1_reset) 343 /* 344 * The CPU and system bus are running at 32KHz and executing from 345 * IRAM when this code is executed; immediately switch to CLKM and 346 * enable PLLM, PLLP, PLLC. 347 */ 348 mov32 r0, TEGRA_CLK_RESET_BASE 349 350 mov r1, #(1 << 28) 351 str r1, [r0, #CLK_RESET_SCLK_BURST] 352 str r1, [r0, #CLK_RESET_CCLK_BURST] 353 mov r1, #0 354 str r1, [r0, #CLK_RESET_CCLK_DIVIDER] 355 str r1, [r0, #CLK_RESET_SCLK_DIVIDER] 356 357 pll_enable r1, r0, CLK_RESET_PLLM_BASE 358 pll_enable r1, r0, CLK_RESET_PLLP_BASE 359 pll_enable r1, r0, CLK_RESET_PLLC_BASE 360 361 adr r2, tegra20_sdram_pad_address 362 adr r4, tegra20_sdram_pad_save 363 mov r5, #0 364 365 ldr r6, tegra20_sdram_pad_size 366padload: 367 ldr r7, [r2, r5] @ r7 is the addr in the pad_address 368 369 ldr r1, [r4, r5] 370 str r1, [r7] @ restore the value in pad_save 371 372 add r5, r5, #4 373 cmp r6, r5 374 bne padload 375 376padload_done: 377 /* 255uS delay for PLL stabilization */ 378 mov32 r7, TEGRA_TMRUS_BASE 379 ldr r1, [r7] 380 add r1, r1, #0xff 381 wait_until r1, r7, r9 382 383 adr r4, tegra20_sclk_save 384 ldr r4, [r4] 385 str r4, [r0, #CLK_RESET_SCLK_BURST] 386 mov32 r4, ((1 << 28) | (4)) @ burst policy is PLLP 387 str r4, [r0, #CLK_RESET_CCLK_BURST] 388 389 mov32 r0, TEGRA_EMC_BASE 390 ldr r1, [r0, #EMC_CFG] 391 bic r1, r1, #(1 << 31) @ disable DRAM_CLK_STOP 392 str r1, [r0, #EMC_CFG] 393 394 mov r1, #0 395 str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh 396 mov r1, #1 397 str r1, [r0, #EMC_NOP] 398 str r1, [r0, #EMC_NOP] 399 str r1, [r0, #EMC_REFRESH] 400 401 emc_device_mask r1, r0 402 403exit_selfrefresh_loop: 404 ldr r2, [r0, #EMC_EMC_STATUS] 405 ands r2, r2, r1 406 bne exit_selfrefresh_loop 407 408 mov r1, #0 @ unstall all transactions 409 str r1, [r0, #EMC_REQ_CTRL] 410 411 mov32 r0, TEGRA_PMC_BASE 412 ldr r0, [r0, #PMC_SCRATCH41] 413 ret r0 @ jump to tegra_resume 414ENDPROC(tegra20_lp1_reset) 415 416/* 417 * tegra20_tear_down_core 418 * 419 * copied into and executed from IRAM 420 * puts memory in self-refresh for LP0 and LP1 421 */ 422tegra20_tear_down_core: 423 bl tegra20_sdram_self_refresh 424 bl tegra20_switch_cpu_to_clk32k 425 b tegra20_enter_sleep 426 427/* 428 * tegra20_switch_cpu_to_clk32k 429 * 430 * In LP0 and LP1 all PLLs will be turned off. Switch the CPU and system clock 431 * to the 32KHz clock. 432 */ 433tegra20_switch_cpu_to_clk32k: 434 /* 435 * start by switching to CLKM to safely disable PLLs, then switch to 436 * CLKS. 437 */ 438 mov r0, #(1 << 28) 439 str r0, [r5, #CLK_RESET_SCLK_BURST] 440 str r0, [r5, #CLK_RESET_CCLK_BURST] 441 mov r0, #0 442 str r0, [r5, #CLK_RESET_CCLK_DIVIDER] 443 str r0, [r5, #CLK_RESET_SCLK_DIVIDER] 444 445 /* 2uS delay delay between changing SCLK and disabling PLLs */ 446 mov32 r7, TEGRA_TMRUS_BASE 447 ldr r1, [r7] 448 add r1, r1, #2 449 wait_until r1, r7, r9 450 451 /* disable PLLM, PLLP and PLLC */ 452 ldr r0, [r5, #CLK_RESET_PLLM_BASE] 453 bic r0, r0, #(1 << 30) 454 str r0, [r5, #CLK_RESET_PLLM_BASE] 455 ldr r0, [r5, #CLK_RESET_PLLP_BASE] 456 bic r0, r0, #(1 << 30) 457 str r0, [r5, #CLK_RESET_PLLP_BASE] 458 ldr r0, [r5, #CLK_RESET_PLLC_BASE] 459 bic r0, r0, #(1 << 30) 460 str r0, [r5, #CLK_RESET_PLLC_BASE] 461 462 /* switch to CLKS */ 463 mov r0, #0 /* brust policy = 32KHz */ 464 str r0, [r5, #CLK_RESET_SCLK_BURST] 465 466 ret lr 467 468/* 469 * tegra20_enter_sleep 470 * 471 * uses flow controller to enter sleep state 472 * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1 473 * executes from SDRAM with target state is LP2 474 */ 475tegra20_enter_sleep: 476 mov32 r6, TEGRA_FLOW_CTRL_BASE 477 478 mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT 479 orr r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ 480 cpu_id r1 481 cpu_to_halt_reg r1, r1 482 str r0, [r6, r1] 483 dsb 484 ldr r0, [r6, r1] /* memory barrier */ 485 486halted: 487 dsb 488 wfe /* CPU should be power gated here */ 489 isb 490 b halted 491 492/* 493 * tegra20_sdram_self_refresh 494 * 495 * called with MMU off and caches disabled 496 * puts sdram in self refresh 497 * must be executed from IRAM 498 */ 499tegra20_sdram_self_refresh: 500 mov32 r1, TEGRA_EMC_BASE @ r1 reserved for emc base addr 501 502 mov r2, #3 503 str r2, [r1, #EMC_REQ_CTRL] @ stall incoming DRAM requests 504 505emcidle: 506 ldr r2, [r1, #EMC_EMC_STATUS] 507 tst r2, #4 508 beq emcidle 509 510 mov r2, #1 511 str r2, [r1, #EMC_SELF_REF] 512 513 emc_device_mask r2, r1 514 515emcself: 516 ldr r3, [r1, #EMC_EMC_STATUS] 517 and r3, r3, r2 518 cmp r3, r2 519 bne emcself @ loop until DDR in self-refresh 520 521 adr r2, tegra20_sdram_pad_address 522 adr r3, tegra20_sdram_pad_safe 523 adr r4, tegra20_sdram_pad_save 524 mov r5, #0 525 526 ldr r6, tegra20_sdram_pad_size 527padsave: 528 ldr r0, [r2, r5] @ r0 is the addr in the pad_address 529 530 ldr r1, [r0] 531 str r1, [r4, r5] @ save the content of the addr 532 533 ldr r1, [r3, r5] 534 str r1, [r0] @ set the save val to the addr 535 536 add r5, r5, #4 537 cmp r6, r5 538 bne padsave 539padsave_done: 540 541 mov32 r5, TEGRA_CLK_RESET_BASE 542 ldr r0, [r5, #CLK_RESET_SCLK_BURST] 543 adr r2, tegra20_sclk_save 544 str r0, [r2] 545 dsb 546 ret lr 547 548tegra20_sdram_pad_address: 549 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL 550 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL 551 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CLKCFGPADCTRL 552 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2COMPPADCTRL 553 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2VTTGENPADCTRL 554 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL2 555 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL2 556 557tegra20_sdram_pad_size: 558 .word tegra20_sdram_pad_size - tegra20_sdram_pad_address 559 560tegra20_sdram_pad_safe: 561 .word 0x8 562 .word 0x8 563 .word 0x0 564 .word 0x8 565 .word 0x5500 566 .word 0x08080040 567 .word 0x0 568 569tegra20_sclk_save: 570 .word 0x0 571 572tegra20_sdram_pad_save: 573 .rept (tegra20_sdram_pad_size - tegra20_sdram_pad_address) / 4 574 .long 0 575 .endr 576 577 .ltorg 578/* dummy symbol for end of IRAM */ 579 .align L1_CACHE_SHIFT 580 .globl tegra20_iram_end 581tegra20_iram_end: 582 b . 583#endif 584