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 | */ | |
eaad2db0 | 14 | #include <linux/linkage.h> |
2edb90ae | 15 | #include <linux/clk/at91_pmc.h> |
eaad2db0 | 16 | #include <mach/hardware.h> |
f363c407 | 17 | #include <mach/at91_ramc.h> |
eaad2db0 | 18 | |
0ab285c2 WY |
19 | #define SRAMC_SELF_FRESH_ACTIVE 0x01 |
20 | #define SRAMC_SELF_FRESH_EXIT 0x00 | |
21 | ||
8ff12ad3 | 22 | pmc .req r0 |
fb7e197b JCPV |
23 | tmp1 .req r4 |
24 | tmp2 .req r5 | |
eaad2db0 AV |
25 | |
26 | /* | |
27 | * Wait until master clock is ready (after switching master clock source) | |
28 | */ | |
29 | .macro wait_mckrdy | |
ad4a38d2 | 30 | 1: ldr tmp1, [pmc, #AT91_PMC_SR] |
0dcfed14 | 31 | tst tmp1, #AT91_PMC_MCKRDY |
eaad2db0 | 32 | beq 1b |
eaad2db0 AV |
33 | .endm |
34 | ||
35 | /* | |
36 | * Wait until master oscillator has stabilized. | |
37 | */ | |
38 | .macro wait_moscrdy | |
ad4a38d2 | 39 | 1: ldr tmp1, [pmc, #AT91_PMC_SR] |
0dcfed14 | 40 | tst tmp1, #AT91_PMC_MOSCS |
eaad2db0 | 41 | beq 1b |
eaad2db0 AV |
42 | .endm |
43 | ||
44 | /* | |
45 | * Wait until PLLA has locked. | |
46 | */ | |
47 | .macro wait_pllalock | |
ad4a38d2 | 48 | 1: ldr tmp1, [pmc, #AT91_PMC_SR] |
0dcfed14 | 49 | tst tmp1, #AT91_PMC_LOCKA |
eaad2db0 | 50 | beq 1b |
eaad2db0 AV |
51 | .endm |
52 | ||
eaad2db0 AV |
53 | .text |
54 | ||
e7b848d7 WY |
55 | .arm |
56 | ||
fb7e197b JCPV |
57 | /* void at91_slow_clock(void __iomem *pmc, void __iomem *sdramc, |
58 | * void __iomem *ramc1, int memctrl) | |
59 | */ | |
eaad2db0 AV |
60 | ENTRY(at91_slow_clock) |
61 | /* Save registers on stack */ | |
fb7e197b | 62 | stmfd sp!, {r4 - r12, lr} |
eaad2db0 AV |
63 | |
64 | /* | |
65 | * Register usage: | |
8ff12ad3 JCPV |
66 | * R0 = Base address of AT91_PMC |
67 | * R1 = Base address of RAM Controller (SDRAM, DDRSDR, or AT91_SYS) | |
68 | * R2 = Base address of second RAM Controller or 0 if not present | |
fb7e197b | 69 | * R3 = Memory controller |
eaad2db0 | 70 | * R4 = temporary register |
fb7e197b | 71 | * R5 = temporary register |
eaad2db0 | 72 | */ |
eaad2db0 AV |
73 | |
74 | /* Drain write buffer */ | |
0dcfed14 JCPV |
75 | mov tmp1, #0 |
76 | mcr p15, 0, tmp1, c7, c10, 4 | |
eaad2db0 | 77 | |
0ab285c2 WY |
78 | str r0, .pmc_base |
79 | str r1, .sramc_base | |
80 | str r2, .sramc1_base | |
81 | str r3, .memtype | |
fb7e197b | 82 | |
0ab285c2 WY |
83 | /* Active the self-refresh mode */ |
84 | mov r0, #SRAMC_SELF_FRESH_ACTIVE | |
85 | bl at91_sramc_self_refresh | |
fb7e197b | 86 | |
0ab285c2 | 87 | ldr pmc, .pmc_base |
eaad2db0 | 88 | |
eaad2db0 | 89 | /* Save Master clock setting */ |
b5514952 | 90 | ldr tmp1, [pmc, #AT91_PMC_MCKR] |
0dcfed14 | 91 | str tmp1, .saved_mckr |
eaad2db0 AV |
92 | |
93 | /* | |
94 | * Set the Master clock source to slow clock | |
95 | */ | |
0dcfed14 | 96 | bic tmp1, tmp1, #AT91_PMC_CSS |
b5514952 | 97 | str tmp1, [pmc, #AT91_PMC_MCKR] |
eaad2db0 AV |
98 | |
99 | wait_mckrdy | |
100 | ||
eaad2db0 | 101 | /* Save PLLA setting and disable it */ |
b5514952 | 102 | ldr tmp1, [pmc, #AT91_CKGR_PLLAR] |
0dcfed14 | 103 | str tmp1, .saved_pllar |
eaad2db0 | 104 | |
0dcfed14 JCPV |
105 | mov tmp1, #AT91_PMC_PLLCOUNT |
106 | orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ | |
b5514952 | 107 | str tmp1, [pmc, #AT91_CKGR_PLLAR] |
eaad2db0 | 108 | |
eaad2db0 | 109 | /* Turn off the main oscillator */ |
b5514952 | 110 | ldr tmp1, [pmc, #AT91_CKGR_MOR] |
0dcfed14 | 111 | bic tmp1, tmp1, #AT91_PMC_MOSCEN |
5957457a | 112 | orr tmp1, tmp1, #AT91_PMC_KEY |
b5514952 | 113 | str tmp1, [pmc, #AT91_CKGR_MOR] |
eaad2db0 AV |
114 | |
115 | /* Wait for interrupt */ | |
0dcfed14 | 116 | mcr p15, 0, tmp1, c7, c0, 4 |
eaad2db0 AV |
117 | |
118 | /* Turn on the main oscillator */ | |
b5514952 | 119 | ldr tmp1, [pmc, #AT91_CKGR_MOR] |
0dcfed14 | 120 | orr tmp1, tmp1, #AT91_PMC_MOSCEN |
5957457a | 121 | orr tmp1, tmp1, #AT91_PMC_KEY |
b5514952 | 122 | str tmp1, [pmc, #AT91_CKGR_MOR] |
eaad2db0 AV |
123 | |
124 | wait_moscrdy | |
125 | ||
eaad2db0 | 126 | /* Restore PLLA setting */ |
0dcfed14 | 127 | ldr tmp1, .saved_pllar |
b5514952 | 128 | str tmp1, [pmc, #AT91_CKGR_PLLAR] |
eaad2db0 | 129 | |
0dcfed14 | 130 | tst tmp1, #(AT91_PMC_MUL & 0xff0000) |
9823f1a8 | 131 | bne 3f |
0dcfed14 | 132 | tst tmp1, #(AT91_PMC_MUL & ~0xff0000) |
9823f1a8 AL |
133 | beq 4f |
134 | 3: | |
eaad2db0 | 135 | wait_pllalock |
9823f1a8 | 136 | 4: |
eaad2db0 | 137 | |
eaad2db0 AV |
138 | /* |
139 | * Restore master clock setting | |
140 | */ | |
0ab285c2 | 141 | ldr tmp1, .saved_mckr |
b5514952 | 142 | str tmp1, [pmc, #AT91_PMC_MCKR] |
eaad2db0 AV |
143 | |
144 | wait_mckrdy | |
145 | ||
0ab285c2 WY |
146 | /* Exit the self-refresh mode */ |
147 | mov r0, #SRAMC_SELF_FRESH_EXIT | |
148 | bl at91_sramc_self_refresh | |
149 | ||
150 | /* Restore registers, and return */ | |
151 | ldmfd sp!, {r4 - r12, pc} | |
152 | ENDPROC(at91_slow_clock) | |
153 | ||
154 | /* | |
155 | * void at91_sramc_self_refresh(unsigned int is_active) | |
156 | * | |
157 | * @input param: | |
158 | * @r0: 1 - active self-refresh mode | |
159 | * 0 - exit self-refresh mode | |
160 | * register usage: | |
161 | * @r1: memory type | |
162 | * @r2: base address of the sram controller | |
163 | */ | |
164 | ||
165 | ENTRY(at91_sramc_self_refresh) | |
166 | ldr r1, .memtype | |
167 | ldr r2, .sramc_base | |
168 | ||
169 | cmp r1, #AT91_MEMCTRL_MC | |
170 | bne ddrc_sf | |
171 | ||
fb7e197b JCPV |
172 | /* |
173 | * at91rm9200 Memory controller | |
fb7e197b | 174 | */ |
0ab285c2 WY |
175 | |
176 | /* | |
177 | * For exiting the self-refresh mode, do nothing, | |
178 | * automatically exit the self-refresh mode. | |
179 | */ | |
180 | tst r0, #SRAMC_SELF_FRESH_ACTIVE | |
181 | beq exit_sramc_sf | |
182 | ||
183 | /* Active SDRAM self-refresh mode */ | |
184 | mov r3, #1 | |
185 | str r3, [r2, #AT91RM9200_SDRAMC_SRR] | |
186 | b exit_sramc_sf | |
187 | ||
188 | ddrc_sf: | |
189 | cmp r1, #AT91_MEMCTRL_DDRSDR | |
190 | bne sdramc_sf | |
fb7e197b JCPV |
191 | |
192 | /* | |
0ab285c2 | 193 | * DDR Memory controller |
fb7e197b | 194 | */ |
0ab285c2 WY |
195 | tst r0, #SRAMC_SELF_FRESH_ACTIVE |
196 | beq ddrc_exit_sf | |
197 | ||
198 | /* LPDDR1 --> force DDR2 mode during self-refresh */ | |
199 | ldr r3, [r2, #AT91_DDRSDRC_MDR] | |
200 | str r3, .saved_sam9_mdr | |
201 | bic r3, r3, #~AT91_DDRSDRC_MD | |
202 | cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR | |
203 | ldreq r3, [r2, #AT91_DDRSDRC_MDR] | |
204 | biceq r3, r3, #AT91_DDRSDRC_MD | |
205 | orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 | |
206 | streq r3, [r2, #AT91_DDRSDRC_MDR] | |
207 | ||
208 | /* Active DDRC self-refresh mode */ | |
209 | ldr r3, [r2, #AT91_DDRSDRC_LPR] | |
210 | str r3, .saved_sam9_lpr | |
211 | bic r3, r3, #AT91_DDRSDRC_LPCB | |
212 | orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH | |
213 | str r3, [r2, #AT91_DDRSDRC_LPR] | |
214 | ||
215 | /* If using the 2nd ddr controller */ | |
216 | ldr r2, .sramc1_base | |
217 | cmp r2, #0 | |
218 | beq no_2nd_ddrc | |
219 | ||
220 | ldr r3, [r2, #AT91_DDRSDRC_MDR] | |
221 | str r3, .saved_sam9_mdr1 | |
222 | bic r3, r3, #~AT91_DDRSDRC_MD | |
223 | cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR | |
224 | ldreq r3, [r2, #AT91_DDRSDRC_MDR] | |
225 | biceq r3, r3, #AT91_DDRSDRC_MD | |
226 | orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 | |
227 | streq r3, [r2, #AT91_DDRSDRC_MDR] | |
228 | ||
229 | /* Active DDRC self-refresh mode */ | |
230 | ldr r3, [r2, #AT91_DDRSDRC_LPR] | |
231 | str r3, .saved_sam9_lpr1 | |
232 | bic r3, r3, #AT91_DDRSDRC_LPCB | |
233 | orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH | |
234 | str r3, [r2, #AT91_DDRSDRC_LPR] | |
235 | ||
236 | no_2nd_ddrc: | |
237 | b exit_sramc_sf | |
238 | ||
239 | ddrc_exit_sf: | |
02f513a0 | 240 | /* Restore MDR in case of LPDDR1 */ |
0ab285c2 WY |
241 | ldr r3, .saved_sam9_mdr |
242 | str r3, [r2, #AT91_DDRSDRC_MDR] | |
7dca3343 | 243 | /* Restore LPR on AT91 with DDRAM */ |
0ab285c2 WY |
244 | ldr r3, .saved_sam9_lpr |
245 | str r3, [r2, #AT91_DDRSDRC_LPR] | |
7dca3343 | 246 | |
0ab285c2 WY |
247 | /* If using the 2nd ddr controller */ |
248 | ldr r2, .sramc1_base | |
249 | cmp r2, #0 | |
250 | ldrne r3, .saved_sam9_mdr1 | |
251 | strne r3, [r2, #AT91_DDRSDRC_MDR] | |
252 | ldrne r3, .saved_sam9_lpr1 | |
253 | strne r3, [r2, #AT91_DDRSDRC_LPR] | |
7dca3343 | 254 | |
0ab285c2 | 255 | b exit_sramc_sf |
fb7e197b JCPV |
256 | |
257 | /* | |
258 | * SDRAMC Memory controller | |
259 | */ | |
0ab285c2 WY |
260 | sdramc_sf: |
261 | tst r0, #SRAMC_SELF_FRESH_ACTIVE | |
262 | beq sdramc_exit_sf | |
263 | ||
264 | /* Active SDRAMC self-refresh mode */ | |
265 | ldr r3, [r2, #AT91_SDRAMC_LPR] | |
266 | str r3, .saved_sam9_lpr | |
267 | bic r3, r3, #AT91_SDRAMC_LPCB | |
268 | orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH | |
269 | str r3, [r2, #AT91_SDRAMC_LPR] | |
270 | ||
271 | sdramc_exit_sf: | |
272 | ldr r3, .saved_sam9_lpr | |
273 | str r3, [r2, #AT91_SDRAMC_LPR] | |
274 | ||
275 | exit_sramc_sf: | |
276 | mov pc, lr | |
277 | ENDPROC(at91_sramc_self_refresh) | |
278 | ||
279 | .pmc_base: | |
280 | .word 0 | |
281 | .sramc_base: | |
282 | .word 0 | |
283 | .sramc1_base: | |
284 | .word 0 | |
285 | .memtype: | |
286 | .word 0 | |
eaad2db0 AV |
287 | .saved_mckr: |
288 | .word 0 | |
eaad2db0 AV |
289 | .saved_pllar: |
290 | .word 0 | |
eaad2db0 AV |
291 | .saved_sam9_lpr: |
292 | .word 0 | |
7dca3343 NF |
293 | .saved_sam9_lpr1: |
294 | .word 0 | |
02f513a0 PR |
295 | .saved_sam9_mdr: |
296 | .word 0 | |
02f513a0 PR |
297 | .saved_sam9_mdr1: |
298 | .word 0 | |
299 | ||
eaad2db0 AV |
300 | ENTRY(at91_slow_clock_sz) |
301 | .word .-at91_slow_clock |