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