diff options
Diffstat (limited to 'drivers/net/wireless/libertas/if_sdio.c')
-rw-r--r-- | drivers/net/wireless/libertas/if_sdio.c | 127 |
1 files changed, 64 insertions, 63 deletions
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 7d1a3c6b6ce0..64dd345d30f5 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -35,6 +35,8 @@ | |||
35 | #include <linux/mmc/card.h> | 35 | #include <linux/mmc/card.h> |
36 | #include <linux/mmc/sdio_func.h> | 36 | #include <linux/mmc/sdio_func.h> |
37 | #include <linux/mmc/sdio_ids.h> | 37 | #include <linux/mmc/sdio_ids.h> |
38 | #include <linux/mmc/sdio.h> | ||
39 | #include <linux/mmc/host.h> | ||
38 | 40 | ||
39 | #include "host.h" | 41 | #include "host.h" |
40 | #include "decl.h" | 42 | #include "decl.h" |
@@ -313,12 +315,30 @@ out: | |||
313 | return ret; | 315 | return ret; |
314 | } | 316 | } |
315 | 317 | ||
318 | static int if_sdio_wait_status(struct if_sdio_card *card, const u8 condition) | ||
319 | { | ||
320 | u8 status; | ||
321 | unsigned long timeout; | ||
322 | int ret = 0; | ||
323 | |||
324 | timeout = jiffies + HZ; | ||
325 | while (1) { | ||
326 | status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); | ||
327 | if (ret) | ||
328 | return ret; | ||
329 | if ((status & condition) == condition) | ||
330 | break; | ||
331 | if (time_after(jiffies, timeout)) | ||
332 | return -ETIMEDOUT; | ||
333 | mdelay(1); | ||
334 | } | ||
335 | return ret; | ||
336 | } | ||
337 | |||
316 | static int if_sdio_card_to_host(struct if_sdio_card *card) | 338 | static int if_sdio_card_to_host(struct if_sdio_card *card) |
317 | { | 339 | { |
318 | int ret; | 340 | int ret; |
319 | u8 status; | ||
320 | u16 size, type, chunk; | 341 | u16 size, type, chunk; |
321 | unsigned long timeout; | ||
322 | 342 | ||
323 | lbs_deb_enter(LBS_DEB_SDIO); | 343 | lbs_deb_enter(LBS_DEB_SDIO); |
324 | 344 | ||
@@ -333,19 +353,9 @@ static int if_sdio_card_to_host(struct if_sdio_card *card) | |||
333 | goto out; | 353 | goto out; |
334 | } | 354 | } |
335 | 355 | ||
336 | timeout = jiffies + HZ; | 356 | ret = if_sdio_wait_status(card, IF_SDIO_IO_RDY); |
337 | while (1) { | 357 | if (ret) |
338 | status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); | 358 | goto out; |
339 | if (ret) | ||
340 | goto out; | ||
341 | if (status & IF_SDIO_IO_RDY) | ||
342 | break; | ||
343 | if (time_after(jiffies, timeout)) { | ||
344 | ret = -ETIMEDOUT; | ||
345 | goto out; | ||
346 | } | ||
347 | mdelay(1); | ||
348 | } | ||
349 | 359 | ||
350 | /* | 360 | /* |
351 | * The transfer must be in one transaction or the firmware | 361 | * The transfer must be in one transaction or the firmware |
@@ -412,8 +422,6 @@ static void if_sdio_host_to_card_worker(struct work_struct *work) | |||
412 | { | 422 | { |
413 | struct if_sdio_card *card; | 423 | struct if_sdio_card *card; |
414 | struct if_sdio_packet *packet; | 424 | struct if_sdio_packet *packet; |
415 | unsigned long timeout; | ||
416 | u8 status; | ||
417 | int ret; | 425 | int ret; |
418 | unsigned long flags; | 426 | unsigned long flags; |
419 | 427 | ||
@@ -433,25 +441,15 @@ static void if_sdio_host_to_card_worker(struct work_struct *work) | |||
433 | 441 | ||
434 | sdio_claim_host(card->func); | 442 | sdio_claim_host(card->func); |
435 | 443 | ||
436 | timeout = jiffies + HZ; | 444 | ret = if_sdio_wait_status(card, IF_SDIO_IO_RDY); |
437 | while (1) { | 445 | if (ret == 0) { |
438 | status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); | 446 | ret = sdio_writesb(card->func, card->ioport, |
439 | if (ret) | 447 | packet->buffer, packet->nb); |
440 | goto release; | ||
441 | if (status & IF_SDIO_IO_RDY) | ||
442 | break; | ||
443 | if (time_after(jiffies, timeout)) { | ||
444 | ret = -ETIMEDOUT; | ||
445 | goto release; | ||
446 | } | ||
447 | mdelay(1); | ||
448 | } | 448 | } |
449 | 449 | ||
450 | ret = sdio_writesb(card->func, card->ioport, | ||
451 | packet->buffer, packet->nb); | ||
452 | if (ret) | 450 | if (ret) |
453 | goto release; | 451 | lbs_pr_err("error %d sending packet to firmware\n", ret); |
454 | release: | 452 | |
455 | sdio_release_host(card->func); | 453 | sdio_release_host(card->func); |
456 | 454 | ||
457 | kfree(packet); | 455 | kfree(packet); |
@@ -464,10 +462,11 @@ release: | |||
464 | /* Firmware */ | 462 | /* Firmware */ |
465 | /********************************************************************/ | 463 | /********************************************************************/ |
466 | 464 | ||
465 | #define FW_DL_READY_STATUS (IF_SDIO_IO_RDY | IF_SDIO_DL_RDY) | ||
466 | |||
467 | static int if_sdio_prog_helper(struct if_sdio_card *card) | 467 | static int if_sdio_prog_helper(struct if_sdio_card *card) |
468 | { | 468 | { |
469 | int ret; | 469 | int ret; |
470 | u8 status; | ||
471 | const struct firmware *fw; | 470 | const struct firmware *fw; |
472 | unsigned long timeout; | 471 | unsigned long timeout; |
473 | u8 *chunk_buffer; | 472 | u8 *chunk_buffer; |
@@ -499,20 +498,14 @@ static int if_sdio_prog_helper(struct if_sdio_card *card) | |||
499 | size = fw->size; | 498 | size = fw->size; |
500 | 499 | ||
501 | while (size) { | 500 | while (size) { |
502 | timeout = jiffies + HZ; | 501 | ret = if_sdio_wait_status(card, FW_DL_READY_STATUS); |
503 | while (1) { | 502 | if (ret) |
504 | status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); | 503 | goto release; |
505 | if (ret) | 504 | |
506 | goto release; | 505 | /* On some platforms (like Davinci) the chip needs more time |
507 | if ((status & IF_SDIO_IO_RDY) && | 506 | * between helper blocks. |
508 | (status & IF_SDIO_DL_RDY)) | 507 | */ |
509 | break; | 508 | mdelay(2); |
510 | if (time_after(jiffies, timeout)) { | ||
511 | ret = -ETIMEDOUT; | ||
512 | goto release; | ||
513 | } | ||
514 | mdelay(1); | ||
515 | } | ||
516 | 509 | ||
517 | chunk_size = min(size, (size_t)60); | 510 | chunk_size = min(size, (size_t)60); |
518 | 511 | ||
@@ -582,7 +575,6 @@ out: | |||
582 | static int if_sdio_prog_real(struct if_sdio_card *card) | 575 | static int if_sdio_prog_real(struct if_sdio_card *card) |
583 | { | 576 | { |
584 | int ret; | 577 | int ret; |
585 | u8 status; | ||
586 | const struct firmware *fw; | 578 | const struct firmware *fw; |
587 | unsigned long timeout; | 579 | unsigned long timeout; |
588 | u8 *chunk_buffer; | 580 | u8 *chunk_buffer; |
@@ -614,20 +606,9 @@ static int if_sdio_prog_real(struct if_sdio_card *card) | |||
614 | size = fw->size; | 606 | size = fw->size; |
615 | 607 | ||
616 | while (size) { | 608 | while (size) { |
617 | timeout = jiffies + HZ; | 609 | ret = if_sdio_wait_status(card, FW_DL_READY_STATUS); |
618 | while (1) { | 610 | if (ret) |
619 | status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); | 611 | goto release; |
620 | if (ret) | ||
621 | goto release; | ||
622 | if ((status & IF_SDIO_IO_RDY) && | ||
623 | (status & IF_SDIO_DL_RDY)) | ||
624 | break; | ||
625 | if (time_after(jiffies, timeout)) { | ||
626 | ret = -ETIMEDOUT; | ||
627 | goto release; | ||
628 | } | ||
629 | mdelay(1); | ||
630 | } | ||
631 | 612 | ||
632 | req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret); | 613 | req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret); |
633 | if (ret) | 614 | if (ret) |
@@ -943,6 +924,7 @@ static int if_sdio_probe(struct sdio_func *func, | |||
943 | int ret, i; | 924 | int ret, i; |
944 | unsigned int model; | 925 | unsigned int model; |
945 | struct if_sdio_packet *packet; | 926 | struct if_sdio_packet *packet; |
927 | struct mmc_host *host = func->card->host; | ||
946 | 928 | ||
947 | lbs_deb_enter(LBS_DEB_SDIO); | 929 | lbs_deb_enter(LBS_DEB_SDIO); |
948 | 930 | ||
@@ -1023,6 +1005,25 @@ static int if_sdio_probe(struct sdio_func *func, | |||
1023 | if (ret) | 1005 | if (ret) |
1024 | goto disable; | 1006 | goto disable; |
1025 | 1007 | ||
1008 | /* For 1-bit transfers to the 8686 model, we need to enable the | ||
1009 | * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 | ||
1010 | * bit to allow access to non-vendor registers. */ | ||
1011 | if ((card->model == IF_SDIO_MODEL_8686) && | ||
1012 | (host->caps & MMC_CAP_SDIO_IRQ) && | ||
1013 | (host->ios.bus_width == MMC_BUS_WIDTH_1)) { | ||
1014 | u8 reg; | ||
1015 | |||
1016 | func->card->quirks |= MMC_QUIRK_LENIENT_FN0; | ||
1017 | reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret); | ||
1018 | if (ret) | ||
1019 | goto release_int; | ||
1020 | |||
1021 | reg |= SDIO_BUS_ECSI; | ||
1022 | sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret); | ||
1023 | if (ret) | ||
1024 | goto release_int; | ||
1025 | } | ||
1026 | |||
1026 | card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret); | 1027 | card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret); |
1027 | if (ret) | 1028 | if (ret) |
1028 | goto release_int; | 1029 | goto release_int; |