• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * This file contains sleep low-level functions for PowerBook G3.
3 *    Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org)
4 *    and Paul Mackerras (paulus@samba.org).
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <asm/processor.h>
14#include <asm/page.h>
15#include <asm/ppc_asm.h>
16#include <asm/cputable.h>
17#include <asm/cache.h>
18#include <asm/thread_info.h>
19#include <asm/asm-offsets.h>
20#include <asm/mmu.h>
21#include <asm/feature-fixups.h>
22
23#define MAGIC	0x4c617273	/* 'Lars' */
24
25/*
26 * Structure for storing CPU registers on the stack.
27 */
28#define SL_SP		0
29#define SL_PC		4
30#define SL_MSR		8
31#define SL_SDR1		0xc
32#define SL_SPRG0	0x10	/* 4 sprg's */
33#define SL_DBAT0	0x20
34#define SL_IBAT0	0x28
35#define SL_DBAT1	0x30
36#define SL_IBAT1	0x38
37#define SL_DBAT2	0x40
38#define SL_IBAT2	0x48
39#define SL_DBAT3	0x50
40#define SL_IBAT3	0x58
41#define SL_DBAT4	0x60
42#define SL_IBAT4	0x68
43#define SL_DBAT5	0x70
44#define SL_IBAT5	0x78
45#define SL_DBAT6	0x80
46#define SL_IBAT6	0x88
47#define SL_DBAT7	0x90
48#define SL_IBAT7	0x98
49#define SL_TB		0xa0
50#define SL_R2		0xa8
51#define SL_CR		0xac
52#define SL_R12		0xb0	/* r12 to r31 */
53#define SL_SIZE		(SL_R12 + 80)
54
55	.section .text
56	.align	5
57
58#if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC) || \
59    (defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32))
60
61/* This gets called by via-pmu.c late during the sleep process.
62 * The PMU was already send the sleep command and will shut us down
63 * soon. We need to save all that is needed and setup the wakeup
64 * vector that will be called by the ROM on wakeup
65 */
66_GLOBAL(low_sleep_handler)
67#ifndef CONFIG_6xx
68	blr
69#else
70	mflr	r0
71	stw	r0,4(r1)
72	stwu	r1,-SL_SIZE(r1)
73	mfcr	r0
74	stw	r0,SL_CR(r1)
75	stw	r2,SL_R2(r1)
76	stmw	r12,SL_R12(r1)
77
78	/* Save MSR & SDR1 */
79	mfmsr	r4
80	stw	r4,SL_MSR(r1)
81	mfsdr1	r4
82	stw	r4,SL_SDR1(r1)
83
84	/* Get a stable timebase and save it */
851:	mftbu	r4
86	stw	r4,SL_TB(r1)
87	mftb	r5
88	stw	r5,SL_TB+4(r1)
89	mftbu	r3
90	cmpw	r3,r4
91	bne	1b
92
93	/* Save SPRGs */
94	mfsprg	r4,0
95	stw	r4,SL_SPRG0(r1)
96	mfsprg	r4,1
97	stw	r4,SL_SPRG0+4(r1)
98	mfsprg	r4,2
99	stw	r4,SL_SPRG0+8(r1)
100	mfsprg	r4,3
101	stw	r4,SL_SPRG0+12(r1)
102
103	/* Save BATs */
104	mfdbatu	r4,0
105	stw	r4,SL_DBAT0(r1)
106	mfdbatl	r4,0
107	stw	r4,SL_DBAT0+4(r1)
108	mfdbatu	r4,1
109	stw	r4,SL_DBAT1(r1)
110	mfdbatl	r4,1
111	stw	r4,SL_DBAT1+4(r1)
112	mfdbatu	r4,2
113	stw	r4,SL_DBAT2(r1)
114	mfdbatl	r4,2
115	stw	r4,SL_DBAT2+4(r1)
116	mfdbatu	r4,3
117	stw	r4,SL_DBAT3(r1)
118	mfdbatl	r4,3
119	stw	r4,SL_DBAT3+4(r1)
120	mfibatu	r4,0
121	stw	r4,SL_IBAT0(r1)
122	mfibatl	r4,0
123	stw	r4,SL_IBAT0+4(r1)
124	mfibatu	r4,1
125	stw	r4,SL_IBAT1(r1)
126	mfibatl	r4,1
127	stw	r4,SL_IBAT1+4(r1)
128	mfibatu	r4,2
129	stw	r4,SL_IBAT2(r1)
130	mfibatl	r4,2
131	stw	r4,SL_IBAT2+4(r1)
132	mfibatu	r4,3
133	stw	r4,SL_IBAT3(r1)
134	mfibatl	r4,3
135	stw	r4,SL_IBAT3+4(r1)
136
137BEGIN_MMU_FTR_SECTION
138	mfspr	r4,SPRN_DBAT4U
139	stw	r4,SL_DBAT4(r1)
140	mfspr	r4,SPRN_DBAT4L
141	stw	r4,SL_DBAT4+4(r1)
142	mfspr	r4,SPRN_DBAT5U
143	stw	r4,SL_DBAT5(r1)
144	mfspr	r4,SPRN_DBAT5L
145	stw	r4,SL_DBAT5+4(r1)
146	mfspr	r4,SPRN_DBAT6U
147	stw	r4,SL_DBAT6(r1)
148	mfspr	r4,SPRN_DBAT6L
149	stw	r4,SL_DBAT6+4(r1)
150	mfspr	r4,SPRN_DBAT7U
151	stw	r4,SL_DBAT7(r1)
152	mfspr	r4,SPRN_DBAT7L
153	stw	r4,SL_DBAT7+4(r1)
154	mfspr	r4,SPRN_IBAT4U
155	stw	r4,SL_IBAT4(r1)
156	mfspr	r4,SPRN_IBAT4L
157	stw	r4,SL_IBAT4+4(r1)
158	mfspr	r4,SPRN_IBAT5U
159	stw	r4,SL_IBAT5(r1)
160	mfspr	r4,SPRN_IBAT5L
161	stw	r4,SL_IBAT5+4(r1)
162	mfspr	r4,SPRN_IBAT6U
163	stw	r4,SL_IBAT6(r1)
164	mfspr	r4,SPRN_IBAT6L
165	stw	r4,SL_IBAT6+4(r1)
166	mfspr	r4,SPRN_IBAT7U
167	stw	r4,SL_IBAT7(r1)
168	mfspr	r4,SPRN_IBAT7L
169	stw	r4,SL_IBAT7+4(r1)
170END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
171
172	/* Backup various CPU config stuffs */
173	bl	__save_cpu_setup
174
175	/* The ROM can wake us up via 2 different vectors:
176	 *  - On wallstreet & lombard, we must write a magic
177	 *    value 'Lars' at address 4 and a pointer to a
178	 *    memory location containing the PC to resume from
179	 *    at address 0.
180	 *  - On Core99, we must store the wakeup vector at
181	 *    address 0x80 and eventually it's parameters
182	 *    at address 0x84. I've have some trouble with those
183	 *    parameters however and I no longer use them.
184	 */
185	lis	r5,grackle_wake_up@ha
186	addi	r5,r5,grackle_wake_up@l
187	tophys(r5,r5)
188	stw	r5,SL_PC(r1)
189	lis	r4,KERNELBASE@h
190	tophys(r5,r1)
191	addi	r5,r5,SL_PC
192	lis	r6,MAGIC@ha
193	addi	r6,r6,MAGIC@l
194	stw	r5,0(r4)
195	stw	r6,4(r4)
196	/* Setup stuffs at 0x80-0x84 for Core99 */
197	lis	r3,core99_wake_up@ha
198	addi	r3,r3,core99_wake_up@l
199	tophys(r3,r3)
200	stw	r3,0x80(r4)
201	stw	r5,0x84(r4)
202	/* Store a pointer to our backup storage into
203	 * a kernel global
204	 */
205	lis r3,sleep_storage@ha
206	addi r3,r3,sleep_storage@l
207	stw r5,0(r3)
208
209	.globl	low_cpu_die
210low_cpu_die:
211	/* Flush & disable all caches */
212	bl	flush_disable_caches
213
214	/* Turn off data relocation. */
215	mfmsr	r3		/* Save MSR in r7 */
216	rlwinm	r3,r3,0,28,26	/* Turn off DR bit */
217	sync
218	mtmsr	r3
219	isync
220
221BEGIN_FTR_SECTION
222	/* Flush any pending L2 data prefetches to work around HW bug */
223	sync
224	lis	r3,0xfff0
225	lwz	r0,0(r3)	/* perform cache-inhibited load to ROM */
226	sync			/* (caches are disabled at this point) */
227END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
228
229/*
230 * Set the HID0 and MSR for sleep.
231 */
232	mfspr	r2,SPRN_HID0
233	rlwinm	r2,r2,0,10,7	/* clear doze, nap */
234	oris	r2,r2,HID0_SLEEP@h
235	sync
236	isync
237	mtspr	SPRN_HID0,r2
238	sync
239
240/* This loop puts us back to sleep in case we have a spurrious
241 * wakeup so that the host bridge properly stays asleep. The
242 * CPU will be turned off, either after a known time (about 1
243 * second) on wallstreet & lombard, or as soon as the CPU enters
244 * SLEEP mode on core99
245 */
246	mfmsr	r2
247	oris	r2,r2,MSR_POW@h
2481:	sync
249	mtmsr	r2
250	isync
251	b	1b
252
253/*
254 * Here is the resume code.
255 */
256
257
258/*
259 * Core99 machines resume here
260 * r4 has the physical address of SL_PC(sp) (unused)
261 */
262_GLOBAL(core99_wake_up)
263	/* Make sure HID0 no longer contains any sleep bit and that data cache
264	 * is disabled
265	 */
266	mfspr	r3,SPRN_HID0
267	rlwinm	r3,r3,0,11,7		/* clear SLEEP, NAP, DOZE bits */
268	rlwinm	3,r3,0,18,15		/* clear DCE, ICE */
269	mtspr	SPRN_HID0,r3
270	sync
271	isync
272
273	/* sanitize MSR */
274	mfmsr	r3
275	ori	r3,r3,MSR_EE|MSR_IP
276	xori	r3,r3,MSR_EE|MSR_IP
277	sync
278	isync
279	mtmsr	r3
280	sync
281	isync
282
283	/* Recover sleep storage */
284	lis	r3,sleep_storage@ha
285	addi	r3,r3,sleep_storage@l
286	tophys(r3,r3)
287	lwz	r1,0(r3)
288
289	/* Pass thru to older resume code ... */
290/*
291 * Here is the resume code for older machines.
292 * r1 has the physical address of SL_PC(sp).
293 */
294
295grackle_wake_up:
296
297	/* Restore the kernel's segment registers before
298	 * we do any r1 memory access as we are not sure they
299	 * are in a sane state above the first 256Mb region
300	 */
301	li	r0,16		/* load up segment register values */
302	mtctr	r0		/* for context 0 */
303	lis	r3,0x2000	/* Ku = 1, VSID = 0 */
304	li	r4,0
3053:	mtsrin	r3,r4
306	addi	r3,r3,0x111	/* increment VSID */
307	addis	r4,r4,0x1000	/* address of next segment */
308	bdnz	3b
309	sync
310	isync
311
312	subi	r1,r1,SL_PC
313
314	/* Restore various CPU config stuffs */
315	bl	__restore_cpu_setup
316
317	/* Make sure all FPRs have been initialized */
318	bl	reloc_offset
319	bl	__init_fpu_registers
320
321	/* Invalidate & enable L1 cache, we don't care about
322	 * whatever the ROM may have tried to write to memory
323	 */
324	bl	__inval_enable_L1
325
326	/* Restore the BATs, and SDR1.  Then we can turn on the MMU. */
327	lwz	r4,SL_SDR1(r1)
328	mtsdr1	r4
329	lwz	r4,SL_SPRG0(r1)
330	mtsprg	0,r4
331	lwz	r4,SL_SPRG0+4(r1)
332	mtsprg	1,r4
333	lwz	r4,SL_SPRG0+8(r1)
334	mtsprg	2,r4
335	lwz	r4,SL_SPRG0+12(r1)
336	mtsprg	3,r4
337
338	lwz	r4,SL_DBAT0(r1)
339	mtdbatu	0,r4
340	lwz	r4,SL_DBAT0+4(r1)
341	mtdbatl	0,r4
342	lwz	r4,SL_DBAT1(r1)
343	mtdbatu	1,r4
344	lwz	r4,SL_DBAT1+4(r1)
345	mtdbatl	1,r4
346	lwz	r4,SL_DBAT2(r1)
347	mtdbatu	2,r4
348	lwz	r4,SL_DBAT2+4(r1)
349	mtdbatl	2,r4
350	lwz	r4,SL_DBAT3(r1)
351	mtdbatu	3,r4
352	lwz	r4,SL_DBAT3+4(r1)
353	mtdbatl	3,r4
354	lwz	r4,SL_IBAT0(r1)
355	mtibatu	0,r4
356	lwz	r4,SL_IBAT0+4(r1)
357	mtibatl	0,r4
358	lwz	r4,SL_IBAT1(r1)
359	mtibatu	1,r4
360	lwz	r4,SL_IBAT1+4(r1)
361	mtibatl	1,r4
362	lwz	r4,SL_IBAT2(r1)
363	mtibatu	2,r4
364	lwz	r4,SL_IBAT2+4(r1)
365	mtibatl	2,r4
366	lwz	r4,SL_IBAT3(r1)
367	mtibatu	3,r4
368	lwz	r4,SL_IBAT3+4(r1)
369	mtibatl	3,r4
370
371BEGIN_MMU_FTR_SECTION
372	lwz	r4,SL_DBAT4(r1)
373	mtspr	SPRN_DBAT4U,r4
374	lwz	r4,SL_DBAT4+4(r1)
375	mtspr	SPRN_DBAT4L,r4
376	lwz	r4,SL_DBAT5(r1)
377	mtspr	SPRN_DBAT5U,r4
378	lwz	r4,SL_DBAT5+4(r1)
379	mtspr	SPRN_DBAT5L,r4
380	lwz	r4,SL_DBAT6(r1)
381	mtspr	SPRN_DBAT6U,r4
382	lwz	r4,SL_DBAT6+4(r1)
383	mtspr	SPRN_DBAT6L,r4
384	lwz	r4,SL_DBAT7(r1)
385	mtspr	SPRN_DBAT7U,r4
386	lwz	r4,SL_DBAT7+4(r1)
387	mtspr	SPRN_DBAT7L,r4
388	lwz	r4,SL_IBAT4(r1)
389	mtspr	SPRN_IBAT4U,r4
390	lwz	r4,SL_IBAT4+4(r1)
391	mtspr	SPRN_IBAT4L,r4
392	lwz	r4,SL_IBAT5(r1)
393	mtspr	SPRN_IBAT5U,r4
394	lwz	r4,SL_IBAT5+4(r1)
395	mtspr	SPRN_IBAT5L,r4
396	lwz	r4,SL_IBAT6(r1)
397	mtspr	SPRN_IBAT6U,r4
398	lwz	r4,SL_IBAT6+4(r1)
399	mtspr	SPRN_IBAT6L,r4
400	lwz	r4,SL_IBAT7(r1)
401	mtspr	SPRN_IBAT7U,r4
402	lwz	r4,SL_IBAT7+4(r1)
403	mtspr	SPRN_IBAT7L,r4
404END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
405
406	/* Flush all TLBs */
407	lis	r4,0x1000
4081:	addic.	r4,r4,-0x1000
409	tlbie	r4
410	blt	1b
411	sync
412
413	/* restore the MSR and turn on the MMU */
414	lwz	r3,SL_MSR(r1)
415	bl	turn_on_mmu
416
417	/* get back the stack pointer */
418	tovirt(r1,r1)
419
420	/* Restore TB */
421	li	r3,0
422	mttbl	r3
423	lwz	r3,SL_TB(r1)
424	lwz	r4,SL_TB+4(r1)
425	mttbu	r3
426	mttbl	r4
427
428	/* Restore the callee-saved registers and return */
429	lwz	r0,SL_CR(r1)
430	mtcr	r0
431	lwz	r2,SL_R2(r1)
432	lmw	r12,SL_R12(r1)
433	addi	r1,r1,SL_SIZE
434	lwz	r0,4(r1)
435	mtlr	r0
436	blr
437
438turn_on_mmu:
439	mflr	r4
440	tovirt(r4,r4)
441	mtsrr0	r4
442	mtsrr1	r3
443	sync
444	isync
445	rfi
446
447#endif /* defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ) */
448
449	.section .data
450	.balign	L1_CACHE_BYTES
451sleep_storage:
452	.long 0
453	.balign	L1_CACHE_BYTES, 0
454
455#endif /* CONFIG_6xx */
456	.section .text
457