Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
[pandora-kernel.git] / arch / arm / mach-omap1 / sleep.S
1 /*
2  * linux/arch/arm/mach-omap1/sleep.S
3  *
4  * Low-level OMAP7XX/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/linkage.h>
36 #include <asm/assembler.h>
37 #include <mach/io.h>
38 #include "pm.h"
39
40                 .text
41
42
43 /*
44  * Forces OMAP into deep sleep state
45  *
46  * omapXXXX_cpu_suspend()
47  *
48  * The values of the registers ARM_IDLECT1 and ARM_IDLECT2 are passed
49  * as arg0 and arg1 from caller. arg0 is stored in register r0 and arg1
50  * in register r1.
51  *
52  * Note: This code get's copied to internal SRAM at boot. When the OMAP
53  *       wakes up it continues execution at the point it went to sleep.
54  *
55  * Note: Because of errata work arounds we have processor specific functions
56  *       here. They are mostly the same, but slightly different.
57  *
58  */
59
60 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
61         .align  3
62 ENTRY(omap7xx_cpu_suspend)
63
64         @ save registers on stack
65         stmfd   sp!, {r0 - r12, lr}
66
67         @ Drain write cache
68         mov     r4, #0
69         mcr     p15, 0, r0, c7, c10, 4
70         nop
71
72         @ load base address of Traffic Controller
73         mov     r6, #TCMIF_ASM_BASE & 0xff000000
74         orr     r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
75         orr     r6, r6, #TCMIF_ASM_BASE & 0x0000ff00
76
77         @ prepare to put SDRAM into self-refresh manually
78         ldr     r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
79         orr     r9, r7, #SELF_REFRESH_MODE & 0xff000000
80         orr     r9, r9, #SELF_REFRESH_MODE & 0x000000ff
81         str     r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
82
83         @ prepare to put EMIFS to Sleep
84         ldr     r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
85         orr     r9, r8, #IDLE_EMIFS_REQUEST & 0xff
86         str     r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
87
88         @ load base address of ARM_IDLECT1 and ARM_IDLECT2
89         mov     r4, #CLKGEN_REG_ASM_BASE & 0xff000000
90         orr     r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
91         orr     r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
92
93         @ turn off clock domains
94         @ do not disable PERCK (0x04)
95         mov     r5, #OMAP7XX_IDLECT2_SLEEP_VAL & 0xff
96         orr     r5, r5, #OMAP7XX_IDLECT2_SLEEP_VAL & 0xff00
97         strh    r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
98
99         @ request ARM idle
100         mov     r3, #OMAP7XX_IDLECT1_SLEEP_VAL & 0xff
101         orr     r3, r3, #OMAP7XX_IDLECT1_SLEEP_VAL & 0xff00
102         strh    r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
103
104         @ disable instruction cache
105         mrc     p15, 0, r9, c1, c0, 0
106         bic     r2, r9, #0x1000
107         mcr     p15, 0, r2, c1, c0, 0
108         nop
109
110 /*
111  * Let's wait for the next wake up event to wake us up. r0 can't be
112  * used here because r0 holds ARM_IDLECT1
113  */
114         mov     r2, #0
115         mcr     p15, 0, r2, c7, c0, 4           @ wait for interrupt
116 /*
117  * omap7xx_cpu_suspend()'s resume point.
118  *
119  * It will just start executing here, so we'll restore stuff from the
120  * stack.
121  */
122         @ re-enable Icache
123         mcr     p15, 0, r9, c1, c0, 0
124
125         @ reset the ARM_IDLECT1 and ARM_IDLECT2.
126         strh    r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
127         strh    r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
128
129         @ Restore EMIFF controls
130         str     r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
131         str     r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
132
133         @ restore regs and return
134         ldmfd   sp!, {r0 - r12, pc}
135
136 ENTRY(omap7xx_cpu_suspend_sz)
137         .word   . - omap7xx_cpu_suspend
138 #endif /* CONFIG_ARCH_OMAP730 || CONFIG_ARCH_OMAP850 */
139
140 #ifdef CONFIG_ARCH_OMAP15XX
141         .align  3
142 ENTRY(omap1510_cpu_suspend)
143
144         @ save registers on stack
145         stmfd   sp!, {r0 - r12, lr}
146
147         @ load base address of Traffic Controller
148         mov     r4, #TCMIF_ASM_BASE & 0xff000000
149         orr     r4, r4, #TCMIF_ASM_BASE & 0x00ff0000
150         orr     r4, r4, #TCMIF_ASM_BASE & 0x0000ff00
151
152         @ work around errata of OMAP1510 PDE bit for TC shut down
153         @ clear PDE bit
154         ldr     r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
155         bic     r5, r5, #PDE_BIT & 0xff
156         str     r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
157
158         @ set PWD_EN bit
159         and     r5, r5, #PWD_EN_BIT & 0xff
160         str     r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
161
162         @ prepare to put SDRAM into self-refresh manually
163         ldr     r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
164         orr     r5, r5, #SELF_REFRESH_MODE & 0xff000000
165         orr     r5, r5, #SELF_REFRESH_MODE & 0x000000ff
166         str     r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
167
168         @ prepare to put EMIFS to Sleep
169         ldr     r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
170         orr     r5, r5, #IDLE_EMIFS_REQUEST & 0xff
171         str     r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
172
173         @ load base address of ARM_IDLECT1 and ARM_IDLECT2
174         mov     r4, #CLKGEN_REG_ASM_BASE & 0xff000000
175         orr     r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
176         orr     r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
177
178         @ turn off clock domains
179         mov     r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
180         orr     r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
181         strh    r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
182
183         @ request ARM idle
184         mov     r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff
185         orr     r3, r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff00
186         strh    r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
187
188         mov     r5, #IDLE_WAIT_CYCLES & 0xff
189         orr     r5, r5, #IDLE_WAIT_CYCLES & 0xff00
190 l_1510_2:
191         subs    r5, r5, #1
192         bne     l_1510_2
193 /*
194  * Let's wait for the next wake up event to wake us up. r0 can't be
195  * used here because r0 holds ARM_IDLECT1
196  */
197         mov     r2, #0
198         mcr     p15, 0, r2, c7, c0, 4           @ wait for interrupt
199 /*
200  * omap1510_cpu_suspend()'s resume point.
201  *
202  * It will just start executing here, so we'll restore stuff from the
203  * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
204  */
205         strh    r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
206         strh    r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
207
208         @ restore regs and return
209         ldmfd   sp!, {r0 - r12, pc}
210
211 ENTRY(omap1510_cpu_suspend_sz)
212         .word   . - omap1510_cpu_suspend
213 #endif /* CONFIG_ARCH_OMAP15XX */
214
215 #if defined(CONFIG_ARCH_OMAP16XX)
216         .align  3
217 ENTRY(omap1610_cpu_suspend)
218
219         @ save registers on stack
220         stmfd   sp!, {r0 - r12, lr}
221
222         @ Drain write cache
223         mov     r4, #0
224         mcr     p15, 0, r0, c7, c10, 4
225         nop
226
227         @ Load base address of Traffic Controller
228         mov     r6, #TCMIF_ASM_BASE & 0xff000000
229         orr     r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
230         orr     r6, r6, #TCMIF_ASM_BASE & 0x0000ff00
231
232         @ Prepare to put SDRAM into self-refresh manually
233         ldr     r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
234         orr     r9, r7, #SELF_REFRESH_MODE & 0xff000000
235         orr     r9, r9, #SELF_REFRESH_MODE & 0x000000ff
236         str     r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
237
238         @ Prepare to put EMIFS to Sleep
239         ldr     r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
240         orr     r9, r8, #IDLE_EMIFS_REQUEST & 0xff
241         str     r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
242
243         @ Load base address of ARM_IDLECT1 and ARM_IDLECT2
244         mov     r4, #CLKGEN_REG_ASM_BASE & 0xff000000
245         orr     r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
246         orr     r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
247
248         @ Turn off clock domains
249         @ Do not disable PERCK (0x04)
250         mov     r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
251         orr     r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
252         strh    r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
253
254         @ Request ARM idle
255         mov     r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
256         orr     r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00
257         strh    r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
258
259 /*
260  * Let's wait for the next wake up event to wake us up. r0 can't be
261  * used here because r0 holds ARM_IDLECT1
262  */
263         mov     r2, #0
264         mcr     p15, 0, r2, c7, c0, 4           @ wait for interrupt
265
266         @ Errata (HEL3SU467, section 1.4.4) specifies nop-instructions
267         @ according to this formula:
268         @ 2 + (4*DPLL_MULT)/DPLL_DIV/ARMDIV
269         @ Max DPLL_MULT = 18
270         @ DPLL_DIV = 1
271         @ ARMDIV = 1
272         @ => 74 nop-instructions
273         nop
274         nop
275         nop
276         nop
277         nop
278         nop
279         nop
280         nop
281         nop
282         nop     @10
283         nop
284         nop
285         nop
286         nop
287         nop
288         nop
289         nop
290         nop
291         nop
292         nop     @20
293         nop
294         nop
295         nop
296         nop
297         nop
298         nop
299         nop
300         nop
301         nop
302         nop     @30
303         nop
304         nop
305         nop
306         nop
307         nop
308         nop
309         nop
310         nop
311         nop
312         nop     @40
313         nop
314         nop
315         nop
316         nop
317         nop
318         nop
319         nop
320         nop
321         nop
322         nop     @50
323         nop
324         nop
325         nop
326         nop
327         nop
328         nop
329         nop
330         nop
331         nop
332         nop     @60
333         nop
334         nop
335         nop
336         nop
337         nop
338         nop
339         nop
340         nop
341         nop
342         nop     @70
343         nop
344         nop
345         nop
346         nop     @74
347 /*
348  * omap1610_cpu_suspend()'s resume point.
349  *
350  * It will just start executing here, so we'll restore stuff from the
351  * stack.
352  */
353         @ Restore the ARM_IDLECT1 and ARM_IDLECT2.
354         strh    r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
355         strh    r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
356
357         @ Restore EMIFF controls
358         str     r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
359         str     r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
360
361         @ Restore regs and return
362         ldmfd   sp!, {r0 - r12, pc}
363
364 ENTRY(omap1610_cpu_suspend_sz)
365         .word   . - omap1610_cpu_suspend
366 #endif /* CONFIG_ARCH_OMAP16XX */