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 .macro pll_enable, rd, r_car_base, pll_base
47 	ldr	\rd, [\r_car_base, #\pll_base]
48 	tst	\rd, #(1 << 30)
49 	orreq	\rd, \rd, #(1 << 30)
50 	streq	\rd, [\r_car_base, #\pll_base]
51 .endm
52 
53 .macro emc_device_mask, rd, base
54 	ldr	\rd, [\base, #EMC_ADR_CFG]
55 	tst	\rd, #(0x3 << 24)
56 	moveq	\rd, #(0x1 << 8)		@ just 1 device
57 	movne	\rd, #(0x3 << 8)		@ 2 devices
58 .endm
59 
60 #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
61 /*
62  * tegra20_hotplug_shutdown(void)
63  *
64  * puts the current cpu in reset
65  * should never return
66  */
67 ENTRY(tegra20_hotplug_shutdown)
68 	/* Put this CPU down */
69 	cpu_id	r0
70 	bl	tegra20_cpu_shutdown
71 	ret	lr			@ should never get here
72 ENDPROC(tegra20_hotplug_shutdown)
73 
74 /*
75  * tegra20_cpu_shutdown(int cpu)
76  *
77  * r0 is cpu to reset
78  *
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.
84  *
85  * corrupts r0-r3, r12
86  */
87 ENTRY(tegra20_cpu_shutdown)
88 	cmp	r0, #0
89 	reteq	lr			@ must not be called for CPU 0
90 
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
95 	ldr	r2, [r3, r1]
96 	isb
97 	dsb
98 	movw	r1, 0x1011
99 	mov	r1, r1, lsl r0
100 	ldr	r3, =TEGRA_CLK_RESET_VIRT
101 	str	r1, [r3, #0x340]	@ put slave CPU in reset
102 	isb
103 	dsb
104 	cpu_id	r3
105 	cmp	r3, r0
106 	beq	.
107 	ret	lr
108 ENDPROC(tegra20_cpu_shutdown)
109 #endif
110 
111 #ifdef CONFIG_PM_SLEEP
112 /*
113  * tegra20_sleep_core_finish(unsigned long v2p)
114  *
115  * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to
116  * tegra20_tear_down_core in IRAM
117  */
118 ENTRY(tegra20_sleep_core_finish)
119 	mov     r4, r0
120 	/* Flush, disable the L1 data cache and exit SMP */
121 	mov     r0, #TEGRA_FLUSH_CACHE_ALL
122 	bl	tegra_disable_clean_inv_dcache
123 	mov     r0, r4
124 
125 	mov32	r3, tegra_shut_off_mmu
126 	add	r3, r3, r0
127 
128 	mov32	r0, tegra20_tear_down_core
129 	mov32	r1, tegra20_iram_start
130 	sub	r0, r0, r1
131 	mov32	r1, TEGRA_IRAM_LPx_RESUME_AREA
132 	add	r0, r0, r1
133 
134 	ret	r3
135 ENDPROC(tegra20_sleep_core_finish)
136 
137 /*
138  * tegra20_tear_down_cpu
139  *
140  * Switches the CPU cluster to PLL-P and enters sleep.
141  */
142 ENTRY(tegra20_tear_down_cpu)
143 	bl	tegra_switch_cpu_to_pllp
144 	b	tegra20_enter_sleep
145 ENDPROC(tegra20_tear_down_cpu)
146 
147 /* START OF ROUTINES COPIED TO IRAM */
148 	.align L1_CACHE_SHIFT
149 	.globl tegra20_iram_start
150 tegra20_iram_start:
151 
152 /*
153  * tegra20_lp1_reset
154  *
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
161  * PMC_SCRATCH41.
162  *
163  * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
164  */
165 ENTRY(tegra20_lp1_reset)
166 	/*
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.
170 	 */
171 	mov32	r0, TEGRA_CLK_RESET_BASE
172 
173 	mov	r1, #(1 << 28)
174 	str	r1, [r0, #CLK_RESET_SCLK_BURST]
175 	str	r1, [r0, #CLK_RESET_CCLK_BURST]
176 	mov	r1, #0
177 	str	r1, [r0, #CLK_RESET_CCLK_DIVIDER]
178 	str	r1, [r0, #CLK_RESET_SCLK_DIVIDER]
179 
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
183 
184 	adr	r2, tegra20_sdram_pad_address
185 	adr	r4, tegra20_sdram_pad_save
186 	mov	r5, #0
187 
188 	ldr	r6, tegra20_sdram_pad_size
189 padload:
190 	ldr	r7, [r2, r5]		@ r7 is the addr in the pad_address
191 
192 	ldr	r1, [r4, r5]
193 	str	r1, [r7]		@ restore the value in pad_save
194 
195 	add	r5, r5, #4
196 	cmp	r6, r5
197 	bne	padload
198 
199 padload_done:
200 	/* 255uS delay for PLL stabilization */
201 	mov32	r7, TEGRA_TMRUS_BASE
202 	ldr	r1, [r7]
203 	add	r1, r1, #0xff
204 	wait_until r1, r7, r9
205 
206 	adr	r4, tegra20_sclk_save
207 	ldr	r4, [r4]
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]
211 
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]
216 
217 	mov	r1, #0
218 	str	r1, [r0, #EMC_SELF_REF]	@ take DRAM out of self refresh
219 	mov	r1, #1
220 	str	r1, [r0, #EMC_NOP]
221 	str	r1, [r0, #EMC_NOP]
222 
223 	emc_device_mask r1, r0
224 
225 exit_selfrefresh_loop:
226 	ldr	r2, [r0, #EMC_EMC_STATUS]
227 	ands	r2, r2, r1
228 	bne	exit_selfrefresh_loop
229 
230 	mov	r1, #0			@ unstall all transactions
231 	str	r1, [r0, #EMC_REQ_CTRL]
232 
233 	mov32	r0, TEGRA_PMC_BASE
234 	ldr	r0, [r0, #PMC_SCRATCH41]
235 	ret	r0			@ jump to tegra_resume
236 ENDPROC(tegra20_lp1_reset)
237 
238 /*
239  * tegra20_tear_down_core
240  *
241  * copied into and executed from IRAM
242  * puts memory in self-refresh for LP0 and LP1
243  */
244 tegra20_tear_down_core:
245 	bl	tegra20_sdram_self_refresh
246 	bl	tegra20_switch_cpu_to_clk32k
247 	b	tegra20_enter_sleep
248 
249 /*
250  * tegra20_switch_cpu_to_clk32k
251  *
252  * In LP0 and LP1 all PLLs will be turned off. Switch the CPU and system clock
253  * to the 32KHz clock.
254  */
255 tegra20_switch_cpu_to_clk32k:
256 	/*
257 	 * start by switching to CLKM to safely disable PLLs, then switch to
258 	 * CLKS.
259 	 */
260 	mov	r0, #(1 << 28)
261 	str	r0, [r5, #CLK_RESET_SCLK_BURST]
262 	str	r0, [r5, #CLK_RESET_CCLK_BURST]
263 	mov	r0, #0
264 	str	r0, [r5, #CLK_RESET_CCLK_DIVIDER]
265 	str	r0, [r5, #CLK_RESET_SCLK_DIVIDER]
266 
267 	/* 2uS delay delay between changing SCLK and disabling PLLs */
268 	mov32	r7, TEGRA_TMRUS_BASE
269 	ldr	r1, [r7]
270 	add	r1, r1, #2
271 	wait_until r1, r7, r9
272 
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]
283 
284 	/* switch to CLKS */
285 	mov	r0, #0	/* brust policy = 32KHz */
286 	str	r0, [r5, #CLK_RESET_SCLK_BURST]
287 
288 	ret	lr
289 
290 /*
291  * tegra20_enter_sleep
292  *
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
296  */
297 tegra20_enter_sleep:
298 	mov32   r6, TEGRA_FLOW_CTRL_BASE
299 
300 	mov     r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
301 	orr	r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
302 	cpu_id	r1
303 	cpu_to_halt_reg r1, r1
304 	str	r0, [r6, r1]
305 	dsb
306 	ldr	r0, [r6, r1] /* memory barrier */
307 
308 halted:
309 	dsb
310 	wfe	/* CPU should be power gated here */
311 	isb
312 	b	halted
313 
314 /*
315  * tegra20_sdram_self_refresh
316  *
317  * called with MMU off and caches disabled
318  * puts sdram in self refresh
319  * must be executed from IRAM
320  */
321 tegra20_sdram_self_refresh:
322 	mov32	r1, TEGRA_EMC_BASE	@ r1 reserved for emc base addr
323 
324 	mov	r2, #3
325 	str	r2, [r1, #EMC_REQ_CTRL]	@ stall incoming DRAM requests
326 
327 emcidle:
328 	ldr	r2, [r1, #EMC_EMC_STATUS]
329 	tst	r2, #4
330 	beq	emcidle
331 
332 	mov	r2, #1
333 	str	r2, [r1, #EMC_SELF_REF]
334 
335 	emc_device_mask r2, r1
336 
337 emcself:
338 	ldr	r3, [r1, #EMC_EMC_STATUS]
339 	and	r3, r3, r2
340 	cmp	r3, r2
341 	bne	emcself			@ loop until DDR in self-refresh
342 
343 	adr	r2, tegra20_sdram_pad_address
344 	adr	r3, tegra20_sdram_pad_safe
345 	adr	r4, tegra20_sdram_pad_save
346 	mov	r5, #0
347 
348 	ldr	r6, tegra20_sdram_pad_size
349 padsave:
350 	ldr	r0, [r2, r5]		@ r0 is the addr in the pad_address
351 
352 	ldr	r1, [r0]
353 	str	r1, [r4, r5]		@ save the content of the addr
354 
355 	ldr	r1, [r3, r5]
356 	str	r1, [r0]		@ set the save val to the addr
357 
358 	add	r5, r5, #4
359 	cmp	r6, r5
360 	bne	padsave
361 padsave_done:
362 
363 	mov32	r5, TEGRA_CLK_RESET_BASE
364 	ldr	r0, [r5, #CLK_RESET_SCLK_BURST]
365 	adr	r2, tegra20_sclk_save
366 	str	r0, [r2]
367 	dsb
368 	ret	lr
369 
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
378 
379 tegra20_sdram_pad_size:
380 	.word	tegra20_sdram_pad_size - tegra20_sdram_pad_address
381 
382 tegra20_sdram_pad_safe:
383 	.word	0x8
384 	.word	0x8
385 	.word	0x0
386 	.word	0x8
387 	.word	0x5500
388 	.word	0x08080040
389 	.word	0x0
390 
391 tegra20_sclk_save:
392 	.word	0x0
393 
394 tegra20_sdram_pad_save:
395 	.rept (tegra20_sdram_pad_size - tegra20_sdram_pad_address) / 4
396 	.long	0
397 	.endr
398 
399 	.ltorg
400 /* dummy symbol for end of IRAM */
401 	.align L1_CACHE_SHIFT
402 	.globl tegra20_iram_end
403 tegra20_iram_end:
404 	b	.
405 #endif
406