xref: /openbmc/linux/arch/sh/kernel/cpu/shmobile/sleep.S (revision 309214af)
1/*
2 * arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S
3 *
4 * Sleep mode and Standby modes support for SuperH Mobile
5 *
6 *  Copyright (C) 2009 Magnus Damm
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License.  See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12
13#include <linux/sys.h>
14#include <linux/errno.h>
15#include <linux/linkage.h>
16#include <asm/asm-offsets.h>
17#include <asm/suspend.h>
18
19/*
20 * Kernel mode register usage, see entry.S:
21 *	k0	scratch
22 *	k1	scratch
23 *	k4	scratch
24 */
25#define k0	r0
26#define k1	r1
27#define k4	r4
28
29/* manage self-refresh and enter standby mode.
30 * this code will be copied to on-chip memory and executed from there.
31 */
32
33	.balign 	4096,0,4096
34ENTRY(sh_mobile_standby)
35
36	/* save original vbr */
37	stc	vbr, r1
38	mova	saved_vbr, r0
39	mov.l	r1, @r0
40
41	/* point vbr to our on-chip memory page */
42	ldc	r5, vbr
43
44	/* save return address */
45	mova	saved_spc, r0
46	sts	pr, r5
47	mov.l	r5, @r0
48
49	/* save sr */
50	mova	saved_sr, r0
51	stc	sr, r5
52	mov.l	r5, @r0
53
54	/* save mode flags */
55	mova	saved_mode, r0
56	mov.l	r4, @r0
57
58	/* put mode flags in r0 */
59	mov	r4, r0
60
61	tst	#SUSP_SH_SF, r0
62	bt	skip_set_sf
63#ifdef CONFIG_CPU_SUBTYPE_SH7724
64	/* DBSC: put memory in self-refresh mode */
65	mov.l	dben_reg, r4
66	mov.l	dben_data0, r1
67	mov.l	r1, @r4
68
69	mov.l	dbrfpdn0_reg, r4
70	mov.l	dbrfpdn0_data0, r1
71	mov.l	r1, @r4
72
73	mov.l	dbcmdcnt_reg, r4
74	mov.l	dbcmdcnt_data0, r1
75	mov.l	r1, @r4
76
77	mov.l	dbcmdcnt_reg, r4
78	mov.l	dbcmdcnt_data1, r1
79	mov.l	r1, @r4
80
81	mov.l	dbrfpdn0_reg, r4
82	mov.l	dbrfpdn0_data1, r1
83	mov.l	r1, @r4
84#else
85	/* SBSC: disable power down and put in self-refresh mode */
86	mov.l	1f, r4
87	mov.l	2f, r1
88	mov.l	@r4, r2
89	or	r1, r2
90	mov.l   3f, r3
91	and	r3, r2
92	mov.l	r2, @r4
93#endif
94
95skip_set_sf:
96	tst	#SUSP_SH_STANDBY, r0
97	bt	test_rstandby
98
99	/* set mode to "software standby mode" */
100	bra	do_sleep
101	 mov	#0x80, r1
102
103test_rstandby:
104	tst	#SUSP_SH_RSTANDBY, r0
105	bt	test_ustandby
106
107	/* set mode to "r-standby mode" */
108	bra	do_sleep
109	 mov	#0x20, r1
110
111test_ustandby:
112	tst	#SUSP_SH_USTANDBY, r0
113	bt	force_sleep
114
115	/* set mode to "u-standby mode" */
116	bra	do_sleep
117	 mov	#0x10, r1
118
119force_sleep:
120
121	/* set mode to "sleep mode" */
122	mov	#0x00, r1
123
124do_sleep:
125	/* setup and enter selected standby mode */
126	mov.l	5f, r4
127	mov.l	r1, @r4
128again:
129	sleep
130	bra	again
131	 nop
132
133restore_jump_vbr:
134	/* setup spc with return address to c code */
135	mov.l	saved_spc, k0
136	ldc	k0, spc
137
138	/* restore vbr */
139	mov.l	saved_vbr, k0
140	ldc	k0, vbr
141
142	/* setup ssr with saved sr */
143	mov.l	saved_sr, k0
144	ldc	k0, ssr
145
146	/* get mode flags */
147	mov.l	saved_mode, k0
148
149done_sleep:
150	/* reset standby mode to sleep mode */
151	mov.l	5f, k4
152	mov	#0x00, k1
153	mov.l	k1, @k4
154
155	tst	#SUSP_SH_SF, k0
156	bt	skip_restore_sf
157
158#ifdef CONFIG_CPU_SUBTYPE_SH7724
159	/* DBSC: put memory in auto-refresh mode */
160	mov.l	dbrfpdn0_reg, k4
161	mov.l	dbrfpdn0_data0, k1
162	mov.l	k1, @k4
163
164	nop /* sleep 140 ns */
165	nop
166	nop
167	nop
168
169	mov.l	dbcmdcnt_reg, k4
170	mov.l	dbcmdcnt_data0, k1
171	mov.l	k1, @k4
172
173	mov.l	dbcmdcnt_reg, k4
174	mov.l	dbcmdcnt_data1, k1
175	mov.l	k1, @k4
176
177	mov.l	dben_reg, k4
178	mov.l	dben_data1, k1
179	mov.l	k1, @k4
180
181	mov.l	dbrfpdn0_reg, k4
182	mov.l	dbrfpdn0_data2, k1
183	mov.l	k1, @k4
184#else
185	/* SBSC: set auto-refresh mode */
186	mov.l	1f, k4
187	mov.l	@k4, k0
188	mov.l   4f, k1
189	and	k1, k0
190	mov.l	k0, @k4
191	mov.l	6f, k4
192	mov.l	8f, k0
193	mov.l	@k4, k1
194	mov	#-1, k4
195	add	k4, k1
196	or	k1, k0
197	mov.l	7f, k1
198	mov.l	k0, @k1
199#endif
200skip_restore_sf:
201	/* jump to vbr vector */
202	mov.l	saved_vbr, k0
203	mov.l	offset_vbr, k4
204	add	k4, k0
205	jmp	@k0
206	 nop
207
208	.balign 4
209saved_mode:	.long	0
210saved_spc:	.long	0
211saved_sr:	.long	0
212saved_vbr:	.long	0
213offset_vbr:	.long	0x600
214#ifdef CONFIG_CPU_SUBTYPE_SH7724
215dben_reg:	.long	0xfd000010 /* DBEN */
216dben_data0:	.long	0
217dben_data1:	.long	1
218dbrfpdn0_reg:	.long	0xfd000040 /* DBRFPDN0 */
219dbrfpdn0_data0:	.long	0
220dbrfpdn0_data1:	.long	1
221dbrfpdn0_data2:	.long	0x00010000
222dbcmdcnt_reg:	.long	0xfd000014 /* DBCMDCNT */
223dbcmdcnt_data0:	.long	2
224dbcmdcnt_data1:	.long	4
225#else
2261:	.long	0xfe400008 /* SDCR0 */
2272:	.long	0x00000400
2283:	.long	0xffff7fff
2294:	.long	0xfffffbff
230#endif
2315:	.long	0xa4150020 /* STBCR */
2326:	.long   0xfe40001c /* RTCOR */
2337:	.long   0xfe400018 /* RTCNT */
2348:	.long   0xa55a0000
235
236
237/* interrupt vector @ 0x600 */
238	.balign 	0x400,0,0x400
239	.long	0xdeadbeef
240	.balign 	0x200,0,0x200
241	bra	restore_jump_vbr
242	 nop
243sh_mobile_standby_end:
244
245ENTRY(sh_mobile_standby_size)
246	.long sh_mobile_standby_end - sh_mobile_standby
247