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