1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * GIC Initialization Routines.
4 *
5 * (C) Copyright 2013
6 * David Feng <fenghua@phytium.com.cn>
7 */
8
9#include <asm-offsets.h>
10#include <config.h>
11#include <linux/linkage.h>
12#include <asm/gic.h>
13#include <asm/macro.h>
14
15
16/*************************************************************************
17 *
18 * void gic_init_secure(DistributorBase);
19 *
20 * Initialize secure copy of GIC at EL3.
21 *
22 *************************************************************************/
23ENTRY(gic_init_secure)
24	/*
25	 * Initialize Distributor
26	 * x0: Distributor Base
27	 */
28#if defined(CONFIG_GICV3)
29	mov	w9, #0x37		/* EnableGrp0 | EnableGrp1NS */
30					/* EnableGrp1S | ARE_S | ARE_NS */
31	str	w9, [x0, GICD_CTLR]	/* Secure GICD_CTLR */
32	ldr	w9, [x0, GICD_TYPER]
33	and	w10, w9, #0x1f		/* ITLinesNumber */
34	cbz	w10, 1f			/* No SPIs */
35	add	x11, x0, (GICD_IGROUPRn + 4)
36	add	x12, x0, (GICD_IGROUPMODRn + 4)
37	mov	w9, #~0
380:	str	w9, [x11], #0x4
39	str	wzr, [x12], #0x4	/* Config SPIs as Group1NS */
40	sub	w10, w10, #0x1
41	cbnz	w10, 0b
42#elif defined(CONFIG_GICV2)
43	switch_el x1, 2f, 1f, 1f
442:
45	mov	w9, #0x3		/* EnableGrp0 | EnableGrp1 */
46	str	w9, [x0, GICD_CTLR]	/* Secure GICD_CTLR */
47	ldr	w9, [x0, GICD_TYPER]
48	and	w10, w9, #0x1f		/* ITLinesNumber */
49	cbz	w10, 1f			/* No SPIs */
50	add	x11, x0, GICD_IGROUPRn
51	mov	w9, #~0			/* Config SPIs as Grp1 */
52	str	w9, [x11], #0x4
530:	str	w9, [x11], #0x4
54	sub	w10, w10, #0x1
55	cbnz	w10, 0b
56
57	ldr	x1, =GICC_BASE		/* GICC_CTLR */
58	mov	w0, #3			/* EnableGrp0 | EnableGrp1 */
59	str	w0, [x1]
60
61	mov	w0, #1 << 7		/* allow NS access to GICC_PMR */
62	str	w0, [x1, #4]		/* GICC_PMR */
63#endif
641:
65	ret
66ENDPROC(gic_init_secure)
67
68
69/*************************************************************************
70 * For Gicv2:
71 * void gic_init_secure_percpu(DistributorBase, CpuInterfaceBase);
72 * For Gicv3:
73 * void gic_init_secure_percpu(ReDistributorBase);
74 *
75 * Initialize secure copy of GIC at EL3.
76 *
77 *************************************************************************/
78ENTRY(gic_init_secure_percpu)
79#if defined(CONFIG_GICV3)
80	/*
81	 * Initialize ReDistributor
82	 * x0: ReDistributor Base
83	 */
84	mrs	x10, mpidr_el1
85	lsr	x9, x10, #32
86	bfi	x10, x9, #24, #8	/* w10 is aff3:aff2:aff1:aff0 */
87	mov	x9, x0
881:	ldr	x11, [x9, GICR_TYPER]
89	lsr	x11, x11, #32		/* w11 is aff3:aff2:aff1:aff0 */
90	cmp	w10, w11
91	b.eq	2f
92	add	x9, x9, #(2 << 16)
93	b	1b
94
952:
96#if defined(CONFIG_GICV3_SUPPORT_GIC600)
97        mov     w10, #0x0               /* Power on redistributor */
98        str     w10, [x9, GICR_PWRR]
995:      ldr     w10, [x9, GICR_PWRR]    /* Wait until the power on state is reflected */
100        tbnz    w10, #1, 5b             /* If RDPD == 0 then powered on */
101#endif
102
103	/* x9: ReDistributor Base Address of Current CPU */
104	mov	w10, #~0x2
105	ldr	w11, [x9, GICR_WAKER]
106	and	w11, w11, w10		/* Clear ProcessorSleep */
107	str	w11, [x9, GICR_WAKER]
108	dsb	st
109	isb
1103:	ldr	w10, [x9, GICR_WAKER]
111	tbnz	w10, #2, 3b		/* Wait Children be Alive */
112
113	add	x10, x9, #(1 << 16)	/* SGI_Base */
114	mov	w11, #~0
115	str	w11, [x10, GICR_IGROUPRn]
116	str	wzr, [x10, GICR_IGROUPMODRn]	/* SGIs|PPIs Group1NS */
117	mov	w11, #0x1		/* Enable SGI 0 */
118	str	w11, [x10, GICR_ISENABLERn]
119
120	switch_el x10, 3f, 2f, 1f
1213:
122	/* Initialize Cpu Interface */
123	mrs	x10, ICC_SRE_EL3
124	orr	x10, x10, #0xf		/* SRE & Disable IRQ/FIQ Bypass & */
125					/* Allow EL2 access to ICC_SRE_EL2 */
126	msr	ICC_SRE_EL3, x10
127	isb
128
129	mov	x10, #0x3		/* EnableGrp1NS | EnableGrp1S */
130	msr	ICC_IGRPEN1_EL3, x10
131	isb
132
133	msr	ICC_CTLR_EL3, xzr
134	isb
1352:
136	mrs	x10, ICC_SRE_EL2
137	orr	x10, x10, #0xf		/* SRE & Disable IRQ/FIQ Bypass & */
138					/* Allow EL1 access to ICC_SRE_EL1 */
139	msr	ICC_SRE_EL2, x10
140	isb
1411:
142	msr	ICC_CTLR_EL1, xzr	/* NonSecure ICC_CTLR_EL1 */
143	isb
144
145	mov	x10, #0x1 << 7		/* Non-Secure access to ICC_PMR_EL1 */
146	msr	ICC_PMR_EL1, x10
147	isb
148#elif defined(CONFIG_GICV2)
149	/*
150	 * Initialize SGIs and PPIs
151	 * x0: Distributor Base
152	 * x1: Cpu Interface Base
153	 */
154	switch_el x2, 4f, 5f, 5f
1554:
156	mov	w9, #~0			/* Config SGIs and PPIs as Grp1 */
157	str	w9, [x0, GICD_IGROUPRn]	/* GICD_IGROUPR0 */
158	mov	w9, #0x1		/* Enable SGI 0 */
159	str	w9, [x0, GICD_ISENABLERn]
160
161	/* Initialize Cpu Interface */
162	mov	w9, #0x1e7		/* Disable IRQ/FIQ Bypass & */
163					/* Enable Ack Group1 Interrupt & */
164					/* EnableGrp0 & EnableGrp1 */
165	str	w9, [x1, GICC_CTLR]	/* Secure GICC_CTLR */
166
167	mov	w9, #0x1 << 7		/* Non-Secure access to GICC_PMR */
168	str	w9, [x1, GICC_PMR]
169#endif
1705:
171	ret
172ENDPROC(gic_init_secure_percpu)
173
174
175/*************************************************************************
176 * For Gicv2:
177 * void gic_kick_secondary_cpus(DistributorBase);
178 * For Gicv3:
179 * void gic_kick_secondary_cpus(void);
180 *
181 *************************************************************************/
182ENTRY(gic_kick_secondary_cpus)
183#if defined(CONFIG_GICV3)
184	mov	x9, #(1 << 40)
185	msr	ICC_ASGI1R_EL1, x9
186	isb
187#elif defined(CONFIG_GICV2)
188	mov	w9, #0x8000
189	movk	w9, #0x100, lsl #16
190	str	w9, [x0, GICD_SGIR]
191#endif
192	ret
193ENDPROC(gic_kick_secondary_cpus)
194
195
196/*************************************************************************
197 * For Gicv2:
198 * void gic_wait_for_interrupt(CpuInterfaceBase);
199 * For Gicv3:
200 * void gic_wait_for_interrupt(void);
201 *
202 * Wait for SGI 0 from master.
203 *
204 *************************************************************************/
205ENTRY(gic_wait_for_interrupt)
206#if defined(CONFIG_GICV3)
207	gic_wait_for_interrupt_m x9
208#elif defined(CONFIG_GICV2)
209	gic_wait_for_interrupt_m x0, w9
210#endif
211	ret
212ENDPROC(gic_wait_for_interrupt)
213