Date: Sat, 1 Feb 2014 17:41:55 +0000 (UTC) From: Nathan Whitehorn <nwhitehorn@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r261352 - in head/sys: conf dev/fdt mips/beri Message-ID: <201402011741.s11HftLN085317@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: nwhitehorn Date: Sat Feb 1 17:41:54 2014 New Revision: 261352 URL: http://svnweb.freebsd.org/changeset/base/261352 Log: Provide a simpler and more standards-compliant simplebus implementation to get the Routerboard 800 up and running with the vendor device tree. This does not implement some BERI-specific features (which hopefully won't be necessary soon), so move the old code to mips/beri, with a higher attach priority when built, until MIPS interrupt domain support is rearranged. Added: head/sys/mips/beri/beri_simplebus.c - copied, changed from r261350, head/sys/dev/fdt/simplebus.c head/sys/mips/beri/fdt_ic_if.m - copied unchanged from r261350, head/sys/dev/fdt/fdt_ic_if.m Deleted: head/sys/dev/fdt/fdt_ic_if.m Modified: head/sys/conf/files head/sys/dev/fdt/simplebus.c head/sys/mips/beri/files.beri Modified: head/sys/conf/files ============================================================================== --- head/sys/conf/files Sat Feb 1 17:17:35 2014 (r261351) +++ head/sys/conf/files Sat Feb 1 17:41:54 2014 (r261352) @@ -1367,7 +1367,6 @@ dev/fb/fbd.c optional fbd | vt dev/fb/fb_if.m standard dev/fb/splash.c optional sc splash dev/fdt/fdt_common.c optional fdt -dev/fdt/fdt_ic_if.m optional fdt dev/fdt/fdt_slicer.c optional fdt cfi | fdt nand dev/fdt/fdt_static_dtb.S optional fdt fdt_dtb_static \ dependency "$S/boot/fdt/dts/${FDT_DTS_FILE}" Modified: head/sys/dev/fdt/simplebus.c ============================================================================== --- head/sys/dev/fdt/simplebus.c Sat Feb 1 17:17:35 2014 (r261351) +++ head/sys/dev/fdt/simplebus.c Sat Feb 1 17:41:54 2014 (r261352) @@ -1,10 +1,7 @@ /*- - * Copyright (c) 2009-2010 The FreeBSD Foundation + * Copyright (c) 2013 Nathan Whitehorn * All rights reserved. * - * This software was developed by Semihalf under sponsorship from - * the FreeBSD Foundation. - * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -17,7 +14,7 @@ * 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 + * 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) @@ -29,95 +26,85 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); - -#include "opt_platform.h" #include <sys/param.h> #include <sys/systm.h> -#include <sys/ktr.h> -#include <sys/kernel.h> #include <sys/module.h> #include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> #include <sys/rman.h> -#include <sys/malloc.h> +#include <dev/ofw/openfirm.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> -#include <dev/ofw/openfirm.h> -#include "fdt_common.h" -#include "fdt_ic_if.h" -#include "ofw_bus_if.h" - -#ifdef DEBUG -#define debugf(fmt, args...) do { printf("%s(): ", __func__); \ - printf(fmt,##args); } while (0) -#else -#define debugf(fmt, args...) -#endif - -static MALLOC_DEFINE(M_SIMPLEBUS, "simplebus", "simplebus devices information"); +struct simplebus_range { + uint64_t bus; + uint64_t host; + uint64_t size; +}; struct simplebus_softc { - int sc_addr_cells; - int sc_size_cells; + device_t dev; + phandle_t node; + + struct simplebus_range *ranges; + int nranges; + + pcell_t acells, scells; }; struct simplebus_devinfo { - struct ofw_bus_devinfo di_ofw; - struct resource_list di_res; - - /* Interrupts sense-level info for this device */ - struct fdt_sense_level di_intr_sl[DI_MAX_INTR_NUM]; + struct ofw_bus_devinfo obdinfo; + struct resource_list rl; }; /* - * Prototypes. + * Bus interface. */ -static int simplebus_probe(device_t); -static int simplebus_attach(device_t); - -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 int simplebus_probe(device_t dev); +static int simplebus_attach(device_t dev); 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 void simplebus_probe_nomatch(device_t bus, device_t child); +static int simplebus_print_child(device_t bus, device_t child); -static ofw_bus_get_devinfo_t simplebus_get_devinfo; +/* + * ofw_bus interface + */ +static const struct ofw_bus_devinfo *simplebus_get_devinfo(device_t bus, + device_t child); /* - * Bus interface definition. + * local methods */ -static device_method_t simplebus_methods[] = { + +static int simplebus_fill_ranges(phandle_t node, + struct simplebus_softc *sc); +static struct simplebus_devinfo *simplebus_setup_dinfo(device_t dev, + phandle_t node); + +/* + * Driver methods. + */ +static device_method_t simplebus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, simplebus_probe), DEVMETHOD(device_attach, simplebus_attach), - DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ DEVMETHOD(bus_print_child, simplebus_print_child), + DEVMETHOD(bus_probe_nomatch, simplebus_probe_nomatch), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_alloc_resource, simplebus_alloc_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, simplebus_teardown_intr), - DEVMETHOD(bus_get_resource_list, simplebus_get_resource_list), + 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_adjust_resource, bus_generic_adjust_resource), + DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), - /* OFW bus interface */ + /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_devinfo, simplebus_get_devinfo), DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), @@ -125,7 +112,7 @@ static device_method_t simplebus_methods DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), - { 0, 0 } + DEVMETHOD_END }; static driver_t simplebus_driver = { @@ -133,18 +120,16 @@ static driver_t simplebus_driver = { simplebus_methods, sizeof(struct simplebus_softc) }; - -devclass_t simplebus_devclass; - +static devclass_t simplebus_devclass; DRIVER_MODULE(simplebus, nexus, simplebus_driver, simplebus_devclass, 0, 0); -DRIVER_MODULE(simplebus, simplebus, simplebus_driver, simplebus_devclass, 0, - 0); static int simplebus_probe(device_t dev) { - - if (!ofw_bus_is_compatible(dev, "simple-bus")) + + if (!ofw_bus_is_compatible(dev, "simple-bus") && + (ofw_bus_get_type(dev) == NULL || strcmp(ofw_bus_get_type(dev), + "soc") != 0)) return (ENXIO); device_set_desc(dev, "Flattened device tree simple bus"); @@ -155,102 +140,188 @@ simplebus_probe(device_t dev) static int simplebus_attach(device_t dev) { - device_t dev_child; - struct simplebus_devinfo *di; - struct simplebus_softc *sc; - phandle_t dt_node, dt_child; + struct simplebus_softc *sc; + struct simplebus_devinfo *di; + phandle_t node; + device_t cdev; + node = ofw_bus_get_node(dev); sc = device_get_softc(dev); + sc->dev = dev; + sc->node = node; + /* - * Walk simple-bus and add direct subordinates as our children. + * Some important numbers */ - dt_node = ofw_bus_get_node(dev); - for (dt_child = OF_child(dt_node); dt_child != 0; - dt_child = OF_peer(dt_child)) { - - /* Check and process 'status' property. */ - if (!(fdt_is_enabled(dt_child))) - continue; + sc->acells = 2; + OF_getencprop(node, "#address-cells", &sc->acells, sizeof(sc->acells)); + sc->scells = 1; + OF_getencprop(node, "#size-cells", &sc->scells, sizeof(sc->scells)); - if (!(fdt_pm_is_enabled(dt_child))) - continue; + if (simplebus_fill_ranges(node, sc) < 0) { + device_printf(dev, "could not get ranges\n"); + return (ENXIO); + } - di = malloc(sizeof(*di), M_SIMPLEBUS, M_WAITOK | M_ZERO); + /* + * In principle, simplebus could have an interrupt map, but ignore that + * for now + */ - if (ofw_bus_gen_setup_devinfo(&di->di_ofw, dt_child) != 0) { - free(di, M_SIMPLEBUS); - device_printf(dev, "could not set up devinfo\n"); + for (node = OF_child(node); node > 0; node = OF_peer(node)) { + if ((di = simplebus_setup_dinfo(dev, node)) == NULL) continue; - } - - resource_list_init(&di->di_res); - if (fdt_reg_to_rl(dt_child, &di->di_res)) { - device_printf(dev, - "%s: could not process 'reg' " - "property\n", di->di_ofw.obd_name); - ofw_bus_gen_destroy_devinfo(&di->di_ofw); - free(di, M_SIMPLEBUS); + cdev = device_add_child(dev, NULL, -1); + if (cdev == NULL) { + device_printf(dev, "<%s>: device_add_child failed\n", + di->obdinfo.obd_name); + resource_list_free(&di->rl); + ofw_bus_gen_destroy_devinfo(&di->obdinfo); + free(di, M_DEVBUF); continue; } + device_set_ivars(cdev, di); + } - if (fdt_intr_to_rl(dev, dt_child, &di->di_res, di->di_intr_sl)) { - device_printf(dev, "%s: could not process " - "'interrupts' property\n", di->di_ofw.obd_name); - resource_list_free(&di->di_res); - ofw_bus_gen_destroy_devinfo(&di->di_ofw); - free(di, M_SIMPLEBUS); - continue; - } + return (bus_generic_attach(dev)); +} - /* Add newbus device for this FDT node */ - dev_child = device_add_child(dev, NULL, -1); - if (dev_child == NULL) { - device_printf(dev, "could not add child: %s\n", - di->di_ofw.obd_name); - resource_list_free(&di->di_res); - ofw_bus_gen_destroy_devinfo(&di->di_ofw); - free(di, M_SIMPLEBUS); - continue; +static int +simplebus_fill_ranges(phandle_t node, struct simplebus_softc *sc) +{ + int host_address_cells; + cell_t *base_ranges; + ssize_t nbase_ranges; + int err; + int i, j, k; + + err = OF_searchencprop(OF_parent(node), "#address-cells", + &host_address_cells, sizeof(host_address_cells)); + if (err <= 0) + return (-1); + + nbase_ranges = OF_getproplen(node, "ranges"); + if (nbase_ranges < 0) + return (-1); + sc->nranges = nbase_ranges / sizeof(cell_t) / + (sc->acells + host_address_cells + sc->scells); + if (sc->nranges == 0) + return (0); + + sc->ranges = malloc(sc->nranges * sizeof(sc->ranges[0]), + M_DEVBUF, M_WAITOK); + base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK); + OF_getencprop(node, "ranges", base_ranges, nbase_ranges); + + for (i = 0, j = 0; i < sc->nranges; i++) { + sc->ranges[i].bus = 0; + for (k = 0; k < sc->acells; k++) { + sc->ranges[i].bus <<= 32; + sc->ranges[i].bus |= base_ranges[j++]; + } + sc->ranges[i].host = 0; + for (k = 0; k < host_address_cells; k++) { + sc->ranges[i].host <<= 32; + sc->ranges[i].host |= base_ranges[j++]; + } + sc->ranges[i].size = 0; + for (k = 0; k < sc->scells; k++) { + sc->ranges[i].size <<= 32; + sc->ranges[i].size |= base_ranges[j++]; } -#ifdef DEBUG - device_printf(dev, "added child: %s\n\n", di->di_ofw.obd_name); -#endif - device_set_ivars(dev_child, di); } - return (bus_generic_attach(dev)); + free(base_ranges, M_DEVBUF); + return (sc->nranges); } -static int -simplebus_print_child(device_t dev, device_t child) +static struct simplebus_devinfo * +simplebus_setup_dinfo(device_t dev, phandle_t node) { - device_t ip; - struct simplebus_devinfo *di; - struct resource_list *rl; - int rv; + struct simplebus_softc *sc; + struct simplebus_devinfo *ndi; + uint32_t *reg, *intr, icells; + uint64_t phys, size; + phandle_t iparent; + int i, j, k; + int nintr; + int nreg; - di = device_get_ivars(child); - rl = &di->di_res; + sc = device_get_softc(dev); - rv = 0; - rv += bus_print_child_header(dev, child); - rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx"); - rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); - if ((ip = simplebus_get_interrupt_parent(child)) != NULL) - rv += printf(" (%s)", device_get_nameunit(ip)); - rv += bus_print_child_footer(dev, child); + ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO); + if (ofw_bus_gen_setup_devinfo(&ndi->obdinfo, node) != 0) { + free(ndi, M_DEVBUF); + return (NULL); + } - return (rv); + resource_list_init(&ndi->rl); + nreg = OF_getencprop_alloc(node, "reg", sizeof(*reg), (void **)®); + if (nreg == -1) + nreg = 0; + if (nreg % (sc->acells + sc->scells) != 0) { + if (bootverbose) + device_printf(dev, "Malformed reg property on <%s>\n", + ndi->obdinfo.obd_name); + nreg = 0; + } + + for (i = 0, k = 0; i < nreg; i += sc->acells + sc->scells, k++) { + phys = size = 0; + for (j = 0; j < sc->acells; j++) { + phys <<= 32; + phys |= reg[i + j]; + } + for (j = 0; j < sc->scells; j++) { + size <<= 32; + size |= reg[i + sc->acells + j]; + } + + resource_list_add(&ndi->rl, SYS_RES_MEMORY, k, + phys, phys + size - 1, size); + } + free(reg, M_OFWPROP); + + nintr = OF_getencprop_alloc(node, "interrupts", sizeof(*intr), + (void **)&intr); + if (nintr > 0) { + iparent = 0; + OF_searchencprop(node, "interrupt-parent", &iparent, + sizeof(iparent)); + OF_searchencprop(OF_xref_phandle(iparent), "#interrupt-cells", + &icells, sizeof(icells)); + for (i = 0, k = 0; i < nintr; i += icells, k++) { + intr[i] = ofw_bus_map_intr(dev, iparent, icells, + &intr[i]); + resource_list_add(&ndi->rl, SYS_RES_IRQ, k, intr[i], + intr[i], 1); + } + free(intr, M_OFWPROP); + } + + return (ndi); +} + +static const struct ofw_bus_devinfo * +simplebus_get_devinfo(device_t bus __unused, device_t child) +{ + struct simplebus_devinfo *ndi; + + ndi = device_get_ivars(child); + return (&ndi->obdinfo); } static struct resource * 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_softc *sc; struct simplebus_devinfo *di; struct resource_list_entry *rle; + int j; + + sc = device_get_softc(bus); /* * Request for the default allocation with a given rid: use resource @@ -263,7 +334,7 @@ simplebus_alloc_resource(device_t bus, d if (type == SYS_RES_IOPORT) type = SYS_RES_MEMORY; - rle = resource_list_find(&di->di_res, type, *rid); + rle = resource_list_find(&di->rl, type, *rid); if (rle == NULL) { if (bootverbose) device_printf(bus, "no default resources for " @@ -273,153 +344,69 @@ simplebus_alloc_resource(device_t bus, d start = rle->start; end = rle->end; 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)); + if (type == SYS_RES_MEMORY) { + /* Remap through ranges property */ + for (j = 0; j < sc->nranges; j++) { + if (start >= sc->ranges[j].bus && end < + sc->ranges[j].bus + sc->ranges[j].size) { + start -= sc->ranges[j].bus; + start += sc->ranges[j].host; + end -= sc->ranges[j].bus; + end += sc->ranges[j].host; + break; + } + } + if (j == sc->nranges && sc->nranges != 0) { + if (bootverbose) + device_printf(bus, "Could not map resource " + "%#lx-%#lx\n", start, end); + + return (NULL); + } + } 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) -{ - struct simplebus_devinfo *di; - - di = device_get_ivars(child); - return (&di->di_res); -} - -static device_t -simplebus_get_interrupt_parent(device_t dev) +simplebus_print_res(struct simplebus_devinfo *di) { - struct simplebus_devinfo *di; - struct fdt_ic *ic; - device_t ip; - phandle_t ph, iph; - - ip = NULL; - - di = device_get_ivars(dev); - if (di == NULL) - return (NULL); + int rv; - if (OF_getencprop(di->di_ofw.obd_node, "interrupt-parent", &iph, - sizeof(iph)) > 0) { - ph = OF_xref_phandle(iph); - SLIST_FOREACH(ic, &fdt_ic_list_head, fdt_ics) { - if (ic->iph == ph) { - ip = ic->dev; - break; - } - } - } - return (ip); + rv = 0; + rv += resource_list_print_type(&di->rl, "mem", SYS_RES_MEMORY, "%#lx"); + rv += resource_list_print_type(&di->rl, "irq", SYS_RES_IRQ, "%ld"); + return (rv); } -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) +static void +simplebus_probe_nomatch(device_t bus, device_t child) { - struct simplebus_devinfo *di; - device_t ic; - enum intr_trigger trig; - enum intr_polarity pol; - int error, irq, rid; + const char *name, *type; - di = device_get_ivars(child); - if (di == NULL) - return (ENXIO); - - if (res == NULL) - return (EINVAL); + if (!bootverbose) + return; - rid = rman_get_rid(res); - 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) { - 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); - } + name = ofw_bus_get_name(child); + type = ofw_bus_get_type(child); - 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); + device_printf(bus, "<%s>", name != NULL ? name : "unknown"); + simplebus_print_res(device_get_ivars(child)); + printf(" type %s (no driver attached)\n", + type != NULL ? type : "unknown"); } static int -simplebus_teardown_intr(device_t bus, device_t child, struct resource *res, - void *cookie) +simplebus_print_child(device_t bus, device_t child) { - device_t ic; - - if ((ic = simplebus_get_interrupt_parent(child)) != NULL) - return (FDT_IC_TEARDOWN_INTR(ic, child, res, cookie)); + int rv; - return (bus_generic_teardown_intr(bus, child, res, cookie)); + rv = bus_print_child_header(bus, child); + rv += simplebus_print_res(device_get_ivars(child)); + rv += bus_print_child_footer(bus, child); + return (rv); } -static const struct ofw_bus_devinfo * -simplebus_get_devinfo(device_t bus, device_t child) -{ - struct simplebus_devinfo *di; - - di = device_get_ivars(child); - return (&di->di_ofw); -} Copied and modified: head/sys/mips/beri/beri_simplebus.c (from r261350, head/sys/dev/fdt/simplebus.c) ============================================================================== --- head/sys/dev/fdt/simplebus.c Sat Feb 1 12:33:58 2014 (r261350, copy source) +++ head/sys/mips/beri/beri_simplebus.c Sat Feb 1 17:41:54 2014 (r261352) @@ -44,7 +44,7 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/ofw_bus_subr.h> #include <dev/ofw/openfirm.h> -#include "fdt_common.h" +#include <dev/fdt/fdt_common.h> #include "fdt_ic_if.h" #include "ofw_bus_if.h" @@ -149,7 +149,7 @@ simplebus_probe(device_t dev) device_set_desc(dev, "Flattened device tree simple bus"); - return (BUS_PROBE_GENERIC); + return (BUS_PROBE_SPECIFIC); } static int Copied: head/sys/mips/beri/fdt_ic_if.m (from r261350, head/sys/dev/fdt/fdt_ic_if.m) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/mips/beri/fdt_ic_if.m Sat Feb 1 17:41:54 2014 (r261352, copy of r261350, head/sys/dev/fdt/fdt_ic_if.m) @@ -0,0 +1,266 @@ +#- +# Copyright (c) 2013 SRI International +# Copyright (c) 1998-2004 Doug Rabson +# All rights reserved. +# +# 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. +# +# $FreeBSD$ +# + +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/bus.h> + +/** + * @defgroup FST_IC fdt_ic - KObj methods for interrupt controllers + * @brief A set of methods required device drivers that are interrupt + * controllers. Derived from sys/kern/bus_if.m. + * @{ + */ +INTERFACE fdt_ic; + +/** + * @brief Allocate an interrupt resource + * + * This method is called by child devices of an interrupt controller to + * allocate an interrup. The meaning of the resource-ID field varies + * from bus to bus and is opaque to the interrupt controller. If a + * resource was allocated and the caller did not use the RF_ACTIVE + * to specify that it should be activated immediately, the caller is + * responsible for calling FDT_IC_ACTIVATE_INTR() when it actually uses + * the interupt. + * + * @param _dev the interrupt-parent device of @p _child + * @param _child the device which is requesting an allocation + * @param _rid a pointer to the resource identifier + * @param _irq interrupt source to allocate + * @param _flags any extra flags to control the resource + * allocation - see @c RF_XXX flags in + * <sys/rman.h> for details + * + * @returns the interrupt which was allocated or @c NULL if no + * resource could be allocated + */ +METHOD struct resource * alloc_intr { + device_t _dev; + device_t _child; + int *_rid; + u_long _irq; + u_int _flags; +}; + +/** + * @brief Activate an interrupt + * + * Activate an interrupt previously allocated with FDT_IC_ALLOC_INTR(). + * + * @param _dev the parent device of @p _child + * @param _r interrupt to activate + */ +METHOD int activate_intr { + device_t _dev; + struct resource *_r; +}; + +/** + * @brief Deactivate an interrupt + * + * Deactivate a resource previously allocated with FDT_IC_ALLOC_INTR(). + * + * @param _dev the parent device of @p _child + * @param _r the interrupt to deactivate + */ +METHOD int deactivate_intr { + device_t _dev; + struct resource *_r; +}; + +/** + * @brief Release an interrupt + * + * Free an interupt allocated by the FDT_IC_ALLOC_INTR. + * + * @param _dev the parent device of @p _child + * @param _r the resource to release + */ +METHOD int release_intr { + device_t _dev; + struct resource *_res; +}; + +/** + * @brief Install an interrupt handler + * + * This method is used to associate an interrupt handler function with + * an irq resource. When the interrupt triggers, the function @p _intr + * will be called with the value of @p _arg as its single + * argument. The value returned in @p *_cookiep is used to cancel the + * interrupt handler - the caller should save this value to use in a + * future call to FDT_IC_TEARDOWN_INTR(). + * + * @param _dev the interrupt-parent device of @p _child + * @param _child the device which allocated the resource + * @param _irq the resource representing the interrupt + * @param _flags a set of bits from enum intr_type specifying + * the class of interrupt + * @param _intr the function to call when the interrupt + * triggers + * @param _arg a value to use as the single argument in calls + * to @p _intr + * @param _cookiep a pointer to a location to recieve a cookie + * value that may be used to remove the interrupt + * handler + */ +METHOD int setup_intr { + device_t _dev; + device_t _child; + struct resource *_irq; + int _flags; + driver_filter_t *_filter; + driver_intr_t *_intr; + void *_arg; + void **_cookiep; +}; + +/** + * @brief Uninstall an interrupt handler + * + * This method is used to disassociate an interrupt handler function + * with an irq resource. The value of @p _cookie must be the value + * returned from a previous call to FDT_IC_SETUP_INTR(). + * + * @param _dev the interrupt-parent device of @p _child + * @param _child the device which allocated the resource + * @param _irq the resource representing the interrupt + * @param _cookie the cookie value returned when the interrupt + * was originally registered + */ +METHOD int teardown_intr { + device_t _dev; + device_t _child; + struct resource *_irq; + void *_cookie; +}; + +/** + * @brief Allow drivers to request that an interrupt be bound to a specific + * CPU. + * + * @param _dev the interrupt-parent device of @p _child + * @param _child the device which allocated the resource + * @param _irq the resource representing the interrupt + * @param _cpu the CPU to bind the interrupt to + */ +METHOD int bind_intr { + device_t _dev; + device_t _child; + struct resource *_irq; + int _cpu; +}; + +/** + * @brief Allow drivers to specify the trigger mode and polarity + * of the specified interrupt. + * + * @param _dev the interrupt-parent device + * @param _irq the interrupt number to modify + * @param _trig the trigger mode required + * @param _pol the interrupt polarity required + */ +METHOD int config_intr { + device_t _dev; + int _irq; + enum intr_trigger _trig; + enum intr_polarity _pol; +}; + +/** + * @brief Allow drivers to associate a description with an active + * interrupt handler. + * + * @param _dev the interrupt-parent device of @p _child + * @param _child the device which allocated the resource + * @param _irq the resource representing the interrupt + * @param _cookie the cookie value returned when the interrupt + * was originally registered + * @param _descr the description to associate with the interrupt + */ +METHOD int describe_intr { + device_t _dev; + device_t _child; + struct resource *_irq; + void *_cookie; + const char *_descr; +}; + +/** + * @brief Notify an ic that specified child's IRQ should be remapped. + * + * @param _dev the interrupt-parent device + * @param _child the child device + * @param _irq the irq number + */ +METHOD int remap_intr { + device_t _dev; + device_t _child; + u_int _irq; +}; + +/** + * @brief Enable an IPI source. + * + * @param _dev the interrupt controller + * @param _tid the thread ID (relative to the interrupt controller) + * to enable IPIs for + * @param _ipi_irq hardware IRQ to send IPIs to + */ +METHOD void setup_ipi { + device_t _dev; + u_int _tid; + u_int _irq; +}; + +/** + * @brief Send an IPI to the specified thread. + * + * @param _dev the interrupt controller + * @param _tid the thread ID (relative to the interrupt controller) + * to send IPIs to + */ +METHOD void send_ipi { + device_t _dev; + u_int _tid; +}; + +/** + * @brief Clear the IPI on the specfied thread. Only call with the + * local hardware thread or interrupts may be lost! + * + * @param _dev the interrupt controller + * @param _tid the thread ID (relative to the interrupt controller) + * to clear the IPI on + */ +METHOD void clear_ipi { + device_t _dev; + u_int _tid; +}; Modified: head/sys/mips/beri/files.beri ============================================================================== --- head/sys/mips/beri/files.beri Sat Feb 1 17:17:35 2014 (r261351) +++ head/sys/mips/beri/files.beri Sat Feb 1 17:41:54 2014 (r261352) @@ -18,5 +18,7 @@ dev/terasic/mtl/terasic_mtl_syscons.c op dev/terasic/mtl/terasic_mtl_text.c optional terasic_mtl mips/beri/beri_machdep.c standard mips/beri/beri_pic.c optional fdt +mips/beri/beri_simplebus.c optional fdt +mips/beri/fdt_ic_if.m optional fdt mips/mips/intr_machdep.c standard mips/mips/tick.c standard
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201402011741.s11HftLN085317>