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