1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 5 * Copyright (c) 2010-2011 Adrian Chadd, Xenion Pty Ltd 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer, 13 * without modification. 14 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 15 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 16 * redistribution must be conditioned upon including a substantially 17 * similar Disclaimer requirement for further binary redistribution. 18 * 19 * NO WARRANTY 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 23 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 24 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 25 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 28 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGES. 31 */ 32 33#include <sys/cdefs.h> 34__FBSDID("$FreeBSD: releng/12.0/sys/dev/ath/if_ath_ahb.c 326255 2017-11-27 14:52:40Z pfg $"); 35 36/* 37 * AHB bus front-end for the Atheros Wireless LAN controller driver. 38 */ 39 40#include "opt_ath.h" 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/malloc.h> 45#include <sys/module.h> 46#include <sys/kernel.h> 47#include <sys/lock.h> 48#include <sys/mutex.h> 49#include <sys/errno.h> 50 51#include <machine/bus.h> 52#include <machine/resource.h> 53#include <sys/bus.h> 54#include <sys/rman.h> 55 56#include <sys/socket.h> 57 58#include <net/if.h> 59#include <net/if_media.h> 60#include <net/if_arp.h> 61#include <net/ethernet.h> 62 63#include <net80211/ieee80211_var.h> 64 65#include <dev/ath/if_athvar.h> 66 67#include <mips/atheros/ar71xxreg.h> 68#include <mips/atheros/ar91xxreg.h> 69#include <mips/atheros/ar71xx_cpudef.h> 70 71/* For EEPROM firmware */ 72#ifdef ATH_EEPROM_FIRMWARE 73#include <sys/linker.h> 74#include <sys/firmware.h> 75#endif /* ATH_EEPROM_FIRMWARE */ 76 77/* 78 * bus glue. 79 */ 80 81/* number of 16 bit words */ 82#define ATH_EEPROM_DATA_SIZE 2048 83 84struct ath_ahb_softc { 85 struct ath_softc sc_sc; 86 struct resource *sc_sr; /* memory resource */ 87 struct resource *sc_irq; /* irq resource */ 88 void *sc_ih; /* interrupt handler */ 89}; 90 91#define VENDOR_ATHEROS 0x168c 92#define AR9130_DEVID 0x000b 93 94static int 95ath_ahb_probe(device_t dev) 96{ 97 int vendor_id, device_id; 98 const char* devname; 99 100 /* 101 * Check if a device/vendor ID is provided in hints. 102 */ 103 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 104 "vendor_id", &vendor_id) != 0) { 105 vendor_id = VENDOR_ATHEROS; 106 } 107 108 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 109 "device_id", &device_id) != 0) { 110 device_id = AR9130_DEVID; 111 } 112 113 device_printf(dev, "Vendor=0x%04x, Device=0x%04x\n", 114 vendor_id & 0xffff, 115 device_id & 0xffff); 116 117 /* Attempt to probe */ 118 devname = ath_hal_probe(vendor_id, device_id); 119 120 if (devname != NULL) { 121 device_set_desc(dev, devname); 122 return BUS_PROBE_DEFAULT; 123 } 124 return ENXIO; 125} 126 127static void 128ath_ahb_intr(void *arg) 129{ 130 /* XXX TODO: check if its ours! */ 131 ar71xx_device_flush_ddr(AR71XX_CPU_DDR_FLUSH_WMAC); 132 ath_intr(arg); 133} 134 135static int 136ath_ahb_attach(device_t dev) 137{ 138 struct ath_ahb_softc *psc = device_get_softc(dev); 139 struct ath_softc *sc = &psc->sc_sc; 140 int error = ENXIO; 141 int rid; 142 int device_id, vendor_id; 143#ifdef ATH_EEPROM_FIRMWARE 144 const struct firmware *fw = NULL; 145 const char *buf; 146#endif 147 148 sc->sc_dev = dev; 149 150 rid = 0; 151 psc->sc_sr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 152 if (psc->sc_sr == NULL) { 153 device_printf(dev, "cannot map register space\n"); 154 goto bad; 155 } 156 157 sc->sc_st = (HAL_BUS_TAG) rman_get_bustag(psc->sc_sr); 158 sc->sc_sh = (HAL_BUS_HANDLE) rman_get_bushandle(psc->sc_sr); 159 /* 160 * Mark device invalid so any interrupts (shared or otherwise) 161 * that arrive before the HAL is setup are discarded. 162 */ 163 sc->sc_invalid = 1; 164 165#ifdef ATH_EEPROM_FIRMWARE 166 /* 167 * If there's an EEPROM firmware image, load that in. 168 */ 169 if (resource_string_value(device_get_name(dev), device_get_unit(dev), 170 "eeprom_firmware", &buf) == 0) { 171 device_printf(dev, "%s: looking up firmware @ '%s'\n", 172 __func__, buf); 173 174 fw = firmware_get(buf); 175 if (fw == NULL) { 176 device_printf(dev, "%s: couldn't find firmware\n", 177 __func__); 178 goto bad1; 179 } 180 181 device_printf(dev, "%s: EEPROM firmware @ %p\n", 182 __func__, fw->data); 183 sc->sc_eepromdata = 184 malloc(fw->datasize, M_TEMP, M_WAITOK | M_ZERO); 185 if (! sc->sc_eepromdata) { 186 device_printf(dev, "%s: can't malloc eepromdata\n", 187 __func__); 188 goto bad1; 189 } 190 memcpy(sc->sc_eepromdata, fw->data, fw->datasize); 191 firmware_put(fw, 0); 192 } 193#endif /* ATH_EEPROM_FIRMWARE */ 194 195 /* 196 * Arrange interrupt line. 197 */ 198 rid = 0; 199 psc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE|RF_ACTIVE); 200 if (psc->sc_irq == NULL) { 201 device_printf(dev, "could not map interrupt\n"); 202 goto bad1; 203 } 204 if (bus_setup_intr(dev, psc->sc_irq, 205 INTR_TYPE_NET | INTR_MPSAFE, 206 NULL, ath_ahb_intr, sc, &psc->sc_ih)) { 207 device_printf(dev, "could not establish interrupt\n"); 208 goto bad2; 209 } 210 211 /* 212 * Setup DMA descriptor area. 213 */ 214 if (bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 215 1, 0, /* alignment, bounds */ 216 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 217 BUS_SPACE_MAXADDR, /* highaddr */ 218 NULL, NULL, /* filter, filterarg */ 219 0x3ffff, /* maxsize XXX */ 220 ATH_MAX_SCATTER, /* nsegments */ 221 0x3ffff, /* maxsegsize XXX */ 222 BUS_DMA_ALLOCNOW, /* flags */ 223 NULL, /* lockfunc */ 224 NULL, /* lockarg */ 225 &sc->sc_dmat)) { 226 device_printf(dev, "cannot allocate DMA tag\n"); 227 goto bad3; 228 } 229 230 /* 231 * Check if a device/vendor ID is provided in hints. 232 */ 233 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 234 "vendor_id", &vendor_id) != 0) { 235 vendor_id = VENDOR_ATHEROS; 236 } 237 238 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 239 "device_id", &device_id) != 0) { 240 device_id = AR9130_DEVID; 241 } 242 243 ATH_LOCK_INIT(sc); 244 ATH_PCU_LOCK_INIT(sc); 245 ATH_RX_LOCK_INIT(sc); 246 ATH_TX_LOCK_INIT(sc); 247 ATH_TXSTATUS_LOCK_INIT(sc); 248 249 error = ath_attach(device_id, sc); 250 if (error == 0) /* success */ 251 return 0; 252 253 ATH_TXSTATUS_LOCK_DESTROY(sc); 254 ATH_RX_LOCK_DESTROY(sc); 255 ATH_TX_LOCK_DESTROY(sc); 256 ATH_PCU_LOCK_DESTROY(sc); 257 ATH_LOCK_DESTROY(sc); 258 bus_dma_tag_destroy(sc->sc_dmat); 259bad3: 260 bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih); 261bad2: 262 bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq); 263bad1: 264 bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_sr); 265bad: 266 /* XXX?! */ 267 if (sc->sc_eepromdata) 268 free(sc->sc_eepromdata, M_TEMP); 269 return (error); 270} 271 272static int 273ath_ahb_detach(device_t dev) 274{ 275 struct ath_ahb_softc *psc = device_get_softc(dev); 276 struct ath_softc *sc = &psc->sc_sc; 277 278 /* check if device was removed */ 279 sc->sc_invalid = !bus_child_present(dev); 280 281 ath_detach(sc); 282 283 bus_generic_detach(dev); 284 bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih); 285 bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq); 286 287 bus_dma_tag_destroy(sc->sc_dmat); 288 bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_sr); 289 /* XXX?! */ 290 if (sc->sc_eepromdata) 291 free(sc->sc_eepromdata, M_TEMP); 292 293 ATH_TXSTATUS_LOCK_DESTROY(sc); 294 ATH_RX_LOCK_DESTROY(sc); 295 ATH_TX_LOCK_DESTROY(sc); 296 ATH_PCU_LOCK_DESTROY(sc); 297 ATH_LOCK_DESTROY(sc); 298 299 return (0); 300} 301 302static int 303ath_ahb_shutdown(device_t dev) 304{ 305 struct ath_ahb_softc *psc = device_get_softc(dev); 306 307 ath_shutdown(&psc->sc_sc); 308 return (0); 309} 310 311static int 312ath_ahb_suspend(device_t dev) 313{ 314 struct ath_ahb_softc *psc = device_get_softc(dev); 315 316 ath_suspend(&psc->sc_sc); 317 318 return (0); 319} 320 321static int 322ath_ahb_resume(device_t dev) 323{ 324 struct ath_ahb_softc *psc = device_get_softc(dev); 325 326 ath_resume(&psc->sc_sc); 327 328 return (0); 329} 330 331static device_method_t ath_ahb_methods[] = { 332 /* Device interface */ 333 DEVMETHOD(device_probe, ath_ahb_probe), 334 DEVMETHOD(device_attach, ath_ahb_attach), 335 DEVMETHOD(device_detach, ath_ahb_detach), 336 DEVMETHOD(device_shutdown, ath_ahb_shutdown), 337 DEVMETHOD(device_suspend, ath_ahb_suspend), 338 DEVMETHOD(device_resume, ath_ahb_resume), 339 { 0,0 } 340}; 341static driver_t ath_ahb_driver = { 342 "ath", 343 ath_ahb_methods, 344 sizeof (struct ath_ahb_softc) 345}; 346static devclass_t ath_devclass; 347DRIVER_MODULE(if_ath_ahb, nexus, ath_ahb_driver, ath_devclass, 0, 0); 348DRIVER_MODULE(if_ath_ahb, apb, ath_ahb_driver, ath_devclass, 0, 0); 349MODULE_VERSION(if_ath_ahb, 1); 350MODULE_DEPEND(if_ath_ahb, wlan, 1, 1, 1); /* 802.11 media layer */ 351MODULE_DEPEND(if_ath_ahb, ath_main, 1, 1, 1); /* if_ath driver */ 352MODULE_DEPEND(if_ath_ahb, ath_hal, 1, 1, 1); /* ath HAL */ 353