aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Fox <pgf@laptop.org>2010-10-29 09:57:28 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-10-29 14:33:25 -0400
commit731b2034999bbfe86c9074f1b0d611940bf7c323 (patch)
tree6ef7cf2f32e0352242fb06fad132722546eb1980
parent4fc4fbd1d9a05fa4f348b499aca3a6f8d3c9bbe6 (diff)
libertas: Fix sd8686 firmware reload
For the SD8686, we cannot rely on the scratch register to read the firmware load status, because the same register is used for storing RX packet length. Broaden the check to account for this. The module can now be unloaded/reloaded successfully. Based on the implementation from libertas_tf. Signed-off-by: Daniel Drake <dsd@laptop.org> Acked-by: Dan Williams <dcbw@redhat.com> Signed-off-by: Steve deRosier <steve@cozybit.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c32
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 296fd00a512..e5685dc317a 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
716success: 742success:
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 */