14ad7e9b0SAdrian Chadd /*- 24ad7e9b0SAdrian Chadd * Copyright (c) 2015 Landon Fuller <landon@landonf.org> 34ad7e9b0SAdrian Chadd * All rights reserved. 44ad7e9b0SAdrian Chadd * 54ad7e9b0SAdrian Chadd * Redistribution and use in source and binary forms, with or without 64ad7e9b0SAdrian Chadd * modification, are permitted provided that the following conditions 74ad7e9b0SAdrian Chadd * are met: 84ad7e9b0SAdrian Chadd * 1. Redistributions of source code must retain the above copyright 94ad7e9b0SAdrian Chadd * notice, this list of conditions and the following disclaimer, 104ad7e9b0SAdrian Chadd * without modification. 114ad7e9b0SAdrian Chadd * 2. Redistributions in binary form must reproduce at minimum a disclaimer 124ad7e9b0SAdrian Chadd * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 134ad7e9b0SAdrian Chadd * redistribution must be conditioned upon including a substantially 144ad7e9b0SAdrian Chadd * similar Disclaimer requirement for further binary redistribution. 154ad7e9b0SAdrian Chadd * 164ad7e9b0SAdrian Chadd * NO WARRANTY 174ad7e9b0SAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 184ad7e9b0SAdrian Chadd * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 194ad7e9b0SAdrian Chadd * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 204ad7e9b0SAdrian Chadd * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 214ad7e9b0SAdrian Chadd * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 224ad7e9b0SAdrian Chadd * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 234ad7e9b0SAdrian Chadd * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 244ad7e9b0SAdrian Chadd * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 254ad7e9b0SAdrian Chadd * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 264ad7e9b0SAdrian Chadd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 274ad7e9b0SAdrian Chadd * THE POSSIBILITY OF SUCH DAMAGES. 284ad7e9b0SAdrian Chadd */ 294ad7e9b0SAdrian Chadd 304ad7e9b0SAdrian Chadd #include <sys/cdefs.h> 314ad7e9b0SAdrian Chadd __FBSDID("$FreeBSD$"); 324ad7e9b0SAdrian Chadd 334ad7e9b0SAdrian Chadd /* 344ad7e9b0SAdrian Chadd * Broadcom Home Networking Division (HND) Bus Driver. 354ad7e9b0SAdrian Chadd * 364ad7e9b0SAdrian Chadd * The Broadcom HND family of devices consists of both SoCs and host-connected 374ad7e9b0SAdrian Chadd * networking chipsets containing a common family of Broadcom IP cores, 384ad7e9b0SAdrian Chadd * including an integrated MIPS and/or ARM cores. 394ad7e9b0SAdrian Chadd * 404ad7e9b0SAdrian Chadd * HND devices expose a nearly identical interface whether accessible over a 414ad7e9b0SAdrian Chadd * native SoC interconnect, or when connected via a host interface such as 424ad7e9b0SAdrian Chadd * PCIe. As a result, the majority of hardware support code should be re-usable 434ad7e9b0SAdrian Chadd * across host drivers for HND networking chipsets, as well as FreeBSD support 444ad7e9b0SAdrian Chadd * for Broadcom MIPS/ARM HND SoCs. 454ad7e9b0SAdrian Chadd * 464ad7e9b0SAdrian Chadd * Earlier HND models used the siba(4) on-chip interconnect, while later models 474ad7e9b0SAdrian Chadd * use bcma(4); the programming model is almost entirely independent 484ad7e9b0SAdrian Chadd * of the actual underlying interconect. 494ad7e9b0SAdrian Chadd */ 504ad7e9b0SAdrian Chadd 514ad7e9b0SAdrian Chadd #include <sys/param.h> 524ad7e9b0SAdrian Chadd #include <sys/kernel.h> 534ad7e9b0SAdrian Chadd #include <sys/bus.h> 544ad7e9b0SAdrian Chadd #include <sys/module.h> 554ad7e9b0SAdrian Chadd #include <sys/systm.h> 564ad7e9b0SAdrian Chadd 574ad7e9b0SAdrian Chadd #include <machine/bus.h> 584ad7e9b0SAdrian Chadd #include <sys/rman.h> 594ad7e9b0SAdrian Chadd #include <machine/resource.h> 604ad7e9b0SAdrian Chadd 61*fdedcd9fSLandon J. Fuller #include <dev/bhnd/cores/chipc/chipcvar.h> 62*fdedcd9fSLandon J. Fuller 63*fdedcd9fSLandon J. Fuller #include "bhnd_chipc_if.h" 64*fdedcd9fSLandon J. Fuller #include "bhnd_nvram_if.h" 65*fdedcd9fSLandon J. Fuller 664ad7e9b0SAdrian Chadd #include "bhnd.h" 674ad7e9b0SAdrian Chadd #include "bhndvar.h" 684ad7e9b0SAdrian Chadd 694ad7e9b0SAdrian Chadd MALLOC_DEFINE(M_BHND, "bhnd", "bhnd bus data structures"); 704ad7e9b0SAdrian Chadd 71*fdedcd9fSLandon J. Fuller /* Bus pass at which all bus-required children must be available, and 72*fdedcd9fSLandon J. Fuller * attachment may be finalized. */ 73*fdedcd9fSLandon J. Fuller #define BHND_FINISH_ATTACH_PASS BUS_PASS_DEFAULT 74*fdedcd9fSLandon J. Fuller 754ad7e9b0SAdrian Chadd /** 764ad7e9b0SAdrian Chadd * bhnd_generic_probe_nomatch() reporting configuration. 774ad7e9b0SAdrian Chadd */ 784ad7e9b0SAdrian Chadd static const struct bhnd_nomatch { 794ad7e9b0SAdrian Chadd uint16_t vendor; /**< core designer */ 804ad7e9b0SAdrian Chadd uint16_t device; /**< core id */ 814ad7e9b0SAdrian Chadd bool if_verbose; /**< print when bootverbose is set. */ 824ad7e9b0SAdrian Chadd } bhnd_nomatch_table[] = { 834ad7e9b0SAdrian Chadd { BHND_MFGID_ARM, BHND_COREID_OOB_ROUTER, true }, 844ad7e9b0SAdrian Chadd { BHND_MFGID_ARM, BHND_COREID_EROM, true }, 854ad7e9b0SAdrian Chadd { BHND_MFGID_ARM, BHND_COREID_PL301, true }, 864ad7e9b0SAdrian Chadd { BHND_MFGID_ARM, BHND_COREID_APB_BRIDGE, true }, 874ad7e9b0SAdrian Chadd { BHND_MFGID_ARM, BHND_COREID_AXI_UNMAPPED, false }, 884ad7e9b0SAdrian Chadd 894ad7e9b0SAdrian Chadd { BHND_MFGID_INVALID, BHND_COREID_INVALID, false } 904ad7e9b0SAdrian Chadd }; 914ad7e9b0SAdrian Chadd 92*fdedcd9fSLandon J. Fuller 93*fdedcd9fSLandon J. Fuller static int bhnd_delete_children(struct bhnd_softc *sc); 94*fdedcd9fSLandon J. Fuller 95*fdedcd9fSLandon J. Fuller static int bhnd_finish_attach(struct bhnd_softc *sc); 96*fdedcd9fSLandon J. Fuller 97*fdedcd9fSLandon J. Fuller static device_t bhnd_find_chipc(struct bhnd_softc *sc); 98*fdedcd9fSLandon J. Fuller static struct chipc_caps *bhnd_find_chipc_caps(struct bhnd_softc *sc); 99*fdedcd9fSLandon J. Fuller static device_t bhnd_find_platform_dev(struct bhnd_softc *sc, 100*fdedcd9fSLandon J. Fuller const char *classname); 101*fdedcd9fSLandon J. Fuller static device_t bhnd_find_pmu(struct bhnd_softc *sc); 102*fdedcd9fSLandon J. Fuller static device_t bhnd_find_nvram(struct bhnd_softc *sc); 103*fdedcd9fSLandon J. Fuller 1044ad7e9b0SAdrian Chadd static int compare_ascending_probe_order(const void *lhs, 1054ad7e9b0SAdrian Chadd const void *rhs); 1064ad7e9b0SAdrian Chadd static int compare_descending_probe_order(const void *lhs, 1074ad7e9b0SAdrian Chadd const void *rhs); 1084ad7e9b0SAdrian Chadd 1094ad7e9b0SAdrian Chadd /** 110386fb140SAdrian Chadd * Default bhnd(4) bus driver implementation of DEVICE_ATTACH(). 1114ad7e9b0SAdrian Chadd * 112386fb140SAdrian Chadd * This implementation calls device_probe_and_attach() for each of the device's 113386fb140SAdrian Chadd * children, in bhnd probe order. 1144ad7e9b0SAdrian Chadd */ 1154ad7e9b0SAdrian Chadd int 1164ad7e9b0SAdrian Chadd bhnd_generic_attach(device_t dev) 1174ad7e9b0SAdrian Chadd { 118*fdedcd9fSLandon J. Fuller struct bhnd_softc *sc; 1194ad7e9b0SAdrian Chadd device_t *devs; 1204ad7e9b0SAdrian Chadd int ndevs; 1214ad7e9b0SAdrian Chadd int error; 1224ad7e9b0SAdrian Chadd 1234ad7e9b0SAdrian Chadd if (device_is_attached(dev)) 1244ad7e9b0SAdrian Chadd return (EBUSY); 1254ad7e9b0SAdrian Chadd 126*fdedcd9fSLandon J. Fuller sc = device_get_softc(dev); 127*fdedcd9fSLandon J. Fuller sc->dev = dev; 128*fdedcd9fSLandon J. Fuller 1294ad7e9b0SAdrian Chadd if ((error = device_get_children(dev, &devs, &ndevs))) 1304ad7e9b0SAdrian Chadd return (error); 1314ad7e9b0SAdrian Chadd 132*fdedcd9fSLandon J. Fuller /* Probe and attach all children */ 1334ad7e9b0SAdrian Chadd qsort(devs, ndevs, sizeof(*devs), compare_ascending_probe_order); 1344ad7e9b0SAdrian Chadd for (int i = 0; i < ndevs; i++) { 1354ad7e9b0SAdrian Chadd device_t child = devs[i]; 1364ad7e9b0SAdrian Chadd device_probe_and_attach(child); 1374ad7e9b0SAdrian Chadd } 1384ad7e9b0SAdrian Chadd 139*fdedcd9fSLandon J. Fuller /* Try to finalize attachment */ 140*fdedcd9fSLandon J. Fuller if (bus_current_pass >= BHND_FINISH_ATTACH_PASS) { 141*fdedcd9fSLandon J. Fuller if ((error = bhnd_finish_attach(sc))) 142*fdedcd9fSLandon J. Fuller goto cleanup; 143*fdedcd9fSLandon J. Fuller } 144*fdedcd9fSLandon J. Fuller 145*fdedcd9fSLandon J. Fuller cleanup: 1464ad7e9b0SAdrian Chadd free(devs, M_TEMP); 147*fdedcd9fSLandon J. Fuller 148*fdedcd9fSLandon J. Fuller if (error) 149*fdedcd9fSLandon J. Fuller bhnd_delete_children(sc); 150*fdedcd9fSLandon J. Fuller 151*fdedcd9fSLandon J. Fuller return (error); 152*fdedcd9fSLandon J. Fuller } 153*fdedcd9fSLandon J. Fuller 154*fdedcd9fSLandon J. Fuller /** 155*fdedcd9fSLandon J. Fuller * Detach and delete all children, in reverse of their attach order. 156*fdedcd9fSLandon J. Fuller */ 157*fdedcd9fSLandon J. Fuller static int 158*fdedcd9fSLandon J. Fuller bhnd_delete_children(struct bhnd_softc *sc) 159*fdedcd9fSLandon J. Fuller { 160*fdedcd9fSLandon J. Fuller device_t *devs; 161*fdedcd9fSLandon J. Fuller int ndevs; 162*fdedcd9fSLandon J. Fuller int error; 163*fdedcd9fSLandon J. Fuller 164*fdedcd9fSLandon J. Fuller if ((error = device_get_children(sc->dev, &devs, &ndevs))) 165*fdedcd9fSLandon J. Fuller return (error); 166*fdedcd9fSLandon J. Fuller 167*fdedcd9fSLandon J. Fuller /* Detach in the reverse of attach order */ 168*fdedcd9fSLandon J. Fuller qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order); 169*fdedcd9fSLandon J. Fuller for (int i = 0; i < ndevs; i++) { 170*fdedcd9fSLandon J. Fuller device_t child = devs[i]; 171*fdedcd9fSLandon J. Fuller 172*fdedcd9fSLandon J. Fuller /* Terminate on first error */ 173*fdedcd9fSLandon J. Fuller if ((error = device_delete_child(sc->dev, child))) 174*fdedcd9fSLandon J. Fuller goto cleanup; 175*fdedcd9fSLandon J. Fuller } 176*fdedcd9fSLandon J. Fuller 177*fdedcd9fSLandon J. Fuller cleanup: 178*fdedcd9fSLandon J. Fuller free(devs, M_TEMP); 179*fdedcd9fSLandon J. Fuller return (error); 1804ad7e9b0SAdrian Chadd } 1814ad7e9b0SAdrian Chadd 1824ad7e9b0SAdrian Chadd /** 183386fb140SAdrian Chadd * Default bhnd(4) bus driver implementation of DEVICE_DETACH(). 1844ad7e9b0SAdrian Chadd * 185cef367e6SEitan Adler * This implementation calls device_detach() for each of the device's 186386fb140SAdrian Chadd * children, in reverse bhnd probe order, terminating if any call to 187386fb140SAdrian Chadd * device_detach() fails. 1884ad7e9b0SAdrian Chadd */ 1894ad7e9b0SAdrian Chadd int 1904ad7e9b0SAdrian Chadd bhnd_generic_detach(device_t dev) 1914ad7e9b0SAdrian Chadd { 192*fdedcd9fSLandon J. Fuller struct bhnd_softc *sc; 1934ad7e9b0SAdrian Chadd 1944ad7e9b0SAdrian Chadd if (!device_is_attached(dev)) 1954ad7e9b0SAdrian Chadd return (EBUSY); 1964ad7e9b0SAdrian Chadd 197*fdedcd9fSLandon J. Fuller sc = device_get_softc(dev); 198*fdedcd9fSLandon J. Fuller return (bhnd_delete_children(sc)); 1994ad7e9b0SAdrian Chadd } 2004ad7e9b0SAdrian Chadd 2014ad7e9b0SAdrian Chadd /** 202386fb140SAdrian Chadd * Default bhnd(4) bus driver implementation of DEVICE_SHUTDOWN(). 2034ad7e9b0SAdrian Chadd * 204386fb140SAdrian Chadd * This implementation calls device_shutdown() for each of the device's 205386fb140SAdrian Chadd * children, in reverse bhnd probe order, terminating if any call to 206386fb140SAdrian Chadd * device_shutdown() fails. 2074ad7e9b0SAdrian Chadd */ 2084ad7e9b0SAdrian Chadd int 2094ad7e9b0SAdrian Chadd bhnd_generic_shutdown(device_t dev) 2104ad7e9b0SAdrian Chadd { 2114ad7e9b0SAdrian Chadd device_t *devs; 2124ad7e9b0SAdrian Chadd int ndevs; 2134ad7e9b0SAdrian Chadd int error; 2144ad7e9b0SAdrian Chadd 2154ad7e9b0SAdrian Chadd if (!device_is_attached(dev)) 2164ad7e9b0SAdrian Chadd return (EBUSY); 2174ad7e9b0SAdrian Chadd 2184ad7e9b0SAdrian Chadd if ((error = device_get_children(dev, &devs, &ndevs))) 2194ad7e9b0SAdrian Chadd return (error); 2204ad7e9b0SAdrian Chadd 2214ad7e9b0SAdrian Chadd /* Shutdown in the reverse of attach order */ 2224ad7e9b0SAdrian Chadd qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order); 2234ad7e9b0SAdrian Chadd for (int i = 0; i < ndevs; i++) { 2244ad7e9b0SAdrian Chadd device_t child = devs[i]; 2254ad7e9b0SAdrian Chadd 2264ad7e9b0SAdrian Chadd /* Terminate on first error */ 2274ad7e9b0SAdrian Chadd if ((error = device_shutdown(child))) 2284ad7e9b0SAdrian Chadd goto cleanup; 2294ad7e9b0SAdrian Chadd } 2304ad7e9b0SAdrian Chadd 2314ad7e9b0SAdrian Chadd cleanup: 2324ad7e9b0SAdrian Chadd free(devs, M_TEMP); 2334ad7e9b0SAdrian Chadd return (error); 2344ad7e9b0SAdrian Chadd } 2354ad7e9b0SAdrian Chadd 2364ad7e9b0SAdrian Chadd /** 237386fb140SAdrian Chadd * Default bhnd(4) bus driver implementation of DEVICE_RESUME(). 2384ad7e9b0SAdrian Chadd * 239386fb140SAdrian Chadd * This implementation calls BUS_RESUME_CHILD() for each of the device's 240386fb140SAdrian Chadd * children in bhnd probe order, terminating if any call to BUS_RESUME_CHILD() 241386fb140SAdrian Chadd * fails. 2424ad7e9b0SAdrian Chadd */ 2434ad7e9b0SAdrian Chadd int 2444ad7e9b0SAdrian Chadd bhnd_generic_resume(device_t dev) 2454ad7e9b0SAdrian Chadd { 2464ad7e9b0SAdrian Chadd device_t *devs; 2474ad7e9b0SAdrian Chadd int ndevs; 2484ad7e9b0SAdrian Chadd int error; 2494ad7e9b0SAdrian Chadd 2504ad7e9b0SAdrian Chadd if (!device_is_attached(dev)) 2514ad7e9b0SAdrian Chadd return (EBUSY); 2524ad7e9b0SAdrian Chadd 2534ad7e9b0SAdrian Chadd if ((error = device_get_children(dev, &devs, &ndevs))) 2544ad7e9b0SAdrian Chadd return (error); 2554ad7e9b0SAdrian Chadd 2564ad7e9b0SAdrian Chadd qsort(devs, ndevs, sizeof(*devs), compare_ascending_probe_order); 2574ad7e9b0SAdrian Chadd for (int i = 0; i < ndevs; i++) { 2584ad7e9b0SAdrian Chadd device_t child = devs[i]; 2594ad7e9b0SAdrian Chadd 2604ad7e9b0SAdrian Chadd /* Terminate on first error */ 2614ad7e9b0SAdrian Chadd if ((error = BUS_RESUME_CHILD(device_get_parent(child), child))) 2624ad7e9b0SAdrian Chadd goto cleanup; 2634ad7e9b0SAdrian Chadd } 2644ad7e9b0SAdrian Chadd 2654ad7e9b0SAdrian Chadd cleanup: 2664ad7e9b0SAdrian Chadd free(devs, M_TEMP); 2674ad7e9b0SAdrian Chadd return (error); 2684ad7e9b0SAdrian Chadd } 2694ad7e9b0SAdrian Chadd 2704ad7e9b0SAdrian Chadd /** 271386fb140SAdrian Chadd * Default bhnd(4) bus driver implementation of DEVICE_SUSPEND(). 2724ad7e9b0SAdrian Chadd * 273386fb140SAdrian Chadd * This implementation calls BUS_SUSPEND_CHILD() for each of the device's 274386fb140SAdrian Chadd * children in reverse bhnd probe order. If any call to BUS_SUSPEND_CHILD() 275386fb140SAdrian Chadd * fails, the suspend operation is terminated and any devices that were 276386fb140SAdrian Chadd * suspended are resumed immediately by calling their BUS_RESUME_CHILD() 277386fb140SAdrian Chadd * methods. 2784ad7e9b0SAdrian Chadd */ 2794ad7e9b0SAdrian Chadd int 2804ad7e9b0SAdrian Chadd bhnd_generic_suspend(device_t dev) 2814ad7e9b0SAdrian Chadd { 2824ad7e9b0SAdrian Chadd device_t *devs; 2834ad7e9b0SAdrian Chadd int ndevs; 2844ad7e9b0SAdrian Chadd int error; 2854ad7e9b0SAdrian Chadd 2864ad7e9b0SAdrian Chadd if (!device_is_attached(dev)) 2874ad7e9b0SAdrian Chadd return (EBUSY); 2884ad7e9b0SAdrian Chadd 2894ad7e9b0SAdrian Chadd if ((error = device_get_children(dev, &devs, &ndevs))) 2904ad7e9b0SAdrian Chadd return (error); 2914ad7e9b0SAdrian Chadd 2924ad7e9b0SAdrian Chadd /* Suspend in the reverse of attach order */ 2934ad7e9b0SAdrian Chadd qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order); 2944ad7e9b0SAdrian Chadd for (int i = 0; i < ndevs; i++) { 2954ad7e9b0SAdrian Chadd device_t child = devs[i]; 2964ad7e9b0SAdrian Chadd error = BUS_SUSPEND_CHILD(device_get_parent(child), child); 2974ad7e9b0SAdrian Chadd 2984ad7e9b0SAdrian Chadd /* On error, resume suspended devices and then terminate */ 2994ad7e9b0SAdrian Chadd if (error) { 3004ad7e9b0SAdrian Chadd for (int j = 0; j < i; j++) { 3014ad7e9b0SAdrian Chadd BUS_RESUME_CHILD(device_get_parent(devs[j]), 3024ad7e9b0SAdrian Chadd devs[j]); 3034ad7e9b0SAdrian Chadd } 3044ad7e9b0SAdrian Chadd 3054ad7e9b0SAdrian Chadd goto cleanup; 3064ad7e9b0SAdrian Chadd } 3074ad7e9b0SAdrian Chadd } 3084ad7e9b0SAdrian Chadd 3094ad7e9b0SAdrian Chadd cleanup: 3104ad7e9b0SAdrian Chadd free(devs, M_TEMP); 3114ad7e9b0SAdrian Chadd return (error); 3124ad7e9b0SAdrian Chadd } 3134ad7e9b0SAdrian Chadd 314*fdedcd9fSLandon J. Fuller static void 315*fdedcd9fSLandon J. Fuller bhnd_new_pass(device_t dev) 316*fdedcd9fSLandon J. Fuller { 317*fdedcd9fSLandon J. Fuller struct bhnd_softc *sc; 318*fdedcd9fSLandon J. Fuller int error; 319*fdedcd9fSLandon J. Fuller 320*fdedcd9fSLandon J. Fuller sc = device_get_softc(dev); 321*fdedcd9fSLandon J. Fuller 322*fdedcd9fSLandon J. Fuller /* Attach any permissible children */ 323*fdedcd9fSLandon J. Fuller bus_generic_new_pass(dev); 324*fdedcd9fSLandon J. Fuller 325*fdedcd9fSLandon J. Fuller /* Finalize attachment */ 326*fdedcd9fSLandon J. Fuller if (!sc->attach_done && bus_current_pass >= BHND_FINISH_ATTACH_PASS) { 327*fdedcd9fSLandon J. Fuller if ((error = bhnd_finish_attach(sc))) { 328*fdedcd9fSLandon J. Fuller panic("bhnd_finish_attach() failed: %d", error); 329*fdedcd9fSLandon J. Fuller } 330*fdedcd9fSLandon J. Fuller } 331*fdedcd9fSLandon J. Fuller } 332*fdedcd9fSLandon J. Fuller 333*fdedcd9fSLandon J. Fuller /* 334*fdedcd9fSLandon J. Fuller * Finish any pending bus attachment operations. 335*fdedcd9fSLandon J. Fuller * 336*fdedcd9fSLandon J. Fuller * When attached as a SoC bus (as opposed to a bridged WiFi device), our 337*fdedcd9fSLandon J. Fuller * platform devices may not be attached until later bus passes, necessitating 338*fdedcd9fSLandon J. Fuller * delayed initialization on our part. 339*fdedcd9fSLandon J. Fuller */ 340*fdedcd9fSLandon J. Fuller static int 341*fdedcd9fSLandon J. Fuller bhnd_finish_attach(struct bhnd_softc *sc) 342*fdedcd9fSLandon J. Fuller { 343*fdedcd9fSLandon J. Fuller struct chipc_caps *ccaps; 344*fdedcd9fSLandon J. Fuller 345*fdedcd9fSLandon J. Fuller GIANT_REQUIRED; /* newbus */ 346*fdedcd9fSLandon J. Fuller 347*fdedcd9fSLandon J. Fuller KASSERT(bus_current_pass >= BHND_FINISH_ATTACH_PASS, 348*fdedcd9fSLandon J. Fuller ("bhnd_finish_attach() called in pass %d", bus_current_pass)); 349*fdedcd9fSLandon J. Fuller 350*fdedcd9fSLandon J. Fuller KASSERT(!sc->attach_done, ("duplicate call to bhnd_finish_attach()")); 351*fdedcd9fSLandon J. Fuller 352*fdedcd9fSLandon J. Fuller /* Locate chipc device */ 353*fdedcd9fSLandon J. Fuller if ((sc->chipc_dev = bhnd_find_chipc(sc)) == NULL) { 354*fdedcd9fSLandon J. Fuller device_printf(sc->dev, "error: ChipCommon device not found\n"); 355*fdedcd9fSLandon J. Fuller return (ENXIO); 356*fdedcd9fSLandon J. Fuller } 357*fdedcd9fSLandon J. Fuller 358*fdedcd9fSLandon J. Fuller ccaps = BHND_CHIPC_GET_CAPS(sc->chipc_dev); 359*fdedcd9fSLandon J. Fuller 360*fdedcd9fSLandon J. Fuller /* Look for NVRAM device */ 361*fdedcd9fSLandon J. Fuller if (ccaps->nvram_src != BHND_NVRAM_SRC_UNKNOWN) { 362*fdedcd9fSLandon J. Fuller if ((sc->nvram_dev = bhnd_find_nvram(sc)) == NULL) { 363*fdedcd9fSLandon J. Fuller device_printf(sc->dev, 364*fdedcd9fSLandon J. Fuller "warning: %s NVRAM device not found\n", 365*fdedcd9fSLandon J. Fuller bhnd_nvram_src_name(ccaps->nvram_src)); 366*fdedcd9fSLandon J. Fuller } 367*fdedcd9fSLandon J. Fuller } 368*fdedcd9fSLandon J. Fuller 369*fdedcd9fSLandon J. Fuller /* Look for a PMU */ 370*fdedcd9fSLandon J. Fuller if (ccaps->pmu) { 371*fdedcd9fSLandon J. Fuller if ((sc->pmu_dev = bhnd_find_pmu(sc)) == NULL) { 372*fdedcd9fSLandon J. Fuller device_printf(sc->dev, 373*fdedcd9fSLandon J. Fuller "warning: PMU device not found\n"); 374*fdedcd9fSLandon J. Fuller } 375*fdedcd9fSLandon J. Fuller } 376*fdedcd9fSLandon J. Fuller 377*fdedcd9fSLandon J. Fuller /* Mark attach as completed */ 378*fdedcd9fSLandon J. Fuller sc->attach_done = true; 379*fdedcd9fSLandon J. Fuller 380*fdedcd9fSLandon J. Fuller return (0); 381*fdedcd9fSLandon J. Fuller } 382*fdedcd9fSLandon J. Fuller 383*fdedcd9fSLandon J. Fuller /* Locate the ChipCommon core. */ 384*fdedcd9fSLandon J. Fuller static device_t 385*fdedcd9fSLandon J. Fuller bhnd_find_chipc(struct bhnd_softc *sc) 386*fdedcd9fSLandon J. Fuller { 387*fdedcd9fSLandon J. Fuller device_t chipc; 388*fdedcd9fSLandon J. Fuller 389*fdedcd9fSLandon J. Fuller /* Make sure we're holding Giant for newbus */ 390*fdedcd9fSLandon J. Fuller GIANT_REQUIRED; 391*fdedcd9fSLandon J. Fuller 392*fdedcd9fSLandon J. Fuller /* chipc_dev is initialized during attachment */ 393*fdedcd9fSLandon J. Fuller if (sc->attach_done) { 394*fdedcd9fSLandon J. Fuller if ((chipc = sc->chipc_dev) == NULL) 395*fdedcd9fSLandon J. Fuller return (NULL); 396*fdedcd9fSLandon J. Fuller 397*fdedcd9fSLandon J. Fuller goto found; 398*fdedcd9fSLandon J. Fuller } 399*fdedcd9fSLandon J. Fuller 400*fdedcd9fSLandon J. Fuller /* Locate chipc core with a core unit of 0 */ 401*fdedcd9fSLandon J. Fuller chipc = bhnd_find_child(sc->dev, BHND_DEVCLASS_CC, 0); 402*fdedcd9fSLandon J. Fuller if (chipc == NULL) 403*fdedcd9fSLandon J. Fuller return (NULL); 404*fdedcd9fSLandon J. Fuller 405*fdedcd9fSLandon J. Fuller found: 406*fdedcd9fSLandon J. Fuller if (device_get_state(chipc) < DS_ATTACHING) { 407*fdedcd9fSLandon J. Fuller device_printf(sc->dev, "chipc found, but did not attach\n"); 408*fdedcd9fSLandon J. Fuller return (NULL); 409*fdedcd9fSLandon J. Fuller } 410*fdedcd9fSLandon J. Fuller 411*fdedcd9fSLandon J. Fuller return (chipc); 412*fdedcd9fSLandon J. Fuller } 413*fdedcd9fSLandon J. Fuller 414*fdedcd9fSLandon J. Fuller /* Locate the ChipCommon core and return the device capabilities */ 415*fdedcd9fSLandon J. Fuller static struct chipc_caps * 416*fdedcd9fSLandon J. Fuller bhnd_find_chipc_caps(struct bhnd_softc *sc) 417*fdedcd9fSLandon J. Fuller { 418*fdedcd9fSLandon J. Fuller device_t chipc; 419*fdedcd9fSLandon J. Fuller 420*fdedcd9fSLandon J. Fuller if ((chipc = bhnd_find_chipc(sc)) == NULL) { 421*fdedcd9fSLandon J. Fuller device_printf(sc->dev, 422*fdedcd9fSLandon J. Fuller "chipc unavailable; cannot fetch capabilities\n"); 423*fdedcd9fSLandon J. Fuller return (NULL); 424*fdedcd9fSLandon J. Fuller } 425*fdedcd9fSLandon J. Fuller 426*fdedcd9fSLandon J. Fuller return (BHND_CHIPC_GET_CAPS(chipc)); 427*fdedcd9fSLandon J. Fuller } 428*fdedcd9fSLandon J. Fuller 429*fdedcd9fSLandon J. Fuller /** 430*fdedcd9fSLandon J. Fuller * Find an attached platform device on @p dev, searching first for cores 431*fdedcd9fSLandon J. Fuller * matching @p classname, and if not found, searching the children of the first 432*fdedcd9fSLandon J. Fuller * bhnd_chipc device on the bus. 433*fdedcd9fSLandon J. Fuller * 434*fdedcd9fSLandon J. Fuller * @param sc Driver state. 435*fdedcd9fSLandon J. Fuller * @param chipc Attached ChipCommon device. 436*fdedcd9fSLandon J. Fuller * @param classname Device class to search for. 437*fdedcd9fSLandon J. Fuller * 438*fdedcd9fSLandon J. Fuller * @retval device_t A matching device. 439*fdedcd9fSLandon J. Fuller * @retval NULL If no matching device is found. 440*fdedcd9fSLandon J. Fuller */ 441*fdedcd9fSLandon J. Fuller static device_t 442*fdedcd9fSLandon J. Fuller bhnd_find_platform_dev(struct bhnd_softc *sc, const char *classname) 443*fdedcd9fSLandon J. Fuller { 444*fdedcd9fSLandon J. Fuller device_t chipc, child; 445*fdedcd9fSLandon J. Fuller 446*fdedcd9fSLandon J. Fuller /* Make sure we're holding Giant for newbus */ 447*fdedcd9fSLandon J. Fuller GIANT_REQUIRED; 448*fdedcd9fSLandon J. Fuller 449*fdedcd9fSLandon J. Fuller /* Look for a directly-attached child */ 450*fdedcd9fSLandon J. Fuller child = device_find_child(sc->dev, classname, -1); 451*fdedcd9fSLandon J. Fuller if (child != NULL) 452*fdedcd9fSLandon J. Fuller goto found; 453*fdedcd9fSLandon J. Fuller 454*fdedcd9fSLandon J. Fuller /* Look for the first matching ChipCommon child */ 455*fdedcd9fSLandon J. Fuller if ((chipc = bhnd_find_chipc(sc)) == NULL) { 456*fdedcd9fSLandon J. Fuller device_printf(sc->dev, 457*fdedcd9fSLandon J. Fuller "chipc unavailable; cannot locate %s\n", classname); 458*fdedcd9fSLandon J. Fuller return (NULL); 459*fdedcd9fSLandon J. Fuller } 460*fdedcd9fSLandon J. Fuller 461*fdedcd9fSLandon J. Fuller child = device_find_child(chipc, classname, -1); 462*fdedcd9fSLandon J. Fuller if (child == NULL) 463*fdedcd9fSLandon J. Fuller return (NULL); 464*fdedcd9fSLandon J. Fuller 465*fdedcd9fSLandon J. Fuller found: 466*fdedcd9fSLandon J. Fuller if (device_get_state(child) < DS_ATTACHING) 467*fdedcd9fSLandon J. Fuller return (NULL); 468*fdedcd9fSLandon J. Fuller 469*fdedcd9fSLandon J. Fuller return (child); 470*fdedcd9fSLandon J. Fuller } 471*fdedcd9fSLandon J. Fuller 472*fdedcd9fSLandon J. Fuller /* Locate the PMU device, if any */ 473*fdedcd9fSLandon J. Fuller static device_t 474*fdedcd9fSLandon J. Fuller bhnd_find_pmu(struct bhnd_softc *sc) 475*fdedcd9fSLandon J. Fuller { 476*fdedcd9fSLandon J. Fuller struct chipc_caps *ccaps; 477*fdedcd9fSLandon J. Fuller 478*fdedcd9fSLandon J. Fuller /* Make sure we're holding Giant for newbus */ 479*fdedcd9fSLandon J. Fuller GIANT_REQUIRED; 480*fdedcd9fSLandon J. Fuller 481*fdedcd9fSLandon J. Fuller /* pmu_dev is initialized during attachment */ 482*fdedcd9fSLandon J. Fuller if (sc->attach_done) { 483*fdedcd9fSLandon J. Fuller if (sc->pmu_dev == NULL) 484*fdedcd9fSLandon J. Fuller return (NULL); 485*fdedcd9fSLandon J. Fuller 486*fdedcd9fSLandon J. Fuller if (device_get_state(sc->pmu_dev) < DS_ATTACHING) 487*fdedcd9fSLandon J. Fuller return (NULL); 488*fdedcd9fSLandon J. Fuller 489*fdedcd9fSLandon J. Fuller return (sc->pmu_dev); 490*fdedcd9fSLandon J. Fuller } 491*fdedcd9fSLandon J. Fuller 492*fdedcd9fSLandon J. Fuller if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL) 493*fdedcd9fSLandon J. Fuller return (NULL); 494*fdedcd9fSLandon J. Fuller 495*fdedcd9fSLandon J. Fuller if (!ccaps->pmu) 496*fdedcd9fSLandon J. Fuller return (NULL); 497*fdedcd9fSLandon J. Fuller 498*fdedcd9fSLandon J. Fuller return (bhnd_find_platform_dev(sc, "bhnd_pmu")); 499*fdedcd9fSLandon J. Fuller } 500*fdedcd9fSLandon J. Fuller 501*fdedcd9fSLandon J. Fuller /* Locate the NVRAM device, if any */ 502*fdedcd9fSLandon J. Fuller static device_t 503*fdedcd9fSLandon J. Fuller bhnd_find_nvram(struct bhnd_softc *sc) 504*fdedcd9fSLandon J. Fuller { 505*fdedcd9fSLandon J. Fuller struct chipc_caps *ccaps; 506*fdedcd9fSLandon J. Fuller 507*fdedcd9fSLandon J. Fuller /* Make sure we're holding Giant for newbus */ 508*fdedcd9fSLandon J. Fuller GIANT_REQUIRED; 509*fdedcd9fSLandon J. Fuller 510*fdedcd9fSLandon J. Fuller 511*fdedcd9fSLandon J. Fuller /* nvram_dev is initialized during attachment */ 512*fdedcd9fSLandon J. Fuller if (sc->attach_done) { 513*fdedcd9fSLandon J. Fuller if (sc->nvram_dev == NULL) 514*fdedcd9fSLandon J. Fuller return (NULL); 515*fdedcd9fSLandon J. Fuller 516*fdedcd9fSLandon J. Fuller if (device_get_state(sc->nvram_dev) < DS_ATTACHING) 517*fdedcd9fSLandon J. Fuller return (NULL); 518*fdedcd9fSLandon J. Fuller 519*fdedcd9fSLandon J. Fuller return (sc->nvram_dev); 520*fdedcd9fSLandon J. Fuller } 521*fdedcd9fSLandon J. Fuller 522*fdedcd9fSLandon J. Fuller if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL) 523*fdedcd9fSLandon J. Fuller return (NULL); 524*fdedcd9fSLandon J. Fuller 525*fdedcd9fSLandon J. Fuller if (ccaps->nvram_src == BHND_NVRAM_SRC_UNKNOWN) 526*fdedcd9fSLandon J. Fuller return (NULL); 527*fdedcd9fSLandon J. Fuller 528*fdedcd9fSLandon J. Fuller return (bhnd_find_platform_dev(sc, "bhnd_nvram")); 529*fdedcd9fSLandon J. Fuller } 530*fdedcd9fSLandon J. Fuller 5314ad7e9b0SAdrian Chadd /* 5324ad7e9b0SAdrian Chadd * Ascending comparison of bhnd device's probe order. 5334ad7e9b0SAdrian Chadd */ 5344ad7e9b0SAdrian Chadd static int 5354ad7e9b0SAdrian Chadd compare_ascending_probe_order(const void *lhs, const void *rhs) 5364ad7e9b0SAdrian Chadd { 5374ad7e9b0SAdrian Chadd device_t ldev, rdev; 5384ad7e9b0SAdrian Chadd int lorder, rorder; 5394ad7e9b0SAdrian Chadd 5404ad7e9b0SAdrian Chadd ldev = (*(const device_t *) lhs); 5414ad7e9b0SAdrian Chadd rdev = (*(const device_t *) rhs); 5424ad7e9b0SAdrian Chadd 5434ad7e9b0SAdrian Chadd lorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(ldev), ldev); 5444ad7e9b0SAdrian Chadd rorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(rdev), rdev); 5454ad7e9b0SAdrian Chadd 5464ad7e9b0SAdrian Chadd if (lorder < rorder) { 5474ad7e9b0SAdrian Chadd return (-1); 5484ad7e9b0SAdrian Chadd } else if (lorder > rorder) { 5494ad7e9b0SAdrian Chadd return (1); 5504ad7e9b0SAdrian Chadd } else { 5514ad7e9b0SAdrian Chadd return (0); 5524ad7e9b0SAdrian Chadd } 5534ad7e9b0SAdrian Chadd } 5544ad7e9b0SAdrian Chadd 5554ad7e9b0SAdrian Chadd /* 5564ad7e9b0SAdrian Chadd * Descending comparison of bhnd device's probe order. 5574ad7e9b0SAdrian Chadd */ 5584ad7e9b0SAdrian Chadd static int 5594ad7e9b0SAdrian Chadd compare_descending_probe_order(const void *lhs, const void *rhs) 5604ad7e9b0SAdrian Chadd { 5614ad7e9b0SAdrian Chadd return (compare_ascending_probe_order(rhs, lhs)); 5624ad7e9b0SAdrian Chadd } 5634ad7e9b0SAdrian Chadd 5644ad7e9b0SAdrian Chadd /** 565386fb140SAdrian Chadd * Default bhnd(4) bus driver implementation of BHND_BUS_GET_PROBE_ORDER(). 5664ad7e9b0SAdrian Chadd * 5674ad7e9b0SAdrian Chadd * This implementation determines probe ordering based on the device's class 5684ad7e9b0SAdrian Chadd * and other properties, including whether the device is serving as a host 5694ad7e9b0SAdrian Chadd * bridge. 5704ad7e9b0SAdrian Chadd */ 5714ad7e9b0SAdrian Chadd int 5724ad7e9b0SAdrian Chadd bhnd_generic_get_probe_order(device_t dev, device_t child) 5734ad7e9b0SAdrian Chadd { 5744ad7e9b0SAdrian Chadd switch (bhnd_get_class(child)) { 5754ad7e9b0SAdrian Chadd case BHND_DEVCLASS_CC: 576d567592bSAdrian Chadd /* Must be early enough to provide NVRAM access to the 577d567592bSAdrian Chadd * host bridge */ 578d567592bSAdrian Chadd return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_FIRST); 5794ad7e9b0SAdrian Chadd 5804ad7e9b0SAdrian Chadd case BHND_DEVCLASS_CC_B: 5814ad7e9b0SAdrian Chadd /* fall through */ 5824ad7e9b0SAdrian Chadd case BHND_DEVCLASS_PMU: 5834ad7e9b0SAdrian Chadd return (BHND_PROBE_BUS + BHND_PROBE_ORDER_EARLY); 5844ad7e9b0SAdrian Chadd 5854ad7e9b0SAdrian Chadd case BHND_DEVCLASS_SOC_ROUTER: 5864ad7e9b0SAdrian Chadd return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LATE); 5874ad7e9b0SAdrian Chadd 5884ad7e9b0SAdrian Chadd case BHND_DEVCLASS_SOC_BRIDGE: 5894ad7e9b0SAdrian Chadd return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LAST); 5904ad7e9b0SAdrian Chadd 5914ad7e9b0SAdrian Chadd case BHND_DEVCLASS_CPU: 5924ad7e9b0SAdrian Chadd return (BHND_PROBE_CPU + BHND_PROBE_ORDER_FIRST); 5934ad7e9b0SAdrian Chadd 5944ad7e9b0SAdrian Chadd case BHND_DEVCLASS_RAM: 5954ad7e9b0SAdrian Chadd /* fall through */ 5964ad7e9b0SAdrian Chadd case BHND_DEVCLASS_MEMC: 5974ad7e9b0SAdrian Chadd return (BHND_PROBE_CPU + BHND_PROBE_ORDER_EARLY); 5984ad7e9b0SAdrian Chadd 5994ad7e9b0SAdrian Chadd case BHND_DEVCLASS_NVRAM: 6004ad7e9b0SAdrian Chadd return (BHND_PROBE_RESOURCE + BHND_PROBE_ORDER_EARLY); 6014ad7e9b0SAdrian Chadd 6024ad7e9b0SAdrian Chadd case BHND_DEVCLASS_PCI: 6034ad7e9b0SAdrian Chadd case BHND_DEVCLASS_PCIE: 6044ad7e9b0SAdrian Chadd case BHND_DEVCLASS_PCCARD: 6054ad7e9b0SAdrian Chadd case BHND_DEVCLASS_ENET: 6064ad7e9b0SAdrian Chadd case BHND_DEVCLASS_ENET_MAC: 6074ad7e9b0SAdrian Chadd case BHND_DEVCLASS_ENET_PHY: 6084ad7e9b0SAdrian Chadd case BHND_DEVCLASS_WLAN: 6094ad7e9b0SAdrian Chadd case BHND_DEVCLASS_WLAN_MAC: 6104ad7e9b0SAdrian Chadd case BHND_DEVCLASS_WLAN_PHY: 6114ad7e9b0SAdrian Chadd case BHND_DEVCLASS_EROM: 6124ad7e9b0SAdrian Chadd case BHND_DEVCLASS_OTHER: 6134ad7e9b0SAdrian Chadd case BHND_DEVCLASS_INVALID: 614d9352570SAdrian Chadd if (bhnd_find_hostb_device(dev) == child) 6154ad7e9b0SAdrian Chadd return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY); 6164ad7e9b0SAdrian Chadd 6174ad7e9b0SAdrian Chadd return (BHND_PROBE_DEFAULT); 618054ae231SAdrian Chadd default: 619054ae231SAdrian Chadd return (BHND_PROBE_DEFAULT); 6204ad7e9b0SAdrian Chadd } 6214ad7e9b0SAdrian Chadd } 6224ad7e9b0SAdrian Chadd 6234ad7e9b0SAdrian Chadd /** 624386fb140SAdrian Chadd * Default bhnd(4) bus driver implementation of BHND_BUS_IS_REGION_VALID(). 6254ad7e9b0SAdrian Chadd * 6264ad7e9b0SAdrian Chadd * This implementation assumes that port and region numbers are 0-indexed and 6274ad7e9b0SAdrian Chadd * are allocated non-sparsely, using BHND_BUS_GET_PORT_COUNT() and 6284ad7e9b0SAdrian Chadd * BHND_BUS_GET_REGION_COUNT() to determine if @p port and @p region fall 6294ad7e9b0SAdrian Chadd * within the defined range. 6304ad7e9b0SAdrian Chadd */ 631386fb140SAdrian Chadd static bool 6324ad7e9b0SAdrian Chadd bhnd_generic_is_region_valid(device_t dev, device_t child, 6334ad7e9b0SAdrian Chadd bhnd_port_type type, u_int port, u_int region) 6344ad7e9b0SAdrian Chadd { 6354ad7e9b0SAdrian Chadd if (port >= bhnd_get_port_count(child, type)) 6364ad7e9b0SAdrian Chadd return (false); 6374ad7e9b0SAdrian Chadd 6384ad7e9b0SAdrian Chadd if (region >= bhnd_get_region_count(child, type, port)) 6394ad7e9b0SAdrian Chadd return (false); 6404ad7e9b0SAdrian Chadd 6414ad7e9b0SAdrian Chadd return (true); 6424ad7e9b0SAdrian Chadd } 6434ad7e9b0SAdrian Chadd 6444ad7e9b0SAdrian Chadd /** 645*fdedcd9fSLandon J. Fuller * Default bhnd(4) bus driver implementation of BHND_BUS_GET_NVRAM_VAR(). 646*fdedcd9fSLandon J. Fuller * 647*fdedcd9fSLandon J. Fuller * This implementation searches @p dev for a usable NVRAM child device. 648*fdedcd9fSLandon J. Fuller * 649*fdedcd9fSLandon J. Fuller * If no usable child device is found on @p dev, the request is delegated to 650*fdedcd9fSLandon J. Fuller * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev. 651*fdedcd9fSLandon J. Fuller */ 652*fdedcd9fSLandon J. Fuller int 653*fdedcd9fSLandon J. Fuller bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name, 654*fdedcd9fSLandon J. Fuller void *buf, size_t *size) 655*fdedcd9fSLandon J. Fuller { 656*fdedcd9fSLandon J. Fuller struct bhnd_softc *sc; 657*fdedcd9fSLandon J. Fuller device_t nvram, parent; 658*fdedcd9fSLandon J. Fuller 659*fdedcd9fSLandon J. Fuller sc = device_get_softc(dev); 660*fdedcd9fSLandon J. Fuller 661*fdedcd9fSLandon J. Fuller /* If a NVRAM device is available, consult it first */ 662*fdedcd9fSLandon J. Fuller if ((nvram = bhnd_find_nvram(sc)) != NULL) 663*fdedcd9fSLandon J. Fuller return BHND_NVRAM_GETVAR(nvram, name, buf, size); 664*fdedcd9fSLandon J. Fuller 665*fdedcd9fSLandon J. Fuller /* Otherwise, try to delegate to parent */ 666*fdedcd9fSLandon J. Fuller if ((parent = device_get_parent(dev)) == NULL) 667*fdedcd9fSLandon J. Fuller return (ENODEV); 668*fdedcd9fSLandon J. Fuller 669*fdedcd9fSLandon J. Fuller return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child, 670*fdedcd9fSLandon J. Fuller name, buf, size)); 671*fdedcd9fSLandon J. Fuller } 672*fdedcd9fSLandon J. Fuller 673*fdedcd9fSLandon J. Fuller /** 674386fb140SAdrian Chadd * Default bhnd(4) bus driver implementation of BUS_PRINT_CHILD(). 6754ad7e9b0SAdrian Chadd * 6764ad7e9b0SAdrian Chadd * This implementation requests the device's struct resource_list via 6774ad7e9b0SAdrian Chadd * BUS_GET_RESOURCE_LIST. 6784ad7e9b0SAdrian Chadd */ 6794ad7e9b0SAdrian Chadd int 6804ad7e9b0SAdrian Chadd bhnd_generic_print_child(device_t dev, device_t child) 6814ad7e9b0SAdrian Chadd { 6824ad7e9b0SAdrian Chadd struct resource_list *rl; 6834ad7e9b0SAdrian Chadd int retval = 0; 6844ad7e9b0SAdrian Chadd 6854ad7e9b0SAdrian Chadd retval += bus_print_child_header(dev, child); 6864ad7e9b0SAdrian Chadd 6874ad7e9b0SAdrian Chadd rl = BUS_GET_RESOURCE_LIST(dev, child); 6884ad7e9b0SAdrian Chadd if (rl != NULL) { 6894ad7e9b0SAdrian Chadd retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, 690f8fd3fb5SJustin Hibbits "%#jx"); 6914ad7e9b0SAdrian Chadd } 6924ad7e9b0SAdrian Chadd 6934ad7e9b0SAdrian Chadd retval += printf(" at core %u", bhnd_get_core_index(child)); 6944ad7e9b0SAdrian Chadd 6954ad7e9b0SAdrian Chadd retval += bus_print_child_domain(dev, child); 6964ad7e9b0SAdrian Chadd retval += bus_print_child_footer(dev, child); 6974ad7e9b0SAdrian Chadd 6984ad7e9b0SAdrian Chadd return (retval); 6994ad7e9b0SAdrian Chadd } 7004ad7e9b0SAdrian Chadd 7014ad7e9b0SAdrian Chadd /** 702386fb140SAdrian Chadd * Default bhnd(4) bus driver implementation of BUS_PROBE_NOMATCH(). 7034ad7e9b0SAdrian Chadd * 7044ad7e9b0SAdrian Chadd * This implementation requests the device's struct resource_list via 7054ad7e9b0SAdrian Chadd * BUS_GET_RESOURCE_LIST. 7064ad7e9b0SAdrian Chadd */ 7074ad7e9b0SAdrian Chadd void 7084ad7e9b0SAdrian Chadd bhnd_generic_probe_nomatch(device_t dev, device_t child) 7094ad7e9b0SAdrian Chadd { 7104ad7e9b0SAdrian Chadd struct resource_list *rl; 7114ad7e9b0SAdrian Chadd const struct bhnd_nomatch *nm; 7124ad7e9b0SAdrian Chadd bool report; 7134ad7e9b0SAdrian Chadd 7144ad7e9b0SAdrian Chadd /* Fetch reporting configuration for this device */ 7154ad7e9b0SAdrian Chadd report = true; 7164ad7e9b0SAdrian Chadd for (nm = bhnd_nomatch_table; nm->device != BHND_COREID_INVALID; nm++) { 7174ad7e9b0SAdrian Chadd if (nm->vendor != bhnd_get_vendor(child)) 7184ad7e9b0SAdrian Chadd continue; 7194ad7e9b0SAdrian Chadd 7204ad7e9b0SAdrian Chadd if (nm->device != bhnd_get_device(child)) 7214ad7e9b0SAdrian Chadd continue; 7224ad7e9b0SAdrian Chadd 7234ad7e9b0SAdrian Chadd report = false; 7244ad7e9b0SAdrian Chadd if (bootverbose && nm->if_verbose) 7254ad7e9b0SAdrian Chadd report = true; 7264ad7e9b0SAdrian Chadd break; 7274ad7e9b0SAdrian Chadd } 7284ad7e9b0SAdrian Chadd 7294ad7e9b0SAdrian Chadd if (!report) 7304ad7e9b0SAdrian Chadd return; 7314ad7e9b0SAdrian Chadd 7324ad7e9b0SAdrian Chadd /* Print the non-matched device info */ 7334ad7e9b0SAdrian Chadd device_printf(dev, "<%s %s>", bhnd_get_vendor_name(child), 7344ad7e9b0SAdrian Chadd bhnd_get_device_name(child)); 7354ad7e9b0SAdrian Chadd 7364ad7e9b0SAdrian Chadd rl = BUS_GET_RESOURCE_LIST(dev, child); 7374ad7e9b0SAdrian Chadd if (rl != NULL) 738f8fd3fb5SJustin Hibbits resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx"); 7394ad7e9b0SAdrian Chadd 7404ad7e9b0SAdrian Chadd printf(" at core %u (no driver attached)\n", 7414ad7e9b0SAdrian Chadd bhnd_get_core_index(child)); 7424ad7e9b0SAdrian Chadd } 7434ad7e9b0SAdrian Chadd 7444ad7e9b0SAdrian Chadd /** 7454ad7e9b0SAdrian Chadd * Default implementation of BUS_CHILD_PNPINFO_STR(). 7464ad7e9b0SAdrian Chadd */ 7474ad7e9b0SAdrian Chadd static int 7484ad7e9b0SAdrian Chadd bhnd_child_pnpinfo_str(device_t dev, device_t child, char *buf, 7494ad7e9b0SAdrian Chadd size_t buflen) 7504ad7e9b0SAdrian Chadd { 7514ad7e9b0SAdrian Chadd if (device_get_parent(child) != dev) { 7524ad7e9b0SAdrian Chadd return (BUS_CHILD_PNPINFO_STR(device_get_parent(dev), child, 7534ad7e9b0SAdrian Chadd buf, buflen)); 7544ad7e9b0SAdrian Chadd } 7554ad7e9b0SAdrian Chadd 7564ad7e9b0SAdrian Chadd snprintf(buf, buflen, "vendor=0x%hx device=0x%hx rev=0x%hhx", 7574ad7e9b0SAdrian Chadd bhnd_get_vendor(child), bhnd_get_device(child), 7584ad7e9b0SAdrian Chadd bhnd_get_hwrev(child)); 7594ad7e9b0SAdrian Chadd 7604ad7e9b0SAdrian Chadd return (0); 7614ad7e9b0SAdrian Chadd } 7624ad7e9b0SAdrian Chadd 7634ad7e9b0SAdrian Chadd /** 764386fb140SAdrian Chadd * Default implementation of BUS_CHILD_LOCATION_STR(). 7654ad7e9b0SAdrian Chadd */ 7664ad7e9b0SAdrian Chadd static int 7674ad7e9b0SAdrian Chadd bhnd_child_location_str(device_t dev, device_t child, char *buf, 7684ad7e9b0SAdrian Chadd size_t buflen) 7694ad7e9b0SAdrian Chadd { 7704ad7e9b0SAdrian Chadd bhnd_addr_t addr; 7714ad7e9b0SAdrian Chadd bhnd_size_t size; 7724ad7e9b0SAdrian Chadd 7734ad7e9b0SAdrian Chadd if (device_get_parent(child) != dev) { 7744ad7e9b0SAdrian Chadd return (BUS_CHILD_LOCATION_STR(device_get_parent(dev), child, 7754ad7e9b0SAdrian Chadd buf, buflen)); 7764ad7e9b0SAdrian Chadd } 7774ad7e9b0SAdrian Chadd 7784ad7e9b0SAdrian Chadd 7794ad7e9b0SAdrian Chadd if (bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &addr, &size)) { 7804ad7e9b0SAdrian Chadd /* No device default port/region */ 7814ad7e9b0SAdrian Chadd if (buflen > 0) 7824ad7e9b0SAdrian Chadd *buf = '\0'; 7834ad7e9b0SAdrian Chadd return (0); 7844ad7e9b0SAdrian Chadd } 7854ad7e9b0SAdrian Chadd 7864ad7e9b0SAdrian Chadd snprintf(buf, buflen, "port0.0=0x%llx", (unsigned long long) addr); 7874ad7e9b0SAdrian Chadd return (0); 7884ad7e9b0SAdrian Chadd } 7894ad7e9b0SAdrian Chadd 7904ad7e9b0SAdrian Chadd /** 791688fc8c0SLandon J. Fuller * Default bhnd(4) bus driver implementation of BUS_ADD_CHILD(). 792688fc8c0SLandon J. Fuller * 793688fc8c0SLandon J. Fuller * This implementation manages internal bhnd(4) state, and must be called 794688fc8c0SLandon J. Fuller * by subclassing drivers. 795688fc8c0SLandon J. Fuller */ 796688fc8c0SLandon J. Fuller device_t 797688fc8c0SLandon J. Fuller bhnd_generic_add_child(device_t dev, u_int order, const char *name, int unit) 798688fc8c0SLandon J. Fuller { 799688fc8c0SLandon J. Fuller struct bhnd_devinfo *dinfo; 800688fc8c0SLandon J. Fuller device_t child; 801688fc8c0SLandon J. Fuller 802688fc8c0SLandon J. Fuller child = device_add_child_ordered(dev, order, name, unit); 803688fc8c0SLandon J. Fuller if (child == NULL) 804688fc8c0SLandon J. Fuller return (NULL); 805688fc8c0SLandon J. Fuller 806688fc8c0SLandon J. Fuller if ((dinfo = BHND_BUS_ALLOC_DEVINFO(dev)) == NULL) { 807688fc8c0SLandon J. Fuller device_delete_child(dev, child); 808688fc8c0SLandon J. Fuller return (NULL); 809688fc8c0SLandon J. Fuller } 810688fc8c0SLandon J. Fuller 811688fc8c0SLandon J. Fuller device_set_ivars(child, dinfo); 812688fc8c0SLandon J. Fuller 813688fc8c0SLandon J. Fuller /* Inform concrete bus driver. */ 814688fc8c0SLandon J. Fuller BHND_BUS_CHILD_ADDED(dev, child); 815688fc8c0SLandon J. Fuller 816688fc8c0SLandon J. Fuller return (child); 817688fc8c0SLandon J. Fuller } 818688fc8c0SLandon J. Fuller 819688fc8c0SLandon J. Fuller /** 820688fc8c0SLandon J. Fuller * Default bhnd(4) bus driver implementation of BUS_CHILD_DELETED(). 821688fc8c0SLandon J. Fuller * 822688fc8c0SLandon J. Fuller * This implementation manages internal bhnd(4) state, and must be called 823688fc8c0SLandon J. Fuller * by subclassing drivers. 824688fc8c0SLandon J. Fuller */ 825688fc8c0SLandon J. Fuller void 826688fc8c0SLandon J. Fuller bhnd_generic_child_deleted(device_t dev, device_t child) 827688fc8c0SLandon J. Fuller { 828688fc8c0SLandon J. Fuller struct bhnd_softc *sc; 829688fc8c0SLandon J. Fuller struct bhnd_devinfo *dinfo; 830688fc8c0SLandon J. Fuller 831688fc8c0SLandon J. Fuller sc = device_get_softc(dev); 832688fc8c0SLandon J. Fuller 833688fc8c0SLandon J. Fuller /* Free device info */ 834688fc8c0SLandon J. Fuller if ((dinfo = device_get_ivars(child)) != NULL) 835688fc8c0SLandon J. Fuller BHND_BUS_FREE_DEVINFO(dev, dinfo); 836*fdedcd9fSLandon J. Fuller 837*fdedcd9fSLandon J. Fuller /* Clean up platform device references */ 838*fdedcd9fSLandon J. Fuller if (sc->chipc_dev == child) { 839*fdedcd9fSLandon J. Fuller sc->chipc_dev = NULL; 840*fdedcd9fSLandon J. Fuller } else if (sc->nvram_dev == child) { 841*fdedcd9fSLandon J. Fuller sc->nvram_dev = NULL; 842*fdedcd9fSLandon J. Fuller } else if (sc->pmu_dev == child) { 843*fdedcd9fSLandon J. Fuller sc->pmu_dev = NULL; 844*fdedcd9fSLandon J. Fuller } 845688fc8c0SLandon J. Fuller } 846688fc8c0SLandon J. Fuller 847688fc8c0SLandon J. Fuller /** 8484ad7e9b0SAdrian Chadd * Helper function for implementing BUS_SUSPEND_CHILD(). 8494ad7e9b0SAdrian Chadd * 8504ad7e9b0SAdrian Chadd * TODO: Power management 8514ad7e9b0SAdrian Chadd * 8524ad7e9b0SAdrian Chadd * If @p child is not a direct child of @p dev, suspension is delegated to 8534ad7e9b0SAdrian Chadd * the @p dev parent. 8544ad7e9b0SAdrian Chadd */ 8554ad7e9b0SAdrian Chadd int 8564ad7e9b0SAdrian Chadd bhnd_generic_suspend_child(device_t dev, device_t child) 8574ad7e9b0SAdrian Chadd { 8584ad7e9b0SAdrian Chadd if (device_get_parent(child) != dev) 8594ad7e9b0SAdrian Chadd BUS_SUSPEND_CHILD(device_get_parent(dev), child); 8604ad7e9b0SAdrian Chadd 8614ad7e9b0SAdrian Chadd return bus_generic_suspend_child(dev, child); 8624ad7e9b0SAdrian Chadd } 8634ad7e9b0SAdrian Chadd 8644ad7e9b0SAdrian Chadd /** 8654ad7e9b0SAdrian Chadd * Helper function for implementing BUS_RESUME_CHILD(). 8664ad7e9b0SAdrian Chadd * 8674ad7e9b0SAdrian Chadd * TODO: Power management 8684ad7e9b0SAdrian Chadd * 8694ad7e9b0SAdrian Chadd * If @p child is not a direct child of @p dev, suspension is delegated to 8704ad7e9b0SAdrian Chadd * the @p dev parent. 8714ad7e9b0SAdrian Chadd */ 8724ad7e9b0SAdrian Chadd int 8734ad7e9b0SAdrian Chadd bhnd_generic_resume_child(device_t dev, device_t child) 8744ad7e9b0SAdrian Chadd { 8754ad7e9b0SAdrian Chadd if (device_get_parent(child) != dev) 8764ad7e9b0SAdrian Chadd BUS_RESUME_CHILD(device_get_parent(dev), child); 8774ad7e9b0SAdrian Chadd 8784ad7e9b0SAdrian Chadd return bus_generic_resume_child(dev, child); 8794ad7e9b0SAdrian Chadd } 8804ad7e9b0SAdrian Chadd 8814ad7e9b0SAdrian Chadd /* 8824ad7e9b0SAdrian Chadd * Delegate all indirect I/O to the parent device. When inherited by 8834ad7e9b0SAdrian Chadd * non-bridged bus implementations, resources will never be marked as 8840e141e3cSAdrian Chadd * indirect, and these methods will never be called. 8854ad7e9b0SAdrian Chadd */ 886a73ac06dSAdrian Chadd #define BHND_IO_READ(_type, _name, _method) \ 887a73ac06dSAdrian Chadd static _type \ 888a73ac06dSAdrian Chadd bhnd_read_ ## _name (device_t dev, device_t child, \ 889a73ac06dSAdrian Chadd struct bhnd_resource *r, bus_size_t offset) \ 890a73ac06dSAdrian Chadd { \ 891a73ac06dSAdrian Chadd return (BHND_BUS_READ_ ## _method( \ 892a73ac06dSAdrian Chadd device_get_parent(dev), child, r, offset)); \ 8934ad7e9b0SAdrian Chadd } 8944ad7e9b0SAdrian Chadd 895a73ac06dSAdrian Chadd #define BHND_IO_WRITE(_type, _name, _method) \ 896a73ac06dSAdrian Chadd static void \ 897a73ac06dSAdrian Chadd bhnd_write_ ## _name (device_t dev, device_t child, \ 898a73ac06dSAdrian Chadd struct bhnd_resource *r, bus_size_t offset, _type value) \ 899a73ac06dSAdrian Chadd { \ 900a73ac06dSAdrian Chadd return (BHND_BUS_WRITE_ ## _method( \ 901a73ac06dSAdrian Chadd device_get_parent(dev), child, r, offset, \ 902a73ac06dSAdrian Chadd value)); \ 9034ad7e9b0SAdrian Chadd } 9044ad7e9b0SAdrian Chadd 9050e141e3cSAdrian Chadd #define BHND_IO_MISC(_type, _op, _method) \ 906a73ac06dSAdrian Chadd static void \ 9070e141e3cSAdrian Chadd bhnd_ ## _op (device_t dev, device_t child, \ 9080e141e3cSAdrian Chadd struct bhnd_resource *r, bus_size_t offset, _type datap, \ 909a73ac06dSAdrian Chadd bus_size_t count) \ 910a73ac06dSAdrian Chadd { \ 911a73ac06dSAdrian Chadd BHND_BUS_ ## _method(device_get_parent(dev), child, r, \ 912a73ac06dSAdrian Chadd offset, datap, count); \ 9134ad7e9b0SAdrian Chadd } 9144ad7e9b0SAdrian Chadd 915a73ac06dSAdrian Chadd #define BHND_IO_METHODS(_type, _size) \ 916a73ac06dSAdrian Chadd BHND_IO_READ(_type, _size, _size) \ 917a73ac06dSAdrian Chadd BHND_IO_WRITE(_type, _size, _size) \ 918a73ac06dSAdrian Chadd \ 919a73ac06dSAdrian Chadd BHND_IO_READ(_type, stream_ ## _size, STREAM_ ## _size) \ 920a73ac06dSAdrian Chadd BHND_IO_WRITE(_type, stream_ ## _size, STREAM_ ## _size) \ 921a73ac06dSAdrian Chadd \ 9220e141e3cSAdrian Chadd BHND_IO_MISC(_type*, read_multi_ ## _size, \ 9230e141e3cSAdrian Chadd READ_MULTI_ ## _size) \ 9240e141e3cSAdrian Chadd BHND_IO_MISC(_type*, write_multi_ ## _size, \ 9250e141e3cSAdrian Chadd WRITE_MULTI_ ## _size) \ 926a73ac06dSAdrian Chadd \ 9270e141e3cSAdrian Chadd BHND_IO_MISC(_type*, read_multi_stream_ ## _size, \ 928a73ac06dSAdrian Chadd READ_MULTI_STREAM_ ## _size) \ 9290e141e3cSAdrian Chadd BHND_IO_MISC(_type*, write_multi_stream_ ## _size, \ 930a73ac06dSAdrian Chadd WRITE_MULTI_STREAM_ ## _size) \ 9310e141e3cSAdrian Chadd \ 9320e141e3cSAdrian Chadd BHND_IO_MISC(_type, set_multi_ ## _size, SET_MULTI_ ## _size) \ 9330e141e3cSAdrian Chadd BHND_IO_MISC(_type, set_region_ ## _size, SET_REGION_ ## _size) \ 9340e141e3cSAdrian Chadd \ 9350e141e3cSAdrian Chadd BHND_IO_MISC(_type*, read_region_ ## _size, \ 9360e141e3cSAdrian Chadd READ_REGION_ ## _size) \ 9370e141e3cSAdrian Chadd BHND_IO_MISC(_type*, write_region_ ## _size, \ 9380e141e3cSAdrian Chadd WRITE_REGION_ ## _size) \ 9390e141e3cSAdrian Chadd \ 9400e141e3cSAdrian Chadd BHND_IO_MISC(_type*, read_region_stream_ ## _size, \ 9410e141e3cSAdrian Chadd READ_REGION_STREAM_ ## _size) \ 9420e141e3cSAdrian Chadd BHND_IO_MISC(_type*, write_region_stream_ ## _size, \ 9430e141e3cSAdrian Chadd WRITE_REGION_STREAM_ ## _size) \ 9444ad7e9b0SAdrian Chadd 945a73ac06dSAdrian Chadd BHND_IO_METHODS(uint8_t, 1); 946a73ac06dSAdrian Chadd BHND_IO_METHODS(uint16_t, 2); 947a73ac06dSAdrian Chadd BHND_IO_METHODS(uint32_t, 4); 9484ad7e9b0SAdrian Chadd 9494ad7e9b0SAdrian Chadd static void 9504ad7e9b0SAdrian Chadd bhnd_barrier(device_t dev, device_t child, struct bhnd_resource *r, 9514ad7e9b0SAdrian Chadd bus_size_t offset, bus_size_t length, int flags) 9524ad7e9b0SAdrian Chadd { 9534ad7e9b0SAdrian Chadd BHND_BUS_BARRIER(device_get_parent(dev), child, r, offset, length, 9544ad7e9b0SAdrian Chadd flags); 9554ad7e9b0SAdrian Chadd } 9564ad7e9b0SAdrian Chadd 9574ad7e9b0SAdrian Chadd static device_method_t bhnd_methods[] = { 9584ad7e9b0SAdrian Chadd /* Device interface */ \ 9594ad7e9b0SAdrian Chadd DEVMETHOD(device_attach, bhnd_generic_attach), 9604ad7e9b0SAdrian Chadd DEVMETHOD(device_detach, bhnd_generic_detach), 9614ad7e9b0SAdrian Chadd DEVMETHOD(device_shutdown, bhnd_generic_shutdown), 9624ad7e9b0SAdrian Chadd DEVMETHOD(device_suspend, bhnd_generic_suspend), 9634ad7e9b0SAdrian Chadd DEVMETHOD(device_resume, bhnd_generic_resume), 9644ad7e9b0SAdrian Chadd 9654ad7e9b0SAdrian Chadd /* Bus interface */ 966*fdedcd9fSLandon J. Fuller DEVMETHOD(bus_new_pass, bhnd_new_pass), 967688fc8c0SLandon J. Fuller DEVMETHOD(bus_add_child, bhnd_generic_add_child), 968688fc8c0SLandon J. Fuller DEVMETHOD(bus_child_deleted, bhnd_generic_child_deleted), 9694ad7e9b0SAdrian Chadd DEVMETHOD(bus_probe_nomatch, bhnd_generic_probe_nomatch), 9704ad7e9b0SAdrian Chadd DEVMETHOD(bus_print_child, bhnd_generic_print_child), 9714ad7e9b0SAdrian Chadd DEVMETHOD(bus_child_pnpinfo_str, bhnd_child_pnpinfo_str), 9724ad7e9b0SAdrian Chadd DEVMETHOD(bus_child_location_str, bhnd_child_location_str), 9734ad7e9b0SAdrian Chadd 9744ad7e9b0SAdrian Chadd DEVMETHOD(bus_suspend_child, bhnd_generic_suspend_child), 9754ad7e9b0SAdrian Chadd DEVMETHOD(bus_resume_child, bhnd_generic_resume_child), 9764ad7e9b0SAdrian Chadd 9774ad7e9b0SAdrian Chadd DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), 9784ad7e9b0SAdrian Chadd DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 9794ad7e9b0SAdrian Chadd DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource), 9804ad7e9b0SAdrian Chadd DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource), 9814ad7e9b0SAdrian Chadd DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), 9824ad7e9b0SAdrian Chadd DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), 9834ad7e9b0SAdrian Chadd DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 9844ad7e9b0SAdrian Chadd DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 9854ad7e9b0SAdrian Chadd 9864ad7e9b0SAdrian Chadd DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 9874ad7e9b0SAdrian Chadd DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 9884ad7e9b0SAdrian Chadd DEVMETHOD(bus_config_intr, bus_generic_config_intr), 9894ad7e9b0SAdrian Chadd DEVMETHOD(bus_bind_intr, bus_generic_bind_intr), 9904ad7e9b0SAdrian Chadd DEVMETHOD(bus_describe_intr, bus_generic_describe_intr), 9914ad7e9b0SAdrian Chadd 9924ad7e9b0SAdrian Chadd DEVMETHOD(bus_get_dma_tag, bus_generic_get_dma_tag), 9934ad7e9b0SAdrian Chadd 9944ad7e9b0SAdrian Chadd /* BHND interface */ 995386fb140SAdrian Chadd DEVMETHOD(bhnd_bus_get_chipid, bhnd_bus_generic_get_chipid), 9964ad7e9b0SAdrian Chadd DEVMETHOD(bhnd_bus_get_probe_order, bhnd_generic_get_probe_order), 997386fb140SAdrian Chadd DEVMETHOD(bhnd_bus_is_region_valid, bhnd_generic_is_region_valid), 998386fb140SAdrian Chadd DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_bus_generic_is_hw_disabled), 999*fdedcd9fSLandon J. Fuller DEVMETHOD(bhnd_bus_get_nvram_var, bhnd_generic_get_nvram_var), 10000e141e3cSAdrian Chadd 10010e141e3cSAdrian Chadd /* BHND interface (bus I/O) */ 10024ad7e9b0SAdrian Chadd DEVMETHOD(bhnd_bus_read_1, bhnd_read_1), 10034ad7e9b0SAdrian Chadd DEVMETHOD(bhnd_bus_read_2, bhnd_read_2), 10044ad7e9b0SAdrian Chadd DEVMETHOD(bhnd_bus_read_4, bhnd_read_4), 10054ad7e9b0SAdrian Chadd DEVMETHOD(bhnd_bus_write_1, bhnd_write_1), 10064ad7e9b0SAdrian Chadd DEVMETHOD(bhnd_bus_write_2, bhnd_write_2), 10074ad7e9b0SAdrian Chadd DEVMETHOD(bhnd_bus_write_4, bhnd_write_4), 10080e141e3cSAdrian Chadd 1009a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_stream_1, bhnd_read_stream_1), 1010a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_stream_2, bhnd_read_stream_2), 1011a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_stream_4, bhnd_read_stream_4), 1012a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_stream_1, bhnd_write_stream_1), 1013a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_stream_2, bhnd_write_stream_2), 1014a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_stream_4, bhnd_write_stream_4), 1015a73ac06dSAdrian Chadd 1016a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_multi_1, bhnd_read_multi_1), 1017a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_multi_2, bhnd_read_multi_2), 1018a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_multi_4, bhnd_read_multi_4), 1019a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_multi_1, bhnd_write_multi_1), 1020a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_multi_2, bhnd_write_multi_2), 1021a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_multi_4, bhnd_write_multi_4), 1022a73ac06dSAdrian Chadd 1023a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_multi_stream_1, bhnd_read_multi_stream_1), 1024a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_multi_stream_2, bhnd_read_multi_stream_2), 1025a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_multi_stream_4, bhnd_read_multi_stream_4), 1026a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_multi_stream_1,bhnd_write_multi_stream_1), 1027a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_multi_stream_2,bhnd_write_multi_stream_2), 1028a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_multi_stream_4,bhnd_write_multi_stream_4), 1029a73ac06dSAdrian Chadd 10300e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_set_multi_1, bhnd_set_multi_1), 10310e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_set_multi_2, bhnd_set_multi_2), 10320e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_set_multi_4, bhnd_set_multi_4), 10330e141e3cSAdrian Chadd 10340e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_set_region_1, bhnd_set_region_1), 10350e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_set_region_2, bhnd_set_region_2), 10360e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_set_region_4, bhnd_set_region_4), 10370e141e3cSAdrian Chadd 10380e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_read_region_1, bhnd_read_region_1), 10390e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_read_region_2, bhnd_read_region_2), 10400e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_read_region_4, bhnd_read_region_4), 10410e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_write_region_1, bhnd_write_region_1), 10420e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_write_region_2, bhnd_write_region_2), 10430e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_write_region_4, bhnd_write_region_4), 10440e141e3cSAdrian Chadd 10450e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_read_region_stream_1,bhnd_read_region_stream_1), 10460e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_read_region_stream_2,bhnd_read_region_stream_2), 10470e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_read_region_stream_4,bhnd_read_region_stream_4), 10480e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_write_region_stream_1, bhnd_write_region_stream_1), 10490e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_write_region_stream_2, bhnd_write_region_stream_2), 10500e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_write_region_stream_4, bhnd_write_region_stream_4), 10510e141e3cSAdrian Chadd 10524ad7e9b0SAdrian Chadd DEVMETHOD(bhnd_bus_barrier, bhnd_barrier), 10534ad7e9b0SAdrian Chadd 10544ad7e9b0SAdrian Chadd DEVMETHOD_END 10554ad7e9b0SAdrian Chadd }; 10564ad7e9b0SAdrian Chadd 10574ad7e9b0SAdrian Chadd devclass_t bhnd_devclass; /**< bhnd bus. */ 10584ad7e9b0SAdrian Chadd devclass_t bhnd_hostb_devclass; /**< bhnd bus host bridge. */ 10594ad7e9b0SAdrian Chadd devclass_t bhnd_nvram_devclass; /**< bhnd NVRAM device */ 10604ad7e9b0SAdrian Chadd 10614ad7e9b0SAdrian Chadd DEFINE_CLASS_0(bhnd, bhnd_driver, bhnd_methods, sizeof(struct bhnd_softc)); 10624ad7e9b0SAdrian Chadd MODULE_VERSION(bhnd, 1); 1063