diff --git a/sys/dev/fdt/fdt_mips.c b/sys/dev/fdt/fdt_mips.c index 4df31d841643..190457423751 100644 --- a/sys/dev/fdt/fdt_mips.c +++ b/sys/dev/fdt/fdt_mips.c @@ -68,7 +68,26 @@ fdt_pic_decode_mips4k_cp0(phandle_t node, pcell_t *intr, int *interrupt, return (0); } +/* + * CHERI PIC decoder. + */ +static int +fdt_pic_decode_beri(phandle_t node, pcell_t *intr, int *interrupt, + int *trig, int *pol) +{ + + if (!fdt_is_compatible(node, "sri-cambridge,beri-pic")) + return (ENXIO); + + *interrupt = fdt32_to_cpu(intr[0]); + *trig = INTR_TRIGGER_CONFORM; + *pol = INTR_POLARITY_CONFORM; + + return (0); +} + fdt_pic_decode_t fdt_pic_table[] = { &fdt_pic_decode_mips4k_cp0, + &fdt_pic_decode_beri, NULL }; diff --git a/sys/mips/beri/beri_pic.c b/sys/mips/beri/beri_pic.c new file mode 100644 index 000000000000..1eca708d4d6f --- /dev/null +++ b/sys/mips/beri/beri_pic.c @@ -0,0 +1,706 @@ +/*- + * Copyright (c) 2013 SRI International + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * 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. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include "fdt_ic_if.h" + +struct beripic_softc; + +static uint64_t bp_read_cfg(struct beripic_softc *, int); +static void bp_write_cfg(struct beripic_softc *, int, uint64_t); +static void bp_detach_resources(device_t); +static char *bp_strconfig(uint64_t, char *, size_t); +static void bp_config_source(device_t, int, int, u_long, u_long); +#ifdef __mips__ +static void bp_set_counter_name(device_t, device_t, int); +#endif + +static int beripic_fdt_probe(device_t); +static int beripic_fdt_attach(device_t); + +static int beripic_activate_intr(device_t, struct resource *); +static struct resource * + beripic_alloc_intr(device_t, device_t, int *, u_long, u_int); +static int beripic_config_intr(device_t, int, enum intr_trigger, + enum intr_polarity); +static int beripic_release_intr(device_t, struct resource *); +static int beripic_setup_intr(device_t, device_t, struct resource *, + int, driver_filter_t *, driver_intr_t *, void *, void **); +static int beripic_teardown_intr(device_t, device_t, struct resource *, + void *); + +static int beripic_filter(void *); +static void beripic_intr(void *); + +#define BP_MAX_HARD_IRQS 6 +#define BP_FIRST_SOFT 64 + +struct beripic_softc { + device_t bp_dev; + struct resource *bp_cfg_res; + struct resource *bp_read_res; + struct resource *bp_set_res; + struct resource *bp_clear_res; + int bp_cfg_rid; + int bp_read_rid; + int bp_set_rid; + int bp_clear_rid; + bus_space_tag_t bp_cfg_bst; + bus_space_tag_t bp_read_bst; + bus_space_tag_t bp_set_bst; + bus_space_tag_t bp_clear_bst; + bus_space_handle_t bp_cfg_bsh; + bus_space_handle_t bp_read_bsh; + bus_space_handle_t bp_set_bsh; + bus_space_handle_t bp_clear_bsh; + + struct resource *bp_irqs[BP_MAX_HARD_IRQS]; + int bp_irq_rids[BP_MAX_HARD_IRQS]; + int bp_nirqs; + int bp_next_irq; + int bp_next_tid; + + int bp_nthreads; + + int bp_nhard; + int bp_nsoft; + int bp_nsrcs; + struct rman bp_src_rman; + +#ifdef __mips__ + mips_intrcnt_t *bp_counters; +#endif + + struct mtx bp_cfgmtx; +}; + +struct beripic_intr_arg { + driver_filter_t *filter; + driver_intr_t *intr; + void *arg; + struct resource *irq; +#ifdef __mips__ + mips_intrcnt_t counter; +#endif +}; + +struct beripic_cookie { + struct beripic_intr_arg *bpia; + struct resource *hirq; + void *cookie; +}; + +#define BP_CFG_MASK_E 0x80000000ull +#define BP_CFG_SHIFT_E 31 +#define BP_CFG_MASK_TID 0x7FFFFF00ull /* Depends on CPU */ +#define BP_CFG_SHIFT_TID 8 +#define BP_CFG_MASK_IRQ 0x0000000Full +#define BP_CFG_SHIFT_IRQ 0 +#define BP_CFG_VALID (BP_CFG_MASK_E|BP_CFG_MASK_TID|BP_CFG_MASK_IRQ) +#define BP_CFG_RESERVED ~BP_CFG_VALID + +#define BP_CFG_ENABLED(cfg) (((cfg) & BP_CFG_MASK_E) >> BP_CFG_SHIFT_E) +#define BP_CFG_TID(cfg) (((cfg) & BP_CFG_MASK_TID) >> BP_CFG_SHIFT_TID) +#define BP_CFG_IRQ(cfg) (((cfg) & BP_CFG_MASK_IRQ) >> BP_CFG_SHIFT_IRQ) + +MALLOC_DEFINE(M_BERIPIC, "beripic", "beripic memory"); + +static uint64_t +bp_read_cfg(struct beripic_softc *sc, int irq) +{ + + KASSERT((irq >= 0 && irq < sc->bp_nsrcs), + ("IRQ of of range %d (0-%d)", irq, sc->bp_nsrcs - 1)); + return (bus_space_read_8(sc->bp_cfg_bst, sc->bp_cfg_bsh, irq * 8)); +} + +static void +bp_write_cfg(struct beripic_softc *sc, int irq, uint64_t config) +{ + + KASSERT((irq >= 0 && irq < sc->bp_nsrcs), + ("IRQ of of range %d (0-%d)", irq, sc->bp_nsrcs - 1)); + bus_space_write_8(sc->bp_cfg_bst, sc->bp_cfg_bsh, irq * 8, config); +} + +static void +bp_detach_resources(device_t dev) +{ + struct beripic_softc *sc; + int i; + + sc = device_get_softc(dev); + + if (sc->bp_cfg_res != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, sc->bp_cfg_rid, + sc->bp_cfg_res); + sc->bp_cfg_res = NULL; + } + if (sc->bp_read_res != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, sc->bp_read_rid, + sc->bp_read_res); + sc->bp_read_res = NULL; + } + if (sc->bp_set_res != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, sc->bp_set_rid, + sc->bp_set_res); + sc->bp_set_res = NULL; + } + if (sc->bp_clear_res != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, sc->bp_clear_rid, + sc->bp_clear_res); + sc->bp_clear_res = NULL; + } + for (i = sc->bp_nirqs - 1; i >= 0; i--) { + bus_release_resource(dev, SYS_RES_IRQ, sc->bp_irq_rids[i], + sc->bp_irqs[i]); + } + sc->bp_nirqs = 0; +} + +static char * +bp_strconfig(uint64_t config, char *configstr, size_t len) +{ + + if (snprintf(configstr, len, "%s tid: %llu hardintr %llu", + BP_CFG_ENABLED(config) ? "enabled" : "disabled", + BP_CFG_TID(config), BP_CFG_IRQ(config)) > len - 1) + return (NULL); + return (configstr); +} + +static void +bp_config_source(device_t ic, int src, int enable, u_long tid, u_long irq) +{ + struct beripic_softc *sc; + uint64_t config; + + sc = device_get_softc(ic); + + config = 0; + config |= enable << BP_CFG_SHIFT_E; + config |= tid << BP_CFG_SHIFT_TID; + config |= irq << BP_CFG_SHIFT_IRQ; + + bp_write_cfg(sc, src, config); +} + +#ifdef __mips__ +static void +bp_set_counter_name(device_t ic, device_t child, int src) +{ + struct beripic_softc *sc; + char name[MAXCOMLEN + 1]; + + sc = device_get_softc(ic); + + if (snprintf(name, sizeof(name), "bp%dsrc%d%s%s%s", + device_get_unit(ic), src, src < sc->bp_nhard ? "" : "s", + child == NULL ? "" : " ", + child == NULL ? " " : device_get_nameunit(child)) >= sizeof(name)) + name[sizeof(name) - 2] = '+'; + + mips_intrcnt_setname(sc->bp_counters[src], name); +} +#endif + +static int +beripic_fdt_probe(device_t dev) +{ + + if (!ofw_bus_is_compatible(dev, "sri-cambridge,beri-pic")) + return (ENXIO); + + device_set_desc(dev, "BERI Programmable Interrupt Controller"); + return (BUS_PROBE_DEFAULT); +} + +static int +beripic_fdt_attach(device_t dev) +{ + char configstr[64]; + struct beripic_softc *sc; + struct fdt_ic *fic; + pcell_t nhard, nsoft; + phandle_t ph; + int error, i, src; + uint64_t config; + + sc = device_get_softc(dev); + sc->bp_dev = dev; + + mtx_init(&sc->bp_cfgmtx, "beripic config lock", NULL, MTX_DEF); + + /* + * FDT lists CONFIG, IP_READ, IP_SET, and IP_CLEAR registers as + * seperate memory regions in that order. + */ + sc->bp_cfg_rid = 0; + sc->bp_cfg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->bp_cfg_rid, RF_ACTIVE); + if (sc->bp_cfg_res == NULL) { + device_printf(dev, "failed to map config memory"); + error = ENXIO; + goto err; + } + if (bootverbose) + device_printf(sc->bp_dev, "config region at mem %p-%p\n", + (void *)rman_get_start(sc->bp_cfg_res), + (void *)(rman_get_start(sc->bp_cfg_res) + + rman_get_size(sc->bp_cfg_res))); + + sc->bp_read_rid = 1; + sc->bp_read_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->bp_read_rid, RF_ACTIVE); + if (sc->bp_read_res == NULL) { + device_printf(dev, "failed to map IP read memory"); + error = ENXIO; + goto err; + } + if (bootverbose) + device_printf(sc->bp_dev, "IP read region at mem %p-%p\n", + (void *)rman_get_start(sc->bp_read_res), + (void *)(rman_get_start(sc->bp_read_res) + + rman_get_size(sc->bp_read_res))); + + sc->bp_set_rid = 2; + sc->bp_set_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->bp_set_rid, RF_ACTIVE); + if (sc->bp_set_res == NULL) { + device_printf(dev, "failed to map IP read memory"); + error = ENXIO; + goto err; + } + if (bootverbose) + device_printf(sc->bp_dev, "IP set region at mem %p-%p\n", + (void *)rman_get_start(sc->bp_set_res), + (void *)(rman_get_start(sc->bp_set_res) + + rman_get_size(sc->bp_set_res))); + + sc->bp_clear_rid = 3; + sc->bp_clear_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->bp_clear_rid, RF_ACTIVE); + if (sc->bp_clear_res == NULL) { + device_printf(dev, "failed to map IP read memory"); + error = ENXIO; + goto err; + } + if (bootverbose) + device_printf(sc->bp_dev, "IP clear region at mem %p-%p\n", + (void *)rman_get_start(sc->bp_clear_res), + (void *)(rman_get_start(sc->bp_clear_res) + + rman_get_size(sc->bp_clear_res))); + + i = 0; + for (i = 0; i < BP_MAX_HARD_IRQS; i++) { + sc->bp_irq_rids[i] = i; + sc->bp_irqs[i] = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &sc->bp_irq_rids[i], RF_ACTIVE | RF_SHAREABLE); + if (sc->bp_irqs[i] == NULL) + break; + } + if (i == 0) { + device_printf(dev, "failed to allocate any parent IRQs!"); + error = ENXIO; + goto err; + } + sc->bp_nirqs = i; + + ph = ofw_bus_gen_get_node(device_get_parent(dev), dev); + +#ifndef SMP + sc->bp_nthreads = 1; +#else + sc->bp_nthreads = 1; + /* XXX: get nthreads from cpu(s) somehow */ +#endif + + if (OF_getprop(ph, "hard-interrupt-sources", &nhard, sizeof(nhard)) + <= 0) { + device_printf(dev, "failed to get number of hard sources"); + error = ENXIO; + goto err; + } + if (OF_getprop(ph, "soft-interrupt-sources", &nsoft, sizeof(nsoft)) + <= 0) { + device_printf(dev, "failed to get number of soft sources"); + error = ENXIO; + goto err; + } + + sc->bp_nhard = nhard; + sc->bp_nsoft = nsoft; + sc->bp_nsrcs = sc->bp_nhard + sc->bp_nsoft; + /* XXX: should deal with gap between hard and soft */ + KASSERT(sc->bp_nhard <= BP_FIRST_SOFT, + ("too many hard sources")); + KASSERT(rman_get_size(sc->bp_cfg_res) / 8 == sc->bp_nsrcs, + ("config space size does not match sources")); + KASSERT(sc->bp_nhard % 64 == 0, + ("Non-multiple of 64 intr counts not supported")); + KASSERT(sc->bp_nsoft % 64 == 0, + ("Non-multiple of 64 intr counts not supported")); + if (bootverbose) + device_printf(dev, "%d hard and %d soft sources\n", + sc->bp_nhard, sc->bp_nsoft); + +#ifdef __mips__ + sc->bp_counters = malloc(sizeof(*sc->bp_counters) * sc->bp_nsrcs, + M_BERIPIC, M_WAITOK|M_ZERO); + for (i = 0; i < sc->bp_nsrcs; i++) { + sc->bp_counters[i] = mips_intrcnt_create(""); + bp_set_counter_name(dev, NULL, i); + } +#endif + + sc->bp_src_rman.rm_start = 0; + sc->bp_src_rman.rm_end = sc->bp_nsrcs - 1; + sc->bp_src_rman.rm_type = RMAN_ARRAY; + sc->bp_src_rman.rm_descr = "Interrupt source"; + if (rman_init(&(sc->bp_src_rman)) != 0 || + rman_manage_region(&(sc->bp_src_rman), 0, sc->bp_nsrcs - 1) != 0) { + device_printf(dev, "Failed to set up sources rman"); + error = ENXIO; + goto err; + } + + sc->bp_cfg_bst = rman_get_bustag(sc->bp_cfg_res); + sc->bp_cfg_bsh = rman_get_bushandle(sc->bp_cfg_res); + sc->bp_read_bst = rman_get_bustag(sc->bp_read_res); + sc->bp_read_bsh = rman_get_bushandle(sc->bp_read_res); + sc->bp_set_bst = rman_get_bustag(sc->bp_set_res); + sc->bp_set_bsh = rman_get_bushandle(sc->bp_set_res); + sc->bp_clear_bst = rman_get_bustag(sc->bp_clear_res); + sc->bp_clear_bsh = rman_get_bushandle(sc->bp_clear_res); + + for (src = 0; src < sc->bp_nsrcs; src++) { + config = bp_read_cfg(sc, src); + if (config == 0) + continue; + + if (bootverbose) { + device_printf(dev, "initial config: src %d: %s\n", src, + bp_strconfig(config, configstr, sizeof(configstr))); + if (config & BP_CFG_RESERVED) + device_printf(dev, + "reserved bits not 0: 0x%016jx\n", + (uintmax_t) config); + } + + bp_config_source(dev, src, 0, 0, 0); + } + + fic = malloc(sizeof(*fic), M_BERIPIC, M_WAITOK|M_ZERO); + fic->iph = ph; + fic->dev = dev; + SLIST_INSERT_HEAD(&fdt_ic_list_head, fic, fdt_ics); + + return (0); +err: + bp_detach_resources(dev); + + return (error); +} + +static struct resource * +beripic_alloc_intr(device_t ic, device_t child, int *rid, u_long irq, + u_int flags) +{ + struct beripic_softc *sc; + struct resource *rv; + + sc = device_get_softc(ic); + + rv = rman_reserve_resource(&(sc->bp_src_rman), irq, irq, 1, flags, + child); + if (rv == NULL) + printf("%s: could not reserve source interrupt for %s\n", + __func__, device_get_nameunit(child)); + rman_set_rid(rv, *rid); + + if ((flags & RF_ACTIVE) && + beripic_activate_intr(ic, rv) != 0) { + printf("%s: could not activate interrupt\n", __func__); + rman_release_resource(rv); + return (NULL); + } + + return (rv); +} + +static int +beripic_release_intr(device_t ic, struct resource *r) +{ + + return (rman_release_resource(r)); +} + +static int +beripic_activate_intr(device_t ic, struct resource *r) +{ + + return (rman_activate_resource(r)); +} + +static int +beripic_deactivate_intr(device_t ic, struct resource *r) +{ + + return (rman_deactivate_resource(r)); +} + +static int +beripic_config_intr(device_t dev, int irq, enum intr_trigger trig, + enum intr_polarity pol) +{ + + if (trig != INTR_TRIGGER_CONFORM || pol != INTR_POLARITY_CONFORM) + return (EINVAL); + + return (0); +} + +static int +beripic_setup_intr(device_t ic, device_t child, struct resource *irq, + int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg, + void **cookiep) +{ + struct beripic_softc *sc; + struct beripic_intr_arg *bpia; + struct beripic_cookie *bpc; + int error; + u_long hirq, src, tid; + + sc = device_get_softc(ic); + + src = rman_get_start(irq); + + KASSERT(src < sc->bp_nsrcs, ("source (%lu) out of range 0-%d", + src, sc->bp_nsrcs - 1)); + + bpia = malloc(sizeof(*bpia), M_BERIPIC, M_WAITOK|M_ZERO); + bpia->filter = filter; + bpia->intr = intr; + bpia->arg = arg; + bpia->irq = irq; +#ifdef __mips__ + bpia->counter = sc->bp_counters[src]; + bp_set_counter_name(ic, child, src); +#endif + + bpc = malloc(sizeof(*bpc), M_BERIPIC, M_WAITOK|M_ZERO); + bpc->bpia = bpia; + + mtx_lock(&(sc->bp_cfgmtx)); + bpc->hirq = sc->bp_irqs[sc->bp_next_irq]; + hirq = rman_get_start(bpc->hirq); + tid = sc->bp_next_tid; + + error = BUS_SETUP_INTR(device_get_parent(ic), ic, bpc->hirq, flags, + beripic_filter, intr == NULL ? NULL : beripic_intr, bpia, + &(bpc->cookie)); + if (error != 0) + goto err; + +#ifdef NOTYET +#ifdef SMP + /* XXX: bind ithread to cpu */ + sc->bp_next_tid++; + if (sc->bp_next_tid >= sc->bp_nthreads) + sc->bp_next_tid = 0; +#endif +#endif + if (sc->bp_next_tid == 0) { + sc->bp_next_irq++; + if (sc->bp_next_irq >= sc->bp_nirqs) + sc->bp_next_irq = 0; + } + mtx_unlock(&(sc->bp_cfgmtx)); + + *cookiep = bpc; + + bp_config_source(ic, rman_get_start(irq), 1, tid, hirq); + + return (0); +err: + free(bpc, M_BERIPIC); + free(bpia, M_BERIPIC); + + return (error); +} + +static int +beripic_teardown_intr(device_t dev, device_t child, struct resource *irq, + void *cookie) +{ + struct beripic_cookie *bpc; + int error; + + bpc = cookie; + + bp_config_source(dev, rman_get_start(irq), 0, 0, 0); + + free(bpc->bpia, M_BERIPIC); + + error = BUS_TEARDOWN_INTR(device_get_parent(dev), dev, bpc->hirq, + bpc->cookie); + + free(bpc, M_BERIPIC); + + return (error); +} + +static int +beripic_filter(void *arg) +{ + struct beripic_intr_arg *bpic; + + bpic = arg; + +#ifdef __mips__ + mips_intrcnt_inc(bpic->counter); +#endif + + /* XXX: Add a check that our source is high */ + + if (bpic->filter == NULL) + return (FILTER_SCHEDULE_THREAD); + + return (bpic->filter(bpic->arg)); +} + +static void +beripic_intr(void *arg) +{ + struct beripic_intr_arg *bpic; + + bpic = arg; + + KASSERT(bpic->intr != NULL, + ("%s installed, but no child intr", __func__)); + + bpic->intr(bpic->arg); +} + +#ifdef SMP +static void +beripic_setup_ipi(device_t ic, u_int tid, u_int ipi_irq) +{ + + bp_config_source(ic, BP_FIRST_SOFT + tid, 1, tid, ipi_irq); +} + +static void +beripic_send_ipi(device_t ic, u_int tid) +{ + struct beripic_softc *sc; + uint64_t bit; + + sc = device_get_softc(ic); + + KASSERT(tid < sc->bp_nsoft, ("tid (%d) too large\n", tid)); + + printf("sending ipi to %d soft intrs %jx\n", tid, + bus_space_read_8(sc->bp_read_bst, sc->bp_read_bsh, 8)); + + bit = 1ULL << (tid % 64); + bus_space_write_8(sc->bp_set_bst, sc->bp_set_bsh, + (BP_FIRST_SOFT / 8) + (tid / 64), bit); + + printf("sent ipi to %d soft intrs %jx\n", tid, + bus_space_read_8(sc->bp_read_bst, sc->bp_read_bsh, 8)); +} + +static void +beripic_clear_ipi(device_t ic, u_int tid) +{ + struct beripic_softc *sc; + uint64_t bit; + + sc = device_get_softc(ic); + + KASSERT(tid < sc->bp_nsoft, ("tid (%d) to large\n", tid)); + + bit = 1ULL << (tid % 64); + bus_space_write_8(sc->bp_clear_bst, sc->bp_clear_bsh, + (BP_FIRST_SOFT / 8) + (tid / 64), bit); +} +#endif + +devclass_t beripic_devclass; + +static device_method_t beripic_fdt_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, beripic_fdt_probe), + DEVMETHOD(device_attach, beripic_fdt_attach), + + DEVMETHOD(fdt_ic_activate_intr, beripic_activate_intr), + DEVMETHOD(fdt_ic_alloc_intr, beripic_alloc_intr), + DEVMETHOD(fdt_ic_config_intr, beripic_config_intr), + DEVMETHOD(fdt_ic_deactivate_intr, beripic_deactivate_intr), + DEVMETHOD(fdt_ic_release_intr, beripic_release_intr), + DEVMETHOD(fdt_ic_setup_intr, beripic_setup_intr), + DEVMETHOD(fdt_ic_teardown_intr, beripic_teardown_intr), + +#ifdef SMP + DEVMETHOD(fdt_ic_setup_ipi, beripic_setup_ipi), + DEVMETHOD(fdt_ic_clear_ipi, beripic_clear_ipi), + DEVMETHOD(fdt_ic_send_ipi, beripic_send_ipi), +#endif + + { 0, 0 }, +}; + +static driver_t beripic_fdt_driver = { + "beripic", + beripic_fdt_methods, + sizeof(struct beripic_softc) +}; + +DRIVER_MODULE(beripic, simplebus, beripic_fdt_driver, beripic_devclass, 0, 0); diff --git a/sys/mips/beri/files.beri b/sys/mips/beri/files.beri index fdae914add0f..7bdcb3176232 100644 --- a/sys/mips/beri/files.beri +++ b/sys/mips/beri/files.beri @@ -17,5 +17,6 @@ dev/terasic/mtl/terasic_mtl_reg.c optional terasic_mtl dev/terasic/mtl/terasic_mtl_syscons.c optional terasic_mtl dev/terasic/mtl/terasic_mtl_text.c optional terasic_mtl mips/beri/beri_machdep.c standard +mips/beri/beri_pic.c optional fdt mips/mips/intr_machdep.c standard mips/mips/tick.c standard