xref: /rk3399_rockchip-uboot/arch/arm/cpu/armv7/sleep.S (revision aee63dc84c1f5be59ea35ceb209a4ea937bdeb41)
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	ldr     r4, CORTEX_A7_PART_NUM
61	cmp	r5, r4
62	beq	a7_suspend
63	ldr     r4, CORTEX_A9_PART_NUM
64	cmp	r5, r4
65	beq	a9_suspend
66
67	/* cpu not supported */
68	b	.
69
70	/* A9 needs PCR/DIAG */
71a9_suspend:
72	read_pcr r4
73	read_diag r5
74	stmia	r0!, {r4 - r5}
75
76a7_suspend:
77	read_fcseidr r4
78	read_tpidruro r5
79	stmia	r0!, {r4 - r5}
80
81	read_dacr  r4
82	read_ttbr0 r5
83	read_ttbr1 r6
84	read_ttbcr r7
85	read_sctlr r8
86	read_actlr r9
87	read_cpacr r10
88	stmia	r0!, {r4 - r10}
89
90	read_prrr r4
91	read_nmrr r5
92	read_vbar r6
93	mrs r7, CPSR
94	stmia	r0, {r4 - r7}
95
96	pop	{r4 - r11}
97	bx	lr
98ENDPROC(cpu_do_suspend)
99
100ENTRY(cpu_resume)
101	/* Disable interrupt */
102	cpsid	aif
103
104	/* Load gd !! */
105	adr r1, _suspend_gd
106	ldr r2, [r1]
107
108	/* Get pm_ctx */
109	add r2, r2, #PM_CTX_PHYS
110	ldr r0, [r2]
111
112	/* Need to use r0!, because cpu_do_resume needs it */
113	ldmia	r0!, {sp, pc}
114ENDPROC(cpu_resume)
115
116/*
117 * void sm_do_cpu_do_resume(paddr suspend_regs) __noreturn;
118 * Restore the registers stored when cpu_do_suspend
119 * r0 points to the physical base address of the suspend_regs
120 * field of struct pm_ctx.
121 */
122ENTRY(cpu_do_resume)
123	read_midr r4
124	ubfx	r5, r4, #4, #12
125	ldr     r4, CORTEX_A7_PART_NUM
126	cmp	r5, r4
127	beq	a7_resume
128
129	/*
130	 * A9 needs PCR/DIAG
131	 */
132	ldmia   r0!, {r4 - r5}
133	write_pcr r4
134	write_diag r5
135
136a7_resume:
137	/* v7 resume */
138	mov	ip, #0
139
140	/* Invalidate icache to PoU */
141	write_iciallu
142	/* set reserved context */
143	write_contextidr ip
144
145	ldmia	r0!, {r4 - r5}
146	write_fcseidr r4
147	write_tpidruro r5
148
149	ldmia	r0!, {r4 - r10}
150	/* Invalidate entire TLB */
151	write_tlbiall
152	write_dacr r4
153	write_ttbr0 r5
154	write_ttbr1 r6
155	write_ttbcr r7
156
157	ldmia	r0, {r4 - r7}
158	write_prrr  r4
159	write_nmrr  r5
160	write_vbar  r6
161
162	write_actlr r9
163	write_cpacr r10
164	write_bpiall
165	isb
166	dsb
167
168	/* MMU will be enabled here */
169	write_sctlr r8
170	isb
171
172	/* Restore interrupt */
173	msr CPSR_c, r7
174
175	mov	r0, #0
176	b	suspend_return
177ENDPROC(cpu_do_resume)
178
179.align 4
180_suspend_gd:
181	.word	0x0
182CORTEX_A7_PART_NUM:
183	.word	0xC07
184CORTEX_A9_PART_NUM:
185	.word	0xC09
186