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