Deleted Added
full compact
gic.c (297390) gic.c (297539)
1/*-
2 * Copyright (c) 2011 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * Developed by Damjan Marion <damjan.marion@gmail.com>
6 *
7 * Based on OMAP4 GIC code by Ben Gray
8 *

--- 18 unchanged lines hidden (view full) ---

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
31 * SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2011 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * Developed by Damjan Marion <damjan.marion@gmail.com>
6 *
7 * Based on OMAP4 GIC code by Ben Gray
8 *

--- 18 unchanged lines hidden (view full) ---

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
31 * SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: head/sys/arm/arm/gic.c 297390 2016-03-29 13:51:26Z andrew $");
35__FBSDID("$FreeBSD: head/sys/arm/arm/gic.c 297539 2016-04-04 09:15:25Z skra $");
36
37#include "opt_platform.h"
38
36
37#include "opt_platform.h"
38
39#include "opt_platform.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/bus.h>
44#include <sys/kernel.h>
45#include <sys/ktr.h>
46#include <sys/module.h>
47#include <sys/malloc.h>
48#include <sys/rman.h>

--- 64 unchanged lines hidden (view full) ---

113#define GICD_ICFGR_TRIG_EDGE (1 << 1)
114#define GICD_ICFGR_TRIG_MASK 0x2
115
116#ifndef GIC_DEFAULT_ICFGR_INIT
117#define GIC_DEFAULT_ICFGR_INIT 0x00000000
118#endif
119
120#ifdef ARM_INTRNG
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/bus.h>
42#include <sys/kernel.h>
43#include <sys/ktr.h>
44#include <sys/module.h>
45#include <sys/malloc.h>
46#include <sys/rman.h>

--- 64 unchanged lines hidden (view full) ---

111#define GICD_ICFGR_TRIG_EDGE (1 << 1)
112#define GICD_ICFGR_TRIG_MASK 0x2
113
114#ifndef GIC_DEFAULT_ICFGR_INIT
115#define GIC_DEFAULT_ICFGR_INIT 0x00000000
116#endif
117
118#ifdef ARM_INTRNG
119struct gic_irqsrc {
120 struct intr_irqsrc gi_isrc;
121 uint32_t gi_irq;
122 enum intr_polarity gi_pol;
123 enum intr_trigger gi_trig;
124};
125
121static u_int gic_irq_cpu;
122static int arm_gic_intr(void *);
126static u_int gic_irq_cpu;
127static int arm_gic_intr(void *);
123static int arm_gic_bind(device_t dev, struct intr_irqsrc *isrc);
128static int arm_gic_bind_intr(device_t dev, struct intr_irqsrc *isrc);
124
125#ifdef SMP
126u_int sgi_to_ipi[GIC_LAST_SGI - GIC_FIRST_SGI + 1];
129
130#ifdef SMP
131u_int sgi_to_ipi[GIC_LAST_SGI - GIC_FIRST_SGI + 1];
127#define ISRC_IPI(isrc) sgi_to_ipi[isrc->isrc_data - GIC_FIRST_SGI]
132u_int sgi_first_unused = GIC_FIRST_SGI;
128#endif
129#endif
130
131struct arm_gic_softc {
132 device_t gic_dev;
133#ifdef ARM_INTRNG
134 void * gic_intrhand;
133#endif
134#endif
135
136struct arm_gic_softc {
137 device_t gic_dev;
138#ifdef ARM_INTRNG
139 void * gic_intrhand;
135 struct intr_irqsrc ** gic_irqs;
140 struct gic_irqsrc * gic_irqs;
136#endif
137 struct resource * gic_res[3];
138 bus_space_tag_t gic_c_bst;
139 bus_space_tag_t gic_d_bst;
140 bus_space_handle_t gic_c_bsh;
141 bus_space_handle_t gic_d_bsh;
142 uint8_t ver;
143 struct mtx mutex;
144 uint32_t nirqs;
145#ifdef GIC_DEBUG_SPURIOUS
146 uint32_t last_irq[MAXCPU];
147#endif
148};
149
141#endif
142 struct resource * gic_res[3];
143 bus_space_tag_t gic_c_bst;
144 bus_space_tag_t gic_d_bst;
145 bus_space_handle_t gic_c_bsh;
146 bus_space_handle_t gic_d_bsh;
147 uint8_t ver;
148 struct mtx mutex;
149 uint32_t nirqs;
150#ifdef GIC_DEBUG_SPURIOUS
151 uint32_t last_irq[MAXCPU];
152#endif
153};
154
155#ifdef ARM_INTRNG
156#define GIC_INTR_ISRC(sc, irq) (&sc->gic_irqs[irq].gi_isrc)
157#endif
158
150static struct resource_spec arm_gic_spec[] = {
151 { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Distributor registers */
152 { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* CPU Interrupt Intf. registers */
153#ifdef ARM_INTRNG
154 { SYS_RES_IRQ, 0, RF_ACTIVE | RF_OPTIONAL }, /* Parent interrupt */
155#endif
156 { -1, 0 }
157};

--- 80 unchanged lines hidden (view full) ---

238 /* Set priority mask register. */
239 gic_c_write_4(sc, GICC_PMR, 0xff);
240
241 /* Enable interrupt distribution */
242 gic_d_write_4(sc, GICD_CTLR, 0x01);
243
244 /* Unmask attached SGI interrupts. */
245 for (irq = GIC_FIRST_SGI; irq <= GIC_LAST_SGI; irq++) {
159static struct resource_spec arm_gic_spec[] = {
160 { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Distributor registers */
161 { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* CPU Interrupt Intf. registers */
162#ifdef ARM_INTRNG
163 { SYS_RES_IRQ, 0, RF_ACTIVE | RF_OPTIONAL }, /* Parent interrupt */
164#endif
165 { -1, 0 }
166};

--- 80 unchanged lines hidden (view full) ---

247 /* Set priority mask register. */
248 gic_c_write_4(sc, GICC_PMR, 0xff);
249
250 /* Enable interrupt distribution */
251 gic_d_write_4(sc, GICD_CTLR, 0x01);
252
253 /* Unmask attached SGI interrupts. */
254 for (irq = GIC_FIRST_SGI; irq <= GIC_LAST_SGI; irq++) {
246 isrc = sc->gic_irqs[irq];
255 isrc = GIC_INTR_ISRC(sc, irq);
247 if (isrc != NULL && isrc->isrc_handlers != 0) {
248 CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
249 gic_irq_unmask(sc, irq);
250 }
251 }
252
253 /* Unmask attached PPI interrupts. */
254 for (irq = GIC_FIRST_PPI; irq <= GIC_LAST_PPI; irq++) {
256 if (isrc != NULL && isrc->isrc_handlers != 0) {
257 CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
258 gic_irq_unmask(sc, irq);
259 }
260 }
261
262 /* Unmask attached PPI interrupts. */
263 for (irq = GIC_FIRST_PPI; irq <= GIC_LAST_PPI; irq++) {
255 isrc = sc->gic_irqs[irq];
264 isrc = GIC_INTR_ISRC(sc, irq);
256 if (isrc == NULL || isrc->isrc_handlers == 0)
257 continue;
258 if (isrc->isrc_flags & INTR_ISRCF_BOUND) {
259 if (CPU_ISSET(PCPU_GET(cpuid), &isrc->isrc_cpu))
260 gic_irq_unmask(sc, irq);
261 } else {
262 CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
263 gic_irq_unmask(sc, irq);

--- 100 unchanged lines hidden (view full) ---

364gic_xref(device_t dev)
365{
366#ifdef FDT
367 return (OF_xref_from_node(ofw_bus_get_node(dev)));
368#else
369 return (0);
370#endif
371}
265 if (isrc == NULL || isrc->isrc_handlers == 0)
266 continue;
267 if (isrc->isrc_flags & INTR_ISRCF_BOUND) {
268 if (CPU_ISSET(PCPU_GET(cpuid), &isrc->isrc_cpu))
269 gic_irq_unmask(sc, irq);
270 } else {
271 CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
272 gic_irq_unmask(sc, irq);

--- 100 unchanged lines hidden (view full) ---

373gic_xref(device_t dev)
374{
375#ifdef FDT
376 return (OF_xref_from_node(ofw_bus_get_node(dev)));
377#else
378 return (0);
379#endif
380}
381
382static int
383arm_gic_register_isrcs(struct arm_gic_softc *sc, uint32_t num)
384{
385 int error;
386 uint32_t irq;
387 struct gic_irqsrc *irqs;
388 struct intr_irqsrc *isrc;
389 const char *name;
390
391 irqs = malloc(num * sizeof(struct gic_irqsrc), M_DEVBUF,
392 M_WAITOK | M_ZERO);
393
394 name = device_get_nameunit(sc->gic_dev);
395 for (irq = 0; irq < num; irq++) {
396 irqs[irq].gi_irq = irq;
397 irqs[irq].gi_pol = INTR_POLARITY_CONFORM;
398 irqs[irq].gi_trig = INTR_TRIGGER_CONFORM;
399
400 isrc = &irqs[irq].gi_isrc;
401 if (irq <= GIC_LAST_SGI) {
402 error = intr_isrc_register(isrc, sc->gic_dev,
403 INTR_ISRCF_IPI, "%s,i%u", name, irq - GIC_FIRST_SGI);
404 } else if (irq <= GIC_LAST_PPI) {
405 error = intr_isrc_register(isrc, sc->gic_dev,
406 INTR_ISRCF_PPI, "%s,p%u", name, irq - GIC_FIRST_PPI);
407 } else {
408 error = intr_isrc_register(isrc, sc->gic_dev, 0,
409 "%s,s%u", name, irq - GIC_FIRST_SPI);
410 }
411 if (error != 0) {
412 /* XXX call intr_isrc_deregister() */
413 free(irqs, M_DEVBUF);
414 return (error);
415 }
416 }
417 sc->gic_irqs = irqs;
418 sc->nirqs = num;
419 return (0);
420}
372#endif
373
374static int
375arm_gic_attach(device_t dev)
376{
377 struct arm_gic_softc *sc;
378 int i;
421#endif
422
423static int
424arm_gic_attach(device_t dev)
425{
426 struct arm_gic_softc *sc;
427 int i;
379 uint32_t icciidr, mask;
428 uint32_t icciidr, mask, nirqs;
380#ifdef ARM_INTRNG
381 phandle_t pxref;
382 intptr_t xref = gic_xref(dev);
383#endif
384
385 if (gic_sc)
386 return (ENXIO);
387

--- 17 unchanged lines hidden (view full) ---

405 /* CPU Interface */
406 sc->gic_c_bst = rman_get_bustag(sc->gic_res[1]);
407 sc->gic_c_bsh = rman_get_bushandle(sc->gic_res[1]);
408
409 /* Disable interrupt forwarding to the CPU interface */
410 gic_d_write_4(sc, GICD_CTLR, 0x00);
411
412 /* Get the number of interrupts */
429#ifdef ARM_INTRNG
430 phandle_t pxref;
431 intptr_t xref = gic_xref(dev);
432#endif
433
434 if (gic_sc)
435 return (ENXIO);
436

--- 17 unchanged lines hidden (view full) ---

454 /* CPU Interface */
455 sc->gic_c_bst = rman_get_bustag(sc->gic_res[1]);
456 sc->gic_c_bsh = rman_get_bushandle(sc->gic_res[1]);
457
458 /* Disable interrupt forwarding to the CPU interface */
459 gic_d_write_4(sc, GICD_CTLR, 0x00);
460
461 /* Get the number of interrupts */
413 sc->nirqs = gic_d_read_4(sc, GICD_TYPER);
414 sc->nirqs = 32 * ((sc->nirqs & 0x1f) + 1);
462 nirqs = gic_d_read_4(sc, GICD_TYPER);
463 nirqs = 32 * ((nirqs & 0x1f) + 1);
415
416#ifdef ARM_INTRNG
464
465#ifdef ARM_INTRNG
417 sc->gic_irqs = malloc(sc->nirqs * sizeof (*sc->gic_irqs), M_DEVBUF,
418 M_WAITOK | M_ZERO);
466 if (arm_gic_register_isrcs(sc, nirqs)) {
467 device_printf(dev, "could not register irqs\n");
468 goto cleanup;
469 }
419#else
470#else
471 sc->nirqs = nirqs;
472
420 /* Set up function pointers */
421 arm_post_filter = gic_post_filter;
422 arm_config_irq = gic_config_irq;
423#endif
424
425 icciidr = gic_c_read_4(sc, GICC_IIDR);
426 device_printf(dev,"pn 0x%x, arch 0x%x, rev 0x%x, implementer 0x%x irqs %u\n",
427 icciidr>>20, (icciidr>>16) & 0xF, (icciidr>>12) & 0xf,

--- 63 unchanged lines hidden (view full) ---

491 * - doesn't have interrupt parent
492 * - his interrupt parent is this controller
493 */
494 pxref = ofw_bus_find_iparent(ofw_bus_get_node(dev));
495 if (pxref == 0 || xref == pxref) {
496 if (intr_pic_claim_root(dev, xref, arm_gic_intr, sc,
497 GIC_LAST_SGI - GIC_FIRST_SGI + 1) != 0) {
498 device_printf(dev, "could not set PIC as a root\n");
473 /* Set up function pointers */
474 arm_post_filter = gic_post_filter;
475 arm_config_irq = gic_config_irq;
476#endif
477
478 icciidr = gic_c_read_4(sc, GICC_IIDR);
479 device_printf(dev,"pn 0x%x, arch 0x%x, rev 0x%x, implementer 0x%x irqs %u\n",
480 icciidr>>20, (icciidr>>16) & 0xF, (icciidr>>12) & 0xf,

--- 63 unchanged lines hidden (view full) ---

544 * - doesn't have interrupt parent
545 * - his interrupt parent is this controller
546 */
547 pxref = ofw_bus_find_iparent(ofw_bus_get_node(dev));
548 if (pxref == 0 || xref == pxref) {
549 if (intr_pic_claim_root(dev, xref, arm_gic_intr, sc,
550 GIC_LAST_SGI - GIC_FIRST_SGI + 1) != 0) {
551 device_printf(dev, "could not set PIC as a root\n");
499 intr_pic_unregister(dev, xref);
552 intr_pic_deregister(dev, xref);
500 goto cleanup;
501 }
502 } else {
503 if (sc->gic_res[2] == NULL) {
504 device_printf(dev,
505 "not root PIC must have defined interrupt\n");
553 goto cleanup;
554 }
555 } else {
556 if (sc->gic_res[2] == NULL) {
557 device_printf(dev,
558 "not root PIC must have defined interrupt\n");
506 intr_pic_unregister(dev, xref);
559 intr_pic_deregister(dev, xref);
507 goto cleanup;
508 }
509 if (bus_setup_intr(dev, sc->gic_res[2], INTR_TYPE_CLK,
510 arm_gic_intr, NULL, sc, &sc->gic_intrhand)) {
511 device_printf(dev, "could not setup irq handler\n");
560 goto cleanup;
561 }
562 if (bus_setup_intr(dev, sc->gic_res[2], INTR_TYPE_CLK,
563 arm_gic_intr, NULL, sc, &sc->gic_intrhand)) {
564 device_printf(dev, "could not setup irq handler\n");
512 intr_pic_unregister(dev, xref);
565 intr_pic_deregister(dev, xref);
513 goto cleanup;
514 }
515 }
516
517 OF_device_register_xref(xref, dev);
518 return (0);
519
520cleanup:

--- 7 unchanged lines hidden (view full) ---

528#endif
529}
530
531#ifdef ARM_INTRNG
532static int
533arm_gic_intr(void *arg)
534{
535 struct arm_gic_softc *sc = arg;
566 goto cleanup;
567 }
568 }
569
570 OF_device_register_xref(xref, dev);
571 return (0);
572
573cleanup:

--- 7 unchanged lines hidden (view full) ---

581#endif
582}
583
584#ifdef ARM_INTRNG
585static int
586arm_gic_intr(void *arg)
587{
588 struct arm_gic_softc *sc = arg;
536 struct intr_irqsrc *isrc;
589 struct gic_irqsrc *gi;
537 uint32_t irq_active_reg, irq;
538 struct trapframe *tf;
539
540 irq_active_reg = gic_c_read_4(sc, GICC_IAR);
541 irq = irq_active_reg & 0x3FF;
542
543 /*
544 * 1. We do EOI here because recent read value from active interrupt

--- 19 unchanged lines hidden (view full) ---

564 "Spurious interrupt detected: last irq: %d on CPU%d\n",
565 sc->last_irq[PCPU_GET(cpuid)], PCPU_GET(cpuid));
566#endif
567 return (FILTER_HANDLED);
568 }
569
570 tf = curthread->td_intr_frame;
571dispatch_irq:
590 uint32_t irq_active_reg, irq;
591 struct trapframe *tf;
592
593 irq_active_reg = gic_c_read_4(sc, GICC_IAR);
594 irq = irq_active_reg & 0x3FF;
595
596 /*
597 * 1. We do EOI here because recent read value from active interrupt

--- 19 unchanged lines hidden (view full) ---

617 "Spurious interrupt detected: last irq: %d on CPU%d\n",
618 sc->last_irq[PCPU_GET(cpuid)], PCPU_GET(cpuid));
619#endif
620 return (FILTER_HANDLED);
621 }
622
623 tf = curthread->td_intr_frame;
624dispatch_irq:
572 isrc = sc->gic_irqs[irq];
573 if (isrc == NULL) {
574 device_printf(sc->gic_dev, "Stray interrupt %u detected\n", irq);
575 gic_irq_mask(sc, irq);
576 gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
577 goto next_irq;
578 }
579
625 gi = sc->gic_irqs + irq;
580 /*
581 * Note that GIC_FIRST_SGI is zero and is not used in 'if' statement
582 * as compiler complains that comparing u_int >= 0 is always true.
583 */
584 if (irq <= GIC_LAST_SGI) {
585#ifdef SMP
586 /* Call EOI for all IPI before dispatch. */
587 gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
626 /*
627 * Note that GIC_FIRST_SGI is zero and is not used in 'if' statement
628 * as compiler complains that comparing u_int >= 0 is always true.
629 */
630 if (irq <= GIC_LAST_SGI) {
631#ifdef SMP
632 /* Call EOI for all IPI before dispatch. */
633 gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
588 intr_ipi_dispatch(ISRC_IPI(isrc), tf);
634 intr_ipi_dispatch(sgi_to_ipi[gi->gi_irq], tf);
589 goto next_irq;
590#else
591 device_printf(sc->gic_dev, "SGI %u on UP system detected\n",
592 irq - GIC_FIRST_SGI);
593 gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
594 goto next_irq;
595#endif
596 }
597
598#ifdef GIC_DEBUG_SPURIOUS
599 sc->last_irq[PCPU_GET(cpuid)] = irq;
600#endif
635 goto next_irq;
636#else
637 device_printf(sc->gic_dev, "SGI %u on UP system detected\n",
638 irq - GIC_FIRST_SGI);
639 gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
640 goto next_irq;
641#endif
642 }
643
644#ifdef GIC_DEBUG_SPURIOUS
645 sc->last_irq[PCPU_GET(cpuid)] = irq;
646#endif
601 if (isrc->isrc_trig == INTR_TRIGGER_EDGE)
647 if (gi->gi_trig == INTR_TRIGGER_EDGE)
602 gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
603
648 gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
649
604 intr_irq_dispatch(isrc, tf);
650 if (intr_isrc_dispatch(&gi->gi_isrc, tf) != 0) {
651 gic_irq_mask(sc, irq);
652 if (gi->gi_trig != INTR_TRIGGER_EDGE)
653 gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
654 device_printf(sc->gic_dev, "Stray irq %u disabled\n", irq);
655 }
605
606next_irq:
607 arm_irq_memory_barrier(irq);
608 irq_active_reg = gic_c_read_4(sc, GICC_IAR);
609 irq = irq_active_reg & 0x3FF;
610 if (irq < sc->nirqs)
611 goto dispatch_irq;
612
613 return (FILTER_HANDLED);
614}
615
656
657next_irq:
658 arm_irq_memory_barrier(irq);
659 irq_active_reg = gic_c_read_4(sc, GICC_IAR);
660 irq = irq_active_reg & 0x3FF;
661 if (irq < sc->nirqs)
662 goto dispatch_irq;
663
664 return (FILTER_HANDLED);
665}
666
616static int
617gic_attach_isrc(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int irq)
618{
619 const char *name;
620
621 /*
622 * 1. The link between ISRC and controller must be set atomically.
623 * 2. Just do things only once in rare case when consumers
624 * of shared interrupt came here at the same moment.
625 */
626 mtx_lock_spin(&sc->mutex);
627 if (sc->gic_irqs[irq] != NULL) {
628 mtx_unlock_spin(&sc->mutex);
629 return (sc->gic_irqs[irq] == isrc ? 0 : EEXIST);
630 }
631 sc->gic_irqs[irq] = isrc;
632 isrc->isrc_data = irq;
633 mtx_unlock_spin(&sc->mutex);
634
635 name = device_get_nameunit(sc->gic_dev);
636 if (irq <= GIC_LAST_SGI)
637 intr_irq_set_name(isrc, "%s,i%u", name, irq - GIC_FIRST_SGI);
638 else if (irq <= GIC_LAST_PPI)
639 intr_irq_set_name(isrc, "%s,p%u", name, irq - GIC_FIRST_PPI);
640 else
641 intr_irq_set_name(isrc, "%s,s%u", name, irq - GIC_FIRST_SPI);
642 return (0);
643}
644
645static int
646gic_detach_isrc(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int irq)
647{
648
649 mtx_lock_spin(&sc->mutex);
650 if (sc->gic_irqs[irq] != isrc) {
651 mtx_unlock_spin(&sc->mutex);
652 return (sc->gic_irqs[irq] == NULL ? 0 : EINVAL);
653 }
654 sc->gic_irqs[irq] = NULL;
655 isrc->isrc_data = 0;
656 mtx_unlock_spin(&sc->mutex);
657
658 intr_irq_set_name(isrc, "");
659 return (0);
660}
661
662static void
663gic_config(struct arm_gic_softc *sc, u_int irq, enum intr_trigger trig,
664 enum intr_polarity pol)
665{
666 uint32_t reg;
667 uint32_t mask;
668
669 if (irq < GIC_FIRST_SPI)

--- 41 unchanged lines hidden (view full) ---

711 for (mask = 0, cpu = 0; cpu < end; cpu++)
712 if (CPU_ISSET(cpu, cpus))
713 mask |= 1 << cpu;
714
715 gic_d_write_1(sc, GICD_ITARGETSR(0) + irq, mask);
716 return (0);
717}
718
667static void
668gic_config(struct arm_gic_softc *sc, u_int irq, enum intr_trigger trig,
669 enum intr_polarity pol)
670{
671 uint32_t reg;
672 uint32_t mask;
673
674 if (irq < GIC_FIRST_SPI)

--- 41 unchanged lines hidden (view full) ---

716 for (mask = 0, cpu = 0; cpu < end; cpu++)
717 if (CPU_ISSET(cpu, cpus))
718 mask |= 1 << cpu;
719
720 gic_d_write_1(sc, GICD_ITARGETSR(0) + irq, mask);
721 return (0);
722}
723
724#ifdef FDT
719static int
725static int
720gic_irq_from_nspc(struct arm_gic_softc *sc, u_int type, u_int num, u_int *irqp)
726gic_map_fdt(device_t dev, u_int ncells, pcell_t *cells, u_int *irqp,
727 enum intr_polarity *polp, enum intr_trigger *trigp)
721{
722
728{
729
723 switch (type) {
724 case INTR_IRQ_NSPC_PLAIN:
725 *irqp = num;
726 return (*irqp < sc->nirqs ? 0 : EINVAL);
730 if (ncells == 1) {
731 *irqp = cells[0];
732 *polp = INTR_POLARITY_CONFORM;
733 *trigp = INTR_TRIGGER_CONFORM;
734 return (0);
735 }
736 if (ncells == 3) {
737 u_int irq, tripol;
727
738
728 case INTR_IRQ_NSPC_IRQ:
729 *irqp = num + GIC_FIRST_PPI;
730 return (*irqp < sc->nirqs ? 0 : EINVAL);
739 /*
740 * The 1st cell is the interrupt type:
741 * 0 = SPI
742 * 1 = PPI
743 * The 2nd cell contains the interrupt number:
744 * [0 - 987] for SPI
745 * [0 - 15] for PPI
746 * The 3rd cell is the flags, encoded as follows:
747 * bits[3:0] trigger type and level flags
748 * 1 = low-to-high edge triggered
749 * 2 = high-to-low edge triggered
750 * 4 = active high level-sensitive
751 * 8 = active low level-sensitive
752 * bits[15:8] PPI interrupt cpu mask
753 * Each bit corresponds to each of the 8 possible cpus
754 * attached to the GIC. A bit set to '1' indicated
755 * the interrupt is wired to that CPU.
756 */
757 switch (cells[0]) {
758 case 0:
759 irq = GIC_FIRST_SPI + cells[1];
760 /* SPI irq is checked later. */
761 break;
762 case 1:
763 irq = GIC_FIRST_PPI + cells[1];
764 if (irq > GIC_LAST_PPI) {
765 device_printf(dev, "unsupported PPI interrupt "
766 "number %u\n", cells[1]);
767 return (EINVAL);
768 }
769 break;
770 default:
771 device_printf(dev, "unsupported interrupt type "
772 "configuration %u\n", cells[0]);
773 return (EINVAL);
774 }
731
775
732 case INTR_IRQ_NSPC_IPI:
733 *irqp = num + GIC_FIRST_SGI;
734 return (*irqp < GIC_LAST_SGI ? 0 : EINVAL);
776 tripol = cells[2] & 0xff;
777 if (tripol & 0xf0 || (tripol & 0x0a && cells[0] == 0))
778 device_printf(dev, "unsupported trigger/polarity "
779 "configuration 0x%02x\n", tripol);
735
780
736 default:
737 return (EINVAL);
781 *irqp = irq;
782 *polp = INTR_POLARITY_CONFORM;
783 *trigp = tripol & 0x03 ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL;
784 return (0);
738 }
785 }
786 return (EINVAL);
739}
787}
788#endif
740
741static int
789
790static int
742gic_map_nspc(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp)
791gic_map_intr(device_t dev, struct intr_map_data *data, u_int *irqp,
792 enum intr_polarity *polp, enum intr_trigger *trigp)
743{
793{
744 int error;
745
746 error = gic_irq_from_nspc(sc, isrc->isrc_nspc_type, isrc->isrc_nspc_num,
747 irqp);
748 if (error != 0)
749 return (error);
750 return (gic_attach_isrc(sc, isrc, *irqp));
751}
752
753#ifdef FDT
754static int
755gic_map_fdt(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp)
756{
757 u_int irq, tripol;
758 enum intr_trigger trig;
794 u_int irq;
759 enum intr_polarity pol;
795 enum intr_polarity pol;
760 int error;
796 enum intr_trigger trig;
797 struct arm_gic_softc *sc;
761
798
762 if (isrc->isrc_ncells == 1) {
763 irq = isrc->isrc_cells[0];
764 pol = INTR_POLARITY_CONFORM;
765 trig = INTR_TRIGGER_CONFORM;
766 } else if (isrc->isrc_ncells == 3) {
767 if (isrc->isrc_cells[0] == 0)
768 irq = isrc->isrc_cells[1] + GIC_FIRST_SPI;
769 else
770 irq = isrc->isrc_cells[1] + GIC_FIRST_PPI;
771
772 /*
773 * In intr[2], bits[3:0] are trigger type and level flags.
774 * 1 = low-to-high edge triggered
775 * 2 = high-to-low edge triggered
776 * 4 = active high level-sensitive
777 * 8 = active low level-sensitive
778 * The hardware only supports active-high-level or rising-edge.
779 */
780 tripol = isrc->isrc_cells[2];
781 if (tripol & 0x0a && irq >= GIC_FIRST_SPI) {
782 device_printf(sc->gic_dev,
783 "unsupported trigger/polarity configuration "
784 "0x%02x\n", tripol & 0x0f);
785 }
786 pol = INTR_POLARITY_CONFORM;
787 if (tripol & 0x03)
788 trig = INTR_TRIGGER_EDGE;
789 else
790 trig = INTR_TRIGGER_LEVEL;
791 } else
799 sc = device_get_softc(dev);
800 switch (data->type) {
801#ifdef FDT
802 case INTR_MAP_DATA_FDT:
803 if (gic_map_fdt(dev, data->fdt.ncells, data->fdt.cells, &irq,
804 &pol, &trig) != 0)
805 return (EINVAL);
806 break;
807#endif
808 default:
792 return (EINVAL);
809 return (EINVAL);
810 }
793
794 if (irq >= sc->nirqs)
795 return (EINVAL);
811
812 if (irq >= sc->nirqs)
813 return (EINVAL);
814 if (pol != INTR_POLARITY_CONFORM && pol != INTR_POLARITY_LOW &&
815 pol != INTR_POLARITY_HIGH)
816 return (EINVAL);
817 if (trig != INTR_TRIGGER_CONFORM && trig != INTR_TRIGGER_EDGE &&
818 trig != INTR_TRIGGER_LEVEL)
819 return (EINVAL);
796
820
797 error = gic_attach_isrc(sc, isrc, irq);
798 if (error != 0)
799 return (error);
800
801 isrc->isrc_nspc_type = INTR_IRQ_NSPC_PLAIN;
802 isrc->isrc_nspc_num = irq;
803 isrc->isrc_trig = trig;
804 isrc->isrc_pol = pol;
805
806 *irqp = irq;
821 *irqp = irq;
822 if (polp != NULL)
823 *polp = pol;
824 if (trigp != NULL)
825 *trigp = trig;
807 return (0);
808}
826 return (0);
827}
809#endif
810
811static int
828
829static int
812arm_gic_register(device_t dev, struct intr_irqsrc *isrc, boolean_t *is_percpu)
830arm_gic_map_intr(device_t dev, struct intr_map_data *data,
831 struct intr_irqsrc **isrcp)
813{
832{
814 struct arm_gic_softc *sc = device_get_softc(dev);
815 u_int irq;
816 int error;
833 int error;
834 u_int irq;
835 struct arm_gic_softc *sc;
817
836
818 if (isrc->isrc_type == INTR_ISRCT_NAMESPACE)
819 error = gic_map_nspc(sc, isrc, &irq);
820#ifdef FDT
821 else if (isrc->isrc_type == INTR_ISRCT_FDT)
822 error = gic_map_fdt(sc, isrc, &irq);
823#endif
824 else
825 return (EINVAL);
826
827 if (error == 0)
828 *is_percpu = irq < GIC_FIRST_SPI ? TRUE : FALSE;
837 error = gic_map_intr(dev, data, &irq, NULL, NULL);
838 if (error == 0) {
839 sc = device_get_softc(dev);
840 *isrcp = GIC_INTR_ISRC(sc, irq);
841 }
829 return (error);
830}
831
842 return (error);
843}
844
832static void
833arm_gic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
845static int
846arm_gic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
847 struct resource *res, struct intr_map_data *data)
834{
835 struct arm_gic_softc *sc = device_get_softc(dev);
848{
849 struct arm_gic_softc *sc = device_get_softc(dev);
836 u_int irq = isrc->isrc_data;
850 struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
851 u_int irq;
852 enum intr_trigger trig;
853 enum intr_polarity pol;
837
854
838 if (isrc->isrc_trig == INTR_TRIGGER_CONFORM)
839 isrc->isrc_trig = INTR_TRIGGER_LEVEL;
855 if (data == NULL)
856 return (ENOTSUP);
840
857
858 /* Get config for resource. */
859 if (gic_map_intr(dev, data, &irq, &pol, &trig))
860 return (EINVAL);
861
862 if (gi->gi_irq != irq)
863 return (EINVAL);
864
865 /* Compare config if this is not first setup. */
866 if (isrc->isrc_handlers != 0) {
867 if ((pol != INTR_POLARITY_CONFORM && pol != gi->gi_pol) ||
868 (trig != INTR_TRIGGER_CONFORM && trig != gi->gi_trig))
869 return (EINVAL);
870 else
871 return (0);
872 }
873
874 if (pol == INTR_POLARITY_CONFORM)
875 pol = INTR_POLARITY_LOW; /* just pick some */
876 if (trig == INTR_TRIGGER_CONFORM)
877 trig = INTR_TRIGGER_EDGE; /* just pick some */
878
879 gi->gi_pol = pol;
880 gi->gi_trig = trig;
881
841 /*
842 * XXX - In case that per CPU interrupt is going to be enabled in time
843 * when SMP is already started, we need some IPI call which
844 * enables it on others CPUs. Further, it's more complicated as
845 * pic_enable_source() and pic_disable_source() should act on
846 * per CPU basis only. Thus, it should be solved here somehow.
847 */
882 /*
883 * XXX - In case that per CPU interrupt is going to be enabled in time
884 * when SMP is already started, we need some IPI call which
885 * enables it on others CPUs. Further, it's more complicated as
886 * pic_enable_source() and pic_disable_source() should act on
887 * per CPU basis only. Thus, it should be solved here somehow.
888 */
848 if (isrc->isrc_flags & INTR_ISRCF_PERCPU)
889 if (isrc->isrc_flags & INTR_ISRCF_PPI)
849 CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
850
890 CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
891
851 gic_config(sc, irq, isrc->isrc_trig, isrc->isrc_pol);
852 arm_gic_bind(dev, isrc);
892 gic_config(sc, gi->gi_irq, trig, pol);
893 arm_gic_bind_intr(dev, isrc);
894 return (0);
853}
854
895}
896
855static void
856arm_gic_enable_source(device_t dev, struct intr_irqsrc *isrc)
897static int
898arm_gic_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
899 struct resource *res, struct intr_map_data *data)
857{
900{
858 struct arm_gic_softc *sc = device_get_softc(dev);
859 u_int irq = isrc->isrc_data;
901 struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
860
902
861 arm_irq_memory_barrier(irq);
862 gic_irq_unmask(sc, irq);
903 if (isrc->isrc_handlers == 0) {
904 gi->gi_pol = INTR_POLARITY_CONFORM;
905 gi->gi_trig = INTR_TRIGGER_CONFORM;
906 }
907 return (0);
863}
864
865static void
908}
909
910static void
866arm_gic_disable_source(device_t dev, struct intr_irqsrc *isrc)
911arm_gic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
867{
868 struct arm_gic_softc *sc = device_get_softc(dev);
912{
913 struct arm_gic_softc *sc = device_get_softc(dev);
869 u_int irq = isrc->isrc_data;
914 struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
870
915
871 gic_irq_mask(sc, irq);
916 arm_irq_memory_barrier(gi->gi_irq);
917 gic_irq_unmask(sc, gi->gi_irq);
872}
873
918}
919
874static int
875arm_gic_unregister(device_t dev, struct intr_irqsrc *isrc)
920static void
921arm_gic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
876{
877 struct arm_gic_softc *sc = device_get_softc(dev);
922{
923 struct arm_gic_softc *sc = device_get_softc(dev);
878 u_int irq = isrc->isrc_data;
924 struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
879
925
880 return (gic_detach_isrc(sc, isrc, irq));
926 gic_irq_mask(sc, gi->gi_irq);
881}
882
883static void
884arm_gic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
885{
886 struct arm_gic_softc *sc = device_get_softc(dev);
927}
928
929static void
930arm_gic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
931{
932 struct arm_gic_softc *sc = device_get_softc(dev);
933 struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
887
934
888 arm_gic_disable_source(dev, isrc);
889 gic_c_write_4(sc, GICC_EOIR, isrc->isrc_data);
935 arm_gic_disable_intr(dev, isrc);
936 gic_c_write_4(sc, GICC_EOIR, gi->gi_irq);
890}
891
892static void
893arm_gic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
894{
895
896 arm_irq_memory_barrier(0);
937}
938
939static void
940arm_gic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
941{
942
943 arm_irq_memory_barrier(0);
897 arm_gic_enable_source(dev, isrc);
944 arm_gic_enable_intr(dev, isrc);
898}
899
900static void
901arm_gic_post_filter(device_t dev, struct intr_irqsrc *isrc)
902{
903 struct arm_gic_softc *sc = device_get_softc(dev);
945}
946
947static void
948arm_gic_post_filter(device_t dev, struct intr_irqsrc *isrc)
949{
950 struct arm_gic_softc *sc = device_get_softc(dev);
951 struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
904
905 /* EOI for edge-triggered done earlier. */
952
953 /* EOI for edge-triggered done earlier. */
906 if (isrc->isrc_trig == INTR_TRIGGER_EDGE)
954 if (gi->gi_trig == INTR_TRIGGER_EDGE)
907 return;
908
909 arm_irq_memory_barrier(0);
955 return;
956
957 arm_irq_memory_barrier(0);
910 gic_c_write_4(sc, GICC_EOIR, isrc->isrc_data);
958 gic_c_write_4(sc, GICC_EOIR, gi->gi_irq);
911}
912
913static int
959}
960
961static int
914arm_gic_bind(device_t dev, struct intr_irqsrc *isrc)
962arm_gic_bind_intr(device_t dev, struct intr_irqsrc *isrc)
915{
916 struct arm_gic_softc *sc = device_get_softc(dev);
963{
964 struct arm_gic_softc *sc = device_get_softc(dev);
917 uint32_t irq = isrc->isrc_data;
965 struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
918
966
919 if (irq < GIC_FIRST_SPI)
967 if (gi->gi_irq < GIC_FIRST_SPI)
920 return (EINVAL);
921
922 if (CPU_EMPTY(&isrc->isrc_cpu)) {
923 gic_irq_cpu = intr_irq_next_cpu(gic_irq_cpu, &all_cpus);
924 CPU_SETOF(gic_irq_cpu, &isrc->isrc_cpu);
925 }
968 return (EINVAL);
969
970 if (CPU_EMPTY(&isrc->isrc_cpu)) {
971 gic_irq_cpu = intr_irq_next_cpu(gic_irq_cpu, &all_cpus);
972 CPU_SETOF(gic_irq_cpu, &isrc->isrc_cpu);
973 }
926 return (gic_bind(sc, irq, &isrc->isrc_cpu));
974 return (gic_bind(sc, gi->gi_irq, &isrc->isrc_cpu));
927}
928
929#ifdef SMP
930static void
975}
976
977#ifdef SMP
978static void
931arm_gic_ipi_send(device_t dev, struct intr_irqsrc *isrc, cpuset_t cpus)
979arm_gic_ipi_send(device_t dev, struct intr_irqsrc *isrc, cpuset_t cpus,
980 u_int ipi)
932{
933 struct arm_gic_softc *sc = device_get_softc(dev);
981{
982 struct arm_gic_softc *sc = device_get_softc(dev);
934 uint32_t irq, val = 0, i;
983 struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
984 uint32_t val = 0, i;
935
985
936 irq = isrc->isrc_data;
937
938 for (i = 0; i < MAXCPU; i++)
939 if (CPU_ISSET(i, &cpus))
940 val |= 1 << (16 + i);
941
986 for (i = 0; i < MAXCPU; i++)
987 if (CPU_ISSET(i, &cpus))
988 val |= 1 << (16 + i);
989
942 gic_d_write_4(sc, GICD_SGIR(0), val | irq);
990 gic_d_write_4(sc, GICD_SGIR(0), val | gi->gi_irq);
943}
944
945static int
991}
992
993static int
946arm_gic_ipi_setup(device_t dev, u_int ipi, struct intr_irqsrc *isrc)
994arm_gic_ipi_setup(device_t dev, u_int ipi, struct intr_irqsrc **isrcp)
947{
948 struct arm_gic_softc *sc = device_get_softc(dev);
995{
996 struct arm_gic_softc *sc = device_get_softc(dev);
949 u_int irq;
950 int error;
951
997
952 error = gic_map_nspc(sc, isrc, &irq);
953 if (error != 0)
954 return (error);
955 sgi_to_ipi[irq - GIC_FIRST_SGI] = ipi;
998 if (sgi_first_unused > GIC_LAST_SGI)
999 return (ENOSPC);
1000
1001 *isrcp = GIC_INTR_ISRC(sc, sgi_first_unused);
1002 sgi_to_ipi[sgi_first_unused++] = ipi;
956 return (0);
957}
958#endif
959#else
960static int
961arm_gic_next_irq(struct arm_gic_softc *sc, int last_irq)
962{
963 uint32_t active_irq;

--- 202 unchanged lines hidden (view full) ---

1166#endif /* ARM_INTRNG */
1167
1168static device_method_t arm_gic_methods[] = {
1169 /* Device interface */
1170 DEVMETHOD(device_probe, arm_gic_probe),
1171 DEVMETHOD(device_attach, arm_gic_attach),
1172#ifdef ARM_INTRNG
1173 /* Interrupt controller interface */
1003 return (0);
1004}
1005#endif
1006#else
1007static int
1008arm_gic_next_irq(struct arm_gic_softc *sc, int last_irq)
1009{
1010 uint32_t active_irq;

--- 202 unchanged lines hidden (view full) ---

1213#endif /* ARM_INTRNG */
1214
1215static device_method_t arm_gic_methods[] = {
1216 /* Device interface */
1217 DEVMETHOD(device_probe, arm_gic_probe),
1218 DEVMETHOD(device_attach, arm_gic_attach),
1219#ifdef ARM_INTRNG
1220 /* Interrupt controller interface */
1174 DEVMETHOD(pic_disable_source, arm_gic_disable_source),
1221 DEVMETHOD(pic_disable_intr, arm_gic_disable_intr),
1175 DEVMETHOD(pic_enable_intr, arm_gic_enable_intr),
1222 DEVMETHOD(pic_enable_intr, arm_gic_enable_intr),
1176 DEVMETHOD(pic_enable_source, arm_gic_enable_source),
1223 DEVMETHOD(pic_map_intr, arm_gic_map_intr),
1224 DEVMETHOD(pic_setup_intr, arm_gic_setup_intr),
1225 DEVMETHOD(pic_teardown_intr, arm_gic_teardown_intr),
1177 DEVMETHOD(pic_post_filter, arm_gic_post_filter),
1178 DEVMETHOD(pic_post_ithread, arm_gic_post_ithread),
1179 DEVMETHOD(pic_pre_ithread, arm_gic_pre_ithread),
1226 DEVMETHOD(pic_post_filter, arm_gic_post_filter),
1227 DEVMETHOD(pic_post_ithread, arm_gic_post_ithread),
1228 DEVMETHOD(pic_pre_ithread, arm_gic_pre_ithread),
1180 DEVMETHOD(pic_register, arm_gic_register),
1181 DEVMETHOD(pic_unregister, arm_gic_unregister),
1182#ifdef SMP
1229#ifdef SMP
1183 DEVMETHOD(pic_bind, arm_gic_bind),
1230 DEVMETHOD(pic_bind_intr, arm_gic_bind_intr),
1184 DEVMETHOD(pic_init_secondary, arm_gic_init_secondary),
1185 DEVMETHOD(pic_ipi_send, arm_gic_ipi_send),
1186 DEVMETHOD(pic_ipi_setup, arm_gic_ipi_setup),
1187#endif
1188#endif
1189 { 0, 0 }
1190};
1191

--- 12 unchanged lines hidden ---
1231 DEVMETHOD(pic_init_secondary, arm_gic_init_secondary),
1232 DEVMETHOD(pic_ipi_send, arm_gic_ipi_send),
1233 DEVMETHOD(pic_ipi_setup, arm_gic_ipi_setup),
1234#endif
1235#endif
1236 { 0, 0 }
1237};
1238

--- 12 unchanged lines hidden ---