[ARM] 3430/1: ARM: OMAP: 5/8 Update PM
[safe/jmp/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/config.h>
25 #include <linux/linkage.h>
26 #include <asm/assembler.h>
27 #include <asm/arch/io.h>
28 #include <asm/arch/pm.h>
29
30 #define A_32KSYNC_CR_V          IO_ADDRESS(OMAP_TIMER32K_BASE+0x10)
31 #define A_PRCM_VOLTCTRL_V       IO_ADDRESS(OMAP24XX_PRCM_BASE+0x50)
32 #define A_PRCM_CLKCFG_CTRL_V    IO_ADDRESS(OMAP24XX_PRCM_BASE+0x80)
33 #define A_CM_CLKEN_PLL_V        IO_ADDRESS(OMAP24XX_PRCM_BASE+0x500)
34 #define A_CM_IDLEST_CKGEN_V     IO_ADDRESS(OMAP24XX_PRCM_BASE+0x520)
35 #define A_CM_CLKSEL1_PLL_V      IO_ADDRESS(OMAP24XX_PRCM_BASE+0x540)
36 #define A_CM_CLKSEL2_PLL_V      IO_ADDRESS(OMAP24XX_PRCM_BASE+0x544)
37
38 #define A_SDRC_DLLA_CTRL_V      IO_ADDRESS(OMAP24XX_SDRC_BASE+0x60)
39 #define A_SDRC_POWER_V          IO_ADDRESS(OMAP24XX_SDRC_BASE+0x70)
40 #define A_SDRC_RFR_CTRL_V       IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA4)
41 #define A_SDRC0_V               (0xC0000000)
42 #define A_SDRC_MANUAL_V         IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA8)
43
44         .text
45
46 /*
47  * Forces OMAP into idle state
48  *
49  * omap24xx_idle_loop_suspend() - This bit of code just executes the WFI
50  * for normal idles.
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 ENTRY(omap24xx_idle_loop_suspend)
56         stmfd   sp!, {r0, lr}           @ save registers on stack
57         mov     r0, #0                  @ clear for mcr setup
58         mcr     p15, 0, r0, c7, c0, 4   @ wait for interrupt
59         ldmfd   sp!, {r0, pc}           @ restore regs and return
60
61 ENTRY(omap24xx_idle_loop_suspend_sz)
62         .word   . - omap24xx_idle_loop_suspend
63
64 /*
65  * omap242x_cpu_suspend() - Forces OMAP into deep sleep state by completing
66  * SDRC shutdown then ARM shutdown.  Upon wake MPU is back on so just restore
67  * SDRC.
68  *
69  * Input:
70  * R0 : DLL ctrl value pre-Sleep
71  * R1 : Processor+Revision
72  *      2420: 0x21 = 242xES1, 0x26 = 242xES2.2
73  *      2430: 0x31 = 2430ES1, 0x32 = 2430ES2
74  *
75  * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on
76  * when we get called, but the DLL probably isn't.  We will wait a bit more in
77  * case the DPLL isn't quite there yet. The code will wait on DLL for DDR even
78  * if in unlocked mode.
79  *
80  * For less than 242x-ES2.2 upon wake from a sleep mode where the external
81  * oscillator was stopped, a timing bug exists where a non-stabilized 12MHz
82  * clock can pass into the PRCM can cause problems at DSP and IVA.
83  * To work around this the code will switch to the 32kHz source prior to sleep.
84  * Post sleep we will shift back to using the DPLL.  Apparently,
85  * CM_IDLEST_CLKGEN does not reflect the full clock change so you need to wait
86  * 3x12MHz + 3x32kHz clocks for a full switch.
87  *
88  * The DLL load value is not kept in RETENTION or OFF.  It needs to be restored
89  * at wake
90  */
91 ENTRY(omap24xx_cpu_suspend)
92         stmfd   sp!, {r0 - r12, lr}     @ save registers on stack
93         mov     r3, #0x0                @ clear for mrc call
94         mcr     p15, 0, r3, c7, c10, 4  @ memory barrier, hope SDR/DDR finished
95         nop
96         nop
97         ldr     r3, A_SDRC_POWER        @ addr of sdrc power
98         ldr     r4, [r3]                @ value of sdrc power
99         orr     r4, r4, #0x40           @ enable self refresh on idle req
100         mov     r5, #0x2000             @ set delay (DPLL relock + DLL relock)
101         str     r4, [r3]                @ make it so
102         mov     r2, #0
103         nop
104         mcr     p15, 0, r2, c7, c0, 4   @ wait for interrupt
105         nop
106 loop:
107         subs    r5, r5, #0x1            @ awake, wait just a bit
108         bne     loop
109
110         /* The DPLL has on before we take the DDR out of self refresh */
111         bic     r4, r4, #0x40           @ now clear self refresh bit.
112         str     r4, [r3]                @ put vlaue back.
113         ldr     r4, A_SDRC0             @ make a clock happen
114         ldr     r4, [r4]
115         nop                             @ start auto refresh only after clk ok
116         movs    r0, r0                  @ see if DDR or SDR
117         ldrne   r1, A_SDRC_DLLA_CTRL_S  @ get addr of DLL ctrl
118         strne   r0, [r1]                @ rewrite DLLA to force DLL reload
119         addne   r1, r1, #0x8            @ move to DLLB
120         strne   r0, [r1]                @ rewrite DLLB to force DLL reload
121
122         mov     r5, #0x1000
123 loop2:
124         subs    r5, r5, #0x1
125         bne     loop2
126         /* resume*/
127         ldmfd   sp!, {r0 - r12, pc}     @ restore regs and return
128
129 A_SDRC_POWER:
130         .word A_SDRC_POWER_V
131 A_SDRC0:
132         .word A_SDRC0_V
133 A_CM_CLKSEL2_PLL_S:
134         .word A_CM_CLKSEL2_PLL_V
135 A_CM_CLKEN_PLL:
136         .word A_CM_CLKEN_PLL_V
137 A_SDRC_DLLA_CTRL_S:
138         .word A_SDRC_DLLA_CTRL_V
139 A_SDRC_MANUAL_S:
140         .word A_SDRC_MANUAL_V
141
142 ENTRY(omap24xx_cpu_suspend_sz)
143         .word   . - omap24xx_cpu_suspend
144