xref: /OK3568_Linux_fs/kernel/arch/arm/mach-tegra/sleep-tegra20.S (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0-only */
2*4882a593Smuzhiyun/*
3*4882a593Smuzhiyun * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
4*4882a593Smuzhiyun * Copyright (c) 2011, Google, Inc.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Author: Colin Cross <ccross@android.com>
7*4882a593Smuzhiyun *         Gary King <gking@nvidia.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun#include <linux/linkage.h>
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun#include <soc/tegra/flowctrl.h>
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun#include <asm/assembler.h>
15*4882a593Smuzhiyun#include <asm/proc-fns.h>
16*4882a593Smuzhiyun#include <asm/cp15.h>
17*4882a593Smuzhiyun#include <asm/cache.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun#include "irammap.h"
20*4882a593Smuzhiyun#include "reset.h"
21*4882a593Smuzhiyun#include "sleep.h"
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun#define EMC_CFG				0xc
24*4882a593Smuzhiyun#define EMC_ADR_CFG			0x10
25*4882a593Smuzhiyun#define EMC_NOP				0xdc
26*4882a593Smuzhiyun#define EMC_SELF_REF			0xe0
27*4882a593Smuzhiyun#define EMC_REQ_CTRL			0x2b0
28*4882a593Smuzhiyun#define EMC_EMC_STATUS			0x2b4
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun#define CLK_RESET_CCLK_BURST		0x20
31*4882a593Smuzhiyun#define CLK_RESET_CCLK_DIVIDER		0x24
32*4882a593Smuzhiyun#define CLK_RESET_SCLK_BURST		0x28
33*4882a593Smuzhiyun#define CLK_RESET_SCLK_DIVIDER		0x2c
34*4882a593Smuzhiyun#define CLK_RESET_PLLC_BASE		0x80
35*4882a593Smuzhiyun#define CLK_RESET_PLLM_BASE		0x90
36*4882a593Smuzhiyun#define CLK_RESET_PLLP_BASE		0xa0
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun#define APB_MISC_XM2CFGCPADCTRL		0x8c8
39*4882a593Smuzhiyun#define APB_MISC_XM2CFGDPADCTRL		0x8cc
40*4882a593Smuzhiyun#define APB_MISC_XM2CLKCFGPADCTRL	0x8d0
41*4882a593Smuzhiyun#define APB_MISC_XM2COMPPADCTRL		0x8d4
42*4882a593Smuzhiyun#define APB_MISC_XM2VTTGENPADCTRL	0x8d8
43*4882a593Smuzhiyun#define APB_MISC_XM2CFGCPADCTRL2	0x8e4
44*4882a593Smuzhiyun#define APB_MISC_XM2CFGDPADCTRL2	0x8e8
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun.macro pll_enable, rd, r_car_base, pll_base
47*4882a593Smuzhiyun	ldr	\rd, [\r_car_base, #\pll_base]
48*4882a593Smuzhiyun	tst	\rd, #(1 << 30)
49*4882a593Smuzhiyun	orreq	\rd, \rd, #(1 << 30)
50*4882a593Smuzhiyun	streq	\rd, [\r_car_base, #\pll_base]
51*4882a593Smuzhiyun.endm
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun.macro emc_device_mask, rd, base
54*4882a593Smuzhiyun	ldr	\rd, [\base, #EMC_ADR_CFG]
55*4882a593Smuzhiyun	tst	\rd, #(0x3 << 24)
56*4882a593Smuzhiyun	moveq	\rd, #(0x1 << 8)		@ just 1 device
57*4882a593Smuzhiyun	movne	\rd, #(0x3 << 8)		@ 2 devices
58*4882a593Smuzhiyun.endm
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
61*4882a593Smuzhiyun/*
62*4882a593Smuzhiyun * tegra20_hotplug_shutdown(void)
63*4882a593Smuzhiyun *
64*4882a593Smuzhiyun * puts the current cpu in reset
65*4882a593Smuzhiyun * should never return
66*4882a593Smuzhiyun */
67*4882a593SmuzhiyunENTRY(tegra20_hotplug_shutdown)
68*4882a593Smuzhiyun	/* Put this CPU down */
69*4882a593Smuzhiyun	cpu_id	r0
70*4882a593Smuzhiyun	bl	tegra20_cpu_shutdown
71*4882a593Smuzhiyun	ret	lr			@ should never get here
72*4882a593SmuzhiyunENDPROC(tegra20_hotplug_shutdown)
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun/*
75*4882a593Smuzhiyun * tegra20_cpu_shutdown(int cpu)
76*4882a593Smuzhiyun *
77*4882a593Smuzhiyun * r0 is cpu to reset
78*4882a593Smuzhiyun *
79*4882a593Smuzhiyun * puts the specified CPU in wait-for-event mode on the flow controller
80*4882a593Smuzhiyun * and puts the CPU in reset
81*4882a593Smuzhiyun * can be called on the current cpu or another cpu
82*4882a593Smuzhiyun * if called on the current cpu, does not return
83*4882a593Smuzhiyun * MUST NOT BE CALLED FOR CPU 0.
84*4882a593Smuzhiyun *
85*4882a593Smuzhiyun * corrupts r0-r3, r12
86*4882a593Smuzhiyun */
87*4882a593SmuzhiyunENTRY(tegra20_cpu_shutdown)
88*4882a593Smuzhiyun	cmp	r0, #0
89*4882a593Smuzhiyun	reteq	lr			@ must not be called for CPU 0
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun	cpu_to_halt_reg r1, r0
92*4882a593Smuzhiyun	ldr	r3, =TEGRA_FLOW_CTRL_VIRT
93*4882a593Smuzhiyun	mov	r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
94*4882a593Smuzhiyun	str	r2, [r3, r1]		@ put flow controller in wait event mode
95*4882a593Smuzhiyun	ldr	r2, [r3, r1]
96*4882a593Smuzhiyun	isb
97*4882a593Smuzhiyun	dsb
98*4882a593Smuzhiyun	movw	r1, 0x1011
99*4882a593Smuzhiyun	mov	r1, r1, lsl r0
100*4882a593Smuzhiyun	ldr	r3, =TEGRA_CLK_RESET_VIRT
101*4882a593Smuzhiyun	str	r1, [r3, #0x340]	@ put slave CPU in reset
102*4882a593Smuzhiyun	isb
103*4882a593Smuzhiyun	dsb
104*4882a593Smuzhiyun	cpu_id	r3
105*4882a593Smuzhiyun	cmp	r3, r0
106*4882a593Smuzhiyun	beq	.
107*4882a593Smuzhiyun	ret	lr
108*4882a593SmuzhiyunENDPROC(tegra20_cpu_shutdown)
109*4882a593Smuzhiyun#endif
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun#ifdef CONFIG_PM_SLEEP
112*4882a593Smuzhiyun/*
113*4882a593Smuzhiyun * tegra20_sleep_core_finish(unsigned long v2p)
114*4882a593Smuzhiyun *
115*4882a593Smuzhiyun * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to
116*4882a593Smuzhiyun * tegra20_tear_down_core in IRAM
117*4882a593Smuzhiyun */
118*4882a593SmuzhiyunENTRY(tegra20_sleep_core_finish)
119*4882a593Smuzhiyun	mov     r4, r0
120*4882a593Smuzhiyun	/* Flush, disable the L1 data cache and exit SMP */
121*4882a593Smuzhiyun	mov     r0, #TEGRA_FLUSH_CACHE_ALL
122*4882a593Smuzhiyun	bl	tegra_disable_clean_inv_dcache
123*4882a593Smuzhiyun	mov     r0, r4
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun	mov32	r3, tegra_shut_off_mmu
126*4882a593Smuzhiyun	add	r3, r3, r0
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun	mov32	r0, tegra20_tear_down_core
129*4882a593Smuzhiyun	mov32	r1, tegra20_iram_start
130*4882a593Smuzhiyun	sub	r0, r0, r1
131*4882a593Smuzhiyun	mov32	r1, TEGRA_IRAM_LPx_RESUME_AREA
132*4882a593Smuzhiyun	add	r0, r0, r1
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun	ret	r3
135*4882a593SmuzhiyunENDPROC(tegra20_sleep_core_finish)
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun/*
138*4882a593Smuzhiyun * tegra20_tear_down_cpu
139*4882a593Smuzhiyun *
140*4882a593Smuzhiyun * Switches the CPU cluster to PLL-P and enters sleep.
141*4882a593Smuzhiyun */
142*4882a593SmuzhiyunENTRY(tegra20_tear_down_cpu)
143*4882a593Smuzhiyun	bl	tegra_switch_cpu_to_pllp
144*4882a593Smuzhiyun	b	tegra20_enter_sleep
145*4882a593SmuzhiyunENDPROC(tegra20_tear_down_cpu)
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun/* START OF ROUTINES COPIED TO IRAM */
148*4882a593Smuzhiyun	.align L1_CACHE_SHIFT
149*4882a593Smuzhiyun	.globl tegra20_iram_start
150*4882a593Smuzhiyuntegra20_iram_start:
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun/*
153*4882a593Smuzhiyun * tegra20_lp1_reset
154*4882a593Smuzhiyun *
155*4882a593Smuzhiyun * reset vector for LP1 restore; copied into IRAM during suspend.
156*4882a593Smuzhiyun * Brings the system back up to a safe staring point (SDRAM out of
157*4882a593Smuzhiyun * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP,
158*4882a593Smuzhiyun * system clock running on the same PLL that it suspended at), and
159*4882a593Smuzhiyun * jumps to tegra_resume to restore virtual addressing and PLLX.
160*4882a593Smuzhiyun * The physical address of tegra_resume expected to be stored in
161*4882a593Smuzhiyun * PMC_SCRATCH41.
162*4882a593Smuzhiyun *
163*4882a593Smuzhiyun * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
164*4882a593Smuzhiyun */
165*4882a593SmuzhiyunENTRY(tegra20_lp1_reset)
166*4882a593Smuzhiyun	/*
167*4882a593Smuzhiyun	 * The CPU and system bus are running at 32KHz and executing from
168*4882a593Smuzhiyun	 * IRAM when this code is executed; immediately switch to CLKM and
169*4882a593Smuzhiyun	 * enable PLLM, PLLP, PLLC.
170*4882a593Smuzhiyun	 */
171*4882a593Smuzhiyun	mov32	r0, TEGRA_CLK_RESET_BASE
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun	mov	r1, #(1 << 28)
174*4882a593Smuzhiyun	str	r1, [r0, #CLK_RESET_SCLK_BURST]
175*4882a593Smuzhiyun	str	r1, [r0, #CLK_RESET_CCLK_BURST]
176*4882a593Smuzhiyun	mov	r1, #0
177*4882a593Smuzhiyun	str	r1, [r0, #CLK_RESET_CCLK_DIVIDER]
178*4882a593Smuzhiyun	str	r1, [r0, #CLK_RESET_SCLK_DIVIDER]
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun	pll_enable r1, r0, CLK_RESET_PLLM_BASE
181*4882a593Smuzhiyun	pll_enable r1, r0, CLK_RESET_PLLP_BASE
182*4882a593Smuzhiyun	pll_enable r1, r0, CLK_RESET_PLLC_BASE
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun	adr	r2, tegra20_sdram_pad_address
185*4882a593Smuzhiyun	adr	r4, tegra20_sdram_pad_save
186*4882a593Smuzhiyun	mov	r5, #0
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun	ldr	r6, tegra20_sdram_pad_size
189*4882a593Smuzhiyunpadload:
190*4882a593Smuzhiyun	ldr	r7, [r2, r5]		@ r7 is the addr in the pad_address
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun	ldr	r1, [r4, r5]
193*4882a593Smuzhiyun	str	r1, [r7]		@ restore the value in pad_save
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun	add	r5, r5, #4
196*4882a593Smuzhiyun	cmp	r6, r5
197*4882a593Smuzhiyun	bne	padload
198*4882a593Smuzhiyun
199*4882a593Smuzhiyunpadload_done:
200*4882a593Smuzhiyun	/* 255uS delay for PLL stabilization */
201*4882a593Smuzhiyun	mov32	r7, TEGRA_TMRUS_BASE
202*4882a593Smuzhiyun	ldr	r1, [r7]
203*4882a593Smuzhiyun	add	r1, r1, #0xff
204*4882a593Smuzhiyun	wait_until r1, r7, r9
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun	adr	r4, tegra20_sclk_save
207*4882a593Smuzhiyun	ldr	r4, [r4]
208*4882a593Smuzhiyun	str	r4, [r0, #CLK_RESET_SCLK_BURST]
209*4882a593Smuzhiyun	mov32	r4, ((1 << 28) | (4))	@ burst policy is PLLP
210*4882a593Smuzhiyun	str	r4, [r0, #CLK_RESET_CCLK_BURST]
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun	mov32	r0, TEGRA_EMC_BASE
213*4882a593Smuzhiyun	ldr	r1, [r0, #EMC_CFG]
214*4882a593Smuzhiyun	bic	r1, r1, #(1 << 31)	@ disable DRAM_CLK_STOP
215*4882a593Smuzhiyun	str	r1, [r0, #EMC_CFG]
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun	mov	r1, #0
218*4882a593Smuzhiyun	str	r1, [r0, #EMC_SELF_REF]	@ take DRAM out of self refresh
219*4882a593Smuzhiyun	mov	r1, #1
220*4882a593Smuzhiyun	str	r1, [r0, #EMC_NOP]
221*4882a593Smuzhiyun	str	r1, [r0, #EMC_NOP]
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun	emc_device_mask r1, r0
224*4882a593Smuzhiyun
225*4882a593Smuzhiyunexit_selfrefresh_loop:
226*4882a593Smuzhiyun	ldr	r2, [r0, #EMC_EMC_STATUS]
227*4882a593Smuzhiyun	ands	r2, r2, r1
228*4882a593Smuzhiyun	bne	exit_selfrefresh_loop
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun	mov	r1, #0			@ unstall all transactions
231*4882a593Smuzhiyun	str	r1, [r0, #EMC_REQ_CTRL]
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun	mov32	r0, TEGRA_PMC_BASE
234*4882a593Smuzhiyun	ldr	r0, [r0, #PMC_SCRATCH41]
235*4882a593Smuzhiyun	ret	r0			@ jump to tegra_resume
236*4882a593SmuzhiyunENDPROC(tegra20_lp1_reset)
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun/*
239*4882a593Smuzhiyun * tegra20_tear_down_core
240*4882a593Smuzhiyun *
241*4882a593Smuzhiyun * copied into and executed from IRAM
242*4882a593Smuzhiyun * puts memory in self-refresh for LP0 and LP1
243*4882a593Smuzhiyun */
244*4882a593Smuzhiyuntegra20_tear_down_core:
245*4882a593Smuzhiyun	bl	tegra20_sdram_self_refresh
246*4882a593Smuzhiyun	bl	tegra20_switch_cpu_to_clk32k
247*4882a593Smuzhiyun	b	tegra20_enter_sleep
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun/*
250*4882a593Smuzhiyun * tegra20_switch_cpu_to_clk32k
251*4882a593Smuzhiyun *
252*4882a593Smuzhiyun * In LP0 and LP1 all PLLs will be turned off. Switch the CPU and system clock
253*4882a593Smuzhiyun * to the 32KHz clock.
254*4882a593Smuzhiyun */
255*4882a593Smuzhiyuntegra20_switch_cpu_to_clk32k:
256*4882a593Smuzhiyun	/*
257*4882a593Smuzhiyun	 * start by switching to CLKM to safely disable PLLs, then switch to
258*4882a593Smuzhiyun	 * CLKS.
259*4882a593Smuzhiyun	 */
260*4882a593Smuzhiyun	mov	r0, #(1 << 28)
261*4882a593Smuzhiyun	str	r0, [r5, #CLK_RESET_SCLK_BURST]
262*4882a593Smuzhiyun	str	r0, [r5, #CLK_RESET_CCLK_BURST]
263*4882a593Smuzhiyun	mov	r0, #0
264*4882a593Smuzhiyun	str	r0, [r5, #CLK_RESET_CCLK_DIVIDER]
265*4882a593Smuzhiyun	str	r0, [r5, #CLK_RESET_SCLK_DIVIDER]
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun	/* 2uS delay delay between changing SCLK and disabling PLLs */
268*4882a593Smuzhiyun	mov32	r7, TEGRA_TMRUS_BASE
269*4882a593Smuzhiyun	ldr	r1, [r7]
270*4882a593Smuzhiyun	add	r1, r1, #2
271*4882a593Smuzhiyun	wait_until r1, r7, r9
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun	/* disable PLLM, PLLP and PLLC */
274*4882a593Smuzhiyun	ldr	r0, [r5, #CLK_RESET_PLLM_BASE]
275*4882a593Smuzhiyun	bic	r0, r0, #(1 << 30)
276*4882a593Smuzhiyun	str	r0, [r5, #CLK_RESET_PLLM_BASE]
277*4882a593Smuzhiyun	ldr	r0, [r5, #CLK_RESET_PLLP_BASE]
278*4882a593Smuzhiyun	bic	r0, r0, #(1 << 30)
279*4882a593Smuzhiyun	str	r0, [r5, #CLK_RESET_PLLP_BASE]
280*4882a593Smuzhiyun	ldr	r0, [r5, #CLK_RESET_PLLC_BASE]
281*4882a593Smuzhiyun	bic	r0, r0, #(1 << 30)
282*4882a593Smuzhiyun	str	r0, [r5, #CLK_RESET_PLLC_BASE]
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun	/* switch to CLKS */
285*4882a593Smuzhiyun	mov	r0, #0	/* brust policy = 32KHz */
286*4882a593Smuzhiyun	str	r0, [r5, #CLK_RESET_SCLK_BURST]
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun	ret	lr
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun/*
291*4882a593Smuzhiyun * tegra20_enter_sleep
292*4882a593Smuzhiyun *
293*4882a593Smuzhiyun * uses flow controller to enter sleep state
294*4882a593Smuzhiyun * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1
295*4882a593Smuzhiyun * executes from SDRAM with target state is LP2
296*4882a593Smuzhiyun */
297*4882a593Smuzhiyuntegra20_enter_sleep:
298*4882a593Smuzhiyun	mov32   r6, TEGRA_FLOW_CTRL_BASE
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun	mov     r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
301*4882a593Smuzhiyun	orr	r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
302*4882a593Smuzhiyun	cpu_id	r1
303*4882a593Smuzhiyun	cpu_to_halt_reg r1, r1
304*4882a593Smuzhiyun	str	r0, [r6, r1]
305*4882a593Smuzhiyun	dsb
306*4882a593Smuzhiyun	ldr	r0, [r6, r1] /* memory barrier */
307*4882a593Smuzhiyun
308*4882a593Smuzhiyunhalted:
309*4882a593Smuzhiyun	dsb
310*4882a593Smuzhiyun	wfe	/* CPU should be power gated here */
311*4882a593Smuzhiyun	isb
312*4882a593Smuzhiyun	b	halted
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun/*
315*4882a593Smuzhiyun * tegra20_sdram_self_refresh
316*4882a593Smuzhiyun *
317*4882a593Smuzhiyun * called with MMU off and caches disabled
318*4882a593Smuzhiyun * puts sdram in self refresh
319*4882a593Smuzhiyun * must be executed from IRAM
320*4882a593Smuzhiyun */
321*4882a593Smuzhiyuntegra20_sdram_self_refresh:
322*4882a593Smuzhiyun	mov32	r1, TEGRA_EMC_BASE	@ r1 reserved for emc base addr
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun	mov	r2, #3
325*4882a593Smuzhiyun	str	r2, [r1, #EMC_REQ_CTRL]	@ stall incoming DRAM requests
326*4882a593Smuzhiyun
327*4882a593Smuzhiyunemcidle:
328*4882a593Smuzhiyun	ldr	r2, [r1, #EMC_EMC_STATUS]
329*4882a593Smuzhiyun	tst	r2, #4
330*4882a593Smuzhiyun	beq	emcidle
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun	mov	r2, #1
333*4882a593Smuzhiyun	str	r2, [r1, #EMC_SELF_REF]
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun	emc_device_mask r2, r1
336*4882a593Smuzhiyun
337*4882a593Smuzhiyunemcself:
338*4882a593Smuzhiyun	ldr	r3, [r1, #EMC_EMC_STATUS]
339*4882a593Smuzhiyun	and	r3, r3, r2
340*4882a593Smuzhiyun	cmp	r3, r2
341*4882a593Smuzhiyun	bne	emcself			@ loop until DDR in self-refresh
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun	adr	r2, tegra20_sdram_pad_address
344*4882a593Smuzhiyun	adr	r3, tegra20_sdram_pad_safe
345*4882a593Smuzhiyun	adr	r4, tegra20_sdram_pad_save
346*4882a593Smuzhiyun	mov	r5, #0
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun	ldr	r6, tegra20_sdram_pad_size
349*4882a593Smuzhiyunpadsave:
350*4882a593Smuzhiyun	ldr	r0, [r2, r5]		@ r0 is the addr in the pad_address
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun	ldr	r1, [r0]
353*4882a593Smuzhiyun	str	r1, [r4, r5]		@ save the content of the addr
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun	ldr	r1, [r3, r5]
356*4882a593Smuzhiyun	str	r1, [r0]		@ set the save val to the addr
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun	add	r5, r5, #4
359*4882a593Smuzhiyun	cmp	r6, r5
360*4882a593Smuzhiyun	bne	padsave
361*4882a593Smuzhiyunpadsave_done:
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun	mov32	r5, TEGRA_CLK_RESET_BASE
364*4882a593Smuzhiyun	ldr	r0, [r5, #CLK_RESET_SCLK_BURST]
365*4882a593Smuzhiyun	adr	r2, tegra20_sclk_save
366*4882a593Smuzhiyun	str	r0, [r2]
367*4882a593Smuzhiyun	dsb
368*4882a593Smuzhiyun	ret	lr
369*4882a593Smuzhiyun
370*4882a593Smuzhiyuntegra20_sdram_pad_address:
371*4882a593Smuzhiyun	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL
372*4882a593Smuzhiyun	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL
373*4882a593Smuzhiyun	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2CLKCFGPADCTRL
374*4882a593Smuzhiyun	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2COMPPADCTRL
375*4882a593Smuzhiyun	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2VTTGENPADCTRL
376*4882a593Smuzhiyun	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL2
377*4882a593Smuzhiyun	.word	TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL2
378*4882a593Smuzhiyun
379*4882a593Smuzhiyuntegra20_sdram_pad_size:
380*4882a593Smuzhiyun	.word	tegra20_sdram_pad_size - tegra20_sdram_pad_address
381*4882a593Smuzhiyun
382*4882a593Smuzhiyuntegra20_sdram_pad_safe:
383*4882a593Smuzhiyun	.word	0x8
384*4882a593Smuzhiyun	.word	0x8
385*4882a593Smuzhiyun	.word	0x0
386*4882a593Smuzhiyun	.word	0x8
387*4882a593Smuzhiyun	.word	0x5500
388*4882a593Smuzhiyun	.word	0x08080040
389*4882a593Smuzhiyun	.word	0x0
390*4882a593Smuzhiyun
391*4882a593Smuzhiyuntegra20_sclk_save:
392*4882a593Smuzhiyun	.word	0x0
393*4882a593Smuzhiyun
394*4882a593Smuzhiyuntegra20_sdram_pad_save:
395*4882a593Smuzhiyun	.rept (tegra20_sdram_pad_size - tegra20_sdram_pad_address) / 4
396*4882a593Smuzhiyun	.long	0
397*4882a593Smuzhiyun	.endr
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun	.ltorg
400*4882a593Smuzhiyun/* dummy symbol for end of IRAM */
401*4882a593Smuzhiyun	.align L1_CACHE_SHIFT
402*4882a593Smuzhiyun	.globl tegra20_iram_end
403*4882a593Smuzhiyuntegra20_iram_end:
404*4882a593Smuzhiyun	b	.
405*4882a593Smuzhiyun#endif
406