1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. 4 * Copyright (c) 2011, Google, Inc. 5 * 6 * Author: Colin Cross <ccross@android.com> 7 * Gary King <gking@nvidia.com> 8 */ 9 10#include <linux/linkage.h> 11 12#include <soc/tegra/flowctrl.h> 13 14#include <asm/assembler.h> 15#include <asm/proc-fns.h> 16#include <asm/cp15.h> 17#include <asm/cache.h> 18 19#include "irammap.h" 20#include "reset.h" 21#include "sleep.h" 22 23#define EMC_CFG 0xc 24#define EMC_ADR_CFG 0x10 25#define EMC_NOP 0xdc 26#define EMC_SELF_REF 0xe0 27#define EMC_REQ_CTRL 0x2b0 28#define EMC_EMC_STATUS 0x2b4 29 30#define CLK_RESET_CCLK_BURST 0x20 31#define CLK_RESET_CCLK_DIVIDER 0x24 32#define CLK_RESET_SCLK_BURST 0x28 33#define CLK_RESET_SCLK_DIVIDER 0x2c 34#define CLK_RESET_PLLC_BASE 0x80 35#define CLK_RESET_PLLM_BASE 0x90 36#define CLK_RESET_PLLP_BASE 0xa0 37 38#define APB_MISC_XM2CFGCPADCTRL 0x8c8 39#define APB_MISC_XM2CFGDPADCTRL 0x8cc 40#define APB_MISC_XM2CLKCFGPADCTRL 0x8d0 41#define APB_MISC_XM2COMPPADCTRL 0x8d4 42#define APB_MISC_XM2VTTGENPADCTRL 0x8d8 43#define APB_MISC_XM2CFGCPADCTRL2 0x8e4 44#define APB_MISC_XM2CFGDPADCTRL2 0x8e8 45 46#define PLLC_STORE_MASK (1 << 0) 47#define PLLM_STORE_MASK (1 << 1) 48#define PLLP_STORE_MASK (1 << 2) 49 50.arch armv7-a 51 52.macro test_pll_state, rd, test_mask 53 ldr \rd, tegra_pll_state 54 tst \rd, #\test_mask 55.endm 56 57.macro store_pll_state, rd, tmp, r_car_base, pll_base, pll_mask 58 ldr \rd, [\r_car_base, #\pll_base] 59 tst \rd, #(1 << 30) 60 ldr \rd, tegra_pll_state 61 biceq \rd, \rd, #\pll_mask 62 orrne \rd, \rd, #\pll_mask 63 adr \tmp, tegra_pll_state 64 str \rd, [\tmp] 65.endm 66 67.macro pll_enable, rd, r_car_base, pll_base, test_mask 68 test_pll_state \rd, \test_mask 69 beq 1f 70 71 ldr \rd, [\r_car_base, #\pll_base] 72 tst \rd, #(1 << 30) 73 orreq \rd, \rd, #(1 << 30) 74 streq \rd, [\r_car_base, #\pll_base] 751: 76.endm 77 78.macro emc_device_mask, rd, base 79 ldr \rd, [\base, #EMC_ADR_CFG] 80 tst \rd, #(0x3 << 24) 81 moveq \rd, #(0x1 << 8) @ just 1 device 82 movne \rd, #(0x3 << 8) @ 2 devices 83.endm 84 85#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP) 86/* 87 * tegra20_hotplug_shutdown(void) 88 * 89 * puts the current cpu in reset 90 * should never return 91 */ 92ENTRY(tegra20_hotplug_shutdown) 93 /* Put this CPU down */ 94 cpu_id r0 95 bl tegra20_cpu_shutdown 96 ret lr @ should never get here 97ENDPROC(tegra20_hotplug_shutdown) 98 99/* 100 * tegra20_cpu_shutdown(int cpu) 101 * 102 * r0 is cpu to reset 103 * 104 * puts the specified CPU in wait-for-event mode on the flow controller 105 * and puts the CPU in reset 106 * can be called on the current cpu or another cpu 107 * if called on the current cpu, does not return 108 * MUST NOT BE CALLED FOR CPU 0. 109 * 110 * corrupts r0-r3, r12 111 */ 112ENTRY(tegra20_cpu_shutdown) 113 cmp r0, #0 114 reteq lr @ must not be called for CPU 0 115 116 cpu_to_halt_reg r1, r0 117 ldr r3, =TEGRA_FLOW_CTRL_VIRT 118 mov r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME 119 str r2, [r3, r1] @ put flow controller in wait event mode 120 ldr r2, [r3, r1] 121 isb 122 dsb 123 movw r1, 0x1011 124 mov r1, r1, lsl r0 125 ldr r3, =TEGRA_CLK_RESET_VIRT 126 str r1, [r3, #0x340] @ put slave CPU in reset 127 isb 128 dsb 129 cpu_id r3 130 cmp r3, r0 131 beq . 132 ret lr 133ENDPROC(tegra20_cpu_shutdown) 134#endif 135 136#ifdef CONFIG_PM_SLEEP 137/* 138 * tegra20_sleep_core_finish(unsigned long v2p) 139 * 140 * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to 141 * tegra20_tear_down_core in IRAM 142 */ 143ENTRY(tegra20_sleep_core_finish) 144 mov r4, r0 145 /* Flush, disable the L1 data cache and exit SMP */ 146 mov r0, #TEGRA_FLUSH_CACHE_ALL 147 bl tegra_disable_clean_inv_dcache 148 mov r0, r4 149 150 mov32 r3, tegra_shut_off_mmu 151 add r3, r3, r0 152 153 mov32 r0, tegra20_tear_down_core 154 mov32 r1, tegra20_iram_start 155 sub r0, r0, r1 156 mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA 157 add r0, r0, r1 158 159 ret r3 160ENDPROC(tegra20_sleep_core_finish) 161 162/* 163 * tegra20_tear_down_cpu 164 * 165 * Switches the CPU cluster to PLL-P and enters sleep. 166 */ 167ENTRY(tegra20_tear_down_cpu) 168 bl tegra_switch_cpu_to_pllp 169 b tegra20_enter_sleep 170ENDPROC(tegra20_tear_down_cpu) 171 172/* START OF ROUTINES COPIED TO IRAM */ 173 .align L1_CACHE_SHIFT 174 .globl tegra20_iram_start 175tegra20_iram_start: 176 177/* 178 * tegra20_lp1_reset 179 * 180 * reset vector for LP1 restore; copied into IRAM during suspend. 181 * Brings the system back up to a safe staring point (SDRAM out of 182 * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP, 183 * system clock running on the same PLL that it suspended at), and 184 * jumps to tegra_resume to restore virtual addressing and PLLX. 185 * The physical address of tegra_resume expected to be stored in 186 * PMC_SCRATCH41. 187 * 188 * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA. 189 */ 190ENTRY(tegra20_lp1_reset) 191 /* 192 * The CPU and system bus are running at 32KHz and executing from 193 * IRAM when this code is executed; immediately switch to CLKM and 194 * enable PLLM, PLLP, PLLC. 195 */ 196 mov32 r0, TEGRA_CLK_RESET_BASE 197 198 mov r1, #(1 << 28) 199 str r1, [r0, #CLK_RESET_SCLK_BURST] 200 str r1, [r0, #CLK_RESET_CCLK_BURST] 201 mov r1, #0 202 str r1, [r0, #CLK_RESET_CCLK_DIVIDER] 203 str r1, [r0, #CLK_RESET_SCLK_DIVIDER] 204 205 pll_enable r1, r0, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK 206 pll_enable r1, r0, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK 207 pll_enable r1, r0, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK 208 209 adr r2, tegra20_sdram_pad_address 210 adr r4, tegra20_sdram_pad_save 211 mov r5, #0 212 213 ldr r6, tegra20_sdram_pad_size 214padload: 215 ldr r7, [r2, r5] @ r7 is the addr in the pad_address 216 217 ldr r1, [r4, r5] 218 str r1, [r7] @ restore the value in pad_save 219 220 add r5, r5, #4 221 cmp r6, r5 222 bne padload 223 224padload_done: 225 /* 255uS delay for PLL stabilization */ 226 mov32 r7, TEGRA_TMRUS_BASE 227 ldr r1, [r7] 228 add r1, r1, #0xff 229 wait_until r1, r7, r9 230 231 adr r4, tegra20_sclk_save 232 ldr r4, [r4] 233 str r4, [r0, #CLK_RESET_SCLK_BURST] 234 mov32 r4, ((1 << 28) | (4)) @ burst policy is PLLP 235 str r4, [r0, #CLK_RESET_CCLK_BURST] 236 237 mov32 r0, TEGRA_EMC_BASE 238 ldr r1, [r0, #EMC_CFG] 239 bic r1, r1, #(1 << 31) @ disable DRAM_CLK_STOP 240 str r1, [r0, #EMC_CFG] 241 242 mov r1, #0 243 str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh 244 mov r1, #1 245 str r1, [r0, #EMC_NOP] 246 str r1, [r0, #EMC_NOP] 247 248 emc_device_mask r1, r0 249 250exit_selfrefresh_loop: 251 ldr r2, [r0, #EMC_EMC_STATUS] 252 ands r2, r2, r1 253 bne exit_selfrefresh_loop 254 255 mov r1, #0 @ unstall all transactions 256 str r1, [r0, #EMC_REQ_CTRL] 257 258 mov32 r0, TEGRA_PMC_BASE 259 ldr r0, [r0, #PMC_SCRATCH41] 260 ret r0 @ jump to tegra_resume 261ENDPROC(tegra20_lp1_reset) 262 263/* 264 * tegra20_tear_down_core 265 * 266 * copied into and executed from IRAM 267 * puts memory in self-refresh for LP0 and LP1 268 */ 269tegra20_tear_down_core: 270 bl tegra20_sdram_self_refresh 271 bl tegra20_switch_cpu_to_clk32k 272 b tegra20_enter_sleep 273 274/* 275 * tegra20_switch_cpu_to_clk32k 276 * 277 * In LP0 and LP1 all PLLs will be turned off. Switch the CPU and system clock 278 * to the 32KHz clock. 279 */ 280tegra20_switch_cpu_to_clk32k: 281 /* 282 * start by switching to CLKM to safely disable PLLs, then switch to 283 * CLKS. 284 */ 285 mov r0, #(1 << 28) 286 str r0, [r5, #CLK_RESET_SCLK_BURST] 287 str r0, [r5, #CLK_RESET_CCLK_BURST] 288 mov r0, #0 289 str r0, [r5, #CLK_RESET_CCLK_DIVIDER] 290 str r0, [r5, #CLK_RESET_SCLK_DIVIDER] 291 292 /* 2uS delay delay between changing SCLK and disabling PLLs */ 293 mov32 r7, TEGRA_TMRUS_BASE 294 ldr r1, [r7] 295 add r1, r1, #2 296 wait_until r1, r7, r9 297 298 store_pll_state r0, r1, r5, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK 299 store_pll_state r0, r1, r5, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK 300 store_pll_state r0, r1, r5, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK 301 302 /* disable PLLM, PLLP and PLLC */ 303 ldr r0, [r5, #CLK_RESET_PLLM_BASE] 304 bic r0, r0, #(1 << 30) 305 str r0, [r5, #CLK_RESET_PLLM_BASE] 306 ldr r0, [r5, #CLK_RESET_PLLP_BASE] 307 bic r0, r0, #(1 << 30) 308 str r0, [r5, #CLK_RESET_PLLP_BASE] 309 ldr r0, [r5, #CLK_RESET_PLLC_BASE] 310 bic r0, r0, #(1 << 30) 311 str r0, [r5, #CLK_RESET_PLLC_BASE] 312 313 /* switch to CLKS */ 314 mov r0, #0 /* brust policy = 32KHz */ 315 str r0, [r5, #CLK_RESET_SCLK_BURST] 316 317 ret lr 318 319/* 320 * tegra20_enter_sleep 321 * 322 * uses flow controller to enter sleep state 323 * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1 324 * executes from SDRAM with target state is LP2 325 */ 326tegra20_enter_sleep: 327 mov32 r6, TEGRA_FLOW_CTRL_BASE 328 329 mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT 330 orr r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ 331 cpu_id r1 332 cpu_to_halt_reg r1, r1 333 str r0, [r6, r1] 334 dsb 335 ldr r0, [r6, r1] /* memory barrier */ 336 337halted: 338 dsb 339 wfe /* CPU should be power gated here */ 340 isb 341 b halted 342 343/* 344 * tegra20_sdram_self_refresh 345 * 346 * called with MMU off and caches disabled 347 * puts sdram in self refresh 348 * must be executed from IRAM 349 */ 350tegra20_sdram_self_refresh: 351 mov32 r1, TEGRA_EMC_BASE @ r1 reserved for emc base addr 352 353 mov r2, #3 354 str r2, [r1, #EMC_REQ_CTRL] @ stall incoming DRAM requests 355 356emcidle: 357 ldr r2, [r1, #EMC_EMC_STATUS] 358 tst r2, #4 359 beq emcidle 360 361 mov r2, #1 362 str r2, [r1, #EMC_SELF_REF] 363 364 emc_device_mask r2, r1 365 366emcself: 367 ldr r3, [r1, #EMC_EMC_STATUS] 368 and r3, r3, r2 369 cmp r3, r2 370 bne emcself @ loop until DDR in self-refresh 371 372 adr r2, tegra20_sdram_pad_address 373 adr r3, tegra20_sdram_pad_safe 374 adr r4, tegra20_sdram_pad_save 375 mov r5, #0 376 377 ldr r6, tegra20_sdram_pad_size 378padsave: 379 ldr r0, [r2, r5] @ r0 is the addr in the pad_address 380 381 ldr r1, [r0] 382 str r1, [r4, r5] @ save the content of the addr 383 384 ldr r1, [r3, r5] 385 str r1, [r0] @ set the save val to the addr 386 387 add r5, r5, #4 388 cmp r6, r5 389 bne padsave 390padsave_done: 391 392 mov32 r5, TEGRA_CLK_RESET_BASE 393 ldr r0, [r5, #CLK_RESET_SCLK_BURST] 394 adr r2, tegra20_sclk_save 395 str r0, [r2] 396 dsb 397 ret lr 398 399tegra20_sdram_pad_address: 400 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL 401 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL 402 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CLKCFGPADCTRL 403 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2COMPPADCTRL 404 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2VTTGENPADCTRL 405 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL2 406 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL2 407 408tegra20_sdram_pad_size: 409 .word tegra20_sdram_pad_size - tegra20_sdram_pad_address 410 411tegra20_sdram_pad_safe: 412 .word 0x8 413 .word 0x8 414 .word 0x0 415 .word 0x8 416 .word 0x5500 417 .word 0x08080040 418 .word 0x0 419 420tegra20_sclk_save: 421 .word 0x0 422 423tegra20_sdram_pad_save: 424 .rept (tegra20_sdram_pad_size - tegra20_sdram_pad_address) / 4 425 .long 0 426 .endr 427 428tegra_pll_state: 429 .word 0x0 430 431 .ltorg 432/* dummy symbol for end of IRAM */ 433 .align L1_CACHE_SHIFT 434 .globl tegra20_iram_end 435tegra20_iram_end: 436 b . 437#endif 438