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