Merge branch 'v6v7' into devel
[linux/fpc-iii.git] / arch / arm / mach-at91 / pm_slowclock.S
blobf7922a436172a063bf188af5fc2b24cad4ab148e
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  */
15 #include <linux/linkage.h>
16 #include <mach/hardware.h>
17 #include <mach/at91_pmc.h>
19 #if defined(CONFIG_ARCH_AT91RM9200)
20 #include <mach/at91rm9200_mc.h>
21 #elif defined(CONFIG_ARCH_AT91CAP9)
22 #include <mach/at91cap9_ddrsdr.h>
23 #elif defined(CONFIG_ARCH_AT91SAM9G45)
24 #include <mach/at91sam9_ddrsdr.h>
25 #else
26 #include <mach/at91sam9_sdramc.h>
27 #endif
30 #ifdef CONFIG_ARCH_AT91SAM9263
32  * FIXME either or both the SDRAM controllers (EB0, EB1) might be in use;
33  * handle those cases both here and in the Suspend-To-RAM support.
34  */
35 #warning Assuming EB1 SDRAM controller is *NOT* used
36 #endif
39  * When SLOWDOWN_MASTER_CLOCK is defined we will also slow down the Master
40  * clock during suspend by adjusting its prescalar and divisor.
41  * NOTE: This hasn't been shown to be stable on SAM9s; and on the RM9200 there
42  *       are errata regarding adjusting the prescalar and divisor.
43  */
44 #undef SLOWDOWN_MASTER_CLOCK
46 #define MCKRDY_TIMEOUT          1000
47 #define MOSCRDY_TIMEOUT         1000
48 #define PLLALOCK_TIMEOUT        1000
49 #define PLLBLOCK_TIMEOUT        1000
53  * Wait until master clock is ready (after switching master clock source)
54  */
55         .macro wait_mckrdy
56         mov     r4, #MCKRDY_TIMEOUT
57 1:      sub     r4, r4, #1
58         cmp     r4, #0
59         beq     2f
60         ldr     r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
61         tst     r3, #AT91_PMC_MCKRDY
62         beq     1b
64         .endm
67  * Wait until master oscillator has stabilized.
68  */
69         .macro wait_moscrdy
70         mov     r4, #MOSCRDY_TIMEOUT
71 1:      sub     r4, r4, #1
72         cmp     r4, #0
73         beq     2f
74         ldr     r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
75         tst     r3, #AT91_PMC_MOSCS
76         beq     1b
78         .endm
81  * Wait until PLLA has locked.
82  */
83         .macro wait_pllalock
84         mov     r4, #PLLALOCK_TIMEOUT
85 1:      sub     r4, r4, #1
86         cmp     r4, #0
87         beq     2f
88         ldr     r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
89         tst     r3, #AT91_PMC_LOCKA
90         beq     1b
92         .endm
95  * Wait until PLLB has locked.
96  */
97         .macro wait_pllblock
98         mov     r4, #PLLBLOCK_TIMEOUT
99 1:      sub     r4, r4, #1
100         cmp     r4, #0
101         beq     2f
102         ldr     r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
103         tst     r3, #AT91_PMC_LOCKB
104         beq     1b
106         .endm
108         .text
110 ENTRY(at91_slow_clock)
111         /* Save registers on stack */
112         stmfd   sp!, {r0 - r12, lr}
114         /*
115          * Register usage:
116          *  R1 = Base address of AT91_PMC
117          *  R2 = Base address of RAM Controller (SDRAM, DDRSDR, or AT91_SYS)
118          *  R3 = temporary register
119          *  R4 = temporary register
120          *  R5 = Base address of second RAM Controller or 0 if not present
121          */
122         ldr     r1, .at91_va_base_pmc
123         ldr     r2, .at91_va_base_sdramc
124         ldr     r5, .at91_va_base_ramc1
126         /* Drain write buffer */
127         mov     r0, #0
128         mcr     p15, 0, r0, c7, c10, 4
130 #ifdef CONFIG_ARCH_AT91RM9200
131         /* Put SDRAM in self-refresh mode */
132         mov     r3, #1
133         str     r3, [r2, #AT91_SDRAMC_SRR]
134 #elif defined(CONFIG_ARCH_AT91CAP9) \
135         || defined(CONFIG_ARCH_AT91SAM9G45)
137         /* prepare for DDRAM self-refresh mode */
138         ldr     r3, [r2, #AT91_DDRSDRC_LPR]
139         str     r3, .saved_sam9_lpr
140         bic     r3, #AT91_DDRSDRC_LPCB
141         orr     r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
143         /* figure out if we use the second ram controller */
144         cmp     r5, #0
145         ldrne   r4, [r5, #AT91_DDRSDRC_LPR]
146         strne   r4, .saved_sam9_lpr1
147         bicne   r4, #AT91_DDRSDRC_LPCB
148         orrne   r4, #AT91_DDRSDRC_LPCB_SELF_REFRESH
150         /* Enable DDRAM self-refresh mode */
151         str     r3, [r2, #AT91_DDRSDRC_LPR]
152         strne   r4, [r5, #AT91_DDRSDRC_LPR]
153 #else
154         /* Enable SDRAM self-refresh mode */
155         ldr     r3, [r2, #AT91_SDRAMC_LPR]
156         str     r3, .saved_sam9_lpr
158         bic     r3, #AT91_SDRAMC_LPCB
159         orr     r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
160         str     r3, [r2, #AT91_SDRAMC_LPR]
161 #endif
163         /* Save Master clock setting */
164         ldr     r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
165         str     r3, .saved_mckr
167         /*
168          * Set the Master clock source to slow clock
169          */
170         bic     r3, r3, #AT91_PMC_CSS
171         str     r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
173         wait_mckrdy
175 #ifdef SLOWDOWN_MASTER_CLOCK
176         /*
177          * Set the Master Clock PRES and MDIV fields.
178          *
179          * See AT91RM9200 errata #27 and #28 for details.
180          */
181         mov     r3, #0
182         str     r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
184         wait_mckrdy
185 #endif
187         /* Save PLLA setting and disable it */
188         ldr     r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
189         str     r3, .saved_pllar
191         mov     r3, #AT91_PMC_PLLCOUNT
192         orr     r3, r3, #(1 << 29)              /* bit 29 always set */
193         str     r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
195         /* Save PLLB setting and disable it */
196         ldr     r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
197         str     r3, .saved_pllbr
199         mov     r3, #AT91_PMC_PLLCOUNT
200         str     r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
202         /* Turn off the main oscillator */
203         ldr     r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
204         bic     r3, r3, #AT91_PMC_MOSCEN
205         str     r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
207         /* Wait for interrupt */
208         mcr     p15, 0, r0, c7, c0, 4
210         /* Turn on the main oscillator */
211         ldr     r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
212         orr     r3, r3, #AT91_PMC_MOSCEN
213         str     r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
215         wait_moscrdy
217         /* Restore PLLB setting */
218         ldr     r3, .saved_pllbr
219         str     r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
221         tst     r3, #(AT91_PMC_MUL &  0xff0000)
222         bne     1f
223         tst     r3, #(AT91_PMC_MUL & ~0xff0000)
224         beq     2f
226         wait_pllblock
229         /* Restore PLLA setting */
230         ldr     r3, .saved_pllar
231         str     r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
233         tst     r3, #(AT91_PMC_MUL &  0xff0000)
234         bne     3f
235         tst     r3, #(AT91_PMC_MUL & ~0xff0000)
236         beq     4f
238         wait_pllalock
241 #ifdef SLOWDOWN_MASTER_CLOCK
242         /*
243          * First set PRES if it was not 0,
244          * than set CSS and MDIV fields.
245          *
246          * See AT91RM9200 errata #27 and #28 for details.
247          */
248         ldr     r3, .saved_mckr
249         tst     r3, #AT91_PMC_PRES
250         beq     2f
251         and     r3, r3, #AT91_PMC_PRES
252         str     r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
254         wait_mckrdy
255 #endif
257         /*
258          * Restore master clock setting
259          */
260 2:      ldr     r3, .saved_mckr
261         str     r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
263         wait_mckrdy
265 #ifdef CONFIG_ARCH_AT91RM9200
266         /* Do nothing - self-refresh is automatically disabled. */
267 #elif defined(CONFIG_ARCH_AT91CAP9) \
268         || defined(CONFIG_ARCH_AT91SAM9G45)
269         /* Restore LPR on AT91 with DDRAM */
270         ldr     r3, .saved_sam9_lpr
271         str     r3, [r2, #AT91_DDRSDRC_LPR]
273         /* if we use the second ram controller */
274         cmp     r5, #0
275         ldrne   r4, .saved_sam9_lpr1
276         strne   r4, [r5, #AT91_DDRSDRC_LPR]
278 #else
279         /* Restore LPR on AT91 with SDRAM */
280         ldr     r3, .saved_sam9_lpr
281         str     r3, [r2, #AT91_SDRAMC_LPR]
282 #endif
284         /* Restore registers, and return */
285         ldmfd   sp!, {r0 - r12, pc}
288 .saved_mckr:
289         .word 0
291 .saved_pllar:
292         .word 0
294 .saved_pllbr:
295         .word 0
297 .saved_sam9_lpr:
298         .word 0
300 .saved_sam9_lpr1:
301         .word 0
303 .at91_va_base_pmc:
304         .word AT91_VA_BASE_SYS + AT91_PMC
306 #ifdef CONFIG_ARCH_AT91RM9200
307 .at91_va_base_sdramc:
308         .word AT91_VA_BASE_SYS
309 #elif defined(CONFIG_ARCH_AT91CAP9) \
310         || defined(CONFIG_ARCH_AT91SAM9G45)
311 .at91_va_base_sdramc:
312         .word AT91_VA_BASE_SYS + AT91_DDRSDRC0
313 #else
314 .at91_va_base_sdramc:
315         .word AT91_VA_BASE_SYS + AT91_SDRAMC0
316 #endif
318 .at91_va_base_ramc1:
319 #if defined(CONFIG_ARCH_AT91SAM9G45)
320         .word AT91_VA_BASE_SYS + AT91_DDRSDRC1
321 #else
322         .word 0
323 #endif
325 ENTRY(at91_slow_clock_sz)
326         .word .-at91_slow_clock