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 || defined(CONFIG_ARCH_AT91SAM9G45)
23 #include <mach/at91sam9_ddrsdr.h>
25 #include <mach/at91sam9_sdramc.h>
29 #ifdef CONFIG_ARCH_AT91SAM9263
31 * FIXME either or both the SDRAM controllers (EB0, EB1) might be in use;
32 * handle those cases both here and in the Suspend-To-RAM support.
34 #warning Assuming EB1 SDRAM controller is *NOT* used
38 * When SLOWDOWN_MASTER_CLOCK is defined we will also slow down the Master
39 * clock during suspend by adjusting its prescalar and divisor.
40 * NOTE: This hasn't been shown to be stable on SAM9s; and on the RM9200 there
41 * are errata regarding adjusting the prescalar and divisor.
43 #undef SLOWDOWN_MASTER_CLOCK
45 #define MCKRDY_TIMEOUT 1000
46 #define MOSCRDY_TIMEOUT 1000
47 #define PLLALOCK_TIMEOUT 1000
48 #define PLLBLOCK_TIMEOUT 1000
52 * Wait until master clock is ready (after switching master clock source)
55 mov r4, #MCKRDY_TIMEOUT
59 ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
60 tst r3, #AT91_PMC_MCKRDY
66 * Wait until master oscillator has stabilized.
69 mov r4, #MOSCRDY_TIMEOUT
73 ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
74 tst r3, #AT91_PMC_MOSCS
80 * Wait until PLLA has locked.
83 mov r4, #PLLALOCK_TIMEOUT
87 ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
88 tst r3, #AT91_PMC_LOCKA
94 * Wait until PLLB has locked.
97 mov r4, #PLLBLOCK_TIMEOUT
101 ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
102 tst r3, #AT91_PMC_LOCKB
109 ENTRY(at91_slow_clock)
110 /* Save registers on stack */
111 stmfd sp!, {r0 - r12, lr}
115 * R1 = Base address of AT91_PMC
116 * R2 = Base address of RAM Controller (SDRAM, DDRSDR, or AT91_SYS)
117 * R3 = temporary register
118 * R4 = temporary register
119 * R5 = Base address of second RAM Controller or 0 if not present
121 ldr r1, .at91_va_base_pmc
122 ldr r2, .at91_va_base_sdramc
123 ldr r5, .at91_va_base_ramc1
125 /* Drain write buffer */
127 mcr p15, 0, r0, c7, c10, 4
129 #ifdef CONFIG_ARCH_AT91RM9200
130 /* Put SDRAM in self-refresh mode */
132 str r3, [r2, #AT91_SDRAMC_SRR]
133 #elif defined(CONFIG_ARCH_AT91CAP9) \
134 || defined(CONFIG_ARCH_AT91SAM9G45)
136 /* prepare for DDRAM self-refresh mode */
137 ldr r3, [r2, #AT91_DDRSDRC_LPR]
138 str r3, .saved_sam9_lpr
139 bic r3, #AT91_DDRSDRC_LPCB
140 orr r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
142 /* figure out if we use the second ram controller */
144 ldrne r4, [r5, #AT91_DDRSDRC_LPR]
145 strne r4, .saved_sam9_lpr1
146 bicne r4, #AT91_DDRSDRC_LPCB
147 orrne r4, #AT91_DDRSDRC_LPCB_SELF_REFRESH
149 /* Enable DDRAM self-refresh mode */
150 str r3, [r2, #AT91_DDRSDRC_LPR]
151 strne r4, [r5, #AT91_DDRSDRC_LPR]
153 /* Enable SDRAM self-refresh mode */
154 ldr r3, [r2, #AT91_SDRAMC_LPR]
155 str r3, .saved_sam9_lpr
157 bic r3, #AT91_SDRAMC_LPCB
158 orr r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
159 str r3, [r2, #AT91_SDRAMC_LPR]
162 /* Save Master clock setting */
163 ldr r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
167 * Set the Master clock source to slow clock
169 bic r3, r3, #AT91_PMC_CSS
170 str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
174 #ifdef SLOWDOWN_MASTER_CLOCK
176 * Set the Master Clock PRES and MDIV fields.
178 * See AT91RM9200 errata #27 and #28 for details.
181 str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
186 /* Save PLLA setting and disable it */
187 ldr r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
190 mov r3, #AT91_PMC_PLLCOUNT
191 orr r3, r3, #(1 << 29) /* bit 29 always set */
192 str r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
194 /* Save PLLB setting and disable it */
195 ldr r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
198 mov r3, #AT91_PMC_PLLCOUNT
199 str r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
201 /* Turn off the main oscillator */
202 ldr r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
203 bic r3, r3, #AT91_PMC_MOSCEN
204 str r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
206 /* Wait for interrupt */
207 mcr p15, 0, r0, c7, c0, 4
209 /* Turn on the main oscillator */
210 ldr r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
211 orr r3, r3, #AT91_PMC_MOSCEN
212 str r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
216 /* Restore PLLB setting */
218 str r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
220 tst r3, #(AT91_PMC_MUL & 0xff0000)
222 tst r3, #(AT91_PMC_MUL & ~0xff0000)
228 /* Restore PLLA setting */
230 str r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
232 tst r3, #(AT91_PMC_MUL & 0xff0000)
234 tst r3, #(AT91_PMC_MUL & ~0xff0000)
240 #ifdef SLOWDOWN_MASTER_CLOCK
242 * First set PRES if it was not 0,
243 * than set CSS and MDIV fields.
245 * See AT91RM9200 errata #27 and #28 for details.
248 tst r3, #AT91_PMC_PRES
250 and r3, r3, #AT91_PMC_PRES
251 str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
257 * Restore master clock setting
259 2: ldr r3, .saved_mckr
260 str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
264 #ifdef CONFIG_ARCH_AT91RM9200
265 /* Do nothing - self-refresh is automatically disabled. */
266 #elif defined(CONFIG_ARCH_AT91CAP9) \
267 || defined(CONFIG_ARCH_AT91SAM9G45)
268 /* Restore LPR on AT91 with DDRAM */
269 ldr r3, .saved_sam9_lpr
270 str r3, [r2, #AT91_DDRSDRC_LPR]
272 /* if we use the second ram controller */
274 ldrne r4, .saved_sam9_lpr1
275 strne r4, [r5, #AT91_DDRSDRC_LPR]
278 /* Restore LPR on AT91 with SDRAM */
279 ldr r3, .saved_sam9_lpr
280 str r3, [r2, #AT91_SDRAMC_LPR]
283 /* Restore registers, and return */
284 ldmfd sp!, {r0 - r12, pc}
303 .word AT91_VA_BASE_SYS + AT91_PMC
305 #ifdef CONFIG_ARCH_AT91RM9200
306 .at91_va_base_sdramc:
307 .word AT91_VA_BASE_SYS
308 #elif defined(CONFIG_ARCH_AT91CAP9) \
309 || defined(CONFIG_ARCH_AT91SAM9G45)
310 .at91_va_base_sdramc:
311 .word AT91_VA_BASE_SYS + AT91_DDRSDRC0
313 .at91_va_base_sdramc:
314 .word AT91_VA_BASE_SYS + AT91_SDRAMC0
318 #if defined(CONFIG_ARCH_AT91SAM9G45)
319 .word AT91_VA_BASE_SYS + AT91_DDRSDRC1
324 ENTRY(at91_slow_clock_sz)
325 .word .-at91_slow_clock