Commit | Line | Data |
---|---|---|
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 | ||
7dca3343 | 19 | #if defined(CONFIG_ARCH_AT91RM9200) |
eaad2db0 AV |
20 | #include <mach/at91rm9200_mc.h> |
21 | #elif defined(CONFIG_ARCH_AT91CAP9) | |
22 | #include <mach/at91cap9_ddrsdr.h> | |
7dca3343 NF |
23 | #elif defined(CONFIG_ARCH_AT91SAM9G45) |
24 | #include <mach/at91sam9_ddrsdr.h> | |
eaad2db0 AV |
25 | #else |
26 | #include <mach/at91sam9_sdramc.h> | |
27 | #endif | |
28 | ||
29 | ||
30 | #ifdef CONFIG_ARCH_AT91SAM9263 | |
31 | /* | |
32 | * FIXME either or both the SDRAM controllers (EB0, EB1) might be in use; | |
33 | * handle those cases both here and in the Suspend-To-RAM support. | |
34 | */ | |
eaad2db0 AV |
35 | #warning Assuming EB1 SDRAM controller is *NOT* used |
36 | #endif | |
37 | ||
38 | /* | |
39 | * When SLOWDOWN_MASTER_CLOCK is defined we will also slow down the Master | |
40 | * clock during suspend by adjusting its prescalar and divisor. | |
41 | * NOTE: This hasn't been shown to be stable on SAM9s; and on the RM9200 there | |
42 | * are errata regarding adjusting the prescalar and divisor. | |
43 | */ | |
44 | #undef SLOWDOWN_MASTER_CLOCK | |
45 | ||
46 | #define MCKRDY_TIMEOUT 1000 | |
47 | #define MOSCRDY_TIMEOUT 1000 | |
48 | #define PLLALOCK_TIMEOUT 1000 | |
49 | #define PLLBLOCK_TIMEOUT 1000 | |
50 | ||
51 | ||
52 | /* | |
53 | * Wait until master clock is ready (after switching master clock source) | |
54 | */ | |
55 | .macro wait_mckrdy | |
56 | mov r4, #MCKRDY_TIMEOUT | |
57 | 1: sub r4, r4, #1 | |
58 | cmp r4, #0 | |
59 | beq 2f | |
60 | ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)] | |
61 | tst r3, #AT91_PMC_MCKRDY | |
62 | beq 1b | |
63 | 2: | |
64 | .endm | |
65 | ||
66 | /* | |
67 | * Wait until master oscillator has stabilized. | |
68 | */ | |
69 | .macro wait_moscrdy | |
70 | mov r4, #MOSCRDY_TIMEOUT | |
71 | 1: sub r4, r4, #1 | |
72 | cmp r4, #0 | |
73 | beq 2f | |
74 | ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)] | |
75 | tst r3, #AT91_PMC_MOSCS | |
76 | beq 1b | |
77 | 2: | |
78 | .endm | |
79 | ||
80 | /* | |
81 | * Wait until PLLA has locked. | |
82 | */ | |
83 | .macro wait_pllalock | |
84 | mov r4, #PLLALOCK_TIMEOUT | |
85 | 1: sub r4, r4, #1 | |
86 | cmp r4, #0 | |
87 | beq 2f | |
88 | ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)] | |
89 | tst r3, #AT91_PMC_LOCKA | |
90 | beq 1b | |
91 | 2: | |
92 | .endm | |
93 | ||
94 | /* | |
95 | * Wait until PLLB has locked. | |
96 | */ | |
97 | .macro wait_pllblock | |
98 | mov r4, #PLLBLOCK_TIMEOUT | |
99 | 1: sub r4, r4, #1 | |
100 | cmp r4, #0 | |
101 | beq 2f | |
102 | ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)] | |
103 | tst r3, #AT91_PMC_LOCKB | |
104 | beq 1b | |
105 | 2: | |
106 | .endm | |
107 | ||
108 | .text | |
109 | ||
110 | ENTRY(at91_slow_clock) | |
111 | /* Save registers on stack */ | |
112 | stmfd sp!, {r0 - r12, lr} | |
113 | ||
114 | /* | |
115 | * Register usage: | |
116 | * R1 = Base address of AT91_PMC | |
7dca3343 | 117 | * R2 = Base address of RAM Controller (SDRAM, DDRSDR, or AT91_SYS) |
eaad2db0 AV |
118 | * R3 = temporary register |
119 | * R4 = temporary register | |
7dca3343 | 120 | * R5 = Base address of second RAM Controller or 0 if not present |
eaad2db0 AV |
121 | */ |
122 | ldr r1, .at91_va_base_pmc | |
123 | ldr r2, .at91_va_base_sdramc | |
7dca3343 | 124 | ldr r5, .at91_va_base_ramc1 |
eaad2db0 AV |
125 | |
126 | /* Drain write buffer */ | |
a2a571b7 | 127 | mov r0, #0 |
eaad2db0 AV |
128 | mcr p15, 0, r0, c7, c10, 4 |
129 | ||
130 | #ifdef CONFIG_ARCH_AT91RM9200 | |
131 | /* Put SDRAM in self-refresh mode */ | |
132 | mov r3, #1 | |
133 | str r3, [r2, #AT91_SDRAMC_SRR] | |
7dca3343 NF |
134 | #elif defined(CONFIG_ARCH_AT91CAP9) \ |
135 | || defined(CONFIG_ARCH_AT91SAM9G45) | |
eaad2db0 | 136 | |
7dca3343 NF |
137 | /* prepare for DDRAM self-refresh mode */ |
138 | ldr r3, [r2, #AT91_DDRSDRC_LPR] | |
139 | str r3, .saved_sam9_lpr | |
140 | bic r3, #AT91_DDRSDRC_LPCB | |
141 | orr r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH | |
142 | ||
143 | /* figure out if we use the second ram controller */ | |
144 | cmp r5, #0 | |
145 | ldrne r4, [r5, #AT91_DDRSDRC_LPR] | |
146 | strne r4, .saved_sam9_lpr1 | |
147 | bicne r4, #AT91_DDRSDRC_LPCB | |
148 | orrne r4, #AT91_DDRSDRC_LPCB_SELF_REFRESH | |
149 | ||
150 | /* Enable DDRAM self-refresh mode */ | |
151 | str r3, [r2, #AT91_DDRSDRC_LPR] | |
152 | strne r4, [r5, #AT91_DDRSDRC_LPR] | |
eaad2db0 AV |
153 | #else |
154 | /* Enable SDRAM self-refresh mode */ | |
7dca3343 | 155 | ldr r3, [r2, #AT91_SDRAMC_LPR] |
eaad2db0 AV |
156 | str r3, .saved_sam9_lpr |
157 | ||
7dca3343 NF |
158 | bic r3, #AT91_SDRAMC_LPCB |
159 | orr r3, #AT91_SDRAMC_LPCB_SELF_REFRESH | |
160 | str r3, [r2, #AT91_SDRAMC_LPR] | |
eaad2db0 AV |
161 | #endif |
162 | ||
163 | /* Save Master clock setting */ | |
164 | ldr r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)] | |
165 | str r3, .saved_mckr | |
166 | ||
167 | /* | |
168 | * Set the Master clock source to slow clock | |
169 | */ | |
170 | bic r3, r3, #AT91_PMC_CSS | |
171 | str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)] | |
172 | ||
173 | wait_mckrdy | |
174 | ||
175 | #ifdef SLOWDOWN_MASTER_CLOCK | |
176 | /* | |
177 | * Set the Master Clock PRES and MDIV fields. | |
178 | * | |
179 | * See AT91RM9200 errata #27 and #28 for details. | |
180 | */ | |
181 | mov r3, #0 | |
182 | str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)] | |
183 | ||
184 | wait_mckrdy | |
185 | #endif | |
186 | ||
187 | /* Save PLLA setting and disable it */ | |
188 | ldr r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)] | |
189 | str r3, .saved_pllar | |
190 | ||
191 | mov r3, #AT91_PMC_PLLCOUNT | |
192 | orr r3, r3, #(1 << 29) /* bit 29 always set */ | |
193 | str r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)] | |
194 | ||
eaad2db0 AV |
195 | /* Save PLLB setting and disable it */ |
196 | ldr r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)] | |
197 | str r3, .saved_pllbr | |
198 | ||
199 | mov r3, #AT91_PMC_PLLCOUNT | |
200 | str r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)] | |
201 | ||
eaad2db0 AV |
202 | /* Turn off the main oscillator */ |
203 | ldr r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)] | |
204 | bic r3, r3, #AT91_PMC_MOSCEN | |
205 | str r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)] | |
206 | ||
207 | /* Wait for interrupt */ | |
208 | mcr p15, 0, r0, c7, c0, 4 | |
209 | ||
210 | /* Turn on the main oscillator */ | |
211 | ldr r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)] | |
212 | orr r3, r3, #AT91_PMC_MOSCEN | |
213 | str r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)] | |
214 | ||
215 | wait_moscrdy | |
216 | ||
217 | /* Restore PLLB setting */ | |
218 | ldr r3, .saved_pllbr | |
219 | str r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)] | |
220 | ||
9823f1a8 AL |
221 | tst r3, #(AT91_PMC_MUL & 0xff0000) |
222 | bne 1f | |
223 | tst r3, #(AT91_PMC_MUL & ~0xff0000) | |
224 | beq 2f | |
225 | 1: | |
eaad2db0 | 226 | wait_pllblock |
9823f1a8 | 227 | 2: |
eaad2db0 AV |
228 | |
229 | /* Restore PLLA setting */ | |
230 | ldr r3, .saved_pllar | |
231 | str r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)] | |
232 | ||
9823f1a8 AL |
233 | tst r3, #(AT91_PMC_MUL & 0xff0000) |
234 | bne 3f | |
235 | tst r3, #(AT91_PMC_MUL & ~0xff0000) | |
236 | beq 4f | |
237 | 3: | |
eaad2db0 | 238 | wait_pllalock |
9823f1a8 | 239 | 4: |
eaad2db0 AV |
240 | |
241 | #ifdef SLOWDOWN_MASTER_CLOCK | |
242 | /* | |
243 | * First set PRES if it was not 0, | |
244 | * than set CSS and MDIV fields. | |
245 | * | |
246 | * See AT91RM9200 errata #27 and #28 for details. | |
247 | */ | |
248 | ldr r3, .saved_mckr | |
249 | tst r3, #AT91_PMC_PRES | |
250 | beq 2f | |
251 | and r3, r3, #AT91_PMC_PRES | |
252 | str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)] | |
253 | ||
254 | wait_mckrdy | |
255 | #endif | |
256 | ||
257 | /* | |
258 | * Restore master clock setting | |
259 | */ | |
260 | 2: ldr r3, .saved_mckr | |
261 | str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)] | |
262 | ||
263 | wait_mckrdy | |
264 | ||
265 | #ifdef CONFIG_ARCH_AT91RM9200 | |
266 | /* Do nothing - self-refresh is automatically disabled. */ | |
7dca3343 NF |
267 | #elif defined(CONFIG_ARCH_AT91CAP9) \ |
268 | || defined(CONFIG_ARCH_AT91SAM9G45) | |
269 | /* Restore LPR on AT91 with DDRAM */ | |
eaad2db0 | 270 | ldr r3, .saved_sam9_lpr |
7dca3343 NF |
271 | str r3, [r2, #AT91_DDRSDRC_LPR] |
272 | ||
273 | /* if we use the second ram controller */ | |
274 | cmp r5, #0 | |
275 | ldrne r4, .saved_sam9_lpr1 | |
276 | strne r4, [r5, #AT91_DDRSDRC_LPR] | |
277 | ||
eaad2db0 | 278 | #else |
7dca3343 | 279 | /* Restore LPR on AT91 with SDRAM */ |
eaad2db0 | 280 | ldr r3, .saved_sam9_lpr |
7dca3343 | 281 | str r3, [r2, #AT91_SDRAMC_LPR] |
eaad2db0 AV |
282 | #endif |
283 | ||
284 | /* Restore registers, and return */ | |
285 | ldmfd sp!, {r0 - r12, pc} | |
286 | ||
287 | ||
288 | .saved_mckr: | |
289 | .word 0 | |
290 | ||
291 | .saved_pllar: | |
292 | .word 0 | |
293 | ||
294 | .saved_pllbr: | |
295 | .word 0 | |
296 | ||
297 | .saved_sam9_lpr: | |
298 | .word 0 | |
299 | ||
7dca3343 NF |
300 | .saved_sam9_lpr1: |
301 | .word 0 | |
302 | ||
eaad2db0 AV |
303 | .at91_va_base_pmc: |
304 | .word AT91_VA_BASE_SYS + AT91_PMC | |
305 | ||
306 | #ifdef CONFIG_ARCH_AT91RM9200 | |
307 | .at91_va_base_sdramc: | |
308 | .word AT91_VA_BASE_SYS | |
7dca3343 NF |
309 | #elif defined(CONFIG_ARCH_AT91CAP9) \ |
310 | || defined(CONFIG_ARCH_AT91SAM9G45) | |
eaad2db0 | 311 | .at91_va_base_sdramc: |
7dca3343 | 312 | .word AT91_VA_BASE_SYS + AT91_DDRSDRC0 |
eaad2db0 AV |
313 | #else |
314 | .at91_va_base_sdramc: | |
7dca3343 NF |
315 | .word AT91_VA_BASE_SYS + AT91_SDRAMC0 |
316 | #endif | |
317 | ||
318 | .at91_va_base_ramc1: | |
319 | #if defined(CONFIG_ARCH_AT91SAM9G45) | |
320 | .word AT91_VA_BASE_SYS + AT91_DDRSDRC1 | |
321 | #else | |
322 | .word 0 | |
eaad2db0 AV |
323 | #endif |
324 | ||
325 | ENTRY(at91_slow_clock_sz) | |
326 | .word .-at91_slow_clock |