xref: /openbmc/linux/arch/sh/kernel/cpu/shmobile/sleep.S (revision 309214af)
1e9edb3feSPaul Mundt/*
2e9edb3feSPaul Mundt * arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S
3e9edb3feSPaul Mundt *
4e9edb3feSPaul Mundt * Sleep mode and Standby modes support for SuperH Mobile
5e9edb3feSPaul Mundt *
6e9edb3feSPaul Mundt *  Copyright (C) 2009 Magnus Damm
7e9edb3feSPaul Mundt *
8e9edb3feSPaul Mundt * This file is subject to the terms and conditions of the GNU General Public
9e9edb3feSPaul Mundt * License.  See the file "COPYING" in the main directory of this archive
10e9edb3feSPaul Mundt * for more details.
11e9edb3feSPaul Mundt */
12e9edb3feSPaul Mundt
13e9edb3feSPaul Mundt#include <linux/sys.h>
14e9edb3feSPaul Mundt#include <linux/errno.h>
15e9edb3feSPaul Mundt#include <linux/linkage.h>
16e9edb3feSPaul Mundt#include <asm/asm-offsets.h>
17e9edb3feSPaul Mundt#include <asm/suspend.h>
18e9edb3feSPaul Mundt
19309214afSMagnus Damm/*
20309214afSMagnus Damm * Kernel mode register usage, see entry.S:
21309214afSMagnus Damm *	k0	scratch
22309214afSMagnus Damm *	k1	scratch
23309214afSMagnus Damm *	k4	scratch
24309214afSMagnus Damm */
25309214afSMagnus Damm#define k0	r0
26309214afSMagnus Damm#define k1	r1
27309214afSMagnus Damm#define k4	r4
28309214afSMagnus Damm
29e9edb3feSPaul Mundt/* manage self-refresh and enter standby mode.
30e9edb3feSPaul Mundt * this code will be copied to on-chip memory and executed from there.
31e9edb3feSPaul Mundt */
32e9edb3feSPaul Mundt
33e9edb3feSPaul Mundt	.balign 	4096,0,4096
34e9edb3feSPaul MundtENTRY(sh_mobile_standby)
35309214afSMagnus Damm
36309214afSMagnus Damm	/* save original vbr */
37309214afSMagnus Damm	stc	vbr, r1
38309214afSMagnus Damm	mova	saved_vbr, r0
39309214afSMagnus Damm	mov.l	r1, @r0
40309214afSMagnus Damm
41309214afSMagnus Damm	/* point vbr to our on-chip memory page */
42309214afSMagnus Damm	ldc	r5, vbr
43309214afSMagnus Damm
44309214afSMagnus Damm	/* save return address */
45309214afSMagnus Damm	mova	saved_spc, r0
46309214afSMagnus Damm	sts	pr, r5
47309214afSMagnus Damm	mov.l	r5, @r0
48309214afSMagnus Damm
49309214afSMagnus Damm	/* save sr */
50309214afSMagnus Damm	mova	saved_sr, r0
51309214afSMagnus Damm	stc	sr, r5
52309214afSMagnus Damm	mov.l	r5, @r0
53309214afSMagnus Damm
54309214afSMagnus Damm	/* save mode flags */
55309214afSMagnus Damm	mova	saved_mode, r0
56309214afSMagnus Damm	mov.l	r4, @r0
57309214afSMagnus Damm
58309214afSMagnus Damm	/* put mode flags in r0 */
59e9edb3feSPaul Mundt	mov	r4, r0
60e9edb3feSPaul Mundt
61e9edb3feSPaul Mundt	tst	#SUSP_SH_SF, r0
62e9edb3feSPaul Mundt	bt	skip_set_sf
63237674e0SMagnus Damm#ifdef CONFIG_CPU_SUBTYPE_SH7724
64237674e0SMagnus Damm	/* DBSC: put memory in self-refresh mode */
65237674e0SMagnus Damm	mov.l	dben_reg, r4
66237674e0SMagnus Damm	mov.l	dben_data0, r1
67237674e0SMagnus Damm	mov.l	r1, @r4
68237674e0SMagnus Damm
69237674e0SMagnus Damm	mov.l	dbrfpdn0_reg, r4
70237674e0SMagnus Damm	mov.l	dbrfpdn0_data0, r1
71237674e0SMagnus Damm	mov.l	r1, @r4
72237674e0SMagnus Damm
73237674e0SMagnus Damm	mov.l	dbcmdcnt_reg, r4
74237674e0SMagnus Damm	mov.l	dbcmdcnt_data0, r1
75237674e0SMagnus Damm	mov.l	r1, @r4
76237674e0SMagnus Damm
77237674e0SMagnus Damm	mov.l	dbcmdcnt_reg, r4
78237674e0SMagnus Damm	mov.l	dbcmdcnt_data1, r1
79237674e0SMagnus Damm	mov.l	r1, @r4
80237674e0SMagnus Damm
81237674e0SMagnus Damm	mov.l	dbrfpdn0_reg, r4
82237674e0SMagnus Damm	mov.l	dbrfpdn0_data1, r1
83237674e0SMagnus Damm	mov.l	r1, @r4
84237674e0SMagnus Damm#else
85237674e0SMagnus Damm	/* SBSC: disable power down and put in self-refresh mode */
86e9edb3feSPaul Mundt	mov.l	1f, r4
87e9edb3feSPaul Mundt	mov.l	2f, r1
88e9edb3feSPaul Mundt	mov.l	@r4, r2
89e9edb3feSPaul Mundt	or	r1, r2
90e9edb3feSPaul Mundt	mov.l   3f, r3
91e9edb3feSPaul Mundt	and	r3, r2
92e9edb3feSPaul Mundt	mov.l	r2, @r4
93237674e0SMagnus Damm#endif
94e9edb3feSPaul Mundt
95e9edb3feSPaul Mundtskip_set_sf:
96e9edb3feSPaul Mundt	tst	#SUSP_SH_STANDBY, r0
97e9edb3feSPaul Mundt	bt	test_rstandby
98e9edb3feSPaul Mundt
99e9edb3feSPaul Mundt	/* set mode to "software standby mode" */
100e9edb3feSPaul Mundt	bra	do_sleep
101e9edb3feSPaul Mundt	 mov	#0x80, r1
102e9edb3feSPaul Mundt
103e9edb3feSPaul Mundttest_rstandby:
104e9edb3feSPaul Mundt	tst	#SUSP_SH_RSTANDBY, r0
105e9edb3feSPaul Mundt	bt	test_ustandby
106e9edb3feSPaul Mundt
107e9edb3feSPaul Mundt	/* set mode to "r-standby mode" */
108e9edb3feSPaul Mundt	bra	do_sleep
109e9edb3feSPaul Mundt	 mov	#0x20, r1
110e9edb3feSPaul Mundt
111e9edb3feSPaul Mundttest_ustandby:
112e9edb3feSPaul Mundt	tst	#SUSP_SH_USTANDBY, r0
113309214afSMagnus Damm	bt	force_sleep
114e9edb3feSPaul Mundt
115e9edb3feSPaul Mundt	/* set mode to "u-standby mode" */
116309214afSMagnus Damm	bra	do_sleep
117e9edb3feSPaul Mundt	 mov	#0x10, r1
118e9edb3feSPaul Mundt
119309214afSMagnus Dammforce_sleep:
120309214afSMagnus Damm
121309214afSMagnus Damm	/* set mode to "sleep mode" */
122309214afSMagnus Damm	mov	#0x00, r1
123e9edb3feSPaul Mundt
124e9edb3feSPaul Mundtdo_sleep:
125e9edb3feSPaul Mundt	/* setup and enter selected standby mode */
126e9edb3feSPaul Mundt	mov.l	5f, r4
127e9edb3feSPaul Mundt	mov.l	r1, @r4
128309214afSMagnus Dammagain:
129e9edb3feSPaul Mundt	sleep
130309214afSMagnus Damm	bra	again
131309214afSMagnus Damm	 nop
132309214afSMagnus Damm
133309214afSMagnus Dammrestore_jump_vbr:
134309214afSMagnus Damm	/* setup spc with return address to c code */
135309214afSMagnus Damm	mov.l	saved_spc, k0
136309214afSMagnus Damm	ldc	k0, spc
137309214afSMagnus Damm
138309214afSMagnus Damm	/* restore vbr */
139309214afSMagnus Damm	mov.l	saved_vbr, k0
140309214afSMagnus Damm	ldc	k0, vbr
141309214afSMagnus Damm
142309214afSMagnus Damm	/* setup ssr with saved sr */
143309214afSMagnus Damm	mov.l	saved_sr, k0
144309214afSMagnus Damm	ldc	k0, ssr
145309214afSMagnus Damm
146309214afSMagnus Damm	/* get mode flags */
147309214afSMagnus Damm	mov.l	saved_mode, k0
148e9edb3feSPaul Mundt
149e9edb3feSPaul Mundtdone_sleep:
150e9edb3feSPaul Mundt	/* reset standby mode to sleep mode */
151309214afSMagnus Damm	mov.l	5f, k4
152309214afSMagnus Damm	mov	#0x00, k1
153309214afSMagnus Damm	mov.l	k1, @k4
154e9edb3feSPaul Mundt
155309214afSMagnus Damm	tst	#SUSP_SH_SF, k0
156e9edb3feSPaul Mundt	bt	skip_restore_sf
157e9edb3feSPaul Mundt
158237674e0SMagnus Damm#ifdef CONFIG_CPU_SUBTYPE_SH7724
159237674e0SMagnus Damm	/* DBSC: put memory in auto-refresh mode */
160309214afSMagnus Damm	mov.l	dbrfpdn0_reg, k4
161309214afSMagnus Damm	mov.l	dbrfpdn0_data0, k1
162309214afSMagnus Damm	mov.l	k1, @k4
163237674e0SMagnus Damm
164309214afSMagnus Damm	nop /* sleep 140 ns */
165237674e0SMagnus Damm	nop
166237674e0SMagnus Damm	nop
167237674e0SMagnus Damm	nop
168237674e0SMagnus Damm
169309214afSMagnus Damm	mov.l	dbcmdcnt_reg, k4
170309214afSMagnus Damm	mov.l	dbcmdcnt_data0, k1
171309214afSMagnus Damm	mov.l	k1, @k4
172237674e0SMagnus Damm
173309214afSMagnus Damm	mov.l	dbcmdcnt_reg, k4
174309214afSMagnus Damm	mov.l	dbcmdcnt_data1, k1
175309214afSMagnus Damm	mov.l	k1, @k4
176237674e0SMagnus Damm
177309214afSMagnus Damm	mov.l	dben_reg, k4
178309214afSMagnus Damm	mov.l	dben_data1, k1
179309214afSMagnus Damm	mov.l	k1, @k4
180237674e0SMagnus Damm
181309214afSMagnus Damm	mov.l	dbrfpdn0_reg, k4
182309214afSMagnus Damm	mov.l	dbrfpdn0_data2, k1
183309214afSMagnus Damm	mov.l	k1, @k4
184237674e0SMagnus Damm#else
185237674e0SMagnus Damm	/* SBSC: set auto-refresh mode */
186309214afSMagnus Damm	mov.l	1f, k4
187309214afSMagnus Damm	mov.l	@k4, k0
188309214afSMagnus Damm	mov.l   4f, k1
189309214afSMagnus Damm	and	k1, k0
190309214afSMagnus Damm	mov.l	k0, @k4
191309214afSMagnus Damm	mov.l	6f, k4
192309214afSMagnus Damm	mov.l	8f, k0
193309214afSMagnus Damm	mov.l	@k4, k1
194309214afSMagnus Damm	mov	#-1, k4
195309214afSMagnus Damm	add	k4, k1
196309214afSMagnus Damm	or	k1, k0
197309214afSMagnus Damm	mov.l	7f, k1
198309214afSMagnus Damm	mov.l	k0, @k1
199237674e0SMagnus Damm#endif
200e9edb3feSPaul Mundtskip_restore_sf:
201309214afSMagnus Damm	/* jump to vbr vector */
202309214afSMagnus Damm	mov.l	saved_vbr, k0
203309214afSMagnus Damm	mov.l	offset_vbr, k4
204309214afSMagnus Damm	add	k4, k0
205309214afSMagnus Damm	jmp	@k0
206e9edb3feSPaul Mundt	 nop
207e9edb3feSPaul Mundt
208e9edb3feSPaul Mundt	.balign 4
209309214afSMagnus Dammsaved_mode:	.long	0
210309214afSMagnus Dammsaved_spc:	.long	0
211309214afSMagnus Dammsaved_sr:	.long	0
212309214afSMagnus Dammsaved_vbr:	.long	0
213309214afSMagnus Dammoffset_vbr:	.long	0x600
214237674e0SMagnus Damm#ifdef CONFIG_CPU_SUBTYPE_SH7724
215237674e0SMagnus Dammdben_reg:	.long	0xfd000010 /* DBEN */
216237674e0SMagnus Dammdben_data0:	.long	0
217237674e0SMagnus Dammdben_data1:	.long	1
218237674e0SMagnus Dammdbrfpdn0_reg:	.long	0xfd000040 /* DBRFPDN0 */
219237674e0SMagnus Dammdbrfpdn0_data0:	.long	0
220237674e0SMagnus Dammdbrfpdn0_data1:	.long	1
221237674e0SMagnus Dammdbrfpdn0_data2:	.long	0x00010000
222237674e0SMagnus Dammdbcmdcnt_reg:	.long	0xfd000014 /* DBCMDCNT */
223237674e0SMagnus Dammdbcmdcnt_data0:	.long	2
224237674e0SMagnus Dammdbcmdcnt_data1:	.long	4
225237674e0SMagnus Damm#else
226e9edb3feSPaul Mundt1:	.long	0xfe400008 /* SDCR0 */
227e9edb3feSPaul Mundt2:	.long	0x00000400
228e9edb3feSPaul Mundt3:	.long	0xffff7fff
229e9edb3feSPaul Mundt4:	.long	0xfffffbff
230237674e0SMagnus Damm#endif
231e9edb3feSPaul Mundt5:	.long	0xa4150020 /* STBCR */
232e9edb3feSPaul Mundt6:	.long   0xfe40001c /* RTCOR */
233e9edb3feSPaul Mundt7:	.long   0xfe400018 /* RTCNT */
234e9edb3feSPaul Mundt8:	.long   0xa55a0000
235e9edb3feSPaul Mundt
236309214afSMagnus Damm
237e9edb3feSPaul Mundt/* interrupt vector @ 0x600 */
238e9edb3feSPaul Mundt	.balign 	0x400,0,0x400
239e9edb3feSPaul Mundt	.long	0xdeadbeef
240e9edb3feSPaul Mundt	.balign 	0x200,0,0x200
241309214afSMagnus Damm	bra	restore_jump_vbr
242e9edb3feSPaul Mundt	 nop
243e9edb3feSPaul Mundtsh_mobile_standby_end:
244e9edb3feSPaul Mundt
245e9edb3feSPaul MundtENTRY(sh_mobile_standby_size)
246e9edb3feSPaul Mundt	.long sh_mobile_standby_end - sh_mobile_standby
247