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 PLLC_STORE_MASK (1 << 0)
47 #define PLLM_STORE_MASK (1 << 1)
48 #define PLLP_STORE_MASK (1 << 2)
52 .macro test_pll_state, rd, test_mask
53 ldr \rd, tegra_pll_state
57 .macro store_pll_state, rd, tmp, r_car_base, pll_base, pll_mask
58 ldr \rd, [\r_car_base, #\pll_base]
60 ldr \rd, tegra_pll_state
61 biceq \rd, \rd, #\pll_mask
62 orrne \rd, \rd, #\pll_mask
63 adr \tmp, tegra_pll_state
67 .macro pll_enable, rd, r_car_base, pll_base, test_mask
68 test_pll_state \rd, \test_mask
71 ldr \rd, [\r_car_base, #\pll_base]
73 orreq \rd, \rd, #(1 << 30)
74 streq \rd, [\r_car_base, #\pll_base]
78 .macro emc_device_mask, rd, base
79 ldr \rd, [\base, #EMC_ADR_CFG]
81 moveq \rd, #(0x1 << 8) @ just 1 device
82 movne \rd, #(0x3 << 8) @ 2 devices
85 #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
87 * tegra20_hotplug_shutdown(void)
89 * puts the current cpu in reset
92 ENTRY(tegra20_hotplug_shutdown)
93 /* Put this CPU down */
95 bl tegra20_cpu_shutdown
96 ret lr @ should never get here
97 ENDPROC(tegra20_hotplug_shutdown)
100 * tegra20_cpu_shutdown(int cpu)
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.
110 * corrupts r0-r3, r12
112 ENTRY(tegra20_cpu_shutdown)
114 reteq lr @ must not be called for CPU 0
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
125 ldr r3, =TEGRA_CLK_RESET_VIRT
126 str r1, [r3, #0x340] @ put slave CPU in reset
133 ENDPROC(tegra20_cpu_shutdown)
136 #ifdef CONFIG_PM_SLEEP
138 * tegra20_sleep_core_finish(unsigned long v2p)
140 * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to
141 * tegra20_tear_down_core in IRAM
143 ENTRY(tegra20_sleep_core_finish)
145 /* Flush, disable the L1 data cache and exit SMP */
146 mov r0, #TEGRA_FLUSH_CACHE_ALL
147 bl tegra_disable_clean_inv_dcache
150 mov32 r3, tegra_shut_off_mmu
153 mov32 r0, tegra20_tear_down_core
154 mov32 r1, tegra20_iram_start
156 mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA
160 ENDPROC(tegra20_sleep_core_finish)
163 * tegra20_tear_down_cpu
165 * Switches the CPU cluster to PLL-P and enters sleep.
167 ENTRY(tegra20_tear_down_cpu)
168 bl tegra_switch_cpu_to_pllp
169 b tegra20_enter_sleep
170 ENDPROC(tegra20_tear_down_cpu)
172 /* START OF ROUTINES COPIED TO IRAM */
173 .align L1_CACHE_SHIFT
174 .globl tegra20_iram_start
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
188 * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
190 ENTRY(tegra20_lp1_reset)
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.
196 mov32 r0, TEGRA_CLK_RESET_BASE
199 str r1, [r0, #CLK_RESET_SCLK_BURST]
200 str r1, [r0, #CLK_RESET_CCLK_BURST]
202 str r1, [r0, #CLK_RESET_CCLK_DIVIDER]
203 str r1, [r0, #CLK_RESET_SCLK_DIVIDER]
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
209 adr r2, tegra20_sdram_pad_address
210 adr r4, tegra20_sdram_pad_save
213 ldr r6, tegra20_sdram_pad_size
215 ldr r7, [r2, r5] @ r7 is the addr in the pad_address
218 str r1, [r7] @ restore the value in pad_save
225 /* 255uS delay for PLL stabilization */
226 mov32 r7, TEGRA_TMRUS_BASE
229 wait_until r1, r7, r9
231 adr r4, tegra20_sclk_save
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]
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]
243 str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh
245 str r1, [r0, #EMC_NOP]
246 str r1, [r0, #EMC_NOP]
248 emc_device_mask r1, r0
250 exit_selfrefresh_loop:
251 ldr r2, [r0, #EMC_EMC_STATUS]
253 bne exit_selfrefresh_loop
255 mov r1, #0 @ unstall all transactions
256 str r1, [r0, #EMC_REQ_CTRL]
258 mov32 r0, TEGRA_PMC_BASE
259 ldr r0, [r0, #PMC_SCRATCH41]
260 ret r0 @ jump to tegra_resume
261 ENDPROC(tegra20_lp1_reset)
264 * tegra20_tear_down_core
266 * copied into and executed from IRAM
267 * puts memory in self-refresh for LP0 and LP1
269 tegra20_tear_down_core:
270 bl tegra20_sdram_self_refresh
271 bl tegra20_switch_cpu_to_clk32k
272 b tegra20_enter_sleep
275 * tegra20_switch_cpu_to_clk32k
277 * In LP0 and LP1 all PLLs will be turned off. Switch the CPU and system clock
278 * to the 32KHz clock.
280 tegra20_switch_cpu_to_clk32k:
282 * start by switching to CLKM to safely disable PLLs, then switch to
286 str r0, [r5, #CLK_RESET_SCLK_BURST]
287 str r0, [r5, #CLK_RESET_CCLK_BURST]
289 str r0, [r5, #CLK_RESET_CCLK_DIVIDER]
290 str r0, [r5, #CLK_RESET_SCLK_DIVIDER]
292 /* 2uS delay delay between changing SCLK and disabling PLLs */
293 mov32 r7, TEGRA_TMRUS_BASE
296 wait_until r1, r7, r9
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
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]
314 mov r0, #0 /* brust policy = 32KHz */
315 str r0, [r5, #CLK_RESET_SCLK_BURST]
320 * tegra20_enter_sleep
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
327 mov32 r6, TEGRA_FLOW_CTRL_BASE
329 mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
330 orr r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
332 cpu_to_halt_reg r1, r1
335 ldr r0, [r6, r1] /* memory barrier */
339 wfe /* CPU should be power gated here */
344 * tegra20_sdram_self_refresh
346 * called with MMU off and caches disabled
347 * puts sdram in self refresh
348 * must be executed from IRAM
350 tegra20_sdram_self_refresh:
351 mov32 r1, TEGRA_EMC_BASE @ r1 reserved for emc base addr
354 str r2, [r1, #EMC_REQ_CTRL] @ stall incoming DRAM requests
357 ldr r2, [r1, #EMC_EMC_STATUS]
362 str r2, [r1, #EMC_SELF_REF]
364 emc_device_mask r2, r1
367 ldr r3, [r1, #EMC_EMC_STATUS]
370 bne emcself @ loop until DDR in self-refresh
372 adr r2, tegra20_sdram_pad_address
373 adr r3, tegra20_sdram_pad_safe
374 adr r4, tegra20_sdram_pad_save
377 ldr r6, tegra20_sdram_pad_size
379 ldr r0, [r2, r5] @ r0 is the addr in the pad_address
382 str r1, [r4, r5] @ save the content of the addr
385 str r1, [r0] @ set the save val to the addr
392 mov32 r5, TEGRA_CLK_RESET_BASE
393 ldr r0, [r5, #CLK_RESET_SCLK_BURST]
394 adr r2, tegra20_sclk_save
399 tegra20_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
408 tegra20_sdram_pad_size:
409 .word tegra20_sdram_pad_size - tegra20_sdram_pad_address
411 tegra20_sdram_pad_safe:
423 tegra20_sdram_pad_save:
424 .rept (tegra20_sdram_pad_size - tegra20_sdram_pad_address) / 4
432 /* dummy symbol for end of IRAM */
433 .align L1_CACHE_SHIFT
434 .globl tegra20_iram_end