2 * arch/arm/mach-at91/pm_slow_clock.S
4 * Copyright (C) 2006 Savin Zlobec
7 * Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee
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.
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>
26 #include <mach/at91sam9_sdramc.h>
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.
35 #warning Assuming EB1 SDRAM controller is *NOT* used
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.
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)
56 mov r4, #MCKRDY_TIMEOUT
60 ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
61 tst r3, #AT91_PMC_MCKRDY
67 * Wait until master oscillator has stabilized.
70 mov r4, #MOSCRDY_TIMEOUT
74 ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
75 tst r3, #AT91_PMC_MOSCS
81 * Wait until PLLA has locked.
84 mov r4, #PLLALOCK_TIMEOUT
88 ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
89 tst r3, #AT91_PMC_LOCKA
95 * Wait until PLLB has locked.
98 mov r4, #PLLBLOCK_TIMEOUT
102 ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
103 tst r3, #AT91_PMC_LOCKB
110 ENTRY(at91_slow_clock)
111 /* Save registers on stack */
112 stmfd sp!, {r0 - r12, lr}
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
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 */
128 mcr p15, 0, r0, c7, c10, 4
130 #ifdef CONFIG_ARCH_AT91RM9200
131 /* Put SDRAM in self-refresh mode */
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 */
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]
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]
163 /* Save Master clock setting */
164 ldr r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
168 * Set the Master clock source to slow clock
170 bic r3, r3, #AT91_PMC_CSS
171 str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
175 #ifdef SLOWDOWN_MASTER_CLOCK
177 * Set the Master Clock PRES and MDIV fields.
179 * See AT91RM9200 errata #27 and #28 for details.
182 str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
187 /* Save PLLA setting and disable it */
188 ldr r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
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)]
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)]
217 /* Restore PLLB setting */
219 str r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
221 tst r3, #(AT91_PMC_MUL & 0xff0000)
223 tst r3, #(AT91_PMC_MUL & ~0xff0000)
229 /* Restore PLLA setting */
231 str r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
233 tst r3, #(AT91_PMC_MUL & 0xff0000)
235 tst r3, #(AT91_PMC_MUL & ~0xff0000)
241 #ifdef SLOWDOWN_MASTER_CLOCK
243 * First set PRES if it was not 0,
244 * than set CSS and MDIV fields.
246 * See AT91RM9200 errata #27 and #28 for details.
249 tst r3, #AT91_PMC_PRES
251 and r3, r3, #AT91_PMC_PRES
252 str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
258 * Restore master clock setting
260 2: ldr r3, .saved_mckr
261 str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
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 */
275 ldrne r4, .saved_sam9_lpr1
276 strne r4, [r5, #AT91_DDRSDRC_LPR]
279 /* Restore LPR on AT91 with SDRAM */
280 ldr r3, .saved_sam9_lpr
281 str r3, [r2, #AT91_SDRAMC_LPR]
284 /* Restore registers, and return */
285 ldmfd sp!, {r0 - r12, pc}
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
314 .at91_va_base_sdramc:
315 .word AT91_VA_BASE_SYS + AT91_SDRAMC0
319 #if defined(CONFIG_ARCH_AT91SAM9G45)
320 .word AT91_VA_BASE_SYS + AT91_DDRSDRC1
325 ENTRY(at91_slow_clock_sz)
326 .word .-at91_slow_clock