xref: /OK3568_Linux_fs/u-boot/arch/arm/cpu/armv7/sleep.S (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1/*
2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd.
3 *
4 * SPDX-License-Identifier:	GPL-2.0+
5 */
6
7#include <asm/arm32_macros.S>
8#include <asm/macro.h>
9#include <asm-offsets.h>
10#include <asm/psci.h>
11#include <config.h>
12#include <linux/linkage.h>
13
14	.globl cpu_suspend
15	.globl cpu_do_suspend
16	.globl cpu_suspend_save
17	.globl cpu_resume
18	.globl cpu_do_resume
19
20/*
21 * int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
22 * @arg will be passed to fn as argument
23 * return value: 0 - cpu resumed from suspended state.
24 *		 -1 - cpu not suspended.
25 */
26ENTRY(cpu_suspend)
27	push	{r4 - r12, lr}
28
29	mov	r5, sp
30	sub	sp, sp, #PM_CTX_SIZE
31	push	{r0, r1}
32
33	/* r9 is gd, save it to __suspend_gd !!! */
34	adr	r4, __suspend_gd
35	str	r9, [r4]
36
37	mov	r1, r5
38	add	r0, sp, #8
39	blx	cpu_suspend_save
40
41	adr	lr, aborted
42	/* Jump to arch specific suspend */
43	pop	{r0, pc}
44
45aborted:
46	/* cpu not suspended */
47	add	sp, sp, #PM_CTX_SIZE
48	/* Return -1 to the caller */
49	mov	r0, #(-1)
50
51suspend_return:
52	pop	{r4 - r12, pc}
53ENDPROC(cpu_suspend)
54
55ENTRY(cpu_do_suspend)
56	push	{r4 - r11}
57
58	read_midr r4
59	ubfx	r5, r4, #4, #12
60
61	ldr     r4, CORTEX_A7_PART_NUM
62	cmp	r5, r4
63	beq	a7_suspend
64
65	ldr     r4, CORTEX_A9_PART_NUM
66	cmp	r5, r4
67	beq	a9_suspend
68
69	b	other_suspend
70
71	/* A9 needs PCR/DIAG */
72a9_suspend:
73	read_pcr r4
74	read_diag r5
75	stmia	r0!, {r4 - r5}
76
77a7_suspend:
78	read_fcseidr r4
79	read_tpidruro r5
80	stmia	r0!, {r4 - r5}
81
82other_suspend:
83	read_dacr  r4
84	read_ttbr0 r5
85	read_ttbr1 r6
86	read_ttbcr r7
87	read_sctlr r8
88	read_actlr r9
89	read_cpacr r10
90	stmia	r0!, {r4 - r10}
91
92	read_prrr r4
93	read_nmrr r5
94	read_vbar r6
95	mrs r7, CPSR
96	stmia	r0, {r4 - r7}
97
98	pop	{r4 - r11}
99	bx	lr
100ENDPROC(cpu_do_suspend)
101
102ENTRY(cpu_resume)
103	/* Disable interrupt */
104	cpsid	aif
105
106	/* Load gd !! */
107	adr r1, __suspend_gd
108	ldr r2, [r1]
109
110	/* Get pm_ctx */
111	add r2, r2, #PM_CTX_PHYS
112	ldr r0, [r2]
113
114	/* Need to use r0!, because cpu_do_resume needs it */
115	ldmia	r0!, {sp, pc}
116ENDPROC(cpu_resume)
117
118/*
119 * void sm_do_cpu_do_resume(paddr suspend_regs) __noreturn;
120 * Restore the registers stored when cpu_do_suspend
121 * r0 points to the physical base address of the suspend_regs
122 * field of struct pm_ctx.
123 */
124ENTRY(cpu_do_resume)
125	read_midr r4
126	ubfx	r5, r4, #4, #12
127
128	ldr	r4, CORTEX_A9_PART_NUM
129	cmp	r5, r4
130	beq	a9_resume
131
132	ldr     r4, CORTEX_A7_PART_NUM
133	cmp	r5, r4
134	beq	a7_resume
135
136	/* v7 resume */
137	mov	ip, #0
138	/* Invalidate icache to PoU */
139	write_iciallu
140	/* set reserved context */
141	write_contextidr ip
142	b	other_resume
143
144a9_resume:
145	/*
146	 * A9 needs PCR/DIAG
147	 */
148	ldmia   r0!, {r4 - r5}
149	write_pcr r4
150	write_diag r5
151
152a7_resume:
153	/* v7 resume */
154	mov	ip, #0
155
156	/* Invalidate icache to PoU */
157	write_iciallu
158	/* set reserved context */
159	write_contextidr ip
160
161	ldmia	r0!, {r4 - r5}
162	write_fcseidr r4
163	write_tpidruro r5
164
165other_resume:
166	ldmia	r0!, {r4 - r10}
167	/* Invalidate entire TLB */
168	write_tlbiall
169	write_dacr r4
170	write_ttbr0 r5
171	write_ttbr1 r6
172	write_ttbcr r7
173
174	ldmia	r0, {r4 - r7}
175	write_prrr  r4
176	write_nmrr  r5
177	write_vbar  r6
178
179	write_actlr r9
180	write_cpacr r10
181	write_bpiall
182	isb
183	dsb
184
185	/* MMU will be enabled here */
186	write_sctlr r8
187	isb
188
189	/* Restore interrupt */
190	msr CPSR_c, r7
191
192	mov	r0, #0
193	b	suspend_return
194ENDPROC(cpu_do_resume)
195
196.align 4
197__suspend_gd:
198	.word	0x0
199CORTEX_A7_PART_NUM:
200	.word	0xC07
201CORTEX_A9_PART_NUM:
202	.word	0xC09
203