1/*
2 * linux/arch/arm/mach-pnx4008/sleep.S
3 *
4 * PNX4008 support for STOP mode and SDRAM self-refresh
5 *
6 * Authors: Dmitry Chigirev, Vitaly Wool <source@mvista.com>
7 *
8 * 2005 (c) MontaVista Software, Inc. This file is licensed under
9 * the terms of the GNU General Public License version 2. This program
10 * is licensed "as is" without any warranty of any kind, whether express
11 * or implied.
12 */
13
14#include <linux/linkage.h>
15#include <asm/assembler.h>
16#include <mach/hardware.h>
17
18#define PWRMAN_VA_BASE IO_ADDRESS(PNX4008_PWRMAN_BASE)
19#define PWR_CTRL_REG_OFFS 0x44
20
21#define SDRAM_CFG_VA_BASE IO_ADDRESS(PNX4008_SDRAM_CFG_BASE)
22#define MPMC_STATUS_REG_OFFS 0x4
23
24		.text
25
26ENTRY(pnx4008_cpu_suspend)
27	@this function should be entered in Direct run mode.
28
29	@ save registers on stack
30	stmfd	sp!, {r0 - r6, lr}
31
32	@ setup Power Manager base address in r4
33	@ and put it's value in r5
34	mov	r4, #(PWRMAN_VA_BASE & 0xff000000)
35	orr	r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000)
36	orr	r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00)
37	orr	r4, r4, #(PWRMAN_VA_BASE & 0x000000ff)
38	ldr	r5, [r4, #PWR_CTRL_REG_OFFS]
39
40	@ setup SDRAM controller base address in r2
41	@ and put it's value in r3
42	mov	r2, #(SDRAM_CFG_VA_BASE & 0xff000000)
43	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000)
44	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00)
45	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff)
46	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround
47
48	@ clear SDRAM self-refresh bit latch
49	and	r5, r5, #(~(1 << 8))
50	@ clear SDRAM self-refresh bit
51	and	r5, r5, #(~(1 << 9))
52	str	r5, [r4, #PWR_CTRL_REG_OFFS]
53
54	@ do save current bit settings in r1
55	mov	r1, r5
56
57	@ set SDRAM self-refresh bit
58	orr	r5, r5, #(1 << 9)
59	str	r5, [r4, #PWR_CTRL_REG_OFFS]
60
61	@ set SDRAM self-refresh bit latch
62	orr	r5, r5, #(1 << 8)
63	str	r5, [r4, #PWR_CTRL_REG_OFFS]
64
65	@ clear SDRAM self-refresh bit latch
66	and	r5, r5, #(~(1 << 8))
67	str	r5, [r4, #PWR_CTRL_REG_OFFS]
68
69	@ clear SDRAM self-refresh bit
70	and	r5, r5, #(~(1 << 9))
71	str	r5, [r4, #PWR_CTRL_REG_OFFS]
72
73	@ wait for SDRAM to get into self-refresh mode
742:	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS]
75	tst	r3, #(1 << 2)
76	beq	2b
77
78	@ to prepare SDRAM to get out of self-refresh mode after wakeup
79	orr	r5, r5, #(1 << 7)
80	str	r5, [r4, #PWR_CTRL_REG_OFFS]
81
82	@ do enter stop mode
83	orr	r5, r5, #(1 << 0)
84	str	r5, [r4, #PWR_CTRL_REG_OFFS]
85	nop
86	nop
87	nop
88	nop
89	nop
90	nop
91	nop
92	nop
93	nop
94
95	@ sleeping now...
96
97	@ coming out of STOP mode into Direct Run mode
98	@ clear STOP mode and SDRAM self-refresh bits
99	str	r1, [r4, #PWR_CTRL_REG_OFFS]
100
101	@ wait for SDRAM to get out self-refresh mode
1023:	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS]
103	tst	r3, #5
104	bne	3b
105
106	@ restore regs and return
107	ldmfd   sp!, {r0 - r6, pc}
108
109ENTRY(pnx4008_cpu_suspend_sz)
110	.word	. - pnx4008_cpu_suspend
111
112ENTRY(pnx4008_cpu_standby)
113	@ save registers on stack
114	stmfd	sp!, {r0 - r6, lr}
115
116	@ setup Power Manager base address in r4
117	@ and put it's value in r5
118	mov	r4, #(PWRMAN_VA_BASE & 0xff000000)
119	orr	r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000)
120	orr	r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00)
121	orr	r4, r4, #(PWRMAN_VA_BASE & 0x000000ff)
122	ldr	r5, [r4, #PWR_CTRL_REG_OFFS]
123
124	@ setup SDRAM controller base address in r2
125	@ and put it's value in r3
126	mov	r2, #(SDRAM_CFG_VA_BASE & 0xff000000)
127	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000)
128	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00)
129	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff)
130	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround
131
132	@ clear SDRAM self-refresh bit latch
133	and	r5, r5, #(~(1 << 8))
134	@ clear SDRAM self-refresh bit
135	and	r5, r5, #(~(1 << 9))
136	str	r5, [r4, #PWR_CTRL_REG_OFFS]
137
138	@ do save current bit settings in r1
139	mov	r1, r5
140
141	@ set SDRAM self-refresh bit
142	orr	r5, r5, #(1 << 9)
143	str	r5, [r4, #PWR_CTRL_REG_OFFS]
144
145	@ set SDRAM self-refresh bit latch
146	orr	r5, r5, #(1 << 8)
147	str	r5, [r4, #PWR_CTRL_REG_OFFS]
148
149	@ clear SDRAM self-refresh bit latch
150	and	r5, r5, #(~(1 << 8))
151	str	r5, [r4, #PWR_CTRL_REG_OFFS]
152
153	@ clear SDRAM self-refresh bit
154	and	r5, r5, #(~(1 << 9))
155	str	r5, [r4, #PWR_CTRL_REG_OFFS]
156
157	@ wait for SDRAM to get into self-refresh mode
1582:	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS]
159	tst	r3, #(1 << 2)
160	beq	2b
161
162	@ set 'get out of self-refresh mode after wakeup' bit
163	orr	r5, r5, #(1 << 7)
164	str	r5, [r4, #PWR_CTRL_REG_OFFS]
165
166	mcr     p15, 0, r0, c7, c0, 4	@ kinda sleeping now...
167
168	@ set SDRAM self-refresh bit latch
169	orr	r5, r5, #(1 << 8)
170	str	r5, [r4, #PWR_CTRL_REG_OFFS]
171
172	@ clear SDRAM self-refresh bit latch
173	and	r5, r5, #(~(1 << 8))
174	str	r5, [r4, #PWR_CTRL_REG_OFFS]
175
176	@ wait for SDRAM to get out self-refresh mode
1773:	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS]
178	tst	r3, #5
179	bne	3b
180
181	@ restore regs and return
182	ldmfd   sp!, {r0 - r6, pc}
183
184ENTRY(pnx4008_cpu_standby_sz)
185	.word	. - pnx4008_cpu_standby
186
187ENTRY(pnx4008_cache_clean_invalidate)
188	stmfd	sp!, {r0 - r6, lr}
189#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
190	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
191#else
1921:	mrc	p15, 0, r15, c7, c14, 3		@ test,clean,invalidate
193	bne     1b
194#endif
195	ldmfd   sp!, {r0 - r6, pc}
196