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 | */ |
5fcf8d1a PD |
83 | /* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */ |
84 | .align 3 | |
5726a8b9 | 85 | ENTRY(at91_pm_suspend_in_sram) |
eaad2db0 | 86 | /* Save registers on stack */ |
fb7e197b | 87 | stmfd sp!, {r4 - r12, lr} |
eaad2db0 | 88 | |
eaad2db0 | 89 | /* Drain write buffer */ |
0dcfed14 JCPV |
90 | mov tmp1, #0 |
91 | mcr p15, 0, tmp1, c7, c10, 4 | |
eaad2db0 | 92 | |
0ab285c2 WY |
93 | str r0, .pmc_base |
94 | str r1, .sramc_base | |
95 | str r2, .sramc1_base | |
23be4be5 WY |
96 | |
97 | and r0, r3, #AT91_PM_MEMTYPE_MASK | |
98 | str r0, .memtype | |
99 | ||
100 | lsr r0, r3, #AT91_PM_MODE_OFFSET | |
101 | and r0, r0, #AT91_PM_MODE_MASK | |
102 | str r0, .pm_mode | |
fb7e197b | 103 | |
0ab285c2 WY |
104 | /* Active the self-refresh mode */ |
105 | mov r0, #SRAMC_SELF_FRESH_ACTIVE | |
106 | bl at91_sramc_self_refresh | |
fb7e197b | 107 | |
23be4be5 WY |
108 | ldr r0, .pm_mode |
109 | tst r0, #AT91_PM_SLOW_CLOCK | |
110 | beq skip_disable_main_clock | |
111 | ||
0ab285c2 | 112 | ldr pmc, .pmc_base |
eaad2db0 | 113 | |
eaad2db0 | 114 | /* Save Master clock setting */ |
b5514952 | 115 | ldr tmp1, [pmc, #AT91_PMC_MCKR] |
0dcfed14 | 116 | str tmp1, .saved_mckr |
eaad2db0 AV |
117 | |
118 | /* | |
119 | * Set the Master clock source to slow clock | |
120 | */ | |
0dcfed14 | 121 | bic tmp1, tmp1, #AT91_PMC_CSS |
b5514952 | 122 | str tmp1, [pmc, #AT91_PMC_MCKR] |
eaad2db0 AV |
123 | |
124 | wait_mckrdy | |
125 | ||
eaad2db0 | 126 | /* Save PLLA setting and disable it */ |
b5514952 | 127 | ldr tmp1, [pmc, #AT91_CKGR_PLLAR] |
0dcfed14 | 128 | str tmp1, .saved_pllar |
eaad2db0 | 129 | |
0dcfed14 JCPV |
130 | mov tmp1, #AT91_PMC_PLLCOUNT |
131 | orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ | |
b5514952 | 132 | str tmp1, [pmc, #AT91_CKGR_PLLAR] |
eaad2db0 | 133 | |
eaad2db0 | 134 | /* Turn off the main oscillator */ |
b5514952 | 135 | ldr tmp1, [pmc, #AT91_CKGR_MOR] |
0dcfed14 | 136 | bic tmp1, tmp1, #AT91_PMC_MOSCEN |
5957457a | 137 | orr tmp1, tmp1, #AT91_PMC_KEY |
b5514952 | 138 | str tmp1, [pmc, #AT91_CKGR_MOR] |
eaad2db0 | 139 | |
23be4be5 WY |
140 | skip_disable_main_clock: |
141 | ldr pmc, .pmc_base | |
142 | ||
eaad2db0 | 143 | /* Wait for interrupt */ |
20567658 | 144 | at91_cpu_idle |
eaad2db0 | 145 | |
23be4be5 WY |
146 | ldr r0, .pm_mode |
147 | tst r0, #AT91_PM_SLOW_CLOCK | |
148 | beq skip_enable_main_clock | |
149 | ||
150 | ldr pmc, .pmc_base | |
151 | ||
eaad2db0 | 152 | /* Turn on the main oscillator */ |
b5514952 | 153 | ldr tmp1, [pmc, #AT91_CKGR_MOR] |
0dcfed14 | 154 | orr tmp1, tmp1, #AT91_PMC_MOSCEN |
5957457a | 155 | orr tmp1, tmp1, #AT91_PMC_KEY |
b5514952 | 156 | str tmp1, [pmc, #AT91_CKGR_MOR] |
eaad2db0 AV |
157 | |
158 | wait_moscrdy | |
159 | ||
eaad2db0 | 160 | /* Restore PLLA setting */ |
0dcfed14 | 161 | ldr tmp1, .saved_pllar |
b5514952 | 162 | str tmp1, [pmc, #AT91_CKGR_PLLAR] |
eaad2db0 | 163 | |
0dcfed14 | 164 | tst tmp1, #(AT91_PMC_MUL & 0xff0000) |
9823f1a8 | 165 | bne 3f |
0dcfed14 | 166 | tst tmp1, #(AT91_PMC_MUL & ~0xff0000) |
9823f1a8 AL |
167 | beq 4f |
168 | 3: | |
eaad2db0 | 169 | wait_pllalock |
9823f1a8 | 170 | 4: |
eaad2db0 | 171 | |
eaad2db0 AV |
172 | /* |
173 | * Restore master clock setting | |
174 | */ | |
0ab285c2 | 175 | ldr tmp1, .saved_mckr |
b5514952 | 176 | str tmp1, [pmc, #AT91_PMC_MCKR] |
eaad2db0 AV |
177 | |
178 | wait_mckrdy | |
179 | ||
23be4be5 | 180 | skip_enable_main_clock: |
0ab285c2 WY |
181 | /* Exit the self-refresh mode */ |
182 | mov r0, #SRAMC_SELF_FRESH_EXIT | |
183 | bl at91_sramc_self_refresh | |
184 | ||
185 | /* Restore registers, and return */ | |
186 | ldmfd sp!, {r4 - r12, pc} | |
5726a8b9 | 187 | ENDPROC(at91_pm_suspend_in_sram) |
0ab285c2 WY |
188 | |
189 | /* | |
190 | * void at91_sramc_self_refresh(unsigned int is_active) | |
191 | * | |
192 | * @input param: | |
193 | * @r0: 1 - active self-refresh mode | |
194 | * 0 - exit self-refresh mode | |
195 | * register usage: | |
196 | * @r1: memory type | |
197 | * @r2: base address of the sram controller | |
198 | */ | |
199 | ||
200 | ENTRY(at91_sramc_self_refresh) | |
201 | ldr r1, .memtype | |
202 | ldr r2, .sramc_base | |
203 | ||
204 | cmp r1, #AT91_MEMCTRL_MC | |
205 | bne ddrc_sf | |
206 | ||
fb7e197b JCPV |
207 | /* |
208 | * at91rm9200 Memory controller | |
fb7e197b | 209 | */ |
0ab285c2 WY |
210 | |
211 | /* | |
212 | * For exiting the self-refresh mode, do nothing, | |
213 | * automatically exit the self-refresh mode. | |
214 | */ | |
215 | tst r0, #SRAMC_SELF_FRESH_ACTIVE | |
216 | beq exit_sramc_sf | |
217 | ||
218 | /* Active SDRAM self-refresh mode */ | |
219 | mov r3, #1 | |
d7d45f25 | 220 | str r3, [r2, #AT91_MC_SDRAMC_SRR] |
0ab285c2 WY |
221 | b exit_sramc_sf |
222 | ||
223 | ddrc_sf: | |
224 | cmp r1, #AT91_MEMCTRL_DDRSDR | |
225 | bne sdramc_sf | |
fb7e197b JCPV |
226 | |
227 | /* | |
0ab285c2 | 228 | * DDR Memory controller |
fb7e197b | 229 | */ |
0ab285c2 WY |
230 | tst r0, #SRAMC_SELF_FRESH_ACTIVE |
231 | beq ddrc_exit_sf | |
232 | ||
233 | /* LPDDR1 --> force DDR2 mode during self-refresh */ | |
234 | ldr r3, [r2, #AT91_DDRSDRC_MDR] | |
235 | str r3, .saved_sam9_mdr | |
236 | bic r3, r3, #~AT91_DDRSDRC_MD | |
237 | cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR | |
238 | ldreq r3, [r2, #AT91_DDRSDRC_MDR] | |
239 | biceq r3, r3, #AT91_DDRSDRC_MD | |
240 | orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 | |
241 | streq r3, [r2, #AT91_DDRSDRC_MDR] | |
242 | ||
243 | /* Active DDRC self-refresh mode */ | |
244 | ldr r3, [r2, #AT91_DDRSDRC_LPR] | |
245 | str r3, .saved_sam9_lpr | |
246 | bic r3, r3, #AT91_DDRSDRC_LPCB | |
247 | orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH | |
248 | str r3, [r2, #AT91_DDRSDRC_LPR] | |
249 | ||
250 | /* If using the 2nd ddr controller */ | |
251 | ldr r2, .sramc1_base | |
252 | cmp r2, #0 | |
253 | beq no_2nd_ddrc | |
254 | ||
255 | ldr r3, [r2, #AT91_DDRSDRC_MDR] | |
256 | str r3, .saved_sam9_mdr1 | |
257 | bic r3, r3, #~AT91_DDRSDRC_MD | |
258 | cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR | |
259 | ldreq r3, [r2, #AT91_DDRSDRC_MDR] | |
260 | biceq r3, r3, #AT91_DDRSDRC_MD | |
261 | orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 | |
262 | streq r3, [r2, #AT91_DDRSDRC_MDR] | |
263 | ||
264 | /* Active DDRC self-refresh mode */ | |
265 | ldr r3, [r2, #AT91_DDRSDRC_LPR] | |
266 | str r3, .saved_sam9_lpr1 | |
267 | bic r3, r3, #AT91_DDRSDRC_LPCB | |
268 | orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH | |
269 | str r3, [r2, #AT91_DDRSDRC_LPR] | |
270 | ||
271 | no_2nd_ddrc: | |
272 | b exit_sramc_sf | |
273 | ||
274 | ddrc_exit_sf: | |
02f513a0 | 275 | /* Restore MDR in case of LPDDR1 */ |
0ab285c2 WY |
276 | ldr r3, .saved_sam9_mdr |
277 | str r3, [r2, #AT91_DDRSDRC_MDR] | |
7dca3343 | 278 | /* Restore LPR on AT91 with DDRAM */ |
0ab285c2 WY |
279 | ldr r3, .saved_sam9_lpr |
280 | str r3, [r2, #AT91_DDRSDRC_LPR] | |
7dca3343 | 281 | |
0ab285c2 WY |
282 | /* If using the 2nd ddr controller */ |
283 | ldr r2, .sramc1_base | |
284 | cmp r2, #0 | |
285 | ldrne r3, .saved_sam9_mdr1 | |
286 | strne r3, [r2, #AT91_DDRSDRC_MDR] | |
287 | ldrne r3, .saved_sam9_lpr1 | |
288 | strne r3, [r2, #AT91_DDRSDRC_LPR] | |
7dca3343 | 289 | |
0ab285c2 | 290 | b exit_sramc_sf |
fb7e197b JCPV |
291 | |
292 | /* | |
293 | * SDRAMC Memory controller | |
294 | */ | |
0ab285c2 WY |
295 | sdramc_sf: |
296 | tst r0, #SRAMC_SELF_FRESH_ACTIVE | |
297 | beq sdramc_exit_sf | |
298 | ||
299 | /* Active SDRAMC self-refresh mode */ | |
300 | ldr r3, [r2, #AT91_SDRAMC_LPR] | |
301 | str r3, .saved_sam9_lpr | |
302 | bic r3, r3, #AT91_SDRAMC_LPCB | |
303 | orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH | |
304 | str r3, [r2, #AT91_SDRAMC_LPR] | |
305 | ||
306 | sdramc_exit_sf: | |
307 | ldr r3, .saved_sam9_lpr | |
308 | str r3, [r2, #AT91_SDRAMC_LPR] | |
309 | ||
310 | exit_sramc_sf: | |
311 | mov pc, lr | |
312 | ENDPROC(at91_sramc_self_refresh) | |
313 | ||
314 | .pmc_base: | |
315 | .word 0 | |
316 | .sramc_base: | |
317 | .word 0 | |
318 | .sramc1_base: | |
319 | .word 0 | |
320 | .memtype: | |
321 | .word 0 | |
23be4be5 WY |
322 | .pm_mode: |
323 | .word 0 | |
eaad2db0 AV |
324 | .saved_mckr: |
325 | .word 0 | |
eaad2db0 AV |
326 | .saved_pllar: |
327 | .word 0 | |
eaad2db0 AV |
328 | .saved_sam9_lpr: |
329 | .word 0 | |
7dca3343 NF |
330 | .saved_sam9_lpr1: |
331 | .word 0 | |
02f513a0 PR |
332 | .saved_sam9_mdr: |
333 | .word 0 | |
02f513a0 PR |
334 | .saved_sam9_mdr1: |
335 | .word 0 | |
336 | ||
5726a8b9 WY |
337 | ENTRY(at91_pm_suspend_in_sram_sz) |
338 | .word .-at91_pm_suspend_in_sram |