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