1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
4 * Copyright (c) 2011, Google, Inc.
6 * Author: Colin Cross <ccross@android.com>
7 * Gary King <gking@nvidia.com>
10 #include <linux/linkage.h>
12 #include <soc/tegra/flowctrl.h>
14 #include <asm/assembler.h>
15 #include <asm/proc-fns.h>
17 #include <asm/cache.h>
24 #define EMC_ADR_CFG 0x10
26 #define EMC_SELF_REF 0xe0
27 #define EMC_REQ_CTRL 0x2b0
28 #define EMC_EMC_STATUS 0x2b4
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
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
46 #define __tegra20_cpu1_resettable_status_offset \
47 (__tegra_cpu_reset_handler_data_offset + RESET_DATA(RESETTABLE_STATUS))
49 .macro pll_enable, rd, r_car_base, pll_base
50 ldr \rd, [\r_car_base, #\pll_base]
52 orreq \rd, \rd, #(1 << 30)
53 streq \rd, [\r_car_base, #\pll_base]
56 .macro emc_device_mask, rd, base
57 ldr \rd, [\base, #EMC_ADR_CFG]
59 moveq \rd, #(0x1 << 8) @ just 1 device
60 movne \rd, #(0x3 << 8) @ 2 devices
63 #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
65 * tegra20_hotplug_shutdown(void)
67 * puts the current cpu in reset
70 ENTRY(tegra20_hotplug_shutdown)
71 /* Put this CPU down */
73 bl tegra20_cpu_shutdown
74 ret lr @ should never get here
75 ENDPROC(tegra20_hotplug_shutdown)
78 * tegra20_cpu_shutdown(int cpu)
82 * puts the specified CPU in wait-for-event mode on the flow controller
83 * and puts the CPU in reset
84 * can be called on the current cpu or another cpu
85 * if called on the current cpu, does not return
86 * MUST NOT BE CALLED FOR CPU 0.
90 ENTRY(tegra20_cpu_shutdown)
92 reteq lr @ must not be called for CPU 0
93 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
94 ldr r2, =__tegra20_cpu1_resettable_status_offset
95 mov r12, #CPU_RESETTABLE
98 cpu_to_halt_reg r1, r0
99 ldr r3, =TEGRA_FLOW_CTRL_VIRT
100 mov r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
101 str r2, [r3, r1] @ put flow controller in wait event mode
107 ldr r3, =TEGRA_CLK_RESET_VIRT
108 str r1, [r3, #0x340] @ put slave CPU in reset
115 ENDPROC(tegra20_cpu_shutdown)
118 #ifdef CONFIG_PM_SLEEP
122 * spinlock implementation with no atomic test-and-set and no coherence
123 * using Peterson's algorithm on strongly-ordered registers
124 * used to synchronize a cpu waking up from wfi with entering lp2 on idle
126 * The reference link of Peterson's algorithm:
127 * http://en.wikipedia.org/wiki/Peterson's_algorithm
129 * SCRATCH37 = r1 = !turn (inverted from Peterson's algorithm)
131 * r2 = flag[0] (in SCRATCH38)
132 * r3 = flag[1] (in SCRATCH39)
134 * r2 = flag[1] (in SCRATCH39)
135 * r3 = flag[0] (in SCRATCH38)
137 * must be called with MMU on
138 * corrupts r0-r3, r12
140 ENTRY(tegra_pen_lock)
141 mov32 r3, TEGRA_PMC_VIRT
143 add r1, r3, #PMC_SCRATCH37
145 addeq r2, r3, #PMC_SCRATCH38
146 addeq r3, r3, #PMC_SCRATCH39
147 addne r2, r3, #PMC_SCRATCH39
148 addne r3, r3, #PMC_SCRATCH38
151 str r12, [r2] @ flag[cpu] = 1
153 str r12, [r1] @ !turn = cpu
156 cmp r12, #1 @ flag[!cpu] == 1?
158 cmpeq r12, r0 @ !turn == cpu?
159 beq 1b @ while !turn == cpu && flag[!cpu] == 1
162 ENDPROC(tegra_pen_lock)
164 ENTRY(tegra_pen_unlock)
166 mov32 r3, TEGRA_PMC_VIRT
169 addeq r2, r3, #PMC_SCRATCH38
170 addne r2, r3, #PMC_SCRATCH39
174 ENDPROC(tegra_pen_unlock)
177 * tegra20_cpu_clear_resettable(void)
179 * Called to clear the "resettable soon" flag in IRAM variable when
180 * it is expected that the secondary CPU will be idle soon.
182 ENTRY(tegra20_cpu_clear_resettable)
183 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
184 ldr r2, =__tegra20_cpu1_resettable_status_offset
185 mov r12, #CPU_NOT_RESETTABLE
188 ENDPROC(tegra20_cpu_clear_resettable)
191 * tegra20_cpu_set_resettable_soon(void)
193 * Called to set the "resettable soon" flag in IRAM variable when
194 * it is expected that the secondary CPU will be idle soon.
196 ENTRY(tegra20_cpu_set_resettable_soon)
197 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
198 ldr r2, =__tegra20_cpu1_resettable_status_offset
199 mov r12, #CPU_RESETTABLE_SOON
202 ENDPROC(tegra20_cpu_set_resettable_soon)
205 * tegra20_cpu_is_resettable_soon(void)
207 * Returns true if the "resettable soon" flag in IRAM variable has been
208 * set because it is expected that the secondary CPU will be idle soon.
210 ENTRY(tegra20_cpu_is_resettable_soon)
211 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
212 ldr r2, =__tegra20_cpu1_resettable_status_offset
214 cmp r12, #CPU_RESETTABLE_SOON
218 ENDPROC(tegra20_cpu_is_resettable_soon)
221 * tegra20_sleep_core_finish(unsigned long v2p)
223 * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to
224 * tegra20_tear_down_core in IRAM
226 ENTRY(tegra20_sleep_core_finish)
228 /* Flush, disable the L1 data cache and exit SMP */
229 mov r0, #TEGRA_FLUSH_CACHE_ALL
230 bl tegra_disable_clean_inv_dcache
233 mov32 r3, tegra_shut_off_mmu
236 mov32 r0, tegra20_tear_down_core
237 mov32 r1, tegra20_iram_start
239 mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA
243 ENDPROC(tegra20_sleep_core_finish)
246 * tegra20_sleep_cpu_secondary_finish(unsigned long v2p)
248 * Enters WFI on secondary CPU by exiting coherency.
250 ENTRY(tegra20_sleep_cpu_secondary_finish)
251 stmfd sp!, {r4-r11, lr}
253 mrc p15, 0, r11, c1, c0, 1 @ save actlr before exiting coherency
255 /* Flush and disable the L1 data cache */
256 mov r0, #TEGRA_FLUSH_CACHE_LOUIS
257 bl tegra_disable_clean_inv_dcache
259 mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT
260 ldr r4, =__tegra20_cpu1_resettable_status_offset
261 mov r3, #CPU_RESETTABLE
267 * cpu may be reset while in wfi, which will return through
268 * tegra_resume to cpu_resume
269 * or interrupt may wake wfi, which will return here
270 * cpu state is unchanged - MMU is on, cache is on, coherency
271 * is off, and the data cache is off
273 * r11 contains the original actlr
278 mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT
279 ldr r4, =__tegra20_cpu1_resettable_status_offset
280 mov r3, #CPU_NOT_RESETTABLE
285 /* Re-enable the data cache */
286 mrc p15, 0, r10, c1, c0, 0
288 mcr p15, 0, r10, c1, c0, 0
291 mcr p15, 0, r11, c1, c0, 1 @ reenable coherency
293 /* Invalidate the TLBs & BTAC */
295 mcr p15, 0, r1, c8, c3, 0 @ invalidate shared TLBs
296 mcr p15, 0, r1, c7, c1, 6 @ invalidate shared BTAC
300 /* the cpu was running with coherency disabled,
301 * caches may be out of date */
302 bl v7_flush_kern_cache_louis
304 ldmfd sp!, {r4 - r11, pc}
305 ENDPROC(tegra20_sleep_cpu_secondary_finish)
308 * tegra20_tear_down_cpu
310 * Switches the CPU cluster to PLL-P and enters sleep.
312 ENTRY(tegra20_tear_down_cpu)
313 bl tegra_switch_cpu_to_pllp
314 b tegra20_enter_sleep
315 ENDPROC(tegra20_tear_down_cpu)
317 /* START OF ROUTINES COPIED TO IRAM */
318 .align L1_CACHE_SHIFT
319 .globl tegra20_iram_start
325 * reset vector for LP1 restore; copied into IRAM during suspend.
326 * Brings the system back up to a safe staring point (SDRAM out of
327 * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP,
328 * system clock running on the same PLL that it suspended at), and
329 * jumps to tegra_resume to restore virtual addressing and PLLX.
330 * The physical address of tegra_resume expected to be stored in
333 * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
335 ENTRY(tegra20_lp1_reset)
337 * The CPU and system bus are running at 32KHz and executing from
338 * IRAM when this code is executed; immediately switch to CLKM and
339 * enable PLLM, PLLP, PLLC.
341 mov32 r0, TEGRA_CLK_RESET_BASE
344 str r1, [r0, #CLK_RESET_SCLK_BURST]
345 str r1, [r0, #CLK_RESET_CCLK_BURST]
347 str r1, [r0, #CLK_RESET_CCLK_DIVIDER]
348 str r1, [r0, #CLK_RESET_SCLK_DIVIDER]
350 pll_enable r1, r0, CLK_RESET_PLLM_BASE
351 pll_enable r1, r0, CLK_RESET_PLLP_BASE
352 pll_enable r1, r0, CLK_RESET_PLLC_BASE
354 adr r2, tegra20_sdram_pad_address
355 adr r4, tegra20_sdram_pad_save
358 ldr r6, tegra20_sdram_pad_size
360 ldr r7, [r2, r5] @ r7 is the addr in the pad_address
363 str r1, [r7] @ restore the value in pad_save
370 /* 255uS delay for PLL stabilization */
371 mov32 r7, TEGRA_TMRUS_BASE
374 wait_until r1, r7, r9
376 adr r4, tegra20_sclk_save
378 str r4, [r0, #CLK_RESET_SCLK_BURST]
379 mov32 r4, ((1 << 28) | (4)) @ burst policy is PLLP
380 str r4, [r0, #CLK_RESET_CCLK_BURST]
382 mov32 r0, TEGRA_EMC_BASE
383 ldr r1, [r0, #EMC_CFG]
384 bic r1, r1, #(1 << 31) @ disable DRAM_CLK_STOP
385 str r1, [r0, #EMC_CFG]
388 str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh
390 str r1, [r0, #EMC_NOP]
391 str r1, [r0, #EMC_NOP]
393 emc_device_mask r1, r0
395 exit_selfrefresh_loop:
396 ldr r2, [r0, #EMC_EMC_STATUS]
398 bne exit_selfrefresh_loop
400 mov r1, #0 @ unstall all transactions
401 str r1, [r0, #EMC_REQ_CTRL]
403 mov32 r0, TEGRA_PMC_BASE
404 ldr r0, [r0, #PMC_SCRATCH41]
405 ret r0 @ jump to tegra_resume
406 ENDPROC(tegra20_lp1_reset)
409 * tegra20_tear_down_core
411 * copied into and executed from IRAM
412 * puts memory in self-refresh for LP0 and LP1
414 tegra20_tear_down_core:
415 bl tegra20_sdram_self_refresh
416 bl tegra20_switch_cpu_to_clk32k
417 b tegra20_enter_sleep
420 * tegra20_switch_cpu_to_clk32k
422 * In LP0 and LP1 all PLLs will be turned off. Switch the CPU and system clock
423 * to the 32KHz clock.
425 tegra20_switch_cpu_to_clk32k:
427 * start by switching to CLKM to safely disable PLLs, then switch to
431 str r0, [r5, #CLK_RESET_SCLK_BURST]
432 str r0, [r5, #CLK_RESET_CCLK_BURST]
434 str r0, [r5, #CLK_RESET_CCLK_DIVIDER]
435 str r0, [r5, #CLK_RESET_SCLK_DIVIDER]
437 /* 2uS delay delay between changing SCLK and disabling PLLs */
438 mov32 r7, TEGRA_TMRUS_BASE
441 wait_until r1, r7, r9
443 /* disable PLLM, PLLP and PLLC */
444 ldr r0, [r5, #CLK_RESET_PLLM_BASE]
445 bic r0, r0, #(1 << 30)
446 str r0, [r5, #CLK_RESET_PLLM_BASE]
447 ldr r0, [r5, #CLK_RESET_PLLP_BASE]
448 bic r0, r0, #(1 << 30)
449 str r0, [r5, #CLK_RESET_PLLP_BASE]
450 ldr r0, [r5, #CLK_RESET_PLLC_BASE]
451 bic r0, r0, #(1 << 30)
452 str r0, [r5, #CLK_RESET_PLLC_BASE]
455 mov r0, #0 /* brust policy = 32KHz */
456 str r0, [r5, #CLK_RESET_SCLK_BURST]
461 * tegra20_enter_sleep
463 * uses flow controller to enter sleep state
464 * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1
465 * executes from SDRAM with target state is LP2
468 mov32 r6, TEGRA_FLOW_CTRL_BASE
470 mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
471 orr r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
473 cpu_to_halt_reg r1, r1
476 ldr r0, [r6, r1] /* memory barrier */
480 wfe /* CPU should be power gated here */
485 * tegra20_sdram_self_refresh
487 * called with MMU off and caches disabled
488 * puts sdram in self refresh
489 * must be executed from IRAM
491 tegra20_sdram_self_refresh:
492 mov32 r1, TEGRA_EMC_BASE @ r1 reserved for emc base addr
495 str r2, [r1, #EMC_REQ_CTRL] @ stall incoming DRAM requests
498 ldr r2, [r1, #EMC_EMC_STATUS]
503 str r2, [r1, #EMC_SELF_REF]
505 emc_device_mask r2, r1
508 ldr r3, [r1, #EMC_EMC_STATUS]
511 bne emcself @ loop until DDR in self-refresh
513 adr r2, tegra20_sdram_pad_address
514 adr r3, tegra20_sdram_pad_safe
515 adr r4, tegra20_sdram_pad_save
518 ldr r6, tegra20_sdram_pad_size
520 ldr r0, [r2, r5] @ r0 is the addr in the pad_address
523 str r1, [r4, r5] @ save the content of the addr
526 str r1, [r0] @ set the save val to the addr
533 mov32 r5, TEGRA_CLK_RESET_BASE
534 ldr r0, [r5, #CLK_RESET_SCLK_BURST]
535 adr r2, tegra20_sclk_save
540 tegra20_sdram_pad_address:
541 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL
542 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL
543 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CLKCFGPADCTRL
544 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2COMPPADCTRL
545 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2VTTGENPADCTRL
546 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL2
547 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL2
549 tegra20_sdram_pad_size:
550 .word tegra20_sdram_pad_size - tegra20_sdram_pad_address
552 tegra20_sdram_pad_safe:
564 tegra20_sdram_pad_save:
565 .rept (tegra20_sdram_pad_size - tegra20_sdram_pad_address) / 4
570 /* dummy symbol for end of IRAM */
571 .align L1_CACHE_SHIFT
572 .globl tegra20_iram_end