xref: /openbmc/u-boot/arch/arm/cpu/armv7/ls102xa/psci.S (revision 274bced8)
1/*
2 * Copyright 2015 Freescale Semiconductor, Inc.
3 * Author: Wang Dongsheng <dongsheng.wang@freescale.com>
4 *
5 * SPDX-License-Identifier:	GPL-2.0+
6 */
7
8#include <config.h>
9#include <linux/linkage.h>
10
11#include <asm/armv7.h>
12#include <asm/arch-armv7/generictimer.h>
13#include <asm/psci.h>
14
15#define RCPM_TWAITSR		0x04C
16
17#define SCFG_CORE0_SFT_RST      0x130
18#define SCFG_CORESRENCR         0x204
19
20#define DCFG_CCSR_RSTCR			0x0B0
21#define DCFG_CCSR_RSTCR_RESET_REQ	0x2
22#define DCFG_CCSR_BRR			0x0E4
23#define DCFG_CCSR_SCRATCHRW1		0x200
24
25#define PSCI_FN_PSCI_VERSION_FEATURE_MASK	0x0
26#define PSCI_FN_CPU_SUSPEND_FEATURE_MASK	0x0
27#define PSCI_FN_CPU_OFF_FEATURE_MASK		0x0
28#define PSCI_FN_CPU_ON_FEATURE_MASK		0x0
29#define PSCI_FN_AFFINITY_INFO_FEATURE_MASK	0x0
30#define PSCI_FN_SYSTEM_OFF_FEATURE_MASK		0x0
31#define PSCI_FN_SYSTEM_RESET_FEATURE_MASK	0x0
32#define PSCI_FN_SYSTEM_SUSPEND_FEATURE_MASK	0x0
33
34	.pushsection ._secure.text, "ax"
35
36	.arch_extension sec
37
38	.align	5
39
40#define	ONE_MS		(GENERIC_TIMER_CLK / 1000)
41#define	RESET_WAIT	(30 * ONE_MS)
42
43.globl	psci_version
44psci_version:
45	movw	r0, #0
46	movt	r0, #1
47
48	bx	lr
49
50_ls102x_psci_supported_table:
51	.word	ARM_PSCI_0_2_FN_PSCI_VERSION
52	.word	PSCI_FN_PSCI_VERSION_FEATURE_MASK
53	.word	ARM_PSCI_0_2_FN_CPU_SUSPEND
54	.word	PSCI_FN_CPU_SUSPEND_FEATURE_MASK
55	.word	ARM_PSCI_0_2_FN_CPU_OFF
56	.word	PSCI_FN_CPU_OFF_FEATURE_MASK
57	.word	ARM_PSCI_0_2_FN_CPU_ON
58	.word	PSCI_FN_CPU_ON_FEATURE_MASK
59	.word	ARM_PSCI_0_2_FN_AFFINITY_INFO
60	.word	PSCI_FN_AFFINITY_INFO_FEATURE_MASK
61	.word	ARM_PSCI_0_2_FN_SYSTEM_OFF
62	.word	PSCI_FN_SYSTEM_OFF_FEATURE_MASK
63	.word	ARM_PSCI_0_2_FN_SYSTEM_RESET
64	.word	PSCI_FN_SYSTEM_RESET_FEATURE_MASK
65	.word	ARM_PSCI_1_0_FN_SYSTEM_SUSPEND
66	.word	PSCI_FN_SYSTEM_SUSPEND_FEATURE_MASK
67	.word	0
68	.word	ARM_PSCI_RET_NI
69
70.globl	psci_features
71psci_features:
72	adr	r2, _ls102x_psci_supported_table
731:	ldr	r3, [r2]
74	cmp	r3, #0
75	beq	out_psci_features
76	cmp	r1, r3
77	addne	r2, r2, #8
78	bne	1b
79
80out_psci_features:
81	ldr	r0, [r2, #4]
82	bx	lr
83
84@ r0: return value ARM_PSCI_RET_SUCCESS or ARM_PSCI_RET_INVAL
85@ r1: input target CPU ID in MPIDR format, original value in r1 may be dropped
86@ r4: output validated CPU ID if ARM_PSCI_RET_SUCCESS returns, meaningless for
87@ ARM_PSCI_RET_INVAL,suppose caller saves r4 before calling
88LENTRY(psci_check_target_cpu_id)
89	@ Get the real CPU number
90	and	r4, r1, #0xff
91	mov	r0, #ARM_PSCI_RET_INVAL
92
93	@ Bit[31:24], bits must be zero.
94	tst	r1, #0xff000000
95	bxne	lr
96
97	@ Affinity level 2 - Cluster: only one cluster in LS1021xa.
98	tst	r1, #0xff0000
99	bxne	lr
100
101	@ Affinity level 1 - Processors: should be in 0xf00 format.
102	lsr	r1, r1, #8
103	teq	r1, #0xf
104	bxne	lr
105
106	@ Affinity level 0 - CPU: only 0, 1 are valid in LS1021xa.
107	cmp	r4, #2
108	bxge	lr
109
110	mov	r0, #ARM_PSCI_RET_SUCCESS
111	bx	lr
112ENDPROC(psci_check_target_cpu_id)
113
114	@ r1 = target CPU
115	@ r2 = target PC
116.globl	psci_cpu_on
117psci_cpu_on:
118	push	{r4, r5, r6, lr}
119
120	@ Clear and Get the correct CPU number
121	@ r1 = 0xf01
122	bl	psci_check_target_cpu_id
123	cmp	r0, #ARM_PSCI_RET_INVAL
124	beq	out_psci_cpu_on
125
126	mov	r0, r4
127	mov	r1, r2
128	bl	psci_save_target_pc
129	mov	r1, r4
130
131	@ Get DCFG base address
132	movw	r4, #(CONFIG_SYS_FSL_GUTS_ADDR & 0xffff)
133	movt	r4, #(CONFIG_SYS_FSL_GUTS_ADDR >> 16)
134
135	@ Detect target CPU state
136	ldr	r2, [r4, #DCFG_CCSR_BRR]
137	rev	r2, r2
138	lsr	r2, r2, r1
139	ands	r2, r2, #1
140	beq	holdoff_release
141
142	@ Reset target CPU
143	@ Get SCFG base address
144	movw	r0, #(CONFIG_SYS_FSL_SCFG_ADDR & 0xffff)
145	movt	r0, #(CONFIG_SYS_FSL_SCFG_ADDR >> 16)
146
147	@ Enable CORE Soft Reset
148	movw	r5, #0
149	movt	r5, #(1 << 15)
150	rev	r5, r5
151	str	r5, [r0, #SCFG_CORESRENCR]
152
153	@ Get CPUx offset register
154	mov	r6, #0x4
155	mul	r6, r6, r1
156	add	r2, r0, r6
157
158	@ Do reset on target CPU
159	movw	r5, #0
160	movt	r5, #(1 << 15)
161	rev	r5, r5
162	str	r5, [r2, #SCFG_CORE0_SFT_RST]
163
164	@ Wait target CPU up
165	timer_wait	r2, RESET_WAIT
166
167	@ Disable CORE soft reset
168	mov	r5, #0
169	str	r5, [r0, #SCFG_CORESRENCR]
170
171holdoff_release:
172	@ Release on target CPU
173	ldr	r2, [r4, #DCFG_CCSR_BRR]
174	mov	r6, #1
175	lsl	r6, r6, r1	@ 32 bytes per CPU
176
177	rev	r6, r6
178	orr	r2, r2, r6
179	str	r2, [r4, #DCFG_CCSR_BRR]
180
181	@ Set secondary boot entry
182	ldr	r6, =psci_cpu_entry
183	rev	r6, r6
184	str	r6, [r4, #DCFG_CCSR_SCRATCHRW1]
185
186	isb
187	dsb
188
189	@ Return
190	mov	r0, #ARM_PSCI_RET_SUCCESS
191
192out_psci_cpu_on:
193	pop	{r4, r5, r6, lr}
194	bx	lr
195
196.globl	psci_cpu_off
197psci_cpu_off:
198	bl	psci_cpu_off_common
199
2001:	wfi
201	b	1b
202
203.globl	psci_affinity_info
204psci_affinity_info:
205	push	{lr}
206
207	mov	r0, #ARM_PSCI_RET_INVAL
208
209	@ Verify Affinity level
210	cmp	r2, #0
211	bne	out_affinity_info
212
213	bl	psci_check_target_cpu_id
214	cmp	r0, #ARM_PSCI_RET_INVAL
215	beq	out_affinity_info
216	mov	r1, r4
217
218	@ Get RCPM base address
219	movw	r4, #(CONFIG_SYS_FSL_RCPM_ADDR & 0xffff)
220	movt	r4, #(CONFIG_SYS_FSL_RCPM_ADDR >> 16)
221
222	mov	r0, #PSCI_AFFINITY_LEVEL_ON
223
224	@ Detect target CPU state
225	ldr	r2, [r4, #RCPM_TWAITSR]
226	rev	r2, r2
227	lsr	r2, r2, r1
228	ands	r2, r2, #1
229	beq	out_affinity_info
230
231	mov	r0, #PSCI_AFFINITY_LEVEL_OFF
232
233out_affinity_info:
234	pop	{pc}
235
236.globl	psci_system_reset
237psci_system_reset:
238	@ Get DCFG base address
239	movw	r1, #(CONFIG_SYS_FSL_GUTS_ADDR & 0xffff)
240	movt	r1, #(CONFIG_SYS_FSL_GUTS_ADDR >> 16)
241
242	mov	r2, #DCFG_CCSR_RSTCR_RESET_REQ
243	rev	r2, r2
244	str	r2, [r1, #DCFG_CCSR_RSTCR]
245
2461:	wfi
247	b	1b
248
249.globl	psci_system_suspend
250psci_system_suspend:
251	push	{lr}
252
253	bl	ls1_system_suspend
254
255	pop	{pc}
256
257	.popsection
258