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 #if defined(__DragonFly__) 263 #else 264 NULL, NULL, /* filter, filterarg */ 265 #endif 266 0x3ffff, /* maxsize XXX */ 267 ATH_MAX_SCATTER, /* nsegments */ 268 0x3ffff, /* maxsegsize XXX */ 269 BUS_DMA_ALLOCNOW, /* flags */ 270 #if defined(__DragonFly__) 271 #else 272 NULL, /* lockfunc */ 273 NULL, /* lockarg */ 274 #endif 275 &sc->sc_dmat)) { 276 device_printf(dev, "cannot allocate DMA tag\n"); 277 goto bad3; 278 } 279 280 /* 281 * Check if a device/vendor ID is provided in hints. 282 */ 283 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 284 "vendor_id", &vendor_id) != 0) { 285 vendor_id = VENDOR_ATHEROS; 286 } 287 288 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 289 "device_id", &device_id) != 0) { 290 device_id = AR9130_DEVID; 291 } 292 293 ATH_LOCK_INIT(sc); 294 ATH_PCU_LOCK_INIT(sc); 295 ATH_RX_LOCK_INIT(sc); 296 ATH_TX_LOCK_INIT(sc); 297 ATH_TXSTATUS_LOCK_INIT(sc); 298 299 error = ath_attach(device_id, sc); 300 if (error == 0) /* success */ 301 return 0; 302 303 ATH_TXSTATUS_LOCK_DESTROY(sc); 304 ATH_RX_LOCK_DESTROY(sc); 305 ATH_TX_LOCK_DESTROY(sc); 306 ATH_PCU_LOCK_DESTROY(sc); 307 ATH_LOCK_DESTROY(sc); 308 bus_dma_tag_destroy(sc->sc_dmat); 309 bad3: 310 bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih); 311 bad2: 312 bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq); 313 bad1: 314 bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_eeprom); 315 bad0: 316 bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_sr); 317 bad: 318 /* XXX?! */ 319 if (sc->sc_eepromdata) 320 kfree(sc->sc_eepromdata, M_TEMP); 321 return (error); 322 } 323 324 static int 325 ath_ahb_detach(device_t dev) 326 { 327 struct ath_ahb_softc *psc = device_get_softc(dev); 328 struct ath_softc *sc = &psc->sc_sc; 329 330 /* check if device was removed */ 331 sc->sc_invalid = !bus_child_present(dev); 332 333 ath_detach(sc); 334 335 bus_generic_detach(dev); 336 bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih); 337 bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq); 338 339 bus_dma_tag_destroy(sc->sc_dmat); 340 bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_sr); 341 bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_eeprom); 342 /* XXX?! */ 343 if (sc->sc_eepromdata) 344 kfree(sc->sc_eepromdata, M_TEMP); 345 346 ATH_TXSTATUS_LOCK_DESTROY(sc); 347 ATH_RX_LOCK_DESTROY(sc); 348 ATH_TX_LOCK_DESTROY(sc); 349 ATH_PCU_LOCK_DESTROY(sc); 350 ATH_LOCK_DESTROY(sc); 351 352 return (0); 353 } 354 355 static int 356 ath_ahb_shutdown(device_t dev) 357 { 358 struct ath_ahb_softc *psc = device_get_softc(dev); 359 360 ath_shutdown(&psc->sc_sc); 361 return (0); 362 } 363 364 static int 365 ath_ahb_suspend(device_t dev) 366 { 367 struct ath_ahb_softc *psc = device_get_softc(dev); 368 369 ath_suspend(&psc->sc_sc); 370 371 return (0); 372 } 373 374 static int 375 ath_ahb_resume(device_t dev) 376 { 377 struct ath_ahb_softc *psc = device_get_softc(dev); 378 379 ath_resume(&psc->sc_sc); 380 381 return (0); 382 } 383 384 static device_method_t ath_ahb_methods[] = { 385 /* Device interface */ 386 DEVMETHOD(device_probe, ath_ahb_probe), 387 DEVMETHOD(device_attach, ath_ahb_attach), 388 DEVMETHOD(device_detach, ath_ahb_detach), 389 DEVMETHOD(device_shutdown, ath_ahb_shutdown), 390 DEVMETHOD(device_suspend, ath_ahb_suspend), 391 DEVMETHOD(device_resume, ath_ahb_resume), 392 393 { 0,0 } 394 }; 395 static driver_t ath_ahb_driver = { 396 "ath", 397 ath_ahb_methods, 398 sizeof (struct ath_ahb_softc) 399 }; 400 static devclass_t ath_devclass; 401 DRIVER_MODULE(ath, nexus, ath_ahb_driver, ath_devclass, NULL, NULL); 402 #if defined(__DragonFly__) 403 #else 404 DRIVER_MODULE(ath, apb, ath_ahb_driver, ath_devclass, 0, 0); 405 #endif 406 MODULE_VERSION(ath, 1); 407 MODULE_DEPEND(ath, wlan, 1, 1, 1); /* 802.11 media layer */ 408 MODULE_DEPEND(ath, if_ath, 1, 1, 1); /* if_ath driver */ 409