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