Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-davinci/sleep.S
10699 views
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/memory.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
.word arm926_flush_kern_cache_all
221
222
ENTRY(davinci_cpu_suspend_sz)
223
.word . - davinci_cpu_suspend
224
ENDPROC(davinci_cpu_suspend_sz)
225
226