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)
50 .macro test_pll_state, rd, test_mask
51 ldr \rd, tegra_pll_state
55 .macro store_pll_state, rd, tmp, r_car_base, pll_base, pll_mask
56 ldr \rd, [\r_car_base, #\pll_base]
58 ldr \rd, tegra_pll_state
59 biceq \rd, \rd, #\pll_mask
60 orrne \rd, \rd, #\pll_mask
61 adr \tmp, tegra_pll_state
65 .macro pll_enable, rd, r_car_base, pll_base, test_mask
66 test_pll_state \rd, \test_mask
69 ldr \rd, [\r_car_base, #\pll_base]
71 orreq \rd, \rd, #(1 << 30)
72 streq \rd, [\r_car_base, #\pll_base]
76 .macro emc_device_mask, rd, base
77 ldr \rd, [\base, #EMC_ADR_CFG]
79 moveq \rd, #(0x1 << 8) @ just 1 device
80 movne \rd, #(0x3 << 8) @ 2 devices
83 #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
85 * tegra20_hotplug_shutdown(void)
87 * puts the current cpu in reset
90 ENTRY(tegra20_hotplug_shutdown)
91 /* Put this CPU down */
93 bl tegra20_cpu_shutdown
94 ret lr @ should never get here
95 ENDPROC(tegra20_hotplug_shutdown)
98 * tegra20_cpu_shutdown(int cpu)
102 * puts the specified CPU in wait-for-event mode on the flow controller
103 * and puts the CPU in reset
104 * can be called on the current cpu or another cpu
105 * if called on the current cpu, does not return
106 * MUST NOT BE CALLED FOR CPU 0.
108 * corrupts r0-r3, r12
110 ENTRY(tegra20_cpu_shutdown)
112 reteq lr @ must not be called for CPU 0
114 cpu_to_halt_reg r1, r0
115 ldr r3, =TEGRA_FLOW_CTRL_VIRT
116 mov r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
117 str r2, [r3, r1] @ put flow controller in wait event mode
123 ldr r3, =TEGRA_CLK_RESET_VIRT
124 str r1, [r3, #0x340] @ put slave CPU in reset
131 ENDPROC(tegra20_cpu_shutdown)
134 #ifdef CONFIG_PM_SLEEP
136 * tegra20_sleep_core_finish(unsigned long v2p)
138 * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to
139 * tegra20_tear_down_core in IRAM
141 ENTRY(tegra20_sleep_core_finish)
143 /* Flush, disable the L1 data cache and exit SMP */
144 mov r0, #TEGRA_FLUSH_CACHE_ALL
145 bl tegra_disable_clean_inv_dcache
148 mov32 r3, tegra_shut_off_mmu
151 mov32 r0, tegra20_tear_down_core
152 mov32 r1, tegra20_iram_start
154 mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA
158 ENDPROC(tegra20_sleep_core_finish)
161 * tegra20_tear_down_cpu
163 * Switches the CPU cluster to PLL-P and enters sleep.
165 ENTRY(tegra20_tear_down_cpu)
166 bl tegra_switch_cpu_to_pllp
167 b tegra20_enter_sleep
168 ENDPROC(tegra20_tear_down_cpu)
170 /* START OF ROUTINES COPIED TO IRAM */
171 .align L1_CACHE_SHIFT
172 .globl tegra20_iram_start
178 * reset vector for LP1 restore; copied into IRAM during suspend.
179 * Brings the system back up to a safe staring point (SDRAM out of
180 * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP,
181 * system clock running on the same PLL that it suspended at), and
182 * jumps to tegra_resume to restore virtual addressing and PLLX.
183 * The physical address of tegra_resume expected to be stored in
186 * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
188 ENTRY(tegra20_lp1_reset)
190 * The CPU and system bus are running at 32KHz and executing from
191 * IRAM when this code is executed; immediately switch to CLKM and
192 * enable PLLM, PLLP, PLLC.
194 mov32 r0, TEGRA_CLK_RESET_BASE
197 str r1, [r0, #CLK_RESET_SCLK_BURST]
198 str r1, [r0, #CLK_RESET_CCLK_BURST]
200 str r1, [r0, #CLK_RESET_CCLK_DIVIDER]
201 str r1, [r0, #CLK_RESET_SCLK_DIVIDER]
203 pll_enable r1, r0, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK
204 pll_enable r1, r0, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK
205 pll_enable r1, r0, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK
207 adr r2, tegra20_sdram_pad_address
208 adr r4, tegra20_sdram_pad_save
211 ldr r6, tegra20_sdram_pad_size
213 ldr r7, [r2, r5] @ r7 is the addr in the pad_address
216 str r1, [r7] @ restore the value in pad_save
223 /* 255uS delay for PLL stabilization */
224 mov32 r7, TEGRA_TMRUS_BASE
227 wait_until r1, r7, r9
229 adr r4, tegra20_sclk_save
231 str r4, [r0, #CLK_RESET_SCLK_BURST]
232 mov32 r4, ((1 << 28) | (4)) @ burst policy is PLLP
233 str r4, [r0, #CLK_RESET_CCLK_BURST]
235 mov32 r0, TEGRA_EMC_BASE
236 ldr r1, [r0, #EMC_CFG]
237 bic r1, r1, #(1 << 31) @ disable DRAM_CLK_STOP
238 str r1, [r0, #EMC_CFG]
241 str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh
243 str r1, [r0, #EMC_NOP]
244 str r1, [r0, #EMC_NOP]
246 emc_device_mask r1, r0
248 exit_selfrefresh_loop:
249 ldr r2, [r0, #EMC_EMC_STATUS]
251 bne exit_selfrefresh_loop
253 mov r1, #0 @ unstall all transactions
254 str r1, [r0, #EMC_REQ_CTRL]
256 mov32 r0, TEGRA_PMC_BASE
257 ldr r0, [r0, #PMC_SCRATCH41]
258 ret r0 @ jump to tegra_resume
259 ENDPROC(tegra20_lp1_reset)
262 * tegra20_tear_down_core
264 * copied into and executed from IRAM
265 * puts memory in self-refresh for LP0 and LP1
267 tegra20_tear_down_core:
268 bl tegra20_sdram_self_refresh
269 bl tegra20_switch_cpu_to_clk32k
270 b tegra20_enter_sleep
273 * tegra20_switch_cpu_to_clk32k
275 * In LP0 and LP1 all PLLs will be turned off. Switch the CPU and system clock
276 * to the 32KHz clock.
278 tegra20_switch_cpu_to_clk32k:
280 * start by switching to CLKM to safely disable PLLs, then switch to
284 str r0, [r5, #CLK_RESET_SCLK_BURST]
285 str r0, [r5, #CLK_RESET_CCLK_BURST]
287 str r0, [r5, #CLK_RESET_CCLK_DIVIDER]
288 str r0, [r5, #CLK_RESET_SCLK_DIVIDER]
290 /* 2uS delay delay between changing SCLK and disabling PLLs */
291 mov32 r7, TEGRA_TMRUS_BASE
294 wait_until r1, r7, r9
296 store_pll_state r0, r1, r5, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK
297 store_pll_state r0, r1, r5, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK
298 store_pll_state r0, r1, r5, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK
300 /* disable PLLM, PLLP and PLLC */
301 ldr r0, [r5, #CLK_RESET_PLLM_BASE]
302 bic r0, r0, #(1 << 30)
303 str r0, [r5, #CLK_RESET_PLLM_BASE]
304 ldr r0, [r5, #CLK_RESET_PLLP_BASE]
305 bic r0, r0, #(1 << 30)
306 str r0, [r5, #CLK_RESET_PLLP_BASE]
307 ldr r0, [r5, #CLK_RESET_PLLC_BASE]
308 bic r0, r0, #(1 << 30)
309 str r0, [r5, #CLK_RESET_PLLC_BASE]
312 mov r0, #0 /* brust policy = 32KHz */
313 str r0, [r5, #CLK_RESET_SCLK_BURST]
318 * tegra20_enter_sleep
320 * uses flow controller to enter sleep state
321 * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1
322 * executes from SDRAM with target state is LP2
325 mov32 r6, TEGRA_FLOW_CTRL_BASE
327 mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
328 orr r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
330 cpu_to_halt_reg r1, r1
333 ldr r0, [r6, r1] /* memory barrier */
337 wfe /* CPU should be power gated here */
342 * tegra20_sdram_self_refresh
344 * called with MMU off and caches disabled
345 * puts sdram in self refresh
346 * must be executed from IRAM
348 tegra20_sdram_self_refresh:
349 mov32 r1, TEGRA_EMC_BASE @ r1 reserved for emc base addr
352 str r2, [r1, #EMC_REQ_CTRL] @ stall incoming DRAM requests
355 ldr r2, [r1, #EMC_EMC_STATUS]
360 str r2, [r1, #EMC_SELF_REF]
362 emc_device_mask r2, r1
365 ldr r3, [r1, #EMC_EMC_STATUS]
368 bne emcself @ loop until DDR in self-refresh
370 adr r2, tegra20_sdram_pad_address
371 adr r3, tegra20_sdram_pad_safe
372 adr r4, tegra20_sdram_pad_save
375 ldr r6, tegra20_sdram_pad_size
377 ldr r0, [r2, r5] @ r0 is the addr in the pad_address
380 str r1, [r4, r5] @ save the content of the addr
383 str r1, [r0] @ set the save val to the addr
390 mov32 r5, TEGRA_CLK_RESET_BASE
391 ldr r0, [r5, #CLK_RESET_SCLK_BURST]
392 adr r2, tegra20_sclk_save
397 tegra20_sdram_pad_address:
398 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL
399 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL
400 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CLKCFGPADCTRL
401 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2COMPPADCTRL
402 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2VTTGENPADCTRL
403 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL2
404 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL2
406 tegra20_sdram_pad_size:
407 .word tegra20_sdram_pad_size - tegra20_sdram_pad_address
409 tegra20_sdram_pad_safe:
421 tegra20_sdram_pad_save:
422 .rept (tegra20_sdram_pad_size - tegra20_sdram_pad_address) / 4
430 /* dummy symbol for end of IRAM */
431 .align L1_CACHE_SHIFT
432 .globl tegra20_iram_end