xref: /OK3568_Linux_fs/kernel/arch/powerpc/platforms/52xx/lite5200_sleep.S (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun#include <asm/reg.h>
3*4882a593Smuzhiyun#include <asm/ppc_asm.h>
4*4882a593Smuzhiyun#include <asm/processor.h>
5*4882a593Smuzhiyun#include <asm/cache.h>
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun#define SDRAM_CTRL	0x104
9*4882a593Smuzhiyun#define SC_MODE_EN	(1<<31)
10*4882a593Smuzhiyun#define SC_CKE		(1<<30)
11*4882a593Smuzhiyun#define SC_REF_EN	(1<<28)
12*4882a593Smuzhiyun#define SC_SOFT_PRE	(1<<1)
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun#define GPIOW_GPIOE	0xc00
15*4882a593Smuzhiyun#define GPIOW_DDR	0xc08
16*4882a593Smuzhiyun#define GPIOW_DVO	0xc0c
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun#define CDM_CE		0x214
19*4882a593Smuzhiyun#define CDM_SDRAM	(1<<3)
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun/* helpers... beware: r10 and r4 are overwritten */
23*4882a593Smuzhiyun#define SAVE_SPRN(reg, addr)		\
24*4882a593Smuzhiyun	mfspr	r10, SPRN_##reg;	\
25*4882a593Smuzhiyun	stw	r10, ((addr)*4)(r4);
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun#define LOAD_SPRN(reg, addr)		\
28*4882a593Smuzhiyun	lwz	r10, ((addr)*4)(r4);	\
29*4882a593Smuzhiyun	mtspr	SPRN_##reg, r10;	\
30*4882a593Smuzhiyun	sync;				\
31*4882a593Smuzhiyun	isync;
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun	.data
35*4882a593Smuzhiyunregisters:
36*4882a593Smuzhiyun	.space 0x5c*4
37*4882a593Smuzhiyun	.text
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun/* ---------------------------------------------------------------------- */
40*4882a593Smuzhiyun/* low-power mode with help of M68HLC908QT1 */
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun	.globl lite5200_low_power
43*4882a593Smuzhiyunlite5200_low_power:
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun	mr	r7, r3	/* save SRAM va */
46*4882a593Smuzhiyun	mr	r8, r4	/* save MBAR va */
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun	/* setup wakeup address for u-boot at physical location 0x0 */
49*4882a593Smuzhiyun	lis	r3, CONFIG_KERNEL_START@h
50*4882a593Smuzhiyun	lis	r4, lite5200_wakeup@h
51*4882a593Smuzhiyun	ori	r4, r4, lite5200_wakeup@l
52*4882a593Smuzhiyun	sub	r4, r4, r3
53*4882a593Smuzhiyun	stw	r4, 0(r3)
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun	/*
57*4882a593Smuzhiyun	 * save stuff BDI overwrites
58*4882a593Smuzhiyun	 * 0xf0 (0xe0->0x100 gets overwritten when BDI connected;
59*4882a593Smuzhiyun	 *   even when CONFIG_BDI_SWITCH is disabled and MMU XLAT commented; heisenbug?))
60*4882a593Smuzhiyun	 * WARNING: self-refresh doesn't seem to work when BDI2000 is connected,
61*4882a593Smuzhiyun	 *   possibly because BDI sets SDRAM registers before wakeup code does
62*4882a593Smuzhiyun	 */
63*4882a593Smuzhiyun	lis	r4, registers@h
64*4882a593Smuzhiyun	ori	r4, r4, registers@l
65*4882a593Smuzhiyun	lwz	r10, 0xf0(r3)
66*4882a593Smuzhiyun	stw	r10, (0x1d*4)(r4)
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun	/* save registers to r4 [destroys r10] */
69*4882a593Smuzhiyun	SAVE_SPRN(LR, 0x1c)
70*4882a593Smuzhiyun	bl	save_regs
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun	/* flush caches [destroys r3, r4] */
73*4882a593Smuzhiyun	bl	flush_data_cache
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun	/* copy code to sram */
77*4882a593Smuzhiyun	mr	r4, r7
78*4882a593Smuzhiyun	li	r3, (sram_code_end - sram_code)/4
79*4882a593Smuzhiyun	mtctr	r3
80*4882a593Smuzhiyun	lis	r3, sram_code@h
81*4882a593Smuzhiyun	ori	r3, r3, sram_code@l
82*4882a593Smuzhiyun1:
83*4882a593Smuzhiyun	lwz	r5, 0(r3)
84*4882a593Smuzhiyun	stw	r5, 0(r4)
85*4882a593Smuzhiyun	addi	r3, r3, 4
86*4882a593Smuzhiyun	addi	r4, r4, 4
87*4882a593Smuzhiyun	bdnz	1b
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun	/* get tb_ticks_per_usec */
90*4882a593Smuzhiyun	lis	r3, tb_ticks_per_usec@h
91*4882a593Smuzhiyun	lwz	r11, tb_ticks_per_usec@l(r3)
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun	/* disable I and D caches */
94*4882a593Smuzhiyun	mfspr	r3, SPRN_HID0
95*4882a593Smuzhiyun	ori	r3, r3, HID0_ICE | HID0_DCE
96*4882a593Smuzhiyun	xori	r3, r3, HID0_ICE | HID0_DCE
97*4882a593Smuzhiyun	sync; isync;
98*4882a593Smuzhiyun	mtspr	SPRN_HID0, r3
99*4882a593Smuzhiyun	sync; isync;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun	/* jump to sram */
102*4882a593Smuzhiyun	mtlr	r7
103*4882a593Smuzhiyun	blrl
104*4882a593Smuzhiyun	/* doesn't return */
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun
107*4882a593Smuzhiyunsram_code:
108*4882a593Smuzhiyun	/* self refresh */
109*4882a593Smuzhiyun	lwz	r4, SDRAM_CTRL(r8)
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun	/* send NOP (precharge) */
112*4882a593Smuzhiyun	oris	r4, r4, SC_MODE_EN@h	/* mode_en */
113*4882a593Smuzhiyun	stw	r4, SDRAM_CTRL(r8)
114*4882a593Smuzhiyun	sync
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun	ori	r4, r4, SC_SOFT_PRE	/* soft_pre */
117*4882a593Smuzhiyun	stw	r4, SDRAM_CTRL(r8)
118*4882a593Smuzhiyun	sync
119*4882a593Smuzhiyun	xori	r4, r4, SC_SOFT_PRE
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun	xoris	r4, r4, SC_MODE_EN@h	/* !mode_en */
122*4882a593Smuzhiyun	stw	r4, SDRAM_CTRL(r8)
123*4882a593Smuzhiyun	sync
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun	/* delay (for NOP to finish) */
126*4882a593Smuzhiyun	li	r12, 1
127*4882a593Smuzhiyun	bl	udelay
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun	/*
130*4882a593Smuzhiyun	 * mode_en must not be set when enabling self-refresh
131*4882a593Smuzhiyun	 * send AR with CKE low (self-refresh)
132*4882a593Smuzhiyun	 */
133*4882a593Smuzhiyun	oris	r4, r4, (SC_REF_EN | SC_CKE)@h
134*4882a593Smuzhiyun	xoris	r4, r4, (SC_CKE)@h	/* ref_en !cke */
135*4882a593Smuzhiyun	stw	r4, SDRAM_CTRL(r8)
136*4882a593Smuzhiyun	sync
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun	/* delay (after !CKE there should be two cycles) */
139*4882a593Smuzhiyun	li	r12, 1
140*4882a593Smuzhiyun	bl	udelay
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun	/* disable clock */
143*4882a593Smuzhiyun	lwz	r4, CDM_CE(r8)
144*4882a593Smuzhiyun	ori	r4, r4, CDM_SDRAM
145*4882a593Smuzhiyun	xori	r4, r4, CDM_SDRAM
146*4882a593Smuzhiyun	stw	r4, CDM_CE(r8)
147*4882a593Smuzhiyun	sync
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun	/* delay a bit */
150*4882a593Smuzhiyun	li	r12, 1
151*4882a593Smuzhiyun	bl	udelay
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun	/* turn off with QT chip */
155*4882a593Smuzhiyun	li	r4, 0x02
156*4882a593Smuzhiyun	stb	r4, GPIOW_GPIOE(r8)	/* enable gpio_wkup1 */
157*4882a593Smuzhiyun	sync
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun	stb	r4, GPIOW_DVO(r8)	/* "output" high */
160*4882a593Smuzhiyun	sync
161*4882a593Smuzhiyun	stb	r4, GPIOW_DDR(r8)	/* output */
162*4882a593Smuzhiyun	sync
163*4882a593Smuzhiyun	stb	r4, GPIOW_DVO(r8)	/* output high */
164*4882a593Smuzhiyun	sync
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun	/* 10uS delay */
167*4882a593Smuzhiyun	li	r12, 10
168*4882a593Smuzhiyun	bl	udelay
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun	/* turn off */
171*4882a593Smuzhiyun	li	r4, 0
172*4882a593Smuzhiyun	stb	r4, GPIOW_DVO(r8)	/* output low */
173*4882a593Smuzhiyun	sync
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun	/* wait until we're offline */
176*4882a593Smuzhiyun  1:
177*4882a593Smuzhiyun	b	1b
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun	/* local udelay in sram is needed */
181*4882a593Smuzhiyun  udelay: /* r11 - tb_ticks_per_usec, r12 - usecs, overwrites r13 */
182*4882a593Smuzhiyun	mullw	r12, r12, r11
183*4882a593Smuzhiyun	mftb	r13	/* start */
184*4882a593Smuzhiyun	add	r12, r13, r12 /* end */
185*4882a593Smuzhiyun    1:
186*4882a593Smuzhiyun	mftb	r13	/* current */
187*4882a593Smuzhiyun	cmp	cr0, r13, r12
188*4882a593Smuzhiyun	blt	1b
189*4882a593Smuzhiyun	blr
190*4882a593Smuzhiyun
191*4882a593Smuzhiyunsram_code_end:
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun/* uboot jumps here on resume */
196*4882a593Smuzhiyunlite5200_wakeup:
197*4882a593Smuzhiyun	bl	restore_regs
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun	/* HIDs, MSR */
201*4882a593Smuzhiyun	LOAD_SPRN(HID1, 0x19)
202*4882a593Smuzhiyun	LOAD_SPRN(HID2, 0x1a)
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun	/* address translation is tricky (see turn_on_mmu) */
206*4882a593Smuzhiyun	mfmsr	r10
207*4882a593Smuzhiyun	ori	r10, r10, MSR_DR | MSR_IR
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun	mtspr	SPRN_SRR1, r10
211*4882a593Smuzhiyun	lis	r10, mmu_on@h
212*4882a593Smuzhiyun	ori	r10, r10, mmu_on@l
213*4882a593Smuzhiyun	mtspr	SPRN_SRR0, r10
214*4882a593Smuzhiyun	sync
215*4882a593Smuzhiyun	rfi
216*4882a593Smuzhiyunmmu_on:
217*4882a593Smuzhiyun	/* kernel offset (r4 is still set from restore_registers) */
218*4882a593Smuzhiyun	addis	r4, r4, CONFIG_KERNEL_START@h
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun	/* restore MSR */
222*4882a593Smuzhiyun	lwz	r10, (4*0x1b)(r4)
223*4882a593Smuzhiyun	mtmsr	r10
224*4882a593Smuzhiyun	sync; isync;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun	/* invalidate caches */
227*4882a593Smuzhiyun	mfspr	r10, SPRN_HID0
228*4882a593Smuzhiyun	ori	r5, r10, HID0_ICFI | HID0_DCI
229*4882a593Smuzhiyun	mtspr	SPRN_HID0, r5	/* invalidate caches */
230*4882a593Smuzhiyun	sync; isync;
231*4882a593Smuzhiyun	mtspr	SPRN_HID0, r10
232*4882a593Smuzhiyun	sync; isync;
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun	/* enable caches */
235*4882a593Smuzhiyun	lwz	r10, (4*0x18)(r4)
236*4882a593Smuzhiyun	mtspr	SPRN_HID0, r10	/* restore (enable caches, DPM) */
237*4882a593Smuzhiyun	/* ^ this has to be after address translation set in MSR */
238*4882a593Smuzhiyun	sync
239*4882a593Smuzhiyun	isync
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun	/* restore 0xf0 (BDI2000) */
243*4882a593Smuzhiyun	lis	r3, CONFIG_KERNEL_START@h
244*4882a593Smuzhiyun	lwz	r10, (0x1d*4)(r4)
245*4882a593Smuzhiyun	stw	r10, 0xf0(r3)
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun	LOAD_SPRN(LR, 0x1c)
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun	blr
251*4882a593Smuzhiyun_ASM_NOKPROBE_SYMBOL(lite5200_wakeup)
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun/* ---------------------------------------------------------------------- */
255*4882a593Smuzhiyun/* boring code: helpers */
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun/* save registers */
258*4882a593Smuzhiyun#define SAVE_BAT(n, addr)		\
259*4882a593Smuzhiyun	SAVE_SPRN(DBAT##n##L, addr);	\
260*4882a593Smuzhiyun	SAVE_SPRN(DBAT##n##U, addr+1);	\
261*4882a593Smuzhiyun	SAVE_SPRN(IBAT##n##L, addr+2);	\
262*4882a593Smuzhiyun	SAVE_SPRN(IBAT##n##U, addr+3);
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun#define SAVE_SR(n, addr)		\
265*4882a593Smuzhiyun	mfsr	r10, n;			\
266*4882a593Smuzhiyun	stw	r10, ((addr)*4)(r4);
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun#define SAVE_4SR(n, addr)	\
269*4882a593Smuzhiyun	SAVE_SR(n, addr);	\
270*4882a593Smuzhiyun	SAVE_SR(n+1, addr+1);	\
271*4882a593Smuzhiyun	SAVE_SR(n+2, addr+2);	\
272*4882a593Smuzhiyun	SAVE_SR(n+3, addr+3);
273*4882a593Smuzhiyun
274*4882a593Smuzhiyunsave_regs:
275*4882a593Smuzhiyun	stw	r0, 0(r4)
276*4882a593Smuzhiyun	stw	r1, 0x4(r4)
277*4882a593Smuzhiyun	stw	r2, 0x8(r4)
278*4882a593Smuzhiyun	stmw	r11, 0xc(r4) /* 0xc -> 0x5f, (0x18*4-1) */
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun	SAVE_SPRN(HID0, 0x18)
281*4882a593Smuzhiyun	SAVE_SPRN(HID1, 0x19)
282*4882a593Smuzhiyun	SAVE_SPRN(HID2, 0x1a)
283*4882a593Smuzhiyun	mfmsr	r10
284*4882a593Smuzhiyun	stw	r10, (4*0x1b)(r4)
285*4882a593Smuzhiyun	/*SAVE_SPRN(LR, 0x1c) have to save it before the call */
286*4882a593Smuzhiyun	/* 0x1d reserved by 0xf0 */
287*4882a593Smuzhiyun	SAVE_SPRN(RPA,   0x1e)
288*4882a593Smuzhiyun	SAVE_SPRN(SDR1,  0x1f)
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun	/* save MMU regs */
291*4882a593Smuzhiyun	SAVE_BAT(0, 0x20)
292*4882a593Smuzhiyun	SAVE_BAT(1, 0x24)
293*4882a593Smuzhiyun	SAVE_BAT(2, 0x28)
294*4882a593Smuzhiyun	SAVE_BAT(3, 0x2c)
295*4882a593Smuzhiyun	SAVE_BAT(4, 0x30)
296*4882a593Smuzhiyun	SAVE_BAT(5, 0x34)
297*4882a593Smuzhiyun	SAVE_BAT(6, 0x38)
298*4882a593Smuzhiyun	SAVE_BAT(7, 0x3c)
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun	SAVE_4SR(0, 0x40)
301*4882a593Smuzhiyun	SAVE_4SR(4, 0x44)
302*4882a593Smuzhiyun	SAVE_4SR(8, 0x48)
303*4882a593Smuzhiyun	SAVE_4SR(12, 0x4c)
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun	SAVE_SPRN(SPRG0, 0x50)
306*4882a593Smuzhiyun	SAVE_SPRN(SPRG1, 0x51)
307*4882a593Smuzhiyun	SAVE_SPRN(SPRG2, 0x52)
308*4882a593Smuzhiyun	SAVE_SPRN(SPRG3, 0x53)
309*4882a593Smuzhiyun	SAVE_SPRN(SPRG4, 0x54)
310*4882a593Smuzhiyun	SAVE_SPRN(SPRG5, 0x55)
311*4882a593Smuzhiyun	SAVE_SPRN(SPRG6, 0x56)
312*4882a593Smuzhiyun	SAVE_SPRN(SPRG7, 0x57)
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun	SAVE_SPRN(IABR,  0x58)
315*4882a593Smuzhiyun	SAVE_SPRN(DABR,  0x59)
316*4882a593Smuzhiyun	SAVE_SPRN(TBRL,  0x5a)
317*4882a593Smuzhiyun	SAVE_SPRN(TBRU,  0x5b)
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun	blr
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun/* restore registers */
323*4882a593Smuzhiyun#define LOAD_BAT(n, addr)		\
324*4882a593Smuzhiyun	LOAD_SPRN(DBAT##n##L, addr);	\
325*4882a593Smuzhiyun	LOAD_SPRN(DBAT##n##U, addr+1);	\
326*4882a593Smuzhiyun	LOAD_SPRN(IBAT##n##L, addr+2);	\
327*4882a593Smuzhiyun	LOAD_SPRN(IBAT##n##U, addr+3);
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun#define LOAD_SR(n, addr)		\
330*4882a593Smuzhiyun	lwz	r10, ((addr)*4)(r4);	\
331*4882a593Smuzhiyun	mtsr	n, r10;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun#define LOAD_4SR(n, addr)	\
334*4882a593Smuzhiyun	LOAD_SR(n, addr);	\
335*4882a593Smuzhiyun	LOAD_SR(n+1, addr+1);	\
336*4882a593Smuzhiyun	LOAD_SR(n+2, addr+2);	\
337*4882a593Smuzhiyun	LOAD_SR(n+3, addr+3);
338*4882a593Smuzhiyun
339*4882a593Smuzhiyunrestore_regs:
340*4882a593Smuzhiyun	lis	r4, registers@h
341*4882a593Smuzhiyun	ori	r4, r4, registers@l
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun	/* MMU is not up yet */
344*4882a593Smuzhiyun	subis	r4, r4, CONFIG_KERNEL_START@h
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun	lwz	r0, 0(r4)
347*4882a593Smuzhiyun	lwz	r1, 0x4(r4)
348*4882a593Smuzhiyun	lwz	r2, 0x8(r4)
349*4882a593Smuzhiyun	lmw	r11, 0xc(r4)
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun	/*
352*4882a593Smuzhiyun	 * these are a bit tricky
353*4882a593Smuzhiyun	 *
354*4882a593Smuzhiyun	 * 0x18 - HID0
355*4882a593Smuzhiyun	 * 0x19 - HID1
356*4882a593Smuzhiyun	 * 0x1a - HID2
357*4882a593Smuzhiyun	 * 0x1b - MSR
358*4882a593Smuzhiyun	 * 0x1c - LR
359*4882a593Smuzhiyun	 * 0x1d - reserved by 0xf0 (BDI2000)
360*4882a593Smuzhiyun	 */
361*4882a593Smuzhiyun	LOAD_SPRN(RPA,   0x1e);
362*4882a593Smuzhiyun	LOAD_SPRN(SDR1,  0x1f);
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun	/* restore MMU regs */
365*4882a593Smuzhiyun	LOAD_BAT(0, 0x20)
366*4882a593Smuzhiyun	LOAD_BAT(1, 0x24)
367*4882a593Smuzhiyun	LOAD_BAT(2, 0x28)
368*4882a593Smuzhiyun	LOAD_BAT(3, 0x2c)
369*4882a593Smuzhiyun	LOAD_BAT(4, 0x30)
370*4882a593Smuzhiyun	LOAD_BAT(5, 0x34)
371*4882a593Smuzhiyun	LOAD_BAT(6, 0x38)
372*4882a593Smuzhiyun	LOAD_BAT(7, 0x3c)
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun	LOAD_4SR(0, 0x40)
375*4882a593Smuzhiyun	LOAD_4SR(4, 0x44)
376*4882a593Smuzhiyun	LOAD_4SR(8, 0x48)
377*4882a593Smuzhiyun	LOAD_4SR(12, 0x4c)
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun	/* rest of regs */
380*4882a593Smuzhiyun	LOAD_SPRN(SPRG0, 0x50);
381*4882a593Smuzhiyun	LOAD_SPRN(SPRG1, 0x51);
382*4882a593Smuzhiyun	LOAD_SPRN(SPRG2, 0x52);
383*4882a593Smuzhiyun	LOAD_SPRN(SPRG3, 0x53);
384*4882a593Smuzhiyun	LOAD_SPRN(SPRG4, 0x54);
385*4882a593Smuzhiyun	LOAD_SPRN(SPRG5, 0x55);
386*4882a593Smuzhiyun	LOAD_SPRN(SPRG6, 0x56);
387*4882a593Smuzhiyun	LOAD_SPRN(SPRG7, 0x57);
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun	LOAD_SPRN(IABR,  0x58);
390*4882a593Smuzhiyun	LOAD_SPRN(DABR,  0x59);
391*4882a593Smuzhiyun	LOAD_SPRN(TBWL,  0x5a);	/* these two have separate R/W regs */
392*4882a593Smuzhiyun	LOAD_SPRN(TBWU,  0x5b);
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun	blr
395*4882a593Smuzhiyun_ASM_NOKPROBE_SYMBOL(restore_regs)
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun/* cache flushing code. copied from arch/ppc/boot/util.S */
400*4882a593Smuzhiyun#define NUM_CACHE_LINES (128*8)
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun/*
403*4882a593Smuzhiyun * Flush data cache
404*4882a593Smuzhiyun * Do this by just reading lots of stuff into the cache.
405*4882a593Smuzhiyun */
406*4882a593Smuzhiyunflush_data_cache:
407*4882a593Smuzhiyun	lis	r3,CONFIG_KERNEL_START@h
408*4882a593Smuzhiyun	ori	r3,r3,CONFIG_KERNEL_START@l
409*4882a593Smuzhiyun	li	r4,NUM_CACHE_LINES
410*4882a593Smuzhiyun	mtctr	r4
411*4882a593Smuzhiyun1:
412*4882a593Smuzhiyun	lwz	r4,0(r3)
413*4882a593Smuzhiyun	addi	r3,r3,L1_CACHE_BYTES	/* Next line, please */
414*4882a593Smuzhiyun	bdnz	1b
415*4882a593Smuzhiyun	blr
416