diff --git a/sys/arch/arm/cortex/agtimer.c b/sys/arch/arm/cortex/agtimer.c index 39a1309dd02..68093e6cd88 100644 --- a/sys/arch/arm/cortex/agtimer.c +++ b/sys/arch/arm/cortex/agtimer.c @@ -225,7 +225,6 @@ agtimer_attach(struct device *parent, struct device *self, void *args) struct agtimer_softc *sc = (struct agtimer_softc *)self; struct cortex_attach_args *ia = args; bus_space_handle_t ioh, pioh; - uint32_t ints[3*4]; void *node = ia->ca_node; sc->sc_iot = ia->ca_iot; @@ -268,11 +267,10 @@ agtimer_attach(struct device *parent, struct device *self, void *args) /* establish interrupts */ /* TODO: Add interrupt FDT API. */ - if (node && fdt_node_property_ints(node, "interrupts", - ints, 3*4) == 3*4) { + if (node) { /* Setup secure, non-secure and virtual timer IRQs. */ for (int i = 0; i < 4; i++) { - ampintc_intr_establish(ints[1 + 3 * i] + 16, IPL_CLOCK, + arm_intr_establish_fdt_idx(node, i, IPL_CLOCK, agtimer_intr, NULL, "tick"); } } else { diff --git a/sys/arch/arm/cortex/ampintc.c b/sys/arch/arm/cortex/ampintc.c index d66e2716f4a..8be814e85c7 100644 --- a/sys/arch/arm/cortex/ampintc.c +++ b/sys/arch/arm/cortex/ampintc.c @@ -144,6 +144,7 @@ struct ampintc_softc { bus_space_tag_t sc_iot; bus_space_handle_t sc_d_ioh, sc_p_ioh; struct evcount sc_spur; + int sc_ncells; }; struct ampintc_softc *ampintc; @@ -159,6 +160,8 @@ void *ampintc_intr_establish(int, int, int (*)(void *), void *, char *); void *ampintc_intr_establish_ext(int, int, int (*)(void *), void *, char *); +void *ampintc_intr_establish_fdt_idx(void *, int, int, + int (*)(void *), void *, char *); void ampintc_intr_disestablish(void *); void ampintc_irq_handler(void *); const char *ampintc_intr_string(void *); @@ -246,6 +249,11 @@ ampintc_attach(struct device *parent, struct device *self, void *args) icp = mem.addr; icpsize = mem.size; } + + if (fdt_node_property_int(node, "#interrupt-cells", + &sc->sc_ncells) != 1) + panic("%s: no #interrupt-cells property", + sc->sc_dev.dv_xname); } if (bus_space_map(iot, icp, icpsize, 0, &p_ioh)) @@ -302,6 +310,8 @@ ampintc_attach(struct device *parent, struct device *self, void *args) ampintc_setipl, ampintc_intr_establish_ext, ampintc_intr_disestablish, ampintc_intr_string, ampintc_irq_handler); + arm_set_intr_handler_fdt(node, ampintc_intr_establish_fdt_idx); + /* enable interrupts */ bus_space_write_4(iot, d_ioh, ICD_DCR, 3); bus_space_write_4(iot, p_ioh, ICPICR, 1); @@ -549,6 +559,29 @@ ampintc_intr_establish_ext(int irqno, int level, int (*func)(void *), return ampintc_intr_establish(irqno+32, level, func, arg, name); } +void * +ampintc_intr_establish_fdt_idx(void *node, int idx, int level, + int (*func)(void *), void *arg, char *name) +{ + struct ampintc_softc *sc = ampintc; + int nints = sc->sc_ncells * (idx + 1); + int ints[nints]; + int irq; + + if (fdt_node_property_ints(node, "interrupts", ints, nints) != nints) + panic("%s: no interrupts property", sc->sc_dev.dv_xname); + + irq = ints[idx * 3 + 1]; + if (ints[idx * 3] == 0) + irq += 32; + else if (ints[idx * 3] == 1) + irq += 16; + else + panic("%s: bogus interrupt type", sc->sc_dev.dv_xname); + + return ampintc_intr_establish(irq, level, func, arg, name); +} + void * ampintc_intr_establish(int irqno, int level, int (*func)(void *), void *arg, char *name) diff --git a/sys/arch/armv7/armv7/intr.c b/sys/arch/armv7/armv7/intr.c index 6148ccd0d03..ff6deb4245b 100644 --- a/sys/arch/armv7/armv7/intr.c +++ b/sys/arch/armv7/armv7/intr.c @@ -19,10 +19,12 @@ #include #include #include +#include #include #include #include +#include #include int arm_dflt_splraise(int); @@ -65,16 +67,51 @@ arm_dflt_intr(void *frame) panic("arm_dflt_intr() called"); } +SLIST_HEAD(, ic_entry) ic_list = SLIST_HEAD_INITIALIZER(ic_list); +struct ic_entry { + SLIST_ENTRY(ic_entry) ie_list; + void *ie_node; + struct device *ie_dev; + void *(*ie_intr_establish)(void *node, int idx, int level, + int (*func)(void *), void *cookie, char *name); +}; + +void *arm_intr_establish_fdt(void *node, int level, int (*func)(void *), + void *cookie, char *name) +{ + return arm_intr_establish_fdt_idx(node, 0, level, func, cookie, name); +} + +void *arm_intr_establish_fdt_idx(void *node, int idx, int level, + int (*func)(void *), void *cookie, char *name) +{ + struct ic_entry *ie, *ip; + + ip = fdt_get_interrupt_controller(node); + if (ip == NULL) + return NULL; + + SLIST_FOREACH(ie, &ic_list, ie_list) { + if (ie->ie_node != ip) + continue; + return ie->ie_intr_establish(node, idx, level, func, cookie, + name); + } + + return NULL; +} void *arm_intr_establish(int irqno, int level, int (*func)(void *), void *cookie, char *name) { return arm_intr_func.intr_establish(irqno, level, func, cookie, name); } + void arm_intr_disestablish(void *cookie) { arm_intr_func.intr_disestablish(cookie); } + const char *arm_intr_string(void *cookie) { return arm_intr_func.intr_string(cookie); @@ -200,6 +237,26 @@ arm_do_pending_intr(int pcpl) intr_restore(oldirqstate); } +void +arm_set_intr_handler_fdt(void *node, + void *(*intr_establish)(void *node, int idx, int level, + int (*func)(void *), void *cookie, char *name)) +{ + struct ic_entry *ie; + + if (node == NULL) + return; + + ie = malloc(sizeof(*ie), M_DEVBUF, M_NOWAIT|M_ZERO); + if (ie == NULL) + panic("%s: cannot allocate ic entry", __func__); + + ie->ie_node = node; + ie->ie_intr_establish = intr_establish; + + SLIST_INSERT_HEAD(&ic_list, ie, ie_list); +} + void arm_set_intr_handler(int (*raise)(int), int (*lower)(int), void (*x)(int), void (*setipl)(int), void *(*intr_establish)(int irqno, int level, int (*func)(void *), diff --git a/sys/arch/armv7/include/intr.h b/sys/arch/armv7/include/intr.h index 40bec52b875..eb7fa14f7a4 100644 --- a/sys/arch/armv7/include/intr.h +++ b/sys/arch/armv7/include/intr.h @@ -84,6 +84,9 @@ int spllower(int); void splx(int); void arm_do_pending_intr(int); +void arm_set_intr_handler_fdt(void *node, + void *(*intr_establish)(void *node, int idx, int level, + int (*func)(void *), void *cookie, char *name)); void arm_set_intr_handler(int (*raise)(int), int (*lower)(int), void (*x)(int), void (*setipl)(int), void *(*intr_establish)(int irqno, int level, int (*func)(void *), @@ -163,6 +166,10 @@ void arm_setsoftintr(int si); void *arm_intr_establish(int irqno, int level, int (*func)(void *), void *cookie, char *name); +void *arm_intr_establish_fdt(void *node, int level, int (*func)(void *), + void *cookie, char *name); +void *arm_intr_establish_fdt_idx(void *node, int idx, int level, + int (*func)(void *), void *cookie, char *name); void arm_intr_disestablish(void *cookie); const char *arm_intr_string(void *cookie); diff --git a/sys/arch/armv7/virt/virtio_mmio.c b/sys/arch/armv7/virt/virtio_mmio.c index 04dc17d9f33..3d00606da95 100644 --- a/sys/arch/armv7/virt/virtio_mmio.c +++ b/sys/arch/armv7/virt/virtio_mmio.c @@ -104,7 +104,6 @@ struct virtio_mmio_softc { bus_size_t sc_iosize; bus_dma_tag_t sc_dmat; - int sc_irqno; void *sc_ih; int sc_config_offset; @@ -195,9 +194,6 @@ virtio_mmio_attach(struct device *parent, struct device *self, void *aux) if (fdt_get_memory_address(aa->aa_node, 0, &mem)) panic("%s: could not extract memory data from FDT", __func__); - if (fdt_get_interrupt(aa->aa_node, &sc->sc_irqno)) - panic("%s: could not extract interrupt data from FDT", __func__); - sc->sc_iosize = mem.size; sc->sc_iot = aa->aa_iot; sc->sc_dmat = aa->aa_dmat; @@ -252,7 +248,7 @@ virtio_mmio_attach(struct device *parent, struct device *self, void *aux) goto fail_1; } - sc->sc_ih = arm_intr_establish(sc->sc_irqno, vsc->sc_ipl, + sc->sc_ih = arm_intr_establish_fdt(aa->aa_node, vsc->sc_ipl, virtio_mmio_intr, sc, vsc->sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf("%s: couldn't establish interrupt\n",