xref: /OK3568_Linux_fs/u-boot/arch/arm/cpu/armv8/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/macro.h>
8#include <asm-offsets.h>
9#include <asm/psci.h>
10#include <config.h>
11#include <linux/linkage.h>
12
13	.globl cpu_suspend
14	.globl cpu_do_suspend
15	.globl cpu_suspend_save
16	.globl cpu_resume
17	.globl cpu_do_resume
18
19/*
20 * int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
21 * @arg will be passed to fn as argument
22 * return value: 0 - cpu resumed from suspended state.
23 *		 -1 - cpu not suspended.
24 */
25ENTRY(cpu_suspend)
26	/*
27	 * Save x8~x30(lr is x30, sp is x29), total (23 + 1 reserved)*8=192
28	 */
29	stp	x29, lr, [sp, #-192]!
30	/* Reserve 8-byte after x8, just for offset with 16-byte aligned */
31	str	x8, [sp, #16]
32	stp	x9, x10, [sp, #32]
33	stp	x11, x12, [sp, #48]
34	stp	x13, x14, [sp, #64]
35	stp	x15, x16, [sp, #80]
36	stp	x17, x18, [sp, #96]
37	stp	x19, x20, [sp,#112]
38	stp	x21, x22, [sp,#128]
39	stp	x23, x24, [sp,#144]
40	stp	x25, x26, [sp,#160]
41	stp	x27, x28, [sp,#176]
42
43	mov	x19, sp
44	mov	x20, x0
45	mov	x21, x1
46
47	/* Save arch specific suspend fn and arg to stack */
48	sub	sp, sp, #PM_CTX_SIZE
49	stp	x0, x1, [sp, #-16]!
50
51	/* x18 is gd, save it to _suspend_gd !! */
52	adr	x0, _suspend_gd
53	str	x18, [x0]
54
55	/* x0: pm_ctx;	x1: sp where restore x8~x30 from */
56	add	x0, sp, #16
57	mov	x1, x19
58	bl	cpu_suspend_save
59
60	adr	lr, aborted
61	/* Jump to arch specific suspend */
62	mov	x0, x20
63	br	x21
64
65	/* Should never reach here, otherwise failed */
66aborted:
67	/* cpu not suspended */
68	add	sp, sp, #(16 + PM_CTX_SIZE)
69	/* Return -1 to the caller */
70	mov	x0, #(-1)
71
72suspend_return:
73	ldr	x8, [sp, #16]
74	ldp	x9, x10, [sp, #32]
75	ldp	x11, x12, [sp, #48]
76	ldp	x13, x14, [sp, #64]
77	ldp	x15, x16, [sp, #80]
78	ldp	x17, x18, [sp, #96]
79	ldp	x19, x20, [sp,#112]
80	ldp	x21, x22, [sp,#128]
81	ldp	x23, x24, [sp,#144]
82	ldp	x25, x26, [sp,#160]
83	ldp	x27, x28, [sp,#176]
84	ldp	x29, lr, [sp], #192
85	ret
86ENDPROC(cpu_suspend)
87
88ENTRY(cpu_do_suspend)
89	/*
90	 * Save temporary x2~x12, total: 11*8=88, maybe you need not so many
91	 * registers now, but I save them for future extendion.
92	 */
93	stp	x2,  x3, [sp, #-88]!
94	stp	x4,  x5, [sp, #16]
95	stp	x6,  x7, [sp, #32]
96	stp	x8,  x9, [sp, #48]
97	stp	x10, x11, [sp,#64]
98	str	x12, [sp, #80]
99
100	/*
101	 * Save core registers.
102	 *
103	 * Note: If you want to add/sub the register here,
104	 *	 remember update suspend_regs[] of struct pm_ctx.
105	 */
106	mrs	x2, vbar_el2
107	mrs	x3, cptr_el2
108	mrs	x4, ttbr0_el2
109	mrs	x5, tcr_el2
110	mrs	x6, mair_el2
111	mrs	x7, cntvoff_el2
112	mrs	x8, sctlr_el2
113	mrs	x9, hcr_el2
114	mrs	x10, daif
115
116	stp	x2,  x3, [x0, #0]
117	stp	x4,  x5, [x0, #16]
118	stp	x6,  x7, [x0, #32]
119	stp	x8,  x9, [x0, #48]
120	str	x10, [x0, #64]
121
122	/* Restore temporary x2~x12 */
123	ldp	x4,  x5, [sp, #16]
124	ldp	x6,  x7, [sp, #32]
125	ldp	x8,  x9, [sp, #48]
126	ldp	x10, x11, [sp,#64]
127	ldr	x12, [sp, #80]
128	ldp	x2,  x3, [sp], #88
129	ret
130ENDPROC(cpu_do_suspend)
131
132ENTRY(cpu_resume)
133	/* Disable interrupt */
134	msr       daifset, #0x03
135
136	/* Load gd !! */
137	adr x1, _suspend_gd
138	ldr x2, [x1]
139
140	/* Get pm_ctx */
141	add x2, x2, #PM_CTX_PHYS
142	ldr x0, [x2]
143
144	/* Need x0=x0-16, because cpu_do_resume needs it */
145	ldp	x1, lr, [x0], #16
146	mov	sp, x1
147	ret
148ENDPROC(cpu_resume)
149
150/*
151 * void sm_do_cpu_do_resume(paddr suspend_regs) __noreturn;
152 * Restore the registers stored when cpu_do_suspend
153 * x0 points to the physical base address of the suspend_regs
154 * field of struct pm_ctx.
155 */
156ENTRY(cpu_do_resume)
157	/*
158	 * Invalidate local tlb entries before turning on MMU !!!
159	 */
160	tlbi	alle2
161	dsb	sy
162	isb
163
164	ldp	x2, x3, [x0]
165	ldp	x4, x5, [x0, #16]
166	ldp	x6, x7, [x0, #32]
167	ldp	x8, x9, [x0, #48]
168	ldp	x10, x11, [x0, #64]
169	ldr	x12, [x0, #80]
170
171	/* Restore core register */
172	msr	vbar_el2, x2
173	msr	cptr_el2, x3
174	msr	ttbr0_el2, x4
175	msr	tcr_el2, x5
176	msr	mair_el2, x6
177	msr	cntvoff_el2, x7
178	msr	hcr_el2, x9
179
180	/* Enable MMU here */
181	msr	sctlr_el2, x8
182	dsb	sy
183	isb
184
185	/* resume interrupt */
186	msr	daif, x10
187
188	mov	x0, #0
189	b	suspend_return
190ENDPROC(cpu_do_resume)
191
192.align 3
193_suspend_gd:
194	.long	0x0
195
196