siba_bhndb.c revision 296077
1296077Sadrian/*- 2296077Sadrian * Copyright (c) 2015 Landon Fuller <landon@landonf.org> 3296077Sadrian * All rights reserved. 4296077Sadrian * 5296077Sadrian * Redistribution and use in source and binary forms, with or without 6296077Sadrian * modification, are permitted provided that the following conditions 7296077Sadrian * are met: 8296077Sadrian * 1. Redistributions of source code must retain the above copyright 9296077Sadrian * notice, this list of conditions and the following disclaimer, 10296077Sadrian * without modification. 11296077Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12296077Sadrian * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13296077Sadrian * redistribution must be conditioned upon including a substantially 14296077Sadrian * similar Disclaimer requirement for further binary redistribution. 15296077Sadrian * 16296077Sadrian * NO WARRANTY 17296077Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18296077Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19296077Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20296077Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21296077Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22296077Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23296077Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24296077Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25296077Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26296077Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27296077Sadrian * THE POSSIBILITY OF SUCH DAMAGES. 28296077Sadrian */ 29296077Sadrian 30296077Sadrian#include <sys/cdefs.h> 31296077Sadrian__FBSDID("$FreeBSD: head/sys/dev/bhnd/siba/siba_bhndb.c 296077 2016-02-26 03:34:08Z adrian $"); 32296077Sadrian 33296077Sadrian#include <sys/param.h> 34296077Sadrian#include <sys/kernel.h> 35296077Sadrian#include <sys/bus.h> 36296077Sadrian#include <sys/module.h> 37296077Sadrian 38296077Sadrian#include <dev/bhnd/bhnd_ids.h> 39296077Sadrian#include <dev/bhnd/bhndb/bhndbvar.h> 40296077Sadrian#include <dev/bhnd/bhndb/bhndb_hwdata.h> 41296077Sadrian 42296077Sadrian#include "sibavar.h" 43296077Sadrian 44296077Sadrian/* 45296077Sadrian * Supports attachment of siba(4) bus devices via a bhndb bridge. 46296077Sadrian */ 47296077Sadrian 48296077Sadrianstatic int 49296077Sadriansiba_bhndb_probe(device_t dev) 50296077Sadrian{ 51296077Sadrian const struct bhnd_chipid *cid; 52296077Sadrian 53296077Sadrian /* Check bus type */ 54296077Sadrian cid = BHNDB_GET_CHIPID(device_get_parent(dev), dev); 55296077Sadrian if (cid->chip_type != BHND_CHIPTYPE_SIBA) 56296077Sadrian return (ENXIO); 57296077Sadrian 58296077Sadrian /* Delegate to default probe implementation */ 59296077Sadrian return (siba_probe(dev)); 60296077Sadrian} 61296077Sadrian 62296077Sadrianstatic int 63296077Sadriansiba_bhndb_attach(device_t dev) 64296077Sadrian{ 65296077Sadrian const struct bhnd_chipid *chipid; 66296077Sadrian int error; 67296077Sadrian 68296077Sadrian /* Enumerate our children. */ 69296077Sadrian chipid = BHNDB_GET_CHIPID(device_get_parent(dev), dev); 70296077Sadrian if ((error = siba_add_children(dev, chipid))) 71296077Sadrian return (error); 72296077Sadrian 73296077Sadrian /* Initialize full bridge configuration */ 74296077Sadrian error = BHNDB_INIT_FULL_CONFIG(device_get_parent(dev), dev, 75296077Sadrian bhndb_siba_priority_table); 76296077Sadrian if (error) 77296077Sadrian return (error); 78296077Sadrian 79296077Sadrian /* Call our superclass' implementation */ 80296077Sadrian return (siba_attach(dev)); 81296077Sadrian} 82296077Sadrian 83296077Sadrian/* Suspend all references to the device's cfg register blocks */ 84296077Sadrianstatic void 85296077Sadriansiba_bhndb_suspend_cfgblocks(device_t dev, struct siba_devinfo *dinfo) { 86296077Sadrian for (u_int i = 0; i < dinfo->core_id.num_cfg_blocks; i++) { 87296077Sadrian if (dinfo->cfg[i] == NULL) 88296077Sadrian continue; 89296077Sadrian 90296077Sadrian BHNDB_SUSPEND_RESOURCE(device_get_parent(dev), dev, 91296077Sadrian SYS_RES_MEMORY, dinfo->cfg[i]->res); 92296077Sadrian } 93296077Sadrian} 94296077Sadrian 95296077Sadrianstatic int 96296077Sadriansiba_bhndb_suspend_child(device_t dev, device_t child) 97296077Sadrian{ 98296077Sadrian struct siba_devinfo *dinfo; 99296077Sadrian int error; 100296077Sadrian 101296077Sadrian if (device_get_parent(child) != dev) 102296077Sadrian BUS_SUSPEND_CHILD(device_get_parent(dev), child); 103296077Sadrian 104296077Sadrian dinfo = device_get_ivars(child); 105296077Sadrian 106296077Sadrian /* Suspend the child */ 107296077Sadrian if ((error = bhnd_generic_br_suspend_child(dev, child))) 108296077Sadrian return (error); 109296077Sadrian 110296077Sadrian /* Suspend resource references to the child's config registers */ 111296077Sadrian siba_bhndb_suspend_cfgblocks(dev, dinfo); 112296077Sadrian 113296077Sadrian return (0); 114296077Sadrian} 115296077Sadrian 116296077Sadrianstatic int 117296077Sadriansiba_bhndb_resume_child(device_t dev, device_t child) 118296077Sadrian{ 119296077Sadrian struct siba_devinfo *dinfo; 120296077Sadrian int error; 121296077Sadrian 122296077Sadrian if (device_get_parent(child) != dev) 123296077Sadrian BUS_SUSPEND_CHILD(device_get_parent(dev), child); 124296077Sadrian 125296077Sadrian if (!device_is_suspended(child)) 126296077Sadrian return (EBUSY); 127296077Sadrian 128296077Sadrian dinfo = device_get_ivars(child); 129296077Sadrian 130296077Sadrian /* Resume all resource references to the child's config registers */ 131296077Sadrian for (u_int i = 0; i < dinfo->core_id.num_cfg_blocks; i++) { 132296077Sadrian if (dinfo->cfg[i] == NULL) 133296077Sadrian continue; 134296077Sadrian 135296077Sadrian error = BHNDB_RESUME_RESOURCE(device_get_parent(dev), dev, 136296077Sadrian SYS_RES_MEMORY, dinfo->cfg[i]->res); 137296077Sadrian if (error) { 138296077Sadrian siba_bhndb_suspend_cfgblocks(dev, dinfo); 139296077Sadrian return (error); 140296077Sadrian } 141296077Sadrian } 142296077Sadrian 143296077Sadrian /* Resume the child */ 144296077Sadrian if ((error = bhnd_generic_br_resume_child(dev, child))) { 145296077Sadrian siba_bhndb_suspend_cfgblocks(dev, dinfo); 146296077Sadrian return (error); 147296077Sadrian } 148296077Sadrian 149296077Sadrian return (0); 150296077Sadrian} 151296077Sadrian 152296077Sadrianstatic device_method_t siba_bhndb_methods[] = { 153296077Sadrian /* Device interface */ 154296077Sadrian DEVMETHOD(device_probe, siba_bhndb_probe), 155296077Sadrian DEVMETHOD(device_attach, siba_bhndb_attach), 156296077Sadrian 157296077Sadrian /* Bus interface */ 158296077Sadrian DEVMETHOD(bus_suspend_child, siba_bhndb_suspend_child), 159296077Sadrian DEVMETHOD(bus_resume_child, siba_bhndb_resume_child), 160296077Sadrian 161296077Sadrian DEVMETHOD_END 162296077Sadrian}; 163296077Sadrian 164296077SadrianDEFINE_CLASS_1(bhnd, siba_bhndb_driver, siba_bhndb_methods, 165296077Sadrian sizeof(struct siba_softc), siba_driver); 166296077Sadrian 167296077SadrianDRIVER_MODULE(siba_bhndb, bhndb, siba_bhndb_driver, bhnd_devclass, NULL, NULL); 168296077Sadrian 169296077SadrianMODULE_VERSION(siba_bhndb, 1); 170296077SadrianMODULE_DEPEND(siba_bhndb, siba, 1, 1, 1); 171296077SadrianMODULE_DEPEND(siba_bhndb, bhndb, 1, 1, 1);