ofwbus.c revision 212239
1139825Simp/*- 294755Sbenno * Copyright 1998 Massachusetts Institute of Technology 394755Sbenno * 494755Sbenno * Permission to use, copy, modify, and distribute this software and 594755Sbenno * its documentation for any purpose and without fee is hereby 694755Sbenno * granted, provided that both the above copyright notice and this 794755Sbenno * permission notice appear in all copies, that both the above 894755Sbenno * copyright notice and this permission notice appear in all 994755Sbenno * supporting documentation, and that the name of M.I.T. not be used 1094755Sbenno * in advertising or publicity pertaining to distribution of the 1194755Sbenno * software without specific, written prior permission. M.I.T. makes 1294755Sbenno * no representations about the suitability of this software for any 1394755Sbenno * purpose. It is provided "as is" without express or implied 1494755Sbenno * warranty. 15125702Sgrehan * 1694755Sbenno * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 1794755Sbenno * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 1894755Sbenno * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 1994755Sbenno * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 2094755Sbenno * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2194755Sbenno * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2294755Sbenno * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 2394755Sbenno * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 2494755Sbenno * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2594755Sbenno * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 2694755Sbenno * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2794755Sbenno * SUCH DAMAGE. 2894755Sbenno */ 2994755Sbenno/*- 3094755Sbenno * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved. 3194755Sbenno * 3294755Sbenno * Redistribution and use in source and binary forms, with or without 3394755Sbenno * modification, are permitted provided that the following conditions 3494755Sbenno * are met: 3594755Sbenno * 1. Redistributions of source code must retain the above copyright 3694755Sbenno * notice, this list of conditions and the following disclaimer. 3794755Sbenno * 2. Redistributions in binary form must reproduce the above copyright 3894755Sbenno * notice, this list of conditions and the following disclaimer in the 3994755Sbenno * documentation and/or other materials provided with the distribution. 4094755Sbenno * 4194755Sbenno * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 4294755Sbenno * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4394755Sbenno * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4494755Sbenno * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4594755Sbenno * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4694755Sbenno * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4794755Sbenno * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4894755Sbenno * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4994755Sbenno * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5094755Sbenno * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5194755Sbenno * SUCH DAMAGE. 5294755Sbenno * 5394755Sbenno * from: FreeBSD: src/sys/i386/i386/nexus.c,v 1.43 2001/02/09 5494755Sbenno * 5594755Sbenno * $FreeBSD: head/sys/powerpc/aim/nexus.c 212239 2010-09-05 19:57:24Z mav $ 5694755Sbenno */ 5794755Sbenno 5894755Sbenno#include <sys/param.h> 5994755Sbenno#include <sys/systm.h> 60131102Sgrehan#include <sys/module.h> 6194755Sbenno#include <sys/bus.h> 6294755Sbenno#include <sys/cons.h> 6394755Sbenno#include <sys/kernel.h> 6494755Sbenno#include <sys/malloc.h> 6594755Sbenno 66212239Smav#include <dev/ofw/ofw_bus_subr.h> 6794755Sbenno#include <dev/ofw/openfirm.h> 6894755Sbenno 6994755Sbenno#include <machine/bus.h> 7094755Sbenno#include <machine/frame.h> 7199652Sbenno#include <machine/intr_machdep.h> 7294755Sbenno#include <machine/resource.h> 7394755Sbenno 7499652Sbenno#include <sys/rman.h> 7599652Sbenno 76168885Sgrehan#include "ofw_bus_if.h" 7799652Sbenno#include "pic_if.h" 7899652Sbenno 7994755Sbenno/* 8094755Sbenno * The nexus (which is a pseudo-bus actually) iterates over the nodes that 81133862Smarius * exist in Open Firmware and adds them as devices to this bus so that drivers 8294755Sbenno * can be attached to them. 8394755Sbenno * 8494755Sbenno * Maybe this code should get into dev/ofw to some extent, as some of it should 85133862Smarius * work for all Open Firmware based machines... 8694755Sbenno */ 8794755Sbenno 8894755Sbennostatic MALLOC_DEFINE(M_NEXUS, "nexus", "nexus device information"); 8994755Sbenno 90183882Snwhitehornenum nexus_ivars { 91183882Snwhitehorn NEXUS_IVAR_NODE, 92183882Snwhitehorn NEXUS_IVAR_NAME, 93183882Snwhitehorn NEXUS_IVAR_DEVICE_TYPE, 94183882Snwhitehorn NEXUS_IVAR_COMPATIBLE, 95183882Snwhitehorn}; 96183882Snwhitehorn 9794755Sbennostruct nexus_devinfo { 9894755Sbenno phandle_t ndi_node; 9994755Sbenno /* Some common properties. */ 100125702Sgrehan const char *ndi_name; 101125702Sgrehan const char *ndi_device_type; 102125702Sgrehan const char *ndi_compatible; 10394755Sbenno}; 10494755Sbenno 10594755Sbennostruct nexus_softc { 106171805Smarcel struct rman sc_rman; 10794755Sbenno}; 10894755Sbenno 10999652Sbenno/* 11099652Sbenno * Device interface 11199652Sbenno */ 11299652Sbennostatic int nexus_probe(device_t); 113178367Smarcelstatic int nexus_attach(device_t); 11494755Sbenno 11599652Sbenno/* 11699652Sbenno * Bus interface 11799652Sbenno */ 118124468Sgrehanstatic device_t nexus_add_child(device_t, int, const char *, int); 119178367Smarcelstatic void nexus_probe_nomatch(device_t, device_t); 12099652Sbennostatic int nexus_read_ivar(device_t, device_t, int, uintptr_t *); 12199652Sbennostatic int nexus_write_ivar(device_t, device_t, int, uintptr_t); 122209486Snwhitehorn#ifdef SMP 123209486Snwhitehornstatic int nexus_bind_intr(device_t dev, device_t child, 124209486Snwhitehorn struct resource *irq, int cpu); 125209486Snwhitehorn#endif 126209486Snwhitehornstatic int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, 127209486Snwhitehorn enum intr_polarity pol); 12899652Sbennostatic int nexus_setup_intr(device_t, device_t, struct resource *, int, 129167289Spiso driver_filter_t *, driver_intr_t *, void *, void **); 13099652Sbennostatic int nexus_teardown_intr(device_t, device_t, struct resource *, 13199652Sbenno void *); 13299652Sbennostatic struct resource *nexus_alloc_resource(device_t, device_t, int, int *, 13399652Sbenno u_long, u_long, u_long, u_int); 13499652Sbennostatic int nexus_activate_resource(device_t, device_t, int, int, 13599652Sbenno struct resource *); 13699652Sbennostatic int nexus_deactivate_resource(device_t, device_t, int, int, 13799652Sbenno struct resource *); 13899652Sbennostatic int nexus_release_resource(device_t, device_t, int, int, 13999652Sbenno struct resource *); 14099652Sbenno 141178367Smarcel/* 142178367Smarcel * OFW bus interface. 143178367Smarcel */ 144168885Sgrehanstatic phandle_t nexus_ofw_get_node(device_t, device_t); 145168885Sgrehanstatic const char *nexus_ofw_get_name(device_t, device_t); 146168885Sgrehanstatic const char *nexus_ofw_get_type(device_t, device_t); 147168885Sgrehanstatic const char *nexus_ofw_get_compat(device_t, device_t); 148168885Sgrehan 14999652Sbenno/* 15099652Sbenno * Local routines 15199652Sbenno */ 152124468Sgrehanstatic device_t nexus_device_from_node(device_t, phandle_t); 15399652Sbenno 15494755Sbennostatic device_method_t nexus_methods[] = { 15594755Sbenno /* Device interface */ 15694755Sbenno DEVMETHOD(device_probe, nexus_probe), 157178367Smarcel DEVMETHOD(device_attach, nexus_attach), 15894755Sbenno DEVMETHOD(device_detach, bus_generic_detach), 15994755Sbenno DEVMETHOD(device_shutdown, bus_generic_shutdown), 16094755Sbenno DEVMETHOD(device_suspend, bus_generic_suspend), 16194755Sbenno DEVMETHOD(device_resume, bus_generic_resume), 16294755Sbenno 16394755Sbenno /* Bus interface. Resource management is business of the children... */ 164124468Sgrehan DEVMETHOD(bus_add_child, nexus_add_child), 16594755Sbenno DEVMETHOD(bus_print_child, bus_generic_print_child), 166212239Smav DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), 16794755Sbenno DEVMETHOD(bus_probe_nomatch, nexus_probe_nomatch), 16894755Sbenno DEVMETHOD(bus_read_ivar, nexus_read_ivar), 16994755Sbenno DEVMETHOD(bus_write_ivar, nexus_write_ivar), 17099652Sbenno DEVMETHOD(bus_setup_intr, nexus_setup_intr), 17199652Sbenno DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), 172209486Snwhitehorn#ifdef SMP 173209486Snwhitehorn DEVMETHOD(bus_bind_intr, nexus_bind_intr), 174209486Snwhitehorn#endif 175209486Snwhitehorn DEVMETHOD(bus_config_intr, nexus_config_intr), 17699652Sbenno DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), 17799652Sbenno DEVMETHOD(bus_activate_resource, nexus_activate_resource), 17899652Sbenno DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), 17999652Sbenno DEVMETHOD(bus_release_resource, nexus_release_resource), 18094755Sbenno 181168885Sgrehan /* OFW bus interface */ 182168885Sgrehan DEVMETHOD(ofw_bus_get_node, nexus_ofw_get_node), 183168885Sgrehan DEVMETHOD(ofw_bus_get_name, nexus_ofw_get_name), 184168885Sgrehan DEVMETHOD(ofw_bus_get_type, nexus_ofw_get_type), 185168885Sgrehan DEVMETHOD(ofw_bus_get_compat, nexus_ofw_get_compat), 186168885Sgrehan 18794755Sbenno { 0, 0 } 18894755Sbenno}; 18994755Sbenno 19094755Sbennostatic driver_t nexus_driver = { 19194755Sbenno "nexus", 19294755Sbenno nexus_methods, 19394755Sbenno sizeof(struct nexus_softc), 19494755Sbenno}; 19594755Sbenno 19694755Sbennostatic devclass_t nexus_devclass; 19794755Sbenno 19894755SbennoDRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0); 19994755Sbenno 20094755Sbennostatic int 20194755Sbennonexus_probe(device_t dev) 20294755Sbenno{ 203178367Smarcel bus_generic_probe(dev); 204178367Smarcel device_set_desc(dev, "Open Firmware Nexus device"); 205178367Smarcel return (0); 206178367Smarcel} 207178367Smarcel 208178367Smarcelstatic int 209178367Smarcelnexus_attach(device_t dev) 210178367Smarcel{ 21194755Sbenno phandle_t root; 212124468Sgrehan phandle_t child; 21394755Sbenno struct nexus_softc *sc; 214171805Smarcel u_long start, end; 21594755Sbenno 21694755Sbenno if ((root = OF_peer(0)) == -1) 21794755Sbenno panic("nexus_probe: OF_peer failed."); 21894755Sbenno 21999652Sbenno sc = device_get_softc(dev); 22099652Sbenno 221171805Smarcel start = 0; 222209298Snwhitehorn end = MAX_PICS*INTR_VECTORS - 1; 223171805Smarcel 224171805Smarcel sc->sc_rman.rm_start = start; 225171805Smarcel sc->sc_rman.rm_end = end; 226171805Smarcel sc->sc_rman.rm_type = RMAN_ARRAY; 227171805Smarcel sc->sc_rman.rm_descr = "Interrupt request lines"; 228171805Smarcel if (rman_init(&sc->sc_rman) || 229171805Smarcel rman_manage_region(&sc->sc_rman, start, end)) 230171805Smarcel panic("nexus_probe IRQ rman"); 231171805Smarcel 232124468Sgrehan /* 233124468Sgrehan * Now walk the OFW tree to locate top-level devices 234124468Sgrehan */ 235124468Sgrehan for (child = OF_child(root); child != 0; child = OF_peer(child)) { 236124468Sgrehan if (child == -1) 237124468Sgrehan panic("nexus_probe(): OF_child failed."); 238124468Sgrehan (void)nexus_device_from_node(dev, child); 23999652Sbenno 24094755Sbenno } 241178367Smarcel 242178367Smarcel return (bus_generic_attach(dev)); 24394755Sbenno} 24494755Sbenno 24594755Sbennostatic void 24694755Sbennonexus_probe_nomatch(device_t dev, device_t child) 24794755Sbenno{ 24894755Sbenno char *name, *type; 24994755Sbenno 25094755Sbenno if (BUS_READ_IVAR(dev, child, NEXUS_IVAR_NAME, 25194755Sbenno (uintptr_t *)&name) != 0 || 25294755Sbenno BUS_READ_IVAR(dev, child, NEXUS_IVAR_DEVICE_TYPE, 25394755Sbenno (uintptr_t *)&type) != 0) 25494755Sbenno return; 25594755Sbenno 25694755Sbenno if (type == NULL) 25794755Sbenno type = "(unknown)"; 258124468Sgrehan 259124468Sgrehan if (bootverbose) 260124468Sgrehan device_printf(dev, "<%s>, type %s (no driver attached)\n", 261124468Sgrehan name, type); 26294755Sbenno} 26394755Sbenno 264124468Sgrehanstatic device_t 265124468Sgrehannexus_add_child(device_t dev, int order, const char *name, int unit) 266124468Sgrehan{ 267124468Sgrehan device_t child; 268124468Sgrehan struct nexus_devinfo *dinfo; 269124468Sgrehan 270124468Sgrehan child = device_add_child_ordered(dev, order, name, unit); 271125702Sgrehan if (child == NULL) 272124468Sgrehan return (NULL); 273125702Sgrehan 274124468Sgrehan dinfo = malloc(sizeof(struct nexus_devinfo), M_NEXUS, M_NOWAIT|M_ZERO); 275124468Sgrehan if (dinfo == NULL) 276124468Sgrehan return (NULL); 277124468Sgrehan 278124468Sgrehan dinfo->ndi_node = -1; 279124468Sgrehan dinfo->ndi_name = name; 280125702Sgrehan device_set_ivars(child, dinfo); 281125702Sgrehan 282124468Sgrehan return (child); 283124468Sgrehan} 284124468Sgrehan 285124468Sgrehan 28694755Sbennostatic int 28794755Sbennonexus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 28894755Sbenno{ 28994755Sbenno struct nexus_devinfo *dinfo; 29094755Sbenno 29194755Sbenno if ((dinfo = device_get_ivars(child)) == 0) 29294755Sbenno return (ENOENT); 29394755Sbenno switch (which) { 29494755Sbenno case NEXUS_IVAR_NODE: 29594755Sbenno *result = dinfo->ndi_node; 29694755Sbenno break; 29794755Sbenno case NEXUS_IVAR_NAME: 29894755Sbenno *result = (uintptr_t)dinfo->ndi_name; 29994755Sbenno break; 30094755Sbenno case NEXUS_IVAR_DEVICE_TYPE: 30194755Sbenno *result = (uintptr_t)dinfo->ndi_device_type; 30294755Sbenno break; 30399652Sbenno case NEXUS_IVAR_COMPATIBLE: 30499652Sbenno *result = (uintptr_t)dinfo->ndi_compatible; 30599652Sbenno break; 30694755Sbenno default: 30794755Sbenno return (ENOENT); 30894755Sbenno } 30994755Sbenno return 0; 31094755Sbenno} 31194755Sbenno 31294755Sbennostatic int 31394755Sbennonexus_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 31494755Sbenno{ 31594755Sbenno struct nexus_devinfo *dinfo; 31694755Sbenno 31794755Sbenno if ((dinfo = device_get_ivars(child)) == 0) 31894755Sbenno return (ENOENT); 31994755Sbenno 32094755Sbenno switch (which) { 32194755Sbenno case NEXUS_IVAR_NAME: 322124468Sgrehan return (EINVAL); 323124468Sgrehan 324125434Sgrehan /* Identified devices may want to set these */ 325125434Sgrehan case NEXUS_IVAR_NODE: 326125434Sgrehan dinfo->ndi_node = (phandle_t)value; 327125434Sgrehan break; 328125434Sgrehan 32994755Sbenno case NEXUS_IVAR_DEVICE_TYPE: 330124468Sgrehan dinfo->ndi_device_type = (char *)value; 331124468Sgrehan break; 332124468Sgrehan 33394755Sbenno default: 33494755Sbenno return (ENOENT); 33594755Sbenno } 33694755Sbenno return 0; 33794755Sbenno} 33899652Sbenno 33999652Sbennostatic int 34099652Sbennonexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, 341171805Smarcel driver_filter_t *filter, driver_intr_t *ihand, void *arg, void **cookiep) 34299652Sbenno{ 343171805Smarcel driver_t *driver; 344171805Smarcel int error; 34599652Sbenno 346171805Smarcel /* somebody tried to setup an irq that failed to allocate! */ 347171805Smarcel if (res == NULL) 348171805Smarcel panic("nexus_setup_intr: NULL irq resource!"); 34999652Sbenno 350171805Smarcel *cookiep = 0; 351171805Smarcel if ((rman_get_flags(res) & RF_SHAREABLE) == 0) 352171805Smarcel flags |= INTR_EXCL; 35399652Sbenno 354171805Smarcel driver = device_get_driver(child); 355171805Smarcel 356171805Smarcel /* 357171805Smarcel * We depend here on rman_activate_resource() being idempotent. 358171805Smarcel */ 359171805Smarcel error = rman_activate_resource(res); 360171805Smarcel if (error) 361171805Smarcel return (error); 362171805Smarcel 363171805Smarcel error = powerpc_setup_intr(device_get_nameunit(child), 364171805Smarcel rman_get_start(res), filter, ihand, arg, flags, cookiep); 365171805Smarcel 366171805Smarcel return (error); 36799652Sbenno} 36899652Sbenno 36999652Sbennostatic int 37099652Sbennonexus_teardown_intr(device_t dev, device_t child, struct resource *res, 371171805Smarcel void *cookie) 37299652Sbenno{ 37399652Sbenno 374171805Smarcel return (powerpc_teardown_intr(cookie)); 37599652Sbenno} 37699652Sbenno 377209486Snwhitehorn#ifdef SMP 378209486Snwhitehornstatic int 379209486Snwhitehornnexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu) 380209486Snwhitehorn{ 381209486Snwhitehorn 382209486Snwhitehorn return (powerpc_bind_intr(rman_get_start(irq), cpu)); 383209486Snwhitehorn} 384209486Snwhitehorn#endif 385209486Snwhitehorn 386209486Snwhitehornstatic int 387209486Snwhitehornnexus_config_intr(device_t dev, int irq, enum intr_trigger trig, 388209486Snwhitehorn enum intr_polarity pol) 389209486Snwhitehorn{ 390209486Snwhitehorn 391209486Snwhitehorn return (powerpc_config_intr(irq, trig, pol)); 392209486Snwhitehorn} 393209486Snwhitehorn 39499652Sbenno/* 39599652Sbenno * Allocate resources at the behest of a child. This only handles interrupts, 39699652Sbenno * since I/O resources are handled by child busses. 39799652Sbenno */ 39899652Sbennostatic struct resource * 39999652Sbennonexus_alloc_resource(device_t bus, device_t child, int type, int *rid, 40099652Sbenno u_long start, u_long end, u_long count, u_int flags) 40199652Sbenno{ 402171805Smarcel struct nexus_softc *sc; 403171805Smarcel struct resource *rv; 40499652Sbenno 40599652Sbenno if (type != SYS_RES_IRQ) { 40699652Sbenno device_printf(bus, "unknown resource request from %s\n", 40799652Sbenno device_get_nameunit(child)); 40899652Sbenno return (NULL); 40999652Sbenno } 41099652Sbenno 411171805Smarcel if (count == 0 || start + count - 1 != end) { 412171805Smarcel device_printf(bus, "invalid IRQ allocation from %s\n", 413171805Smarcel device_get_nameunit(child)); 414171805Smarcel return (NULL); 415171805Smarcel } 41699652Sbenno 417171805Smarcel sc = device_get_softc(bus); 41899652Sbenno 419171805Smarcel rv = rman_reserve_resource(&sc->sc_rman, start, end, count, 420171805Smarcel flags, child); 421171805Smarcel if (rv == NULL) { 422171805Smarcel device_printf(bus, "IRQ allocation failed for %s\n", 423171805Smarcel device_get_nameunit(child)); 424171805Smarcel } else 425171805Smarcel rman_set_rid(rv, *rid); 426171805Smarcel 42799652Sbenno return (rv); 42899652Sbenno} 42999652Sbenno 43099652Sbennostatic int 43199652Sbennonexus_activate_resource(device_t bus, device_t child, int type, int rid, 43299652Sbenno struct resource *res) 43399652Sbenno{ 43499652Sbenno 43599652Sbenno /* Not much to be done yet... */ 43699652Sbenno return (rman_activate_resource(res)); 43799652Sbenno} 43899652Sbenno 43999652Sbennostatic int 44099652Sbennonexus_deactivate_resource(device_t bus, device_t child, int type, int rid, 44199652Sbenno struct resource *res) 44299652Sbenno{ 44399652Sbenno 44499652Sbenno /* Not much to be done yet... */ 44599652Sbenno return (rman_deactivate_resource(res)); 44699652Sbenno} 44799652Sbenno 44899652Sbennostatic int 44999652Sbennonexus_release_resource(device_t bus, device_t child, int type, int rid, 45099652Sbenno struct resource *res) 45199652Sbenno{ 45299652Sbenno 45399652Sbenno if (type != SYS_RES_IRQ) { 45499652Sbenno device_printf(bus, "unknown resource request from %s\n", 45599652Sbenno device_get_nameunit(child)); 456124468Sgrehan return (EINVAL); 45799652Sbenno } 45899652Sbenno 459171805Smarcel return (rman_release_resource(res)); 46099652Sbenno} 46199652Sbenno 46299652Sbennostatic device_t 463124468Sgrehannexus_device_from_node(device_t parent, phandle_t node) 46499652Sbenno{ 46599652Sbenno device_t cdev; 46699652Sbenno struct nexus_devinfo *dinfo; 46799652Sbenno char *name, *type, *compatible; 46899652Sbenno 46999652Sbenno OF_getprop_alloc(node, "name", 1, (void **)&name); 47099652Sbenno OF_getprop_alloc(node, "device_type", 1, (void **)&type); 47199652Sbenno OF_getprop_alloc(node, "compatible", 1, (void **)&compatible); 47299652Sbenno cdev = device_add_child(parent, NULL, -1); 47399652Sbenno if (cdev != NULL) { 474111119Simp dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_WAITOK); 47599652Sbenno dinfo->ndi_node = node; 47699652Sbenno dinfo->ndi_name = name; 47799652Sbenno dinfo->ndi_device_type = type; 47899652Sbenno dinfo->ndi_compatible = compatible; 47999652Sbenno device_set_ivars(cdev, dinfo); 48099652Sbenno } else 48199652Sbenno free(name, M_OFWPROP); 48299652Sbenno 48399652Sbenno return (cdev); 48499652Sbenno} 485124468Sgrehan 486168885Sgrehanstatic const char * 487168885Sgrehannexus_ofw_get_name(device_t bus, device_t dev) 488168885Sgrehan{ 489168885Sgrehan struct nexus_devinfo *dinfo; 490168885Sgrehan 491168885Sgrehan if ((dinfo = device_get_ivars(dev)) == NULL) 492168885Sgrehan return (NULL); 493168885Sgrehan 494168885Sgrehan return (dinfo->ndi_name); 495168885Sgrehan} 496168885Sgrehan 497168885Sgrehanstatic phandle_t 498168885Sgrehannexus_ofw_get_node(device_t bus, device_t dev) 499168885Sgrehan{ 500168885Sgrehan struct nexus_devinfo *dinfo; 501168885Sgrehan 502168885Sgrehan if ((dinfo = device_get_ivars(dev)) == NULL) 503168885Sgrehan return (0); 504168885Sgrehan 505168885Sgrehan return (dinfo->ndi_node); 506168885Sgrehan} 507168885Sgrehan 508168885Sgrehanstatic const char * 509168885Sgrehannexus_ofw_get_type(device_t bus, device_t dev) 510168885Sgrehan{ 511168885Sgrehan struct nexus_devinfo *dinfo; 512168885Sgrehan 513168885Sgrehan if ((dinfo = device_get_ivars(dev)) == NULL) 514168885Sgrehan return (NULL); 515168885Sgrehan 516168885Sgrehan return (dinfo->ndi_device_type); 517168885Sgrehan} 518168885Sgrehan 519168885Sgrehanstatic const char * 520168885Sgrehannexus_ofw_get_compat(device_t bus, device_t dev) 521168885Sgrehan{ 522168885Sgrehan struct nexus_devinfo *dinfo; 523168885Sgrehan 524168885Sgrehan if ((dinfo = device_get_ivars(dev)) == NULL) 525168885Sgrehan return (NULL); 526168885Sgrehan 527168885Sgrehan return (dinfo->ndi_compatible); 528168885Sgrehan} 529178367Smarcel 530