1 /*
2 * Copyright 2020 Broadcom
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <sys/__assert.h>
8 #include <sw_isr_table.h>
9 #include <dt-bindings/interrupt-controller/arm-gic.h>
10 #include <drivers/interrupt_controller/gic.h>
11 #include "intc_gic_common_priv.h"
12 #include "intc_gicv3_priv.h"
13
14 /* Redistributor base addresses for each core */
15 mem_addr_t gic_rdists[CONFIG_MP_NUM_CPUS];
16
17 #if defined(CONFIG_ARMV8_A_NS) || defined(CONFIG_GIC_SINGLE_SECURITY_STATE)
18 #define IGROUPR_VAL 0xFFFFFFFFU
19 #else
20 #define IGROUPR_VAL 0x0U
21 #endif
22
gic_get_rdist(void)23 static inline mem_addr_t gic_get_rdist(void)
24 {
25 return gic_rdists[arch_curr_cpu()->id];
26 }
27
28 /*
29 * Wait for register write pending
30 * TODO: add timed wait
31 */
gic_wait_rwp(uint32_t intid)32 static int gic_wait_rwp(uint32_t intid)
33 {
34 uint32_t rwp_mask;
35 mem_addr_t base;
36
37 if (intid < GIC_SPI_INT_BASE) {
38 base = (gic_get_rdist() + GICR_CTLR);
39 rwp_mask = BIT(GICR_CTLR_RWP);
40 } else {
41 base = GICD_CTLR;
42 rwp_mask = BIT(GICD_CTLR_RWP);
43 }
44
45 while (sys_read32(base) & rwp_mask)
46 ;
47
48 return 0;
49 }
50
arm_gic_irq_set_priority(unsigned int intid,unsigned int prio,uint32_t flags)51 void arm_gic_irq_set_priority(unsigned int intid,
52 unsigned int prio, uint32_t flags)
53 {
54 uint32_t mask = BIT(intid & (GIC_NUM_INTR_PER_REG - 1));
55 uint32_t idx = intid / GIC_NUM_INTR_PER_REG;
56 uint32_t shift;
57 uint32_t val;
58 mem_addr_t base = GET_DIST_BASE(intid);
59
60 /* Disable the interrupt */
61 sys_write32(mask, ICENABLER(base, idx));
62 gic_wait_rwp(intid);
63
64 /* PRIORITYR registers provide byte access */
65 sys_write8(prio & GIC_PRI_MASK, IPRIORITYR(base, intid));
66
67 /* Interrupt type config */
68 if (!GIC_IS_SGI(intid)) {
69 idx = intid / GIC_NUM_CFG_PER_REG;
70 shift = (intid & (GIC_NUM_CFG_PER_REG - 1)) * 2;
71
72 val = sys_read32(ICFGR(base, idx));
73 val &= ~(GICD_ICFGR_MASK << shift);
74 if (flags & IRQ_TYPE_EDGE) {
75 val |= (GICD_ICFGR_TYPE << shift);
76 }
77 sys_write32(val, ICFGR(base, idx));
78 }
79 }
80
arm_gic_irq_enable(unsigned int intid)81 void arm_gic_irq_enable(unsigned int intid)
82 {
83 uint32_t mask = BIT(intid & (GIC_NUM_INTR_PER_REG - 1));
84 uint32_t idx = intid / GIC_NUM_INTR_PER_REG;
85
86 sys_write32(mask, ISENABLER(GET_DIST_BASE(intid), idx));
87
88 #ifdef CONFIG_ARMV8_A_NS
89 /*
90 * Affinity routing is enabled for Non-secure state (GICD_CTLR.ARE_NS
91 * is set to '1' when GIC distributor is initialized) ,so need to set
92 * SPI's affinity, now set it to be the PE on which it is enabled.
93 */
94 if (GIC_IS_SPI(intid))
95 sys_write64(MPIDR_TO_CORE(GET_MPIDR()),
96 IROUTER(GET_DIST_BASE(intid), intid));
97 #endif
98 }
99
arm_gic_irq_disable(unsigned int intid)100 void arm_gic_irq_disable(unsigned int intid)
101 {
102 uint32_t mask = BIT(intid & (GIC_NUM_INTR_PER_REG - 1));
103 uint32_t idx = intid / GIC_NUM_INTR_PER_REG;
104
105 sys_write32(mask, ICENABLER(GET_DIST_BASE(intid), idx));
106 /* poll to ensure write is complete */
107 gic_wait_rwp(intid);
108 }
109
arm_gic_irq_is_enabled(unsigned int intid)110 bool arm_gic_irq_is_enabled(unsigned int intid)
111 {
112 uint32_t mask = BIT(intid & (GIC_NUM_INTR_PER_REG - 1));
113 uint32_t idx = intid / GIC_NUM_INTR_PER_REG;
114 uint32_t val;
115
116 val = sys_read32(ISENABLER(GET_DIST_BASE(intid), idx));
117
118 return (val & mask) != 0;
119 }
120
arm_gic_get_active(void)121 unsigned int arm_gic_get_active(void)
122 {
123 int intid;
124
125 /* (Pending -> Active / AP) or (AP -> AP) */
126 intid = read_sysreg(ICC_IAR1_EL1);
127
128 return intid;
129 }
130
arm_gic_eoi(unsigned int intid)131 void arm_gic_eoi(unsigned int intid)
132 {
133 /*
134 * Interrupt request deassertion from peripheral to GIC happens
135 * by clearing interrupt condition by a write to the peripheral
136 * register. It is desired that the write transfer is complete
137 * before the core tries to change GIC state from 'AP/Active' to
138 * a new state on seeing 'EOI write'.
139 * Since ICC interface writes are not ordered against Device
140 * memory writes, a barrier is required to ensure the ordering.
141 * The dsb will also ensure *completion* of previous writes with
142 * DEVICE nGnRnE attribute.
143 */
144 __DSB();
145
146 /* (AP -> Pending) Or (Active -> Inactive) or (AP to AP) nested case */
147 write_sysreg(intid, ICC_EOIR1_EL1);
148 }
149
gic_raise_sgi(unsigned int sgi_id,uint64_t target_aff,uint16_t target_list)150 void gic_raise_sgi(unsigned int sgi_id, uint64_t target_aff,
151 uint16_t target_list)
152 {
153 uint32_t aff3, aff2, aff1;
154 uint64_t sgi_val;
155
156 __ASSERT_NO_MSG(GIC_IS_SGI(sgi_id));
157
158 /* Extract affinity fields from target */
159 aff1 = MPIDR_AFFLVL(target_aff, 1);
160 aff2 = MPIDR_AFFLVL(target_aff, 2);
161 aff3 = MPIDR_AFFLVL(target_aff, 3);
162
163 sgi_val = GICV3_SGIR_VALUE(aff3, aff2, aff1, sgi_id,
164 SGIR_IRM_TO_AFF, target_list);
165
166 __DSB();
167 write_sysreg(sgi_val, ICC_SGI1R);
168 __ISB();
169 }
170
171 /*
172 * Wake up GIC redistributor.
173 * clear ProcessorSleep and wait till ChildAsleep is cleared.
174 * ProcessSleep to be cleared only when ChildAsleep is set
175 * Check if redistributor is not powered already.
176 */
gicv3_rdist_enable(mem_addr_t rdist)177 static void gicv3_rdist_enable(mem_addr_t rdist)
178 {
179 if (!(sys_read32(rdist + GICR_WAKER) & BIT(GICR_WAKER_CA)))
180 return;
181
182 sys_clear_bit(rdist + GICR_WAKER, GICR_WAKER_PS);
183 while (sys_read32(rdist + GICR_WAKER) & BIT(GICR_WAKER_CA))
184 ;
185 }
186
187 /*
188 * Initialize the cpu interface. This should be called by each core.
189 */
gicv3_cpuif_init(void)190 static void gicv3_cpuif_init(void)
191 {
192 uint32_t icc_sre;
193 uint32_t intid;
194
195 mem_addr_t base = gic_get_rdist() + GICR_SGI_BASE_OFF;
196
197 /* Disable all sgi ppi */
198 sys_write32(BIT_MASK(GIC_NUM_INTR_PER_REG), ICENABLER(base, 0));
199 /* Any sgi/ppi intid ie. 0-31 will select GICR_CTRL */
200 gic_wait_rwp(0);
201
202 /* Clear pending */
203 sys_write32(BIT_MASK(GIC_NUM_INTR_PER_REG), ICPENDR(base, 0));
204
205 /* Configure all SGIs/PPIs as G1S or G1NS depending on Zephyr
206 * is run in EL1S or EL1NS respectively.
207 * All interrupts will be delivered as irq
208 */
209 sys_write32(IGROUPR_VAL, IGROUPR(base, 0));
210 sys_write32(BIT_MASK(GIC_NUM_INTR_PER_REG), IGROUPMODR(base, 0));
211
212 /*
213 * Configure default priorities for SGI 0:15 and PPI 0:15.
214 */
215 for (intid = 0; intid < GIC_SPI_INT_BASE;
216 intid += GIC_NUM_PRI_PER_REG) {
217 sys_write32(GIC_INT_DEF_PRI_X4, IPRIORITYR(base, intid));
218 }
219
220 /* Configure PPIs as level triggered */
221 sys_write32(0, ICFGR(base, 1));
222
223 /*
224 * Check if system interface can be enabled.
225 * 'icc_sre_el3' needs to be configured at 'EL3'
226 * to allow access to 'icc_sre_el1' at 'EL1'
227 * eg: z_arch_el3_plat_init can be used by platform.
228 */
229 icc_sre = read_sysreg(ICC_SRE_EL1);
230
231 if (!(icc_sre & ICC_SRE_ELx_SRE_BIT)) {
232 icc_sre = (icc_sre | ICC_SRE_ELx_SRE_BIT |
233 ICC_SRE_ELx_DIB_BIT | ICC_SRE_ELx_DFB_BIT);
234 write_sysreg(icc_sre, ICC_SRE_EL1);
235 icc_sre = read_sysreg(ICC_SRE_EL1);
236
237 __ASSERT_NO_MSG(icc_sre & ICC_SRE_ELx_SRE_BIT);
238 }
239
240 write_sysreg(GIC_IDLE_PRIO, ICC_PMR_EL1);
241
242 /* Allow group1 interrupts */
243 write_sysreg(1, ICC_IGRPEN1_EL1);
244 }
245
246 /*
247 * TODO: Consider Zephyr in EL1NS.
248 */
gicv3_dist_init(void)249 static void gicv3_dist_init(void)
250 {
251 unsigned int num_ints;
252 unsigned int intid;
253 unsigned int idx;
254 mem_addr_t base = GIC_DIST_BASE;
255
256 num_ints = sys_read32(GICD_TYPER);
257 num_ints &= GICD_TYPER_ITLINESNUM_MASK;
258 num_ints = (num_ints + 1) << 5;
259
260 /* Disable the distributor */
261 sys_write32(0, GICD_CTLR);
262 gic_wait_rwp(GIC_SPI_INT_BASE);
263 #ifdef CONFIG_GIC_SINGLE_SECURITY_STATE
264 /*
265 * Before configuration, we need to check whether
266 * the GIC single security state mode is supported.
267 * Make sure GICD_CTRL_NS is 1.
268 */
269 sys_set_bit(GICD_CTLR, GICD_CTRL_NS);
270 __ASSERT(sys_test_bit(GICD_CTLR, GICD_CTRL_NS),
271 "Current GIC does not support single security state");
272 #endif
273
274 /*
275 * Default configuration of all SPIs
276 */
277 for (intid = GIC_SPI_INT_BASE; intid < num_ints;
278 intid += GIC_NUM_INTR_PER_REG) {
279 idx = intid / GIC_NUM_INTR_PER_REG;
280 /* Disable interrupt */
281 sys_write32(BIT_MASK(GIC_NUM_INTR_PER_REG),
282 ICENABLER(base, idx));
283 /* Clear pending */
284 sys_write32(BIT_MASK(GIC_NUM_INTR_PER_REG),
285 ICPENDR(base, idx));
286 sys_write32(IGROUPR_VAL, IGROUPR(base, idx));
287 sys_write32(BIT_MASK(GIC_NUM_INTR_PER_REG),
288 IGROUPMODR(base, idx));
289
290 }
291 /* wait for rwp on GICD */
292 gic_wait_rwp(GIC_SPI_INT_BASE);
293
294 /* Configure default priorities for all SPIs. */
295 for (intid = GIC_SPI_INT_BASE; intid < num_ints;
296 intid += GIC_NUM_PRI_PER_REG) {
297 sys_write32(GIC_INT_DEF_PRI_X4, IPRIORITYR(base, intid));
298 }
299
300 /* Configure all SPIs as active low, level triggered by default */
301 for (intid = GIC_SPI_INT_BASE; intid < num_ints;
302 intid += GIC_NUM_CFG_PER_REG) {
303 idx = intid / GIC_NUM_CFG_PER_REG;
304 sys_write32(0, ICFGR(base, idx));
305 }
306
307 #ifdef CONFIG_ARMV8_A_NS
308 /* Enable distributor with ARE */
309 sys_write32(BIT(GICD_CTRL_ARE_NS) | BIT(GICD_CTLR_ENABLE_G1NS),
310 GICD_CTLR);
311 #elif defined(CONFIG_GIC_SINGLE_SECURITY_STATE)
312 /*
313 * For GIC single security state, the config GIC_SINGLE_SECURITY_STATE
314 * means the GIC is under single security state which has only two
315 * groups: group 0 and group 1.
316 * Then set GICD_CTLR_ARE and GICD_CTLR_ENABLE_G1 to enable Group 1
317 * interrupt.
318 * Since the GICD_CTLR_ARE and GICD_CTRL_ARE_S share BIT(4), and
319 * similarly the GICD_CTLR_ENABLE_G1 and GICD_CTLR_ENABLE_G1NS share
320 * BIT(1), we can reuse them.
321 */
322 sys_write32(BIT(GICD_CTRL_ARE_S) | BIT(GICD_CTLR_ENABLE_G1NS),
323 GICD_CTLR);
324 #else
325 /* enable Group 1 secure interrupts */
326 sys_set_bit(GICD_CTLR, GICD_CTLR_ENABLE_G1S);
327 #endif
328 }
329
__arm_gic_init(void)330 static void __arm_gic_init(void)
331 {
332 uint8_t cpu;
333
334 cpu = arch_curr_cpu()->id;
335 gic_rdists[cpu] = GIC_RDIST_BASE + MPIDR_TO_CORE(GET_MPIDR()) * 0x20000;
336
337 gicv3_rdist_enable(gic_get_rdist());
338
339 gicv3_cpuif_init();
340 }
341
arm_gic_init(const struct device * unused)342 int arm_gic_init(const struct device *unused)
343 {
344 ARG_UNUSED(unused);
345
346 gicv3_dist_init();
347
348 __arm_gic_init();
349
350 return 0;
351 }
352 SYS_INIT(arm_gic_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
353
354 #ifdef CONFIG_SMP
arm_gic_secondary_init(void)355 void arm_gic_secondary_init(void)
356 {
357 __arm_gic_init();
358 }
359 #endif
360