1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2015 Landon Fuller <landon@landonf.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer, 12 * without modification. 13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 14 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 15 * redistribution must be conditioned upon including a substantially 16 * similar Disclaimer requirement for further binary redistribution. 17 * 18 * NO WARRANTY 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 22 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 23 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 24 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 27 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 29 * THE POSSIBILITY OF SUCH DAMAGES. 30 */ 31 32 #include <sys/param.h> 33 #include <sys/kernel.h> 34 #include <sys/bus.h> 35 #include <sys/module.h> 36 37 #include <dev/bhnd/bhnd_ids.h> 38 #include <dev/bhnd/bhndb/bhndbvar.h> 39 #include <dev/bhnd/bhndb/bhndb_hwdata.h> 40 41 #include "bcmavar.h" 42 43 #include "bcma_eromreg.h" 44 #include "bcma_eromvar.h" 45 46 /* 47 * Supports attachment of bcma(4) bus devices via a bhndb bridge. 48 */ 49 50 static int 51 bcma_bhndb_probe(device_t dev) 52 { 53 const struct bhnd_chipid *cid; 54 int error; 55 56 /* Defer to default probe implementation */ 57 if ((error = bcma_probe(dev)) > 0) 58 return (error); 59 60 /* Check bus type */ 61 cid = BHNDB_GET_CHIPID(device_get_parent(dev), dev); 62 if (cid->chip_type != BHND_CHIPTYPE_BCMA) 63 return (ENXIO); 64 65 /* Set device description */ 66 bhnd_set_default_bus_desc(dev, cid); 67 68 return (error); 69 } 70 71 static int 72 bcma_bhndb_attach(device_t dev) 73 { 74 int error; 75 76 /* Perform initial attach and enumerate our children. */ 77 if ((error = bcma_attach(dev))) 78 goto failed; 79 80 /* Delegate remainder to standard bhnd method implementation */ 81 if ((error = bhnd_generic_attach(dev))) 82 goto failed; 83 84 return (0); 85 86 failed: 87 device_delete_children(dev); 88 return (error); 89 } 90 91 static int 92 bcma_bhndb_suspend_child(device_t dev, device_t child) 93 { 94 struct bcma_devinfo *dinfo; 95 int error; 96 97 if (device_get_parent(child) != dev) 98 BUS_SUSPEND_CHILD(device_get_parent(dev), child); 99 100 if (device_is_suspended(child)) 101 return (EBUSY); 102 103 dinfo = device_get_ivars(child); 104 105 /* Suspend the child */ 106 if ((error = bhnd_generic_br_suspend_child(dev, child))) 107 return (error); 108 109 /* Suspend child's agent resource */ 110 if (dinfo->res_agent != NULL) 111 BHNDB_SUSPEND_RESOURCE(device_get_parent(dev), dev, 112 SYS_RES_MEMORY, dinfo->res_agent->res); 113 114 return (0); 115 } 116 117 static int 118 bcma_bhndb_resume_child(device_t dev, device_t child) 119 { 120 struct bcma_devinfo *dinfo; 121 int error; 122 123 if (device_get_parent(child) != dev) 124 BUS_SUSPEND_CHILD(device_get_parent(dev), child); 125 126 if (!device_is_suspended(child)) 127 return (EBUSY); 128 129 dinfo = device_get_ivars(child); 130 131 /* Resume child's agent resource */ 132 if (dinfo->res_agent != NULL) { 133 error = BHNDB_RESUME_RESOURCE(device_get_parent(dev), dev, 134 SYS_RES_MEMORY, dinfo->res_agent->res); 135 if (error) 136 return (error); 137 } 138 139 /* Resume the child */ 140 if ((error = bhnd_generic_br_resume_child(dev, child))) { 141 /* On failure, re-suspend the agent resource */ 142 if (dinfo->res_agent != NULL) { 143 BHNDB_SUSPEND_RESOURCE(device_get_parent(dev), dev, 144 SYS_RES_MEMORY, dinfo->res_agent->res); 145 } 146 147 return (error); 148 } 149 150 return (0); 151 } 152 153 static device_method_t bcma_bhndb_methods[] = { 154 /* Device interface */ 155 DEVMETHOD(device_probe, bcma_bhndb_probe), 156 DEVMETHOD(device_attach, bcma_bhndb_attach), 157 158 /* Bus interface */ 159 DEVMETHOD(bus_suspend_child, bcma_bhndb_suspend_child), 160 DEVMETHOD(bus_resume_child, bcma_bhndb_resume_child), 161 162 DEVMETHOD_END 163 }; 164 165 DEFINE_CLASS_2(bhnd, bcma_bhndb_driver, bcma_bhndb_methods, 166 sizeof(struct bcma_softc), bhnd_bhndb_driver, bcma_driver); 167 168 DRIVER_MODULE(bcma_bhndb, bhndb, bcma_bhndb_driver, NULL, NULL); 169 170 MODULE_VERSION(bcma_bhndb, 1); 171 MODULE_DEPEND(bcma_bhndb, bcma, 1, 1, 1); 172 MODULE_DEPEND(bcma_bhndb, bhnd, 1, 1, 1); 173 MODULE_DEPEND(bcma_bhndb, bhndb, 1, 1, 1); 174