ofwbus.c revision 280772
1139825Simp/*- 294755Sbenno * Copyright 1998 Massachusetts Institute of Technology 3256901Snwhitehorn * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. 4256901Snwhitehorn * Copyright 2006 by Marius Strobl <marius@FreeBSD.org>. 5256901Snwhitehorn * All rights reserved. 694755Sbenno * 794755Sbenno * Permission to use, copy, modify, and distribute this software and 894755Sbenno * its documentation for any purpose and without fee is hereby 994755Sbenno * granted, provided that both the above copyright notice and this 1094755Sbenno * permission notice appear in all copies, that both the above 1194755Sbenno * copyright notice and this permission notice appear in all 1294755Sbenno * supporting documentation, and that the name of M.I.T. not be used 1394755Sbenno * in advertising or publicity pertaining to distribution of the 1494755Sbenno * software without specific, written prior permission. M.I.T. makes 1594755Sbenno * no representations about the suitability of this software for any 1694755Sbenno * purpose. It is provided "as is" without express or implied 1794755Sbenno * warranty. 18125702Sgrehan * 1994755Sbenno * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 2094755Sbenno * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 2194755Sbenno * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 2294755Sbenno * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 2394755Sbenno * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2494755Sbenno * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2594755Sbenno * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 2694755Sbenno * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 2794755Sbenno * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2894755Sbenno * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 2994755Sbenno * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3094755Sbenno * SUCH DAMAGE. 3194755Sbenno * 3294755Sbenno * from: FreeBSD: src/sys/i386/i386/nexus.c,v 1.43 2001/02/09 3394755Sbenno */ 3494755Sbenno 35227843Smarius#include <sys/cdefs.h> 36227843Smarius__FBSDID("$FreeBSD: head/sys/dev/ofw/ofwbus.c 280772 2015-03-27 23:10:15Z ian $"); 37227843Smarius 3894755Sbenno#include <sys/param.h> 3994755Sbenno#include <sys/systm.h> 4094755Sbenno#include <sys/bus.h> 4194755Sbenno#include <sys/kernel.h> 4294755Sbenno#include <sys/malloc.h> 43256901Snwhitehorn#include <sys/module.h> 44256901Snwhitehorn#include <sys/pcpu.h> 45256901Snwhitehorn#include <sys/rman.h> 4694755Sbenno 47256901Snwhitehorn#include <vm/vm.h> 48256901Snwhitehorn#include <vm/pmap.h> 49256901Snwhitehorn 50256855Snwhitehorn#include <dev/ofw/ofw_bus.h> 51212239Smav#include <dev/ofw/ofw_bus_subr.h> 5294755Sbenno#include <dev/ofw/openfirm.h> 53280772Sian#include <dev/fdt/simplebus.h> 5494755Sbenno 5594755Sbenno#include <machine/bus.h> 5694755Sbenno#include <machine/resource.h> 5794755Sbenno 5894755Sbenno/* 59261513Snwhitehorn * The ofwbus (which is a pseudo-bus actually) iterates over the nodes that 60256901Snwhitehorn * hang from the Open Firmware root node and adds them as devices to this bus 61256901Snwhitehorn * (except some special nodes which are excluded) so that drivers can be 62256901Snwhitehorn * attached to them. 6394755Sbenno * 6494755Sbenno */ 6594755Sbenno 66261513Snwhitehornstruct ofwbus_softc { 67280772Sian struct simplebus_softc simplebus_sc; 68261513Snwhitehorn struct rman sc_intr_rman; 69261513Snwhitehorn struct rman sc_mem_rman; 70261513Snwhitehorn}; 7199652Sbenno 72261513Snwhitehornstatic device_identify_t ofwbus_identify; 73261513Snwhitehornstatic device_probe_t ofwbus_probe; 74261513Snwhitehornstatic device_attach_t ofwbus_attach; 75261513Snwhitehornstatic bus_alloc_resource_t ofwbus_alloc_resource; 76261513Snwhitehornstatic bus_adjust_resource_t ofwbus_adjust_resource; 77261513Snwhitehornstatic bus_release_resource_t ofwbus_release_resource; 7899652Sbenno 79261513Snwhitehornstatic device_method_t ofwbus_methods[] = { 8094755Sbenno /* Device interface */ 81261513Snwhitehorn DEVMETHOD(device_identify, ofwbus_identify), 82261513Snwhitehorn DEVMETHOD(device_probe, ofwbus_probe), 83261513Snwhitehorn DEVMETHOD(device_attach, ofwbus_attach), 8494755Sbenno 85256901Snwhitehorn /* Bus interface */ 86261513Snwhitehorn DEVMETHOD(bus_alloc_resource, ofwbus_alloc_resource), 87261513Snwhitehorn DEVMETHOD(bus_adjust_resource, ofwbus_adjust_resource), 88261513Snwhitehorn DEVMETHOD(bus_release_resource, ofwbus_release_resource), 8994755Sbenno 90227843Smarius DEVMETHOD_END 9194755Sbenno}; 9294755Sbenno 93280772SianDEFINE_CLASS_1(ofwbus, ofwbus_driver, ofwbus_methods, 94280772Sian sizeof(struct ofwbus_softc), simplebus_driver); 95261513Snwhitehornstatic devclass_t ofwbus_devclass; 96269594SianEARLY_DRIVER_MODULE(ofwbus, nexus, ofwbus_driver, ofwbus_devclass, 0, 0, 97269597Sian BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); 98261513SnwhitehornMODULE_VERSION(ofwbus, 1); 9994755Sbenno 100261513Snwhitehornstatic void 101261513Snwhitehornofwbus_identify(driver_t *driver, device_t parent) 102261513Snwhitehorn{ 103261513Snwhitehorn 104261513Snwhitehorn /* Check if Open Firmware has been instantiated */ 105265888Snwhitehorn if (OF_peer(0) == 0) 106261513Snwhitehorn return; 107280772Sian 108261513Snwhitehorn if (device_find_child(parent, "ofwbus", -1) == NULL) 109261513Snwhitehorn BUS_ADD_CHILD(parent, 0, "ofwbus", -1); 110261513Snwhitehorn} 111261513Snwhitehorn 112256901Snwhitehornstatic int 113261513Snwhitehornofwbus_probe(device_t dev) 11494755Sbenno{ 115256901Snwhitehorn 116261513Snwhitehorn device_set_desc(dev, "Open Firmware Device Tree"); 117261513Snwhitehorn return (BUS_PROBE_NOWILDCARD); 118178367Smarcel} 119178367Smarcel 120178367Smarcelstatic int 121261513Snwhitehornofwbus_attach(device_t dev) 122178367Smarcel{ 123261513Snwhitehorn struct ofwbus_softc *sc; 124256901Snwhitehorn phandle_t node; 125280772Sian struct ofw_bus_devinfo obd; 12694755Sbenno 12799652Sbenno sc = device_get_softc(dev); 12899652Sbenno 129257075Snwhitehorn node = OF_peer(0); 130171805Smarcel 131261513Snwhitehorn /* 132261513Snwhitehorn * If no Open Firmware, bail early 133261513Snwhitehorn */ 134261513Snwhitehorn if (node == -1) 135261513Snwhitehorn return (ENXIO); 136261513Snwhitehorn 137280772Sian /* 138280772Sian * ofwbus bus starts on unamed node in FDT, so we cannot make 139280772Sian * ofw_bus_devinfo from it. Pass node to simplebus_init directly. 140280772Sian */ 141280772Sian simplebus_init(dev, node); 142257075Snwhitehorn sc->sc_intr_rman.rm_type = RMAN_ARRAY; 143257075Snwhitehorn sc->sc_intr_rman.rm_descr = "Interrupts"; 144257075Snwhitehorn sc->sc_mem_rman.rm_type = RMAN_ARRAY; 145257075Snwhitehorn sc->sc_mem_rman.rm_descr = "Device Memory"; 146257075Snwhitehorn if (rman_init(&sc->sc_intr_rman) != 0 || 147257075Snwhitehorn rman_init(&sc->sc_mem_rman) != 0 || 148257075Snwhitehorn rman_manage_region(&sc->sc_intr_rman, 0, ~0) != 0 || 149257075Snwhitehorn rman_manage_region(&sc->sc_mem_rman, 0, BUS_SPACE_MAXADDR) != 0) 150257075Snwhitehorn panic("%s: failed to set up rmans.", __func__); 151171805Smarcel 152256901Snwhitehorn /* 153256901Snwhitehorn * Allow devices to identify. 154256901Snwhitehorn */ 155256901Snwhitehorn bus_generic_probe(dev); 156256901Snwhitehorn 157256901Snwhitehorn /* 158256901Snwhitehorn * Now walk the OFW tree and attach top-level devices. 159256901Snwhitehorn */ 160256901Snwhitehorn for (node = OF_child(node); node > 0; node = OF_peer(node)) { 161280772Sian if (ofw_bus_gen_setup_devinfo(&obd, node) != 0) 162256901Snwhitehorn continue; 163280772Sian simplebus_add_device(dev, node, 0, NULL, -1, NULL); 16494755Sbenno } 165178367Smarcel return (bus_generic_attach(dev)); 16694755Sbenno} 16794755Sbenno 16899652Sbennostatic struct resource * 169261513Snwhitehornofwbus_alloc_resource(device_t bus, device_t child, int type, int *rid, 17099652Sbenno u_long start, u_long end, u_long count, u_int flags) 17199652Sbenno{ 172261513Snwhitehorn struct ofwbus_softc *sc; 173256901Snwhitehorn struct rman *rm; 174171805Smarcel struct resource *rv; 175256901Snwhitehorn struct resource_list_entry *rle; 176256901Snwhitehorn int isdefault, passthrough; 17799652Sbenno 178256901Snwhitehorn isdefault = (start == 0UL && end == ~0UL); 179256901Snwhitehorn passthrough = (device_get_parent(child) != bus); 180257075Snwhitehorn sc = device_get_softc(bus); 181256901Snwhitehorn rle = NULL; 182256901Snwhitehorn if (!passthrough && isdefault) { 183256901Snwhitehorn rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child), 184256901Snwhitehorn type, *rid); 185280772Sian if (rle == NULL) { 186280772Sian if (bootverbose) 187280772Sian device_printf(bus, "no default resources for " 188280772Sian "rid = %d, type = %d\n", *rid, type); 189256901Snwhitehorn return (NULL); 190280772Sian } 191256901Snwhitehorn start = rle->start; 192256901Snwhitehorn count = ulmax(count, rle->count); 193256901Snwhitehorn end = ulmax(rle->end, start + count - 1); 194256901Snwhitehorn } 195256901Snwhitehorn 196256901Snwhitehorn switch (type) { 197256901Snwhitehorn case SYS_RES_IRQ: 198256901Snwhitehorn rm = &sc->sc_intr_rman; 199256901Snwhitehorn break; 200256901Snwhitehorn case SYS_RES_MEMORY: 201256901Snwhitehorn rm = &sc->sc_mem_rman; 202256901Snwhitehorn break; 203256901Snwhitehorn default: 20499652Sbenno return (NULL); 20599652Sbenno } 20699652Sbenno 207256901Snwhitehorn rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE, 208256901Snwhitehorn child); 209256901Snwhitehorn if (rv == NULL) 210171805Smarcel return (NULL); 211256901Snwhitehorn rman_set_rid(rv, *rid); 212256901Snwhitehorn 213256901Snwhitehorn if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type, 214256901Snwhitehorn *rid, rv) != 0) { 215256901Snwhitehorn rman_release_resource(rv); 216256901Snwhitehorn return (NULL); 217171805Smarcel } 21899652Sbenno 219256901Snwhitehorn if (!passthrough && rle != NULL) { 220256901Snwhitehorn rle->res = rv; 221256901Snwhitehorn rle->start = rman_get_start(rv); 222256901Snwhitehorn rle->end = rman_get_end(rv); 223256901Snwhitehorn rle->count = rle->end - rle->start + 1; 224256901Snwhitehorn } 22599652Sbenno 22699652Sbenno return (rv); 22799652Sbenno} 22899652Sbenno 22999652Sbennostatic int 230261513Snwhitehornofwbus_adjust_resource(device_t bus, device_t child __unused, int type, 231256901Snwhitehorn struct resource *r, u_long start, u_long end) 23299652Sbenno{ 233261513Snwhitehorn struct ofwbus_softc *sc; 234256901Snwhitehorn struct rman *rm; 235261513Snwhitehorn device_t ofwbus; 23699652Sbenno 237261513Snwhitehorn ofwbus = bus; 238261513Snwhitehorn while (strcmp(device_get_name(device_get_parent(ofwbus)), "root") != 0) 239261513Snwhitehorn ofwbus = device_get_parent(ofwbus); 240261513Snwhitehorn sc = device_get_softc(ofwbus); 241256901Snwhitehorn switch (type) { 242256901Snwhitehorn case SYS_RES_IRQ: 243256901Snwhitehorn rm = &sc->sc_intr_rman; 244256901Snwhitehorn break; 245256901Snwhitehorn case SYS_RES_MEMORY: 246256901Snwhitehorn rm = &sc->sc_mem_rman; 247256901Snwhitehorn break; 248256901Snwhitehorn default: 249124468Sgrehan return (EINVAL); 25099652Sbenno } 251256901Snwhitehorn if (rm == NULL) 252256901Snwhitehorn return (ENXIO); 253256901Snwhitehorn if (rman_is_region_manager(r, rm) == 0) 254256901Snwhitehorn return (EINVAL); 255256901Snwhitehorn return (rman_adjust_resource(r, start, end)); 25699652Sbenno} 25799652Sbenno 258256901Snwhitehornstatic int 259274249Szbbofwbus_release_resource(device_t bus, device_t child, int type, 260256901Snwhitehorn int rid, struct resource *r) 26199652Sbenno{ 262274249Szbb struct resource_list_entry *rle; 263256901Snwhitehorn int error; 26499652Sbenno 265274249Szbb /* Clean resource list entry */ 266274249Szbb rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child), type, rid); 267274249Szbb if (rle != NULL) 268274249Szbb rle->res = NULL; 269274249Szbb 270256901Snwhitehorn if ((rman_get_flags(r) & RF_ACTIVE) != 0) { 271256901Snwhitehorn error = bus_deactivate_resource(child, type, rid, r); 272256901Snwhitehorn if (error) 273256901Snwhitehorn return (error); 274256855Snwhitehorn } 275256901Snwhitehorn return (rman_release_resource(r)); 276256901Snwhitehorn} 277