Index: sys/conf/options.mips =================================================================== --- sys/conf/options.mips +++ sys/conf/options.mips @@ -140,3 +140,7 @@ # Options that affect the pmap. # PV_STATS opt_pmap.h +# +# Options to use ARM_INTRNG code +# +MIPS_INTRNG opt_global.h Index: sys/mips/include/intr.h =================================================================== --- /dev/null +++ sys/mips/include/intr.h @@ -0,0 +1,149 @@ +/* $NetBSD: intr.h,v 1.7 2003/06/16 20:01:00 thorpej Exp $ */ + +/*- + * Copyright (c) 1997 Mark Brinicombe. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe + * for the NetBSD Project. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + * + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ + +#ifdef FDT +#include +#endif + +#ifndef NIRQ +#define NIRQ 128 +#endif + +#ifdef notyet +#define INTR_SOLO INTR_MD1 +typedef int intr_irq_filter_t(void *arg, struct trapframe *tf); +#else +typedef int intr_irq_filter_t(void *arg); +#endif + +#define INTR_ISRC_NAMELEN (MAXCOMLEN + 1) + +typedef void intr_ipi_filter_t(void *arg); + +enum intr_isrc_type { + INTR_ISRCT_NAMESPACE, + INTR_ISRCT_FDT +}; + +#define INTR_ISRCF_REGISTERED 0x01 /* registered in a controller */ +#define INTR_ISRCF_PERCPU 0x02 /* per CPU interrupt */ +#define INTR_ISRCF_BOUND 0x04 /* bound to a CPU */ + +/* Interrupt source definition. */ +struct intr_irqsrc { + device_t isrc_dev; /* where isrc is mapped */ + intptr_t isrc_xref; /* device reference key */ + uintptr_t isrc_data; /* device data for isrc */ + u_int isrc_irq; /* unique identificator */ + enum intr_isrc_type isrc_type; /* how is isrc decribed */ + u_int isrc_flags; + char isrc_name[INTR_ISRC_NAMELEN]; + uint16_t isrc_nspc_type; + uint16_t isrc_nspc_num; + enum intr_trigger isrc_trig; + enum intr_polarity isrc_pol; + cpuset_t isrc_cpu; /* on which CPUs is enabled */ + u_int isrc_index; + u_long * isrc_count; + u_int isrc_handlers; + struct intr_event * isrc_event; + intr_irq_filter_t * isrc_filter; + intr_ipi_filter_t * isrc_ipifilter; + void * isrc_arg; +#ifdef FDT + u_int isrc_ncells; + pcell_t isrc_cells[]; /* leave it last */ +#endif +}; + +void intr_irq_set_name(struct intr_irqsrc *isrc, const char *fmt, ...) + __printflike(2, 3); + +void intr_irq_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf); + +#define INTR_IRQ_NSPC_NONE 0 +#define INTR_IRQ_NSPC_PLAIN 1 +#define INTR_IRQ_NSPC_IRQ 2 +#define INTR_IRQ_NSPC_IPI 3 +#define INTR_IRQ_NSPC_SWI 4 + +u_int intr_namespace_map_irq(device_t dev, uint16_t type, uint16_t num); +#ifdef FDT +u_int intr_fdt_map_irq(phandle_t, pcell_t *, u_int); +#endif + +int intr_pic_register(device_t dev, intptr_t xref); +int intr_pic_unregister(device_t dev, intptr_t xref); +int intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter, + void *arg, u_int ipicount); + +int intr_irq_add_handler(device_t dev, driver_filter_t, driver_intr_t, void *, + u_int, int, void **); +int intr_irq_remove_handler(device_t dev, u_int, void *); +int intr_irq_config(u_int, enum intr_trigger, enum intr_polarity); +int intr_irq_describe(u_int, void *, const char *); + +u_int intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask); + +#ifdef SMP +int intr_irq_bind(u_int, int); + +void intr_ipi_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf); + +#define AISHF_NOALLOC 0x0001 + +int intr_ipi_set_handler(u_int ipi, const char *name, intr_ipi_filter_t *filter, + void *arg, u_int flags); + +void intr_pic_init_secondary(void); +#endif + +/* MIPS compatibility for legacy mips code */ +void cpu_init_interrupts(void); +void cpu_establish_hardintr(const char *, driver_filter_t *, driver_intr_t *, + void *, int, int, void **); +void cpu_establish_softintr(const char *, driver_filter_t *, void (*)(void*), + void *, int, int, void **); +/* MIPS interrupt C entry point */ +void cpu_intr(struct trapframe *); + + +#endif /* _MACHINE_INTR_H */ Index: sys/mips/include/smp.h =================================================================== --- sys/mips/include/smp.h +++ sys/mips/include/smp.h @@ -21,6 +21,11 @@ #include +#ifdef MIPS_INTRNG +# define MIPS_IPI_COUNT 1 +# define INTR_IPI_COUNT MIPS_IPI_COUNT +#endif + /* * Interprocessor interrupts for SMP. */ Index: sys/mips/mips/exception.S =================================================================== --- sys/mips/mips/exception.S +++ sys/mips/mips/exception.S @@ -646,7 +646,11 @@ * Call the interrupt handler. a0 points at the saved frame. */ PTR_LA gp, _C_LABEL(_gp) +#ifdef MIPS_INTRNG + PTR_LA k0, _C_LABEL(intr_irq_handler) +#else PTR_LA k0, _C_LABEL(cpu_intr) +#endif jalr k0 REG_S a3, CALLFRAME_RA + KERN_REG_SIZE(sp) # for debugging @@ -758,7 +762,11 @@ /* * Call the interrupt handler. */ +#ifdef MIPS_INTRNG + PTR_LA k0, _C_LABEL(intr_irq_handler) +#else PTR_LA k0, _C_LABEL(cpu_intr) +#endif jalr k0 REG_S a3, CALLFRAME_RA(sp) # for debugging @@ -1190,6 +1198,7 @@ PTR_ADDU sp, sp, CALLFRAME_SIZ END(MipsFPTrap) +#ifndef MIPS_INTRNG /* * Interrupt counters for vmstat. */ @@ -1216,6 +1225,7 @@ #else .int INTRCNT_COUNT * (_MIPS_SZLONG / 8) * 2 #endif +#endif /* MIPS_INTRNG */ /* Index: sys/mips/mips/mips_pic.c =================================================================== --- /dev/null +++ sys/mips/mips/mips_pic.c @@ -0,0 +1,490 @@ +/*- + * Copyright (c) 2015 Alexander Kabaev + * Copyright (c) 2006 Oleksandr Tymoshenko + * Copyright (c) 2002-2004 Juli Mallett + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "opt_platform.h" +#include "opt_hwpmc_hooks.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "pic_if.h" + +#define NHARD_IRQS 6 +#define NSOFT_IRQS 2 +#define NREAL_IRQS (NHARD_IRQS + NSOFT_IRQS) + +static int mips_pic_intr(void *); + +struct mips_pic_softc { + device_t pic_dev; + struct intr_irqsrc * pic_irqs[NREAL_IRQS]; + struct mtx mutex; + uint32_t nirqs; +}; + +static struct mips_pic_softc *pic_sc; + +static struct ofw_compat_data compat_data[] = { + {"mti,cpu-interrupt-controller", true}, + {NULL, false} +}; + +static int +mips_pic_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) + return (ENXIO); + device_set_desc(dev, "MIPS32 Interrupt Controller"); + return (BUS_PROBE_DEFAULT); +} + +static inline void +pic_irq_unmask(struct mips_pic_softc *sc, u_int irq) +{ + + mips_wr_status(mips_rd_status() | ((1 << irq) << 8)); +} + +static inline void +pic_irq_mask(struct mips_pic_softc *sc, u_int irq) +{ + + mips_wr_status(mips_rd_status() & ~((1 << irq) << 8)); +} + +#ifdef SMP +static void +mips_pic_init_secondary(device_t dev) +{ +} +#endif /* SMP */ + +static inline intptr_t +pic_xref(device_t dev) +{ +#ifdef FDT + return (OF_xref_from_node(ofw_bus_get_node(dev))); +#else + return (0); +#endif +} + +static int +mips_pic_attach(device_t dev) +{ + struct mips_pic_softc *sc; + intptr_t xref = pic_xref(dev); + + if (pic_sc) + return (ENXIO); + + sc = device_get_softc(dev); + + sc->pic_dev = dev; + pic_sc = sc; + + /* Initialize mutex */ + mtx_init(&sc->mutex, "PIC lock", "", MTX_SPIN); + + /* Set the number of interrupts */ + sc->nirqs = nitems(sc->pic_irqs); + + /* + * Now, when everything is initialized, it's right time to + * register interrupt controller to interrupt framefork. + */ + if (intr_pic_register(dev, xref) != 0) { + device_printf(dev, "could not register PIC\n"); + goto cleanup; + } + + /* Claim our root controller role */ + if (intr_pic_claim_root(dev, xref, mips_pic_intr, sc, 0) != 0) { + device_printf(dev, "could not set PIC as a root\n"); + intr_pic_unregister(dev, xref); + goto cleanup; + } + + return (0); + +cleanup: + return(ENXIO); +} + +int +mips_pic_intr(void *arg) +{ + struct mips_pic_softc *sc = arg; + register_t cause, status; + struct intr_irqsrc *isrc; + int i, intr; + + cause = mips_rd_cause(); + status = mips_rd_status(); + intr = (cause & MIPS_INT_MASK) >> 8; + /* + * Do not handle masked interrupts. They were masked by + * pre_ithread function (mips_mask_XXX_intr) and will be + * unmasked once ithread is through with handler + */ + intr &= (status & MIPS_INT_MASK) >> 8; + while ((i = fls(intr)) != 0) { + i--; /* Get a 0-offset interrupt. */ + intr &= ~(1 << i); + + isrc = sc->pic_irqs[i]; + if (isrc == NULL) { + device_printf(sc->pic_dev, + "Stray interrupt %u detected\n", i); + pic_irq_mask(sc, i); + continue; + } + + intr_irq_dispatch(isrc, curthread->td_intr_frame); + } + + KASSERT(i == 0, ("all interrupts handled")); + +#ifdef HWPMC_HOOKS + if (pmc_hook && (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN)) + pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, tf); +#endif + return (FILTER_HANDLED); +} + +static int +pic_attach_isrc(struct mips_pic_softc *sc, struct intr_irqsrc *isrc, u_int irq) +{ + + /* + * 1. The link between ISRC and controller must be set atomically. + * 2. Just do things only once in rare case when consumers + * of shared interrupt came here at the same moment. + */ + mtx_lock_spin(&sc->mutex); + if (sc->pic_irqs[irq] != NULL) { + mtx_unlock_spin(&sc->mutex); + return (sc->pic_irqs[irq] == isrc ? 0 : EEXIST); + } + sc->pic_irqs[irq] = isrc; + isrc->isrc_data = irq; + mtx_unlock_spin(&sc->mutex); + + if (irq < NSOFT_IRQS) + intr_irq_set_name(isrc, "sint%u", irq); + else if (irq < NREAL_IRQS) + intr_irq_set_name(isrc, "int%u", irq - NSOFT_IRQS); + else + panic("Invalid irq %u", irq); + return (0); +} + +static int +pic_detach_isrc(struct mips_pic_softc *sc, struct intr_irqsrc *isrc, u_int irq) +{ + + mtx_lock_spin(&sc->mutex); + if (sc->pic_irqs[irq] != isrc) { + mtx_unlock_spin(&sc->mutex); + return (sc->pic_irqs[irq] == NULL ? 0 : EINVAL); + } + sc->pic_irqs[irq] = NULL; + isrc->isrc_data = 0; + mtx_unlock_spin(&sc->mutex); + + intr_irq_set_name(isrc, "%s", ""); + return (0); +} + +static int +pic_irq_from_nspc(struct mips_pic_softc *sc, u_int type, u_int num, u_int *irqp) +{ + + switch (type) { + case INTR_IRQ_NSPC_PLAIN: + *irqp = num; + return (*irqp < sc->nirqs ? 0 : EINVAL); + + case INTR_IRQ_NSPC_SWI: + *irqp = num; + return (num < NSOFT_IRQS ? 0 : EINVAL); + + case INTR_IRQ_NSPC_IRQ: + *irqp = num + NSOFT_IRQS; + return (num < NHARD_IRQS ? 0 : EINVAL); + + default: + return (EINVAL); + } +} + +static int +pic_map_nspc(struct mips_pic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp) +{ + int error; + + error = pic_irq_from_nspc(sc, isrc->isrc_nspc_type, isrc->isrc_nspc_num, + irqp); + if (error != 0) + return (error); + return (pic_attach_isrc(sc, isrc, *irqp)); +} + +#ifdef FDT +static int +pic_map_fdt(struct mips_pic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp) +{ + u_int irq; + int error; + + irq = isrc->isrc_cells[0]; + + if (irq >= sc->nirqs) + return (EINVAL); + + error = pic_attach_isrc(sc, isrc, irq); + if (error != 0) + return (error); + + isrc->isrc_nspc_type = INTR_IRQ_NSPC_PLAIN; + isrc->isrc_nspc_num = irq; + isrc->isrc_trig = INTR_TRIGGER_CONFORM; + isrc->isrc_pol = INTR_POLARITY_CONFORM; + + *irqp = irq; + return (0); +} +#endif + +static int +mips_pic_register(device_t dev, struct intr_irqsrc *isrc, boolean_t *is_percpu) +{ + struct mips_pic_softc *sc = device_get_softc(dev); + u_int irq; + int error; + + if (isrc->isrc_type == INTR_ISRCT_NAMESPACE) + error = pic_map_nspc(sc, isrc, &irq); +#ifdef FDT + else if (isrc->isrc_type == INTR_ISRCT_FDT) + error = pic_map_fdt(sc, isrc, &irq); +#endif + else + return (EINVAL); + + if (error == 0) + *is_percpu = TRUE; + return (error); +} + +static void +mips_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc) +{ + + if (isrc->isrc_trig == INTR_TRIGGER_CONFORM) + isrc->isrc_trig = INTR_TRIGGER_LEVEL; +} + +static void +mips_pic_enable_source(device_t dev, struct intr_irqsrc *isrc) +{ + struct mips_pic_softc *sc = device_get_softc(dev); + u_int irq = isrc->isrc_data; + + pic_irq_unmask(sc, irq); +} + +static void +mips_pic_disable_source(device_t dev, struct intr_irqsrc *isrc) +{ + struct mips_pic_softc *sc = device_get_softc(dev); + u_int irq = isrc->isrc_data; + + pic_irq_mask(sc, irq); +} + +static int +mips_pic_unregister(device_t dev, struct intr_irqsrc *isrc) +{ + struct mips_pic_softc *sc = device_get_softc(dev); + u_int irq = isrc->isrc_data; + + return (pic_detach_isrc(sc, isrc, irq)); +} + +static void +mips_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc) +{ + + mips_pic_disable_source(dev, isrc); +} + +static void +mips_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc) +{ + + mips_pic_enable_source(dev, isrc); +} + +static void +mips_pic_post_filter(device_t dev, struct intr_irqsrc *isrc) +{ +} + +#ifdef SMP +static int +mips_pic_bind(device_t dev, struct intr_irqsrc *isrc) +{ + return (EOPNOTSUPP); +} + +static void +mips_pic_ipi_send(device_t dev, struct intr_irqsrc *isrc, cpuset_t cpus) +{ +} +#endif + +static device_method_t mips_pic_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, mips_pic_probe), + DEVMETHOD(device_attach, mips_pic_attach), + /* Interrupt controller interface */ + DEVMETHOD(pic_disable_source, mips_pic_disable_source), + DEVMETHOD(pic_enable_intr, mips_pic_enable_intr), + DEVMETHOD(pic_enable_source, mips_pic_enable_source), + DEVMETHOD(pic_post_filter, mips_pic_post_filter), + DEVMETHOD(pic_post_ithread, mips_pic_post_ithread), + DEVMETHOD(pic_pre_ithread, mips_pic_pre_ithread), + DEVMETHOD(pic_register, mips_pic_register), + DEVMETHOD(pic_unregister, mips_pic_unregister), +#ifdef SMP + DEVMETHOD(pic_bind, mips_pic_bind), + DEVMETHOD(pic_init_secondary, mips_pic_init_secondary), + DEVMETHOD(pic_ipi_send, mips_pic_ipi_send), +#endif + { 0, 0 } +}; + +static driver_t mips_pic_driver = { + "mips_pic", + mips_pic_methods, + sizeof(struct mips_pic_softc), +}; + +static devclass_t mips_pic_devclass; + +DRIVER_MODULE(cpupic, ofwbus, mips_pic_driver, mips_pic_devclass, 0, 0); + +void +cpu_init_interrupts(void) +{ +} + +void +cpu_establish_hardintr(const char *name, driver_filter_t *filt, + void (*handler)(void*), void *arg, int irq, int flags, void **cookiep) +{ + u_int vec; + int res; + + /* + * We have 6 levels, but thats 0 - 5 (not including 6) + */ + if (irq < 0 || irq >= NHARD_IRQS) + panic("%s called for unknown hard intr %d", __func__, irq); + + KASSERT(pic_sc != NULL, ("%s: no pic", __func__)); + vec = intr_namespace_map_irq(pic_sc->pic_dev, INTR_IRQ_NSPC_IRQ, irq); + KASSERT(vec != NIRQ, ("Unable to map hard IRQ %d\n", irq)); + + res = intr_irq_add_handler(pic_sc->pic_dev, filt, handler, arg, vec, + flags, cookiep); + if (res != 0) panic("Unable to add hard IRQ %d handler", irq); + + (void)pic_irq_from_nspc(pic_sc, INTR_IRQ_NSPC_IRQ, irq, &vec); + KASSERT(pic_sc->pic_irqs[vec] != NULL, + ("Hard IRQ %d not registered\n", irq)); + intr_irq_set_name(pic_sc->pic_irqs[vec], "%s", name); +} + +void +cpu_establish_softintr(const char *name, driver_filter_t *filt, + void (*handler)(void*), void *arg, int irq, int flags, + void **cookiep) +{ + u_int vec; + int res; + + if (irq < 0 || irq > NSOFT_IRQS) + panic("%s called for unknown soft intr %d", __func__, irq); + + KASSERT(pic_sc != NULL, ("%s: no pic", __func__)); + vec = intr_namespace_map_irq(pic_sc->pic_dev, INTR_IRQ_NSPC_SWI, irq); + KASSERT(vec <= NIRQ, ("Unable to map soft IRQ %d\n", irq)); + + intr_irq_add_handler(pic_sc->pic_dev, filt, handler, arg, vec, + flags, cookiep); + if (res != 0) panic("Unable to add soft IRQ %d handler", irq); + + (void)pic_irq_from_nspc(pic_sc, INTR_IRQ_NSPC_SWI, irq, &vec); + KASSERT(pic_sc->pic_irqs[vec] != NULL, + ("Soft IRQ %d not registered\n", irq)); + intr_irq_set_name(pic_sc->pic_irqs[vec], "%s", name); +} + Index: sys/mips/mips/nexus.c =================================================================== --- sys/mips/mips/nexus.c +++ sys/mips/mips/nexus.c @@ -36,6 +36,7 @@ * this code implements the core resource managers for interrupt * requests and memory address space. */ +#include "opt_platform.h" #include __FBSDID("$FreeBSD$"); @@ -53,13 +54,23 @@ #include #include -#include #include #include #include +#ifdef MIPS_INTRNG +#include +#else +#include +#endif + #include "opt_platform.h" +#ifdef FDT +#include +#include "ofw_bus_if.h" +#endif + #undef NEXUS_DEBUG #ifdef NEXUS_DEBUG #define dprintf printf @@ -107,6 +118,19 @@ driver_intr_t *intr, void *arg, void **cookiep); static int nexus_teardown_intr(device_t, device_t, struct resource *, void *); +#ifdef MIPS_INTRNG +#ifdef SMP +static int nexus_bind_intr(device_t, device_t, struct resource *, int); +#endif +#ifdef FDT +static int nexus_ofw_map_intr(device_t dev, device_t child, + phandle_t iparent, int icells, pcell_t *intr); +#endif +static int nexus_describe_intr(device_t dev, device_t child, + struct resource *irq, void *cookie, const char *descr); +static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, + enum intr_polarity pol); +#endif static device_method_t nexus_methods[] = { /* Device interface */ @@ -127,6 +151,16 @@ DEVMETHOD(bus_activate_resource,nexus_activate_resource), DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), DEVMETHOD(bus_hinted_child, nexus_hinted_child), +#ifdef MIPS_INTRNG + DEVMETHOD(bus_config_intr, nexus_config_intr), + DEVMETHOD(bus_describe_intr, nexus_describe_intr), +#ifdef SMP + DEVMETHOD(bus_bind_intr, nexus_bind_intr), +#endif +#ifdef FDT + DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr), +#endif +#endif { 0, 0 } }; @@ -416,9 +450,16 @@ nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { - register_t s; int irq; +#ifdef MIPS_INTRNG + for (irq = rman_get_start(res); irq <= rman_get_end(res); irq++) { + intr_irq_add_handler(child, filt, intr, arg, irq, flags, + cookiep); + } +#else + register_t s; + s = intr_disable(); irq = rman_get_start(res); if (irq >= NUM_MIPS_IRQS) { @@ -429,6 +470,7 @@ cpu_establish_hardintr(device_get_nameunit(child), filt, intr, arg, irq, flags, cookiep); intr_restore(s); +#endif return (0); } @@ -436,9 +478,50 @@ nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) { +#ifdef MIPS_INTRNG + return (intr_irq_remove_handler(child, rman_get_start(r), ih)); +#else printf("Unimplemented %s at %s:%d\n", __func__, __FILE__, __LINE__); return (0); +#endif +} + +#ifdef MIPS_INTRNG +static int +nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, + enum intr_polarity pol) +{ + + return (intr_irq_config(irq, trig, pol)); +} + +static int +nexus_describe_intr(device_t dev, device_t child, struct resource *irq, + void *cookie, const char *descr) +{ + + return (intr_irq_describe(rman_get_start(irq), cookie, descr)); +} + +#ifdef SMP +static int +nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu) +{ + + return (intr_irq_bind(rman_get_start(irq), cpu)); +} +#endif + +#ifdef FDT +static int +nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, + pcell_t *intr) +{ + + return (intr_fdt_map_irq(iparent, intr, icells)); } +#endif +#endif /* MIPS_INTRNG */ static void nexus_hinted_child(device_t bus, const char *dname, int dunit)