Merge branch 'for-greg' of git://gitorious.org/usb/usb into usb-linus
[pandora-kernel.git] / arch / powerpc / kernel / swsusp_32.S
1 #include <linux/threads.h>
2 #include <asm/processor.h>
3 #include <asm/page.h>
4 #include <asm/cputable.h>
5 #include <asm/thread_info.h>
6 #include <asm/ppc_asm.h>
7 #include <asm/asm-offsets.h>
8 #include <asm/mmu.h>
9
10 /*
11  * Structure for storing CPU registers on the save area.
12  */
13 #define SL_SP           0
14 #define SL_PC           4
15 #define SL_MSR          8
16 #define SL_SDR1         0xc
17 #define SL_SPRG0        0x10    /* 4 sprg's */
18 #define SL_DBAT0        0x20
19 #define SL_IBAT0        0x28
20 #define SL_DBAT1        0x30
21 #define SL_IBAT1        0x38
22 #define SL_DBAT2        0x40
23 #define SL_IBAT2        0x48
24 #define SL_DBAT3        0x50
25 #define SL_IBAT3        0x58
26 #define SL_TB           0x60
27 #define SL_R2           0x68
28 #define SL_CR           0x6c
29 #define SL_LR           0x70
30 #define SL_R12          0x74    /* r12 to r31 */
31 #define SL_SIZE         (SL_R12 + 80)
32
33         .section .data
34         .align  5
35
36 _GLOBAL(swsusp_save_area)
37         .space  SL_SIZE
38
39
40         .section .text
41         .align  5
42
43 _GLOBAL(swsusp_arch_suspend)
44
45         lis     r11,swsusp_save_area@h
46         ori     r11,r11,swsusp_save_area@l
47
48         mflr    r0
49         stw     r0,SL_LR(r11)
50         mfcr    r0
51         stw     r0,SL_CR(r11)
52         stw     r1,SL_SP(r11)
53         stw     r2,SL_R2(r11)
54         stmw    r12,SL_R12(r11)
55
56         /* Save MSR & SDR1 */
57         mfmsr   r4
58         stw     r4,SL_MSR(r11)
59         mfsdr1  r4
60         stw     r4,SL_SDR1(r11)
61
62         /* Get a stable timebase and save it */
63 1:      mftbu   r4
64         stw     r4,SL_TB(r11)
65         mftb    r5
66         stw     r5,SL_TB+4(r11)
67         mftbu   r3
68         cmpw    r3,r4
69         bne     1b
70
71         /* Save SPRGs */
72         mfsprg  r4,0
73         stw     r4,SL_SPRG0(r11)
74         mfsprg  r4,1
75         stw     r4,SL_SPRG0+4(r11)
76         mfsprg  r4,2
77         stw     r4,SL_SPRG0+8(r11)
78         mfsprg  r4,3
79         stw     r4,SL_SPRG0+12(r11)
80
81         /* Save BATs */
82         mfdbatu r4,0
83         stw     r4,SL_DBAT0(r11)
84         mfdbatl r4,0
85         stw     r4,SL_DBAT0+4(r11)
86         mfdbatu r4,1
87         stw     r4,SL_DBAT1(r11)
88         mfdbatl r4,1
89         stw     r4,SL_DBAT1+4(r11)
90         mfdbatu r4,2
91         stw     r4,SL_DBAT2(r11)
92         mfdbatl r4,2
93         stw     r4,SL_DBAT2+4(r11)
94         mfdbatu r4,3
95         stw     r4,SL_DBAT3(r11)
96         mfdbatl r4,3
97         stw     r4,SL_DBAT3+4(r11)
98         mfibatu r4,0
99         stw     r4,SL_IBAT0(r11)
100         mfibatl r4,0
101         stw     r4,SL_IBAT0+4(r11)
102         mfibatu r4,1
103         stw     r4,SL_IBAT1(r11)
104         mfibatl r4,1
105         stw     r4,SL_IBAT1+4(r11)
106         mfibatu r4,2
107         stw     r4,SL_IBAT2(r11)
108         mfibatl r4,2
109         stw     r4,SL_IBAT2+4(r11)
110         mfibatu r4,3
111         stw     r4,SL_IBAT3(r11)
112         mfibatl r4,3
113         stw     r4,SL_IBAT3+4(r11)
114
115 #if  0
116         /* Backup various CPU config stuffs */
117         bl      __save_cpu_setup
118 #endif
119         /* Call the low level suspend stuff (we should probably have made
120          * a stackframe...
121          */
122         bl      swsusp_save
123
124         /* Restore LR from the save area */
125         lis     r11,swsusp_save_area@h
126         ori     r11,r11,swsusp_save_area@l
127         lwz     r0,SL_LR(r11)
128         mtlr    r0
129
130         blr
131
132
133 /* Resume code */
134 _GLOBAL(swsusp_arch_resume)
135
136 #ifdef CONFIG_ALTIVEC
137         /* Stop pending alitvec streams and memory accesses */
138 BEGIN_FTR_SECTION
139         DSSALL
140 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
141 #endif
142         sync
143
144         /* Disable MSR:DR to make sure we don't take a TLB or
145          * hash miss during the copy, as our hash table will
146          * for a while be unusable. For .text, we assume we are
147          * covered by a BAT. This works only for non-G5 at this
148          * point. G5 will need a better approach, possibly using
149          * a small temporary hash table filled with large mappings,
150          * disabling the MMU completely isn't a good option for
151          * performance reasons.
152          * (Note that 750's may have the same performance issue as
153          * the G5 in this case, we should investigate using moving
154          * BATs for these CPUs)
155          */
156         mfmsr   r0
157         sync
158         rlwinm  r0,r0,0,28,26           /* clear MSR_DR */
159         mtmsr   r0
160         sync
161         isync
162
163         /* Load ptr the list of pages to copy in r3 */
164         lis     r11,(restore_pblist - KERNELBASE)@h
165         ori     r11,r11,restore_pblist@l
166         lwz     r10,0(r11)
167
168         /* Copy the pages. This is a very basic implementation, to
169          * be replaced by something more cache efficient */
170 1:
171         tophys(r3,r10)
172         li      r0,256
173         mtctr   r0
174         lwz     r11,pbe_address(r3)     /* source */
175         tophys(r5,r11)
176         lwz     r10,pbe_orig_address(r3)        /* destination */
177         tophys(r6,r10)
178 2:
179         lwz     r8,0(r5)
180         lwz     r9,4(r5)
181         lwz     r10,8(r5)
182         lwz     r11,12(r5)
183         addi    r5,r5,16
184         stw     r8,0(r6)
185         stw     r9,4(r6)
186         stw     r10,8(r6)
187         stw     r11,12(r6)
188         addi    r6,r6,16
189         bdnz    2b
190         lwz             r10,pbe_next(r3)
191         cmpwi   0,r10,0
192         bne     1b
193
194         /* Do a very simple cache flush/inval of the L1 to ensure
195          * coherency of the icache
196          */
197         lis     r3,0x0002
198         mtctr   r3
199         li      r3, 0
200 1:
201         lwz     r0,0(r3)
202         addi    r3,r3,0x0020
203         bdnz    1b
204         isync
205         sync
206
207         /* Now flush those cache lines */
208         lis     r3,0x0002
209         mtctr   r3
210         li      r3, 0
211 1:
212         dcbf    0,r3
213         addi    r3,r3,0x0020
214         bdnz    1b
215         sync
216
217         /* Ok, we are now running with the kernel data of the old
218          * kernel fully restored. We can get to the save area
219          * easily now. As for the rest of the code, it assumes the
220          * loader kernel and the booted one are exactly identical
221          */
222         lis     r11,swsusp_save_area@h
223         ori     r11,r11,swsusp_save_area@l
224         tophys(r11,r11)
225
226 #if 0
227         /* Restore various CPU config stuffs */
228         bl      __restore_cpu_setup
229 #endif
230         /* Restore the BATs, and SDR1.  Then we can turn on the MMU.
231          * This is a bit hairy as we are running out of those BATs,
232          * but first, our code is probably in the icache, and we are
233          * writing the same value to the BAT, so that should be fine,
234          * though a better solution will have to be found long-term
235          */
236         lwz     r4,SL_SDR1(r11)
237         mtsdr1  r4
238         lwz     r4,SL_SPRG0(r11)
239         mtsprg  0,r4
240         lwz     r4,SL_SPRG0+4(r11)
241         mtsprg  1,r4
242         lwz     r4,SL_SPRG0+8(r11)
243         mtsprg  2,r4
244         lwz     r4,SL_SPRG0+12(r11)
245         mtsprg  3,r4
246
247 #if 0
248         lwz     r4,SL_DBAT0(r11)
249         mtdbatu 0,r4
250         lwz     r4,SL_DBAT0+4(r11)
251         mtdbatl 0,r4
252         lwz     r4,SL_DBAT1(r11)
253         mtdbatu 1,r4
254         lwz     r4,SL_DBAT1+4(r11)
255         mtdbatl 1,r4
256         lwz     r4,SL_DBAT2(r11)
257         mtdbatu 2,r4
258         lwz     r4,SL_DBAT2+4(r11)
259         mtdbatl 2,r4
260         lwz     r4,SL_DBAT3(r11)
261         mtdbatu 3,r4
262         lwz     r4,SL_DBAT3+4(r11)
263         mtdbatl 3,r4
264         lwz     r4,SL_IBAT0(r11)
265         mtibatu 0,r4
266         lwz     r4,SL_IBAT0+4(r11)
267         mtibatl 0,r4
268         lwz     r4,SL_IBAT1(r11)
269         mtibatu 1,r4
270         lwz     r4,SL_IBAT1+4(r11)
271         mtibatl 1,r4
272         lwz     r4,SL_IBAT2(r11)
273         mtibatu 2,r4
274         lwz     r4,SL_IBAT2+4(r11)
275         mtibatl 2,r4
276         lwz     r4,SL_IBAT3(r11)
277         mtibatu 3,r4
278         lwz     r4,SL_IBAT3+4(r11)
279         mtibatl 3,r4
280 #endif
281
282 BEGIN_MMU_FTR_SECTION
283         li      r4,0
284         mtspr   SPRN_DBAT4U,r4
285         mtspr   SPRN_DBAT4L,r4
286         mtspr   SPRN_DBAT5U,r4
287         mtspr   SPRN_DBAT5L,r4
288         mtspr   SPRN_DBAT6U,r4
289         mtspr   SPRN_DBAT6L,r4
290         mtspr   SPRN_DBAT7U,r4
291         mtspr   SPRN_DBAT7L,r4
292         mtspr   SPRN_IBAT4U,r4
293         mtspr   SPRN_IBAT4L,r4
294         mtspr   SPRN_IBAT5U,r4
295         mtspr   SPRN_IBAT5L,r4
296         mtspr   SPRN_IBAT6U,r4
297         mtspr   SPRN_IBAT6L,r4
298         mtspr   SPRN_IBAT7U,r4
299         mtspr   SPRN_IBAT7L,r4
300 END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
301
302         /* Flush all TLBs */
303         lis     r4,0x1000
304 1:      addic.  r4,r4,-0x1000
305         tlbie   r4
306         bgt     1b
307         sync
308
309         /* restore the MSR and turn on the MMU */
310         lwz     r3,SL_MSR(r11)
311         bl      turn_on_mmu
312         tovirt(r11,r11)
313
314         /* Restore TB */
315         li      r3,0
316         mttbl   r3
317         lwz     r3,SL_TB(r11)
318         lwz     r4,SL_TB+4(r11)
319         mttbu   r3
320         mttbl   r4
321
322         /* Kick decrementer */
323         li      r0,1
324         mtdec   r0
325
326         /* Restore the callee-saved registers and return */
327         lwz     r0,SL_CR(r11)
328         mtcr    r0
329         lwz     r2,SL_R2(r11)
330         lmw     r12,SL_R12(r11)
331         lwz     r1,SL_SP(r11)
332         lwz     r0,SL_LR(r11)
333         mtlr    r0
334
335         // XXX Note: we don't really need to call swsusp_resume
336
337         li      r3,0
338         blr
339
340 /* FIXME:This construct is actually not useful since we don't shut
341  * down the instruction MMU, we could just flip back MSR-DR on.
342  */
343 turn_on_mmu:
344         mflr    r4
345         mtsrr0  r4
346         mtsrr1  r3
347         sync
348         isync
349         rfi
350