* better
[mascara-docs.git] / i386 / linux-2.3.21 / arch / ppc / kernel / sleep.S
blob3ead7bd28eb6800a3d3c574a05e8bf19b3988009
1 /*
2  * This file contains sleep low-level functions for PowerBook G3.
3  *    Copyright (C) 1999 Benjamin Herrenschmidt (bh40@calva.net)
4  *    and Paul Mackerras (paulus@cs.anu.edu.au).
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  */
13 #include "ppc_asm.tmpl"
14 #include <asm/processor.h>
15 #include <asm/page.h>
17 #define MAGIC   0x4c617273      /* 'Lars' */
20  * Structure for storing CPU registers on the stack.
21  */
22 #define SL_SP           0
23 #define SL_PC           4
24 #define SL_MSR          8
25 #define SL_SDR1         0xc
26 #define SL_SPRG0        0x10    /* 4 sprg's */
27 #define SL_DBAT0        0x20
28 #define SL_IBAT0        0x28
29 #define SL_DBAT1        0x30
30 #define SL_IBAT1        0x38
31 #define SL_DBAT2        0x40
32 #define SL_IBAT2        0x48
33 #define SL_DBAT3        0x50
34 #define SL_IBAT3        0x58
35 #define SL_TB           0x60
36 #define SL_HID0         0x68
37 #define SL_R2           0x6c
38 #define SL_R12          0x70    /* r12 to r31 */
39 #define SL_SIZE         (SL_R12 + 80)
41 #define tophys(rd,rs)   addis   rd,rs,-KERNELBASE@h     
42 #define tovirt(rd,rs)   addis   rd,rs,KERNELBASE@h
44         .text
46 _GLOBAL(low_sleep_handler)
47         mflr    r0
48         stw     r0,4(r1)
49         stwu    r1,-SL_SIZE(r1)
50         stw     r2,SL_R2(r1)
51         stmw    r12,SL_R12(r1)
53         /* Save MSR, SDR1, TB  */
54         mfmsr   r4
55         stw     r4,SL_MSR(r1)
56         mfsdr1  r4
57         stw     r4,SL_SDR1(r1)
58 1:      
59         mftbu   r4
60         stw     r4,SL_TB(r1)
61         mftb    r5
62         stw     r5,SL_TB+4(r1)
63         mftbu   r3
64         cmpw    r3,r4
65         bne     1b
66         
67         /* Save SPRGs */
68         mfsprg  r4,0
69         stw     r4,SL_SPRG0(r1)
70         mfsprg  r4,1
71         stw     r4,SL_SPRG0+4(r1)
72         mfsprg  r4,2
73         stw     r4,SL_SPRG0+8(r1)
74         mfsprg  r4,3
75         stw     r4,SL_SPRG0+12(r1)
77         /* Save BATs */
78         mfdbatu r4,0
79         stw     r4,SL_DBAT0(r1)
80         mfdbatl r4,0
81         stw     r4,SL_DBAT0+4(r1)
82         mfdbatu r4,1
83         stw     r4,SL_DBAT1(r1)
84         mfdbatl r4,1
85         stw     r4,SL_DBAT1+4(r1)
86         mfdbatu r4,2
87         stw     r4,SL_DBAT2(r1)
88         mfdbatl r4,2
89         stw     r4,SL_DBAT2+4(r1)
90         mfdbatu r4,3
91         stw     r4,SL_DBAT3(r1)
92         mfdbatl r4,3
93         stw     r4,SL_DBAT3+4(r1)
94         mfibatu r4,0
95         stw     r4,SL_IBAT0(r1)
96         mfibatl r4,0
97         stw     r4,SL_IBAT0+4(r1)
98         mfibatu r4,1
99         stw     r4,SL_IBAT1(r1)
100         mfibatl r4,1
101         stw     r4,SL_IBAT1+4(r1)
102         mfibatu r4,2
103         stw     r4,SL_IBAT2(r1)
104         mfibatl r4,2
105         stw     r4,SL_IBAT2+4(r1)
106         mfibatu r4,3
107         stw     r4,SL_IBAT3(r1)
108         mfibatl r4,3
109         stw     r4,SL_IBAT3+4(r1)
111         /* Save HID0 */
112         mfspr   r4,HID0
113         stw     r4,SL_HID0(r1)
115         /* Set up stuff at address 0 */
116         lis     r5,wake_up@ha
117         addi    r5,r5,wake_up@l
118         tophys(r5,r5)
119         stw     r5,SL_PC(r1)
120         lis     r4,KERNELBASE@h
121         tophys(r5,r1)
122         addi    r5,r5,SL_PC
123         lis     r6,MAGIC@ha
124         addi    r6,r6,MAGIC@l
125         stw     r5,0(r4)
126         stw     r6,4(r4)
129  * Flush the L1 data cache by reading the first 64kB of RAM
130  * and then flushing the same area with the dcbf instruction.
131  * The L2 cache has already been disabled.
132  */
133         li      r4,0x0800       /* 64kB / 32B */
134         mtctr   r4
135         lis     r4,KERNELBASE@h
137         lwz     r0,0(r4)
138         addi    r4,r4,0x0020            /* Go to start of next cache line */
139         bdnz    1b
140         sync
141         
142         li      r4,0x0800       /* 64k */
143         mtctr   r4
144         lis     r4,KERNELBASE@h
146         dcbf    r0,r4
147         addi    r4,r4,0x0020    /* Go to start of next cache line */
148         bdnz    1b
149         sync
152  * Set the HID0 and MSR for sleep.
153  */
154         mfspr   r2,HID0
155         rlwinm  r2,r2,0,10,7    /* clear doze, nap */
156         oris    r2,r2,HID0_SLEEP@h
157         sync
158         mtspr   HID0,r2
159         sync
160         
161         mfmsr   r2
162         oris    r2,r2,MSR_POW@h
163 1:      sync
164         mtmsr   r2
165         isync
166         b       1b
168 /* 
169  * Here is the resume code.
170  * r1 has the physical address of SL_PC(sp).
171  */
172         
173 wake_up:
174         /* Restore the HID0 register.  This turns on the L1 caches. */
175         subi    r1,r1,SL_PC
176         lwz     r3,SL_HID0(r1)
177         sync
178         isync
179         mtspr   HID0,r3
180         sync
182         /* Restore the kernel's segment registers, the
183            BATs, and SDR1.  Then we can turn on the MMU. */
184         li      r0,16           /* load up segment register values */
185         mtctr   r0              /* for context 0 */
186         lis     r3,0x2000       /* Ku = 1, VSID = 0 */
187         li      r4,0
188 3:      mtsrin  r3,r4
189         addi    r3,r3,1         /* increment VSID */
190         addis   r4,r4,0x1000    /* address of next segment */
191         bdnz    3b
192         
193         lwz     r4,SL_SDR1(r1)
194         mtsdr1  r4
195         lwz     r4,SL_SPRG0(r1)
196         mtsprg  0,r4
197         lwz     r4,SL_SPRG0+4(r1)
198         mtsprg  1,r4
199         lwz     r4,SL_SPRG0+8(r1)
200         mtsprg  2,r4
201         lwz     r4,SL_SPRG0+12(r1)
202         mtsprg  3,r4
204         lwz     r4,SL_DBAT0(r1)
205         mtdbatu 0,r4
206         lwz     r4,SL_DBAT0+4(r1)
207         mtdbatl 0,r4
208         lwz     r4,SL_DBAT1(r1)
209         mtdbatu 1,r4
210         lwz     r4,SL_DBAT1+4(r1)
211         mtdbatl 1,r4
212         lwz     r4,SL_DBAT2(r1)
213         mtdbatu 2,r4
214         lwz     r4,SL_DBAT2+4(r1)
215         mtdbatl 2,r4
216         lwz     r4,SL_DBAT3(r1)
217         mtdbatu 3,r4
218         lwz     r4,SL_DBAT3+4(r1)
219         mtdbatl 3,r4
220         lwz     r4,SL_IBAT0(r1)
221         mtibatu 0,r4
222         lwz     r4,SL_IBAT0+4(r1)
223         mtibatl 0,r4
224         lwz     r4,SL_IBAT1(r1)
225         mtibatu 1,r4
226         lwz     r4,SL_IBAT1+4(r1)
227         mtibatl 1,r4
228         lwz     r4,SL_IBAT2(r1)
229         mtibatu 2,r4
230         lwz     r4,SL_IBAT2+4(r1)
231         mtibatl 2,r4
232         lwz     r4,SL_IBAT3(r1)
233         mtibatu 3,r4
234         lwz     r4,SL_IBAT3+4(r1)
235         mtibatl 3,r4
237         /* restore the MSR and turn on the MMU */
238         lwz     r3,SL_MSR(r1)
239         bl      turn_on_mmu     
241         /* get back the stack pointer */
242         tovirt(r1,r1)
244         /* Restore TB */
245         lwz     r3,SL_TB(r1)
246         lwz     r4,SL_TB+4(r1)
247         mttbu   r3
248         mttbl   r4
250         /* Restore the callee-saved registers and return */
251         lwz     r2,SL_R2(r1)
252         lmw     r12,SL_R12(r1)
253         addi    r1,r1,SL_SIZE
254         lwz     r0,4(r1)
255         mtlr    r0
256         blr
258 turn_on_mmu:
259         mflr    r4
260         tovirt(r4,r4)
261         mtsrr0  r4
262         mtsrr1  r3
263         sync
264         rfi