1/*
2 * Copyright 2002 Embedded Edge, LLC
3 * Author: dan@embeddededge.com
4 *
5 * Sleep helper for Au1xxx sleep mode.
6 *
7 * This program is free software; you can redistribute	it and/or modify it
8 * under  the terms of	the GNU General	 Public License as published by the
9 * Free Software Foundation;  either version 2 of the  License, or (at your
10 * option) any later version.
11 */
12
13#include <asm/asm.h>
14#include <asm/mipsregs.h>
15#include <asm/regdef.h>
16#include <asm/stackframe.h>
17
18	.extern __flush_cache_all
19
20	.text
21	.set noreorder
22	.set noat
23	.align	5
24
25
26/* preparatory stuff */
27.macro	SETUP_SLEEP
28	subu	sp, PT_SIZE
29	sw	$1, PT_R1(sp)
30	sw	$2, PT_R2(sp)
31	sw	$3, PT_R3(sp)
32	sw	$4, PT_R4(sp)
33	sw	$5, PT_R5(sp)
34	sw	$6, PT_R6(sp)
35	sw	$7, PT_R7(sp)
36	sw	$16, PT_R16(sp)
37	sw	$17, PT_R17(sp)
38	sw	$18, PT_R18(sp)
39	sw	$19, PT_R19(sp)
40	sw	$20, PT_R20(sp)
41	sw	$21, PT_R21(sp)
42	sw	$22, PT_R22(sp)
43	sw	$23, PT_R23(sp)
44	sw	$26, PT_R26(sp)
45	sw	$27, PT_R27(sp)
46	sw	$28, PT_R28(sp)
47	sw	$30, PT_R30(sp)
48	sw	$31, PT_R31(sp)
49	mfc0	k0, CP0_STATUS
50	sw	k0, 0x20(sp)
51	mfc0	k0, CP0_CONTEXT
52	sw	k0, 0x1c(sp)
53	mfc0	k0, CP0_PAGEMASK
54	sw	k0, 0x18(sp)
55	mfc0	k0, CP0_CONFIG
56	sw	k0, 0x14(sp)
57
58	/* flush caches to make sure context is in memory */
59	la	t1, __flush_cache_all
60	lw	t0, 0(t1)
61	jalr	t0
62	 nop
63
64	/* Now set up the scratch registers so the boot rom will
65	 * return to this point upon wakeup.
66	 * sys_scratch0 : SP
67	 * sys_scratch1 : RA
68	 */
69	lui	t3, 0xb190		/* sys_xxx */
70	sw	sp, 0x0018(t3)
71	la	k0, alchemy_sleep_wakeup	/* resume path */
72	sw	k0, 0x001c(t3)
73.endm
74
75.macro	DO_SLEEP
76	/* put power supply and processor to sleep */
77	sw	zero, 0x0078(t3)	/* sys_slppwr */
78	sync
79	sw	zero, 0x007c(t3)	/* sys_sleep */
80	sync
81	nop
82	nop
83	nop
84	nop
85	nop
86	nop
87	nop
88	nop
89.endm
90
91/* sleep code for Au1000/Au1100/Au1500 memory controller type */
92LEAF(alchemy_sleep_au1000)
93
94	SETUP_SLEEP
95
96	/* cache following instructions, as memory gets put to sleep */
97	la	t0, 1f
98	.set	arch=r4000
99	cache	0x14, 0(t0)
100	cache	0x14, 32(t0)
101	cache	0x14, 64(t0)
102	cache	0x14, 96(t0)
103	.set	mips0
104
1051:	lui	a0, 0xb400		/* mem_xxx */
106	sw	zero, 0x001c(a0)	/* Precharge */
107	sync
108	sw	zero, 0x0020(a0)	/* Auto Refresh */
109	sync
110	sw	zero, 0x0030(a0)	/* Sleep */
111	sync
112
113	DO_SLEEP
114
115END(alchemy_sleep_au1000)
116
117/* sleep code for Au1550/Au1200 memory controller type */
118LEAF(alchemy_sleep_au1550)
119
120	SETUP_SLEEP
121
122	/* cache following instructions, as memory gets put to sleep */
123	la	t0, 1f
124	.set	arch=r4000
125	cache	0x14, 0(t0)
126	cache	0x14, 32(t0)
127	cache	0x14, 64(t0)
128	cache	0x14, 96(t0)
129	.set	mips0
130
1311:	lui	a0, 0xb400		/* mem_xxx */
132	sw	zero, 0x08c0(a0)	/* Precharge */
133	sync
134	sw	zero, 0x08d0(a0)	/* Self Refresh */
135	sync
136
137	/* wait for sdram to enter self-refresh mode */
138	lui	t0, 0x0100
1392:	lw	t1, 0x0850(a0)		/* mem_sdstat */
140	and	t2, t1, t0
141	beq	t2, zero, 2b
142	 nop
143
144	/* disable SDRAM clocks */
145	lui	t0, 0xcfff
146	ori	t0, t0, 0xffff
147	lw	t1, 0x0840(a0)		/* mem_sdconfiga */
148	and	t1, t0, t1		/* clear CE[1:0] */
149	sw	t1, 0x0840(a0)		/* mem_sdconfiga */
150	sync
151
152	DO_SLEEP
153
154END(alchemy_sleep_au1550)
155
156/* sleepcode for Au1300 memory controller type */
157LEAF(alchemy_sleep_au1300)
158
159	SETUP_SLEEP
160
161	/* cache following instructions, as memory gets put to sleep */
162	la	t0, 2f
163	la	t1, 4f
164	subu	t2, t1, t0
165
166	.set	arch=r4000
167
1681:	cache	0x14, 0(t0)
169	subu	t2, t2, 32
170	bgez	t2, 1b
171	 addu	t0, t0, 32
172
173	.set	mips0
174
1752:	lui	a0, 0xb400		/* mem_xxx */
176
177	/* disable all ports in mem_sdportcfga */
178	sw	zero, 0x868(a0)		/* mem_sdportcfga */
179	sync
180
181	/* disable ODT */
182	li	t0, 0x03010000
183	sw	t0, 0x08d8(a0)		/* mem_sdcmd0 */
184	sw	t0, 0x08dc(a0)		/* mem_sdcmd1 */
185	sync
186
187	/* precharge */
188	li	t0, 0x23000400
189	sw	t0, 0x08dc(a0)		/* mem_sdcmd1 */
190	sw	t0, 0x08d8(a0)		/* mem_sdcmd0 */
191	sync
192
193	/* auto refresh */
194	sw	zero, 0x08c8(a0)	/* mem_sdautoref */
195	sync
196
197	/* block access to the DDR */
198	lw	t0, 0x0848(a0)		/* mem_sdconfigb */
199	li	t1, (1 << 7 | 0x3F)
200	or	t0, t0, t1
201	sw	t0, 0x0848(a0)		/* mem_sdconfigb */
202	sync
203
204	/* issue the Self Refresh command */
205	li	t0, 0x10000000
206	sw	t0, 0x08dc(a0)		/* mem_sdcmd1 */
207	sw	t0, 0x08d8(a0)		/* mem_sdcmd0 */
208	sync
209
210	/* wait for sdram to enter self-refresh mode */
211	lui	t0, 0x0300
2123:	lw	t1, 0x0850(a0)		/* mem_sdstat */
213	and	t2, t1, t0
214	bne	t2, t0, 3b
215	 nop
216
217	/* disable SDRAM clocks */
218	li	t0, ~(3<<28)
219	lw	t1, 0x0840(a0)		/* mem_sdconfiga */
220	and	t1, t1, t0		/* clear CE[1:0] */
221	sw	t1, 0x0840(a0)		/* mem_sdconfiga */
222	sync
223
224	DO_SLEEP
2254:
226
227END(alchemy_sleep_au1300)
228
229
230	/* This is where we return upon wakeup.
231	 * Reload all of the registers and return.
232	 */
233LEAF(alchemy_sleep_wakeup)
234	lw	k0, 0x20(sp)
235	mtc0	k0, CP0_STATUS
236	lw	k0, 0x1c(sp)
237	mtc0	k0, CP0_CONTEXT
238	lw	k0, 0x18(sp)
239	mtc0	k0, CP0_PAGEMASK
240	lw	k0, 0x14(sp)
241	mtc0	k0, CP0_CONFIG
242
243	/* We need to catch the early Alchemy SOCs with
244	 * the write-only Config[OD] bit and set it back to one...
245	 */
246	jal	au1x00_fixup_config_od
247	 nop
248	lw	$1, PT_R1(sp)
249	lw	$2, PT_R2(sp)
250	lw	$3, PT_R3(sp)
251	lw	$4, PT_R4(sp)
252	lw	$5, PT_R5(sp)
253	lw	$6, PT_R6(sp)
254	lw	$7, PT_R7(sp)
255	lw	$16, PT_R16(sp)
256	lw	$17, PT_R17(sp)
257	lw	$18, PT_R18(sp)
258	lw	$19, PT_R19(sp)
259	lw	$20, PT_R20(sp)
260	lw	$21, PT_R21(sp)
261	lw	$22, PT_R22(sp)
262	lw	$23, PT_R23(sp)
263	lw	$26, PT_R26(sp)
264	lw	$27, PT_R27(sp)
265	lw	$28, PT_R28(sp)
266	lw	$30, PT_R30(sp)
267	lw	$31, PT_R31(sp)
268	jr	ra
269	 addiu	sp, PT_SIZE
270END(alchemy_sleep_wakeup)
271