PERFORCE change 223121 for review
Brooks Davis
brooks at FreeBSD.org
Fri Mar 22 03:25:34 UTC 2013
http://p4web.freebsd.org/@@223121?ac=10
Change 223121 by brooks at brooks_zenith on 2013/03/22 03:24:48
Implement a driver for Robert Norton's PIC as an FDT
interrupt controller. Devices whose interrupt-parent property
points to a beripic device (or any other interrupt controller
that registers as an FDT IC) will have their interrupt allocation,
activation, and setup operations routed through the IC rather
than down the traditional bus hierarchy.
This driver largely abstracts the underlying CPU away allowing
the PIC to be implemented on CPU's other than BERI. Due to
insufficent abstractions in the FreeBSD codebase a small amount
of MIPS specific code is currently required in fdt_mips.c and
implementing counters properly will likely require a bit more
MIPS specific code.
TODO:
* implement filters for each source.
* add per-source counters.
* SMP support.
Affected files ...
.. //depot/projects/ctsrd/beribsd/src/sys/boot/fdt/dts/beripad-de4.dts#19 edit
.. //depot/projects/ctsrd/beribsd/src/sys/conf/files#16 edit
.. //depot/projects/ctsrd/beribsd/src/sys/dev/fdt/fdt_common.c#7 edit
.. //depot/projects/ctsrd/beribsd/src/sys/dev/fdt/fdt_common.h#6 edit
.. //depot/projects/ctsrd/beribsd/src/sys/dev/fdt/fdt_ic_if.m#1 add
.. //depot/projects/ctsrd/beribsd/src/sys/dev/fdt/fdt_mips.c#5 edit
.. //depot/projects/ctsrd/beribsd/src/sys/dev/fdt/simplebus.c#4 edit
.. //depot/projects/ctsrd/beribsd/src/sys/mips/beri/beri_pic.c#1 add
.. //depot/projects/ctsrd/beribsd/src/sys/mips/beri/files.beri#31 edit
Differences ...
==== //depot/projects/ctsrd/beribsd/src/sys/boot/fdt/dts/beripad-de4.dts#19 (text+ko) ====
@@ -48,6 +48,9 @@
#size-cells = <1>;
cpus {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
cpu at 0 {
compatible = "sri-cambridge,beri";
};
@@ -70,6 +73,24 @@
reg = <0x0 0x40000000>; // 1G at 0x0
};
+ 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>;
+ /*
+ * Ideally we'd have phandle to our core here so we
+ * can query things like nthreads.
+ */
+ }
+
serial at 7f000000 {
compatible = "altera,jtag_uart-11_0";
reg = <0x7f000000 0x40>;
@@ -147,6 +168,7 @@
0x7f007420 0x20>;
/* RX, TX */
interrupts = <1 2>;
+ //interrupt-parent =<&beripic>;
};
ethernet at 7f005000 {
==== //depot/projects/ctsrd/beribsd/src/sys/conf/files#16 (text+ko) ====
@@ -1293,6 +1293,7 @@
dev/fatm/if_fatm.c optional fatm pci
dev/fb/splash.c optional splash
dev/fdt/fdt_common.c optional fdt
+dev/fdt/fdt_ic_if.m optional fdt
dev/fdt/fdt_pci.c optional fdt pci
dev/fdt/fdt_slicer.c optional fdt cfi | fdt nand
dev/fdt/fdt_static_dtb.S optional fdt fdt_dtb_static
==== //depot/projects/ctsrd/beribsd/src/sys/dev/fdt/fdt_common.c#7 (text+ko) ====
@@ -63,6 +63,8 @@
vm_offset_t fdt_immr_va;
vm_offset_t fdt_immr_size;
+struct fdt_ic_list fdt_ic_list_head = SLIST_HEAD_INITIALIZER(fdt_ic_list_head);
+
int
fdt_get_range(phandle_t node, int range_id, u_long *base, u_long *size)
{
==== //depot/projects/ctsrd/beribsd/src/sys/dev/fdt/fdt_common.h#6 (text+ko) ====
@@ -70,6 +70,13 @@
};
extern struct fdt_fixup_entry fdt_fixup_table[];
+extern SLIST_HEAD(fdt_ic_list, fdt_ic) fdt_ic_list_head;
+struct fdt_ic {
+ SLIST_ENTRY(fdt_ic) fdt_ics;
+ ihandle_t iph;
+ device_t dev;
+};
+
extern vm_paddr_t fdt_immr_pa;
extern vm_offset_t fdt_immr_va;
extern vm_offset_t fdt_immr_size;
==== //depot/projects/ctsrd/beribsd/src/sys/dev/fdt/fdt_mips.c#5 (text+ko) ====
@@ -68,7 +68,26 @@
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
};
==== //depot/projects/ctsrd/beribsd/src/sys/dev/fdt/simplebus.c#4 (text+ko) ====
@@ -47,6 +47,7 @@
#include <dev/ofw/openfirm.h>
#include "fdt_common.h"
+#include "fdt_ic_if.h"
#include "ofw_bus_if.h"
#ifdef DEBUG
@@ -80,9 +81,18 @@
static int simplebus_print_child(device_t, device_t);
static int simplebus_setup_intr(device_t, device_t, struct resource *, int,
driver_filter_t *, driver_intr_t *, void *, void **);
+static int simplebus_teardown_intr(device_t, device_t, struct resource *,
+ void *);
+static int simplebus_activate_resource(device_t, device_t, int, int,
+ struct resource *);
static struct resource *simplebus_alloc_resource(device_t, device_t, int,
int *, u_long, u_long, u_long, u_int);
+static int simplebus_deactivate_resource(device_t, device_t, int, int,
+ struct resource *);
+static int simplebus_release_resource(device_t, device_t, int, int,
+ struct resource *);
+static device_t simplebus_get_interrupt_parent(device_t);
static struct resource_list *simplebus_get_resource_list(device_t, device_t);
static ofw_bus_get_devinfo_t simplebus_get_devinfo;
@@ -102,11 +112,11 @@
/* Bus interface */
DEVMETHOD(bus_print_child, simplebus_print_child),
DEVMETHOD(bus_alloc_resource, simplebus_alloc_resource),
- DEVMETHOD(bus_release_resource, bus_generic_release_resource),
- DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
- DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_release_resource, simplebus_release_resource),
+ DEVMETHOD(bus_activate_resource, simplebus_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, simplebus_deactivate_resource),
DEVMETHOD(bus_setup_intr, simplebus_setup_intr),
- DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_teardown_intr, simplebus_teardown_intr),
DEVMETHOD(bus_get_resource_list, simplebus_get_resource_list),
/* OFW bus interface */
@@ -238,6 +248,7 @@
simplebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
+ device_t ic;
struct simplebus_devinfo *di;
struct resource_list_entry *rle;
@@ -263,10 +274,53 @@
count = rle->count;
}
+ if (type == SYS_RES_IRQ &&
+ (ic = simplebus_get_interrupt_parent(child)) != NULL)
+ return(FDT_IC_ALLOC_INTR(ic, child, rid, start, flags));
+
return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
count, flags));
}
+static int
+simplebus_activate_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+ device_t ic;
+
+ if (type == SYS_RES_IRQ &&
+ (ic = simplebus_get_interrupt_parent(child)) != NULL)
+ return (FDT_IC_ACTIVATE_INTR(ic, r));
+
+ return (bus_generic_activate_resource(dev, child, type, rid, r));
+}
+
+static int
+simplebus_deactivate_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+ device_t ic;
+
+ if (type == SYS_RES_IRQ &&
+ (ic = simplebus_get_interrupt_parent(child)) != NULL)
+ return (FDT_IC_DEACTIVATE_INTR(ic, r));
+
+ return (bus_generic_deactivate_resource(dev, child, type, rid, r));
+}
+
+static int
+simplebus_release_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+ device_t ic;
+
+ if (type == SYS_RES_IRQ &&
+ (ic = simplebus_get_interrupt_parent(child)) != NULL)
+ return (FDT_IC_RELEASE_INTR(ic, r));
+
+ return (bus_generic_release_resource(dev, child, type, rid, r));
+}
+
static struct resource_list *
simplebus_get_resource_list(device_t bus, device_t child)
{
@@ -276,15 +330,40 @@
return (&di->di_res);
}
+static device_t
+simplebus_get_interrupt_parent(device_t dev)
+{
+ struct simplebus_devinfo *di;
+ struct fdt_ic *ic;
+ ihandle_t iph;
+ phandle_t ph;
+
+ di = device_get_ivars(dev);
+ if (di == NULL)
+ return (NULL);
+
+ if (OF_getprop(di->di_ofw.obd_node, "interrupt-parent", &iph,
+ sizeof(iph)) > 0) {
+ iph = fdt32_to_cpu(iph);
+ ph = OF_instance_to_package(iph);
+ SLIST_FOREACH(ic, &fdt_ic_list_head, fdt_ics) {
+ if (ic->iph == ph)
+ return (ic->dev);
+ }
+ }
+ return (NULL);
+}
+
static int
simplebus_setup_intr(device_t bus, device_t child, struct resource *res,
int flags, driver_filter_t *filter, driver_intr_t *ihand, void *arg,
void **cookiep)
{
struct simplebus_devinfo *di;
+ device_t ic;
enum intr_trigger trig;
enum intr_polarity pol;
- int error, rid;
+ int error, irq, rid;
if (device_get_parent(child) != bus)
return (ECHILD);
@@ -300,20 +379,41 @@
if (rid >= DI_MAX_INTR_NUM)
return (ENOENT);
+ ic = simplebus_get_interrupt_parent(child);
+
trig = di->di_intr_sl[rid].trig;
pol = di->di_intr_sl[rid].pol;
if (trig != INTR_TRIGGER_CONFORM || pol != INTR_POLARITY_CONFORM) {
- error = bus_generic_config_intr(bus, rman_get_start(res),
- trig, pol);
+ irq = rman_get_start(res);
+ if (ic != NULL)
+ error = FDT_IC_CONFIG_INTR(ic, irq, trig, pol);
+ else
+ error = bus_generic_config_intr(bus, irq, trig, pol);
if (error)
return (error);
}
- error = bus_generic_setup_intr(bus, child, res, flags, filter, ihand,
- arg, cookiep);
+ if (ic != NULL)
+ error = FDT_IC_SETUP_INTR(ic, child, res, flags, filter,
+ ihand, arg, cookiep);
+ else
+ error = bus_generic_setup_intr(bus, child, res, flags, filter,
+ ihand, arg, cookiep);
return (error);
}
+static int
+simplebus_teardown_intr(device_t bus, device_t child, struct resource *res,
+ void *cookie)
+{
+ device_t ic;
+
+ if ((ic = simplebus_get_interrupt_parent(child)) != NULL)
+ return (FDT_IC_TEARDOWN_INTR(ic, child, res, cookie));
+
+ return (bus_generic_teardown_intr(bus, child, res, cookie));
+}
+
static const struct ofw_bus_devinfo *
simplebus_get_devinfo(device_t bus, device_t child)
{
==== //depot/projects/ctsrd/beribsd/src/sys/mips/beri/files.beri#31 (text+ko) ====
@@ -19,5 +19,6 @@
mips/beri/beri_asm.S standard
mips/beri/beri_machdep.c standard
mips/beri/beri_mp.c optional smp
+mips/beri/beri_pic.c optional fdt
mips/mips/intr_machdep.c standard
mips/mips/tick.c standard
More information about the p4-projects
mailing list