From owner-svn-src-all@FreeBSD.ORG Tue May 13 18:14:32 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 2399694D; Tue, 13 May 2014 18:14:32 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::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 0DE9F2137; Tue, 13 May 2014 18:14:32 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s4DIEWKv017795; Tue, 13 May 2014 18:14:32 GMT (envelope-from ian@svn.freebsd.org) Received: (from ian@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s4DIEVsQ017792; Tue, 13 May 2014 18:14:31 GMT (envelope-from ian@svn.freebsd.org) Message-Id: <201405131814.s4DIEVsQ017792@svn.freebsd.org> From: Ian Lepore Date: Tue, 13 May 2014 18:14:31 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r265971 - in stable/10/sys: conf dev/fdt dev/ofw X-SVN-Group: stable-10 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.18 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, 13 May 2014 18:14:32 -0000 Author: ian Date: Tue May 13 18:14:31 2014 New Revision: 265971 URL: http://svnweb.freebsd.org/changeset/base/265971 Log: MFC r257114, r257118 Use common OFW root code to set up fdtbus. This is an almost purely negative diff that should improve reliability somewhat. There should be no differences in behavior -- please report any that crop up. This has been tested on ARM and PPC systems. Make sure to get the right node when looking up #interrupt-cells. Modified: stable/10/sys/conf/files stable/10/sys/dev/fdt/fdtbus.c stable/10/sys/dev/ofw/ofw_nexus.c Modified: stable/10/sys/conf/files ============================================================================== --- stable/10/sys/conf/files Tue May 13 18:08:15 2014 (r265970) +++ stable/10/sys/conf/files Tue May 13 18:14:31 2014 (r265971) @@ -1969,6 +1969,7 @@ dev/ofw/ofw_bus_subr.c optional fdt dev/ofw/ofw_fdt.c optional fdt dev/ofw/ofw_if.m optional fdt dev/ofw/ofw_iicbus.c optional fdt iicbus +dev/ofw/ofw_nexus.c optional fdt dev/ofw/openfirm.c optional fdt dev/ofw/openfirmio.c optional fdt dev/patm/if_patm.c optional patm pci Modified: stable/10/sys/dev/fdt/fdtbus.c ============================================================================== --- stable/10/sys/dev/fdt/fdtbus.c Tue May 13 18:08:15 2014 (r265970) +++ stable/10/sys/dev/fdt/fdtbus.c Tue May 13 18:14:31 2014 (r265971) @@ -42,63 +42,20 @@ __FBSDID("$FreeBSD$"); #include #include +#include -#include "fdt_common.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_FDTBUS, "fdtbus", "FDTbus devices information"); - -struct fdtbus_devinfo { - phandle_t di_node; - char *di_name; - char *di_type; - char *di_compat; - struct resource_list di_res; - - /* Interrupts sense-level info for this device */ - struct fdt_sense_level di_intr_sl[DI_MAX_INTR_NUM]; -}; - -struct fdtbus_softc { - struct rman sc_irq; - struct rman sc_mem; -}; - /* * Prototypes. */ static void fdtbus_identify(driver_t *, device_t); static int fdtbus_probe(device_t); -static int fdtbus_attach(device_t); -static int fdtbus_print_child(device_t, device_t); -static struct resource *fdtbus_alloc_resource(device_t, device_t, int, - int *, u_long, u_long, u_long, u_int); -static int fdtbus_release_resource(device_t, device_t, int, int, - struct resource *); static int fdtbus_activate_resource(device_t, device_t, int, int, struct resource *); static int fdtbus_deactivate_resource(device_t, device_t, int, int, struct resource *); -static int fdtbus_setup_intr(device_t, device_t, struct resource *, int, - driver_filter_t *, driver_intr_t *, void *, void **); - -static const char *fdtbus_ofw_get_name(device_t, device_t); -static phandle_t fdtbus_ofw_get_node(device_t, device_t); -static const char *fdtbus_ofw_get_type(device_t, device_t); -static const char *fdtbus_ofw_get_compat(device_t, device_t); - -/* - * Local routines. - */ -static void newbus_device_from_fdt_node(device_t, phandle_t); /* * Bus interface definition. @@ -107,47 +64,26 @@ static device_method_t fdtbus_methods[] /* Device interface */ DEVMETHOD(device_identify, fdtbus_identify), DEVMETHOD(device_probe, fdtbus_probe), - DEVMETHOD(device_attach, fdtbus_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, fdtbus_print_child), - DEVMETHOD(bus_alloc_resource, fdtbus_alloc_resource), - DEVMETHOD(bus_release_resource, fdtbus_release_resource), DEVMETHOD(bus_activate_resource, fdtbus_activate_resource), DEVMETHOD(bus_deactivate_resource, fdtbus_deactivate_resource), DEVMETHOD(bus_config_intr, bus_generic_config_intr), - DEVMETHOD(bus_setup_intr, fdtbus_setup_intr), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - /* OFW bus interface */ - DEVMETHOD(ofw_bus_get_node, fdtbus_ofw_get_node), - DEVMETHOD(ofw_bus_get_name, fdtbus_ofw_get_name), - DEVMETHOD(ofw_bus_get_type, fdtbus_ofw_get_type), - DEVMETHOD(ofw_bus_get_compat, fdtbus_ofw_get_compat), - - { 0, 0 } -}; - -static driver_t fdtbus_driver = { - "fdtbus", - fdtbus_methods, - sizeof(struct fdtbus_softc) + DEVMETHOD_END }; devclass_t fdtbus_devclass; - +DEFINE_CLASS_1(fdtbus, fdtbus_driver, fdtbus_methods, + sizeof(struct ofw_nexus_softc), ofw_nexus_driver); DRIVER_MODULE(fdtbus, nexus, fdtbus_driver, fdtbus_devclass, 0, 0); static void fdtbus_identify(driver_t *driver, device_t parent) { - debugf("%s(driver=%p, parent=%p)\n", __func__, driver, parent); - if (device_find_child(parent, "fdtbus", -1) == NULL) BUS_ADD_CHILD(parent, 0, "fdtbus", -1); } @@ -156,462 +92,11 @@ static int fdtbus_probe(device_t dev) { - debugf("%s(dev=%p); pass=%u\n", __func__, dev, bus_current_pass); - device_set_desc(dev, "Flattened Device Tree"); return (BUS_PROBE_NOWILDCARD); } static int -fdtbus_attach(device_t dev) -{ - phandle_t root; - phandle_t child; - struct fdtbus_softc *sc; - u_long start, end; - int error; - - if ((root = OF_finddevice("/")) == -1) - panic("fdtbus_attach: no root node."); - - sc = device_get_softc(dev); - - /* - * IRQ rman. - */ - start = 0; - end = ~0; - sc->sc_irq.rm_start = start; - sc->sc_irq.rm_end = end; - sc->sc_irq.rm_type = RMAN_ARRAY; - sc->sc_irq.rm_descr = "Interrupt request lines"; - if ((error = rman_init(&sc->sc_irq)) != 0) { - device_printf(dev, "could not init IRQ rman, error = %d\n", - error); - return (error); - } - if ((error = rman_manage_region(&sc->sc_irq, start, end)) != 0) { - device_printf(dev, "could not manage IRQ region, error = %d\n", - error); - return (error); - } - - /* - * Mem-mapped I/O space rman. - */ - start = 0; - end = ~0ul; - sc->sc_mem.rm_start = start; - sc->sc_mem.rm_end = end; - sc->sc_mem.rm_type = RMAN_ARRAY; - sc->sc_mem.rm_descr = "I/O memory"; - if ((error = rman_init(&sc->sc_mem)) != 0) { - device_printf(dev, "could not init I/O mem rman, error = %d\n", - error); - return (error); - } - if ((error = rman_manage_region(&sc->sc_mem, start, end)) != 0) { - device_printf(dev, "could not manage I/O mem region, " - "error = %d\n", error); - return (error); - } - - /* - * Walk the FDT root node and add top-level devices as our children. - */ - for (child = OF_child(root); child != 0; child = OF_peer(child)) { - /* Check and process 'status' property. */ - if (!(fdt_is_enabled(child))) - continue; - - newbus_device_from_fdt_node(dev, child); - } - - return (bus_generic_attach(dev)); -} - -static int -fdtbus_print_child(device_t dev, device_t child) -{ - struct fdtbus_devinfo *di; - struct resource_list *rl; - int rv; - - di = device_get_ivars(child); - rl = &di->di_res; - - 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"); - rv += bus_print_child_footer(dev, child); - - return (rv); -} - -static void -newbus_device_destroy(device_t dev) -{ - struct fdtbus_devinfo *di; - - di = device_get_ivars(dev); - if (di == NULL) - return; - - free(di->di_name, M_OFWPROP); - free(di->di_type, M_OFWPROP); - free(di->di_compat, M_OFWPROP); - - resource_list_free(&di->di_res); - free(di, M_FDTBUS); -} - -static device_t -newbus_device_create(device_t dev_par, phandle_t node, char *name, char *type, - char *compat) -{ - device_t child; - struct fdtbus_devinfo *di; - - child = device_add_child(dev_par, NULL, -1); - if (child == NULL) { - free(name, M_OFWPROP); - free(type, M_OFWPROP); - free(compat, M_OFWPROP); - return (NULL); - } - - di = malloc(sizeof(*di), M_FDTBUS, M_WAITOK); - di->di_node = node; - di->di_name = name; - di->di_type = type; - di->di_compat = compat; - - resource_list_init(&di->di_res); - - if (fdt_reg_to_rl(node, &di->di_res)) { - device_printf(child, "could not process 'reg' property\n"); - newbus_device_destroy(child); - child = NULL; - goto out; - } - - if (fdt_intr_to_rl(node, &di->di_res, di->di_intr_sl)) { - device_printf(child, "could not process 'interrupts' " - "property\n"); - newbus_device_destroy(child); - child = NULL; - goto out; - } - - device_set_ivars(child, di); - debugf("added child name='%s', node=%p\n", name, (void *)node); - -out: - return (child); -} - -static device_t -newbus_pci_create(device_t dev_par, phandle_t dt_node, u_long par_base, - u_long par_size) -{ - pcell_t reg[3 + 2]; - device_t dev_child; - u_long start, end, count; - struct fdtbus_devinfo *di; - char *name, *type, *compat; - int len; - - OF_getprop_alloc(dt_node, "device_type", 1, (void **)&type); - if (!(type != NULL && strcmp(type, "pci") == 0)) { - /* Only process 'pci' subnodes. */ - free(type, M_OFWPROP); - return (NULL); - } - - OF_getprop_alloc(dt_node, "name", 1, (void **)&name); - OF_getprop_alloc(OF_parent(dt_node), "compatible", 1, - (void **)&compat); - - dev_child = device_add_child(dev_par, NULL, -1); - if (dev_child == NULL) { - free(name, M_OFWPROP); - free(type, M_OFWPROP); - free(compat, M_OFWPROP); - return (NULL); - } - - di = malloc(sizeof(*di), M_FDTBUS, M_WAITOK); - di->di_node = dt_node; - di->di_name = name; - di->di_type = type; - di->di_compat = compat; - - resource_list_init(&di->di_res); - - /* - * Produce and set SYS_RES_MEMORY resources. - */ - start = 0; - count = 0; - - len = OF_getprop(dt_node, "reg", ®, sizeof(reg)); - if (len > 0) { - if (fdt_data_verify((void *)®[1], 2) != 0) { - device_printf(dev_child, "'reg' address value out of " - "range\n"); - newbus_device_destroy(dev_child); - dev_child = NULL; - goto out; - } - start = fdt_data_get((void *)®[1], 2); - - if (fdt_data_verify((void *)®[3], 2) != 0) { - device_printf(dev_child, "'reg' size value out of " - "range\n"); - newbus_device_destroy(dev_child); - dev_child = NULL; - goto out; - } - count = fdt_data_get((void *)®[3], 2); - } - - /* Calculate address range relative to base. */ - par_base &= 0x000ffffful; - start &= 0x000ffffful; - start += par_base + fdt_immr_va; - if (count == 0) - count = par_size; - end = start + count - 1; - - debugf("start = 0x%08lx, end = 0x%08lx, count = 0x%08lx\n", - start, end, count); - - if (count > par_size) { - device_printf(dev_child, "'reg' size value out of range\n"); - newbus_device_destroy(dev_child); - dev_child = NULL; - goto out; - } - - resource_list_add(&di->di_res, SYS_RES_MEMORY, 0, start, end, count); - - /* - * Set SYS_RES_IRQ resources. - */ - if (fdt_intr_to_rl(OF_parent(dt_node), &di->di_res, di->di_intr_sl)) { - device_printf(dev_child, "could not process 'interrupts' " - "property\n"); - newbus_device_destroy(dev_child); - dev_child = NULL; - goto out; - } - - device_set_ivars(dev_child, di); - debugf("added child name='%s', node=%p\n", name, - (void *)dt_node); - -out: - return (dev_child); -} - -static void -pci_from_fdt_node(device_t dev_par, phandle_t dt_node, char *name, - char *type, char *compat) -{ - u_long reg_base, reg_size; - phandle_t dt_child; - - /* - * Retrieve 'reg' property. - */ - if (fdt_regsize(dt_node, ®_base, ®_size) != 0) { - device_printf(dev_par, "could not retrieve 'reg' prop\n"); - return; - } - - /* - * Walk the PCI node and instantiate newbus devices representing - * logical resources (bridges / ports). - */ - for (dt_child = OF_child(dt_node); dt_child != 0; - dt_child = OF_peer(dt_child)) { - - if (!(fdt_is_enabled(dt_child))) - continue; - - newbus_pci_create(dev_par, dt_child, reg_base, reg_size); - } -} - -/* - * These FDT nodes do not need a corresponding newbus device object. - */ -static char *fdt_devices_skip[] = { - "aliases", - "chosen", - "memory", - NULL -}; - -static void -newbus_device_from_fdt_node(device_t dev_par, phandle_t node) -{ - char *name, *type, *compat; - device_t child; - int i; - - OF_getprop_alloc(node, "name", 1, (void **)&name); - OF_getprop_alloc(node, "device_type", 1, (void **)&type); - OF_getprop_alloc(node, "compatible", 1, (void **)&compat); - - for (i = 0; fdt_devices_skip[i] != NULL; i++) - if (name != NULL && strcmp(name, fdt_devices_skip[i]) == 0) { - debugf("skipping instantiating FDT device='%s'\n", - name); - return; - } - - child = newbus_device_create(dev_par, node, name, type, compat); - if (type != NULL && strcmp(type, "pci") == 0) - pci_from_fdt_node(child, node, name, type, compat); -} - -static struct resource * -fdtbus_alloc_resource(device_t bus, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ - struct fdtbus_softc *sc; - struct resource *res; - struct rman *rm; - struct fdtbus_devinfo *di; - struct resource_list_entry *rle; - int needactivate; - - /* - * Request for the default allocation with a given rid: use resource - * list stored in the local device info. - */ - if ((start == 0UL) && (end == ~0UL)) { - if ((di = device_get_ivars(child)) == NULL) - return (NULL); - - if (type == SYS_RES_IOPORT) - type = SYS_RES_MEMORY; - - rle = resource_list_find(&di->di_res, type, *rid); - if (rle == NULL) { - device_printf(bus, "no default resources for " - "rid = %d, type = %d\n", *rid, type); - return (NULL); - } - start = rle->start; - end = rle->end; - count = rle->count; - } - - sc = device_get_softc(bus); - - needactivate = flags & RF_ACTIVE; - flags &= ~RF_ACTIVE; - - switch (type) { - case SYS_RES_IRQ: - rm = &sc->sc_irq; - break; - - case SYS_RES_IOPORT: - case SYS_RES_MEMORY: - rm = &sc->sc_mem; - break; - - default: - return (NULL); - } - - res = rman_reserve_resource(rm, start, end, count, flags, child); - if (res == NULL) { - device_printf(bus, "failed to reserve resource %#lx - %#lx " - "(%#lx)\n", start, end, count); - return (NULL); - } - - rman_set_rid(res, *rid); - - if (type == SYS_RES_IOPORT || type == SYS_RES_MEMORY) { - /* XXX endianess should be set based on SOC node */ - rman_set_bustag(res, fdtbus_bs_tag); - rman_set_bushandle(res, rman_get_start(res)); - } - - if (needactivate) - if (bus_activate_resource(child, type, *rid, res)) { - device_printf(child, "resource activation failed\n"); - rman_release_resource(res); - return (NULL); - } - - return (res); -} - -static int -fdtbus_release_resource(device_t bus, device_t child, int type, int rid, - struct resource *res) -{ - int err; - - if (rman_get_flags(res) & RF_ACTIVE) { - err = bus_deactivate_resource(child, type, rid, res); - if (err) - return (err); - } - - return (rman_release_resource(res)); -} - -static int -fdtbus_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 fdtbus_devinfo *di; - enum intr_trigger trig; - enum intr_polarity pol; - int error, rid; - - if (res == NULL) - return (EINVAL); - - /* - * We are responsible for configuring the interrupts of our direct - * children. - */ - if (device_get_parent(child) == bus) { - di = device_get_ivars(child); - if (di == NULL) - return (ENXIO); - - rid = rman_get_rid(res); - if (rid >= DI_MAX_INTR_NUM) - return (ENOENT); - - 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); - if (error) - return (error); - } - } - - error = bus_generic_setup_intr(bus, child, res, flags, filter, ihand, - arg, cookiep); - return (error); -} - -static int fdtbus_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { @@ -619,6 +104,10 @@ fdtbus_activate_resource(device_t bus, d int error; if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { + /* XXX endianess should be set based on SOC node */ + rman_set_bustag(res, fdtbus_bs_tag); + rman_set_bushandle(res, rman_get_start(res)); + error = bus_space_map(rman_get_bustag(res), rman_get_bushandle(res), rman_get_size(res), 0, &p); if (error) @@ -637,36 +126,3 @@ fdtbus_deactivate_resource(device_t bus, return (rman_deactivate_resource(res)); } -static const char * -fdtbus_ofw_get_name(device_t bus, device_t dev) -{ - struct fdtbus_devinfo *di; - - return ((di = device_get_ivars(dev)) == NULL ? NULL : di->di_name); -} - -static phandle_t -fdtbus_ofw_get_node(device_t bus, device_t dev) -{ - struct fdtbus_devinfo *di; - - return ((di = device_get_ivars(dev)) == NULL ? 0 : di->di_node); -} - -static const char * -fdtbus_ofw_get_type(device_t bus, device_t dev) -{ - struct fdtbus_devinfo *di; - - return ((di = device_get_ivars(dev)) == NULL ? NULL : di->di_type); -} - -static const char * -fdtbus_ofw_get_compat(device_t bus, device_t dev) -{ - struct fdtbus_devinfo *di; - - return ((di = device_get_ivars(dev)) == NULL ? NULL : di->di_compat); -} - - Modified: stable/10/sys/dev/ofw/ofw_nexus.c ============================================================================== --- stable/10/sys/dev/ofw/ofw_nexus.c Tue May 13 18:08:15 2014 (r265970) +++ stable/10/sys/dev/ofw/ofw_nexus.c Tue May 13 18:14:31 2014 (r265971) @@ -464,8 +464,8 @@ nexus_setup_dinfo(device_t dev, phandle_ iparent = 0; OF_searchencprop(node, "interrupt-parent", &iparent, sizeof(iparent)); - OF_searchencprop(iparent, "#interrupt-cells", &icells, - sizeof(icells)); + OF_searchencprop(OF_xref_phandle(iparent), "#interrupt-cells", + &icells, sizeof(icells)); for (i = 0; i < nintr; i+= icells) { intr[i] = ofw_bus_map_intr(dev, iparent, intr[i]); resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i],