Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: libertas sdio driver

Add driver for Marvell's Libertas 8385 and 8686 wifi chips.

Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Acked-by: Dan Williams <dcbw@redhat.com>

+1140
+6
drivers/net/wireless/Kconfig
··· 282 282 ---help--- 283 283 A driver for Marvell Libertas 8385 CompactFlash devices. 284 284 285 + config LIBERTAS_SDIO 286 + tristate "Marvell Libertas 8385 and 8686 SDIO 802.11b/g cards" 287 + depends on LIBERTAS && MMC 288 + ---help--- 289 + A driver for Marvell Libertas 8385 and 8686 SDIO devices. 290 + 285 291 config LIBERTAS_DEBUG 286 292 bool "Enable full debugging output in the Libertas module." 287 293 depends on LIBERTAS
+2
drivers/net/wireless/libertas/Makefile
··· 7 7 8 8 usb8xxx-objs += if_usb.o 9 9 libertas_cs-objs += if_cs.o 10 + libertas_sdio-objs += if_sdio.o 10 11 11 12 obj-$(CONFIG_LIBERTAS) += libertas.o 12 13 obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o 13 14 obj-$(CONFIG_LIBERTAS_CS) += libertas_cs.o 15 + obj-$(CONFIG_LIBERTAS_SDIO) += libertas_sdio.o
+2
drivers/net/wireless/libertas/defs.h
··· 39 39 #define LBS_DEB_FW 0x00080000 40 40 #define LBS_DEB_THREAD 0x00100000 41 41 #define LBS_DEB_HEX 0x00200000 42 + #define LBS_DEB_SDIO 0x00400000 42 43 43 44 extern unsigned int libertas_debug; 44 45 ··· 81 80 #define lbs_deb_usbd(dev, fmt, args...) LBS_DEB_LL(LBS_DEB_USB, " usbd", "%s:" fmt, (dev)->bus_id, ##args) 82 81 #define lbs_deb_cs(fmt, args...) LBS_DEB_LL(LBS_DEB_CS, " cs", fmt, ##args) 83 82 #define lbs_deb_thread(fmt, args...) LBS_DEB_LL(LBS_DEB_THREAD, " thread", fmt, ##args) 83 + #define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " thread", fmt, ##args) 84 84 85 85 #define lbs_pr_info(format, args...) \ 86 86 printk(KERN_INFO DRV_NAME": " format, ## args)
+1079
drivers/net/wireless/libertas/if_sdio.c
··· 1 + /* 2 + * linux/drivers/net/wireless/libertas/if_sdio.c 3 + * 4 + * Copyright 2007 Pierre Ossman 5 + * 6 + * Inspired by if_cs.c, Copyright 2007 Holger Schurig 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License as published by 10 + * the Free Software Foundation; either version 2 of the License, or (at 11 + * your option) any later version. 12 + * 13 + * This hardware has more or less no CMD53 support, so all registers 14 + * must be accessed using sdio_readb()/sdio_writeb(). 15 + * 16 + * Transfers must be in one transaction or the firmware goes bonkers. 17 + * This means that the transfer must either be small enough to do a 18 + * byte based transfer or it must be padded to a multiple of the 19 + * current block size. 20 + * 21 + * As SDIO is still new to the kernel, it is unfortunately common with 22 + * bugs in the host controllers related to that. One such bug is that 23 + * controllers cannot do transfers that aren't a multiple of 4 bytes. 24 + * If you don't have time to fix the host controller driver, you can 25 + * work around the problem by modifying if_sdio_host_to_card() and 26 + * if_sdio_card_to_host() to pad the data. 27 + */ 28 + 29 + #include <linux/moduleparam.h> 30 + #include <linux/firmware.h> 31 + #include <linux/netdevice.h> 32 + #include <linux/delay.h> 33 + #include <linux/mmc/card.h> 34 + #include <linux/mmc/sdio_func.h> 35 + #include <linux/mmc/sdio_ids.h> 36 + 37 + #include "host.h" 38 + #include "decl.h" 39 + #include "defs.h" 40 + #include "dev.h" 41 + #include "if_sdio.h" 42 + 43 + static char *libertas_helper_name = NULL; 44 + module_param_named(helper_name, libertas_helper_name, charp, 0644); 45 + 46 + static char *libertas_fw_name = NULL; 47 + module_param_named(fw_name, libertas_fw_name, charp, 0644); 48 + 49 + static const struct sdio_device_id if_sdio_ids[] = { 50 + { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_LIBERTAS) }, 51 + { /* end: all zeroes */ }, 52 + }; 53 + 54 + MODULE_DEVICE_TABLE(sdio, if_sdio_ids); 55 + 56 + struct if_sdio_model { 57 + int model; 58 + const char *helper; 59 + const char *firmware; 60 + }; 61 + 62 + static struct if_sdio_model if_sdio_models[] = { 63 + { 64 + /* 8385 */ 65 + .model = 0x04, 66 + .helper = "sd8385_helper.bin", 67 + .firmware = "sd8385.bin", 68 + }, 69 + { 70 + /* 8686 */ 71 + .model = 0x0B, 72 + .helper = "sd8686_helper.bin", 73 + .firmware = "sd8686.bin", 74 + }, 75 + }; 76 + 77 + struct if_sdio_packet { 78 + struct if_sdio_packet *next; 79 + u16 nb; 80 + u8 buffer[0] __attribute__((aligned(4))); 81 + }; 82 + 83 + struct if_sdio_card { 84 + struct sdio_func *func; 85 + wlan_private *priv; 86 + 87 + int model; 88 + unsigned long ioport; 89 + 90 + const char *helper; 91 + const char *firmware; 92 + 93 + u8 buffer[65536]; 94 + u8 int_cause; 95 + u32 event; 96 + 97 + spinlock_t lock; 98 + struct if_sdio_packet *packets; 99 + struct work_struct packet_worker; 100 + }; 101 + 102 + /********************************************************************/ 103 + /* I/O */ 104 + /********************************************************************/ 105 + 106 + static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err) 107 + { 108 + int ret, reg; 109 + u16 scratch; 110 + 111 + if (card->model == 0x04) 112 + reg = IF_SDIO_SCRATCH_OLD; 113 + else 114 + reg = IF_SDIO_SCRATCH; 115 + 116 + scratch = sdio_readb(card->func, reg, &ret); 117 + if (!ret) 118 + scratch |= sdio_readb(card->func, reg + 1, &ret) << 8; 119 + 120 + if (err) 121 + *err = ret; 122 + 123 + if (ret) 124 + return 0xffff; 125 + 126 + return scratch; 127 + } 128 + 129 + static int if_sdio_handle_cmd(struct if_sdio_card *card, 130 + u8 *buffer, unsigned size) 131 + { 132 + int ret; 133 + unsigned long flags; 134 + 135 + lbs_deb_enter(LBS_DEB_SDIO); 136 + 137 + spin_lock_irqsave(&card->priv->adapter->driver_lock, flags); 138 + 139 + if (!card->priv->adapter->cur_cmd) { 140 + lbs_deb_sdio("discarding spurious response\n"); 141 + ret = 0; 142 + goto out; 143 + } 144 + 145 + if (size > MRVDRV_SIZE_OF_CMD_BUFFER) { 146 + lbs_deb_sdio("response packet too large (%d bytes)\n", 147 + (int)size); 148 + ret = -E2BIG; 149 + goto out; 150 + } 151 + 152 + memcpy(card->priv->adapter->cur_cmd->bufvirtualaddr, buffer, size); 153 + card->priv->upld_len = size; 154 + 155 + card->int_cause |= MRVDRV_CMD_UPLD_RDY; 156 + 157 + libertas_interrupt(card->priv->dev); 158 + 159 + ret = 0; 160 + 161 + out: 162 + spin_unlock_irqrestore(&card->priv->adapter->driver_lock, flags); 163 + 164 + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); 165 + 166 + return ret; 167 + } 168 + 169 + static int if_sdio_handle_data(struct if_sdio_card *card, 170 + u8 *buffer, unsigned size) 171 + { 172 + int ret; 173 + struct sk_buff *skb; 174 + char *data; 175 + 176 + lbs_deb_enter(LBS_DEB_SDIO); 177 + 178 + if (size > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { 179 + lbs_deb_sdio("response packet too large (%d bytes)\n", 180 + (int)size); 181 + ret = -E2BIG; 182 + goto out; 183 + } 184 + 185 + skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); 186 + if (!skb) { 187 + ret = -ENOMEM; 188 + goto out; 189 + } 190 + 191 + data = skb_put(skb, size); 192 + 193 + memcpy(data, buffer, size); 194 + 195 + libertas_process_rxed_packet(card->priv, skb); 196 + 197 + ret = 0; 198 + 199 + out: 200 + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); 201 + 202 + return ret; 203 + } 204 + 205 + static int if_sdio_handle_event(struct if_sdio_card *card, 206 + u8 *buffer, unsigned size) 207 + { 208 + int ret; 209 + unsigned long flags; 210 + u32 event; 211 + 212 + lbs_deb_enter(LBS_DEB_SDIO); 213 + 214 + if (card->model == 0x04) { 215 + event = sdio_readb(card->func, IF_SDIO_EVENT, &ret); 216 + if (ret) 217 + goto out; 218 + } else { 219 + if (size < 4) { 220 + lbs_deb_sdio("event packet too small (%d bytes)\n", 221 + (int)size); 222 + ret = -EINVAL; 223 + goto out; 224 + } 225 + event = buffer[3] << 24; 226 + event |= buffer[2] << 16; 227 + event |= buffer[1] << 8; 228 + event |= buffer[0] << 0; 229 + event <<= SBI_EVENT_CAUSE_SHIFT; 230 + } 231 + 232 + spin_lock_irqsave(&card->priv->adapter->driver_lock, flags); 233 + 234 + card->event = event; 235 + card->int_cause |= MRVDRV_CARDEVENT; 236 + 237 + libertas_interrupt(card->priv->dev); 238 + 239 + spin_unlock_irqrestore(&card->priv->adapter->driver_lock, flags); 240 + 241 + ret = 0; 242 + 243 + out: 244 + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); 245 + 246 + return ret; 247 + } 248 + 249 + static int if_sdio_card_to_host(struct if_sdio_card *card) 250 + { 251 + int ret; 252 + u8 status; 253 + u16 size, type, chunk; 254 + unsigned long timeout; 255 + 256 + lbs_deb_enter(LBS_DEB_SDIO); 257 + 258 + size = if_sdio_read_scratch(card, &ret); 259 + if (ret) 260 + goto out; 261 + 262 + if (size < 4) { 263 + lbs_deb_sdio("invalid packet size (%d bytes) from firmware\n", 264 + (int)size); 265 + ret = -EINVAL; 266 + goto out; 267 + } 268 + 269 + timeout = jiffies + HZ; 270 + while (1) { 271 + status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); 272 + if (ret) 273 + goto out; 274 + if (status & IF_SDIO_IO_RDY) 275 + break; 276 + if (time_after(jiffies, timeout)) { 277 + ret = -ETIMEDOUT; 278 + goto out; 279 + } 280 + mdelay(1); 281 + } 282 + 283 + /* 284 + * The transfer must be in one transaction or the firmware 285 + * goes suicidal. 286 + */ 287 + chunk = size; 288 + if ((chunk > card->func->cur_blksize) || (chunk > 512)) { 289 + chunk = (chunk + card->func->cur_blksize - 1) / 290 + card->func->cur_blksize * card->func->cur_blksize; 291 + } 292 + 293 + ret = sdio_readsb(card->func, card->buffer, card->ioport, chunk); 294 + if (ret) 295 + goto out; 296 + 297 + chunk = card->buffer[0] | (card->buffer[1] << 8); 298 + type = card->buffer[2] | (card->buffer[3] << 8); 299 + 300 + lbs_deb_sdio("packet of type %d and size %d bytes\n", 301 + (int)type, (int)chunk); 302 + 303 + if (chunk > size) { 304 + lbs_deb_sdio("packet fragment (%d > %d)\n", 305 + (int)chunk, (int)size); 306 + ret = -EINVAL; 307 + goto out; 308 + } 309 + 310 + if (chunk < size) { 311 + lbs_deb_sdio("packet fragment (%d < %d)\n", 312 + (int)chunk, (int)size); 313 + } 314 + 315 + switch (type) { 316 + case MVMS_CMD: 317 + ret = if_sdio_handle_cmd(card, card->buffer + 4, chunk - 4); 318 + if (ret) 319 + goto out; 320 + break; 321 + case MVMS_DAT: 322 + ret = if_sdio_handle_data(card, card->buffer + 4, chunk - 4); 323 + if (ret) 324 + goto out; 325 + break; 326 + case MVMS_EVENT: 327 + ret = if_sdio_handle_event(card, card->buffer + 4, chunk - 4); 328 + if (ret) 329 + goto out; 330 + break; 331 + default: 332 + lbs_deb_sdio("invalid type (%d) from firmware\n", 333 + (int)type); 334 + ret = -EINVAL; 335 + goto out; 336 + } 337 + 338 + out: 339 + if (ret) 340 + lbs_pr_err("problem fetching packet from firmware\n"); 341 + 342 + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); 343 + 344 + return ret; 345 + } 346 + 347 + static void if_sdio_host_to_card_worker(struct work_struct *work) 348 + { 349 + struct if_sdio_card *card; 350 + struct if_sdio_packet *packet; 351 + unsigned long timeout; 352 + u8 status; 353 + int ret; 354 + unsigned long flags; 355 + 356 + lbs_deb_enter(LBS_DEB_SDIO); 357 + 358 + card = container_of(work, struct if_sdio_card, packet_worker); 359 + 360 + while (1) { 361 + spin_lock_irqsave(&card->lock, flags); 362 + packet = card->packets; 363 + if (packet) 364 + card->packets = packet->next; 365 + spin_unlock_irqrestore(&card->lock, flags); 366 + 367 + if (!packet) 368 + break; 369 + 370 + sdio_claim_host(card->func); 371 + 372 + timeout = jiffies + HZ; 373 + while (1) { 374 + status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); 375 + if (ret) 376 + goto release; 377 + if (status & IF_SDIO_IO_RDY) 378 + break; 379 + if (time_after(jiffies, timeout)) { 380 + ret = -ETIMEDOUT; 381 + goto release; 382 + } 383 + mdelay(1); 384 + } 385 + 386 + ret = sdio_writesb(card->func, card->ioport, 387 + packet->buffer, packet->nb); 388 + if (ret) 389 + goto release; 390 + release: 391 + sdio_release_host(card->func); 392 + 393 + kfree(packet); 394 + } 395 + 396 + lbs_deb_leave(LBS_DEB_SDIO); 397 + } 398 + 399 + /********************************************************************/ 400 + /* Firmware */ 401 + /********************************************************************/ 402 + 403 + static int if_sdio_prog_helper(struct if_sdio_card *card) 404 + { 405 + int ret; 406 + u8 status; 407 + const struct firmware *fw; 408 + unsigned long timeout; 409 + u8 *chunk_buffer; 410 + u32 chunk_size; 411 + u8 *firmware; 412 + size_t size; 413 + 414 + lbs_deb_enter(LBS_DEB_SDIO); 415 + 416 + ret = request_firmware(&fw, card->helper, &card->func->dev); 417 + if (ret) { 418 + lbs_pr_err("can't load helper firmware\n"); 419 + goto out; 420 + } 421 + 422 + chunk_buffer = kzalloc(64, GFP_KERNEL); 423 + if (!chunk_buffer) { 424 + ret = -ENOMEM; 425 + goto release_fw; 426 + } 427 + 428 + sdio_claim_host(card->func); 429 + 430 + ret = sdio_set_block_size(card->func, 32); 431 + if (ret) 432 + goto release; 433 + 434 + firmware = fw->data; 435 + size = fw->size; 436 + 437 + while (size) { 438 + timeout = jiffies + HZ; 439 + while (1) { 440 + status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); 441 + if (ret) 442 + goto release; 443 + if ((status & IF_SDIO_IO_RDY) && 444 + (status & IF_SDIO_DL_RDY)) 445 + break; 446 + if (time_after(jiffies, timeout)) { 447 + ret = -ETIMEDOUT; 448 + goto release; 449 + } 450 + mdelay(1); 451 + } 452 + 453 + chunk_size = min(size, (size_t)60); 454 + 455 + *((u32*)chunk_buffer) = cpu_to_le32(chunk_size); 456 + memcpy(chunk_buffer + 4, firmware, chunk_size); 457 + /* 458 + lbs_deb_sdio("sending %d bytes chunk\n", chunk_size); 459 + */ 460 + ret = sdio_writesb(card->func, card->ioport, 461 + chunk_buffer, 64); 462 + if (ret) 463 + goto release; 464 + 465 + firmware += chunk_size; 466 + size -= chunk_size; 467 + } 468 + 469 + /* an empty block marks the end of the transfer */ 470 + memset(chunk_buffer, 0, 4); 471 + ret = sdio_writesb(card->func, card->ioport, chunk_buffer, 64); 472 + if (ret) 473 + goto release; 474 + 475 + lbs_deb_sdio("waiting for helper to boot...\n"); 476 + 477 + /* wait for the helper to boot by looking at the size register */ 478 + timeout = jiffies + HZ; 479 + while (1) { 480 + u16 req_size; 481 + 482 + req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret); 483 + if (ret) 484 + goto release; 485 + 486 + req_size |= sdio_readb(card->func, IF_SDIO_RD_BASE + 1, &ret) << 8; 487 + if (ret) 488 + goto release; 489 + 490 + if (req_size != 0) 491 + break; 492 + 493 + if (time_after(jiffies, timeout)) { 494 + ret = -ETIMEDOUT; 495 + goto release; 496 + } 497 + 498 + msleep(10); 499 + } 500 + 501 + ret = 0; 502 + 503 + release: 504 + sdio_set_block_size(card->func, 0); 505 + sdio_release_host(card->func); 506 + kfree(chunk_buffer); 507 + release_fw: 508 + release_firmware(fw); 509 + 510 + out: 511 + if (ret) 512 + lbs_pr_err("failed to load helper firmware\n"); 513 + 514 + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); 515 + 516 + return ret; 517 + } 518 + 519 + static int if_sdio_prog_real(struct if_sdio_card *card) 520 + { 521 + int ret; 522 + u8 status; 523 + const struct firmware *fw; 524 + unsigned long timeout; 525 + u8 *chunk_buffer; 526 + u32 chunk_size; 527 + u8 *firmware; 528 + size_t size, req_size; 529 + 530 + lbs_deb_enter(LBS_DEB_SDIO); 531 + 532 + ret = request_firmware(&fw, card->firmware, &card->func->dev); 533 + if (ret) { 534 + lbs_pr_err("can't load firmware\n"); 535 + goto out; 536 + } 537 + 538 + chunk_buffer = kzalloc(512, GFP_KERNEL); 539 + if (!chunk_buffer) { 540 + ret = -ENOMEM; 541 + goto release_fw; 542 + } 543 + 544 + sdio_claim_host(card->func); 545 + 546 + ret = sdio_set_block_size(card->func, 32); 547 + if (ret) 548 + goto release; 549 + 550 + firmware = fw->data; 551 + size = fw->size; 552 + 553 + while (size) { 554 + timeout = jiffies + HZ; 555 + while (1) { 556 + status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); 557 + if (ret) 558 + goto release; 559 + if ((status & IF_SDIO_IO_RDY) && 560 + (status & IF_SDIO_DL_RDY)) 561 + break; 562 + if (time_after(jiffies, timeout)) { 563 + ret = -ETIMEDOUT; 564 + goto release; 565 + } 566 + mdelay(1); 567 + } 568 + 569 + req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret); 570 + if (ret) 571 + goto release; 572 + 573 + req_size |= sdio_readb(card->func, IF_SDIO_RD_BASE + 1, &ret) << 8; 574 + if (ret) 575 + goto release; 576 + /* 577 + lbs_deb_sdio("firmware wants %d bytes\n", (int)req_size); 578 + */ 579 + if (req_size == 0) { 580 + lbs_deb_sdio("firmware helper gave up early\n"); 581 + ret = -EIO; 582 + goto release; 583 + } 584 + 585 + if (req_size & 0x01) { 586 + lbs_deb_sdio("firmware helper signalled error\n"); 587 + ret = -EIO; 588 + goto release; 589 + } 590 + 591 + if (req_size > size) 592 + req_size = size; 593 + 594 + while (req_size) { 595 + chunk_size = min(req_size, (size_t)512); 596 + 597 + memcpy(chunk_buffer, firmware, chunk_size); 598 + /* 599 + lbs_deb_sdio("sending %d bytes (%d bytes) chunk\n", 600 + chunk_size, (chunk_size + 31) / 32 * 32); 601 + */ 602 + ret = sdio_writesb(card->func, card->ioport, 603 + chunk_buffer, (chunk_size + 31) / 32 * 32); 604 + if (ret) 605 + goto release; 606 + 607 + firmware += chunk_size; 608 + size -= chunk_size; 609 + req_size -= chunk_size; 610 + } 611 + } 612 + 613 + ret = 0; 614 + 615 + lbs_deb_sdio("waiting for firmware to boot...\n"); 616 + 617 + /* wait for the firmware to boot */ 618 + timeout = jiffies + HZ; 619 + while (1) { 620 + u16 scratch; 621 + 622 + scratch = if_sdio_read_scratch(card, &ret); 623 + if (ret) 624 + goto release; 625 + 626 + if (scratch == IF_SDIO_FIRMWARE_OK) 627 + break; 628 + 629 + if (time_after(jiffies, timeout)) { 630 + ret = -ETIMEDOUT; 631 + goto release; 632 + } 633 + 634 + msleep(10); 635 + } 636 + 637 + ret = 0; 638 + 639 + release: 640 + sdio_set_block_size(card->func, 0); 641 + sdio_release_host(card->func); 642 + kfree(chunk_buffer); 643 + release_fw: 644 + release_firmware(fw); 645 + 646 + out: 647 + if (ret) 648 + lbs_pr_err("failed to load firmware\n"); 649 + 650 + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); 651 + 652 + return ret; 653 + } 654 + 655 + static int if_sdio_prog_firmware(struct if_sdio_card *card) 656 + { 657 + int ret; 658 + u16 scratch; 659 + 660 + lbs_deb_enter(LBS_DEB_SDIO); 661 + 662 + sdio_claim_host(card->func); 663 + scratch = if_sdio_read_scratch(card, &ret); 664 + sdio_release_host(card->func); 665 + 666 + if (ret) 667 + goto out; 668 + 669 + if (scratch == IF_SDIO_FIRMWARE_OK) { 670 + lbs_deb_sdio("firmware already loaded\n"); 671 + goto success; 672 + } 673 + 674 + ret = if_sdio_prog_helper(card); 675 + if (ret) 676 + goto out; 677 + 678 + ret = if_sdio_prog_real(card); 679 + if (ret) 680 + goto out; 681 + 682 + success: 683 + ret = 0; 684 + 685 + out: 686 + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); 687 + 688 + return ret; 689 + } 690 + 691 + /*******************************************************************/ 692 + /* Libertas callbacks */ 693 + /*******************************************************************/ 694 + 695 + static int if_sdio_host_to_card(wlan_private *priv, u8 type, u8 *buf, u16 nb) 696 + { 697 + int ret; 698 + struct if_sdio_card *card; 699 + struct if_sdio_packet *packet, *cur; 700 + u16 size; 701 + unsigned long flags; 702 + 703 + lbs_deb_enter_args(LBS_DEB_SDIO, "type %d, bytes %d", type, nb); 704 + 705 + card = priv->card; 706 + 707 + if (nb > (65536 - sizeof(struct if_sdio_packet) - 4)) { 708 + ret = -EINVAL; 709 + goto out; 710 + } 711 + 712 + /* 713 + * The transfer must be in one transaction or the firmware 714 + * goes suicidal. 715 + */ 716 + size = nb + 4; 717 + if ((size > card->func->cur_blksize) || (size > 512)) { 718 + size = (size + card->func->cur_blksize - 1) / 719 + card->func->cur_blksize * card->func->cur_blksize; 720 + } 721 + 722 + packet = kzalloc(sizeof(struct if_sdio_packet) + size, 723 + GFP_ATOMIC); 724 + if (!packet) { 725 + ret = -ENOMEM; 726 + goto out; 727 + } 728 + 729 + packet->next = NULL; 730 + packet->nb = size; 731 + 732 + /* 733 + * SDIO specific header. 734 + */ 735 + packet->buffer[0] = (nb + 4) & 0xff; 736 + packet->buffer[1] = ((nb + 4) >> 8) & 0xff; 737 + packet->buffer[2] = type; 738 + packet->buffer[3] = 0; 739 + 740 + memcpy(packet->buffer + 4, buf, nb); 741 + 742 + spin_lock_irqsave(&card->lock, flags); 743 + 744 + if (!card->packets) 745 + card->packets = packet; 746 + else { 747 + cur = card->packets; 748 + while (cur->next) 749 + cur = cur->next; 750 + cur->next = packet; 751 + } 752 + 753 + switch (type) { 754 + case MVMS_CMD: 755 + priv->dnld_sent = DNLD_CMD_SENT; 756 + break; 757 + case MVMS_DAT: 758 + priv->dnld_sent = DNLD_DATA_SENT; 759 + break; 760 + default: 761 + lbs_deb_sdio("unknown packet type %d\n", (int)type); 762 + } 763 + 764 + spin_unlock_irqrestore(&card->lock, flags); 765 + 766 + schedule_work(&card->packet_worker); 767 + 768 + ret = 0; 769 + 770 + out: 771 + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); 772 + 773 + return ret; 774 + } 775 + 776 + static int if_sdio_get_int_status(wlan_private *priv, u8 *ireg) 777 + { 778 + struct if_sdio_card *card; 779 + 780 + lbs_deb_enter(LBS_DEB_SDIO); 781 + 782 + card = priv->card; 783 + 784 + *ireg = card->int_cause; 785 + card->int_cause = 0; 786 + 787 + lbs_deb_leave(LBS_DEB_SDIO); 788 + 789 + return 0; 790 + } 791 + 792 + static int if_sdio_read_event_cause(wlan_private *priv) 793 + { 794 + struct if_sdio_card *card; 795 + 796 + lbs_deb_enter(LBS_DEB_SDIO); 797 + 798 + card = priv->card; 799 + 800 + priv->adapter->eventcause = card->event; 801 + 802 + lbs_deb_leave(LBS_DEB_SDIO); 803 + 804 + return 0; 805 + } 806 + 807 + /*******************************************************************/ 808 + /* SDIO callbacks */ 809 + /*******************************************************************/ 810 + 811 + static void if_sdio_interrupt(struct sdio_func *func) 812 + { 813 + int ret; 814 + struct if_sdio_card *card; 815 + u8 cause; 816 + 817 + lbs_deb_enter(LBS_DEB_SDIO); 818 + 819 + card = sdio_get_drvdata(func); 820 + 821 + cause = sdio_readb(card->func, IF_SDIO_H_INT_STATUS, &ret); 822 + if (ret) 823 + goto out; 824 + 825 + lbs_deb_sdio("interrupt: 0x%X\n", (unsigned)cause); 826 + 827 + sdio_writeb(card->func, ~cause, IF_SDIO_H_INT_STATUS, &ret); 828 + if (ret) 829 + goto out; 830 + 831 + /* 832 + * Ignore the define name, this really means the card has 833 + * successfully received the command. 834 + */ 835 + if (cause & IF_SDIO_H_INT_DNLD) { 836 + if ((card->priv->dnld_sent == DNLD_DATA_SENT) && 837 + (card->priv->adapter->connect_status == LIBERTAS_CONNECTED)) 838 + netif_wake_queue(card->priv->dev); 839 + card->priv->dnld_sent = DNLD_RES_RECEIVED; 840 + } 841 + 842 + if (cause & IF_SDIO_H_INT_UPLD) { 843 + ret = if_sdio_card_to_host(card); 844 + if (ret) 845 + goto out; 846 + } 847 + 848 + ret = 0; 849 + 850 + out: 851 + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); 852 + } 853 + 854 + static int if_sdio_probe(struct sdio_func *func, 855 + const struct sdio_device_id *id) 856 + { 857 + struct if_sdio_card *card; 858 + wlan_private *priv; 859 + int ret, i; 860 + unsigned int model; 861 + struct if_sdio_packet *packet; 862 + 863 + lbs_deb_enter(LBS_DEB_SDIO); 864 + 865 + for (i = 0;i < func->card->num_info;i++) { 866 + if (sscanf(func->card->info[i], 867 + "802.11 SDIO ID: %x", &model) == 1) 868 + break; 869 + if (sscanf(func->card->info[i], 870 + "ID: %x", &model) == 1) 871 + break; 872 + } 873 + 874 + if (i == func->card->num_info) { 875 + lbs_pr_err("unable to identify card model\n"); 876 + return -ENODEV; 877 + } 878 + 879 + card = kzalloc(sizeof(struct if_sdio_card), GFP_KERNEL); 880 + if (!card) 881 + return -ENOMEM; 882 + 883 + card->func = func; 884 + card->model = model; 885 + spin_lock_init(&card->lock); 886 + INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); 887 + 888 + for (i = 0;i < ARRAY_SIZE(if_sdio_models);i++) { 889 + if (card->model == if_sdio_models[i].model) 890 + break; 891 + } 892 + 893 + if (i == ARRAY_SIZE(if_sdio_models)) { 894 + lbs_pr_err("unkown card model 0x%x\n", card->model); 895 + ret = -ENODEV; 896 + goto free; 897 + } 898 + 899 + card->helper = if_sdio_models[i].helper; 900 + card->firmware = if_sdio_models[i].firmware; 901 + 902 + if (libertas_helper_name) { 903 + lbs_deb_sdio("overriding helper firmware: %s\n", 904 + libertas_helper_name); 905 + card->helper = libertas_helper_name; 906 + } 907 + 908 + if (libertas_fw_name) { 909 + lbs_deb_sdio("overriding firmware: %s\n", libertas_fw_name); 910 + card->firmware = libertas_fw_name; 911 + } 912 + 913 + sdio_claim_host(func); 914 + 915 + ret = sdio_enable_func(func); 916 + if (ret) 917 + goto release; 918 + 919 + ret = sdio_claim_irq(func, if_sdio_interrupt); 920 + if (ret) 921 + goto disable; 922 + 923 + card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret); 924 + if (ret) 925 + goto release_int; 926 + 927 + card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8; 928 + if (ret) 929 + goto release_int; 930 + 931 + card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16; 932 + if (ret) 933 + goto release_int; 934 + 935 + sdio_release_host(func); 936 + 937 + sdio_set_drvdata(func, card); 938 + 939 + lbs_deb_sdio("class = 0x%X, vendor = 0x%X, " 940 + "device = 0x%X, model = 0x%X, ioport = 0x%X\n", 941 + func->class, func->vendor, func->device, 942 + model, (unsigned)card->ioport); 943 + 944 + ret = if_sdio_prog_firmware(card); 945 + if (ret) 946 + goto reclaim; 947 + 948 + priv = libertas_add_card(card, &func->dev); 949 + if (!priv) { 950 + ret = -ENOMEM; 951 + goto reclaim; 952 + } 953 + 954 + card->priv = priv; 955 + 956 + priv->card = card; 957 + priv->hw_host_to_card = if_sdio_host_to_card; 958 + priv->hw_get_int_status = if_sdio_get_int_status; 959 + priv->hw_read_event_cause = if_sdio_read_event_cause; 960 + 961 + priv->adapter->fw_ready = 1; 962 + 963 + /* 964 + * Enable interrupts now that everything is set up 965 + */ 966 + sdio_claim_host(func); 967 + sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret); 968 + sdio_release_host(func); 969 + if (ret) 970 + goto reclaim; 971 + 972 + ret = libertas_start_card(priv); 973 + if (ret) 974 + goto err_activate_card; 975 + 976 + out: 977 + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); 978 + 979 + return ret; 980 + 981 + err_activate_card: 982 + flush_scheduled_work(); 983 + free_netdev(priv->dev); 984 + kfree(priv->adapter); 985 + reclaim: 986 + sdio_claim_host(func); 987 + release_int: 988 + sdio_release_irq(func); 989 + disable: 990 + sdio_disable_func(func); 991 + release: 992 + sdio_release_host(func); 993 + free: 994 + while (card->packets) { 995 + packet = card->packets; 996 + card->packets = card->packets->next; 997 + kfree(packet); 998 + } 999 + 1000 + kfree(card); 1001 + 1002 + goto out; 1003 + } 1004 + 1005 + static void if_sdio_remove(struct sdio_func *func) 1006 + { 1007 + struct if_sdio_card *card; 1008 + struct if_sdio_packet *packet; 1009 + 1010 + lbs_deb_enter(LBS_DEB_SDIO); 1011 + 1012 + card = sdio_get_drvdata(func); 1013 + 1014 + card->priv->adapter->surpriseremoved = 1; 1015 + 1016 + lbs_deb_sdio("call remove card\n"); 1017 + libertas_stop_card(card->priv); 1018 + libertas_remove_card(card->priv); 1019 + 1020 + flush_scheduled_work(); 1021 + 1022 + sdio_claim_host(func); 1023 + sdio_release_irq(func); 1024 + sdio_disable_func(func); 1025 + sdio_release_host(func); 1026 + 1027 + while (card->packets) { 1028 + packet = card->packets; 1029 + card->packets = card->packets->next; 1030 + kfree(packet); 1031 + } 1032 + 1033 + kfree(card); 1034 + 1035 + lbs_deb_leave(LBS_DEB_SDIO); 1036 + } 1037 + 1038 + static struct sdio_driver if_sdio_driver = { 1039 + .name = "libertas_sdio", 1040 + .id_table = if_sdio_ids, 1041 + .probe = if_sdio_probe, 1042 + .remove = if_sdio_remove, 1043 + }; 1044 + 1045 + /*******************************************************************/ 1046 + /* Module functions */ 1047 + /*******************************************************************/ 1048 + 1049 + static int if_sdio_init_module(void) 1050 + { 1051 + int ret = 0; 1052 + 1053 + lbs_deb_enter(LBS_DEB_SDIO); 1054 + 1055 + printk(KERN_INFO "libertas_sdio: Libertas SDIO driver\n"); 1056 + printk(KERN_INFO "libertas_sdio: Copyright Pierre Ossman\n"); 1057 + 1058 + ret = sdio_register_driver(&if_sdio_driver); 1059 + 1060 + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); 1061 + 1062 + return ret; 1063 + } 1064 + 1065 + static void if_sdio_exit_module(void) 1066 + { 1067 + lbs_deb_enter(LBS_DEB_SDIO); 1068 + 1069 + sdio_unregister_driver(&if_sdio_driver); 1070 + 1071 + lbs_deb_leave(LBS_DEB_SDIO); 1072 + } 1073 + 1074 + module_init(if_sdio_init_module); 1075 + module_exit(if_sdio_exit_module); 1076 + 1077 + MODULE_DESCRIPTION("Libertas SDIO WLAN Driver"); 1078 + MODULE_AUTHOR("Pierre Ossman"); 1079 + MODULE_LICENSE("GPL");
+45
drivers/net/wireless/libertas/if_sdio.h
··· 1 + /* 2 + * linux/drivers/net/wireless/libertas/if_sdio.h 3 + * 4 + * Copyright 2007 Pierre Ossman 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or (at 9 + * your option) any later version. 10 + */ 11 + 12 + #ifndef LIBERTAS_IF_SDIO_H 13 + #define LIBERTAS_IF_SDIO_H 14 + 15 + #define IF_SDIO_IOPORT 0x00 16 + 17 + #define IF_SDIO_H_INT_MASK 0x04 18 + #define IF_SDIO_H_INT_OFLOW 0x08 19 + #define IF_SDIO_H_INT_UFLOW 0x04 20 + #define IF_SDIO_H_INT_DNLD 0x02 21 + #define IF_SDIO_H_INT_UPLD 0x01 22 + 23 + #define IF_SDIO_H_INT_STATUS 0x05 24 + #define IF_SDIO_H_INT_RSR 0x06 25 + #define IF_SDIO_H_INT_STATUS2 0x07 26 + 27 + #define IF_SDIO_RD_BASE 0x10 28 + 29 + #define IF_SDIO_STATUS 0x20 30 + #define IF_SDIO_IO_RDY 0x08 31 + #define IF_SDIO_CIS_RDY 0x04 32 + #define IF_SDIO_UL_RDY 0x02 33 + #define IF_SDIO_DL_RDY 0x01 34 + 35 + #define IF_SDIO_C_INT_MASK 0x24 36 + #define IF_SDIO_C_INT_STATUS 0x28 37 + #define IF_SDIO_C_INT_RSR 0x2C 38 + 39 + #define IF_SDIO_SCRATCH 0x34 40 + #define IF_SDIO_SCRATCH_OLD 0x80fe 41 + #define IF_SDIO_FIRMWARE_OK 0xfedc 42 + 43 + #define IF_SDIO_EVENT 0x80fc 44 + 45 + #endif
+6
include/linux/mmc/sdio_ids.h
··· 19 19 #define SDIO_CLASS_WLAN 0x07 /* WLAN interface */ 20 20 #define SDIO_CLASS_ATA 0x08 /* Embedded SDIO-ATA std interface */ 21 21 22 + /* 23 + * Vendors and devices. Sort key: vendor first, device next. 24 + */ 25 + 26 + #define SDIO_VENDOR_ID_MARVELL 0x02df 27 + #define SDIO_DEVICE_ID_MARVELL_LIBERTAS 0x9103 22 28 23 29 #endif