Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
[linux-2.6] / arch / arm / mach-omap2 / sleep.S
1 /*
2  * linux/arch/arm/mach-omap2/sleep.S
3  *
4  * (C) Copyright 2004
5  * Texas Instruments, <www.ti.com>
6  * Richard Woodruff <r-woodruff2@ti.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <linux/linkage.h>
25 #include <asm/assembler.h>
26 #include <asm/arch/io.h>
27 #include <asm/arch/pm.h>
28
29 #define A_32KSYNC_CR_V          IO_ADDRESS(OMAP_TIMER32K_BASE+0x10)
30 #define A_PRCM_VOLTCTRL_V       IO_ADDRESS(OMAP24XX_PRCM_BASE+0x50)
31 #define A_PRCM_CLKCFG_CTRL_V    IO_ADDRESS(OMAP24XX_PRCM_BASE+0x80)
32 #define A_CM_CLKEN_PLL_V        IO_ADDRESS(OMAP24XX_PRCM_BASE+0x500)
33 #define A_CM_IDLEST_CKGEN_V     IO_ADDRESS(OMAP24XX_PRCM_BASE+0x520)
34 #define A_CM_CLKSEL1_PLL_V      IO_ADDRESS(OMAP24XX_PRCM_BASE+0x540)
35 #define A_CM_CLKSEL2_PLL_V      IO_ADDRESS(OMAP24XX_PRCM_BASE+0x544)
36
37 #define A_SDRC_DLLA_CTRL_V      IO_ADDRESS(OMAP24XX_SDRC_BASE+0x60)
38 #define A_SDRC_POWER_V          IO_ADDRESS(OMAP24XX_SDRC_BASE+0x70)
39 #define A_SDRC_RFR_CTRL_V       IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA4)
40 #define A_SDRC0_V               (0xC0000000)
41 #define A_SDRC_MANUAL_V         IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA8)
42
43         .text
44
45 /*
46  * Forces OMAP into idle state
47  *
48  * omap24xx_idle_loop_suspend() - This bit of code just executes the WFI
49  * for normal idles.
50  *
51  * Note: This code get's copied to internal SRAM at boot. When the OMAP
52  *       wakes up it continues execution at the point it went to sleep.
53  */
54 ENTRY(omap24xx_idle_loop_suspend)
55         stmfd   sp!, {r0, lr}           @ save registers on stack
56         mov     r0, #0                  @ clear for mcr setup
57         mcr     p15, 0, r0, c7, c0, 4   @ wait for interrupt
58         ldmfd   sp!, {r0, pc}           @ restore regs and return
59
60 ENTRY(omap24xx_idle_loop_suspend_sz)
61         .word   . - omap24xx_idle_loop_suspend
62
63 /*
64  * omap242x_cpu_suspend() - Forces OMAP into deep sleep state by completing
65  * SDRC shutdown then ARM shutdown.  Upon wake MPU is back on so just restore
66  * SDRC.
67  *
68  * Input:
69  * R0 : DLL ctrl value pre-Sleep
70  * R1 : Processor+Revision
71  *      2420: 0x21 = 242xES1, 0x26 = 242xES2.2
72  *      2430: 0x31 = 2430ES1, 0x32 = 2430ES2
73  *
74  * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on
75  * when we get called, but the DLL probably isn't.  We will wait a bit more in
76  * case the DPLL isn't quite there yet. The code will wait on DLL for DDR even
77  * if in unlocked mode.
78  *
79  * For less than 242x-ES2.2 upon wake from a sleep mode where the external
80  * oscillator was stopped, a timing bug exists where a non-stabilized 12MHz
81  * clock can pass into the PRCM can cause problems at DSP and IVA.
82  * To work around this the code will switch to the 32kHz source prior to sleep.
83  * Post sleep we will shift back to using the DPLL.  Apparently,
84  * CM_IDLEST_CLKGEN does not reflect the full clock change so you need to wait
85  * 3x12MHz + 3x32kHz clocks for a full switch.
86  *
87  * The DLL load value is not kept in RETENTION or OFF.  It needs to be restored
88  * at wake
89  */
90 ENTRY(omap24xx_cpu_suspend)
91         stmfd   sp!, {r0 - r12, lr}     @ save registers on stack
92         mov     r3, #0x0                @ clear for mrc call
93         mcr     p15, 0, r3, c7, c10, 4  @ memory barrier, hope SDR/DDR finished
94         nop
95         nop
96         ldr     r3, A_SDRC_POWER        @ addr of sdrc power
97         ldr     r4, [r3]                @ value of sdrc power
98         orr     r4, r4, #0x40           @ enable self refresh on idle req
99         mov     r5, #0x2000             @ set delay (DPLL relock + DLL relock)
100         str     r4, [r3]                @ make it so
101         mov     r2, #0
102         nop
103         mcr     p15, 0, r2, c7, c0, 4   @ wait for interrupt
104         nop
105 loop:
106         subs    r5, r5, #0x1            @ awake, wait just a bit
107         bne     loop
108
109         /* The DPLL has on before we take the DDR out of self refresh */
110         bic     r4, r4, #0x40           @ now clear self refresh bit.
111         str     r4, [r3]                @ put vlaue back.
112         ldr     r4, A_SDRC0             @ make a clock happen
113         ldr     r4, [r4]
114         nop                             @ start auto refresh only after clk ok
115         movs    r0, r0                  @ see if DDR or SDR
116         ldrne   r1, A_SDRC_DLLA_CTRL_S  @ get addr of DLL ctrl
117         strne   r0, [r1]                @ rewrite DLLA to force DLL reload
118         addne   r1, r1, #0x8            @ move to DLLB
119         strne   r0, [r1]                @ rewrite DLLB to force DLL reload
120
121         mov     r5, #0x1000
122 loop2:
123         subs    r5, r5, #0x1
124         bne     loop2
125         /* resume*/
126         ldmfd   sp!, {r0 - r12, pc}     @ restore regs and return
127
128 A_SDRC_POWER:
129         .word A_SDRC_POWER_V
130 A_SDRC0:
131         .word A_SDRC0_V
132 A_CM_CLKSEL2_PLL_S:
133         .word A_CM_CLKSEL2_PLL_V
134 A_CM_CLKEN_PLL:
135         .word A_CM_CLKEN_PLL_V
136 A_SDRC_DLLA_CTRL_S:
137         .word A_SDRC_DLLA_CTRL_V
138 A_SDRC_MANUAL_S:
139         .word A_SDRC_MANUAL_V
140
141 ENTRY(omap24xx_cpu_suspend_sz)
142         .word   . - omap24xx_cpu_suspend
143