diff options
author | Tony Lindgren <tony@atomide.com> | 2006-04-02 12:46:25 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-04-02 12:46:25 -0400 |
commit | 670c104ae8e7bcc28be0289a16dac2ddfb88b285 (patch) | |
tree | 1c55f3a466775fd1d3b73ca28947500221e47134 /arch/arm/plat-omap | |
parent | 6e60e79a1d46eaa3369febc2f6c31e0acfaaae3f (diff) |
[ARM] 3430/1: ARM: OMAP: 5/8 Update PM
Patch from Tony Lindgren
Update OMAP PM code from linux-omap tree:
- Move PM code from plat-omap to mach-omap1 and mach-omap2
by Tony Lindgren
- Add minimal PM support for omap24xx by Tony Lindgren and
Richard Woodruff
- Misc updates to omap1 PM code by Tuukka Tikkanen et al
- Updates to the SRAM code needed for PM and FB by Imre Deak
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r-- | arch/arm/plat-omap/pm.c | 1 | ||||
-rw-r--r-- | arch/arm/plat-omap/sleep.S | 452 | ||||
-rw-r--r-- | arch/arm/plat-omap/sram.c | 143 |
3 files changed, 122 insertions, 474 deletions
diff --git a/arch/arm/plat-omap/pm.c b/arch/arm/plat-omap/pm.c index 093efd786f21..1a24e2c10714 100644 --- a/arch/arm/plat-omap/pm.c +++ b/arch/arm/plat-omap/pm.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/pm.h> | 38 | #include <linux/pm.h> |
39 | #include <linux/sched.h> | 39 | #include <linux/sched.h> |
40 | #include <linux/proc_fs.h> | 40 | #include <linux/proc_fs.h> |
41 | #include <linux/pm.h> | ||
41 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
42 | 43 | ||
43 | #include <asm/io.h> | 44 | #include <asm/io.h> |
diff --git a/arch/arm/plat-omap/sleep.S b/arch/arm/plat-omap/sleep.S deleted file mode 100644 index 4cd7d292f854..000000000000 --- a/arch/arm/plat-omap/sleep.S +++ /dev/null | |||
@@ -1,452 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/plat-omap/sleep.S | ||
3 | * | ||
4 | * Low-level OMAP730/1510/1610 sleep/wakeUp support | ||
5 | * | ||
6 | * Initial SA1110 code: | ||
7 | * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> | ||
8 | * | ||
9 | * Adapted for PXA by Nicolas Pitre: | ||
10 | * Copyright (c) 2002 Monta Vista Software, Inc. | ||
11 | * | ||
12 | * Support for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify it | ||
15 | * under the terms of the GNU General Public License as published by the | ||
16 | * Free Software Foundation; either version 2 of the License, or (at your | ||
17 | * option) any later version. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
20 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
22 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
23 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
24 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
25 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
26 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
28 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
29 | * | ||
30 | * You should have received a copy of the GNU General Public License along | ||
31 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
32 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
33 | */ | ||
34 | |||
35 | #include <linux/config.h> | ||
36 | #include <linux/linkage.h> | ||
37 | #include <asm/assembler.h> | ||
38 | #include <asm/arch/io.h> | ||
39 | #include <asm/arch/pm.h> | ||
40 | |||
41 | .text | ||
42 | |||
43 | /* | ||
44 | * Forces OMAP into idle state | ||
45 | * | ||
46 | * omapXXXX_idle_loop_suspend() | ||
47 | * | ||
48 | * Note: This code get's copied to internal SRAM at boot. When the OMAP | ||
49 | * wakes up it continues execution at the point it went to sleep. | ||
50 | * | ||
51 | * Note: Because of slightly different configuration values we have | ||
52 | * processor specific functions here. | ||
53 | */ | ||
54 | |||
55 | #if defined(CONFIG_ARCH_OMAP730) | ||
56 | ENTRY(omap730_idle_loop_suspend) | ||
57 | |||
58 | stmfd sp!, {r0 - r12, lr} @ save registers on stack | ||
59 | |||
60 | @ load base address of ARM_IDLECT1 and ARM_IDLECT2 | ||
61 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 | ||
62 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 | ||
63 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 | ||
64 | |||
65 | @ turn off clock domains | ||
66 | @ get ARM_IDLECT2 into r2 | ||
67 | ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
68 | mov r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff | ||
69 | orr r5, r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff00 | ||
70 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
71 | |||
72 | @ request ARM idle | ||
73 | @ get ARM_IDLECT1 into r1 | ||
74 | ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
75 | orr r3, r1, #OMAP730_IDLE_LOOP_REQUEST & 0xffff | ||
76 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
77 | |||
78 | mov r5, #IDLE_WAIT_CYCLES & 0xff | ||
79 | orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 | ||
80 | l_730: subs r5, r5, #1 | ||
81 | bne l_730 | ||
82 | /* | ||
83 | * Let's wait for the next clock tick to wake us up. | ||
84 | */ | ||
85 | mov r0, #0 | ||
86 | mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt | ||
87 | /* | ||
88 | * omap730_idle_loop_suspend()'s resume point. | ||
89 | * | ||
90 | * It will just start executing here, so we'll restore stuff from the | ||
91 | * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. | ||
92 | */ | ||
93 | |||
94 | @ restore ARM_IDLECT1 and ARM_IDLECT2 and return | ||
95 | @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2 | ||
96 | strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
97 | strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
98 | |||
99 | ldmfd sp!, {r0 - r12, pc} @ restore regs and return | ||
100 | |||
101 | ENTRY(omap730_idle_loop_suspend_sz) | ||
102 | .word . - omap730_idle_loop_suspend | ||
103 | #endif /* CONFIG_ARCH_OMAP730 */ | ||
104 | |||
105 | #ifdef CONFIG_ARCH_OMAP15XX | ||
106 | ENTRY(omap1510_idle_loop_suspend) | ||
107 | |||
108 | stmfd sp!, {r0 - r12, lr} @ save registers on stack | ||
109 | |||
110 | @ load base address of ARM_IDLECT1 and ARM_IDLECT2 | ||
111 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 | ||
112 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 | ||
113 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 | ||
114 | |||
115 | @ turn off clock domains | ||
116 | @ get ARM_IDLECT2 into r2 | ||
117 | ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
118 | mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff | ||
119 | orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00 | ||
120 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
121 | |||
122 | @ request ARM idle | ||
123 | @ get ARM_IDLECT1 into r1 | ||
124 | ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
125 | orr r3, r1, #OMAP1510_IDLE_LOOP_REQUEST & 0xffff | ||
126 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
127 | |||
128 | mov r5, #IDLE_WAIT_CYCLES & 0xff | ||
129 | orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 | ||
130 | l_1510: subs r5, r5, #1 | ||
131 | bne l_1510 | ||
132 | /* | ||
133 | * Let's wait for the next clock tick to wake us up. | ||
134 | */ | ||
135 | mov r0, #0 | ||
136 | mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt | ||
137 | /* | ||
138 | * omap1510_idle_loop_suspend()'s resume point. | ||
139 | * | ||
140 | * It will just start executing here, so we'll restore stuff from the | ||
141 | * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. | ||
142 | */ | ||
143 | |||
144 | @ restore ARM_IDLECT1 and ARM_IDLECT2 and return | ||
145 | @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2 | ||
146 | strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
147 | strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
148 | |||
149 | ldmfd sp!, {r0 - r12, pc} @ restore regs and return | ||
150 | |||
151 | ENTRY(omap1510_idle_loop_suspend_sz) | ||
152 | .word . - omap1510_idle_loop_suspend | ||
153 | #endif /* CONFIG_ARCH_OMAP15XX */ | ||
154 | |||
155 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
156 | ENTRY(omap1610_idle_loop_suspend) | ||
157 | |||
158 | stmfd sp!, {r0 - r12, lr} @ save registers on stack | ||
159 | |||
160 | @ load base address of ARM_IDLECT1 and ARM_IDLECT2 | ||
161 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 | ||
162 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 | ||
163 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 | ||
164 | |||
165 | @ turn off clock domains | ||
166 | @ get ARM_IDLECT2 into r2 | ||
167 | ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
168 | mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff | ||
169 | orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00 | ||
170 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
171 | |||
172 | @ request ARM idle | ||
173 | @ get ARM_IDLECT1 into r1 | ||
174 | ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
175 | orr r3, r1, #OMAP1610_IDLE_LOOP_REQUEST & 0xffff | ||
176 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
177 | |||
178 | mov r5, #IDLE_WAIT_CYCLES & 0xff | ||
179 | orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 | ||
180 | l_1610: subs r5, r5, #1 | ||
181 | bne l_1610 | ||
182 | /* | ||
183 | * Let's wait for the next clock tick to wake us up. | ||
184 | */ | ||
185 | mov r0, #0 | ||
186 | mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt | ||
187 | /* | ||
188 | * omap1610_idle_loop_suspend()'s resume point. | ||
189 | * | ||
190 | * It will just start executing here, so we'll restore stuff from the | ||
191 | * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. | ||
192 | */ | ||
193 | |||
194 | @ restore ARM_IDLECT1 and ARM_IDLECT2 and return | ||
195 | @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2 | ||
196 | strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
197 | strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
198 | |||
199 | ldmfd sp!, {r0 - r12, pc} @ restore regs and return | ||
200 | |||
201 | ENTRY(omap1610_idle_loop_suspend_sz) | ||
202 | .word . - omap1610_idle_loop_suspend | ||
203 | #endif /* CONFIG_ARCH_OMAP16XX */ | ||
204 | |||
205 | /* | ||
206 | * Forces OMAP into deep sleep state | ||
207 | * | ||
208 | * omapXXXX_cpu_suspend() | ||
209 | * | ||
210 | * The values of the registers ARM_IDLECT1 and ARM_IDLECT2 are passed | ||
211 | * as arg0 and arg1 from caller. arg0 is stored in register r0 and arg1 | ||
212 | * in register r1. | ||
213 | * | ||
214 | * Note: This code get's copied to internal SRAM at boot. When the OMAP | ||
215 | * wakes up it continues execution at the point it went to sleep. | ||
216 | * | ||
217 | * Note: Because of errata work arounds we have processor specific functions | ||
218 | * here. They are mostly the same, but slightly different. | ||
219 | * | ||
220 | */ | ||
221 | |||
222 | #if defined(CONFIG_ARCH_OMAP730) | ||
223 | ENTRY(omap730_cpu_suspend) | ||
224 | |||
225 | @ save registers on stack | ||
226 | stmfd sp!, {r0 - r12, lr} | ||
227 | |||
228 | @ Drain write cache | ||
229 | mov r4, #0 | ||
230 | mcr p15, 0, r0, c7, c10, 4 | ||
231 | nop | ||
232 | |||
233 | @ load base address of Traffic Controller | ||
234 | mov r6, #TCMIF_ASM_BASE & 0xff000000 | ||
235 | orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000 | ||
236 | orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00 | ||
237 | |||
238 | @ prepare to put SDRAM into self-refresh manually | ||
239 | ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
240 | orr r9, r7, #SELF_REFRESH_MODE & 0xff000000 | ||
241 | orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff | ||
242 | str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
243 | |||
244 | @ prepare to put EMIFS to Sleep | ||
245 | ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
246 | orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff | ||
247 | str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
248 | |||
249 | @ load base address of ARM_IDLECT1 and ARM_IDLECT2 | ||
250 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 | ||
251 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 | ||
252 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 | ||
253 | |||
254 | @ turn off clock domains | ||
255 | @ do not disable PERCK (0x04) | ||
256 | mov r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff | ||
257 | orr r5, r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff00 | ||
258 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
259 | |||
260 | @ request ARM idle | ||
261 | mov r3, #OMAP730_IDLECT1_SLEEP_VAL & 0xff | ||
262 | orr r3, r3, #OMAP730_IDLECT1_SLEEP_VAL & 0xff00 | ||
263 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
264 | |||
265 | @ disable instruction cache | ||
266 | mrc p15, 0, r9, c1, c0, 0 | ||
267 | bic r2, r9, #0x1000 | ||
268 | mcr p15, 0, r2, c1, c0, 0 | ||
269 | nop | ||
270 | |||
271 | /* | ||
272 | * Let's wait for the next wake up event to wake us up. r0 can't be | ||
273 | * used here because r0 holds ARM_IDLECT1 | ||
274 | */ | ||
275 | mov r2, #0 | ||
276 | mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt | ||
277 | /* | ||
278 | * omap730_cpu_suspend()'s resume point. | ||
279 | * | ||
280 | * It will just start executing here, so we'll restore stuff from the | ||
281 | * stack. | ||
282 | */ | ||
283 | @ re-enable Icache | ||
284 | mcr p15, 0, r9, c1, c0, 0 | ||
285 | |||
286 | @ reset the ARM_IDLECT1 and ARM_IDLECT2. | ||
287 | strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
288 | strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
289 | |||
290 | @ Restore EMIFF controls | ||
291 | str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
292 | str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
293 | |||
294 | @ restore regs and return | ||
295 | ldmfd sp!, {r0 - r12, pc} | ||
296 | |||
297 | ENTRY(omap730_cpu_suspend_sz) | ||
298 | .word . - omap730_cpu_suspend | ||
299 | #endif /* CONFIG_ARCH_OMAP730 */ | ||
300 | |||
301 | #ifdef CONFIG_ARCH_OMAP15XX | ||
302 | ENTRY(omap1510_cpu_suspend) | ||
303 | |||
304 | @ save registers on stack | ||
305 | stmfd sp!, {r0 - r12, lr} | ||
306 | |||
307 | @ load base address of Traffic Controller | ||
308 | mov r4, #TCMIF_ASM_BASE & 0xff000000 | ||
309 | orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000 | ||
310 | orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00 | ||
311 | |||
312 | @ work around errata of OMAP1510 PDE bit for TC shut down | ||
313 | @ clear PDE bit | ||
314 | ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
315 | bic r5, r5, #PDE_BIT & 0xff | ||
316 | str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
317 | |||
318 | @ set PWD_EN bit | ||
319 | and r5, r5, #PWD_EN_BIT & 0xff | ||
320 | str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
321 | |||
322 | @ prepare to put SDRAM into self-refresh manually | ||
323 | ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
324 | orr r5, r5, #SELF_REFRESH_MODE & 0xff000000 | ||
325 | orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff | ||
326 | str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
327 | |||
328 | @ prepare to put EMIFS to Sleep | ||
329 | ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
330 | orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff | ||
331 | str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
332 | |||
333 | @ load base address of ARM_IDLECT1 and ARM_IDLECT2 | ||
334 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 | ||
335 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 | ||
336 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 | ||
337 | |||
338 | @ turn off clock domains | ||
339 | mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff | ||
340 | orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00 | ||
341 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
342 | |||
343 | @ request ARM idle | ||
344 | mov r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff | ||
345 | orr r3, r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff00 | ||
346 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
347 | |||
348 | mov r5, #IDLE_WAIT_CYCLES & 0xff | ||
349 | orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 | ||
350 | l_1510_2: | ||
351 | subs r5, r5, #1 | ||
352 | bne l_1510_2 | ||
353 | /* | ||
354 | * Let's wait for the next wake up event to wake us up. r0 can't be | ||
355 | * used here because r0 holds ARM_IDLECT1 | ||
356 | */ | ||
357 | mov r2, #0 | ||
358 | mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt | ||
359 | /* | ||
360 | * omap1510_cpu_suspend()'s resume point. | ||
361 | * | ||
362 | * It will just start executing here, so we'll restore stuff from the | ||
363 | * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. | ||
364 | */ | ||
365 | strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
366 | strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
367 | |||
368 | @ restore regs and return | ||
369 | ldmfd sp!, {r0 - r12, pc} | ||
370 | |||
371 | ENTRY(omap1510_cpu_suspend_sz) | ||
372 | .word . - omap1510_cpu_suspend | ||
373 | #endif /* CONFIG_ARCH_OMAP15XX */ | ||
374 | |||
375 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
376 | ENTRY(omap1610_cpu_suspend) | ||
377 | |||
378 | @ save registers on stack | ||
379 | stmfd sp!, {r0 - r12, lr} | ||
380 | |||
381 | @ Drain write cache | ||
382 | mov r4, #0 | ||
383 | mcr p15, 0, r0, c7, c10, 4 | ||
384 | nop | ||
385 | |||
386 | @ load base address of Traffic Controller | ||
387 | mov r6, #TCMIF_ASM_BASE & 0xff000000 | ||
388 | orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000 | ||
389 | orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00 | ||
390 | |||
391 | @ prepare to put SDRAM into self-refresh manually | ||
392 | ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
393 | orr r9, r7, #SELF_REFRESH_MODE & 0xff000000 | ||
394 | orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff | ||
395 | str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
396 | |||
397 | @ prepare to put EMIFS to Sleep | ||
398 | ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
399 | orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff | ||
400 | str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
401 | |||
402 | @ load base address of ARM_IDLECT1 and ARM_IDLECT2 | ||
403 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 | ||
404 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 | ||
405 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 | ||
406 | |||
407 | @ turn off clock domains | ||
408 | @ do not disable PERCK (0x04) | ||
409 | mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff | ||
410 | orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00 | ||
411 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
412 | |||
413 | @ request ARM idle | ||
414 | mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff | ||
415 | orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00 | ||
416 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
417 | |||
418 | @ disable instruction cache | ||
419 | mrc p15, 0, r9, c1, c0, 0 | ||
420 | bic r2, r9, #0x1000 | ||
421 | mcr p15, 0, r2, c1, c0, 0 | ||
422 | nop | ||
423 | |||
424 | /* | ||
425 | * Let's wait for the next wake up event to wake us up. r0 can't be | ||
426 | * used here because r0 holds ARM_IDLECT1 | ||
427 | */ | ||
428 | mov r2, #0 | ||
429 | mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt | ||
430 | /* | ||
431 | * omap1610_cpu_suspend()'s resume point. | ||
432 | * | ||
433 | * It will just start executing here, so we'll restore stuff from the | ||
434 | * stack. | ||
435 | */ | ||
436 | @ re-enable Icache | ||
437 | mcr p15, 0, r9, c1, c0, 0 | ||
438 | |||
439 | @ reset the ARM_IDLECT1 and ARM_IDLECT2. | ||
440 | strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
441 | strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
442 | |||
443 | @ Restore EMIFF controls | ||
444 | str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
445 | str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
446 | |||
447 | @ restore regs and return | ||
448 | ldmfd sp!, {r0 - r12, pc} | ||
449 | |||
450 | ENTRY(omap1610_cpu_suspend_sz) | ||
451 | .word . - omap1610_cpu_suspend | ||
452 | #endif /* CONFIG_ARCH_OMAP16XX */ | ||
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index ee82763b02b8..b7bf09b1b412 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c | |||
@@ -16,24 +16,94 @@ | |||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | 18 | ||
19 | #include <asm/mach/map.h> | ||
20 | #include <asm/tlb.h> | 19 | #include <asm/tlb.h> |
21 | #include <asm/io.h> | 20 | #include <asm/io.h> |
22 | #include <asm/cacheflush.h> | 21 | #include <asm/cacheflush.h> |
23 | 22 | ||
23 | #include <asm/mach/map.h> | ||
24 | |||
24 | #include <asm/arch/sram.h> | 25 | #include <asm/arch/sram.h> |
26 | #include <asm/arch/board.h> | ||
25 | 27 | ||
26 | #define OMAP1_SRAM_PA 0x20000000 | 28 | #define OMAP1_SRAM_PA 0x20000000 |
27 | #define OMAP1_SRAM_VA 0xd0000000 | 29 | #define OMAP1_SRAM_VA 0xd0000000 |
28 | #define OMAP2_SRAM_PA 0x40200000 | 30 | #define OMAP2_SRAM_PA 0x40200000 |
31 | #define OMAP2_SRAM_PUB_PA 0x4020f800 | ||
29 | #define OMAP2_SRAM_VA 0xd0000000 | 32 | #define OMAP2_SRAM_VA 0xd0000000 |
33 | #define OMAP2_SRAM_PUB_VA 0xd0000800 | ||
30 | 34 | ||
35 | #if defined(CONFIG_ARCH_OMAP24XX) | ||
36 | #define SRAM_BOOTLOADER_SZ 0x00 | ||
37 | #else | ||
31 | #define SRAM_BOOTLOADER_SZ 0x80 | 38 | #define SRAM_BOOTLOADER_SZ 0x80 |
39 | #endif | ||
40 | |||
41 | #define VA_REQINFOPERM0 IO_ADDRESS(0x68005048) | ||
42 | #define VA_READPERM0 IO_ADDRESS(0x68005050) | ||
43 | #define VA_WRITEPERM0 IO_ADDRESS(0x68005058) | ||
44 | #define VA_CONTROL_STAT IO_ADDRESS(0x480002F8) | ||
45 | #define GP_DEVICE 0x300 | ||
46 | #define TYPE_MASK 0x700 | ||
47 | |||
48 | #define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) | ||
32 | 49 | ||
33 | static unsigned long omap_sram_base; | 50 | static unsigned long omap_sram_base; |
34 | static unsigned long omap_sram_size; | 51 | static unsigned long omap_sram_size; |
35 | static unsigned long omap_sram_ceil; | 52 | static unsigned long omap_sram_ceil; |
36 | 53 | ||
54 | unsigned long omap_fb_sram_start; | ||
55 | unsigned long omap_fb_sram_size; | ||
56 | |||
57 | /* Depending on the target RAMFS firewall setup, the public usable amount of | ||
58 | * SRAM varies. The default accessable size for all device types is 2k. A GP | ||
59 | * device allows ARM11 but not other initators for full size. This | ||
60 | * functionality seems ok until some nice security API happens. | ||
61 | */ | ||
62 | static int is_sram_locked(void) | ||
63 | { | ||
64 | int type = 0; | ||
65 | |||
66 | if (cpu_is_omap242x()) | ||
67 | type = __raw_readl(VA_CONTROL_STAT) & TYPE_MASK; | ||
68 | |||
69 | if (type == GP_DEVICE) { | ||
70 | /* RAMFW: R/W access to all initators for all qualifier sets */ | ||
71 | if (cpu_is_omap242x()) { | ||
72 | __raw_writel(0xFF, VA_REQINFOPERM0); /* all q-vects */ | ||
73 | __raw_writel(0xCFDE, VA_READPERM0); /* all i-read */ | ||
74 | __raw_writel(0xCFDE, VA_WRITEPERM0); /* all i-write */ | ||
75 | } | ||
76 | return 0; | ||
77 | } else | ||
78 | return 1; /* assume locked with no PPA or security driver */ | ||
79 | } | ||
80 | |||
81 | void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail, | ||
82 | unsigned long *start, unsigned long *size) | ||
83 | { | ||
84 | const struct omap_fbmem_config *fbmem_conf; | ||
85 | |||
86 | fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config); | ||
87 | if (fbmem_conf != NULL) { | ||
88 | *start = fbmem_conf->fb_sram_start; | ||
89 | *size = fbmem_conf->fb_sram_size; | ||
90 | } else { | ||
91 | *size = 0; | ||
92 | *start = 0; | ||
93 | } | ||
94 | |||
95 | if (*size && ( | ||
96 | *start < start_avail || | ||
97 | *start + *size > start_avail + size_avail)) { | ||
98 | printk(KERN_ERR "invalid FB SRAM configuration\n"); | ||
99 | *start = start_avail; | ||
100 | *size = size_avail; | ||
101 | } | ||
102 | |||
103 | if (*size) | ||
104 | pr_info("Reserving %lu bytes SRAM for frame buffer\n", *size); | ||
105 | } | ||
106 | |||
37 | /* | 107 | /* |
38 | * The amount of SRAM depends on the core type. | 108 | * The amount of SRAM depends on the core type. |
39 | * Note that we cannot try to test for SRAM here because writes | 109 | * Note that we cannot try to test for SRAM here because writes |
@@ -42,26 +112,45 @@ static unsigned long omap_sram_ceil; | |||
42 | */ | 112 | */ |
43 | void __init omap_detect_sram(void) | 113 | void __init omap_detect_sram(void) |
44 | { | 114 | { |
45 | if (!cpu_is_omap24xx()) | 115 | unsigned long sram_start; |
116 | |||
117 | if (cpu_is_omap24xx()) { | ||
118 | if (is_sram_locked()) { | ||
119 | omap_sram_base = OMAP2_SRAM_PUB_VA; | ||
120 | sram_start = OMAP2_SRAM_PUB_PA; | ||
121 | omap_sram_size = 0x800; /* 2K */ | ||
122 | } else { | ||
123 | omap_sram_base = OMAP2_SRAM_VA; | ||
124 | sram_start = OMAP2_SRAM_PA; | ||
125 | if (cpu_is_omap242x()) | ||
126 | omap_sram_size = 0xa0000; /* 640K */ | ||
127 | else if (cpu_is_omap243x()) | ||
128 | omap_sram_size = 0x10000; /* 64K */ | ||
129 | } | ||
130 | } else { | ||
46 | omap_sram_base = OMAP1_SRAM_VA; | 131 | omap_sram_base = OMAP1_SRAM_VA; |
47 | else | 132 | sram_start = OMAP1_SRAM_PA; |
48 | omap_sram_base = OMAP2_SRAM_VA; | 133 | |
49 | 134 | if (cpu_is_omap730()) | |
50 | if (cpu_is_omap730()) | 135 | omap_sram_size = 0x32000; /* 200K */ |
51 | omap_sram_size = 0x32000; /* 200K */ | 136 | else if (cpu_is_omap15xx()) |
52 | else if (cpu_is_omap15xx()) | 137 | omap_sram_size = 0x30000; /* 192K */ |
53 | omap_sram_size = 0x30000; /* 192K */ | 138 | else if (cpu_is_omap1610() || cpu_is_omap1621() || |
54 | else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710()) | 139 | cpu_is_omap1710()) |
55 | omap_sram_size = 0x4000; /* 16K */ | 140 | omap_sram_size = 0x4000; /* 16K */ |
56 | else if (cpu_is_omap1611()) | 141 | else if (cpu_is_omap1611()) |
57 | omap_sram_size = 0x3e800; /* 250K */ | 142 | omap_sram_size = 0x3e800; /* 250K */ |
58 | else if (cpu_is_omap2420()) | 143 | else { |
59 | omap_sram_size = 0xa0014; /* 640K */ | 144 | printk(KERN_ERR "Could not detect SRAM size\n"); |
60 | else { | 145 | omap_sram_size = 0x4000; |
61 | printk(KERN_ERR "Could not detect SRAM size\n"); | 146 | } |
62 | omap_sram_size = 0x4000; | ||
63 | } | 147 | } |
64 | 148 | get_fb_sram_conf(sram_start + SRAM_BOOTLOADER_SZ, | |
149 | omap_sram_size - SRAM_BOOTLOADER_SZ, | ||
150 | &omap_fb_sram_start, &omap_fb_sram_size); | ||
151 | if (omap_fb_sram_size) | ||
152 | omap_sram_size -= sram_start + omap_sram_size - | ||
153 | omap_fb_sram_start; | ||
65 | omap_sram_ceil = omap_sram_base + omap_sram_size; | 154 | omap_sram_ceil = omap_sram_base + omap_sram_size; |
66 | } | 155 | } |
67 | 156 | ||
@@ -80,12 +169,20 @@ static struct map_desc omap_sram_io_desc[] __initdata = { | |||
80 | */ | 169 | */ |
81 | void __init omap_map_sram(void) | 170 | void __init omap_map_sram(void) |
82 | { | 171 | { |
172 | unsigned long base; | ||
173 | |||
83 | if (omap_sram_size == 0) | 174 | if (omap_sram_size == 0) |
84 | return; | 175 | return; |
85 | 176 | ||
86 | if (cpu_is_omap24xx()) { | 177 | if (cpu_is_omap24xx()) { |
87 | omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA; | 178 | omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA; |
88 | omap_sram_io_desc[0].pfn = __phys_to_pfn(OMAP2_SRAM_PA); | 179 | |
180 | if (is_sram_locked()) | ||
181 | base = OMAP2_SRAM_PUB_PA; | ||
182 | else | ||
183 | base = OMAP2_SRAM_PA; | ||
184 | base = ROUND_DOWN(base, PAGE_SIZE); | ||
185 | omap_sram_io_desc[0].pfn = __phys_to_pfn(base); | ||
89 | } | 186 | } |
90 | 187 | ||
91 | omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE; | 188 | omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE; |
@@ -93,7 +190,8 @@ void __init omap_map_sram(void) | |||
93 | iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc)); | 190 | iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc)); |
94 | 191 | ||
95 | printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n", | 192 | printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n", |
96 | omap_sram_io_desc[0].pfn, omap_sram_io_desc[0].virtual, | 193 | __pfn_to_phys(omap_sram_io_desc[0].pfn), |
194 | omap_sram_io_desc[0].virtual, | ||
97 | omap_sram_io_desc[0].length); | 195 | omap_sram_io_desc[0].length); |
98 | 196 | ||
99 | /* | 197 | /* |
@@ -118,8 +216,9 @@ void * omap_sram_push(void * start, unsigned long size) | |||
118 | printk(KERN_ERR "Not enough space in SRAM\n"); | 216 | printk(KERN_ERR "Not enough space in SRAM\n"); |
119 | return NULL; | 217 | return NULL; |
120 | } | 218 | } |
219 | |||
121 | omap_sram_ceil -= size; | 220 | omap_sram_ceil -= size; |
122 | omap_sram_ceil &= ~0x3; | 221 | omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, sizeof(void *)); |
123 | memcpy((void *)omap_sram_ceil, start, size); | 222 | memcpy((void *)omap_sram_ceil, start, size); |
124 | 223 | ||
125 | return (void *)omap_sram_ceil; | 224 | return (void *)omap_sram_ceil; |