2 * Copyright (c) 2011 The FreeBSD Foundation
5 * Developed by Damjan Marion <damjan.marion@gmail.com>
7 * Based on OMAP4 GIC code by Ben Gray
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the company nor the name of the author may be used to
18 * endorse or promote products derived from this software without specific
19 * prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
37 #include "opt_platform.h"
39 #include "opt_platform.h"
41 #include <sys/param.h>
42 #include <sys/systm.h>
44 #include <sys/kernel.h>
46 #include <sys/module.h>
47 #include <sys/malloc.h>
51 #include <sys/cpuset.h>
53 #include <sys/mutex.h>
56 #include <sys/sched.h>
58 #include <machine/bus.h>
59 #include <machine/intr.h>
60 #include <machine/smp.h>
62 #include <dev/fdt/fdt_common.h>
63 #include <dev/ofw/openfirm.h>
64 #include <dev/ofw/ofw_bus.h>
65 #include <dev/ofw/ofw_bus_subr.h>
71 #define GIC_DEBUG_SPURIOUS
73 /* We are using GICv2 register naming */
75 /* Distributor Registers */
76 #define GICD_CTLR 0x000 /* v1 ICDDCR */
77 #define GICD_TYPER 0x004 /* v1 ICDICTR */
78 #define GICD_IIDR 0x008 /* v1 ICDIIDR */
79 #define GICD_IGROUPR(n) (0x0080 + ((n) * 4)) /* v1 ICDISER */
80 #define GICD_ISENABLER(n) (0x0100 + ((n) * 4)) /* v1 ICDISER */
81 #define GICD_ICENABLER(n) (0x0180 + ((n) * 4)) /* v1 ICDICER */
82 #define GICD_ISPENDR(n) (0x0200 + ((n) * 4)) /* v1 ICDISPR */
83 #define GICD_ICPENDR(n) (0x0280 + ((n) * 4)) /* v1 ICDICPR */
84 #define GICD_ICACTIVER(n) (0x0380 + ((n) * 4)) /* v1 ICDABR */
85 #define GICD_IPRIORITYR(n) (0x0400 + ((n) * 4)) /* v1 ICDIPR */
86 #define GICD_ITARGETSR(n) (0x0800 + ((n) * 4)) /* v1 ICDIPTR */
87 #define GICD_ICFGR(n) (0x0C00 + ((n) * 4)) /* v1 ICDICFR */
88 #define GICD_SGIR(n) (0x0F00 + ((n) * 4)) /* v1 ICDSGIR */
91 #define GICC_CTLR 0x0000 /* v1 ICCICR */
92 #define GICC_PMR 0x0004 /* v1 ICCPMR */
93 #define GICC_BPR 0x0008 /* v1 ICCBPR */
94 #define GICC_IAR 0x000C /* v1 ICCIAR */
95 #define GICC_EOIR 0x0010 /* v1 ICCEOIR */
96 #define GICC_RPR 0x0014 /* v1 ICCRPR */
97 #define GICC_HPPIR 0x0018 /* v1 ICCHPIR */
98 #define GICC_ABPR 0x001C /* v1 ICCABPR */
99 #define GICC_IIDR 0x00FC /* v1 ICCIIDR*/
101 #define GIC_FIRST_SGI 0 /* Irqs 0-15 are SGIs/IPIs. */
102 #define GIC_LAST_SGI 15
103 #define GIC_FIRST_PPI 16 /* Irqs 16-31 are private (per */
104 #define GIC_LAST_PPI 31 /* core) peripheral interrupts. */
105 #define GIC_FIRST_SPI 32 /* Irqs 32+ are shared peripherals. */
107 /* First bit is a polarity bit (0 - low, 1 - high) */
108 #define GICD_ICFGR_POL_LOW (0 << 0)
109 #define GICD_ICFGR_POL_HIGH (1 << 0)
110 #define GICD_ICFGR_POL_MASK 0x1
111 /* Second bit is a trigger bit (0 - level, 1 - edge) */
112 #define GICD_ICFGR_TRIG_LVL (0 << 1)
113 #define GICD_ICFGR_TRIG_EDGE (1 << 1)
114 #define GICD_ICFGR_TRIG_MASK 0x2
116 #ifndef GIC_DEFAULT_ICFGR_INIT
117 #define GIC_DEFAULT_ICFGR_INIT 0x00000000
121 static u_int gic_irq_cpu;
122 static int arm_gic_intr(void *);
123 static int arm_gic_bind(device_t dev, struct intr_irqsrc *isrc);
126 struct arm_gic_softc {
130 struct intr_irqsrc ** gic_irqs;
132 struct resource * gic_res[3];
133 bus_space_tag_t gic_c_bst;
134 bus_space_tag_t gic_d_bst;
135 bus_space_handle_t gic_c_bsh;
136 bus_space_handle_t gic_d_bsh;
140 #ifdef GIC_DEBUG_SPURIOUS
141 uint32_t last_irq[MAXCPU];
145 static struct resource_spec arm_gic_spec[] = {
146 { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Distributor registers */
147 { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* CPU Interrupt Intf. registers */
149 { SYS_RES_IRQ, 0, RF_ACTIVE | RF_OPTIONAL }, /* Parent interrupt */
154 static struct arm_gic_softc *gic_sc = NULL;
156 #define gic_c_read_4(_sc, _reg) \
157 bus_space_read_4((_sc)->gic_c_bst, (_sc)->gic_c_bsh, (_reg))
158 #define gic_c_write_4(_sc, _reg, _val) \
159 bus_space_write_4((_sc)->gic_c_bst, (_sc)->gic_c_bsh, (_reg), (_val))
160 #define gic_d_read_4(_sc, _reg) \
161 bus_space_read_4((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg))
162 #define gic_d_write_1(_sc, _reg, _val) \
163 bus_space_write_1((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg), (_val))
164 #define gic_d_write_4(_sc, _reg, _val) \
165 bus_space_write_4((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg), (_val))
168 static int gic_config_irq(int irq, enum intr_trigger trig,
169 enum intr_polarity pol);
170 static void gic_post_filter(void *);
173 static struct ofw_compat_data compat_data[] = {
174 {"arm,gic", true}, /* Non-standard, used in FreeBSD dts. */
175 {"arm,gic-400", true},
176 {"arm,cortex-a15-gic", true},
177 {"arm,cortex-a9-gic", true},
178 {"arm,cortex-a7-gic", true},
179 {"arm,arm11mp-gic", true},
180 {"brcm,brahma-b15-gic", true},
185 arm_gic_probe(device_t dev)
188 if (!ofw_bus_status_okay(dev))
191 if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
193 device_set_desc(dev, "ARM Generic Interrupt Controller");
194 return (BUS_PROBE_DEFAULT);
199 gic_irq_unmask(struct arm_gic_softc *sc, u_int irq)
202 gic_d_write_4(sc, GICD_ISENABLER(irq >> 5), (1UL << (irq & 0x1F)));
206 gic_irq_mask(struct arm_gic_softc *sc, u_int irq)
209 gic_d_write_4(sc, GICD_ICENABLER(irq >> 5), (1UL << (irq & 0x1F)));
216 arm_gic_init_secondary(device_t dev)
218 struct arm_gic_softc *sc = device_get_softc(dev);
219 struct intr_irqsrc *isrc;
222 for (irq = 0; irq < sc->nirqs; irq += 4)
223 gic_d_write_4(sc, GICD_IPRIORITYR(irq >> 2), 0);
225 /* Set all the interrupts to be in Group 0 (secure) */
226 for (irq = 0; irq < sc->nirqs; irq += 32) {
227 gic_d_write_4(sc, GICD_IGROUPR(irq >> 5), 0);
230 /* Enable CPU interface */
231 gic_c_write_4(sc, GICC_CTLR, 1);
233 /* Set priority mask register. */
234 gic_c_write_4(sc, GICC_PMR, 0xff);
236 /* Enable interrupt distribution */
237 gic_d_write_4(sc, GICD_CTLR, 0x01);
239 /* Unmask attached SGI interrupts. */
240 for (irq = GIC_FIRST_SGI; irq <= GIC_LAST_SGI; irq++) {
241 isrc = sc->gic_irqs[irq];
242 if (isrc != NULL && isrc->isrc_handlers != 0) {
243 CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
244 gic_irq_unmask(sc, irq);
248 /* Unmask attached PPI interrupts. */
249 for (irq = GIC_FIRST_PPI; irq <= GIC_LAST_PPI; irq++) {
250 isrc = sc->gic_irqs[irq];
251 if (isrc == NULL || isrc->isrc_handlers == 0)
253 if (isrc->isrc_flags & INTR_ISRCF_BOUND) {
254 if (CPU_ISSET(PCPU_GET(cpuid), &isrc->isrc_cpu))
255 gic_irq_unmask(sc, irq);
257 CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
258 gic_irq_unmask(sc, irq);
264 arm_gic_init_secondary(device_t dev)
266 struct arm_gic_softc *sc = device_get_softc(dev);
269 for (i = 0; i < sc->nirqs; i += 4)
270 gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0);
272 /* Set all the interrupts to be in Group 0 (secure) */
273 for (i = 0; i < sc->nirqs; i += 32) {
274 gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0);
277 /* Enable CPU interface */
278 gic_c_write_4(sc, GICC_CTLR, 1);
280 /* Set priority mask register. */
281 gic_c_write_4(sc, GICC_PMR, 0xff);
283 /* Enable interrupt distribution */
284 gic_d_write_4(sc, GICD_CTLR, 0x01);
287 * Activate the timer interrupts: virtual, secure, and non-secure.
289 gic_d_write_4(sc, GICD_ISENABLER(27 >> 5), (1UL << (27 & 0x1F)));
290 gic_d_write_4(sc, GICD_ISENABLER(29 >> 5), (1UL << (29 & 0x1F)));
291 gic_d_write_4(sc, GICD_ISENABLER(30 >> 5), (1UL << (30 & 0x1F)));
293 #endif /* ARM_INTRNG */
298 gic_decode_fdt(phandle_t iparent, pcell_t *intr, int *interrupt,
301 static u_int num_intr_cells;
302 static phandle_t self;
303 struct ofw_compat_data *ocd;
306 for (ocd = compat_data; ocd->ocd_str != NULL; ocd++) {
307 if (fdt_is_compatible(iparent, ocd->ocd_str)) {
316 if (num_intr_cells == 0) {
317 if (OF_searchencprop(OF_node_from_xref(iparent),
318 "#interrupt-cells", &num_intr_cells,
319 sizeof(num_intr_cells)) == -1) {
324 if (num_intr_cells == 1) {
325 *interrupt = fdt32_to_cpu(intr[0]);
326 *trig = INTR_TRIGGER_CONFORM;
327 *pol = INTR_POLARITY_CONFORM;
329 if (fdt32_to_cpu(intr[0]) == 0)
330 *interrupt = fdt32_to_cpu(intr[1]) + GIC_FIRST_SPI;
332 *interrupt = fdt32_to_cpu(intr[1]) + GIC_FIRST_PPI;
334 * In intr[2], bits[3:0] are trigger type and level flags.
335 * 1 = low-to-high edge triggered
336 * 2 = high-to-low edge triggered
337 * 4 = active high level-sensitive
338 * 8 = active low level-sensitive
339 * The hardware only supports active-high-level or rising-edge.
341 if (fdt32_to_cpu(intr[2]) & 0x0a) {
342 printf("unsupported trigger/polarity configuration "
343 "0x%02x\n", fdt32_to_cpu(intr[2]) & 0x0f);
345 *pol = INTR_POLARITY_CONFORM;
346 if (fdt32_to_cpu(intr[2]) & 0x03)
347 *trig = INTR_TRIGGER_EDGE;
349 *trig = INTR_TRIGGER_LEVEL;
356 static inline intptr_t
357 gic_xref(device_t dev)
360 return (OF_xref_from_node(ofw_bus_get_node(dev)));
368 arm_gic_attach(device_t dev)
370 struct arm_gic_softc *sc;
375 intptr_t xref = gic_xref(dev);
381 sc = device_get_softc(dev);
383 if (bus_alloc_resources(dev, arm_gic_spec, sc->gic_res)) {
384 device_printf(dev, "could not allocate resources\n");
391 /* Initialize mutex */
392 mtx_init(&sc->mutex, "GIC lock", "", MTX_SPIN);
394 /* Distributor Interface */
395 sc->gic_d_bst = rman_get_bustag(sc->gic_res[0]);
396 sc->gic_d_bsh = rman_get_bushandle(sc->gic_res[0]);
399 sc->gic_c_bst = rman_get_bustag(sc->gic_res[1]);
400 sc->gic_c_bsh = rman_get_bushandle(sc->gic_res[1]);
402 /* Disable interrupt forwarding to the CPU interface */
403 gic_d_write_4(sc, GICD_CTLR, 0x00);
405 /* Get the number of interrupts */
406 sc->nirqs = gic_d_read_4(sc, GICD_TYPER);
407 sc->nirqs = 32 * ((sc->nirqs & 0x1f) + 1);
410 sc->gic_irqs = malloc(sc->nirqs * sizeof (*sc->gic_irqs), M_DEVBUF,
413 /* Set up function pointers */
414 arm_post_filter = gic_post_filter;
415 arm_config_irq = gic_config_irq;
418 icciidr = gic_c_read_4(sc, GICC_IIDR);
419 device_printf(dev,"pn 0x%x, arch 0x%x, rev 0x%x, implementer 0x%x irqs %u\n",
420 icciidr>>20, (icciidr>>16) & 0xF, (icciidr>>12) & 0xf,
421 (icciidr & 0xfff), sc->nirqs);
423 /* Set all global interrupts to be level triggered, active low. */
424 for (i = 32; i < sc->nirqs; i += 16) {
425 gic_d_write_4(sc, GICD_ICFGR(i >> 4), GIC_DEFAULT_ICFGR_INIT);
428 /* Disable all interrupts. */
429 for (i = 32; i < sc->nirqs; i += 32) {
430 gic_d_write_4(sc, GICD_ICENABLER(i >> 5), 0xFFFFFFFF);
433 for (i = 0; i < sc->nirqs; i += 4) {
434 gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0);
435 gic_d_write_4(sc, GICD_ITARGETSR(i >> 2),
436 1 << 0 | 1 << 8 | 1 << 16 | 1 << 24);
439 /* Set all the interrupts to be in Group 0 (secure) */
440 for (i = 0; i < sc->nirqs; i += 32) {
441 gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0);
444 /* Enable CPU interface */
445 gic_c_write_4(sc, GICC_CTLR, 1);
447 /* Set priority mask register. */
448 gic_c_write_4(sc, GICC_PMR, 0xff);
450 /* Enable interrupt distribution */
451 gic_d_write_4(sc, GICD_CTLR, 0x01);
456 * Now, when everything is initialized, it's right time to
457 * register interrupt controller to interrupt framefork.
459 if (intr_pic_register(dev, xref) != 0) {
460 device_printf(dev, "could not register PIC\n");
465 * Controller is root if:
466 * - doesn't have interrupt parent
467 * - his interrupt parent is this controller
469 pxref = ofw_bus_find_iparent(ofw_bus_get_node(dev));
470 if (pxref == 0 || xref == pxref) {
471 if (intr_pic_claim_root(dev, xref, arm_gic_intr, sc,
472 GIC_LAST_SGI - GIC_FIRST_SGI + 1) != 0) {
473 device_printf(dev, "could not set PIC as a root\n");
474 intr_pic_unregister(dev, xref);
478 if (sc->gic_res[2] == NULL) {
480 "not root PIC must have defined interrupt\n");
481 intr_pic_unregister(dev, xref);
484 if (bus_setup_intr(dev, sc->gic_res[2], INTR_TYPE_CLK,
485 arm_gic_intr, NULL, sc, &sc->gic_intrhand)) {
486 device_printf(dev, "could not setup irq handler\n");
487 intr_pic_unregister(dev, xref);
492 OF_device_register_xref(xref, dev);
497 * XXX - not implemented arm_gic_detach() should be called !
499 if (sc->gic_irqs != NULL)
500 free(sc->gic_irqs, M_DEVBUF);
501 bus_release_resources(dev, arm_gic_spec, sc->gic_res);
508 arm_gic_intr(void *arg)
510 struct arm_gic_softc *sc = arg;
511 struct intr_irqsrc *isrc;
512 uint32_t irq_active_reg, irq;
513 struct trapframe *tf;
515 irq_active_reg = gic_c_read_4(sc, GICC_IAR);
516 irq = irq_active_reg & 0x3FF;
519 * 1. We do EOI here because recent read value from active interrupt
520 * register must be used for it. Another approach is to save this
521 * value into associated interrupt source.
522 * 2. EOI must be done on same CPU where interrupt has fired. Thus
523 * we must ensure that interrupted thread does not migrate to
525 * 3. EOI cannot be delayed by any preemption which could happen on
526 * critical_exit() used in MI intr code, when interrupt thread is
527 * scheduled. See next point.
528 * 4. IPI_RENDEZVOUS assumes that no preemption is permitted during
529 * an action and any use of critical_exit() could break this
530 * assumption. See comments within smp_rendezvous_action().
531 * 5. We always return FILTER_HANDLED as this is an interrupt
532 * controller dispatch function. Otherwise, in cascaded interrupt
533 * case, the whole interrupt subtree would be masked.
536 if (irq >= sc->nirqs) {
537 #ifdef GIC_DEBUG_SPURIOUS
538 device_printf(sc->gic_dev,
539 "Spurious interrupt detected: last irq: %d on CPU%d\n",
540 sc->last_irq[PCPU_GET(cpuid)], PCPU_GET(cpuid));
542 return (FILTER_HANDLED);
545 tf = curthread->td_intr_frame;
547 isrc = sc->gic_irqs[irq];
549 device_printf(sc->gic_dev, "Stray interrupt %u detected\n", irq);
550 gic_irq_mask(sc, irq);
551 gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
556 * Note that GIC_FIRST_SGI is zero and is not used in 'if' statement
557 * as compiler complains that comparing u_int >= 0 is always true.
559 if (irq <= GIC_LAST_SGI) {
561 /* Call EOI for all IPI before dispatch. */
562 gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
563 intr_ipi_dispatch(isrc, tf);
566 device_printf(sc->gic_dev, "SGI %u on UP system detected\n",
567 irq - GIC_FIRST_SGI);
568 gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
573 #ifdef GIC_DEBUG_SPURIOUS
574 sc->last_irq[PCPU_GET(cpuid)] = irq;
576 if (isrc->isrc_trig == INTR_TRIGGER_EDGE)
577 gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
579 intr_irq_dispatch(isrc, tf);
582 arm_irq_memory_barrier(irq);
583 irq_active_reg = gic_c_read_4(sc, GICC_IAR);
584 irq = irq_active_reg & 0x3FF;
588 return (FILTER_HANDLED);
592 gic_attach_isrc(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int irq)
597 * 1. The link between ISRC and controller must be set atomically.
598 * 2. Just do things only once in rare case when consumers
599 * of shared interrupt came here at the same moment.
601 mtx_lock_spin(&sc->mutex);
602 if (sc->gic_irqs[irq] != NULL) {
603 mtx_unlock_spin(&sc->mutex);
604 return (sc->gic_irqs[irq] == isrc ? 0 : EEXIST);
606 sc->gic_irqs[irq] = isrc;
607 isrc->isrc_data = irq;
608 mtx_unlock_spin(&sc->mutex);
610 name = device_get_nameunit(sc->gic_dev);
611 if (irq <= GIC_LAST_SGI)
612 intr_irq_set_name(isrc, "%s,i%u", name, irq - GIC_FIRST_SGI);
613 else if (irq <= GIC_LAST_PPI)
614 intr_irq_set_name(isrc, "%s,p%u", name, irq - GIC_FIRST_PPI);
616 intr_irq_set_name(isrc, "%s,s%u", name, irq - GIC_FIRST_SPI);
621 gic_detach_isrc(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int irq)
624 mtx_lock_spin(&sc->mutex);
625 if (sc->gic_irqs[irq] != isrc) {
626 mtx_unlock_spin(&sc->mutex);
627 return (sc->gic_irqs[irq] == NULL ? 0 : EINVAL);
629 sc->gic_irqs[irq] = NULL;
631 mtx_unlock_spin(&sc->mutex);
633 intr_irq_set_name(isrc, "");
638 gic_config(struct arm_gic_softc *sc, u_int irq, enum intr_trigger trig,
639 enum intr_polarity pol)
644 if (irq < GIC_FIRST_SPI)
647 mtx_lock_spin(&sc->mutex);
649 reg = gic_d_read_4(sc, GICD_ICFGR(irq >> 4));
650 mask = (reg >> 2*(irq % 16)) & 0x3;
652 if (pol == INTR_POLARITY_LOW) {
653 mask &= ~GICD_ICFGR_POL_MASK;
654 mask |= GICD_ICFGR_POL_LOW;
655 } else if (pol == INTR_POLARITY_HIGH) {
656 mask &= ~GICD_ICFGR_POL_MASK;
657 mask |= GICD_ICFGR_POL_HIGH;
660 if (trig == INTR_TRIGGER_LEVEL) {
661 mask &= ~GICD_ICFGR_TRIG_MASK;
662 mask |= GICD_ICFGR_TRIG_LVL;
663 } else if (trig == INTR_TRIGGER_EDGE) {
664 mask &= ~GICD_ICFGR_TRIG_MASK;
665 mask |= GICD_ICFGR_TRIG_EDGE;
669 reg = reg & ~(0x3 << 2*(irq % 16));
670 reg = reg | (mask << 2*(irq % 16));
671 gic_d_write_4(sc, GICD_ICFGR(irq >> 4), reg);
673 mtx_unlock_spin(&sc->mutex);
677 gic_bind(struct arm_gic_softc *sc, u_int irq, cpuset_t *cpus)
679 uint32_t cpu, end, mask;
681 end = min(mp_ncpus, 8);
682 for (cpu = end; cpu < MAXCPU; cpu++)
683 if (CPU_ISSET(cpu, cpus))
686 for (mask = 0, cpu = 0; cpu < end; cpu++)
687 if (CPU_ISSET(cpu, cpus))
690 gic_d_write_1(sc, GICD_ITARGETSR(0) + irq, mask);
695 gic_irq_from_nspc(struct arm_gic_softc *sc, u_int type, u_int num, u_int *irqp)
699 case INTR_IRQ_NSPC_PLAIN:
701 return (*irqp < sc->nirqs ? 0 : EINVAL);
703 case INTR_IRQ_NSPC_IRQ:
704 *irqp = num + GIC_FIRST_PPI;
705 return (*irqp < sc->nirqs ? 0 : EINVAL);
707 case INTR_IRQ_NSPC_IPI:
708 *irqp = num + GIC_FIRST_SGI;
709 return (*irqp < GIC_LAST_SGI ? 0 : EINVAL);
717 gic_map_nspc(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp)
721 error = gic_irq_from_nspc(sc, isrc->isrc_nspc_type, isrc->isrc_nspc_num,
725 return (gic_attach_isrc(sc, isrc, *irqp));
730 gic_map_fdt(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp)
733 enum intr_trigger trig;
734 enum intr_polarity pol;
737 if (isrc->isrc_ncells == 1) {
738 irq = isrc->isrc_cells[0];
739 pol = INTR_POLARITY_CONFORM;
740 trig = INTR_TRIGGER_CONFORM;
741 } else if (isrc->isrc_ncells == 3) {
742 if (isrc->isrc_cells[0] == 0)
743 irq = isrc->isrc_cells[1] + GIC_FIRST_SPI;
745 irq = isrc->isrc_cells[1] + GIC_FIRST_PPI;
748 * In intr[2], bits[3:0] are trigger type and level flags.
749 * 1 = low-to-high edge triggered
750 * 2 = high-to-low edge triggered
751 * 4 = active high level-sensitive
752 * 8 = active low level-sensitive
753 * The hardware only supports active-high-level or rising-edge.
755 tripol = isrc->isrc_cells[2];
757 device_printf(sc->gic_dev,
758 "unsupported trigger/polarity configuration "
759 "0x%02x\n", tripol & 0x0f);
761 pol = INTR_POLARITY_CONFORM;
763 trig = INTR_TRIGGER_EDGE;
765 trig = INTR_TRIGGER_LEVEL;
769 if (irq >= sc->nirqs)
772 error = gic_attach_isrc(sc, isrc, irq);
776 isrc->isrc_nspc_type = INTR_IRQ_NSPC_PLAIN;
777 isrc->isrc_nspc_num = irq;
778 isrc->isrc_trig = trig;
779 isrc->isrc_pol = pol;
787 arm_gic_register(device_t dev, struct intr_irqsrc *isrc, boolean_t *is_percpu)
789 struct arm_gic_softc *sc = device_get_softc(dev);
793 if (isrc->isrc_type == INTR_ISRCT_NAMESPACE)
794 error = gic_map_nspc(sc, isrc, &irq);
796 else if (isrc->isrc_type == INTR_ISRCT_FDT)
797 error = gic_map_fdt(sc, isrc, &irq);
803 *is_percpu = irq < GIC_FIRST_SPI ? TRUE : FALSE;
808 arm_gic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
810 struct arm_gic_softc *sc = device_get_softc(dev);
811 u_int irq = isrc->isrc_data;
813 if (isrc->isrc_trig == INTR_TRIGGER_CONFORM)
814 isrc->isrc_trig = INTR_TRIGGER_LEVEL;
817 * XXX - In case that per CPU interrupt is going to be enabled in time
818 * when SMP is already started, we need some IPI call which
819 * enables it on others CPUs. Further, it's more complicated as
820 * pic_enable_source() and pic_disable_source() should act on
821 * per CPU basis only. Thus, it should be solved here somehow.
823 if (isrc->isrc_flags & INTR_ISRCF_PERCPU)
824 CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
826 gic_config(sc, irq, isrc->isrc_trig, isrc->isrc_pol);
827 arm_gic_bind(dev, isrc);
831 arm_gic_enable_source(device_t dev, struct intr_irqsrc *isrc)
833 struct arm_gic_softc *sc = device_get_softc(dev);
834 u_int irq = isrc->isrc_data;
836 arm_irq_memory_barrier(irq);
837 gic_irq_unmask(sc, irq);
841 arm_gic_disable_source(device_t dev, struct intr_irqsrc *isrc)
843 struct arm_gic_softc *sc = device_get_softc(dev);
844 u_int irq = isrc->isrc_data;
846 gic_irq_mask(sc, irq);
850 arm_gic_unregister(device_t dev, struct intr_irqsrc *isrc)
852 struct arm_gic_softc *sc = device_get_softc(dev);
853 u_int irq = isrc->isrc_data;
855 return (gic_detach_isrc(sc, isrc, irq));
859 arm_gic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
861 struct arm_gic_softc *sc = device_get_softc(dev);
863 arm_gic_disable_source(dev, isrc);
864 gic_c_write_4(sc, GICC_EOIR, isrc->isrc_data);
868 arm_gic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
871 arm_irq_memory_barrier(0);
872 arm_gic_enable_source(dev, isrc);
876 arm_gic_post_filter(device_t dev, struct intr_irqsrc *isrc)
878 struct arm_gic_softc *sc = device_get_softc(dev);
880 /* EOI for edge-triggered done earlier. */
881 if (isrc->isrc_trig == INTR_TRIGGER_EDGE)
884 arm_irq_memory_barrier(0);
885 gic_c_write_4(sc, GICC_EOIR, isrc->isrc_data);
889 arm_gic_bind(device_t dev, struct intr_irqsrc *isrc)
891 struct arm_gic_softc *sc = device_get_softc(dev);
892 uint32_t irq = isrc->isrc_data;
894 if (irq < GIC_FIRST_SPI)
897 if (CPU_EMPTY(&isrc->isrc_cpu)) {
898 gic_irq_cpu = intr_irq_next_cpu(gic_irq_cpu, &all_cpus);
899 CPU_SETOF(gic_irq_cpu, &isrc->isrc_cpu);
901 return (gic_bind(sc, irq, &isrc->isrc_cpu));
906 arm_gic_ipi_send(device_t dev, struct intr_irqsrc *isrc, cpuset_t cpus)
908 struct arm_gic_softc *sc = device_get_softc(dev);
909 uint32_t irq, val = 0, i;
911 irq = isrc->isrc_data;
913 for (i = 0; i < MAXCPU; i++)
914 if (CPU_ISSET(i, &cpus))
915 val |= 1 << (16 + i);
917 gic_d_write_4(sc, GICD_SGIR(0), val | irq);
922 arm_gic_next_irq(struct arm_gic_softc *sc, int last_irq)
926 active_irq = gic_c_read_4(sc, GICC_IAR);
929 * Immediatly EOIR the SGIs, because doing so requires the other
930 * bits (ie CPU number), not just the IRQ number, and we do not
931 * have this information later.
933 if ((active_irq & 0x3ff) <= GIC_LAST_SGI)
934 gic_c_write_4(sc, GICC_EOIR, active_irq);
937 if (active_irq == 0x3FF) {
939 device_printf(sc->gic_dev,
940 "Spurious interrupt detected\n");
948 arm_gic_config(device_t dev, int irq, enum intr_trigger trig,
949 enum intr_polarity pol)
951 struct arm_gic_softc *sc = device_get_softc(dev);
955 /* Function is public-accessible, so validate input arguments */
956 if ((irq < 0) || (irq >= sc->nirqs))
958 if ((trig != INTR_TRIGGER_EDGE) && (trig != INTR_TRIGGER_LEVEL) &&
959 (trig != INTR_TRIGGER_CONFORM))
961 if ((pol != INTR_POLARITY_HIGH) && (pol != INTR_POLARITY_LOW) &&
962 (pol != INTR_POLARITY_CONFORM))
965 mtx_lock_spin(&sc->mutex);
967 reg = gic_d_read_4(sc, GICD_ICFGR(irq >> 4));
968 mask = (reg >> 2*(irq % 16)) & 0x3;
970 if (pol == INTR_POLARITY_LOW) {
971 mask &= ~GICD_ICFGR_POL_MASK;
972 mask |= GICD_ICFGR_POL_LOW;
973 } else if (pol == INTR_POLARITY_HIGH) {
974 mask &= ~GICD_ICFGR_POL_MASK;
975 mask |= GICD_ICFGR_POL_HIGH;
978 if (trig == INTR_TRIGGER_LEVEL) {
979 mask &= ~GICD_ICFGR_TRIG_MASK;
980 mask |= GICD_ICFGR_TRIG_LVL;
981 } else if (trig == INTR_TRIGGER_EDGE) {
982 mask &= ~GICD_ICFGR_TRIG_MASK;
983 mask |= GICD_ICFGR_TRIG_EDGE;
987 reg = reg & ~(0x3 << 2*(irq % 16));
988 reg = reg | (mask << 2*(irq % 16));
989 gic_d_write_4(sc, GICD_ICFGR(irq >> 4), reg);
991 mtx_unlock_spin(&sc->mutex);
996 device_printf(dev, "gic_config_irg, invalid parameters\n");
1002 arm_gic_mask(device_t dev, int irq)
1004 struct arm_gic_softc *sc = device_get_softc(dev);
1006 gic_d_write_4(sc, GICD_ICENABLER(irq >> 5), (1UL << (irq & 0x1F)));
1007 gic_c_write_4(sc, GICC_EOIR, irq); /* XXX - not allowed */
1011 arm_gic_unmask(device_t dev, int irq)
1013 struct arm_gic_softc *sc = device_get_softc(dev);
1015 if (irq > GIC_LAST_SGI)
1016 arm_irq_memory_barrier(irq);
1018 gic_d_write_4(sc, GICD_ISENABLER(irq >> 5), (1UL << (irq & 0x1F)));
1023 arm_gic_ipi_send(device_t dev, cpuset_t cpus, u_int ipi)
1025 struct arm_gic_softc *sc = device_get_softc(dev);
1026 uint32_t val = 0, i;
1028 for (i = 0; i < MAXCPU; i++)
1029 if (CPU_ISSET(i, &cpus))
1030 val |= 1 << (16 + i);
1032 gic_d_write_4(sc, GICD_SGIR(0), val | ipi);
1036 arm_gic_ipi_read(device_t dev, int i)
1041 * The intr code will automagically give the frame pointer
1042 * if the interrupt argument is 0.
1044 if ((unsigned int)i > 16)
1053 arm_gic_ipi_clear(device_t dev, int ipi)
1060 gic_post_filter(void *arg)
1062 struct arm_gic_softc *sc = gic_sc;
1063 uintptr_t irq = (uintptr_t) arg;
1065 if (irq > GIC_LAST_SGI)
1066 arm_irq_memory_barrier(irq);
1067 gic_c_write_4(sc, GICC_EOIR, irq);
1071 gic_config_irq(int irq, enum intr_trigger trig, enum intr_polarity pol)
1074 return (arm_gic_config(gic_sc->gic_dev, irq, trig, pol));
1078 arm_mask_irq(uintptr_t nb)
1081 arm_gic_mask(gic_sc->gic_dev, nb);
1085 arm_unmask_irq(uintptr_t nb)
1088 arm_gic_unmask(gic_sc->gic_dev, nb);
1092 arm_get_next_irq(int last_irq)
1095 return (arm_gic_next_irq(gic_sc, last_irq));
1100 intr_pic_init_secondary(void)
1103 arm_gic_init_secondary(gic_sc->gic_dev);
1107 pic_ipi_send(cpuset_t cpus, u_int ipi)
1110 arm_gic_ipi_send(gic_sc->gic_dev, cpus, ipi);
1117 return (arm_gic_ipi_read(gic_sc->gic_dev, i));
1121 pic_ipi_clear(int ipi)
1124 arm_gic_ipi_clear(gic_sc->gic_dev, ipi);
1127 #endif /* ARM_INTRNG */
1129 static device_method_t arm_gic_methods[] = {
1130 /* Device interface */
1131 DEVMETHOD(device_probe, arm_gic_probe),
1132 DEVMETHOD(device_attach, arm_gic_attach),
1134 /* Interrupt controller interface */
1135 DEVMETHOD(pic_disable_source, arm_gic_disable_source),
1136 DEVMETHOD(pic_enable_intr, arm_gic_enable_intr),
1137 DEVMETHOD(pic_enable_source, arm_gic_enable_source),
1138 DEVMETHOD(pic_post_filter, arm_gic_post_filter),
1139 DEVMETHOD(pic_post_ithread, arm_gic_post_ithread),
1140 DEVMETHOD(pic_pre_ithread, arm_gic_pre_ithread),
1141 DEVMETHOD(pic_register, arm_gic_register),
1142 DEVMETHOD(pic_unregister, arm_gic_unregister),
1144 DEVMETHOD(pic_bind, arm_gic_bind),
1145 DEVMETHOD(pic_init_secondary, arm_gic_init_secondary),
1146 DEVMETHOD(pic_ipi_send, arm_gic_ipi_send),
1152 static driver_t arm_gic_driver = {
1155 sizeof(struct arm_gic_softc),
1158 static devclass_t arm_gic_devclass;
1160 EARLY_DRIVER_MODULE(gic, simplebus, arm_gic_driver, arm_gic_devclass, 0, 0,
1161 BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
1162 EARLY_DRIVER_MODULE(gic, ofwbus, arm_gic_driver, arm_gic_devclass, 0, 0,
1163 BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);