From owner-svn-src-all@freebsd.org Tue Apr 18 17:20:05 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 391CDD44F5F; Tue, 18 Apr 2017 17:20:05 +0000 (UTC) (envelope-from br@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D97AC914; Tue, 18 Apr 2017 17:20:04 +0000 (UTC) (envelope-from br@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v3IHK4t6003310; Tue, 18 Apr 2017 17:20:04 GMT (envelope-from br@FreeBSD.org) Received: (from br@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v3IHK3mJ003306; Tue, 18 Apr 2017 17:20:03 GMT (envelope-from br@FreeBSD.org) Message-Id: <201704181720.v3IHK3mJ003306@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: br set sender to br@FreeBSD.org using -f From: Ruslan Bukin Date: Tue, 18 Apr 2017 17:20:03 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r317095 - in head/sys: boot/fdt/dts/mips mips/beri mips/conf X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 18 Apr 2017 17:20:05 -0000 Author: br Date: Tue Apr 18 17:20:03 2017 New Revision: 317095 URL: https://svnweb.freebsd.org/changeset/base/317095 Log: Switch BERI Programmable Interrupt Controller to INTRNG. Sponsored by: DARPA, AFRL Deleted: head/sys/mips/beri/beri_simplebus.c head/sys/mips/beri/fdt_ic_if.m Modified: head/sys/boot/fdt/dts/mips/beri-netfpga.dts head/sys/boot/fdt/dts/mips/beri-sim.dts head/sys/boot/fdt/dts/mips/beripad-de4.dts head/sys/boot/fdt/dts/mips/beripad-sockit.dts head/sys/mips/beri/beri_pic.c head/sys/mips/beri/files.beri head/sys/mips/conf/std.BERI Modified: head/sys/boot/fdt/dts/mips/beri-netfpga.dts ============================================================================== --- head/sys/boot/fdt/dts/mips/beri-netfpga.dts Tue Apr 18 16:27:48 2017 (r317094) +++ head/sys/boot/fdt/dts/mips/beri-netfpga.dts Tue Apr 18 17:20:03 2017 (r317095) @@ -87,30 +87,35 @@ reg = <0x0 0x0FFFFFFF>; // ~256M at 0x0 }; + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + beripic: beripic@7f804000 { + compatible = "sri-cambridge,beri-pic"; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + reg = <0x7f804000 0x400 + 0x7f806000 0x10 + 0x7f806080 0x10 + 0x7f806100 0x10>; + interrupts = < 2 3 4 5 6 >; + hard-interrupt-sources = <64>; + soft-interrupt-sources = <64>; + interrupt-parent = <&cpuintc>; + }; + soc { #address-cells = <1>; #size-cells = <1>; #interrupt-cells = <1>; - /* - * Declare mips,mips4k since BERI doesn't (yet) have a PIC, so - * we use mips4k coprocessor 0 interrupt management directly. - */ compatible = "simple-bus", "mips,mips4k"; - - beripic: beripic@7f804000 { - compatible = "sri-cambridge,beri-pic"; - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <1>; - reg = <0x7f804000 0x400 - 0x7f806000 0x10 - 0x7f806080 0x10 - 0x7f806100 0x10>; - interrupts = <0 1 2 3 4>; - hard-interrupt-sources = <64>; - soft-interrupt-sources = <64>; - }; + ranges; serial0: serial@7f000000 { compatible = "altera,jtag_uart-11_0"; Modified: head/sys/boot/fdt/dts/mips/beri-sim.dts ============================================================================== --- head/sys/boot/fdt/dts/mips/beri-sim.dts Tue Apr 18 16:27:48 2017 (r317094) +++ head/sys/boot/fdt/dts/mips/beri-sim.dts Tue Apr 18 17:20:03 2017 (r317095) @@ -85,30 +85,35 @@ reg = <0x0 0x4000000>; // 64M at 0x0 }; + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + beripic0: beripic@7f804000 { + compatible = "sri-cambridge,beri-pic"; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + reg = <0x7f804000 0x400 + 0x7f806000 0x10 + 0x7f806080 0x10 + 0x7f806100 0x10>; + interrupts = < 2 3 4 5 6 >; + hard-interrupt-sources = <64>; + soft-interrupt-sources = <64>; + interrupt-parent = <&cpuintc>; + }; + soc { #address-cells = <1>; #size-cells = <1>; #interrupt-cells = <1>; - /* - * Declare mips,mips4k since BERI doesn't (yet) have a PIC, so - * we use mips4k coprocessor 0 interrupt management directly. - */ compatible = "simple-bus", "mips,mips4k"; - - beripic0: beripic@7f804000 { - compatible = "sri-cambridge,beri-pic"; - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <1>; - reg = <0x7f804000 0x400 - 0x7f806000 0x10 - 0x7f806080 0x10 - 0x7f806100 0x10>; - interrupts = <0 1 2 3 4>; - hard-interrupt-sources = <64>; - soft-interrupt-sources = <64>; - }; + ranges; serial@7f000000 { compatible = "altera,jtag_uart-11_0"; Modified: head/sys/boot/fdt/dts/mips/beripad-de4.dts ============================================================================== --- head/sys/boot/fdt/dts/mips/beripad-de4.dts Tue Apr 18 16:27:48 2017 (r317094) +++ head/sys/boot/fdt/dts/mips/beripad-de4.dts Tue Apr 18 17:20:03 2017 (r317095) @@ -85,30 +85,35 @@ reg = <0x0 0x40000000>; // 1G at 0x0 }; + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + beripic0: beripic@7f804000 { + compatible = "sri-cambridge,beri-pic"; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + reg = <0x7f804000 0x400 + 0x7f806000 0x10 + 0x7f806080 0x10 + 0x7f806100 0x10>; + interrupts = < 2 3 4 5 6 >; + hard-interrupt-sources = <64>; + soft-interrupt-sources = <64>; + interrupt-parent = <&cpuintc>; + }; + soc { #address-cells = <1>; #size-cells = <1>; #interrupt-cells = <1>; - /* - * Declare mips,mips4k since BERI doesn't (yet) have a PIC, so - * we use mips4k coprocessor 0 interrupt management directly. - */ compatible = "simple-bus", "mips,mips4k"; - - beripic0: beripic@7f804000 { - compatible = "sri-cambridge,beri-pic"; - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <1>; - reg = <0x7f804000 0x400 - 0x7f806000 0x10 - 0x7f806080 0x10 - 0x7f806100 0x10>; - interrupts = <0 1 2 3 4>; - hard-interrupt-sources = <64>; - soft-interrupt-sources = <64>; - }; + ranges; serial@7f002100 { compatible = "ns16550"; Modified: head/sys/boot/fdt/dts/mips/beripad-sockit.dts ============================================================================== --- head/sys/boot/fdt/dts/mips/beripad-sockit.dts Tue Apr 18 16:27:48 2017 (r317094) +++ head/sys/boot/fdt/dts/mips/beripad-sockit.dts Tue Apr 18 17:20:03 2017 (r317095) @@ -83,30 +83,35 @@ reg = <0x0 0x10000000>; /* 256MB at 0x0 */ }; + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + beripic0: beripic@7f804000 { + compatible = "sri-cambridge,beri-pic"; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + reg = <0x0 0x7f804000 0x0 0x400 + 0x0 0x7f806000 0x0 0x10 + 0x0 0x7f806080 0x0 0x10 + 0x0 0x7f806100 0x0 0x10>; + interrupts = < 2 3 4 5 6 >; + hard-interrupt-sources = <64>; + soft-interrupt-sources = <64>; + interrupt-parent = <&cpuintc>; + }; + soc { #address-cells = <2>; #size-cells = <2>; #interrupt-cells = <1>; - /* - * Declare mips,mips4k since BERI doesn't (yet) have a PIC, so - * we use mips4k coprocessor 0 interrupt management directly. - */ compatible = "simple-bus", "mips,mips4k"; - - beripic0: beripic@7f804000 { - compatible = "sri-cambridge,beri-pic"; - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <1>; - reg = <0x0 0x7f804000 0x0 0x400 - 0x0 0x7f806000 0x0 0x10 - 0x0 0x7f806080 0x0 0x10 - 0x0 0x7f806100 0x0 0x10>; - interrupts = <0 1 2 3 4>; - hard-interrupt-sources = <64>; - soft-interrupt-sources = <64>; - }; + ranges; pio0: pio@7f020000 { compatible = "altr,pio"; Modified: head/sys/mips/beri/beri_pic.c ============================================================================== --- head/sys/mips/beri/beri_pic.c Tue Apr 18 16:27:48 2017 (r317094) +++ head/sys/mips/beri/beri_pic.c Tue Apr 18 17:20:03 2017 (r317095) @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2017 Ruslan Bukin * Copyright (c) 2013 SRI International * All rights reserved. * @@ -28,6 +29,8 @@ * SUCH DAMAGE. */ +#include "opt_platform.h" + #include __FBSDID("$FreeBSD$"); @@ -37,221 +40,118 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include -#include +#include +#ifdef SMP +#include +#endif + +#include +#include #include #include -#include +#include "pic_if.h" -#include "fdt_ic_if.h" +#define BP_NUM_HARD_IRQS 5 +#define BP_NUM_IRQS 32 +/* We use hard irqs 15-31 as soft */ +#define BP_FIRST_SOFT 16 + +#define BP_CFG_IRQ_S 0 +#define BP_CFG_IRQ_M (0xf << BP_CFG_IRQ_S) +#define BP_CFG_TID_S 8 +#define BP_CFG_TID_M (0x7FFFFF << BP_CFG_TID_S) +#define BP_CFG_ENABLE (1 << 31) + +enum { + BP_CFG, + BP_IP_READ, + BP_IP_SET, + BP_IP_CLEAR +}; 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 beri_pic_isrc { + struct intr_irqsrc isrc; + u_int irq; + uint32_t mips_hard_irq; }; -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 hirq { + uint32_t irq; + struct beripic_softc *sc; }; -struct beripic_cookie { - struct beripic_intr_arg *bpia; - struct resource *hirq; - void *cookie; +struct beripic_softc { + device_t dev; + uint32_t nirqs; + struct beri_pic_isrc irqs[BP_NUM_IRQS]; + struct resource *res[4 + BP_NUM_HARD_IRQS]; + void *ih[BP_NUM_HARD_IRQS]; + struct hirq hirq[BP_NUM_HARD_IRQS]; + uint8_t mips_hard_irq_idx; }; -#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 struct resource_spec beri_pic_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_MEMORY, 1, RF_ACTIVE }, + { SYS_RES_MEMORY, 2, RF_ACTIVE }, + { SYS_RES_MEMORY, 3, RF_ACTIVE }, + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 1, RF_ACTIVE }, + { SYS_RES_IRQ, 2, RF_ACTIVE }, + { SYS_RES_IRQ, 3, RF_ACTIVE }, + { SYS_RES_IRQ, 4, RF_ACTIVE }, + { -1, 0 } +}; -static void -bp_detach_resources(device_t dev) +static int +beri_pic_intr(void *arg) { struct beripic_softc *sc; + struct intr_irqsrc *isrc; + struct hirq *h; + uint64_t intr; + uint64_t reg; int i; - sc = device_get_softc(dev); + h = arg; + sc = h->sc; - 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; -} + intr = bus_read_8(sc->res[BP_IP_READ], 0); + while ((i = fls(intr)) != 0) { + i--; + intr &= ~(1u << i); -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); -} + isrc = &sc->irqs[i].isrc; -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); -} + reg = bus_read_8(sc->res[BP_CFG], i * 8); + if ((reg & BP_CFG_IRQ_M) != h->irq) { + continue; + } + if ((reg & (BP_CFG_ENABLE)) == 0) { + continue; + } -#ifdef __mips__ -static void -bp_set_counter_name(device_t ic, device_t child, int src) -{ - struct beripic_softc *sc; - char name[MAXCOMLEN + 1]; + if (intr_isrc_dispatch(isrc, curthread->td_intr_frame) != 0) { + device_printf(sc->dev, "Stray interrupt %u detected\n", i); + } - sc = device_get_softc(ic); + bus_write_8(sc->res[BP_IP_CLEAR], 0, (1 << i)); + } - 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); + return (FILTER_HANDLED); } -#endif static int -beripic_fdt_probe(device_t dev) +beripic_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) @@ -261,443 +161,208 @@ beripic_fdt_probe(device_t dev) return (ENXIO); device_set_desc(dev, "BERI Programmable Interrupt Controller"); + return (BUS_PROBE_DEFAULT); } static int -beripic_fdt_attach(device_t dev) +beripic_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; + struct beri_pic_isrc *pic_isrc; + const char *name; + struct intr_irqsrc *isrc; + intptr_t xref; + uint32_t unit; + int err; + int i; sc = device_get_softc(dev); - sc->bp_dev = dev; - - mtx_init(&sc->bp_cfgmtx, "beripic config lock", NULL, MTX_DEF); + sc->dev = dev; - /* - * 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; + if (bus_alloc_resources(dev, beri_pic_spec, sc->res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); } - 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 + xref = OF_xref_from_node(ofw_bus_get_node(dev)); + name = device_get_nameunit(dev); + unit = device_get_unit(dev); + sc->nirqs = BP_NUM_IRQS; + + for (i = 0; i < sc->nirqs; i++) { + sc->irqs[i].irq = i; + isrc = &sc->irqs[i].isrc; + + /* Assign mips hard irq number. */ + pic_isrc = (struct beri_pic_isrc *)isrc; + pic_isrc->mips_hard_irq = sc->mips_hard_irq_idx++; + /* Last IRQ is used for IPIs. */ + if (sc->mips_hard_irq_idx >= (BP_NUM_HARD_IRQS - 1)) { + sc->mips_hard_irq_idx = 0; + } - 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; + err = intr_isrc_register(isrc, sc->dev, + 0, "pic%d,%d", unit, i); + bus_write_8(sc->res[BP_CFG], i * 8, 0); } - 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; + /* + * Now, when everything is initialized, it's right time to + * register interrupt controller to interrupt framefork. + */ + if (intr_pic_register(dev, xref) == NULL) { + device_printf(dev, "could not register PIC\n"); + return (ENXIO); } - 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); + /* Last IRQ is used for IPIs. */ + for (i = 0; i < (BP_NUM_HARD_IRQS - 1); i++) { + sc->hirq[i].sc = sc; + sc->hirq[i].irq = i; + if (bus_setup_intr(dev, sc->res[4+i], INTR_TYPE_CLK, + beri_pic_intr, NULL, &sc->hirq[i], sc->ih[i])) { + device_printf(dev, "could not setup irq handler\n"); + intr_pic_deregister(dev, xref); + return (ENXIO); } - - 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) +static void +beri_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc) { + struct beri_pic_isrc *pic_isrc; struct beripic_softc *sc; - struct resource *rv; - - sc = device_get_softc(ic); + uint64_t reg; - 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)); -} + sc = device_get_softc(dev); + pic_isrc = (struct beri_pic_isrc *)isrc; -static int -beripic_deactivate_intr(device_t ic, struct resource *r) -{ - - return (rman_deactivate_resource(r)); + reg = BP_CFG_ENABLE; + reg |= (pic_isrc->mips_hard_irq << BP_CFG_IRQ_S); + bus_write_8(sc->res[BP_CFG], pic_isrc->irq * 8, reg); } -static int -beripic_config_intr(device_t dev, int irq, enum intr_trigger trig, - enum intr_polarity pol) +static void +beri_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc) { + struct beri_pic_isrc *pic_isrc; + struct beripic_softc *sc; + uint64_t reg; - if (trig != INTR_TRIGGER_CONFORM || pol != INTR_POLARITY_CONFORM) - return (EINVAL); + sc = device_get_softc(dev); + pic_isrc = (struct beri_pic_isrc *)isrc; - return (0); + reg = bus_read_8(sc->res[BP_CFG], pic_isrc->irq * 8); + reg &= ~BP_CFG_ENABLE; + bus_write_8(sc->res[BP_CFG], pic_isrc->irq * 8, reg); } 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) +beri_pic_map_intr(device_t dev, struct intr_map_data *data, + struct intr_irqsrc **isrcp) { 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 + struct intr_map_data_fdt *daf; + uint32_t irq; - 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; + sc = device_get_softc(dev); + daf = (struct intr_map_data_fdt *)data; -#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)); + if (data == NULL || data->type != INTR_MAP_DATA_FDT || + daf->ncells != 1 || daf->cells[0] >= sc->nirqs) + return (EINVAL); - *cookiep = bpc; + irq = daf->cells[0]; - bp_config_source(ic, rman_get_start(irq), 1, tid, hirq); + *isrcp = &sc->irqs[irq].isrc; 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) +static void +beri_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc) { - 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)); + beri_pic_enable_intr(dev, isrc); } static void -beripic_intr(void *arg) +beri_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc) { - struct beripic_intr_arg *bpic; - - bpic = arg; - - KASSERT(bpic->intr != NULL, - ("%s installed, but no child intr", __func__)); - bpic->intr(bpic->arg); + beri_pic_disable_intr(dev, isrc); } *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***