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
73 /* void at91_slow_clock(void __iomem *pmc, void __iomem *sdramc,
74 * void __iomem *ramc1, int memctrl)
76 ENTRY(at91_slow_clock)
77 /* Save registers on stack */
78 stmfd sp!, {r4 - r12, lr}
82 * R0 = Base address of AT91_PMC
83 * R1 = Base address of RAM Controller (SDRAM, DDRSDR, or AT91_SYS)
84 * R2 = Base address of second RAM Controller or 0 if not present
85 * R3 = Memory controller
86 * R4 = temporary register
87 * R5 = temporary register
90 /* Drain write buffer */
92 mcr p15, 0, tmp1, c7, c10, 4
94 cmp memctrl, #AT91_MEMCTRL_MC
98 * at91rm9200 Memory controller
100 /* Put SDRAM in self-refresh mode */
102 str tmp1, [sdramc, #AT91RM9200_SDRAMC_SRR]
106 * DDRSDR Memory controller
109 cmp memctrl, #AT91_MEMCTRL_DDRSDR
112 /* prepare for DDRAM self-refresh mode */
113 ldr tmp1, [sdramc, #AT91_DDRSDRC_LPR]
114 str tmp1, .saved_sam9_lpr
115 bic tmp1, #AT91_DDRSDRC_LPCB
116 orr tmp1, #AT91_DDRSDRC_LPCB_SELF_REFRESH
118 /* figure out if we use the second ram controller */
120 ldrne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
121 strne tmp2, .saved_sam9_lpr1
122 bicne tmp2, #AT91_DDRSDRC_LPCB
123 orrne tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH
125 /* Enable DDRAM self-refresh mode */
126 str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
127 strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
132 * SDRAMC Memory controller
135 /* Enable SDRAM self-refresh mode */
136 ldr tmp1, [sdramc, #AT91_SDRAMC_LPR]
137 str tmp1, .saved_sam9_lpr
139 bic tmp1, #AT91_SDRAMC_LPCB
140 orr tmp1, #AT91_SDRAMC_LPCB_SELF_REFRESH
141 str tmp1, [sdramc, #AT91_SDRAMC_LPR]
144 /* Save Master clock setting */
145 ldr tmp1, [pmc, #AT91_PMC_MCKR]
146 str tmp1, .saved_mckr
149 * Set the Master clock source to slow clock
151 bic tmp1, tmp1, #AT91_PMC_CSS
152 str tmp1, [pmc, #AT91_PMC_MCKR]
156 #ifdef SLOWDOWN_MASTER_CLOCK
158 * Set the Master Clock PRES and MDIV fields.
160 * See AT91RM9200 errata #27 and #28 for details.
163 str tmp1, [pmc, #AT91_PMC_MCKR]
168 /* Save PLLA setting and disable it */
169 ldr tmp1, [pmc, #AT91_CKGR_PLLAR]
170 str tmp1, .saved_pllar
172 mov tmp1, #AT91_PMC_PLLCOUNT
173 orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */
174 str tmp1, [pmc, #AT91_CKGR_PLLAR]
176 /* Save PLLB setting and disable it */
177 ldr tmp1, [pmc, #AT91_CKGR_PLLBR]
178 str tmp1, .saved_pllbr
180 mov tmp1, #AT91_PMC_PLLCOUNT
181 str tmp1, [pmc, #AT91_CKGR_PLLBR]
183 /* Turn off the main oscillator */
184 ldr tmp1, [pmc, #AT91_CKGR_MOR]
185 bic tmp1, tmp1, #AT91_PMC_MOSCEN
186 str tmp1, [pmc, #AT91_CKGR_MOR]
188 /* Wait for interrupt */
189 mcr p15, 0, tmp1, c7, c0, 4
191 /* Turn on the main oscillator */
192 ldr tmp1, [pmc, #AT91_CKGR_MOR]
193 orr tmp1, tmp1, #AT91_PMC_MOSCEN
194 str tmp1, [pmc, #AT91_CKGR_MOR]
198 /* Restore PLLB setting */
199 ldr tmp1, .saved_pllbr
200 str tmp1, [pmc, #AT91_CKGR_PLLBR]
202 tst tmp1, #(AT91_PMC_MUL & 0xff0000)
204 tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
210 /* Restore PLLA setting */
211 ldr tmp1, .saved_pllar
212 str tmp1, [pmc, #AT91_CKGR_PLLAR]
214 tst tmp1, #(AT91_PMC_MUL & 0xff0000)
216 tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
222 #ifdef SLOWDOWN_MASTER_CLOCK
224 * First set PRES if it was not 0,
225 * than set CSS and MDIV fields.
227 * See AT91RM9200 errata #27 and #28 for details.
229 ldr tmp1, .saved_mckr
230 tst tmp1, #AT91_PMC_PRES
232 and tmp1, tmp1, #AT91_PMC_PRES
233 str tmp1, [pmc, #AT91_PMC_MCKR]
239 * Restore master clock setting
241 2: ldr tmp1, .saved_mckr
242 str tmp1, [pmc, #AT91_PMC_MCKR]
247 * at91rm9200 Memory controller
248 * Do nothing - self-refresh is automatically disabled.
250 cmp memctrl, #AT91_MEMCTRL_MC
254 * DDRSDR Memory controller
256 cmp memctrl, #AT91_MEMCTRL_DDRSDR
258 /* Restore LPR on AT91 with DDRAM */
259 ldr tmp1, .saved_sam9_lpr
260 str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
262 /* if we use the second ram controller */
264 ldrne tmp2, .saved_sam9_lpr1
265 strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
270 * SDRAMC Memory controller
273 /* Restore LPR on AT91 with SDRAM */
274 ldr tmp1, .saved_sam9_lpr
275 str tmp1, [sdramc, #AT91_SDRAMC_LPR]
278 /* Restore registers, and return */
279 ldmfd sp!, {r4 - r12, pc}
297 ENTRY(at91_slow_clock_sz)
298 .word .-at91_slow_clock