xref: /openbmc/linux/arch/arm/mach-omap1/sleep.S (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1670c104aSTony Lindgren/*
2670c104aSTony Lindgren * linux/arch/arm/mach-omap1/sleep.S
3670c104aSTony Lindgren *
47c006926SAlistair Buxton * Low-level OMAP7XX/1510/1610 sleep/wakeUp support
5670c104aSTony Lindgren *
6670c104aSTony Lindgren * Initial SA1110 code:
7670c104aSTony Lindgren * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
8670c104aSTony Lindgren *
9670c104aSTony Lindgren * Adapted for PXA by Nicolas Pitre:
10670c104aSTony Lindgren * Copyright (c) 2002 Monta Vista Software, Inc.
11670c104aSTony Lindgren *
12670c104aSTony Lindgren * Support for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com>
13670c104aSTony Lindgren *
14670c104aSTony Lindgren * This program is free software; you can redistribute it and/or modify it
15670c104aSTony Lindgren * under the terms of the GNU General Public License as published by the
16670c104aSTony Lindgren * Free Software Foundation; either version 2 of the License, or (at your
17670c104aSTony Lindgren * option) any later version.
18670c104aSTony Lindgren *
19670c104aSTony Lindgren * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
20670c104aSTony Lindgren * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21670c104aSTony Lindgren * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
22670c104aSTony Lindgren * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23670c104aSTony Lindgren * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24670c104aSTony Lindgren * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25670c104aSTony Lindgren * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26670c104aSTony Lindgren * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27670c104aSTony Lindgren * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28670c104aSTony Lindgren * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29670c104aSTony Lindgren *
30670c104aSTony Lindgren * You should have received a copy of the GNU General Public License along
31670c104aSTony Lindgren * with this program; if not, write to the Free Software Foundation, Inc.,
32670c104aSTony Lindgren * 675 Mass Ave, Cambridge, MA 02139, USA.
33670c104aSTony Lindgren */
34670c104aSTony Lindgren
35670c104aSTony Lindgren#include <linux/linkage.h>
362e3ee9f4STony Lindgren
37670c104aSTony Lindgren#include <asm/assembler.h>
382e3ee9f4STony Lindgren
39*7e0a9e62SArnd Bergmann#include "hardware.h"
404e969010STony Lindgren
412e3ee9f4STony Lindgren#include "iomap.h"
42c912f7e1SKevin Hilman#include "pm.h"
43670c104aSTony Lindgren
44670c104aSTony Lindgren		.text
45670c104aSTony Lindgren
46670c104aSTony Lindgren
47670c104aSTony Lindgren/*
48670c104aSTony Lindgren * Forces OMAP into deep sleep state
49670c104aSTony Lindgren *
50670c104aSTony Lindgren * omapXXXX_cpu_suspend()
51670c104aSTony Lindgren *
52670c104aSTony Lindgren * The values of the registers ARM_IDLECT1 and ARM_IDLECT2 are passed
53670c104aSTony Lindgren * as arg0 and arg1 from caller. arg0 is stored in register r0 and arg1
54670c104aSTony Lindgren * in register r1.
55670c104aSTony Lindgren *
56670c104aSTony Lindgren * Note: This code get's copied to internal SRAM at boot. When the OMAP
57670c104aSTony Lindgren *	 wakes up it continues execution at the point it went to sleep.
58670c104aSTony Lindgren *
59670c104aSTony Lindgren * Note: Because of errata work arounds we have processor specific functions
60670c104aSTony Lindgren *       here. They are mostly the same, but slightly different.
61670c104aSTony Lindgren *
62670c104aSTony Lindgren */
63670c104aSTony Lindgren
64670c104aSTony Lindgren#ifdef CONFIG_ARCH_OMAP15XX
65b6338bdcSJean Pihet	.align	3
66670c104aSTony LindgrenENTRY(omap1510_cpu_suspend)
67670c104aSTony Lindgren
68670c104aSTony Lindgren	@ save registers on stack
69670c104aSTony Lindgren	stmfd	sp!, {r0 - r12, lr}
70670c104aSTony Lindgren
71670c104aSTony Lindgren	@ load base address of Traffic Controller
72670c104aSTony Lindgren	mov	r4, #TCMIF_ASM_BASE & 0xff000000
73670c104aSTony Lindgren	orr	r4, r4, #TCMIF_ASM_BASE & 0x00ff0000
74670c104aSTony Lindgren	orr	r4, r4, #TCMIF_ASM_BASE & 0x0000ff00
75670c104aSTony Lindgren
76670c104aSTony Lindgren	@ work around errata of OMAP1510 PDE bit for TC shut down
77670c104aSTony Lindgren	@ clear PDE bit
78670c104aSTony Lindgren	ldr	r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
79670c104aSTony Lindgren	bic	r5, r5, #PDE_BIT & 0xff
80670c104aSTony Lindgren	str	r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
81670c104aSTony Lindgren
82670c104aSTony Lindgren	@ set PWD_EN bit
83670c104aSTony Lindgren	and	r5, r5, #PWD_EN_BIT & 0xff
84670c104aSTony Lindgren	str	r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
85670c104aSTony Lindgren
86670c104aSTony Lindgren	@ prepare to put SDRAM into self-refresh manually
87670c104aSTony Lindgren	ldr	r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
88670c104aSTony Lindgren	orr	r5, r5, #SELF_REFRESH_MODE & 0xff000000
89670c104aSTony Lindgren	orr	r5, r5, #SELF_REFRESH_MODE & 0x000000ff
90670c104aSTony Lindgren	str	r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
91670c104aSTony Lindgren
92670c104aSTony Lindgren	@ prepare to put EMIFS to Sleep
93670c104aSTony Lindgren	ldr	r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
94670c104aSTony Lindgren	orr	r5, r5, #IDLE_EMIFS_REQUEST & 0xff
95670c104aSTony Lindgren	str	r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
96670c104aSTony Lindgren
97670c104aSTony Lindgren	@ load base address of ARM_IDLECT1 and ARM_IDLECT2
98670c104aSTony Lindgren	mov	r4, #CLKGEN_REG_ASM_BASE & 0xff000000
99670c104aSTony Lindgren	orr	r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
100670c104aSTony Lindgren	orr	r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
101670c104aSTony Lindgren
102670c104aSTony Lindgren	@ turn off clock domains
103670c104aSTony Lindgren	mov	r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
104670c104aSTony Lindgren	orr	r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
105670c104aSTony Lindgren	strh	r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
106670c104aSTony Lindgren
107670c104aSTony Lindgren	@ request ARM idle
108670c104aSTony Lindgren	mov	r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff
109670c104aSTony Lindgren	orr	r3, r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff00
110670c104aSTony Lindgren	strh	r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
111670c104aSTony Lindgren
112670c104aSTony Lindgren	mov	r5, #IDLE_WAIT_CYCLES & 0xff
113670c104aSTony Lindgren	orr	r5, r5, #IDLE_WAIT_CYCLES & 0xff00
114670c104aSTony Lindgrenl_1510_2:
115670c104aSTony Lindgren	subs	r5, r5, #1
116670c104aSTony Lindgren	bne	l_1510_2
117670c104aSTony Lindgren/*
118670c104aSTony Lindgren * Let's wait for the next wake up event to wake us up. r0 can't be
119670c104aSTony Lindgren * used here because r0 holds ARM_IDLECT1
120670c104aSTony Lindgren */
121670c104aSTony Lindgren	mov	r2, #0
122670c104aSTony Lindgren	mcr	p15, 0, r2, c7, c0, 4		@ wait for interrupt
123670c104aSTony Lindgren/*
124670c104aSTony Lindgren * omap1510_cpu_suspend()'s resume point.
125670c104aSTony Lindgren *
126670c104aSTony Lindgren * It will just start executing here, so we'll restore stuff from the
127670c104aSTony Lindgren * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
128670c104aSTony Lindgren */
129670c104aSTony Lindgren	strh	r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
130670c104aSTony Lindgren	strh	r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
131670c104aSTony Lindgren
132670c104aSTony Lindgren	@ restore regs and return
133670c104aSTony Lindgren	ldmfd	sp!, {r0 - r12, pc}
134670c104aSTony Lindgren
135670c104aSTony LindgrenENTRY(omap1510_cpu_suspend_sz)
136670c104aSTony Lindgren	.word	. - omap1510_cpu_suspend
137670c104aSTony Lindgren#endif /* CONFIG_ARCH_OMAP15XX */
138670c104aSTony Lindgren
139670c104aSTony Lindgren#if defined(CONFIG_ARCH_OMAP16XX)
140b6338bdcSJean Pihet	.align	3
141670c104aSTony LindgrenENTRY(omap1610_cpu_suspend)
142670c104aSTony Lindgren
143670c104aSTony Lindgren	@ save registers on stack
144670c104aSTony Lindgren	stmfd	sp!, {r0 - r12, lr}
145670c104aSTony Lindgren
146670c104aSTony Lindgren	@ Drain write cache
147670c104aSTony Lindgren	mov	r4, #0
148670c104aSTony Lindgren	mcr	p15, 0, r0, c7, c10, 4
149670c104aSTony Lindgren	nop
150670c104aSTony Lindgren
151670c104aSTony Lindgren	@ Load base address of Traffic Controller
152670c104aSTony Lindgren	mov	r6, #TCMIF_ASM_BASE & 0xff000000
153670c104aSTony Lindgren	orr	r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
154670c104aSTony Lindgren	orr	r6, r6, #TCMIF_ASM_BASE & 0x0000ff00
155670c104aSTony Lindgren
156670c104aSTony Lindgren	@ Prepare to put SDRAM into self-refresh manually
157670c104aSTony Lindgren	ldr	r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
158670c104aSTony Lindgren	orr	r9, r7, #SELF_REFRESH_MODE & 0xff000000
159670c104aSTony Lindgren	orr	r9, r9, #SELF_REFRESH_MODE & 0x000000ff
160670c104aSTony Lindgren	str	r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
161670c104aSTony Lindgren
162670c104aSTony Lindgren	@ Prepare to put EMIFS to Sleep
163670c104aSTony Lindgren	ldr	r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
164670c104aSTony Lindgren	orr	r9, r8, #IDLE_EMIFS_REQUEST & 0xff
165670c104aSTony Lindgren	str	r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
166670c104aSTony Lindgren
167670c104aSTony Lindgren	@ Load base address of ARM_IDLECT1 and ARM_IDLECT2
168670c104aSTony Lindgren	mov	r4, #CLKGEN_REG_ASM_BASE & 0xff000000
169670c104aSTony Lindgren	orr	r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
170670c104aSTony Lindgren	orr	r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
171670c104aSTony Lindgren
172670c104aSTony Lindgren	@ Turn off clock domains
173670c104aSTony Lindgren	@ Do not disable PERCK (0x04)
174670c104aSTony Lindgren	mov	r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
175670c104aSTony Lindgren	orr	r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
176670c104aSTony Lindgren	strh	r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
177670c104aSTony Lindgren
178670c104aSTony Lindgren	@ Request ARM idle
179670c104aSTony Lindgren	mov	r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
180670c104aSTony Lindgren	orr	r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00
181670c104aSTony Lindgren	strh	r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
182670c104aSTony Lindgren
183670c104aSTony Lindgren/*
184670c104aSTony Lindgren * Let's wait for the next wake up event to wake us up. r0 can't be
185670c104aSTony Lindgren * used here because r0 holds ARM_IDLECT1
186670c104aSTony Lindgren */
187670c104aSTony Lindgren	mov	r2, #0
188670c104aSTony Lindgren	mcr	p15, 0, r2, c7, c0, 4		@ wait for interrupt
189670c104aSTony Lindgren
190670c104aSTony Lindgren	@ Errata (HEL3SU467, section 1.4.4) specifies nop-instructions
191670c104aSTony Lindgren	@ according to this formula:
192670c104aSTony Lindgren	@ 2 + (4*DPLL_MULT)/DPLL_DIV/ARMDIV
193670c104aSTony Lindgren	@ Max DPLL_MULT = 18
194670c104aSTony Lindgren	@ DPLL_DIV = 1
195670c104aSTony Lindgren	@ ARMDIV = 1
196670c104aSTony Lindgren	@ => 74 nop-instructions
197670c104aSTony Lindgren	nop
198670c104aSTony Lindgren	nop
199670c104aSTony Lindgren	nop
200670c104aSTony Lindgren	nop
201670c104aSTony Lindgren	nop
202670c104aSTony Lindgren	nop
203670c104aSTony Lindgren	nop
204670c104aSTony Lindgren	nop
205670c104aSTony Lindgren	nop
206670c104aSTony Lindgren	nop	@10
207670c104aSTony Lindgren	nop
208670c104aSTony Lindgren	nop
209670c104aSTony Lindgren	nop
210670c104aSTony Lindgren	nop
211670c104aSTony Lindgren	nop
212670c104aSTony Lindgren	nop
213670c104aSTony Lindgren	nop
214670c104aSTony Lindgren	nop
215670c104aSTony Lindgren	nop
216670c104aSTony Lindgren	nop	@20
217670c104aSTony Lindgren	nop
218670c104aSTony Lindgren	nop
219670c104aSTony Lindgren	nop
220670c104aSTony Lindgren	nop
221670c104aSTony Lindgren	nop
222670c104aSTony Lindgren	nop
223670c104aSTony Lindgren	nop
224670c104aSTony Lindgren	nop
225670c104aSTony Lindgren	nop
226670c104aSTony Lindgren	nop	@30
227670c104aSTony Lindgren	nop
228670c104aSTony Lindgren	nop
229670c104aSTony Lindgren	nop
230670c104aSTony Lindgren	nop
231670c104aSTony Lindgren	nop
232670c104aSTony Lindgren	nop
233670c104aSTony Lindgren	nop
234670c104aSTony Lindgren	nop
235670c104aSTony Lindgren	nop
236670c104aSTony Lindgren	nop	@40
237670c104aSTony Lindgren	nop
238670c104aSTony Lindgren	nop
239670c104aSTony Lindgren	nop
240670c104aSTony Lindgren	nop
241670c104aSTony Lindgren	nop
242670c104aSTony Lindgren	nop
243670c104aSTony Lindgren	nop
244670c104aSTony Lindgren	nop
245670c104aSTony Lindgren	nop
246670c104aSTony Lindgren	nop	@50
247670c104aSTony Lindgren	nop
248670c104aSTony Lindgren	nop
249670c104aSTony Lindgren	nop
250670c104aSTony Lindgren	nop
251670c104aSTony Lindgren	nop
252670c104aSTony Lindgren	nop
253670c104aSTony Lindgren	nop
254670c104aSTony Lindgren	nop
255670c104aSTony Lindgren	nop
256670c104aSTony Lindgren	nop	@60
257670c104aSTony Lindgren	nop
258670c104aSTony Lindgren	nop
259670c104aSTony Lindgren	nop
260670c104aSTony Lindgren	nop
261670c104aSTony Lindgren	nop
262670c104aSTony Lindgren	nop
263670c104aSTony Lindgren	nop
264670c104aSTony Lindgren	nop
265670c104aSTony Lindgren	nop
266670c104aSTony Lindgren	nop	@70
267670c104aSTony Lindgren	nop
268670c104aSTony Lindgren	nop
269670c104aSTony Lindgren	nop
270670c104aSTony Lindgren	nop	@74
271670c104aSTony Lindgren/*
272670c104aSTony Lindgren * omap1610_cpu_suspend()'s resume point.
273670c104aSTony Lindgren *
274670c104aSTony Lindgren * It will just start executing here, so we'll restore stuff from the
275670c104aSTony Lindgren * stack.
276670c104aSTony Lindgren */
277670c104aSTony Lindgren	@ Restore the ARM_IDLECT1 and ARM_IDLECT2.
278670c104aSTony Lindgren	strh	r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
279670c104aSTony Lindgren	strh	r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
280670c104aSTony Lindgren
281670c104aSTony Lindgren	@ Restore EMIFF controls
282670c104aSTony Lindgren	str	r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
283670c104aSTony Lindgren	str	r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
284670c104aSTony Lindgren
285670c104aSTony Lindgren	@ Restore regs and return
286670c104aSTony Lindgren	ldmfd	sp!, {r0 - r12, pc}
287670c104aSTony Lindgren
288670c104aSTony LindgrenENTRY(omap1610_cpu_suspend_sz)
289670c104aSTony Lindgren	.word	. - omap1610_cpu_suspend
290670c104aSTony Lindgren#endif /* CONFIG_ARCH_OMAP16XX */
291