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