From owner-svn-src-all@FreeBSD.ORG Thu May 15 14:26:14 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 83F2CD3E; Thu, 15 May 2014 14:26:14 +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 6E7772D90; Thu, 15 May 2014 14:26:14 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s4FEQEuI018851; Thu, 15 May 2014 14:26:14 GMT (envelope-from ian@svn.freebsd.org) Received: (from ian@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s4FEQCio018830; Thu, 15 May 2014 14:26:12 GMT (envelope-from ian@svn.freebsd.org) Message-Id: <201405151426.s4FEQCio018830@svn.freebsd.org> From: Ian Lepore Date: Thu, 15 May 2014 14:26:12 +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: r266128 - in stable/10/sys: arm/arm arm/mv conf dev/fdt dev/ofw mips/beri powerpc/ofw powerpc/powerpc powerpc/pseries 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: Thu, 15 May 2014 14:26:14 -0000 Author: ian Date: Thu May 15 14:26:11 2014 New Revision: 266128 URL: http://svnweb.freebsd.org/changeset/base/266128 Log: MFC r261351, r261352, r261355, r261396, r261397, r261398, r261403, r261404, r261405 Open Firmware interrupt specifiers can consist of arbitrary-length byte strings and include arbitrary information (IRQ line/domain/sense). When the ofw_bus_map_intr() API was introduced, it assumed that, as on most systems, these were either 1 cell, containing an interrupt line, or 2, containing a line number plus a sense code. It turns out a non-negligible number of ARM systems use 3 (or even 4!) cells for interrupts, so make this more general. 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. Allow nesting of simplebuses. Add a set of helpers (ofw_bus_get_status() and ofw_bus_status_okay()) to process "status" properties of OF nodes. Fix one remnant endian flaw in nexus. Added: stable/10/sys/mips/beri/beri_simplebus.c - copied unchanged from r261352, head/sys/mips/beri/beri_simplebus.c - copied unchanged from r261352, head/sys/mips/beri/fdt_ic_if.m Directory Properties: stable/10/sys/mips/beri/fdt_ic_if.m (props changed) Deleted: stable/10/sys/dev/fdt/fdt_ic_if.m Modified: stable/10/sys/arm/arm/nexus.c stable/10/sys/arm/mv/mv_pci.c stable/10/sys/conf/files stable/10/sys/dev/fdt/fdt_common.c stable/10/sys/dev/fdt/simplebus.c stable/10/sys/dev/ofw/ofw_bus.h stable/10/sys/dev/ofw/ofw_bus_if.m stable/10/sys/dev/ofw/ofw_bus_subr.c stable/10/sys/dev/ofw/ofw_bus_subr.h stable/10/sys/dev/ofw/ofw_nexus.c stable/10/sys/mips/beri/files.beri stable/10/sys/powerpc/ofw/ofw_pci.c stable/10/sys/powerpc/ofw/ofw_pcib_pci.c stable/10/sys/powerpc/ofw/ofw_pcibus.c stable/10/sys/powerpc/powerpc/nexus.c stable/10/sys/powerpc/pseries/vdevice.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/arm/arm/nexus.c ============================================================================== --- stable/10/sys/arm/arm/nexus.c Thu May 15 14:23:36 2014 (r266127) +++ stable/10/sys/arm/arm/nexus.c Thu May 15 14:26:11 2014 (r266128) @@ -98,7 +98,7 @@ static int nexus_teardown_intr(device_t, #ifdef FDT static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, - int irq); + int icells, pcell_t *intr); #endif static device_method_t nexus_methods[] = { @@ -339,15 +339,16 @@ nexus_deactivate_resource(device_t bus, #ifdef FDT static int -nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int irq) +nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, + pcell_t *intr) { - pcell_t intr[2]; fdt_pic_decode_t intr_decode; phandle_t intr_offset; int i, rv, interrupt, trig, pol; intr_offset = OF_xref_phandle(iparent); - intr[0] = cpu_to_fdt32(irq); + for (i = 0; i < icells; i++) + intr[i] = cpu_to_fdt32(intr[i]); for (i = 0; fdt_pic_table[i] != NULL; i++) { intr_decode = fdt_pic_table[i]; @@ -361,7 +362,7 @@ nexus_ofw_map_intr(device_t dev, device_ } /* Not in table, so guess */ - interrupt = FDT_MAP_IRQ(intr_parent, fdt32_to_cpu(*intr)); + interrupt = FDT_MAP_IRQ(intr_parent, fdt32_to_cpu(intr[0])); return (interrupt); } Modified: stable/10/sys/arm/mv/mv_pci.c ============================================================================== --- stable/10/sys/arm/mv/mv_pci.c Thu May 15 14:23:36 2014 (r266127) +++ stable/10/sys/arm/mv/mv_pci.c Thu May 15 14:26:11 2014 (r266128) @@ -1050,7 +1050,8 @@ mv_pcib_route_interrupt(device_t bus, de { struct mv_pcib_softc *sc; struct ofw_pci_register reg; - uint32_t pintr, mintr; + uint32_t pintr, mintr[4]; + int icells; phandle_t iparent; sc = device_get_softc(bus); @@ -1062,10 +1063,11 @@ mv_pcib_route_interrupt(device_t bus, de (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) | (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT); - if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, ®, - sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), - &iparent)) - return (ofw_bus_map_intr(dev, iparent, mintr)); + icells = ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, + ®, sizeof(reg), &pintr, sizeof(pintr), mintr, sizeof(mintr), + &iparent); + if (icells > 0) + return (ofw_bus_map_intr(dev, iparent, icells, mintr)); /* Maybe it's a real interrupt, not an intpin */ if (pin > 4) Modified: stable/10/sys/conf/files ============================================================================== --- stable/10/sys/conf/files Thu May 15 14:23:36 2014 (r266127) +++ stable/10/sys/conf/files Thu May 15 14:26:11 2014 (r266128) @@ -1404,7 +1404,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: stable/10/sys/dev/fdt/fdt_common.c ============================================================================== --- stable/10/sys/dev/fdt/fdt_common.c Thu May 15 14:23:36 2014 (r266127) +++ stable/10/sys/dev/fdt/fdt_common.c Thu May 15 14:26:11 2014 (r266128) @@ -489,11 +489,10 @@ fdt_intr_to_rl(device_t dev, phandle_t n 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, intr[i]); + intr[i] = ofw_bus_map_intr(dev, iparent, icells, + &intr[i]); resource_list_add(rl, SYS_RES_IRQ, k, intr[i], intr[i], 1); - if (icells > 1) - ofw_bus_config_intr(dev, intr[i], intr[i+1]); } free(intr, M_OFWPROP); } Modified: stable/10/sys/dev/fdt/simplebus.c ============================================================================== --- stable/10/sys/dev/fdt/simplebus.c Thu May 15 14:23:36 2014 (r266127) +++ stable/10/sys/dev/fdt/simplebus.c Thu May 15 14:26:11 2014 (r266128) @@ -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 __FBSDID("$FreeBSD$"); - -#include "opt_platform.h" #include #include -#include -#include #include #include +#include +#include #include -#include +#include #include #include -#include -#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); + +/* + * ofw_bus interface + */ +static const struct ofw_bus_devinfo *simplebus_get_devinfo(device_t bus, + device_t child); -static ofw_bus_get_devinfo_t simplebus_get_devinfo; +/* + * local 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); /* - * Bus interface definition. + * Driver methods. */ -static device_method_t simplebus_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,17 @@ 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); +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 +141,200 @@ 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) { + if (OF_searchencprop(node, "interrupt-parent", &iparent, + sizeof(iparent)) == -1) { + device_printf(dev, "No interrupt-parent found, " + "assuming direct parent\n"); + iparent = OF_parent(node); + } + if (OF_searchencprop(OF_xref_phandle(iparent), + "#interrupt-cells", &icells, sizeof(icells)) == -1) { + device_printf(dev, "Missing #interrupt-cells property, " + "assuming <1>\n"); + icells = 1; + } + if (icells < 1 || icells > nintr) { + device_printf(dev, "Invalid #interrupt-cells property " + "value <%d>, assuming <1>\n", icells); + icells = 1; + } + 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 +347,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 +357,69 @@ simplebus_alloc_resource(device_t bus, d start = rle->start; end = rle->end; count = rle->count; - } + } + + 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); - if (type == SYS_RES_IRQ && - (ic = simplebus_get_interrupt_parent(child)) != NULL) - return(FDT_IC_ALLOC_INTR(ic, child, rid, start, flags)); + 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) +simplebus_print_res(struct simplebus_devinfo *di) { - 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) -{ - 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); -} Modified: stable/10/sys/dev/ofw/ofw_bus.h ============================================================================== --- stable/10/sys/dev/ofw/ofw_bus.h Thu May 15 14:23:36 2014 (r266127) +++ stable/10/sys/dev/ofw/ofw_bus.h Thu May 15 14:26:11 2014 (r266128) @@ -71,15 +71,9 @@ ofw_bus_get_type(device_t dev) } static __inline int -ofw_bus_map_intr(device_t dev, phandle_t iparent, int irq) +ofw_bus_map_intr(device_t dev, phandle_t iparent, int icells, pcell_t *intr) { - return (OFW_BUS_MAP_INTR(dev, dev, iparent, irq)); -} - -static __inline int -ofw_bus_config_intr(device_t dev, int irq, int sense) -{ - return (OFW_BUS_CONFIG_INTR(dev, dev, irq, sense)); + return (OFW_BUS_MAP_INTR(dev, dev, iparent, icells, intr)); } #endif /* !_DEV_OFW_OFW_BUS_H_ */ Modified: stable/10/sys/dev/ofw/ofw_bus_if.m ============================================================================== --- stable/10/sys/dev/ofw/ofw_bus_if.m Thu May 15 14:23:36 2014 (r266127) +++ stable/10/sys/dev/ofw/ofw_bus_if.m Thu May 15 14:26:11 2014 (r266128) @@ -46,6 +46,7 @@ HEADER { char *obd_model; char *obd_name; char *obd_type; + char *obd_status; }; }; @@ -57,7 +58,6 @@ CODE { static ofw_bus_get_node_t ofw_bus_default_get_node; static ofw_bus_get_type_t ofw_bus_default_get_type; static ofw_bus_map_intr_t ofw_bus_default_map_intr; - static ofw_bus_config_intr_t ofw_bus_default_config_intr; static const struct ofw_bus_devinfo * ofw_bus_default_get_devinfo(device_t bus, device_t dev) @@ -103,27 +103,15 @@ CODE { int ofw_bus_default_map_intr(device_t bus, device_t dev, phandle_t iparent, - int irq) + int icells, pcell_t *interrupt) { /* Propagate up the bus hierarchy until someone handles it. */ if (device_get_parent(bus) != NULL) return OFW_BUS_MAP_INTR(device_get_parent(bus), dev, - iparent, irq); + iparent, icells, interrupt); /* If that fails, then assume a one-domain system */ - return (irq); - } - - int - ofw_bus_default_config_intr(device_t bus, device_t dev, int irq, - int sense) - { - /* Propagate up the bus hierarchy until someone handles it. */ - if (device_get_parent(bus) != NULL) - return OFW_BUS_CONFIG_INTR(device_get_parent(bus), dev, - irq, sense); - - return (ENXIO); + return (interrupt[0]); } }; @@ -172,20 +160,14 @@ METHOD const char * get_type { } DEFAULT ofw_bus_default_get_type; # Map an (interrupt parent, IRQ) pair to a unique system-wide interrupt number. +# If the interrupt encoding includes a sense field, the interrupt sense will +# also be configured. METHOD int map_intr { device_t bus; device_t dev; phandle_t iparent; - int irq; + int icells; + pcell_t *interrupt; } DEFAULT ofw_bus_default_map_intr; -# Configure an interrupt using the device-tree encoded sense key (the second -# value in the interrupts property if interrupt-cells is 2). IRQ should be -# encoded as from ofw_bus_map_intr(). -METHOD int config_intr { - device_t bus; - device_t dev; - int irq; - int sense; -} DEFAULT ofw_bus_default_config_intr; Modified: stable/10/sys/dev/ofw/ofw_bus_subr.c ============================================================================== --- stable/10/sys/dev/ofw/ofw_bus_subr.c Thu May 15 14:23:36 2014 (r266127) +++ stable/10/sys/dev/ofw/ofw_bus_subr.c Thu May 15 14:26:11 2014 (r266128) @@ -55,6 +55,7 @@ ofw_bus_gen_setup_devinfo(struct ofw_bus OF_getprop_alloc(node, "compatible", 1, (void **)&obd->obd_compat); OF_getprop_alloc(node, "device_type", 1, (void **)&obd->obd_type); OF_getprop_alloc(node, "model", 1, (void **)&obd->obd_model); + OF_getprop_alloc(node, "status", 1, (void **)&obd->obd_status); obd->obd_node = node; return (0); } @@ -73,6 +74,8 @@ ofw_bus_gen_destroy_devinfo(struct ofw_b free(obd->obd_name, M_OFWPROP); if (obd->obd_type != NULL) free(obd->obd_type, M_OFWPROP); + if (obd->obd_status != NULL) + free(obd->obd_status, M_OFWPROP); } int @@ -147,6 +150,30 @@ ofw_bus_gen_get_type(device_t bus, devic return (obd->obd_type); } +const char * +ofw_bus_get_status(device_t dev) +{ + const struct ofw_bus_devinfo *obd; + + obd = OFW_BUS_GET_DEVINFO(device_get_parent(dev), dev); + if (obd == NULL) + return (NULL); + + return (obd->obd_status); +} + +int +ofw_bus_status_okay(device_t dev) +{ + const char *status; + + status = ofw_bus_get_status(dev); + if (status == NULL || strcmp(status, "okay") == 0) + return (1); + + return (0); +} + int ofw_bus_is_compatible(device_t dev, const char *onecompat) { Modified: stable/10/sys/dev/ofw/ofw_bus_subr.h ============================================================================== --- stable/10/sys/dev/ofw/ofw_bus_subr.h Thu May 15 14:23:36 2014 (r266127) +++ stable/10/sys/dev/ofw/ofw_bus_subr.h Thu May 15 14:26:11 2014 (r266128) @@ -72,6 +72,10 @@ int ofw_bus_lookup_imap(phandle_t, struc int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *, void *, void *, int, phandle_t *); +/* Helper to get device status property */ +const char *ofw_bus_get_status(device_t dev); +int ofw_bus_status_okay(device_t dev); + /* Helper to get node's interrupt parent */ void ofw_bus_find_iparent(phandle_t); Modified: stable/10/sys/dev/ofw/ofw_nexus.c ============================================================================== --- stable/10/sys/dev/ofw/ofw_nexus.c Thu May 15 14:23:36 2014 (r266127) +++ stable/10/sys/dev/ofw/ofw_nexus.c Thu May 15 14:26:11 2014 (r266128) @@ -467,11 +467,10 @@ nexus_setup_dinfo(device_t dev, phandle_ 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]); + intr[i] = ofw_bus_map_intr(dev, iparent, icells, + &intr[i]); resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i], intr[i], 1); - if (icells > 1) - ofw_bus_config_intr(dev, intr[i], intr[i+1]); } free(intr, M_OFWPROP); } Copied: stable/10/sys/mips/beri/beri_simplebus.c (from r261352, head/sys/mips/beri/beri_simplebus.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/10/sys/mips/beri/beri_simplebus.c Thu May 15 14:26:11 2014 (r266128, copy of r261352, head/sys/mips/beri/beri_simplebus.c) @@ -0,0 +1,425 @@ +/*- + * Copyright (c) 2009-2010 The FreeBSD Foundation + * 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: + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "opt_platform.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#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 *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***