Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/arm/mach-omap1/sleep.S
26292 views
1
/*
2
* linux/arch/arm/mach-omap1/sleep.S
3
*
4
* Low-level OMAP7XX/1510/1610 sleep/wakeUp support
5
*
6
* Initial SA1110 code:
7
* Copyright (c) 2001 Cliff Brake <[email protected]>
8
*
9
* Adapted for PXA by Nicolas Pitre:
10
* Copyright (c) 2002 Monta Vista Software, Inc.
11
*
12
* Support for OMAP1510/1610 by Dirk Behme <[email protected]>
13
*
14
* This program is free software; you can redistribute it and/or modify it
15
* under the terms of the GNU General Public License as published by the
16
* Free Software Foundation; either version 2 of the License, or (at your
17
* option) any later version.
18
*
19
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
20
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
22
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
*
30
* You should have received a copy of the GNU General Public License along
31
* with this program; if not, write to the Free Software Foundation, Inc.,
32
* 675 Mass Ave, Cambridge, MA 02139, USA.
33
*/
34
35
#include <linux/linkage.h>
36
37
#include <asm/assembler.h>
38
39
#include "hardware.h"
40
41
#include "iomap.h"
42
#include "pm.h"
43
44
.text
45
46
47
/*
48
* Forces OMAP into deep sleep state
49
*
50
* omapXXXX_cpu_suspend()
51
*
52
* The values of the registers ARM_IDLECT1 and ARM_IDLECT2 are passed
53
* as arg0 and arg1 from caller. arg0 is stored in register r0 and arg1
54
* in register r1.
55
*
56
* Note: This code get's copied to internal SRAM at boot. When the OMAP
57
* wakes up it continues execution at the point it went to sleep.
58
*
59
* Note: Because of errata work arounds we have processor specific functions
60
* here. They are mostly the same, but slightly different.
61
*
62
*/
63
64
#ifdef CONFIG_ARCH_OMAP15XX
65
.align 3
66
ENTRY(omap1510_cpu_suspend)
67
68
@ save registers on stack
69
stmfd sp!, {r0 - r12, lr}
70
71
@ load base address of Traffic Controller
72
mov r4, #TCMIF_ASM_BASE & 0xff000000
73
orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000
74
orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00
75
76
@ work around errata of OMAP1510 PDE bit for TC shut down
77
@ clear PDE bit
78
ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
79
bic r5, r5, #PDE_BIT & 0xff
80
str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
81
82
@ set PWD_EN bit
83
and r5, r5, #PWD_EN_BIT & 0xff
84
str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
85
86
@ prepare to put SDRAM into self-refresh manually
87
ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
88
orr r5, r5, #SELF_REFRESH_MODE & 0xff000000
89
orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff
90
str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
91
92
@ prepare to put EMIFS to Sleep
93
ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
94
orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff
95
str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
96
97
@ load base address of ARM_IDLECT1 and ARM_IDLECT2
98
mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
99
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
100
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
101
102
@ turn off clock domains
103
mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
104
orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
105
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
106
107
@ request ARM idle
108
mov r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff
109
orr r3, r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff00
110
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
111
112
mov r5, #IDLE_WAIT_CYCLES & 0xff
113
orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
114
l_1510_2:
115
subs r5, r5, #1
116
bne l_1510_2
117
/*
118
* Let's wait for the next wake up event to wake us up. r0 can't be
119
* used here because r0 holds ARM_IDLECT1
120
*/
121
mov r2, #0
122
mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt
123
/*
124
* omap1510_cpu_suspend()'s resume point.
125
*
126
* It will just start executing here, so we'll restore stuff from the
127
* stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
128
*/
129
strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
130
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
131
132
@ restore regs and return
133
ldmfd sp!, {r0 - r12, pc}
134
135
ENTRY(omap1510_cpu_suspend_sz)
136
.word . - omap1510_cpu_suspend
137
#endif /* CONFIG_ARCH_OMAP15XX */
138
139
#if defined(CONFIG_ARCH_OMAP16XX)
140
.align 3
141
ENTRY(omap1610_cpu_suspend)
142
143
@ save registers on stack
144
stmfd sp!, {r0 - r12, lr}
145
146
@ Drain write cache
147
mov r4, #0
148
mcr p15, 0, r0, c7, c10, 4
149
nop
150
151
@ Load base address of Traffic Controller
152
mov r6, #TCMIF_ASM_BASE & 0xff000000
153
orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
154
orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00
155
156
@ Prepare to put SDRAM into self-refresh manually
157
ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
158
orr r9, r7, #SELF_REFRESH_MODE & 0xff000000
159
orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff
160
str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
161
162
@ Prepare to put EMIFS to Sleep
163
ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
164
orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff
165
str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
166
167
@ Load base address of ARM_IDLECT1 and ARM_IDLECT2
168
mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
169
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
170
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
171
172
@ Turn off clock domains
173
@ Do not disable PERCK (0x04)
174
mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
175
orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
176
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
177
178
@ Request ARM idle
179
mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
180
orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00
181
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
182
183
/*
184
* Let's wait for the next wake up event to wake us up. r0 can't be
185
* used here because r0 holds ARM_IDLECT1
186
*/
187
mov r2, #0
188
mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt
189
190
@ Errata (HEL3SU467, section 1.4.4) specifies nop-instructions
191
@ according to this formula:
192
@ 2 + (4*DPLL_MULT)/DPLL_DIV/ARMDIV
193
@ Max DPLL_MULT = 18
194
@ DPLL_DIV = 1
195
@ ARMDIV = 1
196
@ => 74 nop-instructions
197
nop
198
nop
199
nop
200
nop
201
nop
202
nop
203
nop
204
nop
205
nop
206
nop @10
207
nop
208
nop
209
nop
210
nop
211
nop
212
nop
213
nop
214
nop
215
nop
216
nop @20
217
nop
218
nop
219
nop
220
nop
221
nop
222
nop
223
nop
224
nop
225
nop
226
nop @30
227
nop
228
nop
229
nop
230
nop
231
nop
232
nop
233
nop
234
nop
235
nop
236
nop @40
237
nop
238
nop
239
nop
240
nop
241
nop
242
nop
243
nop
244
nop
245
nop
246
nop @50
247
nop
248
nop
249
nop
250
nop
251
nop
252
nop
253
nop
254
nop
255
nop
256
nop @60
257
nop
258
nop
259
nop
260
nop
261
nop
262
nop
263
nop
264
nop
265
nop
266
nop @70
267
nop
268
nop
269
nop
270
nop @74
271
/*
272
* omap1610_cpu_suspend()'s resume point.
273
*
274
* It will just start executing here, so we'll restore stuff from the
275
* stack.
276
*/
277
@ Restore the ARM_IDLECT1 and ARM_IDLECT2.
278
strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
279
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
280
281
@ Restore EMIFF controls
282
str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
283
str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
284
285
@ Restore regs and return
286
ldmfd sp!, {r0 - r12, pc}
287
288
ENTRY(omap1610_cpu_suspend_sz)
289
.word . - omap1610_cpu_suspend
290
#endif /* CONFIG_ARCH_OMAP16XX */
291
292