1 /*
2 * Copyright (c) 2018 Marvell
3 * Copyright (c) 2018 Lexmark International, Inc.
4 * Copyright (c) 2019 Stephanos Ioannidis <root@stephanos.io>
5 * Copyright 2024 NXP
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9
10 /*
11 * NOTE: This driver implements the GICv1 and GICv2 interfaces.
12 */
13
14 #include <zephyr/device.h>
15 #include <zephyr/arch/cpu.h>
16 #include <zephyr/devicetree.h>
17 #include <zephyr/sw_isr_table.h>
18 #include <zephyr/dt-bindings/interrupt-controller/arm-gic.h>
19 #include <zephyr/drivers/interrupt_controller/gic.h>
20 #include <zephyr/sys/barrier.h>
21
22 #if defined(CONFIG_GIC_V1)
23 #define DT_DRV_COMPAT arm_gic_v1
24 #elif defined(CONFIG_GIC_V2)
25 #define DT_DRV_COMPAT arm_gic_v2
26 #else
27 #error "Unknown GIC controller compatible for this configuration"
28 #endif
29
30 static const uint64_t cpu_mpid_list[] = {
31 DT_FOREACH_CHILD_STATUS_OKAY_SEP(DT_PATH(cpus), DT_REG_ADDR, (,))
32 };
33
34 BUILD_ASSERT(ARRAY_SIZE(cpu_mpid_list) >= CONFIG_MP_MAX_NUM_CPUS,
35 "The count of CPU Cores nodes in dts is less than CONFIG_MP_MAX_NUM_CPUS\n");
36
arm_gic_irq_enable(unsigned int irq)37 void arm_gic_irq_enable(unsigned int irq)
38 {
39 int int_grp, int_off;
40
41 int_grp = irq / 32;
42 int_off = irq % 32;
43
44 sys_write32((1 << int_off), (GICD_ISENABLERn + int_grp * 4));
45 }
46
arm_gic_irq_disable(unsigned int irq)47 void arm_gic_irq_disable(unsigned int irq)
48 {
49 int int_grp, int_off;
50
51 int_grp = irq / 32;
52 int_off = irq % 32;
53
54 sys_write32((1 << int_off), (GICD_ICENABLERn + int_grp * 4));
55 }
56
arm_gic_irq_is_enabled(unsigned int irq)57 bool arm_gic_irq_is_enabled(unsigned int irq)
58 {
59 int int_grp, int_off;
60 unsigned int enabler;
61
62 int_grp = irq / 32;
63 int_off = irq % 32;
64
65 enabler = sys_read32(GICD_ISENABLERn + int_grp * 4);
66
67 return (enabler & (1 << int_off)) != 0;
68 }
69
arm_gic_irq_is_pending(unsigned int irq)70 bool arm_gic_irq_is_pending(unsigned int irq)
71 {
72 int int_grp, int_off;
73 unsigned int enabler;
74
75 int_grp = irq / 32;
76 int_off = irq % 32;
77
78 enabler = sys_read32(GICD_ISPENDRn + int_grp * 4);
79
80 return (enabler & (1 << int_off)) != 0;
81 }
82
arm_gic_irq_set_pending(unsigned int irq)83 void arm_gic_irq_set_pending(unsigned int irq)
84 {
85 int int_grp, int_off;
86
87 int_grp = irq / 32;
88 int_off = irq % 32;
89
90 sys_write32((1 << int_off), (GICD_ISPENDRn + int_grp * 4));
91 }
92
arm_gic_irq_clear_pending(unsigned int irq)93 void arm_gic_irq_clear_pending(unsigned int irq)
94 {
95 int int_grp, int_off;
96
97 int_grp = irq / 32;
98 int_off = irq % 32;
99
100 sys_write32((1 << int_off), (GICD_ICPENDRn + int_grp * 4));
101 }
102
arm_gic_irq_set_priority(unsigned int irq,unsigned int prio,uint32_t flags)103 void arm_gic_irq_set_priority(
104 unsigned int irq, unsigned int prio, uint32_t flags)
105 {
106 int int_grp, int_off;
107 uint32_t val;
108
109 /* Set priority */
110 sys_write8(prio & 0xff, GICD_IPRIORITYRn + irq);
111
112 /* Set interrupt type */
113 int_grp = (irq / 16) * 4;
114 int_off = (irq % 16) * 2;
115
116 /* GICD_ICFGR0 is read-only; SGIs are always edge-triggered */
117 if (int_grp != 0) {
118 val = sys_read32(GICD_ICFGRn + int_grp);
119 val &= ~(GICD_ICFGR_MASK << int_off);
120 if (flags & IRQ_TYPE_EDGE) {
121 val |= (GICD_ICFGR_TYPE << int_off);
122 }
123
124 sys_write32(val, GICD_ICFGRn + int_grp);
125 }
126 }
127
arm_gic_get_active(void)128 unsigned int arm_gic_get_active(void)
129 {
130 unsigned int irq;
131
132 /*
133 * "ARM Generic Interrupt Controller Architecture version 2.0" states that
134 * [4.4.5 End of Interrupt Register, GICC_EOIR)]:
135 * """
136 * For compatibility with possible extensions to the GIC architecture
137 * specification, ARM recommends that software preserves the entire register
138 * value read from the GICC_IAR when it acknowledges the interrupt, and uses
139 * that entire value for its corresponding write to the GICC_EOIR.
140 * """
141 * Because of that, we read the entire value here, to be later written back to GICC_EOIR
142 */
143 irq = sys_read32(GICC_IAR);
144 return irq;
145 }
146
arm_gic_eoi(unsigned int irq)147 void arm_gic_eoi(unsigned int irq)
148 {
149 /*
150 * Ensure the write to peripheral registers are *complete* before the write
151 * to GIC_EOIR.
152 *
153 * Note: The completion guarantee depends on various factors of system design
154 * and the barrier is the best core can do by which execution of further
155 * instructions waits till the barrier is alive.
156 */
157 barrier_dsync_fence_full();
158
159 /* set to inactive */
160 sys_write32(irq, GICC_EOIR);
161 }
162
gic_raise_sgi(unsigned int sgi_id,uint64_t target_aff,uint16_t target_list)163 void gic_raise_sgi(unsigned int sgi_id, uint64_t target_aff,
164 uint16_t target_list)
165 {
166 uint32_t sgi_val;
167
168 ARG_UNUSED(target_aff);
169
170 sgi_val = GICD_SGIR_TGTFILT_CPULIST |
171 GICD_SGIR_CPULIST(target_list & GICD_SGIR_CPULIST_MASK) |
172 sgi_id;
173
174 barrier_dsync_fence_full();
175 sys_write32(sgi_val, GICD_SGIR);
176 barrier_isync_fence_full();
177 }
178
gic_dist_init(void)179 static void gic_dist_init(void)
180 {
181 unsigned int gic_irqs, i;
182 uint8_t cpu_mask = 0;
183 uint32_t reg_val;
184
185 gic_irqs = sys_read32(GICD_TYPER) & 0x1f;
186 gic_irqs = (gic_irqs + 1) * 32;
187 if (gic_irqs > 1020) {
188 gic_irqs = 1020;
189 }
190
191 /*
192 * Disable the forwarding of pending interrupts
193 * from the Distributor to the CPU interfaces
194 */
195 sys_write32(0, GICD_CTLR);
196
197 /*
198 * Enable all global interrupts distributing to CPUs listed
199 * in dts with the count of arch_num_cpus().
200 */
201 unsigned int num_cpus = arch_num_cpus();
202
203 for (i = 0; i < num_cpus; i++) {
204 cpu_mask |= BIT(cpu_mpid_list[i]);
205 }
206 reg_val = cpu_mask | (cpu_mask << 8) | (cpu_mask << 16)
207 | (cpu_mask << 24);
208 for (i = GIC_SPI_INT_BASE; i < gic_irqs; i += 4) {
209 sys_write32(reg_val, GICD_ITARGETSRn + i);
210 }
211
212 /*
213 * Set all global interrupts to be level triggered, active low.
214 */
215 for (i = GIC_SPI_INT_BASE; i < gic_irqs; i += 16) {
216 sys_write32(0, GICD_ICFGRn + i / 4);
217 }
218
219 /* Set priority on all global interrupts. */
220 for (i = GIC_SPI_INT_BASE; i < gic_irqs; i += 4) {
221 sys_write32(0, GICD_IPRIORITYRn + i);
222 }
223
224 /* Set all interrupts to group 0 */
225 for (i = GIC_SPI_INT_BASE; i < gic_irqs; i += 32) {
226 sys_write32(0, GICD_IGROUPRn + i / 8);
227 }
228
229 /*
230 * Disable all interrupts. Leave the PPI and SGIs alone
231 * as these enables are banked registers.
232 */
233 for (i = GIC_SPI_INT_BASE; i < gic_irqs; i += 32) {
234 #ifndef CONFIG_GIC_V1
235 sys_write32(0xffffffff, GICD_ICACTIVERn + i / 8);
236 #endif
237 sys_write32(0xffffffff, GICD_ICENABLERn + i / 8);
238 }
239
240 /*
241 * Enable the forwarding of pending interrupts
242 * from the Distributor to the CPU interfaces
243 */
244 sys_write32(1, GICD_CTLR);
245 }
246
gic_cpu_init(void)247 static void gic_cpu_init(void)
248 {
249 int i;
250 uint32_t val;
251
252 /*
253 * Deal with the banked PPI and SGI interrupts - disable all
254 * PPI interrupts, ensure all SGI interrupts are enabled.
255 */
256 #ifndef CONFIG_GIC_V1
257 sys_write32(0xffffffff, GICD_ICACTIVERn);
258 #endif
259 sys_write32(0xffff0000, GICD_ICENABLERn);
260 sys_write32(0x0000ffff, GICD_ISENABLERn);
261
262 /*
263 * Set priority on PPI and SGI interrupts
264 */
265 for (i = 0; i < 32; i += 4) {
266 sys_write32(0xa0a0a0a0, GICD_IPRIORITYRn + i);
267 }
268
269 sys_write32(0xf0, GICC_PMR);
270
271 /*
272 * Enable interrupts and signal them using the IRQ signal.
273 */
274 val = sys_read32(GICC_CTLR);
275 #ifndef CONFIG_GIC_V1
276 val &= ~GICC_CTLR_BYPASS_MASK;
277 #endif
278 val |= GICC_CTLR_ENABLE_MASK;
279 sys_write32(val, GICC_CTLR);
280 }
281
282 #define GIC_PARENT_IRQ 0
283 #define GIC_PARENT_IRQ_PRI 0
284 #define GIC_PARENT_IRQ_FLAGS 0
285
286 /**
287 * @brief Initialize the GIC device driver
288 */
arm_gic_init(const struct device * dev)289 int arm_gic_init(const struct device *dev)
290 {
291 /* Init of Distributor interface registers */
292 gic_dist_init();
293
294 /* Init CPU interface registers */
295 gic_cpu_init();
296
297 return 0;
298 }
299
300 DEVICE_DT_INST_DEFINE(0, arm_gic_init, NULL, NULL, NULL,
301 PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, NULL);
302
303 #ifdef CONFIG_SMP
arm_gic_secondary_init(void)304 void arm_gic_secondary_init(void)
305 {
306 /* Init CPU interface registers for each secondary core */
307 gic_cpu_init();
308 }
309 #endif
310