1/*
2 * linux/arch/unicore32/kernel/sleep.S
3 *
4 * Code specific to PKUnity SoC and UniCore ISA
5 *
6 *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
7 *	Copyright (C) 2001-2010 Guan Xuetao
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/linkage.h>
15#include <asm/assembler.h>
16#include <mach/hardware.h>
17
18		.text
19
20pkunity_cpu_save_cp:
21
22	@ get coprocessor registers
23
24	movc	r3, p0.c7, #0			@ PID
25	movc	r4, p0.c2, #0			@ translation table base addr
26	movc	r5, p0.c1, #0			@ control reg
27
28
29	@ store them plus current virtual stack ptr on stack
30	mov	r6, sp
31	stm.w	(r3 - r6), [sp-]
32
33	mov	pc, lr
34
35pkunity_cpu_save_sp:
36	@ preserve phys address of stack
37	mov	r0, sp
38	stw.w	lr, [sp+], #-4
39	b.l	sleep_phys_sp
40	ldw	r1, =sleep_save_sp
41	stw	r0, [r1]
42	ldw.w	pc, [sp]+, #4
43
44/*
45 * puv3_cpu_suspend()
46 *
47 * Forces CPU into sleep state.
48 *
49 * r0 = value for PWRMODE M field for desired sleep state
50 */
51
52ENTRY(puv3_cpu_suspend)
53	stm.w	(r16 - r27, lr), [sp-]		@ save registers on stack
54	stm.w	(r4 - r15), [sp-]		@ save registers on stack
55
56#ifdef	CONFIG_UNICORE_FPU_F64
57	sfm.w	(f0  - f7 ), [sp-]
58	sfm.w	(f8  - f15), [sp-]
59	sfm.w	(f16 - f23), [sp-]
60	sfm.w	(f24 - f31), [sp-]
61	cff	r4, s31
62	stm.w	(r4), [sp-]
63#endif
64	b.l	pkunity_cpu_save_cp
65
66	b.l	pkunity_cpu_save_sp
67
68	@ clean data cache
69	mov	r1, #0
70	movc	p0.c5, r1, #14
71	nop
72	nop
73	nop
74	nop
75
76
77
78	@ DDR2 BaseAddr
79	ldw	r0, =(PKUNITY_DDR2CTRL_BASE)
80
81	@ PM BaseAddr
82	ldw	r1, =(PKUNITY_PM_BASE)
83
84	@ set PLL_SYS_CFG reg, 275
85	movl	r6, #0x00002401
86	stw	r6, [r1+], #0x18
87	@ set PLL_DDR_CFG reg, 66MHz
88	movl	r6, #0x00100c00
89	stw	r6, [r1+], #0x1c
90
91	@ set wake up source
92	movl	r8, #0x800001ff		@ epip4d
93	stw	r8, [r1+], #0xc
94
95	@ set PGSR
96	movl	r5, #0x40000
97	stw	r5, [r1+], #0x10
98
99	@ prepare DDR2 refresh settings
100	ldw	r5, [r0+], #0x24
101	or	r5, r5, #0x00000001
102
103	@ prepare PMCR for PLL changing
104	movl	r6, #0xc
105
106	@ prepare for closing PLL
107	movl	r7, #0x1
108
109	@ prepare sleep mode
110	mov	r8, #0x1
111
112@	movl	r0, 0x11111111
113@	put_word_ocd r0
114	b	pkunity_cpu_do_suspend
115
116	.ltorg
117	.align	5
118pkunity_cpu_do_suspend:
119	b	101f
120	@ put DDR2 into self-refresh
121100:	stw	r5, [r0+], #0x24
122	@ change PLL
123	stw	r6, [r1]
124	b	1f
125
126	.ltorg
127	.align	5
128101:	b	102f
129	@ wait for PLL changing complete
1301:	ldw	r6, [r1+], #0x44
131	csub.a	r6, #0x1
132	bne	1b
133	b	2f
134
135	.ltorg
136	.align	5
137102:	b	100b
138	@ close PLL
1392:	stw	r7, [r1+], #0x4
140	@ enter sleep mode
141	stw	r8, [r1]
1423:	b	3b
143
144
145
146
147/*
148 * puv3_cpu_resume()
149 *
150 * entry point from bootloader into kernel during resume
151 *
152 * Note: Yes, part of the following code is located into the .data section.
153 *       This is to allow sleep_save_sp to be accessed with a relative load
154 *       while we can't rely on any MMU translation.  We could have put
155 *       sleep_save_sp in the .text section as well, but some setups might
156 *       insist on it to be truly read-only.
157 */
158
159	.data
160	.align 5
161ENTRY(puv3_cpu_resume)
162@	movl	r0, 0x20202020
163@	put_word_ocd r0
164
165	ldw	r0, sleep_save_sp		@ stack phys addr
166	ldw	r2, =resume_after_mmu		@ its absolute virtual address
167	ldm	(r3 - r6), [r0]+		@ CP regs + virt stack ptr
168	mov	sp, r6				@ CP regs + virt stack ptr
169
170	mov	r1, #0
171	movc	p0.c6, r1, #6			@ invalidate I & D TLBs
172	movc	p0.c5, r1, #28			@ invalidate I & D caches, BTB
173
174	movc	p0.c7, r3, #0			@ PID
175	movc	p0.c2, r4, #0			@ translation table base addr
176	movc	p0.c1, r5, #0			@ control reg, turn on mmu
177	nop
178	jump	r2
179	nop
180	nop
181	nop
182	nop
183	nop
184
185sleep_save_sp:
186	.word	0				@ preserve stack phys ptr here
187
188	.text
189resume_after_mmu:
190@	movl	r0, 0x30303030
191@	put_word_ocd r0
192
193#ifdef	CONFIG_UNICORE_FPU_F64
194	lfm.w	(f0  - f7 ), [sp]+
195	lfm.w	(f8  - f15), [sp]+
196	lfm.w	(f16 - f23), [sp]+
197	lfm.w	(f24 - f31), [sp]+
198	ldm.w	(r4), [sp]+
199	ctf	r4, s31
200#endif
201	ldm.w	(r4 - r15), [sp]+		@ restore registers from stack
202	ldm.w	(r16 - r27, pc), [sp]+		@ return to caller
203