]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/arm/mach-at91/pm_suspend.S
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi...
[karo-tx-linux.git] / arch / arm / mach-at91 / pm_suspend.S
1 /*
2  * arch/arm/mach-at91/pm_slow_clock.S
3  *
4  *  Copyright (C) 2006 Savin Zlobec
5  *
6  * AT91SAM9 support:
7  *  Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  *
13  */
14 #include <linux/linkage.h>
15 #include <linux/clk/at91_pmc.h>
16 #include "pm.h"
17 #include "generated/at91_pm_data-offsets.h"
18
19 #define SRAMC_SELF_FRESH_ACTIVE         0x01
20 #define SRAMC_SELF_FRESH_EXIT           0x00
21
22 pmc     .req    r0
23 tmp1    .req    r4
24 tmp2    .req    r5
25
26 /*
27  * Wait until master clock is ready (after switching master clock source)
28  */
29         .macro wait_mckrdy
30 1:      ldr     tmp1, [pmc, #AT91_PMC_SR]
31         tst     tmp1, #AT91_PMC_MCKRDY
32         beq     1b
33         .endm
34
35 /*
36  * Wait until master oscillator has stabilized.
37  */
38         .macro wait_moscrdy
39 1:      ldr     tmp1, [pmc, #AT91_PMC_SR]
40         tst     tmp1, #AT91_PMC_MOSCS
41         beq     1b
42         .endm
43
44 /*
45  * Wait until PLLA has locked.
46  */
47         .macro wait_pllalock
48 1:      ldr     tmp1, [pmc, #AT91_PMC_SR]
49         tst     tmp1, #AT91_PMC_LOCKA
50         beq     1b
51         .endm
52
53 /*
54  * Put the processor to enter the idle state
55  */
56         .macro at91_cpu_idle
57
58 #if defined(CONFIG_CPU_V7)
59         mov     tmp1, #AT91_PMC_PCK
60         str     tmp1, [pmc, #AT91_PMC_SCDR]
61
62         dsb
63
64         wfi             @ Wait For Interrupt
65 #else
66         mcr     p15, 0, tmp1, c7, c0, 4
67 #endif
68
69         .endm
70
71         .text
72
73         .arm
74
75 /*
76  * void at91_suspend_sram_fn(struct at91_pm_data*)
77  * @input param:
78  *      @r0: base address of struct at91_pm_data
79  */
80 /* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
81         .align 3
82 ENTRY(at91_pm_suspend_in_sram)
83         /* Save registers on stack */
84         stmfd   sp!, {r4 - r12, lr}
85
86         /* Drain write buffer */
87         mov     tmp1, #0
88         mcr     p15, 0, tmp1, c7, c10, 4
89
90         ldr     tmp1, [r0, #PM_DATA_PMC]
91         str     tmp1, .pmc_base
92         ldr     tmp1, [r0, #PM_DATA_RAMC0]
93         str     tmp1, .sramc_base
94         ldr     tmp1, [r0, #PM_DATA_RAMC1]
95         str     tmp1, .sramc1_base
96         ldr     tmp1, [r0, #PM_DATA_MEMCTRL]
97         str     tmp1, .memtype
98         ldr     tmp1, [r0, #PM_DATA_MODE]
99         str     tmp1, .pm_mode
100         /* Both ldrne below are here to preload their address in the TLB */
101         ldr     tmp1, [r0, #PM_DATA_SHDWC]
102         str     tmp1, .shdwc
103         cmp     tmp1, #0
104         ldrne   tmp2, [tmp1, #0]
105         ldr     tmp1, [r0, #PM_DATA_SFRBU]
106         str     tmp1, .sfr
107         cmp     tmp1, #0
108         ldrne   tmp2, [tmp1, #0x10]
109
110         /* Active the self-refresh mode */
111         mov     r0, #SRAMC_SELF_FRESH_ACTIVE
112         bl      at91_sramc_self_refresh
113
114         ldr     r0, .pm_mode
115         cmp     r0, #AT91_PM_SLOW_CLOCK
116         beq     slow_clock
117         cmp     r0, #AT91_PM_BACKUP
118         beq     backup_mode
119
120         /* Wait for interrupt */
121         ldr     pmc, .pmc_base
122         at91_cpu_idle
123         b       exit_suspend
124
125 slow_clock:
126         bl      at91_slowck_mode
127         b       exit_suspend
128 backup_mode:
129         bl      at91_backup_mode
130         b       exit_suspend
131
132 exit_suspend:
133         /* Exit the self-refresh mode */
134         mov     r0, #SRAMC_SELF_FRESH_EXIT
135         bl      at91_sramc_self_refresh
136
137         /* Restore registers, and return */
138         ldmfd   sp!, {r4 - r12, pc}
139 ENDPROC(at91_pm_suspend_in_sram)
140
141 ENTRY(at91_backup_mode)
142         /*BUMEN*/
143         ldr     r0, .sfr
144         mov     tmp1, #0x1
145         str     tmp1, [r0, #0x10]
146
147         /* Shutdown */
148         ldr     r0, .shdwc
149         mov     tmp1, #0xA5000000
150         add     tmp1, tmp1, #0x1
151         str     tmp1, [r0, #0]
152 ENDPROC(at91_backup_mode)
153
154 ENTRY(at91_slowck_mode)
155         ldr     pmc, .pmc_base
156
157         /* Save Master clock setting */
158         ldr     tmp1, [pmc, #AT91_PMC_MCKR]
159         str     tmp1, .saved_mckr
160
161         /*
162          * Set the Master clock source to slow clock
163          */
164         bic     tmp1, tmp1, #AT91_PMC_CSS
165         str     tmp1, [pmc, #AT91_PMC_MCKR]
166
167         wait_mckrdy
168
169         /* Save PLLA setting and disable it */
170         ldr     tmp1, [pmc, #AT91_CKGR_PLLAR]
171         str     tmp1, .saved_pllar
172
173         mov     tmp1, #AT91_PMC_PLLCOUNT
174         orr     tmp1, tmp1, #(1 << 29)          /* bit 29 always set */
175         str     tmp1, [pmc, #AT91_CKGR_PLLAR]
176
177         /* Turn off the main oscillator */
178         ldr     tmp1, [pmc, #AT91_CKGR_MOR]
179         bic     tmp1, tmp1, #AT91_PMC_MOSCEN
180         orr     tmp1, tmp1, #AT91_PMC_KEY
181         str     tmp1, [pmc, #AT91_CKGR_MOR]
182
183         /* Wait for interrupt */
184         at91_cpu_idle
185
186         /* Turn on the main oscillator */
187         ldr     tmp1, [pmc, #AT91_CKGR_MOR]
188         orr     tmp1, tmp1, #AT91_PMC_MOSCEN
189         orr     tmp1, tmp1, #AT91_PMC_KEY
190         str     tmp1, [pmc, #AT91_CKGR_MOR]
191
192         wait_moscrdy
193
194         /* Restore PLLA setting */
195         ldr     tmp1, .saved_pllar
196         str     tmp1, [pmc, #AT91_CKGR_PLLAR]
197
198         tst     tmp1, #(AT91_PMC_MUL &  0xff0000)
199         bne     3f
200         tst     tmp1, #(AT91_PMC_MUL & ~0xff0000)
201         beq     4f
202 3:
203         wait_pllalock
204 4:
205
206         /*
207          * Restore master clock setting
208          */
209         ldr     tmp1, .saved_mckr
210         str     tmp1, [pmc, #AT91_PMC_MCKR]
211
212         wait_mckrdy
213
214         mov     pc, lr
215 ENDPROC(at91_slowck_mode)
216
217 /*
218  * void at91_sramc_self_refresh(unsigned int is_active)
219  *
220  * @input param:
221  *      @r0: 1 - active self-refresh mode
222  *           0 - exit self-refresh mode
223  * register usage:
224  *      @r1: memory type
225  *      @r2: base address of the sram controller
226  */
227
228 ENTRY(at91_sramc_self_refresh)
229         ldr     r1, .memtype
230         ldr     r2, .sramc_base
231
232         cmp     r1, #AT91_MEMCTRL_MC
233         bne     ddrc_sf
234
235         /*
236          * at91rm9200 Memory controller
237          */
238
239          /*
240           * For exiting the self-refresh mode, do nothing,
241           * automatically exit the self-refresh mode.
242           */
243         tst     r0, #SRAMC_SELF_FRESH_ACTIVE
244         beq     exit_sramc_sf
245
246         /* Active SDRAM self-refresh mode */
247         mov     r3, #1
248         str     r3, [r2, #AT91_MC_SDRAMC_SRR]
249         b       exit_sramc_sf
250
251 ddrc_sf:
252         cmp     r1, #AT91_MEMCTRL_DDRSDR
253         bne     sdramc_sf
254
255         /*
256          * DDR Memory controller
257          */
258         tst     r0, #SRAMC_SELF_FRESH_ACTIVE
259         beq     ddrc_exit_sf
260
261         /* LPDDR1 --> force DDR2 mode during self-refresh */
262         ldr     r3, [r2, #AT91_DDRSDRC_MDR]
263         str     r3, .saved_sam9_mdr
264         bic     r3, r3, #~AT91_DDRSDRC_MD
265         cmp     r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
266         ldreq   r3, [r2, #AT91_DDRSDRC_MDR]
267         biceq   r3, r3, #AT91_DDRSDRC_MD
268         orreq   r3, r3, #AT91_DDRSDRC_MD_DDR2
269         streq   r3, [r2, #AT91_DDRSDRC_MDR]
270
271         /* Active DDRC self-refresh mode */
272         ldr     r3, [r2, #AT91_DDRSDRC_LPR]
273         str     r3, .saved_sam9_lpr
274         bic     r3, r3, #AT91_DDRSDRC_LPCB
275         orr     r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
276         str     r3, [r2, #AT91_DDRSDRC_LPR]
277
278         /* If using the 2nd ddr controller */
279         ldr     r2, .sramc1_base
280         cmp     r2, #0
281         beq     no_2nd_ddrc
282
283         ldr     r3, [r2, #AT91_DDRSDRC_MDR]
284         str     r3, .saved_sam9_mdr1
285         bic     r3, r3, #~AT91_DDRSDRC_MD
286         cmp     r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
287         ldreq   r3, [r2, #AT91_DDRSDRC_MDR]
288         biceq   r3, r3, #AT91_DDRSDRC_MD
289         orreq   r3, r3, #AT91_DDRSDRC_MD_DDR2
290         streq   r3, [r2, #AT91_DDRSDRC_MDR]
291
292         /* Active DDRC self-refresh mode */
293         ldr     r3, [r2, #AT91_DDRSDRC_LPR]
294         str     r3, .saved_sam9_lpr1
295         bic     r3, r3, #AT91_DDRSDRC_LPCB
296         orr     r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
297         str     r3, [r2, #AT91_DDRSDRC_LPR]
298
299 no_2nd_ddrc:
300         b       exit_sramc_sf
301
302 ddrc_exit_sf:
303         /* Restore MDR in case of LPDDR1 */
304         ldr     r3, .saved_sam9_mdr
305         str     r3, [r2, #AT91_DDRSDRC_MDR]
306         /* Restore LPR on AT91 with DDRAM */
307         ldr     r3, .saved_sam9_lpr
308         str     r3, [r2, #AT91_DDRSDRC_LPR]
309
310         /* If using the 2nd ddr controller */
311         ldr     r2, .sramc1_base
312         cmp     r2, #0
313         ldrne   r3, .saved_sam9_mdr1
314         strne   r3, [r2, #AT91_DDRSDRC_MDR]
315         ldrne   r3, .saved_sam9_lpr1
316         strne   r3, [r2, #AT91_DDRSDRC_LPR]
317
318         b       exit_sramc_sf
319
320         /*
321          * SDRAMC Memory controller
322          */
323 sdramc_sf:
324         tst     r0, #SRAMC_SELF_FRESH_ACTIVE
325         beq     sdramc_exit_sf
326
327         /* Active SDRAMC self-refresh mode */
328         ldr     r3, [r2, #AT91_SDRAMC_LPR]
329         str     r3, .saved_sam9_lpr
330         bic     r3, r3, #AT91_SDRAMC_LPCB
331         orr     r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
332         str     r3, [r2, #AT91_SDRAMC_LPR]
333
334 sdramc_exit_sf:
335         ldr     r3, .saved_sam9_lpr
336         str     r3, [r2, #AT91_SDRAMC_LPR]
337
338 exit_sramc_sf:
339         mov     pc, lr
340 ENDPROC(at91_sramc_self_refresh)
341
342 .pmc_base:
343         .word 0
344 .sramc_base:
345         .word 0
346 .sramc1_base:
347         .word 0
348 .shdwc:
349         .word 0
350 .sfr:
351         .word 0
352 .memtype:
353         .word 0
354 .pm_mode:
355         .word 0
356 .saved_mckr:
357         .word 0
358 .saved_pllar:
359         .word 0
360 .saved_sam9_lpr:
361         .word 0
362 .saved_sam9_lpr1:
363         .word 0
364 .saved_sam9_mdr:
365         .word 0
366 .saved_sam9_mdr1:
367         .word 0
368
369 ENTRY(at91_pm_suspend_in_sram_sz)
370         .word .-at91_pm_suspend_in_sram