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