svn commit: r317095 - in head/sys: boot/fdt/dts/mips mips/beri mips/conf
Ruslan Bukin
br at FreeBSD.org
Tue Apr 18 17:20:05 UTC 2017
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 at 0 {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ beripic: beripic at 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 at 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 at 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 at 0 {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ beripic0: beripic at 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 at 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 at 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 at 0 {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ beripic0: beripic at 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 at 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 at 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 at 0 {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ beripic0: beripic at 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 at 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 at 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 <br at bsdpad.com>
* Copyright (c) 2013 SRI International
* All rights reserved.
*
@@ -28,6 +29,8 @@
* SUCH DAMAGE.
*/
+#include "opt_platform.h"
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -37,221 +40,118 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
+#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <machine/bus.h>
-#include <machine/intr_machdep.h>
+#include <machine/intr.h>
+#ifdef SMP
+#include <mips/beri/beri_mp.h>
+#endif
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-#include <dev/fdt/fdt_common.h>
+#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 ***
More information about the svn-src-head
mailing list