Merge branch 'depends/rmk/memory_h' into next/fixes
[linux-2.6.git] / arch / arm / mach-davinci / sleep.S
1 /*
2  * (C) Copyright 2009, Texas Instruments, Inc. http://www.ti.com/
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * version 2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
16  * MA 02111-1307 USA
17  */
18
19 /* replicated define because linux/bitops.h cannot be included in assembly */
20 #define BIT(nr)                 (1 << (nr))
21
22 #include <linux/linkage.h>
23 #include <asm/assembler.h>
24 #include <mach/psc.h>
25 #include <mach/ddr2.h>
26
27 #include "clock.h"
28
29 /* Arbitrary, hardware currently does not update PHYRDY correctly */
30 #define PHYRDY_CYCLES           0x1000
31
32 /* Assume 25 MHz speed for the cycle conversions since PLLs are bypassed */
33 #define PLL_BYPASS_CYCLES       (PLL_BYPASS_TIME * 25)
34 #define PLL_RESET_CYCLES        (PLL_RESET_TIME * 25)
35 #define PLL_LOCK_CYCLES         (PLL_LOCK_TIME * 25)
36
37 #define DEEPSLEEP_SLEEPENABLE_BIT       BIT(31)
38
39         .text
40 /*
41  * Move DaVinci into deep sleep state
42  *
43  * Note: This code is copied to internal SRAM by PM code. When the DaVinci
44  *       wakes up it continues execution at the point it went to sleep.
45  * Register Usage:
46  *      r0: contains virtual base for DDR2 controller
47  *      r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
48  *      r2: contains PSC number for DDR2
49  *      r3: contains virtual base DDR2 PLL controller
50  *      r4: contains virtual address of the DEEPSLEEP register
51  */
52 ENTRY(davinci_cpu_suspend)
53         stmfd   sp!, {r0-r12, lr}               @ save registers on stack
54
55         ldr     ip, CACHE_FLUSH
56         blx     ip
57
58         ldmia   r0, {r0-r4}
59
60         /*
61          * Switch DDR to self-refresh mode.
62          */
63
64         /* calculate SDRCR address */
65         ldr     ip, [r0, #DDR2_SDRCR_OFFSET]
66         bic     ip, ip, #DDR2_SRPD_BIT
67         orr     ip, ip, #DDR2_LPMODEN_BIT
68         str     ip, [r0, #DDR2_SDRCR_OFFSET]
69
70         ldr     ip, [r0, #DDR2_SDRCR_OFFSET]
71         orr     ip, ip, #DDR2_MCLKSTOPEN_BIT
72         str     ip, [r0, #DDR2_SDRCR_OFFSET]
73
74        mov      ip, #PHYRDY_CYCLES
75 1:     subs     ip, ip, #0x1
76        bne      1b
77
78        /* Disable DDR2 LPSC */
79         mov     r7, r0
80         mov     r0, #0x2
81         bl davinci_ddr_psc_config
82         mov     r0, r7
83
84         /* Disable clock to DDR PHY */
85         ldr     ip, [r3, #PLLDIV1]
86         bic     ip, ip, #PLLDIV_EN
87         str     ip, [r3, #PLLDIV1]
88
89         /* Put the DDR PLL in bypass and power down */
90         ldr     ip, [r3, #PLLCTL]
91         bic     ip, ip, #PLLCTL_PLLENSRC
92         bic     ip, ip, #PLLCTL_PLLEN
93         str     ip, [r3, #PLLCTL]
94
95         /* Wait for PLL to switch to bypass */
96        mov      ip, #PLL_BYPASS_CYCLES
97 2:     subs     ip, ip, #0x1
98        bne      2b
99
100        /* Power down the PLL */
101         ldr     ip, [r3, #PLLCTL]
102         orr     ip, ip, #PLLCTL_PLLPWRDN
103         str     ip, [r3, #PLLCTL]
104
105         /* Go to deep sleep */
106         ldr     ip, [r4]
107         orr     ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
108         /* System goes to sleep beyond after this instruction */
109         str     ip, [r4]
110
111         /* Wake up from sleep */
112
113         /* Clear sleep enable */
114         ldr     ip, [r4]
115         bic     ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
116         str     ip, [r4]
117
118         /* initialize the DDR PLL controller */
119
120         /* Put PLL in reset */
121         ldr     ip, [r3, #PLLCTL]
122         bic     ip, ip, #PLLCTL_PLLRST
123         str     ip, [r3, #PLLCTL]
124
125         /* Clear PLL power down */
126         ldr     ip, [r3, #PLLCTL]
127         bic     ip, ip, #PLLCTL_PLLPWRDN
128         str     ip, [r3, #PLLCTL]
129
130        mov      ip, #PLL_RESET_CYCLES
131 3:     subs     ip, ip, #0x1
132        bne      3b
133
134        /* Bring PLL out of reset */
135         ldr     ip, [r3, #PLLCTL]
136         orr     ip, ip, #PLLCTL_PLLRST
137         str     ip, [r3, #PLLCTL]
138
139         /* Wait for PLL to lock (assume prediv = 1, 25MHz OSCIN) */
140        mov      ip, #PLL_LOCK_CYCLES
141 4:     subs     ip, ip, #0x1
142        bne      4b
143
144        /* Remove PLL from bypass mode */
145         ldr     ip, [r3, #PLLCTL]
146         bic     ip, ip, #PLLCTL_PLLENSRC
147         orr     ip, ip, #PLLCTL_PLLEN
148         str     ip, [r3, #PLLCTL]
149
150         /* Start 2x clock to DDR2 */
151
152         ldr     ip, [r3, #PLLDIV1]
153         orr     ip, ip, #PLLDIV_EN
154         str     ip, [r3, #PLLDIV1]
155
156         /* Enable VCLK */
157
158        /* Enable DDR2 LPSC */
159         mov     r7, r0
160         mov     r0, #0x3
161         bl davinci_ddr_psc_config
162         mov     r0, r7
163
164         /* clear  MCLKSTOPEN */
165
166         ldr     ip, [r0, #DDR2_SDRCR_OFFSET]
167         bic     ip, ip, #DDR2_MCLKSTOPEN_BIT
168         str     ip, [r0, #DDR2_SDRCR_OFFSET]
169
170         ldr     ip, [r0, #DDR2_SDRCR_OFFSET]
171         bic     ip, ip, #DDR2_LPMODEN_BIT
172         str     ip, [r0, #DDR2_SDRCR_OFFSET]
173
174         /* Restore registers and return */
175         ldmfd   sp!, {r0-r12, pc}
176
177 ENDPROC(davinci_cpu_suspend)
178
179 /*
180  * Disables or Enables DDR2 LPSC
181  * Register Usage:
182  *      r0: Enable or Disable LPSC r0 = 0x3 => Enable, r0 = 0x2 => Disable LPSC
183  *      r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
184  *      r2: contains PSC number for DDR2
185  */
186 ENTRY(davinci_ddr_psc_config)
187         /* Set next state in mdctl for DDR2 */
188         mov     r6, #MDCTL
189         add     r6, r6, r2, lsl #2
190         ldr     ip, [r1, r6]
191         bic     ip, ip, #MDSTAT_STATE_MASK
192         orr     ip, ip, r0
193         str     ip, [r1, r6]
194
195         /* Enable the Power Domain Transition Command */
196         ldr     ip, [r1, #PTCMD]
197         orr     ip, ip, #0x1
198         str     ip, [r1, #PTCMD]
199
200         /* Check for Transition Complete (PTSTAT) */
201 ptstat_done:
202         ldr     ip, [r1, #PTSTAT]
203         and     ip, ip, #0x1
204         cmp     ip, #0x0
205         bne     ptstat_done
206
207         /* Check for DDR2 clock disable completion; */
208         mov     r6, #MDSTAT
209         add     r6, r6, r2, lsl #2
210 ddr2clk_stop_done:
211         ldr     ip, [r1, r6]
212         and     ip, ip, #MDSTAT_STATE_MASK
213         cmp     ip, r0
214         bne     ddr2clk_stop_done
215
216         mov     pc, lr
217 ENDPROC(davinci_ddr_psc_config)
218
219 CACHE_FLUSH:
220 #ifdef CONFIG_CPU_V6
221         .word   v6_flush_kern_cache_all
222 #else
223         .word   arm926_flush_kern_cache_all
224 #endif
225
226 ENTRY(davinci_cpu_suspend_sz)
227         .word   . - davinci_cpu_suspend
228 ENDPROC(davinci_cpu_suspend_sz)