xref: /linux/arch/mips/alchemy/common/sleeper.S (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*2874c5fdSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-or-later */
2e8c7c482SRalf Baechle/*
3e8c7c482SRalf Baechle * Copyright 2002 Embedded Edge, LLC
4e8c7c482SRalf Baechle * Author: dan@embeddededge.com
5e8c7c482SRalf Baechle *
6e8c7c482SRalf Baechle * Sleep helper for Au1xxx sleep mode.
7e8c7c482SRalf Baechle */
8e8c7c482SRalf Baechle
9e8c7c482SRalf Baechle#include <asm/asm.h>
10e8c7c482SRalf Baechle#include <asm/mipsregs.h>
11e8c7c482SRalf Baechle#include <asm/regdef.h>
12e8c7c482SRalf Baechle#include <asm/stackframe.h>
13e8c7c482SRalf Baechle
14564365b0SManuel Lauss	.extern __flush_cache_all
15564365b0SManuel Lauss
16e8c7c482SRalf Baechle	.text
17564365b0SManuel Lauss	.set noreorder
18e8c7c482SRalf Baechle	.set noat
19e8c7c482SRalf Baechle	.align	5
20e8c7c482SRalf Baechle
212e93d1ecSManuel Lauss
222e93d1ecSManuel Lauss/* preparatory stuff */
232e93d1ecSManuel Lauss.macro	SETUP_SLEEP
24e8c7c482SRalf Baechle	subu	sp, PT_SIZE
25e8c7c482SRalf Baechle	sw	$1, PT_R1(sp)
26e8c7c482SRalf Baechle	sw	$2, PT_R2(sp)
27e8c7c482SRalf Baechle	sw	$3, PT_R3(sp)
28e8c7c482SRalf Baechle	sw	$4, PT_R4(sp)
29e8c7c482SRalf Baechle	sw	$5, PT_R5(sp)
30e8c7c482SRalf Baechle	sw	$6, PT_R6(sp)
31e8c7c482SRalf Baechle	sw	$7, PT_R7(sp)
32e8c7c482SRalf Baechle	sw	$16, PT_R16(sp)
33e8c7c482SRalf Baechle	sw	$17, PT_R17(sp)
34e8c7c482SRalf Baechle	sw	$18, PT_R18(sp)
35e8c7c482SRalf Baechle	sw	$19, PT_R19(sp)
36e8c7c482SRalf Baechle	sw	$20, PT_R20(sp)
37e8c7c482SRalf Baechle	sw	$21, PT_R21(sp)
38e8c7c482SRalf Baechle	sw	$22, PT_R22(sp)
39e8c7c482SRalf Baechle	sw	$23, PT_R23(sp)
40e8c7c482SRalf Baechle	sw	$26, PT_R26(sp)
41e8c7c482SRalf Baechle	sw	$27, PT_R27(sp)
42e8c7c482SRalf Baechle	sw	$28, PT_R28(sp)
43e8c7c482SRalf Baechle	sw	$30, PT_R30(sp)
44e8c7c482SRalf Baechle	sw	$31, PT_R31(sp)
45e8c7c482SRalf Baechle	mfc0	k0, CP0_STATUS
46e8c7c482SRalf Baechle	sw	k0, 0x20(sp)
47e8c7c482SRalf Baechle	mfc0	k0, CP0_CONTEXT
48e8c7c482SRalf Baechle	sw	k0, 0x1c(sp)
49e8c7c482SRalf Baechle	mfc0	k0, CP0_PAGEMASK
50e8c7c482SRalf Baechle	sw	k0, 0x18(sp)
51e8c7c482SRalf Baechle	mfc0	k0, CP0_CONFIG
52e8c7c482SRalf Baechle	sw	k0, 0x14(sp)
53e8c7c482SRalf Baechle
54564365b0SManuel Lauss	/* flush caches to make sure context is in memory */
55564365b0SManuel Lauss	la	t1, __flush_cache_all
56564365b0SManuel Lauss	lw	t0, 0(t1)
57564365b0SManuel Lauss	jalr	t0
58564365b0SManuel Lauss	 nop
59564365b0SManuel Lauss
60e8c7c482SRalf Baechle	/* Now set up the scratch registers so the boot rom will
61e8c7c482SRalf Baechle	 * return to this point upon wakeup.
62564365b0SManuel Lauss	 * sys_scratch0 : SP
63564365b0SManuel Lauss	 * sys_scratch1 : RA
64e8c7c482SRalf Baechle	 */
65564365b0SManuel Lauss	lui	t3, 0xb190		/* sys_xxx */
66564365b0SManuel Lauss	sw	sp, 0x0018(t3)
672e93d1ecSManuel Lauss	la	k0, alchemy_sleep_wakeup	/* resume path */
68564365b0SManuel Lauss	sw	k0, 0x001c(t3)
692e93d1ecSManuel Lauss.endm
70e8c7c482SRalf Baechle
712e93d1ecSManuel Lauss.macro	DO_SLEEP
722e93d1ecSManuel Lauss	/* put power supply and processor to sleep */
732e93d1ecSManuel Lauss	sw	zero, 0x0078(t3)	/* sys_slppwr */
742e93d1ecSManuel Lauss	sync
752e93d1ecSManuel Lauss	sw	zero, 0x007c(t3)	/* sys_sleep */
762e93d1ecSManuel Lauss	sync
772e93d1ecSManuel Lauss	nop
782e93d1ecSManuel Lauss	nop
792e93d1ecSManuel Lauss	nop
802e93d1ecSManuel Lauss	nop
812e93d1ecSManuel Lauss	nop
822e93d1ecSManuel Lauss	nop
832e93d1ecSManuel Lauss	nop
842e93d1ecSManuel Lauss	nop
852e93d1ecSManuel Lauss.endm
862e93d1ecSManuel Lauss
872e93d1ecSManuel Lauss/* sleep code for Au1000/Au1100/Au1500 memory controller type */
882e93d1ecSManuel LaussLEAF(alchemy_sleep_au1000)
892e93d1ecSManuel Lauss
902e93d1ecSManuel Lauss	SETUP_SLEEP
912e93d1ecSManuel Lauss
922e93d1ecSManuel Lauss	/* cache following instructions, as memory gets put to sleep */
93564365b0SManuel Lauss	la	t0, 1f
94a809d460SRalf Baechle	.set	arch=r4000
95e8c7c482SRalf Baechle	cache	0x14, 0(t0)
96e8c7c482SRalf Baechle	cache	0x14, 32(t0)
97e8c7c482SRalf Baechle	cache	0x14, 64(t0)
98e8c7c482SRalf Baechle	cache	0x14, 96(t0)
99e8c7c482SRalf Baechle	.set	mips0
100e8c7c482SRalf Baechle
101564365b0SManuel Lauss1:	lui	a0, 0xb400		/* mem_xxx */
102564365b0SManuel Lauss	sw	zero, 0x001c(a0)	/* Precharge */
103564365b0SManuel Lauss	sync
104564365b0SManuel Lauss	sw	zero, 0x0020(a0)	/* Auto Refresh */
105564365b0SManuel Lauss	sync
106564365b0SManuel Lauss	sw	zero, 0x0030(a0)	/* Sleep */
107564365b0SManuel Lauss	sync
108564365b0SManuel Lauss
1092e93d1ecSManuel Lauss	DO_SLEEP
1102e93d1ecSManuel Lauss
1112e93d1ecSManuel LaussEND(alchemy_sleep_au1000)
1122e93d1ecSManuel Lauss
1132e93d1ecSManuel Lauss/* sleep code for Au1550/Au1200 memory controller type */
1142e93d1ecSManuel LaussLEAF(alchemy_sleep_au1550)
1152e93d1ecSManuel Lauss
1162e93d1ecSManuel Lauss	SETUP_SLEEP
1172e93d1ecSManuel Lauss
1182e93d1ecSManuel Lauss	/* cache following instructions, as memory gets put to sleep */
1192e93d1ecSManuel Lauss	la	t0, 1f
120a809d460SRalf Baechle	.set	arch=r4000
1212e93d1ecSManuel Lauss	cache	0x14, 0(t0)
1222e93d1ecSManuel Lauss	cache	0x14, 32(t0)
1232e93d1ecSManuel Lauss	cache	0x14, 64(t0)
1242e93d1ecSManuel Lauss	cache	0x14, 96(t0)
1252e93d1ecSManuel Lauss	.set	mips0
1262e93d1ecSManuel Lauss
1272e93d1ecSManuel Lauss1:	lui	a0, 0xb400		/* mem_xxx */
128564365b0SManuel Lauss	sw	zero, 0x08c0(a0)	/* Precharge */
129564365b0SManuel Lauss	sync
130564365b0SManuel Lauss	sw	zero, 0x08d0(a0)	/* Self Refresh */
131e8c7c482SRalf Baechle	sync
132e8c7c482SRalf Baechle
133564365b0SManuel Lauss	/* wait for sdram to enter self-refresh mode */
134564365b0SManuel Lauss	lui	t0, 0x0100
135564365b0SManuel Lauss2:	lw	t1, 0x0850(a0)		/* mem_sdstat */
136564365b0SManuel Lauss	and	t2, t1, t0
137564365b0SManuel Lauss	beq	t2, zero, 2b
138564365b0SManuel Lauss	 nop
139564365b0SManuel Lauss
140564365b0SManuel Lauss	/* disable SDRAM clocks */
141564365b0SManuel Lauss	lui	t0, 0xcfff
142564365b0SManuel Lauss	ori	t0, t0, 0xffff
143564365b0SManuel Lauss	lw	t1, 0x0840(a0)		/* mem_sdconfiga */
144564365b0SManuel Lauss	and	t1, t0, t1		/* clear CE[1:0] */
145564365b0SManuel Lauss	sw	t1, 0x0840(a0)		/* mem_sdconfiga */
146e8c7c482SRalf Baechle	sync
147564365b0SManuel Lauss
1482e93d1ecSManuel Lauss	DO_SLEEP
1492e93d1ecSManuel Lauss
1502e93d1ecSManuel LaussEND(alchemy_sleep_au1550)
1512e93d1ecSManuel Lauss
152809f36c6SManuel Lauss/* sleepcode for Au1300 memory controller type */
153809f36c6SManuel LaussLEAF(alchemy_sleep_au1300)
154809f36c6SManuel Lauss
155809f36c6SManuel Lauss	SETUP_SLEEP
156809f36c6SManuel Lauss
157809f36c6SManuel Lauss	/* cache following instructions, as memory gets put to sleep */
158809f36c6SManuel Lauss	la	t0, 2f
159809f36c6SManuel Lauss	la	t1, 4f
160809f36c6SManuel Lauss	subu	t2, t1, t0
161809f36c6SManuel Lauss
162a809d460SRalf Baechle	.set	arch=r4000
163809f36c6SManuel Lauss
164809f36c6SManuel Lauss1:	cache	0x14, 0(t0)
165809f36c6SManuel Lauss	subu	t2, t2, 32
166809f36c6SManuel Lauss	bgez	t2, 1b
167809f36c6SManuel Lauss	 addu	t0, t0, 32
168809f36c6SManuel Lauss
169809f36c6SManuel Lauss	.set	mips0
170809f36c6SManuel Lauss
171809f36c6SManuel Lauss2:	lui	a0, 0xb400		/* mem_xxx */
172809f36c6SManuel Lauss
173809f36c6SManuel Lauss	/* disable all ports in mem_sdportcfga */
174809f36c6SManuel Lauss	sw	zero, 0x868(a0)		/* mem_sdportcfga */
175809f36c6SManuel Lauss	sync
176809f36c6SManuel Lauss
177809f36c6SManuel Lauss	/* disable ODT */
178809f36c6SManuel Lauss	li	t0, 0x03010000
179809f36c6SManuel Lauss	sw	t0, 0x08d8(a0)		/* mem_sdcmd0 */
180809f36c6SManuel Lauss	sw	t0, 0x08dc(a0)		/* mem_sdcmd1 */
181809f36c6SManuel Lauss	sync
182809f36c6SManuel Lauss
183809f36c6SManuel Lauss	/* precharge */
184809f36c6SManuel Lauss	li	t0, 0x23000400
185809f36c6SManuel Lauss	sw	t0, 0x08dc(a0)		/* mem_sdcmd1 */
186809f36c6SManuel Lauss	sw	t0, 0x08d8(a0)		/* mem_sdcmd0 */
187809f36c6SManuel Lauss	sync
188809f36c6SManuel Lauss
189809f36c6SManuel Lauss	/* auto refresh */
190809f36c6SManuel Lauss	sw	zero, 0x08c8(a0)	/* mem_sdautoref */
191809f36c6SManuel Lauss	sync
192809f36c6SManuel Lauss
193809f36c6SManuel Lauss	/* block access to the DDR */
194809f36c6SManuel Lauss	lw	t0, 0x0848(a0)		/* mem_sdconfigb */
195809f36c6SManuel Lauss	li	t1, (1 << 7 | 0x3F)
196809f36c6SManuel Lauss	or	t0, t0, t1
197809f36c6SManuel Lauss	sw	t0, 0x0848(a0)		/* mem_sdconfigb */
198809f36c6SManuel Lauss	sync
199809f36c6SManuel Lauss
200809f36c6SManuel Lauss	/* issue the Self Refresh command */
201809f36c6SManuel Lauss	li	t0, 0x10000000
202809f36c6SManuel Lauss	sw	t0, 0x08dc(a0)		/* mem_sdcmd1 */
203809f36c6SManuel Lauss	sw	t0, 0x08d8(a0)		/* mem_sdcmd0 */
204809f36c6SManuel Lauss	sync
205809f36c6SManuel Lauss
206809f36c6SManuel Lauss	/* wait for sdram to enter self-refresh mode */
207809f36c6SManuel Lauss	lui	t0, 0x0300
208809f36c6SManuel Lauss3:	lw	t1, 0x0850(a0)		/* mem_sdstat */
209809f36c6SManuel Lauss	and	t2, t1, t0
210809f36c6SManuel Lauss	bne	t2, t0, 3b
211809f36c6SManuel Lauss	 nop
212809f36c6SManuel Lauss
213809f36c6SManuel Lauss	/* disable SDRAM clocks */
214809f36c6SManuel Lauss	li	t0, ~(3<<28)
215809f36c6SManuel Lauss	lw	t1, 0x0840(a0)		/* mem_sdconfiga */
216809f36c6SManuel Lauss	and	t1, t1, t0		/* clear CE[1:0] */
217809f36c6SManuel Lauss	sw	t1, 0x0840(a0)		/* mem_sdconfiga */
218809f36c6SManuel Lauss	sync
219809f36c6SManuel Lauss
220809f36c6SManuel Lauss	DO_SLEEP
221809f36c6SManuel Lauss4:
222809f36c6SManuel Lauss
223809f36c6SManuel LaussEND(alchemy_sleep_au1300)
224809f36c6SManuel Lauss
225e8c7c482SRalf Baechle
226e8c7c482SRalf Baechle	/* This is where we return upon wakeup.
227e8c7c482SRalf Baechle	 * Reload all of the registers and return.
228e8c7c482SRalf Baechle	 */
2292e93d1ecSManuel LaussLEAF(alchemy_sleep_wakeup)
2302e93d1ecSManuel Lauss	lw	k0, 0x20(sp)
231e8c7c482SRalf Baechle	mtc0	k0, CP0_STATUS
232e8c7c482SRalf Baechle	lw	k0, 0x1c(sp)
233e8c7c482SRalf Baechle	mtc0	k0, CP0_CONTEXT
234e8c7c482SRalf Baechle	lw	k0, 0x18(sp)
235e8c7c482SRalf Baechle	mtc0	k0, CP0_PAGEMASK
236e8c7c482SRalf Baechle	lw	k0, 0x14(sp)
237e8c7c482SRalf Baechle	mtc0	k0, CP0_CONFIG
238e8c7c482SRalf Baechle
239564365b0SManuel Lauss	/* We need to catch the early Alchemy SOCs with
240e8c7c482SRalf Baechle	 * the write-only Config[OD] bit and set it back to one...
241e8c7c482SRalf Baechle	 */
242e8c7c482SRalf Baechle	jal	au1x00_fixup_config_od
243564365b0SManuel Lauss	 nop
244e8c7c482SRalf Baechle	lw	$1, PT_R1(sp)
245e8c7c482SRalf Baechle	lw	$2, PT_R2(sp)
246e8c7c482SRalf Baechle	lw	$3, PT_R3(sp)
247e8c7c482SRalf Baechle	lw	$4, PT_R4(sp)
248e8c7c482SRalf Baechle	lw	$5, PT_R5(sp)
249e8c7c482SRalf Baechle	lw	$6, PT_R6(sp)
250e8c7c482SRalf Baechle	lw	$7, PT_R7(sp)
251e8c7c482SRalf Baechle	lw	$16, PT_R16(sp)
252e8c7c482SRalf Baechle	lw	$17, PT_R17(sp)
253e8c7c482SRalf Baechle	lw	$18, PT_R18(sp)
254e8c7c482SRalf Baechle	lw	$19, PT_R19(sp)
255e8c7c482SRalf Baechle	lw	$20, PT_R20(sp)
256e8c7c482SRalf Baechle	lw	$21, PT_R21(sp)
257e8c7c482SRalf Baechle	lw	$22, PT_R22(sp)
258e8c7c482SRalf Baechle	lw	$23, PT_R23(sp)
259e8c7c482SRalf Baechle	lw	$26, PT_R26(sp)
260e8c7c482SRalf Baechle	lw	$27, PT_R27(sp)
261e8c7c482SRalf Baechle	lw	$28, PT_R28(sp)
262e8c7c482SRalf Baechle	lw	$30, PT_R30(sp)
263e8c7c482SRalf Baechle	lw	$31, PT_R31(sp)
264e8c7c482SRalf Baechle	jr	ra
265564365b0SManuel Lauss	 addiu	sp, PT_SIZE
2662e93d1ecSManuel LaussEND(alchemy_sleep_wakeup)
267