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