1/*
2 * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
3 * Copyright (c) 2011, Google, Inc.
4 *
5 * Author: Colin Cross <ccross@android.com>
6 *         Gary King <gking@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <linux/linkage.h>
22
23#include <soc/tegra/flowctrl.h>
24
25#include <asm/assembler.h>
26#include <asm/proc-fns.h>
27#include <asm/cp15.h>
28#include <asm/cache.h>
29
30#include "irammap.h"
31#include "sleep.h"
32
33#define EMC_CFG				0xc
34#define EMC_ADR_CFG			0x10
35#define EMC_REFRESH			0x70
36#define EMC_NOP				0xdc
37#define EMC_SELF_REF			0xe0
38#define EMC_REQ_CTRL			0x2b0
39#define EMC_EMC_STATUS			0x2b4
40
41#define CLK_RESET_CCLK_BURST		0x20
42#define CLK_RESET_CCLK_DIVIDER		0x24
43#define CLK_RESET_SCLK_BURST		0x28
44#define CLK_RESET_SCLK_DIVIDER		0x2c
45#define CLK_RESET_PLLC_BASE		0x80
46#define CLK_RESET_PLLM_BASE		0x90
47#define CLK_RESET_PLLP_BASE		0xa0
48
49#define APB_MISC_XM2CFGCPADCTRL		0x8c8
50#define APB_MISC_XM2CFGDPADCTRL		0x8cc
51#define APB_MISC_XM2CLKCFGPADCTRL	0x8d0
52#define APB_MISC_XM2COMPPADCTRL		0x8d4
53#define APB_MISC_XM2VTTGENPADCTRL	0x8d8
54#define APB_MISC_XM2CFGCPADCTRL2	0x8e4
55#define APB_MISC_XM2CFGDPADCTRL2	0x8e8
56
57.macro pll_enable, rd, r_car_base, pll_base
58	ldr	\rd, [\r_car_base, #\pll_base]
59	tst	\rd, #(1 << 30)
60	orreq	\rd, \rd, #(1 << 30)
61	streq	\rd, [\r_car_base, #\pll_base]
62.endm
63
64.macro emc_device_mask, rd, base
65	ldr	\rd, [\base, #EMC_ADR_CFG]
66	tst	\rd, #(0x3 << 24)
67	moveq	\rd, #(0x1 << 8)		@ just 1 device
68	movne	\rd, #(0x3 << 8)		@ 2 devices
69.endm
70
71#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
72/*
73 * tegra20_hotplug_shutdown(void)
74 *
75 * puts the current cpu in reset
76 * should never return
77 */
78ENTRY(tegra20_hotplug_shutdown)
79	/* Put this CPU down */
80	cpu_id	r0
81	bl	tegra20_cpu_shutdown
82	ret	lr			@ should never get here
83ENDPROC(tegra20_hotplug_shutdown)
84
85/*
86 * tegra20_cpu_shutdown(int cpu)
87 *
88 * r0 is cpu to reset
89 *
90 * puts the specified CPU in wait-for-event mode on the flow controller
91 * and puts the CPU in reset
92 * can be called on the current cpu or another cpu
93 * if called on the current cpu, does not return
94 * MUST NOT BE CALLED FOR CPU 0.
95 *
96 * corrupts r0-r3, r12
97 */
98ENTRY(tegra20_cpu_shutdown)
99	cmp	r0, #0
100	reteq	lr			@ must not be called for CPU 0
101	mov32	r1, TEGRA_IRAM_RESET_BASE_VIRT
102	ldr	r2, =__tegra20_cpu1_resettable_status_offset
103	mov	r12, #CPU_RESETTABLE
104	strb	r12, [r1, r2]
105
106	cpu_to_halt_reg r1, r0
107	ldr	r3, =TEGRA_FLOW_CTRL_VIRT
108	mov	r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
109	str	r2, [r3, r1]		@ put flow controller in wait event mode
110	ldr	r2, [r3, r1]
111	isb
112	dsb
113	movw	r1, 0x1011
114	mov	r1, r1, lsl r0
115	ldr	r3, =TEGRA_CLK_RESET_VIRT
116	str	r1, [r3, #0x340]	@ put slave CPU in reset
117	isb
118	dsb
119	cpu_id	r3
120	cmp	r3, r0
121	beq	.
122	ret	lr
123ENDPROC(tegra20_cpu_shutdown)
124#endif
125
126#ifdef CONFIG_PM_SLEEP
127/*
128 * tegra_pen_lock
129 *
130 * spinlock implementation with no atomic test-and-set and no coherence
131 * using Peterson's algorithm on strongly-ordered registers
132 * used to synchronize a cpu waking up from wfi with entering lp2 on idle
133 *
134 * The reference link of Peterson's algorithm:
135 * http://en.wikipedia.org/wiki/Peterson's_algorithm
136 *
137 * SCRATCH37 = r1 = !turn (inverted from Peterson's algorithm)
138 * on cpu 0:
139 * r2 = flag[0] (in SCRATCH38)
140 * r3 = flag[1] (in SCRATCH39)
141 * on cpu1:
142 * r2 = flag[1] (in SCRATCH39)
143 * r3 = flag[0] (in SCRATCH38)
144 *
145 * must be called with MMU on
146 * corrupts r0-r3, r12
147 */
148ENTRY(tegra_pen_lock)
149	mov32	r3, TEGRA_PMC_VIRT
150	cpu_id	r0
151	add	r1, r3, #PMC_SCRATCH37
152	cmp	r0, #0
153	addeq	r2, r3, #PMC_SCRATCH38
154	addeq	r3, r3, #PMC_SCRATCH39
155	addne	r2, r3, #PMC_SCRATCH39
156	addne	r3, r3, #PMC_SCRATCH38
157
158	mov	r12, #1
159	str	r12, [r2]		@ flag[cpu] = 1
160	dsb
161	str	r12, [r1]		@ !turn = cpu
1621:	dsb
163	ldr	r12, [r3]
164	cmp	r12, #1			@ flag[!cpu] == 1?
165	ldreq	r12, [r1]
166	cmpeq	r12, r0			@ !turn == cpu?
167	beq	1b			@ while !turn == cpu && flag[!cpu] == 1
168
169	ret	lr			@ locked
170ENDPROC(tegra_pen_lock)
171
172ENTRY(tegra_pen_unlock)
173	dsb
174	mov32	r3, TEGRA_PMC_VIRT
175	cpu_id	r0
176	cmp	r0, #0
177	addeq	r2, r3, #PMC_SCRATCH38
178	addne	r2, r3, #PMC_SCRATCH39
179	mov	r12, #0
180	str	r12, [r2]
181	ret     lr
182ENDPROC(tegra_pen_unlock)
183
184/*
185 * tegra20_cpu_clear_resettable(void)
186 *
187 * Called to clear the "resettable soon" flag in IRAM variable when
188 * it is expected that the secondary CPU will be idle soon.
189 */
190ENTRY(tegra20_cpu_clear_resettable)
191	mov32	r1, TEGRA_IRAM_RESET_BASE_VIRT
192	ldr	r2, =__tegra20_cpu1_resettable_status_offset
193	mov	r12, #CPU_NOT_RESETTABLE
194	strb	r12, [r1, r2]
195	ret	lr
196ENDPROC(tegra20_cpu_clear_resettable)
197
198/*
199 * tegra20_cpu_set_resettable_soon(void)
200 *
201 * Called to set the "resettable soon" flag in IRAM variable when
202 * it is expected that the secondary CPU will be idle soon.
203 */
204ENTRY(tegra20_cpu_set_resettable_soon)
205	mov32	r1, TEGRA_IRAM_RESET_BASE_VIRT
206	ldr	r2, =__tegra20_cpu1_resettable_status_offset
207	mov	r12, #CPU_RESETTABLE_SOON
208	strb	r12, [r1, r2]
209	ret	lr
210ENDPROC(tegra20_cpu_set_resettable_soon)
211
212/*
213 * tegra20_cpu_is_resettable_soon(void)
214 *
215 * Returns true if the "resettable soon" flag in IRAM variable has been
216 * set because it is expected that the secondary CPU will be idle soon.
217 */
218ENTRY(tegra20_cpu_is_resettable_soon)
219	mov32	r1, TEGRA_IRAM_RESET_BASE_VIRT
220	ldr	r2, =__tegra20_cpu1_resettable_status_offset
221	ldrb	r12, [r1, r2]
222	cmp	r12, #CPU_RESETTABLE_SOON
223	moveq	r0, #1
224	movne	r0, #0
225	ret	lr
226ENDPROC(tegra20_cpu_is_resettable_soon)
227
228/*
229 * tegra20_sleep_core_finish(unsigned long v2p)
230 *
231 * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to
232 * tegra20_tear_down_core in IRAM
233 */
234ENTRY(tegra20_sleep_core_finish)
235	mov     r4, r0
236	/* Flush, disable the L1 data cache and exit SMP */
237	mov     r0, #TEGRA_FLUSH_CACHE_ALL
238	bl	tegra_disable_clean_inv_dcache
239	mov     r0, r4
240
241	mov32	r3, tegra_shut_off_mmu
242	add	r3, r3, r0
243
244	mov32	r0, tegra20_tear_down_core
245	mov32	r1, tegra20_iram_start
246	sub	r0, r0, r1
247	mov32	r1, TEGRA_IRAM_LPx_RESUME_AREA
248	add	r0, r0, r1
249
250	ret	r3
251ENDPROC(tegra20_sleep_core_finish)
252
253/*
254 * tegra20_sleep_cpu_secondary_finish(unsigned long v2p)
255 *
256 * Enters WFI on secondary CPU by exiting coherency.
257 */
258ENTRY(tegra20_sleep_cpu_secondary_finish)
259	stmfd	sp!, {r4-r11, lr}
260
261	mrc	p15, 0, r11, c1, c0, 1  @ save actlr before exiting coherency
262
263	/* Flush and disable the L1 data cache */
264	mov	r0, #TEGRA_FLUSH_CACHE_LOUIS
265	bl	tegra_disable_clean_inv_dcache
266
267	mov32	r0, TEGRA_IRAM_RESET_BASE_VIRT
268	ldr	r4, =__tegra20_cpu1_resettable_status_offset
269	mov	r3, #CPU_RESETTABLE
270	strb	r3, [r0, r4]
271
272	bl	tegra_cpu_do_idle
273
274	/*
275	 * cpu may be reset while in wfi, which will return through
276	 * tegra_resume to cpu_resume
277	 * or interrupt may wake wfi, which will return here
278	 * cpu state is unchanged - MMU is on, cache is on, coherency
279	 * is off, and the data cache is off
280	 *
281	 * r11 contains the original actlr
282	 */
283
284	bl	tegra_pen_lock
285
286	mov32	r0, TEGRA_IRAM_RESET_BASE_VIRT
287	ldr	r4, =__tegra20_cpu1_resettable_status_offset
288	mov	r3, #CPU_NOT_RESETTABLE
289	strb	r3, [r0, r4]
290
291	bl	tegra_pen_unlock
292
293	/* Re-enable the data cache */
294	mrc	p15, 0, r10, c1, c0, 0
295	orr	r10, r10, #CR_C
296	mcr	p15, 0, r10, c1, c0, 0
297	isb
298
299	mcr	p15, 0, r11, c1, c0, 1	@ reenable coherency
300
301	/* Invalidate the TLBs & BTAC */
302	mov	r1, #0
303	mcr	p15, 0, r1, c8, c3, 0	@ invalidate shared TLBs
304	mcr	p15, 0, r1, c7, c1, 6	@ invalidate shared BTAC
305	dsb
306	isb
307
308	/* the cpu was running with coherency disabled,
309	 * caches may be out of date */
310	bl	v7_flush_kern_cache_louis
311
312	ldmfd	sp!, {r4 - r11, pc}
313ENDPROC(tegra20_sleep_cpu_secondary_finish)
314
315/*
316 * tegra20_tear_down_cpu
317 *
318 * Switches the CPU cluster to PLL-P and enters sleep.
319 */
320ENTRY(tegra20_tear_down_cpu)
321	bl	tegra_switch_cpu_to_pllp
322	b	tegra20_enter_sleep
323ENDPROC(tegra20_tear_down_cpu)
324
325/* START OF ROUTINES COPIED TO IRAM */
326	.align L1_CACHE_SHIFT
327	.globl tegra20_iram_start
328tegra20_iram_start:
329
330/*
331 * tegra20_lp1_reset
332 *
333 * reset vector for LP1 restore; copied into IRAM during suspend.
334 * Brings the system back up to a safe staring point (SDRAM out of
335 * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP,
336 * system clock running on the same PLL that it suspended at), and
337 * jumps to tegra_resume to restore virtual addressing and PLLX.
338 * The physical address of tegra_resume expected to be stored in
339 * PMC_SCRATCH41.
340 *
341 * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
342 */
343ENTRY(tegra20_lp1_reset)
344	/*
345	 * The CPU and system bus are running at 32KHz and executing from
346	 * IRAM when this code is executed; immediately switch to CLKM and
347	 * enable PLLM, PLLP, PLLC.
348	 */
349	mov32	r0, TEGRA_CLK_RESET_BASE
350
351	mov	r1, #(1 << 28)
352	str	r1, [r0, #CLK_RESET_SCLK_BURST]
353	str	r1, [r0, #CLK_RESET_CCLK_BURST]
354	mov	r1, #0
355	str	r1, [r0, #CLK_RESET_CCLK_DIVIDER]
356	str	r1, [r0, #CLK_RESET_SCLK_DIVIDER]
357
358	pll_enable r1, r0, CLK_RESET_PLLM_BASE
359	pll_enable r1, r0, CLK_RESET_PLLP_BASE
360	pll_enable r1, r0, CLK_RESET_PLLC_BASE
361
362	adr	r2, tegra20_sdram_pad_address
363	adr	r4, tegra20_sdram_pad_save
364	mov	r5, #0
365
366	ldr	r6, tegra20_sdram_pad_size
367padload:
368	ldr	r7, [r2, r5]		@ r7 is the addr in the pad_address
369
370	ldr	r1, [r4, r5]
371	str	r1, [r7]		@ restore the value in pad_save
372
373	add	r5, r5, #4
374	cmp	r6, r5
375	bne	padload
376
377padload_done:
378	/* 255uS delay for PLL stabilization */
379	mov32	r7, TEGRA_TMRUS_BASE
380	ldr	r1, [r7]
381	add	r1, r1, #0xff
382	wait_until r1, r7, r9
383
384	adr	r4, tegra20_sclk_save
385	ldr	r4, [r4]
386	str	r4, [r0, #CLK_RESET_SCLK_BURST]
387	mov32	r4, ((1 << 28) | (4))	@ burst policy is PLLP
388	str	r4, [r0, #CLK_RESET_CCLK_BURST]
389
390	mov32	r0, TEGRA_EMC_BASE
391	ldr	r1, [r0, #EMC_CFG]
392	bic	r1, r1, #(1 << 31)	@ disable DRAM_CLK_STOP
393	str	r1, [r0, #EMC_CFG]
394
395	mov	r1, #0
396	str	r1, [r0, #EMC_SELF_REF]	@ take DRAM out of self refresh
397	mov	r1, #1
398	str	r1, [r0, #EMC_NOP]
399	str	r1, [r0, #EMC_NOP]
400	str	r1, [r0, #EMC_REFRESH]
401
402	emc_device_mask r1, r0
403
404exit_selfrefresh_loop:
405	ldr	r2, [r0, #EMC_EMC_STATUS]
406	ands	r2, r2, r1
407	bne	exit_selfrefresh_loop
408
409	mov	r1, #0			@ unstall all transactions
410	str	r1, [r0, #EMC_REQ_CTRL]
411
412	mov32	r0, TEGRA_PMC_BASE
413	ldr	r0, [r0, #PMC_SCRATCH41]
414	ret	r0			@ jump to tegra_resume
415ENDPROC(tegra20_lp1_reset)
416
417/*
418 * tegra20_tear_down_core
419 *
420 * copied into and executed from IRAM
421 * puts memory in self-refresh for LP0 and LP1
422 */
423tegra20_tear_down_core:
424	bl	tegra20_sdram_self_refresh
425	bl	tegra20_switch_cpu_to_clk32k
426	b	tegra20_enter_sleep
427
428/*
429 * tegra20_switch_cpu_to_clk32k
430 *
431 * In LP0 and LP1 all PLLs will be turned off. Switch the CPU and system clock
432 * to the 32KHz clock.
433 */
434tegra20_switch_cpu_to_clk32k:
435	/*
436	 * start by switching to CLKM to safely disable PLLs, then switch to
437	 * CLKS.
438	 */
439	mov	r0, #(1 << 28)
440	str	r0, [r5, #CLK_RESET_SCLK_BURST]
441	str	r0, [r5, #CLK_RESET_CCLK_BURST]
442	mov	r0, #0
443	str	r0, [r5, #CLK_RESET_CCLK_DIVIDER]
444	str	r0, [r5, #CLK_RESET_SCLK_DIVIDER]
445
446	/* 2uS delay delay between changing SCLK and disabling PLLs */
447	mov32	r7, TEGRA_TMRUS_BASE
448	ldr	r1, [r7]
449	add	r1, r1, #2
450	wait_until r1, r7, r9
451
452	/* disable PLLM, PLLP and PLLC */
453	ldr	r0, [r5, #CLK_RESET_PLLM_BASE]
454	bic	r0, r0, #(1 << 30)
455	str	r0, [r5, #CLK_RESET_PLLM_BASE]
456	ldr	r0, [r5, #CLK_RESET_PLLP_BASE]
457	bic	r0, r0, #(1 << 30)
458	str	r0, [r5, #CLK_RESET_PLLP_BASE]
459	ldr	r0, [r5, #CLK_RESET_PLLC_BASE]
460	bic	r0, r0, #(1 << 30)
461	str	r0, [r5, #CLK_RESET_PLLC_BASE]
462
463	/* switch to CLKS */
464	mov	r0, #0	/* brust policy = 32KHz */
465	str	r0, [r5, #CLK_RESET_SCLK_BURST]
466
467	ret	lr
468
469/*
470 * tegra20_enter_sleep
471 *
472 * uses flow controller to enter sleep state
473 * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1
474 * executes from SDRAM with target state is LP2
475 */
476tegra20_enter_sleep:
477	mov32   r6, TEGRA_FLOW_CTRL_BASE
478
479	mov     r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
480	orr	r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
481	cpu_id	r1
482	cpu_to_halt_reg r1, r1
483	str	r0, [r6, r1]
484	dsb
485	ldr	r0, [r6, r1] /* memory barrier */
486
487halted:
488	dsb
489	wfe	/* CPU should be power gated here */
490	isb
491	b	halted
492
493/*
494 * tegra20_sdram_self_refresh
495 *
496 * called with MMU off and caches disabled
497 * puts sdram in self refresh
498 * must be executed from IRAM
499 */
500tegra20_sdram_self_refresh:
501	mov32	r1, TEGRA_EMC_BASE	@ r1 reserved for emc base addr
502
503	mov	r2, #3
504	str	r2, [r1, #EMC_REQ_CTRL]	@ stall incoming DRAM requests
505
506emcidle:
507	ldr	r2, [r1, #EMC_EMC_STATUS]
508	tst	r2, #4
509	beq	emcidle
510
511	mov	r2, #1
512	str	r2, [r1, #EMC_SELF_REF]
513
514	emc_device_mask r2, r1
515
516emcself:
517	ldr	r3, [r1, #EMC_EMC_STATUS]
518	and	r3, r3, r2
519	cmp	r3, r2
520	bne	emcself			@ loop until DDR in self-refresh
521
522	adr	r2, tegra20_sdram_pad_address
523	adr	r3, tegra20_sdram_pad_safe
524	adr	r4, tegra20_sdram_pad_save
525	mov	r5, #0
526
527	ldr	r6, tegra20_sdram_pad_size
528padsave:
529	ldr	r0, [r2, r5]		@ r0 is the addr in the pad_address
530
531	ldr	r1, [r0]
532	str	r1, [r4, r5]		@ save the content of the addr
533
534	ldr	r1, [r3, r5]
535	str	r1, [r0]		@ set the save val to the addr
536
537	add	r5, r5, #4
538	cmp	r6, r5
539	bne	padsave
540padsave_done:
541
542	mov32	r5, TEGRA_CLK_RESET_BASE
543	ldr	r0, [r5, #CLK_RESET_SCLK_BURST]
544	adr	r2, tegra20_sclk_save
545	str	r0, [r2]
546	dsb
547	ret	lr
548
549tegra20_sdram_pad_address:
550	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL
551	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL
552	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2CLKCFGPADCTRL
553	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2COMPPADCTRL
554	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2VTTGENPADCTRL
555	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL2
556	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL2
557
558tegra20_sdram_pad_size:
559	.word	tegra20_sdram_pad_size - tegra20_sdram_pad_address
560
561tegra20_sdram_pad_safe:
562	.word	0x8
563	.word	0x8
564	.word	0x0
565	.word	0x8
566	.word	0x5500
567	.word	0x08080040
568	.word	0x0
569
570tegra20_sclk_save:
571	.word	0x0
572
573tegra20_sdram_pad_save:
574	.rept (tegra20_sdram_pad_size - tegra20_sdram_pad_address) / 4
575	.long	0
576	.endr
577
578	.ltorg
579/* dummy symbol for end of IRAM */
580	.align L1_CACHE_SHIFT
581	.globl tegra20_iram_end
582tegra20_iram_end:
583	b	.
584#endif
585