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