Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[linux/fpc-iii.git] / arch / powerpc / kernel / swsusp_booke.S
blob553c1405ee05774b49f355a7c3bfcedc1e7a69f9
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         mfspr   r4,SPRN_SPRG0
78         stw     r4,SL_SPRG0(r11)
79         mfspr   r4,SPRN_SPRG1
80         stw     r4,SL_SPRG1(r11)
81         mfspr   r4,SPRN_SPRG2
82         stw     r4,SL_SPRG2(r11)
83         mfspr   r4,SPRN_SPRG3
84         stw     r4,SL_SPRG3(r11)
85         mfspr   r4,SPRN_SPRG4
86         stw     r4,SL_SPRG4(r11)
87         mfspr   r4,SPRN_SPRG5
88         stw     r4,SL_SPRG5(r11)
89         mfspr   r4,SPRN_SPRG6
90         stw     r4,SL_SPRG6(r11)
91         mfspr   r4,SPRN_SPRG7
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         /*
145          * Mappings from virtual addresses to physical addresses may be
146          * different than they were prior to restoring hibernation state. 
147          * Invalidate the TLB so that the boot CPU is using the new
148          * mappings.
149          */
150         bl      _tlbil_all
152         lwz     r4,SL_SPRG0(r11)
153         mtspr   SPRN_SPRG0,r4
154         lwz     r4,SL_SPRG1(r11)
155         mtspr   SPRN_SPRG1,r4
156         lwz     r4,SL_SPRG2(r11)
157         mtspr   SPRN_SPRG2,r4
158         lwz     r4,SL_SPRG3(r11)
159         mtspr   SPRN_SPRG3,r4
160         lwz     r4,SL_SPRG4(r11)
161         mtspr   SPRN_SPRG4,r4
162         lwz     r4,SL_SPRG5(r11)
163         mtspr   SPRN_SPRG5,r4
164         lwz     r4,SL_SPRG6(r11)
165         mtspr   SPRN_SPRG6,r4
166         lwz     r4,SL_SPRG7(r11)
167         mtspr   SPRN_SPRG7,r4
169         /* restore the MSR */
170         lwz     r3,SL_MSR(r11)
171         mtmsr   r3
173         /* Restore TB */
174         li      r3,0
175         mtspr   SPRN_TBWL,r3
176         lwz     r3,SL_TBU(r11)
177         lwz     r4,SL_TBL(r11)
178         mtspr   SPRN_TBWU,r3
179         mtspr   SPRN_TBWL,r4
181         /* Restore TCR and clear any pending bits in TSR. */
182         lwz     r4,SL_TCR(r11)
183         mtspr   SPRN_TCR,r4
184         lis     r4, (TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS)@h
185         mtspr   SPRN_TSR,r4
187         /* Kick decrementer */
188         li      r0,1
189         mtdec   r0
191         /* Restore the callee-saved registers and return */
192         lwz     r0,SL_CR(r11)
193         mtcr    r0
194         lwz     r2,SL_R2(r11)
195         lmw     r12,SL_R12(r11)
196         lwz     r1,SL_SP(r11)
197         lwz     r0,SL_LR(r11)
198         mtlr    r0
200         li      r3,0
201         blr