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
36 * Wait until master clock is ready (after switching master clock source)
39 1: ldr tmp1, [pmc, #AT91_PMC_SR]
40 tst tmp1, #AT91_PMC_MCKRDY
45 * Wait until master oscillator has stabilized.
48 1: ldr tmp1, [pmc, #AT91_PMC_SR]
49 tst tmp1, #AT91_PMC_MOSCS
54 * Wait until PLLA has locked.
57 1: ldr tmp1, [pmc, #AT91_PMC_SR]
58 tst tmp1, #AT91_PMC_LOCKA
63 * Wait until PLLB has locked.
66 1: ldr tmp1, [pmc, #AT91_PMC_SR]
67 tst tmp1, #AT91_PMC_LOCKB
75 /* void at91_slow_clock(void __iomem *pmc, void __iomem *sdramc,
76 * void __iomem *ramc1, int memctrl)
78 ENTRY(at91_slow_clock)
79 /* Save registers on stack */
80 stmfd sp!, {r4 - r12, lr}
84 * R0 = Base address of AT91_PMC
85 * R1 = Base address of RAM Controller (SDRAM, DDRSDR, or AT91_SYS)
86 * R2 = Base address of second RAM Controller or 0 if not present
87 * R3 = Memory controller
88 * R4 = temporary register
89 * R5 = temporary register
92 /* Drain write buffer */
94 mcr p15, 0, tmp1, c7, c10, 4
96 cmp memctrl, #AT91_MEMCTRL_MC
100 * at91rm9200 Memory controller
102 /* Put SDRAM in self-refresh mode */
104 str tmp1, [sdramc, #AT91RM9200_SDRAMC_SRR]
108 * DDRSDR Memory controller
111 cmp memctrl, #AT91_MEMCTRL_DDRSDR
114 /* LPDDR1 --> force DDR2 mode during self-refresh */
115 ldr tmp1, [sdramc, #AT91_DDRSDRC_MDR]
116 str tmp1, .saved_sam9_mdr
117 bic tmp1, tmp1, #~AT91_DDRSDRC_MD
118 cmp tmp1, #AT91_DDRSDRC_MD_LOW_POWER_DDR
119 ldreq tmp1, [sdramc, #AT91_DDRSDRC_MDR]
120 biceq tmp1, tmp1, #AT91_DDRSDRC_MD
121 orreq tmp1, tmp1, #AT91_DDRSDRC_MD_DDR2
122 streq tmp1, [sdramc, #AT91_DDRSDRC_MDR]
124 /* prepare for DDRAM self-refresh mode */
125 ldr tmp1, [sdramc, #AT91_DDRSDRC_LPR]
126 str tmp1, .saved_sam9_lpr
127 bic tmp1, #AT91_DDRSDRC_LPCB
128 orr tmp1, #AT91_DDRSDRC_LPCB_SELF_REFRESH
130 /* figure out if we use the second ram controller */
134 ldr tmp2, [ramc1, #AT91_DDRSDRC_MDR]
135 str tmp2, .saved_sam9_mdr1
136 bic tmp2, tmp2, #~AT91_DDRSDRC_MD
137 cmp tmp2, #AT91_DDRSDRC_MD_LOW_POWER_DDR
138 ldreq tmp2, [ramc1, #AT91_DDRSDRC_MDR]
139 biceq tmp2, tmp2, #AT91_DDRSDRC_MD
140 orreq tmp2, tmp2, #AT91_DDRSDRC_MD_DDR2
141 streq tmp2, [ramc1, #AT91_DDRSDRC_MDR]
143 ldr tmp2, [ramc1, #AT91_DDRSDRC_LPR]
144 str tmp2, .saved_sam9_lpr1
145 bic tmp2, #AT91_DDRSDRC_LPCB
146 orr tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH
148 /* Enable DDRAM self-refresh mode */
149 str tmp2, [ramc1, #AT91_DDRSDRC_LPR]
151 str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
156 * SDRAMC Memory controller
159 /* Enable SDRAM self-refresh mode */
160 ldr tmp1, [sdramc, #AT91_SDRAMC_LPR]
161 str tmp1, .saved_sam9_lpr
163 bic tmp1, #AT91_SDRAMC_LPCB
164 orr tmp1, #AT91_SDRAMC_LPCB_SELF_REFRESH
165 str tmp1, [sdramc, #AT91_SDRAMC_LPR]
168 /* Save Master clock setting */
169 ldr tmp1, [pmc, #AT91_PMC_MCKR]
170 str tmp1, .saved_mckr
173 * Set the Master clock source to slow clock
175 bic tmp1, tmp1, #AT91_PMC_CSS
176 str tmp1, [pmc, #AT91_PMC_MCKR]
180 #ifdef SLOWDOWN_MASTER_CLOCK
182 * Set the Master Clock PRES and MDIV fields.
184 * See AT91RM9200 errata #27 and #28 for details.
187 str tmp1, [pmc, #AT91_PMC_MCKR]
192 /* Save PLLA setting and disable it */
193 ldr tmp1, [pmc, #AT91_CKGR_PLLAR]
194 str tmp1, .saved_pllar
196 mov tmp1, #AT91_PMC_PLLCOUNT
197 orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */
198 str tmp1, [pmc, #AT91_CKGR_PLLAR]
200 /* Save PLLB setting and disable it */
201 ldr tmp1, [pmc, #AT91_CKGR_PLLBR]
202 str tmp1, .saved_pllbr
204 mov tmp1, #AT91_PMC_PLLCOUNT
205 str tmp1, [pmc, #AT91_CKGR_PLLBR]
207 /* Turn off the main oscillator */
208 ldr tmp1, [pmc, #AT91_CKGR_MOR]
209 bic tmp1, tmp1, #AT91_PMC_MOSCEN
210 orr tmp1, tmp1, #AT91_PMC_KEY
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 orr tmp1, tmp1, #AT91_PMC_KEY
220 str tmp1, [pmc, #AT91_CKGR_MOR]
224 /* Restore PLLB setting */
225 ldr tmp1, .saved_pllbr
226 str tmp1, [pmc, #AT91_CKGR_PLLBR]
228 tst tmp1, #(AT91_PMC_MUL & 0xff0000)
230 tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
236 /* Restore PLLA setting */
237 ldr tmp1, .saved_pllar
238 str tmp1, [pmc, #AT91_CKGR_PLLAR]
240 tst tmp1, #(AT91_PMC_MUL & 0xff0000)
242 tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
248 #ifdef SLOWDOWN_MASTER_CLOCK
250 * First set PRES if it was not 0,
251 * than set CSS and MDIV fields.
253 * See AT91RM9200 errata #27 and #28 for details.
255 ldr tmp1, .saved_mckr
256 tst tmp1, #AT91_PMC_PRES
258 and tmp1, tmp1, #AT91_PMC_PRES
259 str tmp1, [pmc, #AT91_PMC_MCKR]
265 * Restore master clock setting
267 2: ldr tmp1, .saved_mckr
268 str tmp1, [pmc, #AT91_PMC_MCKR]
273 * at91rm9200 Memory controller
274 * Do nothing - self-refresh is automatically disabled.
276 cmp memctrl, #AT91_MEMCTRL_MC
280 * DDRSDR Memory controller
282 cmp memctrl, #AT91_MEMCTRL_DDRSDR
284 /* Restore MDR in case of LPDDR1 */
285 ldr tmp1, .saved_sam9_mdr
286 str tmp1, [sdramc, #AT91_DDRSDRC_MDR]
287 /* Restore LPR on AT91 with DDRAM */
288 ldr tmp1, .saved_sam9_lpr
289 str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
291 /* if we use the second ram controller */
293 ldrne tmp2, .saved_sam9_mdr1
294 strne tmp2, [ramc1, #AT91_DDRSDRC_MDR]
295 ldrne tmp2, .saved_sam9_lpr1
296 strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
301 * SDRAMC Memory controller
304 /* Restore LPR on AT91 with SDRAM */
305 ldr tmp1, .saved_sam9_lpr
306 str tmp1, [sdramc, #AT91_SDRAMC_LPR]
309 /* Restore registers, and return */
310 ldmfd sp!, {r4 - r12, pc}
334 ENTRY(at91_slow_clock_sz)
335 .word .-at91_slow_clock