]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/arm/mach-at91/pm_suspend.S
Merge remote-tracking branch 'mfd/for-mfd-next'
[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
18 #define SRAMC_SELF_FRESH_ACTIVE         0x01
19 #define SRAMC_SELF_FRESH_EXIT           0x00
20
21 pmc     .req    r0
22 tmp1    .req    r4
23 tmp2    .req    r5
24
25 /*
26  * Wait until master clock is ready (after switching master clock source)
27  */
28         .macro wait_mckrdy
29 1:      ldr     tmp1, [pmc, #AT91_PMC_SR]
30         tst     tmp1, #AT91_PMC_MCKRDY
31         beq     1b
32         .endm
33
34 /*
35  * Wait until master oscillator has stabilized.
36  */
37         .macro wait_moscrdy
38 1:      ldr     tmp1, [pmc, #AT91_PMC_SR]
39         tst     tmp1, #AT91_PMC_MOSCS
40         beq     1b
41         .endm
42
43 /*
44  * Wait until PLLA has locked.
45  */
46         .macro wait_pllalock
47 1:      ldr     tmp1, [pmc, #AT91_PMC_SR]
48         tst     tmp1, #AT91_PMC_LOCKA
49         beq     1b
50         .endm
51
52 /*
53  * Put the processor to enter the idle state
54  */
55         .macro at91_cpu_idle
56
57 #if defined(CONFIG_CPU_V7)
58         mov     tmp1, #AT91_PMC_PCK
59         str     tmp1, [pmc, #AT91_PMC_SCDR]
60
61         dsb
62
63         wfi             @ Wait For Interrupt
64 #else
65         mcr     p15, 0, tmp1, c7, c0, 4
66 #endif
67
68         .endm
69
70         .text
71
72         .arm
73
74 /*
75  * void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *sdramc,
76  *                      void __iomem *ramc1, int memctrl)
77  * @input param:
78  *      @r0: base address of AT91_PMC
79  *      @r1: base address of SDRAM Controller (SDRAM, DDRSDR, or AT91_SYS)
80  *      @r2: base address of second SDRAM Controller or 0 if not present
81  *      @r3: pm information
82  */
83 /* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
84         .align 3
85 ENTRY(at91_pm_suspend_in_sram)
86         /* Save registers on stack */
87         stmfd   sp!, {r4 - r12, lr}
88
89         /* Drain write buffer */
90         mov     tmp1, #0
91         mcr     p15, 0, tmp1, c7, c10, 4
92
93         str     r0, .pmc_base
94         str     r1, .sramc_base
95         str     r2, .sramc1_base
96
97         and     r0, r3, #AT91_PM_MEMTYPE_MASK
98         str     r0, .memtype
99
100         lsr     r0, r3, #AT91_PM_MODE_OFFSET
101         and     r0, r0, #AT91_PM_MODE_MASK
102         str     r0, .pm_mode
103
104         /* Active the self-refresh mode */
105         mov     r0, #SRAMC_SELF_FRESH_ACTIVE
106         bl      at91_sramc_self_refresh
107
108         ldr     r0, .pm_mode
109         tst     r0, #AT91_PM_SLOW_CLOCK
110         beq     skip_disable_main_clock
111
112         ldr     pmc, .pmc_base
113
114         /* Save Master clock setting */
115         ldr     tmp1, [pmc, #AT91_PMC_MCKR]
116         str     tmp1, .saved_mckr
117
118         /*
119          * Set the Master clock source to slow clock
120          */
121         bic     tmp1, tmp1, #AT91_PMC_CSS
122         str     tmp1, [pmc, #AT91_PMC_MCKR]
123
124         wait_mckrdy
125
126         /* Save PLLA setting and disable it */
127         ldr     tmp1, [pmc, #AT91_CKGR_PLLAR]
128         str     tmp1, .saved_pllar
129
130         mov     tmp1, #AT91_PMC_PLLCOUNT
131         orr     tmp1, tmp1, #(1 << 29)          /* bit 29 always set */
132         str     tmp1, [pmc, #AT91_CKGR_PLLAR]
133
134         /* Turn off the main oscillator */
135         ldr     tmp1, [pmc, #AT91_CKGR_MOR]
136         bic     tmp1, tmp1, #AT91_PMC_MOSCEN
137         orr     tmp1, tmp1, #AT91_PMC_KEY
138         str     tmp1, [pmc, #AT91_CKGR_MOR]
139
140 skip_disable_main_clock:
141         ldr     pmc, .pmc_base
142
143         /* Wait for interrupt */
144         at91_cpu_idle
145
146         ldr     r0, .pm_mode
147         tst     r0, #AT91_PM_SLOW_CLOCK
148         beq     skip_enable_main_clock
149
150         ldr     pmc, .pmc_base
151
152         /* Turn on the main oscillator */
153         ldr     tmp1, [pmc, #AT91_CKGR_MOR]
154         orr     tmp1, tmp1, #AT91_PMC_MOSCEN
155         orr     tmp1, tmp1, #AT91_PMC_KEY
156         str     tmp1, [pmc, #AT91_CKGR_MOR]
157
158         wait_moscrdy
159
160         /* Restore PLLA setting */
161         ldr     tmp1, .saved_pllar
162         str     tmp1, [pmc, #AT91_CKGR_PLLAR]
163
164         tst     tmp1, #(AT91_PMC_MUL &  0xff0000)
165         bne     3f
166         tst     tmp1, #(AT91_PMC_MUL & ~0xff0000)
167         beq     4f
168 3:
169         wait_pllalock
170 4:
171
172         /*
173          * Restore master clock setting
174          */
175         ldr     tmp1, .saved_mckr
176         str     tmp1, [pmc, #AT91_PMC_MCKR]
177
178         wait_mckrdy
179
180 skip_enable_main_clock:
181         /* Exit the self-refresh mode */
182         mov     r0, #SRAMC_SELF_FRESH_EXIT
183         bl      at91_sramc_self_refresh
184
185         /* Restore registers, and return */
186         ldmfd   sp!, {r4 - r12, pc}
187 ENDPROC(at91_pm_suspend_in_sram)
188
189 /*
190  * void at91_sramc_self_refresh(unsigned int is_active)
191  *
192  * @input param:
193  *      @r0: 1 - active self-refresh mode
194  *           0 - exit self-refresh mode
195  * register usage:
196  *      @r1: memory type
197  *      @r2: base address of the sram controller
198  */
199
200 ENTRY(at91_sramc_self_refresh)
201         ldr     r1, .memtype
202         ldr     r2, .sramc_base
203
204         cmp     r1, #AT91_MEMCTRL_MC
205         bne     ddrc_sf
206
207         /*
208          * at91rm9200 Memory controller
209          */
210
211          /*
212           * For exiting the self-refresh mode, do nothing,
213           * automatically exit the self-refresh mode.
214           */
215         tst     r0, #SRAMC_SELF_FRESH_ACTIVE
216         beq     exit_sramc_sf
217
218         /* Active SDRAM self-refresh mode */
219         mov     r3, #1
220         str     r3, [r2, #AT91_MC_SDRAMC_SRR]
221         b       exit_sramc_sf
222
223 ddrc_sf:
224         cmp     r1, #AT91_MEMCTRL_DDRSDR
225         bne     sdramc_sf
226
227         /*
228          * DDR Memory controller
229          */
230         tst     r0, #SRAMC_SELF_FRESH_ACTIVE
231         beq     ddrc_exit_sf
232
233         /* LPDDR1 --> force DDR2 mode during self-refresh */
234         ldr     r3, [r2, #AT91_DDRSDRC_MDR]
235         str     r3, .saved_sam9_mdr
236         bic     r3, r3, #~AT91_DDRSDRC_MD
237         cmp     r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
238         ldreq   r3, [r2, #AT91_DDRSDRC_MDR]
239         biceq   r3, r3, #AT91_DDRSDRC_MD
240         orreq   r3, r3, #AT91_DDRSDRC_MD_DDR2
241         streq   r3, [r2, #AT91_DDRSDRC_MDR]
242
243         /* Active DDRC self-refresh mode */
244         ldr     r3, [r2, #AT91_DDRSDRC_LPR]
245         str     r3, .saved_sam9_lpr
246         bic     r3, r3, #AT91_DDRSDRC_LPCB
247         orr     r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
248         str     r3, [r2, #AT91_DDRSDRC_LPR]
249
250         /* If using the 2nd ddr controller */
251         ldr     r2, .sramc1_base
252         cmp     r2, #0
253         beq     no_2nd_ddrc
254
255         ldr     r3, [r2, #AT91_DDRSDRC_MDR]
256         str     r3, .saved_sam9_mdr1
257         bic     r3, r3, #~AT91_DDRSDRC_MD
258         cmp     r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
259         ldreq   r3, [r2, #AT91_DDRSDRC_MDR]
260         biceq   r3, r3, #AT91_DDRSDRC_MD
261         orreq   r3, r3, #AT91_DDRSDRC_MD_DDR2
262         streq   r3, [r2, #AT91_DDRSDRC_MDR]
263
264         /* Active DDRC self-refresh mode */
265         ldr     r3, [r2, #AT91_DDRSDRC_LPR]
266         str     r3, .saved_sam9_lpr1
267         bic     r3, r3, #AT91_DDRSDRC_LPCB
268         orr     r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
269         str     r3, [r2, #AT91_DDRSDRC_LPR]
270
271 no_2nd_ddrc:
272         b       exit_sramc_sf
273
274 ddrc_exit_sf:
275         /* Restore MDR in case of LPDDR1 */
276         ldr     r3, .saved_sam9_mdr
277         str     r3, [r2, #AT91_DDRSDRC_MDR]
278         /* Restore LPR on AT91 with DDRAM */
279         ldr     r3, .saved_sam9_lpr
280         str     r3, [r2, #AT91_DDRSDRC_LPR]
281
282         /* If using the 2nd ddr controller */
283         ldr     r2, .sramc1_base
284         cmp     r2, #0
285         ldrne   r3, .saved_sam9_mdr1
286         strne   r3, [r2, #AT91_DDRSDRC_MDR]
287         ldrne   r3, .saved_sam9_lpr1
288         strne   r3, [r2, #AT91_DDRSDRC_LPR]
289
290         b       exit_sramc_sf
291
292         /*
293          * SDRAMC Memory controller
294          */
295 sdramc_sf:
296         tst     r0, #SRAMC_SELF_FRESH_ACTIVE
297         beq     sdramc_exit_sf
298
299         /* Active SDRAMC self-refresh mode */
300         ldr     r3, [r2, #AT91_SDRAMC_LPR]
301         str     r3, .saved_sam9_lpr
302         bic     r3, r3, #AT91_SDRAMC_LPCB
303         orr     r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
304         str     r3, [r2, #AT91_SDRAMC_LPR]
305
306 sdramc_exit_sf:
307         ldr     r3, .saved_sam9_lpr
308         str     r3, [r2, #AT91_SDRAMC_LPR]
309
310 exit_sramc_sf:
311         mov     pc, lr
312 ENDPROC(at91_sramc_self_refresh)
313
314 .pmc_base:
315         .word 0
316 .sramc_base:
317         .word 0
318 .sramc1_base:
319         .word 0
320 .memtype:
321         .word 0
322 .pm_mode:
323         .word 0
324 .saved_mckr:
325         .word 0
326 .saved_pllar:
327         .word 0
328 .saved_sam9_lpr:
329         .word 0
330 .saved_sam9_lpr1:
331         .word 0
332 .saved_sam9_mdr:
333         .word 0
334 .saved_sam9_mdr1:
335         .word 0
336
337 ENTRY(at91_pm_suspend_in_sram_sz)
338         .word .-at91_pm_suspend_in_sram