diff options
| -rw-r--r-- | drivers/net/wireless/libertas/if_sdio.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 296fd00a5129..e5685dc317a8 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
| @@ -684,18 +684,40 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) | |||
| 684 | 684 | ||
| 685 | lbs_deb_enter(LBS_DEB_SDIO); | 685 | lbs_deb_enter(LBS_DEB_SDIO); |
| 686 | 686 | ||
| 687 | /* | ||
| 688 | * Disable interrupts | ||
| 689 | */ | ||
| 690 | sdio_claim_host(card->func); | ||
| 691 | sdio_writeb(card->func, 0x00, IF_SDIO_H_INT_MASK, &ret); | ||
| 692 | sdio_release_host(card->func); | ||
| 693 | |||
| 687 | sdio_claim_host(card->func); | 694 | sdio_claim_host(card->func); |
| 688 | scratch = if_sdio_read_scratch(card, &ret); | 695 | scratch = if_sdio_read_scratch(card, &ret); |
| 689 | sdio_release_host(card->func); | 696 | sdio_release_host(card->func); |
| 690 | 697 | ||
| 698 | lbs_deb_sdio("firmware status = %#x\n", scratch); | ||
| 699 | lbs_deb_sdio("scratch ret = %d\n", ret); | ||
| 700 | |||
| 691 | if (ret) | 701 | if (ret) |
| 692 | goto out; | 702 | goto out; |
| 693 | 703 | ||
| 694 | lbs_deb_sdio("firmware status = %#x\n", scratch); | ||
| 695 | 704 | ||
| 705 | /* | ||
| 706 | * The manual clearly describes that FEDC is the right code to use | ||
| 707 | * to detect firmware presence, but for SD8686 it is not that simple. | ||
| 708 | * Scratch is also used to store the RX packet length, so we lose | ||
| 709 | * the FEDC value early on. So we use a non-zero check in order | ||
| 710 | * to validate firmware presence. | ||
| 711 | * Additionally, the SD8686 in the Gumstix always has the high scratch | ||
| 712 | * bit set, even when the firmware is not loaded. So we have to | ||
| 713 | * exclude that from the test. | ||
| 714 | */ | ||
| 696 | if (scratch == IF_SDIO_FIRMWARE_OK) { | 715 | if (scratch == IF_SDIO_FIRMWARE_OK) { |
| 697 | lbs_deb_sdio("firmware already loaded\n"); | 716 | lbs_deb_sdio("firmware already loaded\n"); |
| 698 | goto success; | 717 | goto success; |
| 718 | } else if ((card->model == MODEL_8686) && (scratch & 0x7fff)) { | ||
| 719 | lbs_deb_sdio("firmware may be running\n"); | ||
| 720 | goto success; | ||
| 699 | } | 721 | } |
| 700 | 722 | ||
| 701 | ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name, | 723 | ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name, |
| @@ -709,10 +731,14 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) | |||
| 709 | if (ret) | 731 | if (ret) |
| 710 | goto out; | 732 | goto out; |
| 711 | 733 | ||
| 734 | lbs_deb_sdio("Helper firmware loaded\n"); | ||
| 735 | |||
| 712 | ret = if_sdio_prog_real(card, mainfw); | 736 | ret = if_sdio_prog_real(card, mainfw); |
| 713 | if (ret) | 737 | if (ret) |
| 714 | goto out; | 738 | goto out; |
| 715 | 739 | ||
| 740 | lbs_deb_sdio("Firmware loaded\n"); | ||
| 741 | |||
| 716 | success: | 742 | success: |
| 717 | sdio_claim_host(card->func); | 743 | sdio_claim_host(card->func); |
| 718 | sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE); | 744 | sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE); |
| @@ -1042,8 +1068,6 @@ static int if_sdio_probe(struct sdio_func *func, | |||
| 1042 | priv->exit_deep_sleep = if_sdio_exit_deep_sleep; | 1068 | priv->exit_deep_sleep = if_sdio_exit_deep_sleep; |
| 1043 | priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup; | 1069 | priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup; |
| 1044 | 1070 | ||
| 1045 | priv->fw_ready = 1; | ||
| 1046 | |||
| 1047 | sdio_claim_host(func); | 1071 | sdio_claim_host(func); |
| 1048 | 1072 | ||
| 1049 | /* | 1073 | /* |
| @@ -1064,6 +1088,8 @@ static int if_sdio_probe(struct sdio_func *func, | |||
| 1064 | if (ret) | 1088 | if (ret) |
| 1065 | goto reclaim; | 1089 | goto reclaim; |
| 1066 | 1090 | ||
| 1091 | priv->fw_ready = 1; | ||
| 1092 | |||
| 1067 | /* | 1093 | /* |
| 1068 | * FUNC_INIT is required for SD8688 WLAN/BT multiple functions | 1094 | * FUNC_INIT is required for SD8688 WLAN/BT multiple functions |
| 1069 | */ | 1095 | */ |
