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 .macro pll_enable, rd, r_car_base, pll_base
47 ldr \rd, [\r_car_base, #\pll_base]
49 orreq \rd, \rd, #(1 << 30)
50 streq \rd, [\r_car_base, #\pll_base]
53 .macro emc_device_mask, rd, base
54 ldr \rd, [\base, #EMC_ADR_CFG]
56 moveq \rd, #(0x1 << 8) @ just 1 device
57 movne \rd, #(0x3 << 8) @ 2 devices
60 #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
62 * tegra20_hotplug_shutdown(void)
64 * puts the current cpu in reset
67 ENTRY(tegra20_hotplug_shutdown)
68 /* Put this CPU down */
70 bl tegra20_cpu_shutdown
71 ret lr @ should never get here
72 ENDPROC(tegra20_hotplug_shutdown)
75 * tegra20_cpu_shutdown(int cpu)
79 * puts the specified CPU in wait-for-event mode on the flow controller
80 * and puts the CPU in reset
81 * can be called on the current cpu or another cpu
82 * if called on the current cpu, does not return
83 * MUST NOT BE CALLED FOR CPU 0.
87 ENTRY(tegra20_cpu_shutdown)
89 reteq lr @ must not be called for CPU 0
91 cpu_to_halt_reg r1, r0
92 ldr r3, =TEGRA_FLOW_CTRL_VIRT
93 mov r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
94 str r2, [r3, r1] @ put flow controller in wait event mode
100 ldr r3, =TEGRA_CLK_RESET_VIRT
101 str r1, [r3, #0x340] @ put slave CPU in reset
108 ENDPROC(tegra20_cpu_shutdown)
111 #ifdef CONFIG_PM_SLEEP
113 * tegra20_sleep_core_finish(unsigned long v2p)
115 * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to
116 * tegra20_tear_down_core in IRAM
118 ENTRY(tegra20_sleep_core_finish)
120 /* Flush, disable the L1 data cache and exit SMP */
121 mov r0, #TEGRA_FLUSH_CACHE_ALL
122 bl tegra_disable_clean_inv_dcache
125 mov32 r3, tegra_shut_off_mmu
128 mov32 r0, tegra20_tear_down_core
129 mov32 r1, tegra20_iram_start
131 mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA
135 ENDPROC(tegra20_sleep_core_finish)
138 * tegra20_tear_down_cpu
140 * Switches the CPU cluster to PLL-P and enters sleep.
142 ENTRY(tegra20_tear_down_cpu)
143 bl tegra_switch_cpu_to_pllp
144 b tegra20_enter_sleep
145 ENDPROC(tegra20_tear_down_cpu)
147 /* START OF ROUTINES COPIED TO IRAM */
148 .align L1_CACHE_SHIFT
149 .globl tegra20_iram_start
155 * reset vector for LP1 restore; copied into IRAM during suspend.
156 * Brings the system back up to a safe staring point (SDRAM out of
157 * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP,
158 * system clock running on the same PLL that it suspended at), and
159 * jumps to tegra_resume to restore virtual addressing and PLLX.
160 * The physical address of tegra_resume expected to be stored in
163 * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
165 ENTRY(tegra20_lp1_reset)
167 * The CPU and system bus are running at 32KHz and executing from
168 * IRAM when this code is executed; immediately switch to CLKM and
169 * enable PLLM, PLLP, PLLC.
171 mov32 r0, TEGRA_CLK_RESET_BASE
174 str r1, [r0, #CLK_RESET_SCLK_BURST]
175 str r1, [r0, #CLK_RESET_CCLK_BURST]
177 str r1, [r0, #CLK_RESET_CCLK_DIVIDER]
178 str r1, [r0, #CLK_RESET_SCLK_DIVIDER]
180 pll_enable r1, r0, CLK_RESET_PLLM_BASE
181 pll_enable r1, r0, CLK_RESET_PLLP_BASE
182 pll_enable r1, r0, CLK_RESET_PLLC_BASE
184 adr r2, tegra20_sdram_pad_address
185 adr r4, tegra20_sdram_pad_save
188 ldr r6, tegra20_sdram_pad_size
190 ldr r7, [r2, r5] @ r7 is the addr in the pad_address
193 str r1, [r7] @ restore the value in pad_save
200 /* 255uS delay for PLL stabilization */
201 mov32 r7, TEGRA_TMRUS_BASE
204 wait_until r1, r7, r9
206 adr r4, tegra20_sclk_save
208 str r4, [r0, #CLK_RESET_SCLK_BURST]
209 mov32 r4, ((1 << 28) | (4)) @ burst policy is PLLP
210 str r4, [r0, #CLK_RESET_CCLK_BURST]
212 mov32 r0, TEGRA_EMC_BASE
213 ldr r1, [r0, #EMC_CFG]
214 bic r1, r1, #(1 << 31) @ disable DRAM_CLK_STOP
215 str r1, [r0, #EMC_CFG]
218 str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh
220 str r1, [r0, #EMC_NOP]
221 str r1, [r0, #EMC_NOP]
223 emc_device_mask r1, r0
225 exit_selfrefresh_loop:
226 ldr r2, [r0, #EMC_EMC_STATUS]
228 bne exit_selfrefresh_loop
230 mov r1, #0 @ unstall all transactions
231 str r1, [r0, #EMC_REQ_CTRL]
233 mov32 r0, TEGRA_PMC_BASE
234 ldr r0, [r0, #PMC_SCRATCH41]
235 ret r0 @ jump to tegra_resume
236 ENDPROC(tegra20_lp1_reset)
239 * tegra20_tear_down_core
241 * copied into and executed from IRAM
242 * puts memory in self-refresh for LP0 and LP1
244 tegra20_tear_down_core:
245 bl tegra20_sdram_self_refresh
246 bl tegra20_switch_cpu_to_clk32k
247 b tegra20_enter_sleep
250 * tegra20_switch_cpu_to_clk32k
252 * In LP0 and LP1 all PLLs will be turned off. Switch the CPU and system clock
253 * to the 32KHz clock.
255 tegra20_switch_cpu_to_clk32k:
257 * start by switching to CLKM to safely disable PLLs, then switch to
261 str r0, [r5, #CLK_RESET_SCLK_BURST]
262 str r0, [r5, #CLK_RESET_CCLK_BURST]
264 str r0, [r5, #CLK_RESET_CCLK_DIVIDER]
265 str r0, [r5, #CLK_RESET_SCLK_DIVIDER]
267 /* 2uS delay delay between changing SCLK and disabling PLLs */
268 mov32 r7, TEGRA_TMRUS_BASE
271 wait_until r1, r7, r9
273 /* disable PLLM, PLLP and PLLC */
274 ldr r0, [r5, #CLK_RESET_PLLM_BASE]
275 bic r0, r0, #(1 << 30)
276 str r0, [r5, #CLK_RESET_PLLM_BASE]
277 ldr r0, [r5, #CLK_RESET_PLLP_BASE]
278 bic r0, r0, #(1 << 30)
279 str r0, [r5, #CLK_RESET_PLLP_BASE]
280 ldr r0, [r5, #CLK_RESET_PLLC_BASE]
281 bic r0, r0, #(1 << 30)
282 str r0, [r5, #CLK_RESET_PLLC_BASE]
285 mov r0, #0 /* brust policy = 32KHz */
286 str r0, [r5, #CLK_RESET_SCLK_BURST]
291 * tegra20_enter_sleep
293 * uses flow controller to enter sleep state
294 * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1
295 * executes from SDRAM with target state is LP2
298 mov32 r6, TEGRA_FLOW_CTRL_BASE
300 mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
301 orr r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
303 cpu_to_halt_reg r1, r1
306 ldr r0, [r6, r1] /* memory barrier */
310 wfe /* CPU should be power gated here */
315 * tegra20_sdram_self_refresh
317 * called with MMU off and caches disabled
318 * puts sdram in self refresh
319 * must be executed from IRAM
321 tegra20_sdram_self_refresh:
322 mov32 r1, TEGRA_EMC_BASE @ r1 reserved for emc base addr
325 str r2, [r1, #EMC_REQ_CTRL] @ stall incoming DRAM requests
328 ldr r2, [r1, #EMC_EMC_STATUS]
333 str r2, [r1, #EMC_SELF_REF]
335 emc_device_mask r2, r1
338 ldr r3, [r1, #EMC_EMC_STATUS]
341 bne emcself @ loop until DDR in self-refresh
343 adr r2, tegra20_sdram_pad_address
344 adr r3, tegra20_sdram_pad_safe
345 adr r4, tegra20_sdram_pad_save
348 ldr r6, tegra20_sdram_pad_size
350 ldr r0, [r2, r5] @ r0 is the addr in the pad_address
353 str r1, [r4, r5] @ save the content of the addr
356 str r1, [r0] @ set the save val to the addr
363 mov32 r5, TEGRA_CLK_RESET_BASE
364 ldr r0, [r5, #CLK_RESET_SCLK_BURST]
365 adr r2, tegra20_sclk_save
370 tegra20_sdram_pad_address:
371 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL
372 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL
373 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CLKCFGPADCTRL
374 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2COMPPADCTRL
375 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2VTTGENPADCTRL
376 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL2
377 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL2
379 tegra20_sdram_pad_size:
380 .word tegra20_sdram_pad_size - tegra20_sdram_pad_address
382 tegra20_sdram_pad_safe:
394 tegra20_sdram_pad_save:
395 .rept (tegra20_sdram_pad_size - tegra20_sdram_pad_address) / 4
400 /* dummy symbol for end of IRAM */
401 .align L1_CACHE_SHIFT
402 .globl tegra20_iram_end