xref: /openbmc/linux/arch/arm/mach-tegra/sleep-tegra20.S (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
19952f691SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
2641b4ef8SJoseph Lo/*
3641b4ef8SJoseph Lo * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
4641b4ef8SJoseph Lo * Copyright (c) 2011, Google, Inc.
5641b4ef8SJoseph Lo *
6641b4ef8SJoseph Lo * Author: Colin Cross <ccross@android.com>
7641b4ef8SJoseph Lo *         Gary King <gking@nvidia.com>
8641b4ef8SJoseph Lo */
9641b4ef8SJoseph Lo
10641b4ef8SJoseph Lo#include <linux/linkage.h>
11641b4ef8SJoseph Lo
127e10cf74SJon Hunter#include <soc/tegra/flowctrl.h>
137e10cf74SJon Hunter
14641b4ef8SJoseph Lo#include <asm/assembler.h>
155c1350bdSJoseph Lo#include <asm/proc-fns.h>
165c1350bdSJoseph Lo#include <asm/cp15.h>
17731a9274SJoseph Lo#include <asm/cache.h>
18641b4ef8SJoseph Lo
19fddb770dSStephen Warren#include "irammap.h"
202af6597aSDmitry Osipenko#include "reset.h"
21641b4ef8SJoseph Lo#include "sleep.h"
22641b4ef8SJoseph Lo
23731a9274SJoseph Lo#define EMC_CFG				0xc
24731a9274SJoseph Lo#define EMC_ADR_CFG			0x10
25731a9274SJoseph Lo#define EMC_NOP				0xdc
26731a9274SJoseph Lo#define EMC_SELF_REF			0xe0
27731a9274SJoseph Lo#define EMC_REQ_CTRL			0x2b0
28731a9274SJoseph Lo#define EMC_EMC_STATUS			0x2b4
29731a9274SJoseph Lo
30731a9274SJoseph Lo#define CLK_RESET_CCLK_BURST		0x20
31731a9274SJoseph Lo#define CLK_RESET_CCLK_DIVIDER		0x24
32731a9274SJoseph Lo#define CLK_RESET_SCLK_BURST		0x28
33731a9274SJoseph Lo#define CLK_RESET_SCLK_DIVIDER		0x2c
34731a9274SJoseph Lo#define CLK_RESET_PLLC_BASE		0x80
35731a9274SJoseph Lo#define CLK_RESET_PLLM_BASE		0x90
36731a9274SJoseph Lo#define CLK_RESET_PLLP_BASE		0xa0
37731a9274SJoseph Lo
38731a9274SJoseph Lo#define APB_MISC_XM2CFGCPADCTRL		0x8c8
39731a9274SJoseph Lo#define APB_MISC_XM2CFGDPADCTRL		0x8cc
40731a9274SJoseph Lo#define APB_MISC_XM2CLKCFGPADCTRL	0x8d0
41731a9274SJoseph Lo#define APB_MISC_XM2COMPPADCTRL		0x8d4
42731a9274SJoseph Lo#define APB_MISC_XM2VTTGENPADCTRL	0x8d8
43731a9274SJoseph Lo#define APB_MISC_XM2CFGCPADCTRL2	0x8e4
44731a9274SJoseph Lo#define APB_MISC_XM2CFGDPADCTRL2	0x8e8
45731a9274SJoseph Lo
46680ae445SDmitry Osipenko#define PLLC_STORE_MASK			(1 << 0)
47680ae445SDmitry Osipenko#define PLLM_STORE_MASK			(1 << 1)
48680ae445SDmitry Osipenko#define PLLP_STORE_MASK			(1 << 2)
49680ae445SDmitry Osipenko
50*a2faac39SNick Desaulniers.arch armv7-a
51*a2faac39SNick Desaulniers
52680ae445SDmitry Osipenko.macro test_pll_state, rd, test_mask
53680ae445SDmitry Osipenko	ldr	\rd, tegra_pll_state
54680ae445SDmitry Osipenko	tst	\rd, #\test_mask
55680ae445SDmitry Osipenko.endm
56680ae445SDmitry Osipenko
57680ae445SDmitry Osipenko.macro store_pll_state, rd, tmp, r_car_base, pll_base, pll_mask
58680ae445SDmitry Osipenko	ldr	\rd, [\r_car_base, #\pll_base]
59680ae445SDmitry Osipenko	tst	\rd, #(1 << 30)
60680ae445SDmitry Osipenko	ldr	\rd, tegra_pll_state
61680ae445SDmitry Osipenko	biceq	\rd, \rd, #\pll_mask
62680ae445SDmitry Osipenko	orrne	\rd, \rd, #\pll_mask
63680ae445SDmitry Osipenko	adr	\tmp, tegra_pll_state
64680ae445SDmitry Osipenko	str	\rd, [\tmp]
65680ae445SDmitry Osipenko.endm
66680ae445SDmitry Osipenko
67680ae445SDmitry Osipenko.macro pll_enable, rd, r_car_base, pll_base, test_mask
68680ae445SDmitry Osipenko	test_pll_state \rd, \test_mask
69680ae445SDmitry Osipenko	beq	1f
70680ae445SDmitry Osipenko
71731a9274SJoseph Lo	ldr	\rd, [\r_car_base, #\pll_base]
72731a9274SJoseph Lo	tst	\rd, #(1 << 30)
73731a9274SJoseph Lo	orreq	\rd, \rd, #(1 << 30)
74731a9274SJoseph Lo	streq	\rd, [\r_car_base, #\pll_base]
75680ae445SDmitry Osipenko1:
76731a9274SJoseph Lo.endm
77731a9274SJoseph Lo
78731a9274SJoseph Lo.macro emc_device_mask, rd, base
79731a9274SJoseph Lo	ldr	\rd, [\base, #EMC_ADR_CFG]
80731a9274SJoseph Lo	tst	\rd, #(0x3 << 24)
81731a9274SJoseph Lo	moveq	\rd, #(0x1 << 8)		@ just 1 device
82731a9274SJoseph Lo	movne	\rd, #(0x3 << 8)		@ 2 devices
83731a9274SJoseph Lo.endm
84731a9274SJoseph Lo
85641b4ef8SJoseph Lo#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
86641b4ef8SJoseph Lo/*
87641b4ef8SJoseph Lo * tegra20_hotplug_shutdown(void)
88641b4ef8SJoseph Lo *
89641b4ef8SJoseph Lo * puts the current cpu in reset
90641b4ef8SJoseph Lo * should never return
91641b4ef8SJoseph Lo */
92641b4ef8SJoseph LoENTRY(tegra20_hotplug_shutdown)
93641b4ef8SJoseph Lo	/* Put this CPU down */
94641b4ef8SJoseph Lo	cpu_id	r0
95641b4ef8SJoseph Lo	bl	tegra20_cpu_shutdown
966ebbf2ceSRussell King	ret	lr			@ should never get here
97641b4ef8SJoseph LoENDPROC(tegra20_hotplug_shutdown)
98641b4ef8SJoseph Lo
99641b4ef8SJoseph Lo/*
100641b4ef8SJoseph Lo * tegra20_cpu_shutdown(int cpu)
101641b4ef8SJoseph Lo *
102641b4ef8SJoseph Lo * r0 is cpu to reset
103641b4ef8SJoseph Lo *
104641b4ef8SJoseph Lo * puts the specified CPU in wait-for-event mode on the flow controller
105641b4ef8SJoseph Lo * and puts the CPU in reset
106641b4ef8SJoseph Lo * can be called on the current cpu or another cpu
107641b4ef8SJoseph Lo * if called on the current cpu, does not return
108641b4ef8SJoseph Lo * MUST NOT BE CALLED FOR CPU 0.
109641b4ef8SJoseph Lo *
110641b4ef8SJoseph Lo * corrupts r0-r3, r12
111641b4ef8SJoseph Lo */
112641b4ef8SJoseph LoENTRY(tegra20_cpu_shutdown)
113641b4ef8SJoseph Lo	cmp	r0, #0
1146ebbf2ceSRussell King	reteq	lr			@ must not be called for CPU 0
115641b4ef8SJoseph Lo
116641b4ef8SJoseph Lo	cpu_to_halt_reg r1, r0
117641b4ef8SJoseph Lo	ldr	r3, =TEGRA_FLOW_CTRL_VIRT
118641b4ef8SJoseph Lo	mov	r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
119641b4ef8SJoseph Lo	str	r2, [r3, r1]		@ put flow controller in wait event mode
120641b4ef8SJoseph Lo	ldr	r2, [r3, r1]
121641b4ef8SJoseph Lo	isb
122641b4ef8SJoseph Lo	dsb
123641b4ef8SJoseph Lo	movw	r1, 0x1011
124641b4ef8SJoseph Lo	mov	r1, r1, lsl r0
125641b4ef8SJoseph Lo	ldr	r3, =TEGRA_CLK_RESET_VIRT
126641b4ef8SJoseph Lo	str	r1, [r3, #0x340]	@ put slave CPU in reset
127641b4ef8SJoseph Lo	isb
128641b4ef8SJoseph Lo	dsb
129641b4ef8SJoseph Lo	cpu_id	r3
130641b4ef8SJoseph Lo	cmp	r3, r0
131641b4ef8SJoseph Lo	beq	.
1326ebbf2ceSRussell King	ret	lr
133641b4ef8SJoseph LoENDPROC(tegra20_cpu_shutdown)
134641b4ef8SJoseph Lo#endif
1355c1350bdSJoseph Lo
1365c1350bdSJoseph Lo#ifdef CONFIG_PM_SLEEP
1375c1350bdSJoseph Lo/*
138731a9274SJoseph Lo * tegra20_sleep_core_finish(unsigned long v2p)
139731a9274SJoseph Lo *
140731a9274SJoseph Lo * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to
141731a9274SJoseph Lo * tegra20_tear_down_core in IRAM
142731a9274SJoseph Lo */
143731a9274SJoseph LoENTRY(tegra20_sleep_core_finish)
1445883ac20SJon Hunter	mov     r4, r0
145731a9274SJoseph Lo	/* Flush, disable the L1 data cache and exit SMP */
1465883ac20SJon Hunter	mov     r0, #TEGRA_FLUSH_CACHE_ALL
147731a9274SJoseph Lo	bl	tegra_disable_clean_inv_dcache
1485883ac20SJon Hunter	mov     r0, r4
149731a9274SJoseph Lo
150731a9274SJoseph Lo	mov32	r3, tegra_shut_off_mmu
151731a9274SJoseph Lo	add	r3, r3, r0
152731a9274SJoseph Lo
153731a9274SJoseph Lo	mov32	r0, tegra20_tear_down_core
154731a9274SJoseph Lo	mov32	r1, tegra20_iram_start
155731a9274SJoseph Lo	sub	r0, r0, r1
156fddb770dSStephen Warren	mov32	r1, TEGRA_IRAM_LPx_RESUME_AREA
157731a9274SJoseph Lo	add	r0, r0, r1
158731a9274SJoseph Lo
1596ebbf2ceSRussell King	ret	r3
160731a9274SJoseph LoENDPROC(tegra20_sleep_core_finish)
161731a9274SJoseph Lo
162731a9274SJoseph Lo/*
1631d328606SJoseph Lo * tegra20_tear_down_cpu
1641d328606SJoseph Lo *
1651d328606SJoseph Lo * Switches the CPU cluster to PLL-P and enters sleep.
1661d328606SJoseph Lo */
1671d328606SJoseph LoENTRY(tegra20_tear_down_cpu)
1681d328606SJoseph Lo	bl	tegra_switch_cpu_to_pllp
1691d328606SJoseph Lo	b	tegra20_enter_sleep
1701d328606SJoseph LoENDPROC(tegra20_tear_down_cpu)
1711d328606SJoseph Lo
172731a9274SJoseph Lo/* START OF ROUTINES COPIED TO IRAM */
173731a9274SJoseph Lo	.align L1_CACHE_SHIFT
174731a9274SJoseph Lo	.globl tegra20_iram_start
175731a9274SJoseph Lotegra20_iram_start:
176731a9274SJoseph Lo
177731a9274SJoseph Lo/*
178731a9274SJoseph Lo * tegra20_lp1_reset
179731a9274SJoseph Lo *
180731a9274SJoseph Lo * reset vector for LP1 restore; copied into IRAM during suspend.
181731a9274SJoseph Lo * Brings the system back up to a safe staring point (SDRAM out of
182731a9274SJoseph Lo * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP,
183731a9274SJoseph Lo * system clock running on the same PLL that it suspended at), and
184731a9274SJoseph Lo * jumps to tegra_resume to restore virtual addressing and PLLX.
185731a9274SJoseph Lo * The physical address of tegra_resume expected to be stored in
186731a9274SJoseph Lo * PMC_SCRATCH41.
187731a9274SJoseph Lo *
188fddb770dSStephen Warren * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
189731a9274SJoseph Lo */
190731a9274SJoseph LoENTRY(tegra20_lp1_reset)
191731a9274SJoseph Lo	/*
192731a9274SJoseph Lo	 * The CPU and system bus are running at 32KHz and executing from
193731a9274SJoseph Lo	 * IRAM when this code is executed; immediately switch to CLKM and
194731a9274SJoseph Lo	 * enable PLLM, PLLP, PLLC.
195731a9274SJoseph Lo	 */
196731a9274SJoseph Lo	mov32	r0, TEGRA_CLK_RESET_BASE
197731a9274SJoseph Lo
198731a9274SJoseph Lo	mov	r1, #(1 << 28)
199731a9274SJoseph Lo	str	r1, [r0, #CLK_RESET_SCLK_BURST]
200731a9274SJoseph Lo	str	r1, [r0, #CLK_RESET_CCLK_BURST]
201731a9274SJoseph Lo	mov	r1, #0
202731a9274SJoseph Lo	str	r1, [r0, #CLK_RESET_CCLK_DIVIDER]
203731a9274SJoseph Lo	str	r1, [r0, #CLK_RESET_SCLK_DIVIDER]
204731a9274SJoseph Lo
205680ae445SDmitry Osipenko	pll_enable r1, r0, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK
206680ae445SDmitry Osipenko	pll_enable r1, r0, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK
207680ae445SDmitry Osipenko	pll_enable r1, r0, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK
208731a9274SJoseph Lo
209731a9274SJoseph Lo	adr	r2, tegra20_sdram_pad_address
210731a9274SJoseph Lo	adr	r4, tegra20_sdram_pad_save
211731a9274SJoseph Lo	mov	r5, #0
212731a9274SJoseph Lo
213731a9274SJoseph Lo	ldr	r6, tegra20_sdram_pad_size
214731a9274SJoseph Lopadload:
215731a9274SJoseph Lo	ldr	r7, [r2, r5]		@ r7 is the addr in the pad_address
216731a9274SJoseph Lo
217731a9274SJoseph Lo	ldr	r1, [r4, r5]
218731a9274SJoseph Lo	str	r1, [r7]		@ restore the value in pad_save
219731a9274SJoseph Lo
220731a9274SJoseph Lo	add	r5, r5, #4
221731a9274SJoseph Lo	cmp	r6, r5
222731a9274SJoseph Lo	bne	padload
223731a9274SJoseph Lo
224731a9274SJoseph Lopadload_done:
225731a9274SJoseph Lo	/* 255uS delay for PLL stabilization */
226731a9274SJoseph Lo	mov32	r7, TEGRA_TMRUS_BASE
227731a9274SJoseph Lo	ldr	r1, [r7]
228731a9274SJoseph Lo	add	r1, r1, #0xff
229731a9274SJoseph Lo	wait_until r1, r7, r9
230731a9274SJoseph Lo
231731a9274SJoseph Lo	adr	r4, tegra20_sclk_save
232731a9274SJoseph Lo	ldr	r4, [r4]
233731a9274SJoseph Lo	str	r4, [r0, #CLK_RESET_SCLK_BURST]
234731a9274SJoseph Lo	mov32	r4, ((1 << 28) | (4))	@ burst policy is PLLP
235731a9274SJoseph Lo	str	r4, [r0, #CLK_RESET_CCLK_BURST]
236731a9274SJoseph Lo
237731a9274SJoseph Lo	mov32	r0, TEGRA_EMC_BASE
238731a9274SJoseph Lo	ldr	r1, [r0, #EMC_CFG]
239731a9274SJoseph Lo	bic	r1, r1, #(1 << 31)	@ disable DRAM_CLK_STOP
240731a9274SJoseph Lo	str	r1, [r0, #EMC_CFG]
241731a9274SJoseph Lo
242731a9274SJoseph Lo	mov	r1, #0
243731a9274SJoseph Lo	str	r1, [r0, #EMC_SELF_REF]	@ take DRAM out of self refresh
244731a9274SJoseph Lo	mov	r1, #1
245731a9274SJoseph Lo	str	r1, [r0, #EMC_NOP]
246731a9274SJoseph Lo	str	r1, [r0, #EMC_NOP]
247731a9274SJoseph Lo
248731a9274SJoseph Lo	emc_device_mask r1, r0
249731a9274SJoseph Lo
250731a9274SJoseph Loexit_selfrefresh_loop:
251731a9274SJoseph Lo	ldr	r2, [r0, #EMC_EMC_STATUS]
252731a9274SJoseph Lo	ands	r2, r2, r1
253731a9274SJoseph Lo	bne	exit_selfrefresh_loop
254731a9274SJoseph Lo
255731a9274SJoseph Lo	mov	r1, #0			@ unstall all transactions
256731a9274SJoseph Lo	str	r1, [r0, #EMC_REQ_CTRL]
257731a9274SJoseph Lo
258731a9274SJoseph Lo	mov32	r0, TEGRA_PMC_BASE
259731a9274SJoseph Lo	ldr	r0, [r0, #PMC_SCRATCH41]
2606ebbf2ceSRussell King	ret	r0			@ jump to tegra_resume
261731a9274SJoseph LoENDPROC(tegra20_lp1_reset)
262731a9274SJoseph Lo
263731a9274SJoseph Lo/*
264731a9274SJoseph Lo * tegra20_tear_down_core
265731a9274SJoseph Lo *
266731a9274SJoseph Lo * copied into and executed from IRAM
267731a9274SJoseph Lo * puts memory in self-refresh for LP0 and LP1
268731a9274SJoseph Lo */
269731a9274SJoseph Lotegra20_tear_down_core:
270731a9274SJoseph Lo	bl	tegra20_sdram_self_refresh
271731a9274SJoseph Lo	bl	tegra20_switch_cpu_to_clk32k
272731a9274SJoseph Lo	b	tegra20_enter_sleep
273731a9274SJoseph Lo
274731a9274SJoseph Lo/*
275731a9274SJoseph Lo * tegra20_switch_cpu_to_clk32k
276731a9274SJoseph Lo *
277731a9274SJoseph Lo * In LP0 and LP1 all PLLs will be turned off. Switch the CPU and system clock
278731a9274SJoseph Lo * to the 32KHz clock.
279731a9274SJoseph Lo */
280731a9274SJoseph Lotegra20_switch_cpu_to_clk32k:
281731a9274SJoseph Lo	/*
282731a9274SJoseph Lo	 * start by switching to CLKM to safely disable PLLs, then switch to
283731a9274SJoseph Lo	 * CLKS.
284731a9274SJoseph Lo	 */
285731a9274SJoseph Lo	mov	r0, #(1 << 28)
286731a9274SJoseph Lo	str	r0, [r5, #CLK_RESET_SCLK_BURST]
287731a9274SJoseph Lo	str	r0, [r5, #CLK_RESET_CCLK_BURST]
288731a9274SJoseph Lo	mov	r0, #0
289731a9274SJoseph Lo	str	r0, [r5, #CLK_RESET_CCLK_DIVIDER]
290731a9274SJoseph Lo	str	r0, [r5, #CLK_RESET_SCLK_DIVIDER]
291731a9274SJoseph Lo
292731a9274SJoseph Lo	/* 2uS delay delay between changing SCLK and disabling PLLs */
293731a9274SJoseph Lo	mov32	r7, TEGRA_TMRUS_BASE
294731a9274SJoseph Lo	ldr	r1, [r7]
295731a9274SJoseph Lo	add	r1, r1, #2
296731a9274SJoseph Lo	wait_until r1, r7, r9
297731a9274SJoseph Lo
298680ae445SDmitry Osipenko	store_pll_state r0, r1, r5, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK
299680ae445SDmitry Osipenko	store_pll_state r0, r1, r5, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK
300680ae445SDmitry Osipenko	store_pll_state r0, r1, r5, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK
301680ae445SDmitry Osipenko
302731a9274SJoseph Lo	/* disable PLLM, PLLP and PLLC */
303731a9274SJoseph Lo	ldr	r0, [r5, #CLK_RESET_PLLM_BASE]
304731a9274SJoseph Lo	bic	r0, r0, #(1 << 30)
305731a9274SJoseph Lo	str	r0, [r5, #CLK_RESET_PLLM_BASE]
306731a9274SJoseph Lo	ldr	r0, [r5, #CLK_RESET_PLLP_BASE]
307731a9274SJoseph Lo	bic	r0, r0, #(1 << 30)
308731a9274SJoseph Lo	str	r0, [r5, #CLK_RESET_PLLP_BASE]
309731a9274SJoseph Lo	ldr	r0, [r5, #CLK_RESET_PLLC_BASE]
310731a9274SJoseph Lo	bic	r0, r0, #(1 << 30)
311731a9274SJoseph Lo	str	r0, [r5, #CLK_RESET_PLLC_BASE]
312731a9274SJoseph Lo
313731a9274SJoseph Lo	/* switch to CLKS */
314731a9274SJoseph Lo	mov	r0, #0	/* brust policy = 32KHz */
315731a9274SJoseph Lo	str	r0, [r5, #CLK_RESET_SCLK_BURST]
316731a9274SJoseph Lo
3176ebbf2ceSRussell King	ret	lr
318731a9274SJoseph Lo
3191d328606SJoseph Lo/*
3201d328606SJoseph Lo * tegra20_enter_sleep
3211d328606SJoseph Lo *
3221d328606SJoseph Lo * uses flow controller to enter sleep state
3231d328606SJoseph Lo * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1
3241d328606SJoseph Lo * executes from SDRAM with target state is LP2
3251d328606SJoseph Lo */
3261d328606SJoseph Lotegra20_enter_sleep:
3271d328606SJoseph Lo	mov32   r6, TEGRA_FLOW_CTRL_BASE
3281d328606SJoseph Lo
3291d328606SJoseph Lo	mov     r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
3301d328606SJoseph Lo	orr	r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
3311d328606SJoseph Lo	cpu_id	r1
3321d328606SJoseph Lo	cpu_to_halt_reg r1, r1
3331d328606SJoseph Lo	str	r0, [r6, r1]
3341d328606SJoseph Lo	dsb
3351d328606SJoseph Lo	ldr	r0, [r6, r1] /* memory barrier */
3361d328606SJoseph Lo
3371d328606SJoseph Lohalted:
3381d328606SJoseph Lo	dsb
3391d328606SJoseph Lo	wfe	/* CPU should be power gated here */
3401d328606SJoseph Lo	isb
3411d328606SJoseph Lo	b	halted
3421d328606SJoseph Lo
343731a9274SJoseph Lo/*
344731a9274SJoseph Lo * tegra20_sdram_self_refresh
345731a9274SJoseph Lo *
346731a9274SJoseph Lo * called with MMU off and caches disabled
347731a9274SJoseph Lo * puts sdram in self refresh
348731a9274SJoseph Lo * must be executed from IRAM
349731a9274SJoseph Lo */
350731a9274SJoseph Lotegra20_sdram_self_refresh:
351731a9274SJoseph Lo	mov32	r1, TEGRA_EMC_BASE	@ r1 reserved for emc base addr
352731a9274SJoseph Lo
353731a9274SJoseph Lo	mov	r2, #3
354731a9274SJoseph Lo	str	r2, [r1, #EMC_REQ_CTRL]	@ stall incoming DRAM requests
355731a9274SJoseph Lo
356731a9274SJoseph Loemcidle:
357731a9274SJoseph Lo	ldr	r2, [r1, #EMC_EMC_STATUS]
358731a9274SJoseph Lo	tst	r2, #4
359731a9274SJoseph Lo	beq	emcidle
360731a9274SJoseph Lo
361731a9274SJoseph Lo	mov	r2, #1
362731a9274SJoseph Lo	str	r2, [r1, #EMC_SELF_REF]
363731a9274SJoseph Lo
364731a9274SJoseph Lo	emc_device_mask r2, r1
365731a9274SJoseph Lo
366731a9274SJoseph Loemcself:
367731a9274SJoseph Lo	ldr	r3, [r1, #EMC_EMC_STATUS]
368731a9274SJoseph Lo	and	r3, r3, r2
369731a9274SJoseph Lo	cmp	r3, r2
370731a9274SJoseph Lo	bne	emcself			@ loop until DDR in self-refresh
371731a9274SJoseph Lo
372731a9274SJoseph Lo	adr	r2, tegra20_sdram_pad_address
373731a9274SJoseph Lo	adr	r3, tegra20_sdram_pad_safe
374731a9274SJoseph Lo	adr	r4, tegra20_sdram_pad_save
375731a9274SJoseph Lo	mov	r5, #0
376731a9274SJoseph Lo
377731a9274SJoseph Lo	ldr	r6, tegra20_sdram_pad_size
378731a9274SJoseph Lopadsave:
379731a9274SJoseph Lo	ldr	r0, [r2, r5]		@ r0 is the addr in the pad_address
380731a9274SJoseph Lo
381731a9274SJoseph Lo	ldr	r1, [r0]
382731a9274SJoseph Lo	str	r1, [r4, r5]		@ save the content of the addr
383731a9274SJoseph Lo
384731a9274SJoseph Lo	ldr	r1, [r3, r5]
385731a9274SJoseph Lo	str	r1, [r0]		@ set the save val to the addr
386731a9274SJoseph Lo
387731a9274SJoseph Lo	add	r5, r5, #4
388731a9274SJoseph Lo	cmp	r6, r5
389731a9274SJoseph Lo	bne	padsave
390731a9274SJoseph Lopadsave_done:
391731a9274SJoseph Lo
392731a9274SJoseph Lo	mov32	r5, TEGRA_CLK_RESET_BASE
393731a9274SJoseph Lo	ldr	r0, [r5, #CLK_RESET_SCLK_BURST]
394731a9274SJoseph Lo	adr	r2, tegra20_sclk_save
395731a9274SJoseph Lo	str	r0, [r2]
396731a9274SJoseph Lo	dsb
3976ebbf2ceSRussell King	ret	lr
398731a9274SJoseph Lo
399731a9274SJoseph Lotegra20_sdram_pad_address:
400731a9274SJoseph Lo	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL
401731a9274SJoseph Lo	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL
402731a9274SJoseph Lo	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2CLKCFGPADCTRL
403731a9274SJoseph Lo	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2COMPPADCTRL
404731a9274SJoseph Lo	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2VTTGENPADCTRL
405731a9274SJoseph Lo	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL2
406731a9274SJoseph Lo	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL2
407731a9274SJoseph Lo
408731a9274SJoseph Lotegra20_sdram_pad_size:
409731a9274SJoseph Lo	.word	tegra20_sdram_pad_size - tegra20_sdram_pad_address
410731a9274SJoseph Lo
411731a9274SJoseph Lotegra20_sdram_pad_safe:
412731a9274SJoseph Lo	.word	0x8
413731a9274SJoseph Lo	.word	0x8
414731a9274SJoseph Lo	.word	0x0
415731a9274SJoseph Lo	.word	0x8
416731a9274SJoseph Lo	.word	0x5500
417731a9274SJoseph Lo	.word	0x08080040
418731a9274SJoseph Lo	.word	0x0
419731a9274SJoseph Lo
420731a9274SJoseph Lotegra20_sclk_save:
421731a9274SJoseph Lo	.word	0x0
422731a9274SJoseph Lo
423731a9274SJoseph Lotegra20_sdram_pad_save:
424731a9274SJoseph Lo	.rept (tegra20_sdram_pad_size - tegra20_sdram_pad_address) / 4
425731a9274SJoseph Lo	.long	0
426731a9274SJoseph Lo	.endr
427731a9274SJoseph Lo
428680ae445SDmitry Osipenkotegra_pll_state:
429680ae445SDmitry Osipenko	.word	0x0
430680ae445SDmitry Osipenko
431731a9274SJoseph Lo	.ltorg
432731a9274SJoseph Lo/* dummy symbol for end of IRAM */
433731a9274SJoseph Lo	.align L1_CACHE_SHIFT
434731a9274SJoseph Lo	.globl tegra20_iram_end
435731a9274SJoseph Lotegra20_iram_end:
436731a9274SJoseph Lo	b	.
4375c1350bdSJoseph Lo#endif
438