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 <linux/clk/at91_pmc.h>
17 #include <mach/hardware.h>
18 #include <mach/at91_ramc.h>
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.
26 #undef SLOWDOWN_MASTER_CLOCK
28 #define MCKRDY_TIMEOUT 1000
29 #define MOSCRDY_TIMEOUT 1000
30 #define PLLALOCK_TIMEOUT 1000
31 #define PLLBLOCK_TIMEOUT 1000
41 * Wait until master clock is ready (after switching master clock source)
44 mov tmp2, #MCKRDY_TIMEOUT
48 ldr tmp1, [pmc, #AT91_PMC_SR]
49 tst tmp1, #AT91_PMC_MCKRDY
55 * Wait until master oscillator has stabilized.
58 mov tmp2, #MOSCRDY_TIMEOUT
62 ldr tmp1, [pmc, #AT91_PMC_SR]
63 tst tmp1, #AT91_PMC_MOSCS
69 * Wait until PLLA has locked.
72 mov tmp2, #PLLALOCK_TIMEOUT
76 ldr tmp1, [pmc, #AT91_PMC_SR]
77 tst tmp1, #AT91_PMC_LOCKA
83 * Wait until PLLB has locked.
86 mov tmp2, #PLLBLOCK_TIMEOUT
90 ldr tmp1, [pmc, #AT91_PMC_SR]
91 tst tmp1, #AT91_PMC_LOCKB
98 /* void at91_slow_clock(void __iomem *pmc, void __iomem *sdramc,
99 * void __iomem *ramc1, int memctrl)
101 ENTRY(at91_slow_clock)
102 /* Save registers on stack */
103 stmfd sp!, {r4 - r12, lr}
107 * R0 = Base address of AT91_PMC
108 * R1 = Base address of RAM Controller (SDRAM, DDRSDR, or AT91_SYS)
109 * R2 = Base address of second RAM Controller or 0 if not present
110 * R3 = Memory controller
111 * R4 = temporary register
112 * R5 = temporary register
115 /* Drain write buffer */
117 mcr p15, 0, tmp1, c7, c10, 4
119 cmp memctrl, #AT91_MEMCTRL_MC
123 * at91rm9200 Memory controller
125 /* Put SDRAM in self-refresh mode */
127 str tmp1, [sdramc, #AT91RM9200_SDRAMC_SRR]
131 * DDRSDR Memory controller
134 cmp memctrl, #AT91_MEMCTRL_DDRSDR
137 /* prepare for DDRAM self-refresh mode */
138 ldr tmp1, [sdramc, #AT91_DDRSDRC_LPR]
139 str tmp1, .saved_sam9_lpr
140 bic tmp1, #AT91_DDRSDRC_LPCB
141 orr tmp1, #AT91_DDRSDRC_LPCB_SELF_REFRESH
143 /* figure out if we use the second ram controller */
145 ldrne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
146 strne tmp2, .saved_sam9_lpr1
147 bicne tmp2, #AT91_DDRSDRC_LPCB
148 orrne tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH
150 /* Enable DDRAM self-refresh mode */
151 str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
152 strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
157 * SDRAMC Memory controller
160 /* Enable SDRAM self-refresh mode */
161 ldr tmp1, [sdramc, #AT91_SDRAMC_LPR]
162 str tmp1, .saved_sam9_lpr
164 bic tmp1, #AT91_SDRAMC_LPCB
165 orr tmp1, #AT91_SDRAMC_LPCB_SELF_REFRESH
166 str tmp1, [sdramc, #AT91_SDRAMC_LPR]
169 /* Save Master clock setting */
170 ldr tmp1, [pmc, #AT91_PMC_MCKR]
171 str tmp1, .saved_mckr
174 * Set the Master clock source to slow clock
176 bic tmp1, tmp1, #AT91_PMC_CSS
177 str tmp1, [pmc, #AT91_PMC_MCKR]
181 #ifdef SLOWDOWN_MASTER_CLOCK
183 * Set the Master Clock PRES and MDIV fields.
185 * See AT91RM9200 errata #27 and #28 for details.
188 str tmp1, [pmc, #AT91_PMC_MCKR]
193 /* Save PLLA setting and disable it */
194 ldr tmp1, [pmc, #AT91_CKGR_PLLAR]
195 str tmp1, .saved_pllar
197 mov tmp1, #AT91_PMC_PLLCOUNT
198 orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */
199 str tmp1, [pmc, #AT91_CKGR_PLLAR]
201 /* Save PLLB setting and disable it */
202 ldr tmp1, [pmc, #AT91_CKGR_PLLBR]
203 str tmp1, .saved_pllbr
205 mov tmp1, #AT91_PMC_PLLCOUNT
206 str tmp1, [pmc, #AT91_CKGR_PLLBR]
208 /* Turn off the main oscillator */
209 ldr tmp1, [pmc, #AT91_CKGR_MOR]
210 bic tmp1, tmp1, #AT91_PMC_MOSCEN
211 str tmp1, [pmc, #AT91_CKGR_MOR]
213 /* Wait for interrupt */
214 mcr p15, 0, tmp1, c7, c0, 4
216 /* Turn on the main oscillator */
217 ldr tmp1, [pmc, #AT91_CKGR_MOR]
218 orr tmp1, tmp1, #AT91_PMC_MOSCEN
219 str tmp1, [pmc, #AT91_CKGR_MOR]
223 /* Restore PLLB setting */
224 ldr tmp1, .saved_pllbr
225 str tmp1, [pmc, #AT91_CKGR_PLLBR]
227 tst tmp1, #(AT91_PMC_MUL & 0xff0000)
229 tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
235 /* Restore PLLA setting */
236 ldr tmp1, .saved_pllar
237 str tmp1, [pmc, #AT91_CKGR_PLLAR]
239 tst tmp1, #(AT91_PMC_MUL & 0xff0000)
241 tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
247 #ifdef SLOWDOWN_MASTER_CLOCK
249 * First set PRES if it was not 0,
250 * than set CSS and MDIV fields.
252 * See AT91RM9200 errata #27 and #28 for details.
254 ldr tmp1, .saved_mckr
255 tst tmp1, #AT91_PMC_PRES
257 and tmp1, tmp1, #AT91_PMC_PRES
258 str tmp1, [pmc, #AT91_PMC_MCKR]
264 * Restore master clock setting
266 2: ldr tmp1, .saved_mckr
267 str tmp1, [pmc, #AT91_PMC_MCKR]
272 * at91rm9200 Memory controller
273 * Do nothing - self-refresh is automatically disabled.
275 cmp memctrl, #AT91_MEMCTRL_MC
279 * DDRSDR Memory controller
281 cmp memctrl, #AT91_MEMCTRL_DDRSDR
283 /* Restore LPR on AT91 with DDRAM */
284 ldr tmp1, .saved_sam9_lpr
285 str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
287 /* if we use the second ram controller */
289 ldrne tmp2, .saved_sam9_lpr1
290 strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
295 * SDRAMC Memory controller
298 /* Restore LPR on AT91 with SDRAM */
299 ldr tmp1, .saved_sam9_lpr
300 str tmp1, [sdramc, #AT91_SDRAMC_LPR]
303 /* Restore registers, and return */
304 ldmfd sp!, {r4 - r12, pc}
322 ENTRY(at91_slow_clock_sz)
323 .word .-at91_slow_clock