Linux 2.6.39-rc2
[pohmelfs.git] / arch / powerpc / kernel / swsusp_booke.S
blob11a39307dd714b0602b9f7e3e4f540345057b71c
1 /*
2  * Based on swsusp_32.S, modified for FSL BookE by
3  * Anton Vorontsov <avorontsov@ru.mvista.com>
4  * Copyright (c) 2009-2010 MontaVista Software, LLC.
5  */
7 #include <linux/threads.h>
8 #include <asm/processor.h>
9 #include <asm/page.h>
10 #include <asm/cputable.h>
11 #include <asm/thread_info.h>
12 #include <asm/ppc_asm.h>
13 #include <asm/asm-offsets.h>
14 #include <asm/mmu.h>
17  * Structure for storing CPU registers on the save area.
18  */
19 #define SL_SP           0
20 #define SL_PC           4
21 #define SL_MSR          8
22 #define SL_TCR          0xc
23 #define SL_SPRG0        0x10
24 #define SL_SPRG1        0x14
25 #define SL_SPRG2        0x18
26 #define SL_SPRG3        0x1c
27 #define SL_SPRG4        0x20
28 #define SL_SPRG5        0x24
29 #define SL_SPRG6        0x28
30 #define SL_SPRG7        0x2c
31 #define SL_TBU          0x30
32 #define SL_TBL          0x34
33 #define SL_R2           0x38
34 #define SL_CR           0x3c
35 #define SL_LR           0x40
36 #define SL_R12          0x44    /* r12 to r31 */
37 #define SL_SIZE         (SL_R12 + 80)
39         .section .data
40         .align  5
42 _GLOBAL(swsusp_save_area)
43         .space  SL_SIZE
46         .section .text
47         .align  5
49 _GLOBAL(swsusp_arch_suspend)
50         lis     r11,swsusp_save_area@h
51         ori     r11,r11,swsusp_save_area@l
53         mflr    r0
54         stw     r0,SL_LR(r11)
55         mfcr    r0
56         stw     r0,SL_CR(r11)
57         stw     r1,SL_SP(r11)
58         stw     r2,SL_R2(r11)
59         stmw    r12,SL_R12(r11)
61         /* Save MSR & TCR */
62         mfmsr   r4
63         stw     r4,SL_MSR(r11)
64         mfspr   r4,SPRN_TCR
65         stw     r4,SL_TCR(r11)
67         /* Get a stable timebase and save it */
68 1:      mfspr   r4,SPRN_TBRU
69         stw     r4,SL_TBU(r11)
70         mfspr   r5,SPRN_TBRL
71         stw     r5,SL_TBL(r11)
72         mfspr   r3,SPRN_TBRU
73         cmpw    r3,r4
74         bne     1b
76         /* Save SPRGs */
77         mfsprg  r4,0
78         stw     r4,SL_SPRG0(r11)
79         mfsprg  r4,1
80         stw     r4,SL_SPRG1(r11)
81         mfsprg  r4,2
82         stw     r4,SL_SPRG2(r11)
83         mfsprg  r4,3
84         stw     r4,SL_SPRG3(r11)
85         mfsprg  r4,4
86         stw     r4,SL_SPRG4(r11)
87         mfsprg  r4,5
88         stw     r4,SL_SPRG5(r11)
89         mfsprg  r4,6
90         stw     r4,SL_SPRG6(r11)
91         mfsprg  r4,7
92         stw     r4,SL_SPRG7(r11)
94         /* Call the low level suspend stuff (we should probably have made
95          * a stackframe...
96          */
97         bl      swsusp_save
99         /* Restore LR from the save area */
100         lis     r11,swsusp_save_area@h
101         ori     r11,r11,swsusp_save_area@l
102         lwz     r0,SL_LR(r11)
103         mtlr    r0
105         blr
107 _GLOBAL(swsusp_arch_resume)
108         sync
110         /* Load ptr the list of pages to copy in r3 */
111         lis     r11,(restore_pblist)@h
112         ori     r11,r11,restore_pblist@l
113         lwz     r3,0(r11)
115         /* Copy the pages. This is a very basic implementation, to
116          * be replaced by something more cache efficient */
118         li      r0,256
119         mtctr   r0
120         lwz     r5,pbe_address(r3)      /* source */
121         lwz     r6,pbe_orig_address(r3) /* destination */
123         lwz     r8,0(r5)
124         lwz     r9,4(r5)
125         lwz     r10,8(r5)
126         lwz     r11,12(r5)
127         addi    r5,r5,16
128         stw     r8,0(r6)
129         stw     r9,4(r6)
130         stw     r10,8(r6)
131         stw     r11,12(r6)
132         addi    r6,r6,16
133         bdnz    2b
134         lwz     r3,pbe_next(r3)
135         cmpwi   0,r3,0
136         bne     1b
138         bl flush_dcache_L1
139         bl flush_instruction_cache
141         lis     r11,swsusp_save_area@h
142         ori     r11,r11,swsusp_save_area@l
144         lwz     r4,SL_SPRG0(r11)
145         mtsprg  0,r4
146         lwz     r4,SL_SPRG1(r11)
147         mtsprg  1,r4
148         lwz     r4,SL_SPRG2(r11)
149         mtsprg  2,r4
150         lwz     r4,SL_SPRG3(r11)
151         mtsprg  3,r4
152         lwz     r4,SL_SPRG4(r11)
153         mtsprg  4,r4
154         lwz     r4,SL_SPRG5(r11)
155         mtsprg  5,r4
156         lwz     r4,SL_SPRG6(r11)
157         mtsprg  6,r4
158         lwz     r4,SL_SPRG7(r11)
159         mtsprg  7,r4
161         /* restore the MSR */
162         lwz     r3,SL_MSR(r11)
163         mtmsr   r3
165         /* Restore TB */
166         li      r3,0
167         mtspr   SPRN_TBWL,r3
168         lwz     r3,SL_TBU(r11)
169         lwz     r4,SL_TBL(r11)
170         mtspr   SPRN_TBWU,r3
171         mtspr   SPRN_TBWL,r4
173         /* Restore TCR and clear any pending bits in TSR. */
174         lwz     r4,SL_TCR(r11)
175         mtspr   SPRN_TCR,r4
176         lis     r4, (TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS)@h
177         mtspr   SPRN_TSR,r4
179         /* Kick decrementer */
180         li      r0,1
181         mtdec   r0
183         /* Restore the callee-saved registers and return */
184         lwz     r0,SL_CR(r11)
185         mtcr    r0
186         lwz     r2,SL_R2(r11)
187         lmw     r12,SL_R12(r11)
188         lwz     r1,SL_SP(r11)
189         lwz     r0,SL_LR(r11)
190         mtlr    r0
192         li      r3,0
193         blr