Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-at91 / pm_slowclock.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
15 #include <linux/linkage.h>
16 #include <linux/clk/at91_pmc.h>
17 #include <mach/hardware.h>
18 #include <mach/at91_ramc.h>
19
20 /*
21  * When SLOWDOWN_MASTER_CLOCK is defined we will also slow down the Master
22  * clock during suspend by adjusting its prescalar and divisor.
23  * NOTE: This hasn't been shown to be stable on SAM9s; and on the RM9200 there
24  *       are errata regarding adjusting the prescalar and divisor.
25  */
26 #undef SLOWDOWN_MASTER_CLOCK
27
28 pmc     .req    r0
29 sdramc  .req    r1
30 ramc1   .req    r2
31 memctrl .req    r3
32 tmp1    .req    r4
33 tmp2    .req    r5
34
35 /*
36  * Wait until master clock is ready (after switching master clock source)
37  */
38         .macro wait_mckrdy
39 1:      ldr     tmp1, [pmc, #AT91_PMC_SR]
40         tst     tmp1, #AT91_PMC_MCKRDY
41         beq     1b
42         .endm
43
44 /*
45  * Wait until master oscillator has stabilized.
46  */
47         .macro wait_moscrdy
48 1:      ldr     tmp1, [pmc, #AT91_PMC_SR]
49         tst     tmp1, #AT91_PMC_MOSCS
50         beq     1b
51         .endm
52
53 /*
54  * Wait until PLLA has locked.
55  */
56         .macro wait_pllalock
57 1:      ldr     tmp1, [pmc, #AT91_PMC_SR]
58         tst     tmp1, #AT91_PMC_LOCKA
59         beq     1b
60         .endm
61
62 /*
63  * Wait until PLLB has locked.
64  */
65         .macro wait_pllblock
66 1:      ldr     tmp1, [pmc, #AT91_PMC_SR]
67         tst     tmp1, #AT91_PMC_LOCKB
68         beq     1b
69         .endm
70
71         .text
72
73         .arm
74
75 /* void at91_slow_clock(void __iomem *pmc, void __iomem *sdramc,
76  *                      void __iomem *ramc1, int memctrl)
77  */
78 ENTRY(at91_slow_clock)
79         /* Save registers on stack */
80         stmfd   sp!, {r4 - r12, lr}
81
82         /*
83          * Register usage:
84          *  R0 = Base address of AT91_PMC
85          *  R1 = Base address of RAM Controller (SDRAM, DDRSDR, or AT91_SYS)
86          *  R2 = Base address of second RAM Controller or 0 if not present
87          *  R3 = Memory controller
88          *  R4 = temporary register
89          *  R5 = temporary register
90          */
91
92         /* Drain write buffer */
93         mov     tmp1, #0
94         mcr     p15, 0, tmp1, c7, c10, 4
95
96         cmp     memctrl, #AT91_MEMCTRL_MC
97         bne     ddr_sr_enable
98
99         /*
100          * at91rm9200 Memory controller
101          */
102         /* Put SDRAM in self-refresh mode */
103         mov     tmp1, #1
104         str     tmp1, [sdramc, #AT91RM9200_SDRAMC_SRR]
105         b       sdr_sr_done
106
107         /*
108          * DDRSDR Memory controller
109          */
110 ddr_sr_enable:
111         cmp     memctrl, #AT91_MEMCTRL_DDRSDR
112         bne     sdr_sr_enable
113
114         /* LPDDR1 --> force DDR2 mode during self-refresh */
115         ldr     tmp1, [sdramc, #AT91_DDRSDRC_MDR]
116         str     tmp1, .saved_sam9_mdr
117         bic     tmp1, tmp1, #~AT91_DDRSDRC_MD
118         cmp     tmp1, #AT91_DDRSDRC_MD_LOW_POWER_DDR
119         ldreq   tmp1, [sdramc, #AT91_DDRSDRC_MDR]
120         biceq   tmp1, tmp1, #AT91_DDRSDRC_MD
121         orreq   tmp1, tmp1, #AT91_DDRSDRC_MD_DDR2
122         streq   tmp1, [sdramc, #AT91_DDRSDRC_MDR]
123
124         /* prepare for DDRAM self-refresh mode */
125         ldr     tmp1, [sdramc, #AT91_DDRSDRC_LPR]
126         str     tmp1, .saved_sam9_lpr
127         bic     tmp1, #AT91_DDRSDRC_LPCB
128         orr     tmp1, #AT91_DDRSDRC_LPCB_SELF_REFRESH
129
130         /* figure out if we use the second ram controller */
131         cmp     ramc1, #0
132         beq     ddr_no_2nd_ctrl
133
134         ldr     tmp2, [ramc1, #AT91_DDRSDRC_MDR]
135         str     tmp2, .saved_sam9_mdr1
136         bic     tmp2, tmp2, #~AT91_DDRSDRC_MD
137         cmp     tmp2, #AT91_DDRSDRC_MD_LOW_POWER_DDR
138         ldreq   tmp2, [ramc1, #AT91_DDRSDRC_MDR]
139         biceq   tmp2, tmp2, #AT91_DDRSDRC_MD
140         orreq   tmp2, tmp2, #AT91_DDRSDRC_MD_DDR2
141         streq   tmp2, [ramc1, #AT91_DDRSDRC_MDR]
142
143         ldr     tmp2, [ramc1, #AT91_DDRSDRC_LPR]
144         str     tmp2, .saved_sam9_lpr1
145         bic     tmp2, #AT91_DDRSDRC_LPCB
146         orr     tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH
147
148         /* Enable DDRAM self-refresh mode */
149         str     tmp2, [ramc1, #AT91_DDRSDRC_LPR]
150 ddr_no_2nd_ctrl:
151         str     tmp1, [sdramc, #AT91_DDRSDRC_LPR]
152
153         b       sdr_sr_done
154
155         /*
156          * SDRAMC Memory controller
157          */
158 sdr_sr_enable:
159         /* Enable SDRAM self-refresh mode */
160         ldr     tmp1, [sdramc, #AT91_SDRAMC_LPR]
161         str     tmp1, .saved_sam9_lpr
162
163         bic     tmp1, #AT91_SDRAMC_LPCB
164         orr     tmp1, #AT91_SDRAMC_LPCB_SELF_REFRESH
165         str     tmp1, [sdramc, #AT91_SDRAMC_LPR]
166
167 sdr_sr_done:
168         /* Save Master clock setting */
169         ldr     tmp1, [pmc, #AT91_PMC_MCKR]
170         str     tmp1, .saved_mckr
171
172         /*
173          * Set the Master clock source to slow clock
174          */
175         bic     tmp1, tmp1, #AT91_PMC_CSS
176         str     tmp1, [pmc, #AT91_PMC_MCKR]
177
178         wait_mckrdy
179
180 #ifdef SLOWDOWN_MASTER_CLOCK
181         /*
182          * Set the Master Clock PRES and MDIV fields.
183          *
184          * See AT91RM9200 errata #27 and #28 for details.
185          */
186         mov     tmp1, #0
187         str     tmp1, [pmc, #AT91_PMC_MCKR]
188
189         wait_mckrdy
190 #endif
191
192         /* Save PLLA setting and disable it */
193         ldr     tmp1, [pmc, #AT91_CKGR_PLLAR]
194         str     tmp1, .saved_pllar
195
196         mov     tmp1, #AT91_PMC_PLLCOUNT
197         orr     tmp1, tmp1, #(1 << 29)          /* bit 29 always set */
198         str     tmp1, [pmc, #AT91_CKGR_PLLAR]
199
200         /* Save PLLB setting and disable it */
201         ldr     tmp1, [pmc, #AT91_CKGR_PLLBR]
202         str     tmp1, .saved_pllbr
203
204         mov     tmp1, #AT91_PMC_PLLCOUNT
205         str     tmp1, [pmc, #AT91_CKGR_PLLBR]
206
207         /* Turn off the main oscillator */
208         ldr     tmp1, [pmc, #AT91_CKGR_MOR]
209         bic     tmp1, tmp1, #AT91_PMC_MOSCEN
210         orr     tmp1, tmp1, #AT91_PMC_KEY
211         str     tmp1, [pmc, #AT91_CKGR_MOR]
212
213         /* Wait for interrupt */
214         mcr     p15, 0, tmp1, c7, c0, 4
215
216         /* Turn on the main oscillator */
217         ldr     tmp1, [pmc, #AT91_CKGR_MOR]
218         orr     tmp1, tmp1, #AT91_PMC_MOSCEN
219         orr     tmp1, tmp1, #AT91_PMC_KEY
220         str     tmp1, [pmc, #AT91_CKGR_MOR]
221
222         wait_moscrdy
223
224         /* Restore PLLB setting */
225         ldr     tmp1, .saved_pllbr
226         str     tmp1, [pmc, #AT91_CKGR_PLLBR]
227
228         tst     tmp1, #(AT91_PMC_MUL &  0xff0000)
229         bne     1f
230         tst     tmp1, #(AT91_PMC_MUL & ~0xff0000)
231         beq     2f
232 1:
233         wait_pllblock
234 2:
235
236         /* Restore PLLA setting */
237         ldr     tmp1, .saved_pllar
238         str     tmp1, [pmc, #AT91_CKGR_PLLAR]
239
240         tst     tmp1, #(AT91_PMC_MUL &  0xff0000)
241         bne     3f
242         tst     tmp1, #(AT91_PMC_MUL & ~0xff0000)
243         beq     4f
244 3:
245         wait_pllalock
246 4:
247
248 #ifdef SLOWDOWN_MASTER_CLOCK
249         /*
250          * First set PRES if it was not 0,
251          * than set CSS and MDIV fields.
252          *
253          * See AT91RM9200 errata #27 and #28 for details.
254          */
255         ldr     tmp1, .saved_mckr
256         tst     tmp1, #AT91_PMC_PRES
257         beq     2f
258         and     tmp1, tmp1, #AT91_PMC_PRES
259         str     tmp1, [pmc, #AT91_PMC_MCKR]
260
261         wait_mckrdy
262 #endif
263
264         /*
265          * Restore master clock setting
266          */
267 2:      ldr     tmp1, .saved_mckr
268         str     tmp1, [pmc, #AT91_PMC_MCKR]
269
270         wait_mckrdy
271
272         /*
273          * at91rm9200 Memory controller
274          * Do nothing - self-refresh is automatically disabled.
275          */
276         cmp     memctrl, #AT91_MEMCTRL_MC
277         beq     ram_restored
278
279         /*
280          * DDRSDR Memory controller
281          */
282         cmp     memctrl, #AT91_MEMCTRL_DDRSDR
283         bne     sdr_en_restore
284         /* Restore MDR in case of LPDDR1 */
285         ldr     tmp1, .saved_sam9_mdr
286         str     tmp1, [sdramc, #AT91_DDRSDRC_MDR]
287         /* Restore LPR on AT91 with DDRAM */
288         ldr     tmp1, .saved_sam9_lpr
289         str     tmp1, [sdramc, #AT91_DDRSDRC_LPR]
290
291         /* if we use the second ram controller */
292         cmp     ramc1, #0
293         ldrne   tmp2, .saved_sam9_mdr1
294         strne   tmp2, [ramc1, #AT91_DDRSDRC_MDR]
295         ldrne   tmp2, .saved_sam9_lpr1
296         strne   tmp2, [ramc1, #AT91_DDRSDRC_LPR]
297
298         b       ram_restored
299
300         /*
301          * SDRAMC Memory controller
302          */
303 sdr_en_restore:
304         /* Restore LPR on AT91 with SDRAM */
305         ldr     tmp1, .saved_sam9_lpr
306         str     tmp1, [sdramc, #AT91_SDRAMC_LPR]
307
308 ram_restored:
309         /* Restore registers, and return */
310         ldmfd   sp!, {r4 - r12, pc}
311
312
313 .saved_mckr:
314         .word 0
315
316 .saved_pllar:
317         .word 0
318
319 .saved_pllbr:
320         .word 0
321
322 .saved_sam9_lpr:
323         .word 0
324
325 .saved_sam9_lpr1:
326         .word 0
327
328 .saved_sam9_mdr:
329         .word 0
330
331 .saved_sam9_mdr1:
332         .word 0
333
334 ENTRY(at91_slow_clock_sz)
335         .word .-at91_slow_clock