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 61fdedcd9fSLandon J. Fuller #include <dev/bhnd/cores/chipc/chipcvar.h> 62fdedcd9fSLandon J. Fuller 63fdedcd9fSLandon J. Fuller #include "bhnd_chipc_if.h" 64fdedcd9fSLandon J. Fuller #include "bhnd_nvram_if.h" 65fdedcd9fSLandon 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 71fdedcd9fSLandon J. Fuller /* Bus pass at which all bus-required children must be available, and 72fdedcd9fSLandon J. Fuller * attachment may be finalized. */ 73fdedcd9fSLandon J. Fuller #define BHND_FINISH_ATTACH_PASS BUS_PASS_DEFAULT 74fdedcd9fSLandon 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 92fdedcd9fSLandon J. Fuller 93fdedcd9fSLandon J. Fuller static int bhnd_delete_children(struct bhnd_softc *sc); 94fdedcd9fSLandon J. Fuller 95fdedcd9fSLandon J. Fuller static int bhnd_finish_attach(struct bhnd_softc *sc); 96fdedcd9fSLandon J. Fuller 97fdedcd9fSLandon J. Fuller static device_t bhnd_find_chipc(struct bhnd_softc *sc); 98fdedcd9fSLandon J. Fuller static struct chipc_caps *bhnd_find_chipc_caps(struct bhnd_softc *sc); 99fdedcd9fSLandon J. Fuller static device_t bhnd_find_platform_dev(struct bhnd_softc *sc, 100fdedcd9fSLandon J. Fuller const char *classname); 101fdedcd9fSLandon J. Fuller static device_t bhnd_find_pmu(struct bhnd_softc *sc); 102fdedcd9fSLandon J. Fuller static device_t bhnd_find_nvram(struct bhnd_softc *sc); 103fdedcd9fSLandon 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 { 118fdedcd9fSLandon 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 126fdedcd9fSLandon J. Fuller sc = device_get_softc(dev); 127fdedcd9fSLandon J. Fuller sc->dev = dev; 128fdedcd9fSLandon J. Fuller 1294ad7e9b0SAdrian Chadd if ((error = device_get_children(dev, &devs, &ndevs))) 1304ad7e9b0SAdrian Chadd return (error); 1314ad7e9b0SAdrian Chadd 132fdedcd9fSLandon 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 139fdedcd9fSLandon J. Fuller /* Try to finalize attachment */ 140fdedcd9fSLandon J. Fuller if (bus_current_pass >= BHND_FINISH_ATTACH_PASS) { 141fdedcd9fSLandon J. Fuller if ((error = bhnd_finish_attach(sc))) 142fdedcd9fSLandon J. Fuller goto cleanup; 143fdedcd9fSLandon J. Fuller } 144fdedcd9fSLandon J. Fuller 145fdedcd9fSLandon J. Fuller cleanup: 1464ad7e9b0SAdrian Chadd free(devs, M_TEMP); 147fdedcd9fSLandon J. Fuller 148fdedcd9fSLandon J. Fuller if (error) 149fdedcd9fSLandon J. Fuller bhnd_delete_children(sc); 150fdedcd9fSLandon J. Fuller 151fdedcd9fSLandon J. Fuller return (error); 152fdedcd9fSLandon J. Fuller } 153fdedcd9fSLandon J. Fuller 154fdedcd9fSLandon J. Fuller /** 155fdedcd9fSLandon J. Fuller * Detach and delete all children, in reverse of their attach order. 156fdedcd9fSLandon J. Fuller */ 157fdedcd9fSLandon J. Fuller static int 158fdedcd9fSLandon J. Fuller bhnd_delete_children(struct bhnd_softc *sc) 159fdedcd9fSLandon J. Fuller { 160fdedcd9fSLandon J. Fuller device_t *devs; 161fdedcd9fSLandon J. Fuller int ndevs; 162fdedcd9fSLandon J. Fuller int error; 163fdedcd9fSLandon J. Fuller 164fdedcd9fSLandon J. Fuller if ((error = device_get_children(sc->dev, &devs, &ndevs))) 165fdedcd9fSLandon J. Fuller return (error); 166fdedcd9fSLandon J. Fuller 167fdedcd9fSLandon J. Fuller /* Detach in the reverse of attach order */ 168fdedcd9fSLandon J. Fuller qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order); 169fdedcd9fSLandon J. Fuller for (int i = 0; i < ndevs; i++) { 170fdedcd9fSLandon J. Fuller device_t child = devs[i]; 171fdedcd9fSLandon J. Fuller 172fdedcd9fSLandon J. Fuller /* Terminate on first error */ 173fdedcd9fSLandon J. Fuller if ((error = device_delete_child(sc->dev, child))) 174fdedcd9fSLandon J. Fuller goto cleanup; 175fdedcd9fSLandon J. Fuller } 176fdedcd9fSLandon J. Fuller 177fdedcd9fSLandon J. Fuller cleanup: 178fdedcd9fSLandon J. Fuller free(devs, M_TEMP); 179fdedcd9fSLandon 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 { 192fdedcd9fSLandon J. Fuller struct bhnd_softc *sc; 1934ad7e9b0SAdrian Chadd 1944ad7e9b0SAdrian Chadd if (!device_is_attached(dev)) 1954ad7e9b0SAdrian Chadd return (EBUSY); 1964ad7e9b0SAdrian Chadd 197fdedcd9fSLandon J. Fuller sc = device_get_softc(dev); 198fdedcd9fSLandon 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 314fdedcd9fSLandon J. Fuller static void 315fdedcd9fSLandon J. Fuller bhnd_new_pass(device_t dev) 316fdedcd9fSLandon J. Fuller { 317fdedcd9fSLandon J. Fuller struct bhnd_softc *sc; 318fdedcd9fSLandon J. Fuller int error; 319fdedcd9fSLandon J. Fuller 320fdedcd9fSLandon J. Fuller sc = device_get_softc(dev); 321fdedcd9fSLandon J. Fuller 322fdedcd9fSLandon J. Fuller /* Attach any permissible children */ 323fdedcd9fSLandon J. Fuller bus_generic_new_pass(dev); 324fdedcd9fSLandon J. Fuller 325fdedcd9fSLandon J. Fuller /* Finalize attachment */ 326fdedcd9fSLandon J. Fuller if (!sc->attach_done && bus_current_pass >= BHND_FINISH_ATTACH_PASS) { 327fdedcd9fSLandon J. Fuller if ((error = bhnd_finish_attach(sc))) { 328fdedcd9fSLandon J. Fuller panic("bhnd_finish_attach() failed: %d", error); 329fdedcd9fSLandon J. Fuller } 330fdedcd9fSLandon J. Fuller } 331fdedcd9fSLandon J. Fuller } 332fdedcd9fSLandon J. Fuller 333fdedcd9fSLandon J. Fuller /* 334fdedcd9fSLandon J. Fuller * Finish any pending bus attachment operations. 335fdedcd9fSLandon J. Fuller * 336fdedcd9fSLandon J. Fuller * When attached as a SoC bus (as opposed to a bridged WiFi device), our 337fdedcd9fSLandon J. Fuller * platform devices may not be attached until later bus passes, necessitating 338fdedcd9fSLandon J. Fuller * delayed initialization on our part. 339fdedcd9fSLandon J. Fuller */ 340fdedcd9fSLandon J. Fuller static int 341fdedcd9fSLandon J. Fuller bhnd_finish_attach(struct bhnd_softc *sc) 342fdedcd9fSLandon J. Fuller { 343fdedcd9fSLandon J. Fuller struct chipc_caps *ccaps; 344fdedcd9fSLandon J. Fuller 345fdedcd9fSLandon J. Fuller GIANT_REQUIRED; /* newbus */ 346fdedcd9fSLandon J. Fuller 347fdedcd9fSLandon J. Fuller KASSERT(bus_current_pass >= BHND_FINISH_ATTACH_PASS, 348fdedcd9fSLandon J. Fuller ("bhnd_finish_attach() called in pass %d", bus_current_pass)); 349fdedcd9fSLandon J. Fuller 350fdedcd9fSLandon J. Fuller KASSERT(!sc->attach_done, ("duplicate call to bhnd_finish_attach()")); 351fdedcd9fSLandon J. Fuller 352fdedcd9fSLandon J. Fuller /* Locate chipc device */ 353fdedcd9fSLandon J. Fuller if ((sc->chipc_dev = bhnd_find_chipc(sc)) == NULL) { 354fdedcd9fSLandon J. Fuller device_printf(sc->dev, "error: ChipCommon device not found\n"); 355fdedcd9fSLandon J. Fuller return (ENXIO); 356fdedcd9fSLandon J. Fuller } 357fdedcd9fSLandon J. Fuller 358fdedcd9fSLandon J. Fuller ccaps = BHND_CHIPC_GET_CAPS(sc->chipc_dev); 359fdedcd9fSLandon J. Fuller 360fdedcd9fSLandon J. Fuller /* Look for NVRAM device */ 361fdedcd9fSLandon J. Fuller if (ccaps->nvram_src != BHND_NVRAM_SRC_UNKNOWN) { 362fdedcd9fSLandon J. Fuller if ((sc->nvram_dev = bhnd_find_nvram(sc)) == NULL) { 363fdedcd9fSLandon J. Fuller device_printf(sc->dev, 364*1728aef2SLandon J. Fuller "warning: NVRAM %s device not found\n", 365fdedcd9fSLandon J. Fuller bhnd_nvram_src_name(ccaps->nvram_src)); 366fdedcd9fSLandon J. Fuller } 367fdedcd9fSLandon J. Fuller } 368fdedcd9fSLandon J. Fuller 369fdedcd9fSLandon J. Fuller /* Look for a PMU */ 370fdedcd9fSLandon J. Fuller if (ccaps->pmu) { 371fdedcd9fSLandon J. Fuller if ((sc->pmu_dev = bhnd_find_pmu(sc)) == NULL) { 372fdedcd9fSLandon J. Fuller device_printf(sc->dev, 373fdedcd9fSLandon J. Fuller "warning: PMU device not found\n"); 374fdedcd9fSLandon J. Fuller } 375fdedcd9fSLandon J. Fuller } 376fdedcd9fSLandon J. Fuller 377fdedcd9fSLandon J. Fuller /* Mark attach as completed */ 378fdedcd9fSLandon J. Fuller sc->attach_done = true; 379fdedcd9fSLandon J. Fuller 380fdedcd9fSLandon J. Fuller return (0); 381fdedcd9fSLandon J. Fuller } 382fdedcd9fSLandon J. Fuller 383fdedcd9fSLandon J. Fuller /* Locate the ChipCommon core. */ 384fdedcd9fSLandon J. Fuller static device_t 385fdedcd9fSLandon J. Fuller bhnd_find_chipc(struct bhnd_softc *sc) 386fdedcd9fSLandon J. Fuller { 387fdedcd9fSLandon J. Fuller device_t chipc; 388fdedcd9fSLandon J. Fuller 389fdedcd9fSLandon J. Fuller /* Make sure we're holding Giant for newbus */ 390fdedcd9fSLandon J. Fuller GIANT_REQUIRED; 391fdedcd9fSLandon J. Fuller 392fdedcd9fSLandon J. Fuller /* chipc_dev is initialized during attachment */ 393fdedcd9fSLandon J. Fuller if (sc->attach_done) { 394fdedcd9fSLandon J. Fuller if ((chipc = sc->chipc_dev) == NULL) 395fdedcd9fSLandon J. Fuller return (NULL); 396fdedcd9fSLandon J. Fuller 397fdedcd9fSLandon J. Fuller goto found; 398fdedcd9fSLandon J. Fuller } 399fdedcd9fSLandon J. Fuller 400fdedcd9fSLandon J. Fuller /* Locate chipc core with a core unit of 0 */ 401fdedcd9fSLandon J. Fuller chipc = bhnd_find_child(sc->dev, BHND_DEVCLASS_CC, 0); 402fdedcd9fSLandon J. Fuller if (chipc == NULL) 403fdedcd9fSLandon J. Fuller return (NULL); 404fdedcd9fSLandon J. Fuller 405fdedcd9fSLandon J. Fuller found: 406fdedcd9fSLandon J. Fuller if (device_get_state(chipc) < DS_ATTACHING) { 407fdedcd9fSLandon J. Fuller device_printf(sc->dev, "chipc found, but did not attach\n"); 408fdedcd9fSLandon J. Fuller return (NULL); 409fdedcd9fSLandon J. Fuller } 410fdedcd9fSLandon J. Fuller 411fdedcd9fSLandon J. Fuller return (chipc); 412fdedcd9fSLandon J. Fuller } 413fdedcd9fSLandon J. Fuller 414fdedcd9fSLandon J. Fuller /* Locate the ChipCommon core and return the device capabilities */ 415fdedcd9fSLandon J. Fuller static struct chipc_caps * 416fdedcd9fSLandon J. Fuller bhnd_find_chipc_caps(struct bhnd_softc *sc) 417fdedcd9fSLandon J. Fuller { 418fdedcd9fSLandon J. Fuller device_t chipc; 419fdedcd9fSLandon J. Fuller 420fdedcd9fSLandon J. Fuller if ((chipc = bhnd_find_chipc(sc)) == NULL) { 421fdedcd9fSLandon J. Fuller device_printf(sc->dev, 422fdedcd9fSLandon J. Fuller "chipc unavailable; cannot fetch capabilities\n"); 423fdedcd9fSLandon J. Fuller return (NULL); 424fdedcd9fSLandon J. Fuller } 425fdedcd9fSLandon J. Fuller 426fdedcd9fSLandon J. Fuller return (BHND_CHIPC_GET_CAPS(chipc)); 427fdedcd9fSLandon J. Fuller } 428fdedcd9fSLandon J. Fuller 429fdedcd9fSLandon J. Fuller /** 430fdedcd9fSLandon J. Fuller * Find an attached platform device on @p dev, searching first for cores 431fdedcd9fSLandon J. Fuller * matching @p classname, and if not found, searching the children of the first 432fdedcd9fSLandon J. Fuller * bhnd_chipc device on the bus. 433fdedcd9fSLandon J. Fuller * 434fdedcd9fSLandon J. Fuller * @param sc Driver state. 435fdedcd9fSLandon J. Fuller * @param chipc Attached ChipCommon device. 436fdedcd9fSLandon J. Fuller * @param classname Device class to search for. 437fdedcd9fSLandon J. Fuller * 438fdedcd9fSLandon J. Fuller * @retval device_t A matching device. 439fdedcd9fSLandon J. Fuller * @retval NULL If no matching device is found. 440fdedcd9fSLandon J. Fuller */ 441fdedcd9fSLandon J. Fuller static device_t 442fdedcd9fSLandon J. Fuller bhnd_find_platform_dev(struct bhnd_softc *sc, const char *classname) 443fdedcd9fSLandon J. Fuller { 444fdedcd9fSLandon J. Fuller device_t chipc, child; 445fdedcd9fSLandon J. Fuller 446fdedcd9fSLandon J. Fuller /* Make sure we're holding Giant for newbus */ 447fdedcd9fSLandon J. Fuller GIANT_REQUIRED; 448fdedcd9fSLandon J. Fuller 449fdedcd9fSLandon J. Fuller /* Look for a directly-attached child */ 450fdedcd9fSLandon J. Fuller child = device_find_child(sc->dev, classname, -1); 451fdedcd9fSLandon J. Fuller if (child != NULL) 452fdedcd9fSLandon J. Fuller goto found; 453fdedcd9fSLandon J. Fuller 454fdedcd9fSLandon J. Fuller /* Look for the first matching ChipCommon child */ 455fdedcd9fSLandon J. Fuller if ((chipc = bhnd_find_chipc(sc)) == NULL) { 456fdedcd9fSLandon J. Fuller device_printf(sc->dev, 457fdedcd9fSLandon J. Fuller "chipc unavailable; cannot locate %s\n", classname); 458fdedcd9fSLandon J. Fuller return (NULL); 459fdedcd9fSLandon J. Fuller } 460fdedcd9fSLandon J. Fuller 461fdedcd9fSLandon J. Fuller child = device_find_child(chipc, classname, -1); 462*1728aef2SLandon J. Fuller if (child != NULL) 463*1728aef2SLandon J. Fuller goto found; 464*1728aef2SLandon J. Fuller 465*1728aef2SLandon J. Fuller /* Look for a parent-attached device (e.g. nexus0 -> bhnd_nvram) */ 466*1728aef2SLandon J. Fuller child = device_find_child(device_get_parent(sc->dev), classname, -1); 467fdedcd9fSLandon J. Fuller if (child == NULL) 468fdedcd9fSLandon J. Fuller return (NULL); 469fdedcd9fSLandon J. Fuller 470fdedcd9fSLandon J. Fuller found: 471fdedcd9fSLandon J. Fuller if (device_get_state(child) < DS_ATTACHING) 472fdedcd9fSLandon J. Fuller return (NULL); 473fdedcd9fSLandon J. Fuller 474fdedcd9fSLandon J. Fuller return (child); 475fdedcd9fSLandon J. Fuller } 476fdedcd9fSLandon J. Fuller 477fdedcd9fSLandon J. Fuller /* Locate the PMU device, if any */ 478fdedcd9fSLandon J. Fuller static device_t 479fdedcd9fSLandon J. Fuller bhnd_find_pmu(struct bhnd_softc *sc) 480fdedcd9fSLandon J. Fuller { 481fdedcd9fSLandon J. Fuller struct chipc_caps *ccaps; 482fdedcd9fSLandon J. Fuller 483fdedcd9fSLandon J. Fuller /* Make sure we're holding Giant for newbus */ 484fdedcd9fSLandon J. Fuller GIANT_REQUIRED; 485fdedcd9fSLandon J. Fuller 486fdedcd9fSLandon J. Fuller /* pmu_dev is initialized during attachment */ 487fdedcd9fSLandon J. Fuller if (sc->attach_done) { 488fdedcd9fSLandon J. Fuller if (sc->pmu_dev == NULL) 489fdedcd9fSLandon J. Fuller return (NULL); 490fdedcd9fSLandon J. Fuller 491fdedcd9fSLandon J. Fuller if (device_get_state(sc->pmu_dev) < DS_ATTACHING) 492fdedcd9fSLandon J. Fuller return (NULL); 493fdedcd9fSLandon J. Fuller 494fdedcd9fSLandon J. Fuller return (sc->pmu_dev); 495fdedcd9fSLandon J. Fuller } 496fdedcd9fSLandon J. Fuller 497fdedcd9fSLandon J. Fuller if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL) 498fdedcd9fSLandon J. Fuller return (NULL); 499fdedcd9fSLandon J. Fuller 500fdedcd9fSLandon J. Fuller if (!ccaps->pmu) 501fdedcd9fSLandon J. Fuller return (NULL); 502fdedcd9fSLandon J. Fuller 503fdedcd9fSLandon J. Fuller return (bhnd_find_platform_dev(sc, "bhnd_pmu")); 504fdedcd9fSLandon J. Fuller } 505fdedcd9fSLandon J. Fuller 506fdedcd9fSLandon J. Fuller /* Locate the NVRAM device, if any */ 507fdedcd9fSLandon J. Fuller static device_t 508fdedcd9fSLandon J. Fuller bhnd_find_nvram(struct bhnd_softc *sc) 509fdedcd9fSLandon J. Fuller { 510fdedcd9fSLandon J. Fuller struct chipc_caps *ccaps; 511fdedcd9fSLandon J. Fuller 512fdedcd9fSLandon J. Fuller /* Make sure we're holding Giant for newbus */ 513fdedcd9fSLandon J. Fuller GIANT_REQUIRED; 514fdedcd9fSLandon J. Fuller 515fdedcd9fSLandon J. Fuller 516fdedcd9fSLandon J. Fuller /* nvram_dev is initialized during attachment */ 517fdedcd9fSLandon J. Fuller if (sc->attach_done) { 518fdedcd9fSLandon J. Fuller if (sc->nvram_dev == NULL) 519fdedcd9fSLandon J. Fuller return (NULL); 520fdedcd9fSLandon J. Fuller 521fdedcd9fSLandon J. Fuller if (device_get_state(sc->nvram_dev) < DS_ATTACHING) 522fdedcd9fSLandon J. Fuller return (NULL); 523fdedcd9fSLandon J. Fuller 524fdedcd9fSLandon J. Fuller return (sc->nvram_dev); 525fdedcd9fSLandon J. Fuller } 526fdedcd9fSLandon J. Fuller 527fdedcd9fSLandon J. Fuller if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL) 528fdedcd9fSLandon J. Fuller return (NULL); 529fdedcd9fSLandon J. Fuller 530fdedcd9fSLandon J. Fuller if (ccaps->nvram_src == BHND_NVRAM_SRC_UNKNOWN) 531fdedcd9fSLandon J. Fuller return (NULL); 532fdedcd9fSLandon J. Fuller 533fdedcd9fSLandon J. Fuller return (bhnd_find_platform_dev(sc, "bhnd_nvram")); 534fdedcd9fSLandon J. Fuller } 535fdedcd9fSLandon J. Fuller 5364ad7e9b0SAdrian Chadd /* 5374ad7e9b0SAdrian Chadd * Ascending comparison of bhnd device's probe order. 5384ad7e9b0SAdrian Chadd */ 5394ad7e9b0SAdrian Chadd static int 5404ad7e9b0SAdrian Chadd compare_ascending_probe_order(const void *lhs, const void *rhs) 5414ad7e9b0SAdrian Chadd { 5424ad7e9b0SAdrian Chadd device_t ldev, rdev; 5434ad7e9b0SAdrian Chadd int lorder, rorder; 5444ad7e9b0SAdrian Chadd 5454ad7e9b0SAdrian Chadd ldev = (*(const device_t *) lhs); 5464ad7e9b0SAdrian Chadd rdev = (*(const device_t *) rhs); 5474ad7e9b0SAdrian Chadd 5484ad7e9b0SAdrian Chadd lorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(ldev), ldev); 5494ad7e9b0SAdrian Chadd rorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(rdev), rdev); 5504ad7e9b0SAdrian Chadd 5514ad7e9b0SAdrian Chadd if (lorder < rorder) { 5524ad7e9b0SAdrian Chadd return (-1); 5534ad7e9b0SAdrian Chadd } else if (lorder > rorder) { 5544ad7e9b0SAdrian Chadd return (1); 5554ad7e9b0SAdrian Chadd } else { 5564ad7e9b0SAdrian Chadd return (0); 5574ad7e9b0SAdrian Chadd } 5584ad7e9b0SAdrian Chadd } 5594ad7e9b0SAdrian Chadd 5604ad7e9b0SAdrian Chadd /* 5614ad7e9b0SAdrian Chadd * Descending comparison of bhnd device's probe order. 5624ad7e9b0SAdrian Chadd */ 5634ad7e9b0SAdrian Chadd static int 5644ad7e9b0SAdrian Chadd compare_descending_probe_order(const void *lhs, const void *rhs) 5654ad7e9b0SAdrian Chadd { 5664ad7e9b0SAdrian Chadd return (compare_ascending_probe_order(rhs, lhs)); 5674ad7e9b0SAdrian Chadd } 5684ad7e9b0SAdrian Chadd 5694ad7e9b0SAdrian Chadd /** 570386fb140SAdrian Chadd * Default bhnd(4) bus driver implementation of BHND_BUS_GET_PROBE_ORDER(). 5714ad7e9b0SAdrian Chadd * 5724ad7e9b0SAdrian Chadd * This implementation determines probe ordering based on the device's class 5734ad7e9b0SAdrian Chadd * and other properties, including whether the device is serving as a host 5744ad7e9b0SAdrian Chadd * bridge. 5754ad7e9b0SAdrian Chadd */ 5764ad7e9b0SAdrian Chadd int 5774ad7e9b0SAdrian Chadd bhnd_generic_get_probe_order(device_t dev, device_t child) 5784ad7e9b0SAdrian Chadd { 5794ad7e9b0SAdrian Chadd switch (bhnd_get_class(child)) { 5804ad7e9b0SAdrian Chadd case BHND_DEVCLASS_CC: 581d567592bSAdrian Chadd /* Must be early enough to provide NVRAM access to the 582d567592bSAdrian Chadd * host bridge */ 583d567592bSAdrian Chadd return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_FIRST); 5844ad7e9b0SAdrian Chadd 5854ad7e9b0SAdrian Chadd case BHND_DEVCLASS_CC_B: 5864ad7e9b0SAdrian Chadd /* fall through */ 5874ad7e9b0SAdrian Chadd case BHND_DEVCLASS_PMU: 5884ad7e9b0SAdrian Chadd return (BHND_PROBE_BUS + BHND_PROBE_ORDER_EARLY); 5894ad7e9b0SAdrian Chadd 5904ad7e9b0SAdrian Chadd case BHND_DEVCLASS_SOC_ROUTER: 5914ad7e9b0SAdrian Chadd return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LATE); 5924ad7e9b0SAdrian Chadd 5934ad7e9b0SAdrian Chadd case BHND_DEVCLASS_SOC_BRIDGE: 5944ad7e9b0SAdrian Chadd return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LAST); 5954ad7e9b0SAdrian Chadd 5964ad7e9b0SAdrian Chadd case BHND_DEVCLASS_CPU: 5974ad7e9b0SAdrian Chadd return (BHND_PROBE_CPU + BHND_PROBE_ORDER_FIRST); 5984ad7e9b0SAdrian Chadd 5994ad7e9b0SAdrian Chadd case BHND_DEVCLASS_RAM: 6004ad7e9b0SAdrian Chadd /* fall through */ 6014ad7e9b0SAdrian Chadd case BHND_DEVCLASS_MEMC: 6024ad7e9b0SAdrian Chadd return (BHND_PROBE_CPU + BHND_PROBE_ORDER_EARLY); 6034ad7e9b0SAdrian Chadd 6044ad7e9b0SAdrian Chadd case BHND_DEVCLASS_NVRAM: 6054ad7e9b0SAdrian Chadd return (BHND_PROBE_RESOURCE + BHND_PROBE_ORDER_EARLY); 6064ad7e9b0SAdrian Chadd 6074ad7e9b0SAdrian Chadd case BHND_DEVCLASS_PCI: 6084ad7e9b0SAdrian Chadd case BHND_DEVCLASS_PCIE: 6094ad7e9b0SAdrian Chadd case BHND_DEVCLASS_PCCARD: 6104ad7e9b0SAdrian Chadd case BHND_DEVCLASS_ENET: 6114ad7e9b0SAdrian Chadd case BHND_DEVCLASS_ENET_MAC: 6124ad7e9b0SAdrian Chadd case BHND_DEVCLASS_ENET_PHY: 6134ad7e9b0SAdrian Chadd case BHND_DEVCLASS_WLAN: 6144ad7e9b0SAdrian Chadd case BHND_DEVCLASS_WLAN_MAC: 6154ad7e9b0SAdrian Chadd case BHND_DEVCLASS_WLAN_PHY: 6164ad7e9b0SAdrian Chadd case BHND_DEVCLASS_EROM: 6174ad7e9b0SAdrian Chadd case BHND_DEVCLASS_OTHER: 6184ad7e9b0SAdrian Chadd case BHND_DEVCLASS_INVALID: 619d9352570SAdrian Chadd if (bhnd_find_hostb_device(dev) == child) 6204ad7e9b0SAdrian Chadd return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY); 6214ad7e9b0SAdrian Chadd 6224ad7e9b0SAdrian Chadd return (BHND_PROBE_DEFAULT); 623054ae231SAdrian Chadd default: 624054ae231SAdrian Chadd return (BHND_PROBE_DEFAULT); 6254ad7e9b0SAdrian Chadd } 6264ad7e9b0SAdrian Chadd } 6274ad7e9b0SAdrian Chadd 6284ad7e9b0SAdrian Chadd /** 629386fb140SAdrian Chadd * Default bhnd(4) bus driver implementation of BHND_BUS_IS_REGION_VALID(). 6304ad7e9b0SAdrian Chadd * 6314ad7e9b0SAdrian Chadd * This implementation assumes that port and region numbers are 0-indexed and 6324ad7e9b0SAdrian Chadd * are allocated non-sparsely, using BHND_BUS_GET_PORT_COUNT() and 6334ad7e9b0SAdrian Chadd * BHND_BUS_GET_REGION_COUNT() to determine if @p port and @p region fall 6344ad7e9b0SAdrian Chadd * within the defined range. 6354ad7e9b0SAdrian Chadd */ 636386fb140SAdrian Chadd static bool 6374ad7e9b0SAdrian Chadd bhnd_generic_is_region_valid(device_t dev, device_t child, 6384ad7e9b0SAdrian Chadd bhnd_port_type type, u_int port, u_int region) 6394ad7e9b0SAdrian Chadd { 6404ad7e9b0SAdrian Chadd if (port >= bhnd_get_port_count(child, type)) 6414ad7e9b0SAdrian Chadd return (false); 6424ad7e9b0SAdrian Chadd 6434ad7e9b0SAdrian Chadd if (region >= bhnd_get_region_count(child, type, port)) 6444ad7e9b0SAdrian Chadd return (false); 6454ad7e9b0SAdrian Chadd 6464ad7e9b0SAdrian Chadd return (true); 6474ad7e9b0SAdrian Chadd } 6484ad7e9b0SAdrian Chadd 6494ad7e9b0SAdrian Chadd /** 650fdedcd9fSLandon J. Fuller * Default bhnd(4) bus driver implementation of BHND_BUS_GET_NVRAM_VAR(). 651fdedcd9fSLandon J. Fuller * 652fdedcd9fSLandon J. Fuller * This implementation searches @p dev for a usable NVRAM child device. 653fdedcd9fSLandon J. Fuller * 654fdedcd9fSLandon J. Fuller * If no usable child device is found on @p dev, the request is delegated to 655fdedcd9fSLandon J. Fuller * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev. 656fdedcd9fSLandon J. Fuller */ 657fdedcd9fSLandon J. Fuller int 658fdedcd9fSLandon J. Fuller bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name, 659*1728aef2SLandon J. Fuller void *buf, size_t *size, bhnd_nvram_type type) 660fdedcd9fSLandon J. Fuller { 661fdedcd9fSLandon J. Fuller struct bhnd_softc *sc; 662fdedcd9fSLandon J. Fuller device_t nvram, parent; 663fdedcd9fSLandon J. Fuller 664fdedcd9fSLandon J. Fuller sc = device_get_softc(dev); 665fdedcd9fSLandon J. Fuller 666fdedcd9fSLandon J. Fuller /* If a NVRAM device is available, consult it first */ 667fdedcd9fSLandon J. Fuller if ((nvram = bhnd_find_nvram(sc)) != NULL) 668*1728aef2SLandon J. Fuller return BHND_NVRAM_GETVAR(nvram, name, buf, size, type); 669fdedcd9fSLandon J. Fuller 670fdedcd9fSLandon J. Fuller /* Otherwise, try to delegate to parent */ 671fdedcd9fSLandon J. Fuller if ((parent = device_get_parent(dev)) == NULL) 672fdedcd9fSLandon J. Fuller return (ENODEV); 673fdedcd9fSLandon J. Fuller 674fdedcd9fSLandon J. Fuller return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child, 675*1728aef2SLandon J. Fuller name, buf, size, type)); 676fdedcd9fSLandon J. Fuller } 677fdedcd9fSLandon J. Fuller 678fdedcd9fSLandon J. Fuller /** 679386fb140SAdrian Chadd * Default bhnd(4) bus driver implementation of BUS_PRINT_CHILD(). 6804ad7e9b0SAdrian Chadd * 6814ad7e9b0SAdrian Chadd * This implementation requests the device's struct resource_list via 6824ad7e9b0SAdrian Chadd * BUS_GET_RESOURCE_LIST. 6834ad7e9b0SAdrian Chadd */ 6844ad7e9b0SAdrian Chadd int 6854ad7e9b0SAdrian Chadd bhnd_generic_print_child(device_t dev, device_t child) 6864ad7e9b0SAdrian Chadd { 6874ad7e9b0SAdrian Chadd struct resource_list *rl; 6884ad7e9b0SAdrian Chadd int retval = 0; 6894ad7e9b0SAdrian Chadd 6904ad7e9b0SAdrian Chadd retval += bus_print_child_header(dev, child); 6914ad7e9b0SAdrian Chadd 6924ad7e9b0SAdrian Chadd rl = BUS_GET_RESOURCE_LIST(dev, child); 6934ad7e9b0SAdrian Chadd if (rl != NULL) { 6944ad7e9b0SAdrian Chadd retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, 695f8fd3fb5SJustin Hibbits "%#jx"); 6964ad7e9b0SAdrian Chadd } 6974ad7e9b0SAdrian Chadd 6984ad7e9b0SAdrian Chadd retval += printf(" at core %u", bhnd_get_core_index(child)); 6994ad7e9b0SAdrian Chadd 7004ad7e9b0SAdrian Chadd retval += bus_print_child_domain(dev, child); 7014ad7e9b0SAdrian Chadd retval += bus_print_child_footer(dev, child); 7024ad7e9b0SAdrian Chadd 7034ad7e9b0SAdrian Chadd return (retval); 7044ad7e9b0SAdrian Chadd } 7054ad7e9b0SAdrian Chadd 7064ad7e9b0SAdrian Chadd /** 707386fb140SAdrian Chadd * Default bhnd(4) bus driver implementation of BUS_PROBE_NOMATCH(). 7084ad7e9b0SAdrian Chadd * 7094ad7e9b0SAdrian Chadd * This implementation requests the device's struct resource_list via 7104ad7e9b0SAdrian Chadd * BUS_GET_RESOURCE_LIST. 7114ad7e9b0SAdrian Chadd */ 7124ad7e9b0SAdrian Chadd void 7134ad7e9b0SAdrian Chadd bhnd_generic_probe_nomatch(device_t dev, device_t child) 7144ad7e9b0SAdrian Chadd { 7154ad7e9b0SAdrian Chadd struct resource_list *rl; 7164ad7e9b0SAdrian Chadd const struct bhnd_nomatch *nm; 7174ad7e9b0SAdrian Chadd bool report; 7184ad7e9b0SAdrian Chadd 7194ad7e9b0SAdrian Chadd /* Fetch reporting configuration for this device */ 7204ad7e9b0SAdrian Chadd report = true; 7214ad7e9b0SAdrian Chadd for (nm = bhnd_nomatch_table; nm->device != BHND_COREID_INVALID; nm++) { 7224ad7e9b0SAdrian Chadd if (nm->vendor != bhnd_get_vendor(child)) 7234ad7e9b0SAdrian Chadd continue; 7244ad7e9b0SAdrian Chadd 7254ad7e9b0SAdrian Chadd if (nm->device != bhnd_get_device(child)) 7264ad7e9b0SAdrian Chadd continue; 7274ad7e9b0SAdrian Chadd 7284ad7e9b0SAdrian Chadd report = false; 7294ad7e9b0SAdrian Chadd if (bootverbose && nm->if_verbose) 7304ad7e9b0SAdrian Chadd report = true; 7314ad7e9b0SAdrian Chadd break; 7324ad7e9b0SAdrian Chadd } 7334ad7e9b0SAdrian Chadd 7344ad7e9b0SAdrian Chadd if (!report) 7354ad7e9b0SAdrian Chadd return; 7364ad7e9b0SAdrian Chadd 7374ad7e9b0SAdrian Chadd /* Print the non-matched device info */ 7384ad7e9b0SAdrian Chadd device_printf(dev, "<%s %s>", bhnd_get_vendor_name(child), 7394ad7e9b0SAdrian Chadd bhnd_get_device_name(child)); 7404ad7e9b0SAdrian Chadd 7414ad7e9b0SAdrian Chadd rl = BUS_GET_RESOURCE_LIST(dev, child); 7424ad7e9b0SAdrian Chadd if (rl != NULL) 743f8fd3fb5SJustin Hibbits resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx"); 7444ad7e9b0SAdrian Chadd 7454ad7e9b0SAdrian Chadd printf(" at core %u (no driver attached)\n", 7464ad7e9b0SAdrian Chadd bhnd_get_core_index(child)); 7474ad7e9b0SAdrian Chadd } 7484ad7e9b0SAdrian Chadd 7494ad7e9b0SAdrian Chadd /** 7504ad7e9b0SAdrian Chadd * Default implementation of BUS_CHILD_PNPINFO_STR(). 7514ad7e9b0SAdrian Chadd */ 7524ad7e9b0SAdrian Chadd static int 7534ad7e9b0SAdrian Chadd bhnd_child_pnpinfo_str(device_t dev, device_t child, char *buf, 7544ad7e9b0SAdrian Chadd size_t buflen) 7554ad7e9b0SAdrian Chadd { 7564ad7e9b0SAdrian Chadd if (device_get_parent(child) != dev) { 7574ad7e9b0SAdrian Chadd return (BUS_CHILD_PNPINFO_STR(device_get_parent(dev), child, 7584ad7e9b0SAdrian Chadd buf, buflen)); 7594ad7e9b0SAdrian Chadd } 7604ad7e9b0SAdrian Chadd 7614ad7e9b0SAdrian Chadd snprintf(buf, buflen, "vendor=0x%hx device=0x%hx rev=0x%hhx", 7624ad7e9b0SAdrian Chadd bhnd_get_vendor(child), bhnd_get_device(child), 7634ad7e9b0SAdrian Chadd bhnd_get_hwrev(child)); 7644ad7e9b0SAdrian Chadd 7654ad7e9b0SAdrian Chadd return (0); 7664ad7e9b0SAdrian Chadd } 7674ad7e9b0SAdrian Chadd 7684ad7e9b0SAdrian Chadd /** 769386fb140SAdrian Chadd * Default implementation of BUS_CHILD_LOCATION_STR(). 7704ad7e9b0SAdrian Chadd */ 7714ad7e9b0SAdrian Chadd static int 7724ad7e9b0SAdrian Chadd bhnd_child_location_str(device_t dev, device_t child, char *buf, 7734ad7e9b0SAdrian Chadd size_t buflen) 7744ad7e9b0SAdrian Chadd { 7754ad7e9b0SAdrian Chadd bhnd_addr_t addr; 7764ad7e9b0SAdrian Chadd bhnd_size_t size; 7774ad7e9b0SAdrian Chadd 7784ad7e9b0SAdrian Chadd if (device_get_parent(child) != dev) { 7794ad7e9b0SAdrian Chadd return (BUS_CHILD_LOCATION_STR(device_get_parent(dev), child, 7804ad7e9b0SAdrian Chadd buf, buflen)); 7814ad7e9b0SAdrian Chadd } 7824ad7e9b0SAdrian Chadd 7834ad7e9b0SAdrian Chadd 7844ad7e9b0SAdrian Chadd if (bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &addr, &size)) { 7854ad7e9b0SAdrian Chadd /* No device default port/region */ 7864ad7e9b0SAdrian Chadd if (buflen > 0) 7874ad7e9b0SAdrian Chadd *buf = '\0'; 7884ad7e9b0SAdrian Chadd return (0); 7894ad7e9b0SAdrian Chadd } 7904ad7e9b0SAdrian Chadd 7914ad7e9b0SAdrian Chadd snprintf(buf, buflen, "port0.0=0x%llx", (unsigned long long) addr); 7924ad7e9b0SAdrian Chadd return (0); 7934ad7e9b0SAdrian Chadd } 7944ad7e9b0SAdrian Chadd 7954ad7e9b0SAdrian Chadd /** 796688fc8c0SLandon J. Fuller * Default bhnd(4) bus driver implementation of BUS_ADD_CHILD(). 797688fc8c0SLandon J. Fuller * 798688fc8c0SLandon J. Fuller * This implementation manages internal bhnd(4) state, and must be called 799688fc8c0SLandon J. Fuller * by subclassing drivers. 800688fc8c0SLandon J. Fuller */ 801688fc8c0SLandon J. Fuller device_t 802688fc8c0SLandon J. Fuller bhnd_generic_add_child(device_t dev, u_int order, const char *name, int unit) 803688fc8c0SLandon J. Fuller { 804688fc8c0SLandon J. Fuller struct bhnd_devinfo *dinfo; 805688fc8c0SLandon J. Fuller device_t child; 806688fc8c0SLandon J. Fuller 807688fc8c0SLandon J. Fuller child = device_add_child_ordered(dev, order, name, unit); 808688fc8c0SLandon J. Fuller if (child == NULL) 809688fc8c0SLandon J. Fuller return (NULL); 810688fc8c0SLandon J. Fuller 811688fc8c0SLandon J. Fuller if ((dinfo = BHND_BUS_ALLOC_DEVINFO(dev)) == NULL) { 812688fc8c0SLandon J. Fuller device_delete_child(dev, child); 813688fc8c0SLandon J. Fuller return (NULL); 814688fc8c0SLandon J. Fuller } 815688fc8c0SLandon J. Fuller 816688fc8c0SLandon J. Fuller device_set_ivars(child, dinfo); 817688fc8c0SLandon J. Fuller 818688fc8c0SLandon J. Fuller /* Inform concrete bus driver. */ 819688fc8c0SLandon J. Fuller BHND_BUS_CHILD_ADDED(dev, child); 820688fc8c0SLandon J. Fuller 821688fc8c0SLandon J. Fuller return (child); 822688fc8c0SLandon J. Fuller } 823688fc8c0SLandon J. Fuller 824688fc8c0SLandon J. Fuller /** 825688fc8c0SLandon J. Fuller * Default bhnd(4) bus driver implementation of BUS_CHILD_DELETED(). 826688fc8c0SLandon J. Fuller * 827688fc8c0SLandon J. Fuller * This implementation manages internal bhnd(4) state, and must be called 828688fc8c0SLandon J. Fuller * by subclassing drivers. 829688fc8c0SLandon J. Fuller */ 830688fc8c0SLandon J. Fuller void 831688fc8c0SLandon J. Fuller bhnd_generic_child_deleted(device_t dev, device_t child) 832688fc8c0SLandon J. Fuller { 833688fc8c0SLandon J. Fuller struct bhnd_softc *sc; 834688fc8c0SLandon J. Fuller struct bhnd_devinfo *dinfo; 835688fc8c0SLandon J. Fuller 836688fc8c0SLandon J. Fuller sc = device_get_softc(dev); 837688fc8c0SLandon J. Fuller 838688fc8c0SLandon J. Fuller /* Free device info */ 839688fc8c0SLandon J. Fuller if ((dinfo = device_get_ivars(child)) != NULL) 840688fc8c0SLandon J. Fuller BHND_BUS_FREE_DEVINFO(dev, dinfo); 841fdedcd9fSLandon J. Fuller 842fdedcd9fSLandon J. Fuller /* Clean up platform device references */ 843fdedcd9fSLandon J. Fuller if (sc->chipc_dev == child) { 844fdedcd9fSLandon J. Fuller sc->chipc_dev = NULL; 845fdedcd9fSLandon J. Fuller } else if (sc->nvram_dev == child) { 846fdedcd9fSLandon J. Fuller sc->nvram_dev = NULL; 847fdedcd9fSLandon J. Fuller } else if (sc->pmu_dev == child) { 848fdedcd9fSLandon J. Fuller sc->pmu_dev = NULL; 849fdedcd9fSLandon J. Fuller } 850688fc8c0SLandon J. Fuller } 851688fc8c0SLandon J. Fuller 852688fc8c0SLandon J. Fuller /** 8534ad7e9b0SAdrian Chadd * Helper function for implementing BUS_SUSPEND_CHILD(). 8544ad7e9b0SAdrian Chadd * 8554ad7e9b0SAdrian Chadd * TODO: Power management 8564ad7e9b0SAdrian Chadd * 8574ad7e9b0SAdrian Chadd * If @p child is not a direct child of @p dev, suspension is delegated to 8584ad7e9b0SAdrian Chadd * the @p dev parent. 8594ad7e9b0SAdrian Chadd */ 8604ad7e9b0SAdrian Chadd int 8614ad7e9b0SAdrian Chadd bhnd_generic_suspend_child(device_t dev, device_t child) 8624ad7e9b0SAdrian Chadd { 8634ad7e9b0SAdrian Chadd if (device_get_parent(child) != dev) 8644ad7e9b0SAdrian Chadd BUS_SUSPEND_CHILD(device_get_parent(dev), child); 8654ad7e9b0SAdrian Chadd 8664ad7e9b0SAdrian Chadd return bus_generic_suspend_child(dev, child); 8674ad7e9b0SAdrian Chadd } 8684ad7e9b0SAdrian Chadd 8694ad7e9b0SAdrian Chadd /** 8704ad7e9b0SAdrian Chadd * Helper function for implementing BUS_RESUME_CHILD(). 8714ad7e9b0SAdrian Chadd * 8724ad7e9b0SAdrian Chadd * TODO: Power management 8734ad7e9b0SAdrian Chadd * 8744ad7e9b0SAdrian Chadd * If @p child is not a direct child of @p dev, suspension is delegated to 8754ad7e9b0SAdrian Chadd * the @p dev parent. 8764ad7e9b0SAdrian Chadd */ 8774ad7e9b0SAdrian Chadd int 8784ad7e9b0SAdrian Chadd bhnd_generic_resume_child(device_t dev, device_t child) 8794ad7e9b0SAdrian Chadd { 8804ad7e9b0SAdrian Chadd if (device_get_parent(child) != dev) 8814ad7e9b0SAdrian Chadd BUS_RESUME_CHILD(device_get_parent(dev), child); 8824ad7e9b0SAdrian Chadd 8834ad7e9b0SAdrian Chadd return bus_generic_resume_child(dev, child); 8844ad7e9b0SAdrian Chadd } 8854ad7e9b0SAdrian Chadd 8864ad7e9b0SAdrian Chadd /* 8874ad7e9b0SAdrian Chadd * Delegate all indirect I/O to the parent device. When inherited by 8884ad7e9b0SAdrian Chadd * non-bridged bus implementations, resources will never be marked as 8890e141e3cSAdrian Chadd * indirect, and these methods will never be called. 8904ad7e9b0SAdrian Chadd */ 891a73ac06dSAdrian Chadd #define BHND_IO_READ(_type, _name, _method) \ 892a73ac06dSAdrian Chadd static _type \ 893a73ac06dSAdrian Chadd bhnd_read_ ## _name (device_t dev, device_t child, \ 894a73ac06dSAdrian Chadd struct bhnd_resource *r, bus_size_t offset) \ 895a73ac06dSAdrian Chadd { \ 896a73ac06dSAdrian Chadd return (BHND_BUS_READ_ ## _method( \ 897a73ac06dSAdrian Chadd device_get_parent(dev), child, r, offset)); \ 8984ad7e9b0SAdrian Chadd } 8994ad7e9b0SAdrian Chadd 900a73ac06dSAdrian Chadd #define BHND_IO_WRITE(_type, _name, _method) \ 901a73ac06dSAdrian Chadd static void \ 902a73ac06dSAdrian Chadd bhnd_write_ ## _name (device_t dev, device_t child, \ 903a73ac06dSAdrian Chadd struct bhnd_resource *r, bus_size_t offset, _type value) \ 904a73ac06dSAdrian Chadd { \ 905a73ac06dSAdrian Chadd return (BHND_BUS_WRITE_ ## _method( \ 906a73ac06dSAdrian Chadd device_get_parent(dev), child, r, offset, \ 907a73ac06dSAdrian Chadd value)); \ 9084ad7e9b0SAdrian Chadd } 9094ad7e9b0SAdrian Chadd 9100e141e3cSAdrian Chadd #define BHND_IO_MISC(_type, _op, _method) \ 911a73ac06dSAdrian Chadd static void \ 9120e141e3cSAdrian Chadd bhnd_ ## _op (device_t dev, device_t child, \ 9130e141e3cSAdrian Chadd struct bhnd_resource *r, bus_size_t offset, _type datap, \ 914a73ac06dSAdrian Chadd bus_size_t count) \ 915a73ac06dSAdrian Chadd { \ 916a73ac06dSAdrian Chadd BHND_BUS_ ## _method(device_get_parent(dev), child, r, \ 917a73ac06dSAdrian Chadd offset, datap, count); \ 9184ad7e9b0SAdrian Chadd } 9194ad7e9b0SAdrian Chadd 920a73ac06dSAdrian Chadd #define BHND_IO_METHODS(_type, _size) \ 921a73ac06dSAdrian Chadd BHND_IO_READ(_type, _size, _size) \ 922a73ac06dSAdrian Chadd BHND_IO_WRITE(_type, _size, _size) \ 923a73ac06dSAdrian Chadd \ 924a73ac06dSAdrian Chadd BHND_IO_READ(_type, stream_ ## _size, STREAM_ ## _size) \ 925a73ac06dSAdrian Chadd BHND_IO_WRITE(_type, stream_ ## _size, STREAM_ ## _size) \ 926a73ac06dSAdrian Chadd \ 9270e141e3cSAdrian Chadd BHND_IO_MISC(_type*, read_multi_ ## _size, \ 9280e141e3cSAdrian Chadd READ_MULTI_ ## _size) \ 9290e141e3cSAdrian Chadd BHND_IO_MISC(_type*, write_multi_ ## _size, \ 9300e141e3cSAdrian Chadd WRITE_MULTI_ ## _size) \ 931a73ac06dSAdrian Chadd \ 9320e141e3cSAdrian Chadd BHND_IO_MISC(_type*, read_multi_stream_ ## _size, \ 933a73ac06dSAdrian Chadd READ_MULTI_STREAM_ ## _size) \ 9340e141e3cSAdrian Chadd BHND_IO_MISC(_type*, write_multi_stream_ ## _size, \ 935a73ac06dSAdrian Chadd WRITE_MULTI_STREAM_ ## _size) \ 9360e141e3cSAdrian Chadd \ 9370e141e3cSAdrian Chadd BHND_IO_MISC(_type, set_multi_ ## _size, SET_MULTI_ ## _size) \ 9380e141e3cSAdrian Chadd BHND_IO_MISC(_type, set_region_ ## _size, SET_REGION_ ## _size) \ 9390e141e3cSAdrian Chadd \ 9400e141e3cSAdrian Chadd BHND_IO_MISC(_type*, read_region_ ## _size, \ 9410e141e3cSAdrian Chadd READ_REGION_ ## _size) \ 9420e141e3cSAdrian Chadd BHND_IO_MISC(_type*, write_region_ ## _size, \ 9430e141e3cSAdrian Chadd WRITE_REGION_ ## _size) \ 9440e141e3cSAdrian Chadd \ 9450e141e3cSAdrian Chadd BHND_IO_MISC(_type*, read_region_stream_ ## _size, \ 9460e141e3cSAdrian Chadd READ_REGION_STREAM_ ## _size) \ 9470e141e3cSAdrian Chadd BHND_IO_MISC(_type*, write_region_stream_ ## _size, \ 9480e141e3cSAdrian Chadd WRITE_REGION_STREAM_ ## _size) \ 9494ad7e9b0SAdrian Chadd 950a73ac06dSAdrian Chadd BHND_IO_METHODS(uint8_t, 1); 951a73ac06dSAdrian Chadd BHND_IO_METHODS(uint16_t, 2); 952a73ac06dSAdrian Chadd BHND_IO_METHODS(uint32_t, 4); 9534ad7e9b0SAdrian Chadd 9544ad7e9b0SAdrian Chadd static void 9554ad7e9b0SAdrian Chadd bhnd_barrier(device_t dev, device_t child, struct bhnd_resource *r, 9564ad7e9b0SAdrian Chadd bus_size_t offset, bus_size_t length, int flags) 9574ad7e9b0SAdrian Chadd { 9584ad7e9b0SAdrian Chadd BHND_BUS_BARRIER(device_get_parent(dev), child, r, offset, length, 9594ad7e9b0SAdrian Chadd flags); 9604ad7e9b0SAdrian Chadd } 9614ad7e9b0SAdrian Chadd 9624ad7e9b0SAdrian Chadd static device_method_t bhnd_methods[] = { 9634ad7e9b0SAdrian Chadd /* Device interface */ \ 9644ad7e9b0SAdrian Chadd DEVMETHOD(device_attach, bhnd_generic_attach), 9654ad7e9b0SAdrian Chadd DEVMETHOD(device_detach, bhnd_generic_detach), 9664ad7e9b0SAdrian Chadd DEVMETHOD(device_shutdown, bhnd_generic_shutdown), 9674ad7e9b0SAdrian Chadd DEVMETHOD(device_suspend, bhnd_generic_suspend), 9684ad7e9b0SAdrian Chadd DEVMETHOD(device_resume, bhnd_generic_resume), 9694ad7e9b0SAdrian Chadd 9704ad7e9b0SAdrian Chadd /* Bus interface */ 971fdedcd9fSLandon J. Fuller DEVMETHOD(bus_new_pass, bhnd_new_pass), 972688fc8c0SLandon J. Fuller DEVMETHOD(bus_add_child, bhnd_generic_add_child), 973688fc8c0SLandon J. Fuller DEVMETHOD(bus_child_deleted, bhnd_generic_child_deleted), 9744ad7e9b0SAdrian Chadd DEVMETHOD(bus_probe_nomatch, bhnd_generic_probe_nomatch), 9754ad7e9b0SAdrian Chadd DEVMETHOD(bus_print_child, bhnd_generic_print_child), 9764ad7e9b0SAdrian Chadd DEVMETHOD(bus_child_pnpinfo_str, bhnd_child_pnpinfo_str), 9774ad7e9b0SAdrian Chadd DEVMETHOD(bus_child_location_str, bhnd_child_location_str), 9784ad7e9b0SAdrian Chadd 9794ad7e9b0SAdrian Chadd DEVMETHOD(bus_suspend_child, bhnd_generic_suspend_child), 9804ad7e9b0SAdrian Chadd DEVMETHOD(bus_resume_child, bhnd_generic_resume_child), 9814ad7e9b0SAdrian Chadd 9824ad7e9b0SAdrian Chadd DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), 9834ad7e9b0SAdrian Chadd DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 9844ad7e9b0SAdrian Chadd DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource), 9854ad7e9b0SAdrian Chadd DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource), 9864ad7e9b0SAdrian Chadd DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), 9874ad7e9b0SAdrian Chadd DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), 9884ad7e9b0SAdrian Chadd DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 9894ad7e9b0SAdrian Chadd DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 9904ad7e9b0SAdrian Chadd 9914ad7e9b0SAdrian Chadd DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 9924ad7e9b0SAdrian Chadd DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 9934ad7e9b0SAdrian Chadd DEVMETHOD(bus_config_intr, bus_generic_config_intr), 9944ad7e9b0SAdrian Chadd DEVMETHOD(bus_bind_intr, bus_generic_bind_intr), 9954ad7e9b0SAdrian Chadd DEVMETHOD(bus_describe_intr, bus_generic_describe_intr), 9964ad7e9b0SAdrian Chadd 9974ad7e9b0SAdrian Chadd DEVMETHOD(bus_get_dma_tag, bus_generic_get_dma_tag), 9984ad7e9b0SAdrian Chadd 9994ad7e9b0SAdrian Chadd /* BHND interface */ 1000386fb140SAdrian Chadd DEVMETHOD(bhnd_bus_get_chipid, bhnd_bus_generic_get_chipid), 10014ad7e9b0SAdrian Chadd DEVMETHOD(bhnd_bus_get_probe_order, bhnd_generic_get_probe_order), 1002386fb140SAdrian Chadd DEVMETHOD(bhnd_bus_is_region_valid, bhnd_generic_is_region_valid), 1003386fb140SAdrian Chadd DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_bus_generic_is_hw_disabled), 1004fdedcd9fSLandon J. Fuller DEVMETHOD(bhnd_bus_get_nvram_var, bhnd_generic_get_nvram_var), 10050e141e3cSAdrian Chadd 10060e141e3cSAdrian Chadd /* BHND interface (bus I/O) */ 10074ad7e9b0SAdrian Chadd DEVMETHOD(bhnd_bus_read_1, bhnd_read_1), 10084ad7e9b0SAdrian Chadd DEVMETHOD(bhnd_bus_read_2, bhnd_read_2), 10094ad7e9b0SAdrian Chadd DEVMETHOD(bhnd_bus_read_4, bhnd_read_4), 10104ad7e9b0SAdrian Chadd DEVMETHOD(bhnd_bus_write_1, bhnd_write_1), 10114ad7e9b0SAdrian Chadd DEVMETHOD(bhnd_bus_write_2, bhnd_write_2), 10124ad7e9b0SAdrian Chadd DEVMETHOD(bhnd_bus_write_4, bhnd_write_4), 10130e141e3cSAdrian Chadd 1014a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_stream_1, bhnd_read_stream_1), 1015a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_stream_2, bhnd_read_stream_2), 1016a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_stream_4, bhnd_read_stream_4), 1017a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_stream_1, bhnd_write_stream_1), 1018a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_stream_2, bhnd_write_stream_2), 1019a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_stream_4, bhnd_write_stream_4), 1020a73ac06dSAdrian Chadd 1021a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_multi_1, bhnd_read_multi_1), 1022a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_multi_2, bhnd_read_multi_2), 1023a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_multi_4, bhnd_read_multi_4), 1024a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_multi_1, bhnd_write_multi_1), 1025a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_multi_2, bhnd_write_multi_2), 1026a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_multi_4, bhnd_write_multi_4), 1027a73ac06dSAdrian Chadd 1028a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_multi_stream_1, bhnd_read_multi_stream_1), 1029a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_multi_stream_2, bhnd_read_multi_stream_2), 1030a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_read_multi_stream_4, bhnd_read_multi_stream_4), 1031a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_multi_stream_1,bhnd_write_multi_stream_1), 1032a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_multi_stream_2,bhnd_write_multi_stream_2), 1033a73ac06dSAdrian Chadd DEVMETHOD(bhnd_bus_write_multi_stream_4,bhnd_write_multi_stream_4), 1034a73ac06dSAdrian Chadd 10350e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_set_multi_1, bhnd_set_multi_1), 10360e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_set_multi_2, bhnd_set_multi_2), 10370e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_set_multi_4, bhnd_set_multi_4), 10380e141e3cSAdrian Chadd 10390e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_set_region_1, bhnd_set_region_1), 10400e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_set_region_2, bhnd_set_region_2), 10410e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_set_region_4, bhnd_set_region_4), 10420e141e3cSAdrian Chadd 10430e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_read_region_1, bhnd_read_region_1), 10440e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_read_region_2, bhnd_read_region_2), 10450e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_read_region_4, bhnd_read_region_4), 10460e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_write_region_1, bhnd_write_region_1), 10470e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_write_region_2, bhnd_write_region_2), 10480e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_write_region_4, bhnd_write_region_4), 10490e141e3cSAdrian Chadd 10500e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_read_region_stream_1,bhnd_read_region_stream_1), 10510e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_read_region_stream_2,bhnd_read_region_stream_2), 10520e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_read_region_stream_4,bhnd_read_region_stream_4), 10530e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_write_region_stream_1, bhnd_write_region_stream_1), 10540e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_write_region_stream_2, bhnd_write_region_stream_2), 10550e141e3cSAdrian Chadd DEVMETHOD(bhnd_bus_write_region_stream_4, bhnd_write_region_stream_4), 10560e141e3cSAdrian Chadd 10574ad7e9b0SAdrian Chadd DEVMETHOD(bhnd_bus_barrier, bhnd_barrier), 10584ad7e9b0SAdrian Chadd 10594ad7e9b0SAdrian Chadd DEVMETHOD_END 10604ad7e9b0SAdrian Chadd }; 10614ad7e9b0SAdrian Chadd 10624ad7e9b0SAdrian Chadd devclass_t bhnd_devclass; /**< bhnd bus. */ 10634ad7e9b0SAdrian Chadd devclass_t bhnd_hostb_devclass; /**< bhnd bus host bridge. */ 10644ad7e9b0SAdrian Chadd devclass_t bhnd_nvram_devclass; /**< bhnd NVRAM device */ 10654ad7e9b0SAdrian Chadd 10664ad7e9b0SAdrian Chadd DEFINE_CLASS_0(bhnd, bhnd_driver, bhnd_methods, sizeof(struct bhnd_softc)); 10674ad7e9b0SAdrian Chadd MODULE_VERSION(bhnd, 1); 1068