From owner-p4-projects@FreeBSD.ORG Fri Mar 22 03:25:34 2013 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 92F9E6E1; Fri, 22 Mar 2013 03:25:34 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 3A96B6DF for ; Fri, 22 Mar 2013 03:25:34 +0000 (UTC) (envelope-from brooks@freebsd.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:1900:2254:2068::682:0]) by mx1.freebsd.org (Postfix) with ESMTP id 1DFCCCD3 for ; Fri, 22 Mar 2013 03:25:34 +0000 (UTC) Received: from skunkworks.freebsd.org ([127.0.1.74]) by skunkworks.freebsd.org (8.14.6/8.14.6) with ESMTP id r2M3PXNw014237 for ; Fri, 22 Mar 2013 03:25:33 GMT (envelope-from brooks@freebsd.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.6/8.14.6/Submit) id r2M3PX8C014234 for perforce@freebsd.org; Fri, 22 Mar 2013 03:25:33 GMT (envelope-from brooks@freebsd.org) Date: Fri, 22 Mar 2013 03:25:33 GMT Message-Id: <201303220325.r2M3PX8C014234@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to brooks@freebsd.org using -f From: Brooks Davis Subject: PERFORCE change 223121 for review To: Perforce Change Reviews Precedence: bulk X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.14 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 22 Mar 2013 03:25:34 -0000 http://p4web.freebsd.org/@@223121?ac=10 Change 223121 by brooks@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@0 { compatible = "sri-cambridge,beri"; }; @@ -70,6 +73,24 @@ reg = <0x0 0x40000000>; // 1G at 0x0 }; + 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>; + /* + * Ideally we'd have phandle to our core here so we + * can query things like nthreads. + */ + } + serial@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@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 #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