]> bbs.cooldavid.org Git - net-next-2.6.git/blame - arch/arm/mach-at91/pm_slowclock.S
Merge branch 'master' of git://dev.medozas.de/linux
[net-next-2.6.git] / arch / arm / mach-at91 / pm_slowclock.S
CommitLineData
eaad2db0
AV
1/*
2 * arch/arm/mach-at91/pm_slow_clock.S
3 *
4 * Copyright (C) 2006 Savin Zlobec
5 *
6 * AT91SAM9 support:
7 * Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee
8 *
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.
12 *
13 */
14
15#include <linux/linkage.h>
16#include <mach/hardware.h>
17#include <mach/at91_pmc.h>
18
19#ifdef CONFIG_ARCH_AT91RM9200
20#include <mach/at91rm9200_mc.h>
21#elif defined(CONFIG_ARCH_AT91CAP9)
22#include <mach/at91cap9_ddrsdr.h>
23#else
24#include <mach/at91sam9_sdramc.h>
25#endif
26
27
28#ifdef CONFIG_ARCH_AT91SAM9263
29/*
30 * FIXME either or both the SDRAM controllers (EB0, EB1) might be in use;
31 * handle those cases both here and in the Suspend-To-RAM support.
32 */
33#define AT91_SDRAMC AT91_SDRAMC0
34#warning Assuming EB1 SDRAM controller is *NOT* used
35#endif
36
37/*
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.
42 */
43#undef SLOWDOWN_MASTER_CLOCK
44
45#define MCKRDY_TIMEOUT 1000
46#define MOSCRDY_TIMEOUT 1000
47#define PLLALOCK_TIMEOUT 1000
48#define PLLBLOCK_TIMEOUT 1000
49
50
51/*
52 * Wait until master clock is ready (after switching master clock source)
53 */
54 .macro wait_mckrdy
55 mov r4, #MCKRDY_TIMEOUT
561: sub r4, r4, #1
57 cmp r4, #0
58 beq 2f
59 ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
60 tst r3, #AT91_PMC_MCKRDY
61 beq 1b
622:
63 .endm
64
65/*
66 * Wait until master oscillator has stabilized.
67 */
68 .macro wait_moscrdy
69 mov r4, #MOSCRDY_TIMEOUT
701: sub r4, r4, #1
71 cmp r4, #0
72 beq 2f
73 ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
74 tst r3, #AT91_PMC_MOSCS
75 beq 1b
762:
77 .endm
78
79/*
80 * Wait until PLLA has locked.
81 */
82 .macro wait_pllalock
83 mov r4, #PLLALOCK_TIMEOUT
841: sub r4, r4, #1
85 cmp r4, #0
86 beq 2f
87 ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
88 tst r3, #AT91_PMC_LOCKA
89 beq 1b
902:
91 .endm
92
93/*
94 * Wait until PLLB has locked.
95 */
96 .macro wait_pllblock
97 mov r4, #PLLBLOCK_TIMEOUT
981: sub r4, r4, #1
99 cmp r4, #0
100 beq 2f
101 ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
102 tst r3, #AT91_PMC_LOCKB
103 beq 1b
1042:
105 .endm
106
107 .text
108
109ENTRY(at91_slow_clock)
110 /* Save registers on stack */
111 stmfd sp!, {r0 - r12, lr}
112
113 /*
114 * Register usage:
115 * R1 = Base address of AT91_PMC
116 * R2 = Base address of AT91_SDRAMC (or AT91_SYS on AT91RM9200)
117 * R3 = temporary register
118 * R4 = temporary register
119 */
120 ldr r1, .at91_va_base_pmc
121 ldr r2, .at91_va_base_sdramc
122
123 /* Drain write buffer */
124 mcr p15, 0, r0, c7, c10, 4
125
126#ifdef CONFIG_ARCH_AT91RM9200
127 /* Put SDRAM in self-refresh mode */
128 mov r3, #1
129 str r3, [r2, #AT91_SDRAMC_SRR]
130#elif defined(CONFIG_ARCH_AT91CAP9)
131 /* Enable SDRAM self-refresh mode */
132 ldr r3, [r2, #AT91_DDRSDRC_LPR - AT91_DDRSDRC]
133 str r3, .saved_sam9_lpr
134
135 mov r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
136 str r3, [r2, #AT91_DDRSDRC_LPR - AT91_DDRSDRC]
137#else
138 /* Enable SDRAM self-refresh mode */
139 ldr r3, [r2, #AT91_SDRAMC_LPR - AT91_SDRAMC]
140 str r3, .saved_sam9_lpr
141
142 mov r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
143 str r3, [r2, #AT91_SDRAMC_LPR - AT91_SDRAMC]
144#endif
145
146 /* Save Master clock setting */
147 ldr r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
148 str r3, .saved_mckr
149
150 /*
151 * Set the Master clock source to slow clock
152 */
153 bic r3, r3, #AT91_PMC_CSS
154 str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
155
156 wait_mckrdy
157
158#ifdef SLOWDOWN_MASTER_CLOCK
159 /*
160 * Set the Master Clock PRES and MDIV fields.
161 *
162 * See AT91RM9200 errata #27 and #28 for details.
163 */
164 mov r3, #0
165 str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
166
167 wait_mckrdy
168#endif
169
170 /* Save PLLA setting and disable it */
171 ldr r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
172 str r3, .saved_pllar
173
174 mov r3, #AT91_PMC_PLLCOUNT
175 orr r3, r3, #(1 << 29) /* bit 29 always set */
176 str r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
177
eaad2db0
AV
178 /* Save PLLB setting and disable it */
179 ldr r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
180 str r3, .saved_pllbr
181
182 mov r3, #AT91_PMC_PLLCOUNT
183 str r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
184
eaad2db0
AV
185 /* Turn off the main oscillator */
186 ldr r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
187 bic r3, r3, #AT91_PMC_MOSCEN
188 str r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
189
190 /* Wait for interrupt */
191 mcr p15, 0, r0, c7, c0, 4
192
193 /* Turn on the main oscillator */
194 ldr r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
195 orr r3, r3, #AT91_PMC_MOSCEN
196 str r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
197
198 wait_moscrdy
199
200 /* Restore PLLB setting */
201 ldr r3, .saved_pllbr
202 str r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
203
9823f1a8
AL
204 tst r3, #(AT91_PMC_MUL & 0xff0000)
205 bne 1f
206 tst r3, #(AT91_PMC_MUL & ~0xff0000)
207 beq 2f
2081:
eaad2db0 209 wait_pllblock
9823f1a8 2102:
eaad2db0
AV
211
212 /* Restore PLLA setting */
213 ldr r3, .saved_pllar
214 str r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
215
9823f1a8
AL
216 tst r3, #(AT91_PMC_MUL & 0xff0000)
217 bne 3f
218 tst r3, #(AT91_PMC_MUL & ~0xff0000)
219 beq 4f
2203:
eaad2db0 221 wait_pllalock
9823f1a8 2224:
eaad2db0
AV
223
224#ifdef SLOWDOWN_MASTER_CLOCK
225 /*
226 * First set PRES if it was not 0,
227 * than set CSS and MDIV fields.
228 *
229 * See AT91RM9200 errata #27 and #28 for details.
230 */
231 ldr r3, .saved_mckr
232 tst r3, #AT91_PMC_PRES
233 beq 2f
234 and r3, r3, #AT91_PMC_PRES
235 str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
236
237 wait_mckrdy
238#endif
239
240 /*
241 * Restore master clock setting
242 */
2432: ldr r3, .saved_mckr
244 str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
245
246 wait_mckrdy
247
248#ifdef CONFIG_ARCH_AT91RM9200
249 /* Do nothing - self-refresh is automatically disabled. */
250#elif defined(CONFIG_ARCH_AT91CAP9)
251 /* Restore LPR on AT91CAP9 */
252 ldr r3, .saved_sam9_lpr
253 str r3, [r2, #AT91_DDRSDRC_LPR - AT91_DDRSDRC]
254#else
255 /* Restore LPR on AT91SAM9 */
256 ldr r3, .saved_sam9_lpr
257 str r3, [r2, #AT91_SDRAMC_LPR - AT91_SDRAMC]
258#endif
259
260 /* Restore registers, and return */
261 ldmfd sp!, {r0 - r12, pc}
262
263
264.saved_mckr:
265 .word 0
266
267.saved_pllar:
268 .word 0
269
270.saved_pllbr:
271 .word 0
272
273.saved_sam9_lpr:
274 .word 0
275
276.at91_va_base_pmc:
277 .word AT91_VA_BASE_SYS + AT91_PMC
278
279#ifdef CONFIG_ARCH_AT91RM9200
280.at91_va_base_sdramc:
281 .word AT91_VA_BASE_SYS
282#elif defined(CONFIG_ARCH_AT91CAP9)
283.at91_va_base_sdramc:
284 .word AT91_VA_BASE_SYS + AT91_DDRSDRC
285#else
286.at91_va_base_sdramc:
287 .word AT91_VA_BASE_SYS + AT91_SDRAMC
288#endif
289
290ENTRY(at91_slow_clock_sz)
291 .word .-at91_slow_clock