Merge git://git.infradead.org/mtd-2.6
[linux-2.6] / arch / powerpc / kernel / swsusp_asm64.S
1 /*
2  * PowerPC 64-bit swsusp implementation
3  *
4  * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5  *
6  * GPLv2
7  */
8
9 #include <linux/threads.h>
10 #include <asm/processor.h>
11 #include <asm/page.h>
12 #include <asm/cputable.h>
13 #include <asm/thread_info.h>
14 #include <asm/ppc_asm.h>
15 #include <asm/asm-offsets.h>
16
17 /*
18  * Structure for storing CPU registers on the save area.
19  */
20 #define SL_r1           0x00    /* stack pointer */
21 #define SL_PC           0x08
22 #define SL_MSR          0x10
23 #define SL_SDR1         0x18
24 #define SL_XER          0x20
25 #define SL_TB           0x40
26 #define SL_r2           0x48
27 #define SL_CR           0x50
28 #define SL_LR           0x58
29 #define SL_r12          0x60
30 #define SL_r13          0x68
31 #define SL_r14          0x70
32 #define SL_r15          0x78
33 #define SL_r16          0x80
34 #define SL_r17          0x88
35 #define SL_r18          0x90
36 #define SL_r19          0x98
37 #define SL_r20          0xa0
38 #define SL_r21          0xa8
39 #define SL_r22          0xb0
40 #define SL_r23          0xb8
41 #define SL_r24          0xc0
42 #define SL_r25          0xc8
43 #define SL_r26          0xd0
44 #define SL_r27          0xd8
45 #define SL_r28          0xe0
46 #define SL_r29          0xe8
47 #define SL_r30          0xf0
48 #define SL_r31          0xf8
49 #define SL_SIZE         SL_r31+8
50
51 /* these macros rely on the save area being
52  * pointed to by r11 */
53 #define SAVE_SPECIAL(special)           \
54         mf##special     r0              ;\
55         std     r0, SL_##special(r11)
56 #define RESTORE_SPECIAL(special)        \
57         ld      r0, SL_##special(r11)   ;\
58         mt##special     r0
59 #define SAVE_REGISTER(reg)              \
60         std     reg, SL_##reg(r11)
61 #define RESTORE_REGISTER(reg)           \
62         ld      reg, SL_##reg(r11)
63
64 /* space for storing cpu state */
65         .section .data
66         .align  5
67 swsusp_save_area:
68         .space SL_SIZE
69
70         .section ".toc","aw"
71 swsusp_save_area_ptr:
72         .tc     swsusp_save_area[TC],swsusp_save_area
73 restore_pblist_ptr:
74         .tc     restore_pblist[TC],restore_pblist
75
76         .section .text
77         .align  5
78 _GLOBAL(swsusp_arch_suspend)
79         ld      r11,swsusp_save_area_ptr@toc(r2)
80         SAVE_SPECIAL(LR)
81         SAVE_REGISTER(r1)
82         SAVE_SPECIAL(CR)
83         SAVE_SPECIAL(TB)
84         SAVE_REGISTER(r2)
85         SAVE_REGISTER(r12)
86         SAVE_REGISTER(r13)
87         SAVE_REGISTER(r14)
88         SAVE_REGISTER(r15)
89         SAVE_REGISTER(r16)
90         SAVE_REGISTER(r17)
91         SAVE_REGISTER(r18)
92         SAVE_REGISTER(r19)
93         SAVE_REGISTER(r20)
94         SAVE_REGISTER(r21)
95         SAVE_REGISTER(r22)
96         SAVE_REGISTER(r23)
97         SAVE_REGISTER(r24)
98         SAVE_REGISTER(r25)
99         SAVE_REGISTER(r26)
100         SAVE_REGISTER(r27)
101         SAVE_REGISTER(r28)
102         SAVE_REGISTER(r29)
103         SAVE_REGISTER(r30)
104         SAVE_REGISTER(r31)
105         SAVE_SPECIAL(MSR)
106         SAVE_SPECIAL(SDR1)
107         SAVE_SPECIAL(XER)
108
109         /* we push the stack up 128 bytes but don't store the
110          * stack pointer on the stack like a real stackframe */
111         addi    r1,r1,-128
112
113         bl _iommu_save
114         bl swsusp_save
115
116         /* restore LR */
117         ld      r11,swsusp_save_area_ptr@toc(r2)
118         RESTORE_SPECIAL(LR)
119         addi    r1,r1,128
120
121         blr
122
123 /* Resume code */
124 _GLOBAL(swsusp_arch_resume)
125         /* Stop pending alitvec streams and memory accesses */
126 BEGIN_FTR_SECTION
127         DSSALL
128 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
129         sync
130
131         ld      r12,restore_pblist_ptr@toc(r2)
132         ld      r12,0(r12)
133
134         cmpdi   r12,0
135         beq-    nothing_to_copy
136         li      r15,PAGE_SIZE>>3
137 copyloop:
138         ld      r13,pbe_address(r12)
139         ld      r14,pbe_orig_address(r12)
140
141         mtctr   r15
142         li      r10,0
143 copy_page_loop:
144         ldx     r0,r10,r13
145         stdx    r0,r10,r14
146         addi    r10,r10,8
147         bdnz copy_page_loop
148
149         ld      r12,pbe_next(r12)
150         cmpdi   r12,0
151         bne+    copyloop
152 nothing_to_copy:
153
154         /* flush caches */
155         lis     r3, 0x10
156         mtctr   r3
157         li      r3, 0
158         ori     r3, r3, CONFIG_KERNEL_START>>48
159         li      r0, 48
160         sld     r3, r3, r0
161         li      r0, 0
162 1:
163         dcbf    r0,r3
164         addi    r3,r3,0x20
165         bdnz    1b
166
167         sync
168
169         tlbia
170
171         ld      r11,swsusp_save_area_ptr@toc(r2)
172
173         RESTORE_SPECIAL(CR)
174
175         /* restore timebase */
176         /* load saved tb */
177         ld      r1, SL_TB(r11)
178         /* get upper 32 bits of it */
179         srdi    r2, r1, 32
180         /* clear tb lower to avoid wrap */
181         li      r0, 0
182         mttbl   r0
183         /* set tb upper */
184         mttbu   r2
185         /* set tb lower */
186         mttbl   r1
187
188         /* restore registers */
189         RESTORE_REGISTER(r1)
190         RESTORE_REGISTER(r2)
191         RESTORE_REGISTER(r12)
192         RESTORE_REGISTER(r13)
193         RESTORE_REGISTER(r14)
194         RESTORE_REGISTER(r15)
195         RESTORE_REGISTER(r16)
196         RESTORE_REGISTER(r17)
197         RESTORE_REGISTER(r18)
198         RESTORE_REGISTER(r19)
199         RESTORE_REGISTER(r20)
200         RESTORE_REGISTER(r21)
201         RESTORE_REGISTER(r22)
202         RESTORE_REGISTER(r23)
203         RESTORE_REGISTER(r24)
204         RESTORE_REGISTER(r25)
205         RESTORE_REGISTER(r26)
206         RESTORE_REGISTER(r27)
207         RESTORE_REGISTER(r28)
208         RESTORE_REGISTER(r29)
209         RESTORE_REGISTER(r30)
210         RESTORE_REGISTER(r31)
211         /* can't use RESTORE_SPECIAL(MSR) */
212         ld      r0, SL_MSR(r11)
213         mtmsrd  r0, 0
214         RESTORE_SPECIAL(SDR1)
215         RESTORE_SPECIAL(XER)
216
217         sync
218
219         addi    r1,r1,-128
220         bl      slb_flush_and_rebolt
221         bl      do_after_copyback
222         addi    r1,r1,128
223
224         ld      r11,swsusp_save_area_ptr@toc(r2)
225         RESTORE_SPECIAL(LR)
226
227         li      r3, 0
228         blr