blob: c84a42c7e36329168ce1fb16b40257f33ddd49eb [file] [log] [blame]
Sandeep Tripathybd985dc2020-04-22 01:55:37 +05301/*
2 * Copyright 2020 Broadcom
Manuel Argüelles2786cb92024-08-05 21:16:25 +07003 * Copyright 2024 NXP
Sandeep Tripathybd985dc2020-04-22 01:55:37 +05304 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
Fabio Baltieri17ae9a72023-09-15 09:59:41 +00008#include <zephyr/device.h>
Huifeng Zhang12fa8332022-12-12 15:37:37 +08009#include <zephyr/kernel.h>
Gerard Marull-Paretas34a68482022-10-04 15:44:11 +020010#include <zephyr/arch/cpu.h>
Gerard Marull-Paretasfb60aab2022-05-06 10:25:46 +020011#include <zephyr/sys/__assert.h>
12#include <zephyr/sw_isr_table.h>
13#include <zephyr/dt-bindings/interrupt-controller/arm-gic.h>
14#include <zephyr/drivers/interrupt_controller/gic.h>
Carlo Caionecb11b2e2023-05-02 11:24:50 +020015#include <zephyr/sys/barrier.h>
Sandeep Tripathybd985dc2020-04-22 01:55:37 +053016#include "intc_gic_common_priv.h"
17#include "intc_gicv3_priv.h"
18
Neil Armstronge819bd82021-08-06 16:28:48 +020019#include <string.h>
20
Fabio Baltieri17ae9a72023-09-15 09:59:41 +000021#define DT_DRV_COMPAT arm_gic_v3
22
Sandeep Tripathybd985dc2020-04-22 01:55:37 +053023/* Redistributor base addresses for each core */
Kumar Galac778eb22022-10-12 10:55:36 -050024mem_addr_t gic_rdists[CONFIG_MP_MAX_NUM_CPUS];
Sandeep Tripathybd985dc2020-04-22 01:55:37 +053025
Jaxson Han36006ed2020-11-24 15:07:23 +080026#if defined(CONFIG_ARMV8_A_NS) || defined(CONFIG_GIC_SINGLE_SECURITY_STATE)
Peng Fan4deba262020-11-03 10:08:26 +080027#define IGROUPR_VAL 0xFFFFFFFFU
28#else
29#define IGROUPR_VAL 0x0U
30#endif
Jiafei Pan77da0352021-04-23 17:07:17 +080031
Neil Armstronge819bd82021-08-06 16:28:48 +020032/*
33 * We allocate memory for PROPBASE to cover 2 ^ lpi_id_bits LPIs to
34 * deal with (one configuration byte per interrupt). PENDBASE has to
35 * be 64kB aligned (one bit per LPI, plus 8192 bits for SPI/PPI/SGI).
36 */
37#define ITS_MAX_LPI_NRBITS 16 /* 64K LPIs */
38
39#define LPI_PROPBASE_SZ(nrbits) ROUND_UP(BIT(nrbits), KB(64))
40#define LPI_PENDBASE_SZ(nrbits) ROUND_UP(BIT(nrbits) / 8, KB(64))
41
42#ifdef CONFIG_GIC_V3_ITS
43static uintptr_t lpi_prop_table;
Neil Armstronga7379992021-08-06 16:32:53 +020044
45atomic_t nlpi_intid = ATOMIC_INIT(8192);
Neil Armstronge819bd82021-08-06 16:28:48 +020046#endif
47
Jiafei Pan77da0352021-04-23 17:07:17 +080048static inline mem_addr_t gic_get_rdist(void)
49{
50 return gic_rdists[arch_curr_cpu()->id];
51}
52
Sandeep Tripathybd985dc2020-04-22 01:55:37 +053053/*
54 * Wait for register write pending
55 * TODO: add timed wait
56 */
Kumar Galaa1b77fd2020-05-27 11:26:57 -050057static int gic_wait_rwp(uint32_t intid)
Sandeep Tripathybd985dc2020-04-22 01:55:37 +053058{
Kumar Galaa1b77fd2020-05-27 11:26:57 -050059 uint32_t rwp_mask;
Sandeep Tripathybd985dc2020-04-22 01:55:37 +053060 mem_addr_t base;
61
62 if (intid < GIC_SPI_INT_BASE) {
Jiafei Pan77da0352021-04-23 17:07:17 +080063 base = (gic_get_rdist() + GICR_CTLR);
Sandeep Tripathybd985dc2020-04-22 01:55:37 +053064 rwp_mask = BIT(GICR_CTLR_RWP);
65 } else {
66 base = GICD_CTLR;
67 rwp_mask = BIT(GICD_CTLR_RWP);
68 }
69
Anas Nashif49b36ea2022-07-06 07:34:50 -040070 while (sys_read32(base) & rwp_mask) {
Sandeep Tripathybd985dc2020-04-22 01:55:37 +053071 ;
Anas Nashif49b36ea2022-07-06 07:34:50 -040072 }
Sandeep Tripathybd985dc2020-04-22 01:55:37 +053073
74 return 0;
75}
76
Neil Armstronge819bd82021-08-06 16:28:48 +020077#ifdef CONFIG_GIC_V3_ITS
78static void arm_gic_lpi_setup(unsigned int intid, bool enable)
79{
80 uint8_t *cfg = &((uint8_t *)lpi_prop_table)[intid - 8192];
81
82 if (enable) {
83 *cfg |= BIT(0);
84 } else {
85 *cfg &= ~BIT(0);
86 }
87
Carlo Caionecb11b2e2023-05-02 11:24:50 +020088 barrier_dsync_fence_full();
Neil Armstronga7379992021-08-06 16:32:53 +020089
90 its_rdist_invall();
Neil Armstronge819bd82021-08-06 16:28:48 +020091}
92
93static void arm_gic_lpi_set_priority(unsigned int intid, unsigned int prio)
94{
95 uint8_t *cfg = &((uint8_t *)lpi_prop_table)[intid - 8192];
96
97 *cfg &= 0xfc;
98 *cfg |= prio & 0xfc;
99
Carlo Caionecb11b2e2023-05-02 11:24:50 +0200100 barrier_dsync_fence_full();
Neil Armstronga7379992021-08-06 16:32:53 +0200101
102 its_rdist_invall();
Neil Armstronge819bd82021-08-06 16:28:48 +0200103}
104
105static bool arm_gic_lpi_is_enabled(unsigned int intid)
106{
107 uint8_t *cfg = &((uint8_t *)lpi_prop_table)[intid - 8192];
108
109 return (*cfg & BIT(0));
110}
111#endif
112
Dat Nguyen Duyeb0428a2022-06-17 21:44:40 +0700113#if defined(CONFIG_ARMV8_A_NS) || defined(CONFIG_GIC_SINGLE_SECURITY_STATE)
114static inline void arm_gic_write_irouter(uint64_t val, unsigned int intid)
115{
116 mem_addr_t addr = IROUTER(GET_DIST_BASE(intid), intid);
117
118#ifdef CONFIG_ARM
119 sys_write32((uint32_t)val, addr);
120 sys_write32((uint32_t)(val >> 32U), addr + 4);
121#else
122 sys_write64(val, addr);
123#endif
124}
125#endif
126
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530127void arm_gic_irq_set_priority(unsigned int intid,
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500128 unsigned int prio, uint32_t flags)
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530129{
Neil Armstronge819bd82021-08-06 16:28:48 +0200130#ifdef CONFIG_GIC_V3_ITS
131 if (intid >= 8192) {
132 arm_gic_lpi_set_priority(intid, prio);
133 return;
134 }
135#endif
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500136 uint32_t mask = BIT(intid & (GIC_NUM_INTR_PER_REG - 1));
137 uint32_t idx = intid / GIC_NUM_INTR_PER_REG;
138 uint32_t shift;
139 uint32_t val;
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530140 mem_addr_t base = GET_DIST_BASE(intid);
141
142 /* Disable the interrupt */
143 sys_write32(mask, ICENABLER(base, idx));
144 gic_wait_rwp(intid);
145
146 /* PRIORITYR registers provide byte access */
147 sys_write8(prio & GIC_PRI_MASK, IPRIORITYR(base, intid));
148
149 /* Interrupt type config */
Sandeep Tripathy2e42a702020-06-12 20:33:53 +0530150 if (!GIC_IS_SGI(intid)) {
151 idx = intid / GIC_NUM_CFG_PER_REG;
152 shift = (intid & (GIC_NUM_CFG_PER_REG - 1)) * 2;
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530153
Sandeep Tripathy2e42a702020-06-12 20:33:53 +0530154 val = sys_read32(ICFGR(base, idx));
155 val &= ~(GICD_ICFGR_MASK << shift);
156 if (flags & IRQ_TYPE_EDGE) {
157 val |= (GICD_ICFGR_TYPE << shift);
158 }
159 sys_write32(val, ICFGR(base, idx));
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530160 }
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530161}
162
163void arm_gic_irq_enable(unsigned int intid)
164{
Neil Armstronge819bd82021-08-06 16:28:48 +0200165#ifdef CONFIG_GIC_V3_ITS
166 if (intid >= 8192) {
167 arm_gic_lpi_setup(intid, true);
168 return;
169 }
170#endif
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500171 uint32_t mask = BIT(intid & (GIC_NUM_INTR_PER_REG - 1));
172 uint32_t idx = intid / GIC_NUM_INTR_PER_REG;
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530173
Dat Nguyen Duyeb0428a2022-06-17 21:44:40 +0700174#if defined(CONFIG_ARMV8_A_NS) || defined(CONFIG_GIC_SINGLE_SECURITY_STATE)
Jiafei Pan6f1dc5d2021-09-03 17:05:57 +0800175 /*
Dat Nguyen Duyeb0428a2022-06-17 21:44:40 +0700176 * Affinity routing is enabled for Armv8-A Non-secure state (GICD_CTLR.ARE_NS
177 * is set to '1') and for GIC single security state (GICD_CTRL.ARE is set to '1'),
178 * so need to set SPI's affinity, now set it to be the PE on which it is enabled.
Jiafei Pan6f1dc5d2021-09-03 17:05:57 +0800179 */
Dat Nguyen Duyeb0428a2022-06-17 21:44:40 +0700180 if (GIC_IS_SPI(intid)) {
181 arm_gic_write_irouter(MPIDR_TO_CORE(GET_MPIDR()), intid);
182 }
Jiafei Pan6f1dc5d2021-09-03 17:05:57 +0800183#endif
chao an5831d912024-09-02 12:31:10 +0800184
185 sys_write32(mask, ISENABLER(GET_DIST_BASE(intid), idx));
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530186}
187
188void arm_gic_irq_disable(unsigned int intid)
189{
Neil Armstronge819bd82021-08-06 16:28:48 +0200190#ifdef CONFIG_GIC_V3_ITS
191 if (intid >= 8192) {
192 arm_gic_lpi_setup(intid, false);
193 return;
194 }
195#endif
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500196 uint32_t mask = BIT(intid & (GIC_NUM_INTR_PER_REG - 1));
197 uint32_t idx = intid / GIC_NUM_INTR_PER_REG;
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530198
199 sys_write32(mask, ICENABLER(GET_DIST_BASE(intid), idx));
200 /* poll to ensure write is complete */
201 gic_wait_rwp(intid);
202}
203
204bool arm_gic_irq_is_enabled(unsigned int intid)
205{
Neil Armstronge819bd82021-08-06 16:28:48 +0200206#ifdef CONFIG_GIC_V3_ITS
207 if (intid >= 8192) {
208 return arm_gic_lpi_is_enabled(intid);
209 }
210#endif
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500211 uint32_t mask = BIT(intid & (GIC_NUM_INTR_PER_REG - 1));
212 uint32_t idx = intid / GIC_NUM_INTR_PER_REG;
213 uint32_t val;
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530214
215 val = sys_read32(ISENABLER(GET_DIST_BASE(intid), idx));
216
217 return (val & mask) != 0;
218}
219
Jaxson Han894f1b12023-05-23 15:59:58 +0800220bool arm_gic_irq_is_pending(unsigned int intid)
221{
222 uint32_t mask = BIT(intid & (GIC_NUM_INTR_PER_REG - 1));
223 uint32_t idx = intid / GIC_NUM_INTR_PER_REG;
224 uint32_t val;
225
226 val = sys_read32(ISPENDR(GET_DIST_BASE(intid), idx));
227
228 return (val & mask) != 0;
229}
230
Manuel Argüelles2786cb92024-08-05 21:16:25 +0700231void arm_gic_irq_set_pending(unsigned int intid)
232{
233 uint32_t mask = BIT(intid & (GIC_NUM_INTR_PER_REG - 1));
234 uint32_t idx = intid / GIC_NUM_INTR_PER_REG;
235
236 sys_write32(mask, ISPENDR(GET_DIST_BASE(intid), idx));
237}
238
Jaxson Han894f1b12023-05-23 15:59:58 +0800239void arm_gic_irq_clear_pending(unsigned int intid)
240{
241 uint32_t mask = BIT(intid & (GIC_NUM_INTR_PER_REG - 1));
242 uint32_t idx = intid / GIC_NUM_INTR_PER_REG;
243
244 sys_write32(mask, ICPENDR(GET_DIST_BASE(intid), idx));
245}
246
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530247unsigned int arm_gic_get_active(void)
248{
249 int intid;
250
251 /* (Pending -> Active / AP) or (AP -> AP) */
252 intid = read_sysreg(ICC_IAR1_EL1);
253
254 return intid;
255}
256
257void arm_gic_eoi(unsigned int intid)
258{
Sandeep Tripathyccb4b1e2020-06-26 17:50:14 +0530259 /*
260 * Interrupt request deassertion from peripheral to GIC happens
261 * by clearing interrupt condition by a write to the peripheral
262 * register. It is desired that the write transfer is complete
263 * before the core tries to change GIC state from 'AP/Active' to
264 * a new state on seeing 'EOI write'.
265 * Since ICC interface writes are not ordered against Device
266 * memory writes, a barrier is required to ensure the ordering.
267 * The dsb will also ensure *completion* of previous writes with
268 * DEVICE nGnRnE attribute.
269 */
Carlo Caionecb11b2e2023-05-02 11:24:50 +0200270 barrier_dsync_fence_full();
Sandeep Tripathyccb4b1e2020-06-26 17:50:14 +0530271
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530272 /* (AP -> Pending) Or (Active -> Inactive) or (AP to AP) nested case */
273 write_sysreg(intid, ICC_EOIR1_EL1);
274}
275
Sandeep Tripathy8aa02482020-06-12 17:31:09 +0530276void gic_raise_sgi(unsigned int sgi_id, uint64_t target_aff,
277 uint16_t target_list)
278{
279 uint32_t aff3, aff2, aff1;
280 uint64_t sgi_val;
281
Xavier Chapron824f4232020-09-22 14:42:43 +0200282 __ASSERT_NO_MSG(GIC_IS_SGI(sgi_id));
Sandeep Tripathy8aa02482020-06-12 17:31:09 +0530283
284 /* Extract affinity fields from target */
285 aff1 = MPIDR_AFFLVL(target_aff, 1);
286 aff2 = MPIDR_AFFLVL(target_aff, 2);
Julien Massotdd74db42022-01-27 14:37:41 +0100287#if defined(CONFIG_ARM)
288 /* There is no Aff3 in AArch32 MPIDR */
289 aff3 = 0;
290#else
Sandeep Tripathy8aa02482020-06-12 17:31:09 +0530291 aff3 = MPIDR_AFFLVL(target_aff, 3);
Julien Massotdd74db42022-01-27 14:37:41 +0100292#endif
Sandeep Tripathy8aa02482020-06-12 17:31:09 +0530293 sgi_val = GICV3_SGIR_VALUE(aff3, aff2, aff1, sgi_id,
294 SGIR_IRM_TO_AFF, target_list);
295
Carlo Caionecb11b2e2023-05-02 11:24:50 +0200296 barrier_dsync_fence_full();
Sandeep Tripathy8aa02482020-06-12 17:31:09 +0530297 write_sysreg(sgi_val, ICC_SGI1R);
Carlo Caione6f3a13d2023-05-02 12:48:53 +0200298 barrier_isync_fence_full();
Sandeep Tripathy8aa02482020-06-12 17:31:09 +0530299}
300
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530301/*
302 * Wake up GIC redistributor.
303 * clear ProcessorSleep and wait till ChildAsleep is cleared.
304 * ProcessSleep to be cleared only when ChildAsleep is set
305 * Check if redistributor is not powered already.
306 */
307static void gicv3_rdist_enable(mem_addr_t rdist)
308{
Anas Nashif49b36ea2022-07-06 07:34:50 -0400309 if (!(sys_read32(rdist + GICR_WAKER) & BIT(GICR_WAKER_CA))) {
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530310 return;
Anas Nashif49b36ea2022-07-06 07:34:50 -0400311 }
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530312
Chad Karaginides47ffe572023-08-30 14:37:54 -0700313 if (GICR_IIDR_PRODUCT_ID_GET(sys_read32(rdist + GICR_IIDR)) >= 0x2) {
314 if (sys_read32(rdist + GICR_PWRR) & BIT(GICR_PWRR_RDPD)) {
315 sys_set_bit(rdist + GICR_PWRR, GICR_PWRR_RDAG);
316 sys_clear_bit(rdist + GICR_PWRR, GICR_PWRR_RDPD);
317 while (sys_read32(rdist + GICR_PWRR) & BIT(GICR_PWRR_RDPD)) {
318 ;
319 }
320 }
321 }
322
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530323 sys_clear_bit(rdist + GICR_WAKER, GICR_WAKER_PS);
Anas Nashif49b36ea2022-07-06 07:34:50 -0400324 while (sys_read32(rdist + GICR_WAKER) & BIT(GICR_WAKER_CA)) {
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530325 ;
Anas Nashif49b36ea2022-07-06 07:34:50 -0400326 }
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530327}
328
Neil Armstronge819bd82021-08-06 16:28:48 +0200329#ifdef CONFIG_GIC_V3_ITS
330/*
331 * Setup LPIs Configuration & Pending tables for redistributors
332 * LPI configuration is global, each redistributor has a pending table
333 */
334static void gicv3_rdist_setup_lpis(mem_addr_t rdist)
335{
336 unsigned int lpi_id_bits = MIN(GICD_TYPER_IDBITS(sys_read32(GICD_TYPER)),
337 ITS_MAX_LPI_NRBITS);
338 uintptr_t lpi_pend_table;
339 uint64_t reg;
340 uint32_t ctlr;
341
342 /* If not, alloc a common prop table for all redistributors */
343 if (!lpi_prop_table) {
344 lpi_prop_table = (uintptr_t)k_aligned_alloc(4 * 1024, LPI_PROPBASE_SZ(lpi_id_bits));
345 memset((void *)lpi_prop_table, 0, LPI_PROPBASE_SZ(lpi_id_bits));
346 }
347
348 lpi_pend_table = (uintptr_t)k_aligned_alloc(64 * 1024, LPI_PENDBASE_SZ(lpi_id_bits));
349 memset((void *)lpi_pend_table, 0, LPI_PENDBASE_SZ(lpi_id_bits));
350
351 ctlr = sys_read32(rdist + GICR_CTLR);
352 ctlr &= ~GICR_CTLR_ENABLE_LPIS;
353 sys_write32(ctlr, rdist + GICR_CTLR);
354
355 /* PROPBASE */
356 reg = (GIC_BASER_SHARE_INNER << GITR_PROPBASER_SHAREABILITY_SHIFT) |
357 (GIC_BASER_CACHE_RAWAWB << GITR_PROPBASER_INNER_CACHE_SHIFT) |
358 (lpi_prop_table & (GITR_PROPBASER_ADDR_MASK << GITR_PROPBASER_ADDR_SHIFT)) |
359 (GIC_BASER_CACHE_INNERLIKE << GITR_PROPBASER_OUTER_CACHE_SHIFT) |
360 ((lpi_id_bits - 1) & GITR_PROPBASER_ID_BITS_MASK);
361 sys_write64(reg, rdist + GICR_PROPBASER);
362 /* TOFIX: check SHAREABILITY validity */
363
364 /* PENDBASE */
365 reg = (GIC_BASER_SHARE_INNER << GITR_PENDBASER_SHAREABILITY_SHIFT) |
366 (GIC_BASER_CACHE_RAWAWB << GITR_PENDBASER_INNER_CACHE_SHIFT) |
367 (lpi_pend_table & (GITR_PENDBASER_ADDR_MASK << GITR_PENDBASER_ADDR_SHIFT)) |
368 (GIC_BASER_CACHE_INNERLIKE << GITR_PENDBASER_OUTER_CACHE_SHIFT) |
369 GITR_PENDBASER_PTZ;
370 sys_write64(reg, rdist + GICR_PENDBASER);
371 /* TOFIX: check SHAREABILITY validity */
372
373 ctlr = sys_read32(rdist + GICR_CTLR);
374 ctlr |= GICR_CTLR_ENABLE_LPIS;
375 sys_write32(ctlr, rdist + GICR_CTLR);
376
Carlo Caionecb11b2e2023-05-02 11:24:50 +0200377 barrier_dsync_fence_full();
Neil Armstronge819bd82021-08-06 16:28:48 +0200378}
379#endif
380
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530381/*
382 * Initialize the cpu interface. This should be called by each core.
383 */
384static void gicv3_cpuif_init(void)
385{
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500386 uint32_t icc_sre;
387 uint32_t intid;
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530388
Jiafei Pan77da0352021-04-23 17:07:17 +0800389 mem_addr_t base = gic_get_rdist() + GICR_SGI_BASE_OFF;
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530390
391 /* Disable all sgi ppi */
Julien Massot03dffa52022-03-09 10:03:34 +0100392 sys_write32(BIT64_MASK(GIC_NUM_INTR_PER_REG), ICENABLER(base, 0));
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530393 /* Any sgi/ppi intid ie. 0-31 will select GICR_CTRL */
394 gic_wait_rwp(0);
395
396 /* Clear pending */
Julien Massot03dffa52022-03-09 10:03:34 +0100397 sys_write32(BIT64_MASK(GIC_NUM_INTR_PER_REG), ICPENDR(base, 0));
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530398
Peng Fan4deba262020-11-03 10:08:26 +0800399 /* Configure all SGIs/PPIs as G1S or G1NS depending on Zephyr
400 * is run in EL1S or EL1NS respectively.
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530401 * All interrupts will be delivered as irq
402 */
Peng Fan4deba262020-11-03 10:08:26 +0800403 sys_write32(IGROUPR_VAL, IGROUPR(base, 0));
Julien Massot03dffa52022-03-09 10:03:34 +0100404 sys_write32(BIT64_MASK(GIC_NUM_INTR_PER_REG), IGROUPMODR(base, 0));
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530405
406 /*
407 * Configure default priorities for SGI 0:15 and PPI 0:15.
408 */
409 for (intid = 0; intid < GIC_SPI_INT_BASE;
410 intid += GIC_NUM_PRI_PER_REG) {
411 sys_write32(GIC_INT_DEF_PRI_X4, IPRIORITYR(base, intid));
412 }
413
414 /* Configure PPIs as level triggered */
415 sys_write32(0, ICFGR(base, 1));
416
417 /*
418 * Check if system interface can be enabled.
419 * 'icc_sre_el3' needs to be configured at 'EL3'
420 * to allow access to 'icc_sre_el1' at 'EL1'
421 * eg: z_arch_el3_plat_init can be used by platform.
422 */
423 icc_sre = read_sysreg(ICC_SRE_EL1);
424
Carlo Caionea2226f52021-02-11 15:22:04 +0100425 if (!(icc_sre & ICC_SRE_ELx_SRE_BIT)) {
426 icc_sre = (icc_sre | ICC_SRE_ELx_SRE_BIT |
427 ICC_SRE_ELx_DIB_BIT | ICC_SRE_ELx_DFB_BIT);
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530428 write_sysreg(icc_sre, ICC_SRE_EL1);
429 icc_sre = read_sysreg(ICC_SRE_EL1);
430
Carlo Caionea2226f52021-02-11 15:22:04 +0100431 __ASSERT_NO_MSG(icc_sre & ICC_SRE_ELx_SRE_BIT);
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530432 }
433
434 write_sysreg(GIC_IDLE_PRIO, ICC_PMR_EL1);
435
436 /* Allow group1 interrupts */
437 write_sysreg(1, ICC_IGRPEN1_EL1);
438}
439
440/*
441 * TODO: Consider Zephyr in EL1NS.
442 */
443static void gicv3_dist_init(void)
444{
445 unsigned int num_ints;
446 unsigned int intid;
447 unsigned int idx;
448 mem_addr_t base = GIC_DIST_BASE;
449
Jiafei Pan0f6d6b22024-09-27 18:39:19 +0800450#ifdef CONFIG_GIC_SAFE_CONFIG
451 /*
452 * Currently multiple OSes can run one the different CPU Cores which share single GIC,
453 * but GIC distributor should avoid to be re-configured in order to avoid crash the
454 * OSes has already been started.
455 */
456 if (sys_read32(GICD_CTLR) & (BIT(GICD_CTLR_ENABLE_G0) | BIT(GICD_CTLR_ENABLE_G1NS))) {
457 return;
458 }
459#endif
460
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530461 num_ints = sys_read32(GICD_TYPER);
462 num_ints &= GICD_TYPER_ITLINESNUM_MASK;
463 num_ints = (num_ints + 1) << 5;
464
Peng Fan4deba262020-11-03 10:08:26 +0800465 /* Disable the distributor */
466 sys_write32(0, GICD_CTLR);
467 gic_wait_rwp(GIC_SPI_INT_BASE);
Jaxson Han36006ed2020-11-24 15:07:23 +0800468#ifdef CONFIG_GIC_SINGLE_SECURITY_STATE
469 /*
470 * Before configuration, we need to check whether
471 * the GIC single security state mode is supported.
472 * Make sure GICD_CTRL_NS is 1.
473 */
474 sys_set_bit(GICD_CTLR, GICD_CTRL_NS);
475 __ASSERT(sys_test_bit(GICD_CTLR, GICD_CTRL_NS),
476 "Current GIC does not support single security state");
477#endif
Peng Fan4deba262020-11-03 10:08:26 +0800478
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530479 /*
480 * Default configuration of all SPIs
481 */
482 for (intid = GIC_SPI_INT_BASE; intid < num_ints;
483 intid += GIC_NUM_INTR_PER_REG) {
484 idx = intid / GIC_NUM_INTR_PER_REG;
485 /* Disable interrupt */
Julien Massot03dffa52022-03-09 10:03:34 +0100486 sys_write32(BIT64_MASK(GIC_NUM_INTR_PER_REG),
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530487 ICENABLER(base, idx));
488 /* Clear pending */
Julien Massot03dffa52022-03-09 10:03:34 +0100489 sys_write32(BIT64_MASK(GIC_NUM_INTR_PER_REG),
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530490 ICPENDR(base, idx));
Peng Fan4deba262020-11-03 10:08:26 +0800491 sys_write32(IGROUPR_VAL, IGROUPR(base, idx));
Julien Massot03dffa52022-03-09 10:03:34 +0100492 sys_write32(BIT64_MASK(GIC_NUM_INTR_PER_REG),
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530493 IGROUPMODR(base, idx));
494
495 }
496 /* wait for rwp on GICD */
497 gic_wait_rwp(GIC_SPI_INT_BASE);
498
499 /* Configure default priorities for all SPIs. */
500 for (intid = GIC_SPI_INT_BASE; intid < num_ints;
501 intid += GIC_NUM_PRI_PER_REG) {
502 sys_write32(GIC_INT_DEF_PRI_X4, IPRIORITYR(base, intid));
503 }
504
505 /* Configure all SPIs as active low, level triggered by default */
506 for (intid = GIC_SPI_INT_BASE; intid < num_ints;
507 intid += GIC_NUM_CFG_PER_REG) {
508 idx = intid / GIC_NUM_CFG_PER_REG;
509 sys_write32(0, ICFGR(base, idx));
510 }
511
Peng Fan4deba262020-11-03 10:08:26 +0800512#ifdef CONFIG_ARMV8_A_NS
513 /* Enable distributor with ARE */
514 sys_write32(BIT(GICD_CTRL_ARE_NS) | BIT(GICD_CTLR_ENABLE_G1NS),
515 GICD_CTLR);
Jaxson Han36006ed2020-11-24 15:07:23 +0800516#elif defined(CONFIG_GIC_SINGLE_SECURITY_STATE)
517 /*
518 * For GIC single security state, the config GIC_SINGLE_SECURITY_STATE
519 * means the GIC is under single security state which has only two
520 * groups: group 0 and group 1.
521 * Then set GICD_CTLR_ARE and GICD_CTLR_ENABLE_G1 to enable Group 1
522 * interrupt.
523 * Since the GICD_CTLR_ARE and GICD_CTRL_ARE_S share BIT(4), and
524 * similarly the GICD_CTLR_ENABLE_G1 and GICD_CTLR_ENABLE_G1NS share
525 * BIT(1), we can reuse them.
526 */
527 sys_write32(BIT(GICD_CTRL_ARE_S) | BIT(GICD_CTLR_ENABLE_G1NS),
528 GICD_CTLR);
Peng Fan4deba262020-11-03 10:08:26 +0800529#else
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530530 /* enable Group 1 secure interrupts */
531 sys_set_bit(GICD_CTLR, GICD_CTLR_ENABLE_G1S);
Peng Fan4deba262020-11-03 10:08:26 +0800532#endif
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530533}
534
Huifeng Zhang68b10e82022-07-05 13:12:12 +0800535static uint64_t arm_gic_mpidr_to_affinity(uint64_t mpidr)
536{
537 uint64_t aff3, aff2, aff1, aff0;
538
539#if defined(CONFIG_ARM)
540 /* There is no Aff3 in AArch32 MPIDR */
541 aff3 = 0;
542#else
543 aff3 = MPIDR_AFFLVL(mpidr, 3);
544#endif
545
546 aff2 = MPIDR_AFFLVL(mpidr, 2);
547 aff1 = MPIDR_AFFLVL(mpidr, 1);
548 aff0 = MPIDR_AFFLVL(mpidr, 0);
549
550 return (aff3 << 24 | aff2 << 16 | aff1 << 8 | aff0);
551}
552
Jaxson Hanf11e6d92022-09-21 14:50:17 +0800553static bool arm_gic_aff_matching(uint64_t gicr_aff, uint64_t aff)
554{
555#if defined(CONFIG_GIC_V3_RDIST_MATCHING_AFF0_ONLY)
556 uint64_t mask = BIT64_MASK(8);
557
558 return (gicr_aff & mask) == (aff & mask);
559#else
560 return gicr_aff == aff;
561#endif
562}
563
Ayan Kumar Halder21745012022-10-27 11:46:15 +0100564static inline uint64_t arm_gic_get_typer(mem_addr_t addr)
565{
566 uint64_t val;
567
568#if defined(CONFIG_ARM)
569 val = sys_read32(addr);
570 val |= (uint64_t)sys_read32(addr + 4) << 32;
571#else
572 val = sys_read64(addr);
573#endif
574
575 return val;
576}
577
Huifeng Zhang68b10e82022-07-05 13:12:12 +0800578static mem_addr_t arm_gic_iterate_rdists(void)
579{
580 uint64_t aff = arm_gic_mpidr_to_affinity(GET_MPIDR());
581
582 for (mem_addr_t rdist_addr = GIC_RDIST_BASE;
583 rdist_addr < GIC_RDIST_BASE + GIC_RDIST_SIZE;
584 rdist_addr += 0x20000) {
Ayan Kumar Halder21745012022-10-27 11:46:15 +0100585 uint64_t val = arm_gic_get_typer(rdist_addr + GICR_TYPER);
Jaxson Hanf11e6d92022-09-21 14:50:17 +0800586 uint64_t gicr_aff = GICR_TYPER_AFFINITY_VALUE_GET(val);
Huifeng Zhang68b10e82022-07-05 13:12:12 +0800587
Jaxson Hanf11e6d92022-09-21 14:50:17 +0800588 if (arm_gic_aff_matching(gicr_aff, aff)) {
Huifeng Zhang68b10e82022-07-05 13:12:12 +0800589 return rdist_addr;
590 }
591
592 if (GICR_TYPER_LAST_GET(val) == 1) {
593 return (mem_addr_t)NULL;
594 }
595 }
596
597 return (mem_addr_t)NULL;
598}
599
Jiafei Pan77da0352021-04-23 17:07:17 +0800600static void __arm_gic_init(void)
601{
602 uint8_t cpu;
Huifeng Zhang68b10e82022-07-05 13:12:12 +0800603 mem_addr_t gic_rd_base;
Jiafei Pan77da0352021-04-23 17:07:17 +0800604
605 cpu = arch_curr_cpu()->id;
Huifeng Zhang68b10e82022-07-05 13:12:12 +0800606 gic_rd_base = arm_gic_iterate_rdists();
607 __ASSERT(gic_rd_base != (mem_addr_t)NULL, "");
608
609 gic_rdists[cpu] = gic_rd_base;
Jiafei Pan77da0352021-04-23 17:07:17 +0800610
Neil Armstronge819bd82021-08-06 16:28:48 +0200611#ifdef CONFIG_GIC_V3_ITS
612 /* Enable LPIs in Redistributor */
613 gicv3_rdist_setup_lpis(gic_get_rdist());
614#endif
615
Jiafei Pan77da0352021-04-23 17:07:17 +0800616 gicv3_rdist_enable(gic_get_rdist());
617
618 gicv3_cpuif_init();
619}
620
Fabio Baltieri17ae9a72023-09-15 09:59:41 +0000621int arm_gic_init(const struct device *dev)
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530622{
623 gicv3_dist_init();
624
Jiafei Pan77da0352021-04-23 17:07:17 +0800625 __arm_gic_init();
Sandeep Tripathybd985dc2020-04-22 01:55:37 +0530626
627 return 0;
628}
Fabio Baltieri17ae9a72023-09-15 09:59:41 +0000629DEVICE_DT_INST_DEFINE(0, arm_gic_init, NULL, NULL, NULL,
630 PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, NULL);
Peng Fan5c1c5bb2020-11-09 15:46:55 +0800631
632#ifdef CONFIG_SMP
633void arm_gic_secondary_init(void)
634{
Jiafei Pan77da0352021-04-23 17:07:17 +0800635 __arm_gic_init();
Neil Armstronga7379992021-08-06 16:32:53 +0200636
637#ifdef CONFIG_GIC_V3_ITS
638 /* Map this CPU Redistributor in all the ITS Collection tables */
639 its_rdist_map();
640#endif
Peng Fan5c1c5bb2020-11-09 15:46:55 +0800641}
642#endif