diff options
Diffstat (limited to 'arch/arm/mach-at91/pm_suspend.S')
-rw-r--r-- | arch/arm/mach-at91/pm_suspend.S | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S new file mode 100644 index 000000000000..7c444c259740 --- /dev/null +++ b/arch/arm/mach-at91/pm_suspend.S | |||
@@ -0,0 +1,338 @@ | |||
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 | #include <linux/linkage.h> | ||
15 | #include <linux/clk/at91_pmc.h> | ||
16 | #include <mach/hardware.h> | ||
17 | #include <mach/at91_ramc.h> | ||
18 | #include "pm.h" | ||
19 | |||
20 | #define SRAMC_SELF_FRESH_ACTIVE 0x01 | ||
21 | #define SRAMC_SELF_FRESH_EXIT 0x00 | ||
22 | |||
23 | pmc .req r0 | ||
24 | tmp1 .req r4 | ||
25 | tmp2 .req r5 | ||
26 | |||
27 | /* | ||
28 | * Wait until master clock is ready (after switching master clock source) | ||
29 | */ | ||
30 | .macro wait_mckrdy | ||
31 | 1: ldr tmp1, [pmc, #AT91_PMC_SR] | ||
32 | tst tmp1, #AT91_PMC_MCKRDY | ||
33 | beq 1b | ||
34 | .endm | ||
35 | |||
36 | /* | ||
37 | * Wait until master oscillator has stabilized. | ||
38 | */ | ||
39 | .macro wait_moscrdy | ||
40 | 1: ldr tmp1, [pmc, #AT91_PMC_SR] | ||
41 | tst tmp1, #AT91_PMC_MOSCS | ||
42 | beq 1b | ||
43 | .endm | ||
44 | |||
45 | /* | ||
46 | * Wait until PLLA has locked. | ||
47 | */ | ||
48 | .macro wait_pllalock | ||
49 | 1: ldr tmp1, [pmc, #AT91_PMC_SR] | ||
50 | tst tmp1, #AT91_PMC_LOCKA | ||
51 | beq 1b | ||
52 | .endm | ||
53 | |||
54 | /* | ||
55 | * Put the processor to enter the idle state | ||
56 | */ | ||
57 | .macro at91_cpu_idle | ||
58 | |||
59 | #if defined(CONFIG_CPU_V7) | ||
60 | mov tmp1, #AT91_PMC_PCK | ||
61 | str tmp1, [pmc, #AT91_PMC_SCDR] | ||
62 | |||
63 | dsb | ||
64 | |||
65 | wfi @ Wait For Interrupt | ||
66 | #else | ||
67 | mcr p15, 0, tmp1, c7, c0, 4 | ||
68 | #endif | ||
69 | |||
70 | .endm | ||
71 | |||
72 | .text | ||
73 | |||
74 | .arm | ||
75 | |||
76 | /* | ||
77 | * void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *sdramc, | ||
78 | * void __iomem *ramc1, int memctrl) | ||
79 | * @input param: | ||
80 | * @r0: base address of AT91_PMC | ||
81 | * @r1: base address of SDRAM Controller (SDRAM, DDRSDR, or AT91_SYS) | ||
82 | * @r2: base address of second SDRAM Controller or 0 if not present | ||
83 | * @r3: pm information | ||
84 | */ | ||
85 | ENTRY(at91_pm_suspend_in_sram) | ||
86 | /* Save registers on stack */ | ||
87 | stmfd sp!, {r4 - r12, lr} | ||
88 | |||
89 | /* Drain write buffer */ | ||
90 | mov tmp1, #0 | ||
91 | mcr p15, 0, tmp1, c7, c10, 4 | ||
92 | |||
93 | str r0, .pmc_base | ||
94 | str r1, .sramc_base | ||
95 | str r2, .sramc1_base | ||
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 | ||
103 | |||
104 | /* Active the self-refresh mode */ | ||
105 | mov r0, #SRAMC_SELF_FRESH_ACTIVE | ||
106 | bl at91_sramc_self_refresh | ||
107 | |||
108 | ldr r0, .pm_mode | ||
109 | tst r0, #AT91_PM_SLOW_CLOCK | ||
110 | beq skip_disable_main_clock | ||
111 | |||
112 | ldr pmc, .pmc_base | ||
113 | |||
114 | /* Save Master clock setting */ | ||
115 | ldr tmp1, [pmc, #AT91_PMC_MCKR] | ||
116 | str tmp1, .saved_mckr | ||
117 | |||
118 | /* | ||
119 | * Set the Master clock source to slow clock | ||
120 | */ | ||
121 | bic tmp1, tmp1, #AT91_PMC_CSS | ||
122 | str tmp1, [pmc, #AT91_PMC_MCKR] | ||
123 | |||
124 | wait_mckrdy | ||
125 | |||
126 | /* Save PLLA setting and disable it */ | ||
127 | ldr tmp1, [pmc, #AT91_CKGR_PLLAR] | ||
128 | str tmp1, .saved_pllar | ||
129 | |||
130 | mov tmp1, #AT91_PMC_PLLCOUNT | ||
131 | orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ | ||
132 | str tmp1, [pmc, #AT91_CKGR_PLLAR] | ||
133 | |||
134 | /* Turn off the main oscillator */ | ||
135 | ldr tmp1, [pmc, #AT91_CKGR_MOR] | ||
136 | bic tmp1, tmp1, #AT91_PMC_MOSCEN | ||
137 | orr tmp1, tmp1, #AT91_PMC_KEY | ||
138 | str tmp1, [pmc, #AT91_CKGR_MOR] | ||
139 | |||
140 | skip_disable_main_clock: | ||
141 | ldr pmc, .pmc_base | ||
142 | |||
143 | /* Wait for interrupt */ | ||
144 | at91_cpu_idle | ||
145 | |||
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 | |||
152 | /* Turn on the main oscillator */ | ||
153 | ldr tmp1, [pmc, #AT91_CKGR_MOR] | ||
154 | orr tmp1, tmp1, #AT91_PMC_MOSCEN | ||
155 | orr tmp1, tmp1, #AT91_PMC_KEY | ||
156 | str tmp1, [pmc, #AT91_CKGR_MOR] | ||
157 | |||
158 | wait_moscrdy | ||
159 | |||
160 | /* Restore PLLA setting */ | ||
161 | ldr tmp1, .saved_pllar | ||
162 | str tmp1, [pmc, #AT91_CKGR_PLLAR] | ||
163 | |||
164 | tst tmp1, #(AT91_PMC_MUL & 0xff0000) | ||
165 | bne 3f | ||
166 | tst tmp1, #(AT91_PMC_MUL & ~0xff0000) | ||
167 | beq 4f | ||
168 | 3: | ||
169 | wait_pllalock | ||
170 | 4: | ||
171 | |||
172 | /* | ||
173 | * Restore master clock setting | ||
174 | */ | ||
175 | ldr tmp1, .saved_mckr | ||
176 | str tmp1, [pmc, #AT91_PMC_MCKR] | ||
177 | |||
178 | wait_mckrdy | ||
179 | |||
180 | skip_enable_main_clock: | ||
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} | ||
187 | ENDPROC(at91_pm_suspend_in_sram) | ||
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 | |||
207 | /* | ||
208 | * at91rm9200 Memory controller | ||
209 | */ | ||
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 | ||
220 | str r3, [r2, #AT91RM9200_SDRAMC_SRR] | ||
221 | b exit_sramc_sf | ||
222 | |||
223 | ddrc_sf: | ||
224 | cmp r1, #AT91_MEMCTRL_DDRSDR | ||
225 | bne sdramc_sf | ||
226 | |||
227 | /* | ||
228 | * DDR Memory controller | ||
229 | */ | ||
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: | ||
275 | /* Restore MDR in case of LPDDR1 */ | ||
276 | ldr r3, .saved_sam9_mdr | ||
277 | str r3, [r2, #AT91_DDRSDRC_MDR] | ||
278 | /* Restore LPR on AT91 with DDRAM */ | ||
279 | ldr r3, .saved_sam9_lpr | ||
280 | str r3, [r2, #AT91_DDRSDRC_LPR] | ||
281 | |||
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] | ||
289 | |||
290 | b exit_sramc_sf | ||
291 | |||
292 | /* | ||
293 | * SDRAMC Memory controller | ||
294 | */ | ||
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 | ||
322 | .pm_mode: | ||
323 | .word 0 | ||
324 | .saved_mckr: | ||
325 | .word 0 | ||
326 | .saved_pllar: | ||
327 | .word 0 | ||
328 | .saved_sam9_lpr: | ||
329 | .word 0 | ||
330 | .saved_sam9_lpr1: | ||
331 | .word 0 | ||
332 | .saved_sam9_mdr: | ||
333 | .word 0 | ||
334 | .saved_sam9_mdr1: | ||
335 | .word 0 | ||
336 | |||
337 | ENTRY(at91_pm_suspend_in_sram_sz) | ||
338 | .word .-at91_pm_suspend_in_sram | ||