GNU Linux-libre 4.19.264-gnu1
[releases.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 "psc.h"
25 #include "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         .arch   armv5te
41 /*
42  * Move DaVinci into deep sleep state
43  *
44  * Note: This code is copied to internal SRAM by PM code. When the DaVinci
45  *       wakes up it continues execution at the point it went to sleep.
46  * Register Usage:
47  *      r0: contains virtual base for DDR2 controller
48  *      r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
49  *      r2: contains PSC number for DDR2
50  *      r3: contains virtual base DDR2 PLL controller
51  *      r4: contains virtual address of the DEEPSLEEP register
52  */
53 ENTRY(davinci_cpu_suspend)
54         stmfd   sp!, {r0-r12, lr}               @ save registers on stack
55
56         ldr     ip, CACHE_FLUSH
57         blx     ip
58
59         ldmia   r0, {r0-r4}
60
61         /*
62          * Switch DDR to self-refresh mode.
63          */
64
65         /* calculate SDRCR address */
66         ldr     ip, [r0, #DDR2_SDRCR_OFFSET]
67         bic     ip, ip, #DDR2_SRPD_BIT
68         orr     ip, ip, #DDR2_LPMODEN_BIT
69         str     ip, [r0, #DDR2_SDRCR_OFFSET]
70
71         ldr     ip, [r0, #DDR2_SDRCR_OFFSET]
72         orr     ip, ip, #DDR2_MCLKSTOPEN_BIT
73         str     ip, [r0, #DDR2_SDRCR_OFFSET]
74
75        mov      ip, #PHYRDY_CYCLES
76 1:     subs     ip, ip, #0x1
77        bne      1b
78
79        /* Disable DDR2 LPSC */
80         mov     r7, r0
81         mov     r0, #0x2
82         bl davinci_ddr_psc_config
83         mov     r0, r7
84
85         /* Disable clock to DDR PHY */
86         ldr     ip, [r3, #PLLDIV1]
87         bic     ip, ip, #PLLDIV_EN
88         str     ip, [r3, #PLLDIV1]
89
90         /* Put the DDR PLL in bypass and power down */
91         ldr     ip, [r3, #PLLCTL]
92         bic     ip, ip, #PLLCTL_PLLENSRC
93         bic     ip, ip, #PLLCTL_PLLEN
94         str     ip, [r3, #PLLCTL]
95
96         /* Wait for PLL to switch to bypass */
97        mov      ip, #PLL_BYPASS_CYCLES
98 2:     subs     ip, ip, #0x1
99        bne      2b
100
101        /* Power down the PLL */
102         ldr     ip, [r3, #PLLCTL]
103         orr     ip, ip, #PLLCTL_PLLPWRDN
104         str     ip, [r3, #PLLCTL]
105
106         /* Go to deep sleep */
107         ldr     ip, [r4]
108         orr     ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
109         /* System goes to sleep beyond after this instruction */
110         str     ip, [r4]
111
112         /* Wake up from sleep */
113
114         /* Clear sleep enable */
115         ldr     ip, [r4]
116         bic     ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
117         str     ip, [r4]
118
119         /* initialize the DDR PLL controller */
120
121         /* Put PLL in reset */
122         ldr     ip, [r3, #PLLCTL]
123         bic     ip, ip, #PLLCTL_PLLRST
124         str     ip, [r3, #PLLCTL]
125
126         /* Clear PLL power down */
127         ldr     ip, [r3, #PLLCTL]
128         bic     ip, ip, #PLLCTL_PLLPWRDN
129         str     ip, [r3, #PLLCTL]
130
131        mov      ip, #PLL_RESET_CYCLES
132 3:     subs     ip, ip, #0x1
133        bne      3b
134
135        /* Bring PLL out of reset */
136         ldr     ip, [r3, #PLLCTL]
137         orr     ip, ip, #PLLCTL_PLLRST
138         str     ip, [r3, #PLLCTL]
139
140         /* Wait for PLL to lock (assume prediv = 1, 25MHz OSCIN) */
141        mov      ip, #PLL_LOCK_CYCLES
142 4:     subs     ip, ip, #0x1
143        bne      4b
144
145        /* Remove PLL from bypass mode */
146         ldr     ip, [r3, #PLLCTL]
147         bic     ip, ip, #PLLCTL_PLLENSRC
148         orr     ip, ip, #PLLCTL_PLLEN
149         str     ip, [r3, #PLLCTL]
150
151         /* Start 2x clock to DDR2 */
152
153         ldr     ip, [r3, #PLLDIV1]
154         orr     ip, ip, #PLLDIV_EN
155         str     ip, [r3, #PLLDIV1]
156
157         /* Enable VCLK */
158
159        /* Enable DDR2 LPSC */
160         mov     r7, r0
161         mov     r0, #0x3
162         bl davinci_ddr_psc_config
163         mov     r0, r7
164
165         /* clear  MCLKSTOPEN */
166
167         ldr     ip, [r0, #DDR2_SDRCR_OFFSET]
168         bic     ip, ip, #DDR2_MCLKSTOPEN_BIT
169         str     ip, [r0, #DDR2_SDRCR_OFFSET]
170
171         ldr     ip, [r0, #DDR2_SDRCR_OFFSET]
172         bic     ip, ip, #DDR2_LPMODEN_BIT
173         str     ip, [r0, #DDR2_SDRCR_OFFSET]
174
175         /* Restore registers and return */
176         ldmfd   sp!, {r0-r12, pc}
177
178 ENDPROC(davinci_cpu_suspend)
179
180 /*
181  * Disables or Enables DDR2 LPSC
182  * Register Usage:
183  *      r0: Enable or Disable LPSC r0 = 0x3 => Enable, r0 = 0x2 => Disable LPSC
184  *      r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
185  *      r2: contains PSC number for DDR2
186  */
187 ENTRY(davinci_ddr_psc_config)
188         /* Set next state in mdctl for DDR2 */
189         mov     r6, #MDCTL
190         add     r6, r6, r2, lsl #2
191         ldr     ip, [r1, r6]
192         bic     ip, ip, #MDSTAT_STATE_MASK
193         orr     ip, ip, r0
194         str     ip, [r1, r6]
195
196         /* Enable the Power Domain Transition Command */
197         ldr     ip, [r1, #PTCMD]
198         orr     ip, ip, #0x1
199         str     ip, [r1, #PTCMD]
200
201         /* Check for Transition Complete (PTSTAT) */
202 ptstat_done:
203         ldr     ip, [r1, #PTSTAT]
204         and     ip, ip, #0x1
205         cmp     ip, #0x0
206         bne     ptstat_done
207
208         /* Check for DDR2 clock disable completion; */
209         mov     r6, #MDSTAT
210         add     r6, r6, r2, lsl #2
211 ddr2clk_stop_done:
212         ldr     ip, [r1, r6]
213         and     ip, ip, #MDSTAT_STATE_MASK
214         cmp     ip, r0
215         bne     ddr2clk_stop_done
216
217         ret     lr
218 ENDPROC(davinci_ddr_psc_config)
219
220 CACHE_FLUSH:
221 #ifdef CONFIG_CPU_V6
222         .word   v6_flush_kern_cache_all
223 #else
224         .word   arm926_flush_kern_cache_all
225 #endif
226
227 ENTRY(davinci_cpu_suspend_sz)
228         .word   . - davinci_cpu_suspend
229 ENDPROC(davinci_cpu_suspend_sz)