Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/arm/mach-davinci/sleep.S
29269 views
1
/* SPDX-License-Identifier: GPL-2.0-only */
2
/*
3
* (C) Copyright 2009, Texas Instruments, Inc. https://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)
217
218