aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/if_sdio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas/if_sdio.c')
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c229
1 files changed, 121 insertions, 108 deletions
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 9804ebc892d4..76caebaa4397 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -65,12 +65,6 @@ static void if_sdio_interrupt(struct sdio_func *func);
65 */ 65 */
66static u8 user_rmmod; 66static u8 user_rmmod;
67 67
68static char *lbs_helper_name = NULL;
69module_param_named(helper_name, lbs_helper_name, charp, 0644);
70
71static char *lbs_fw_name = NULL;
72module_param_named(fw_name, lbs_fw_name, charp, 0644);
73
74static const struct sdio_device_id if_sdio_ids[] = { 68static const struct sdio_device_id if_sdio_ids[] = {
75 { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 69 { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL,
76 SDIO_DEVICE_ID_MARVELL_LIBERTAS) }, 70 SDIO_DEVICE_ID_MARVELL_LIBERTAS) },
@@ -123,11 +117,8 @@ struct if_sdio_card {
123 int model; 117 int model;
124 unsigned long ioport; 118 unsigned long ioport;
125 unsigned int scratch_reg; 119 unsigned int scratch_reg;
126 120 bool started;
127 const char *helper; 121 wait_queue_head_t pwron_waitq;
128 const char *firmware;
129 bool helper_allocated;
130 bool firmware_allocated;
131 122
132 u8 buffer[65536] __attribute__((aligned(4))); 123 u8 buffer[65536] __attribute__((aligned(4)));
133 124
@@ -140,6 +131,9 @@ struct if_sdio_card {
140 u8 rx_unit; 131 u8 rx_unit;
141}; 132};
142 133
134static void if_sdio_finish_power_on(struct if_sdio_card *card);
135static int if_sdio_power_off(struct if_sdio_card *card);
136
143/********************************************************************/ 137/********************************************************************/
144/* I/O */ 138/* I/O */
145/********************************************************************/ 139/********************************************************************/
@@ -680,12 +674,39 @@ out:
680 return ret; 674 return ret;
681} 675}
682 676
677static void if_sdio_do_prog_firmware(struct lbs_private *priv, int ret,
678 const struct firmware *helper,
679 const struct firmware *mainfw)
680{
681 struct if_sdio_card *card = priv->card;
682
683 if (ret) {
684 pr_err("failed to find firmware (%d)\n", ret);
685 return;
686 }
687
688 ret = if_sdio_prog_helper(card, helper);
689 if (ret)
690 goto out;
691
692 lbs_deb_sdio("Helper firmware loaded\n");
693
694 ret = if_sdio_prog_real(card, mainfw);
695 if (ret)
696 goto out;
697
698 lbs_deb_sdio("Firmware loaded\n");
699 if_sdio_finish_power_on(card);
700
701out:
702 release_firmware(helper);
703 release_firmware(mainfw);
704}
705
683static int if_sdio_prog_firmware(struct if_sdio_card *card) 706static int if_sdio_prog_firmware(struct if_sdio_card *card)
684{ 707{
685 int ret; 708 int ret;
686 u16 scratch; 709 u16 scratch;
687 const struct firmware *helper = NULL;
688 const struct firmware *mainfw = NULL;
689 710
690 lbs_deb_enter(LBS_DEB_SDIO); 711 lbs_deb_enter(LBS_DEB_SDIO);
691 712
@@ -719,43 +740,18 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
719 */ 740 */
720 if (scratch == IF_SDIO_FIRMWARE_OK) { 741 if (scratch == IF_SDIO_FIRMWARE_OK) {
721 lbs_deb_sdio("firmware already loaded\n"); 742 lbs_deb_sdio("firmware already loaded\n");
722 goto success; 743 if_sdio_finish_power_on(card);
744 return 0;
723 } else if ((card->model == MODEL_8686) && (scratch & 0x7fff)) { 745 } else if ((card->model == MODEL_8686) && (scratch & 0x7fff)) {
724 lbs_deb_sdio("firmware may be running\n"); 746 lbs_deb_sdio("firmware may be running\n");
725 goto success; 747 if_sdio_finish_power_on(card);
726 } 748 return 0;
727
728 ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name,
729 card->model, &fw_table[0], &helper, &mainfw);
730 if (ret) {
731 pr_err("failed to find firmware (%d)\n", ret);
732 goto out;
733 } 749 }
734 750
735 ret = if_sdio_prog_helper(card, helper); 751 ret = lbs_get_firmware_async(card->priv, &card->func->dev, card->model,
736 if (ret) 752 fw_table, if_sdio_do_prog_firmware);
737 goto out;
738
739 lbs_deb_sdio("Helper firmware loaded\n");
740
741 ret = if_sdio_prog_real(card, mainfw);
742 if (ret)
743 goto out;
744
745 lbs_deb_sdio("Firmware loaded\n");
746
747success:
748 sdio_claim_host(card->func);
749 sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE);
750 sdio_release_host(card->func);
751 ret = 0;
752 753
753out: 754out:
754 if (helper)
755 release_firmware(helper);
756 if (mainfw)
757 release_firmware(mainfw);
758
759 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); 755 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
760 return ret; 756 return ret;
761} 757}
@@ -764,55 +760,15 @@ out:
764/* Power management */ 760/* Power management */
765/********************************************************************/ 761/********************************************************************/
766 762
767static int if_sdio_power_on(struct if_sdio_card *card) 763/* Finish power on sequence (after firmware is loaded) */
764static void if_sdio_finish_power_on(struct if_sdio_card *card)
768{ 765{
769 struct sdio_func *func = card->func; 766 struct sdio_func *func = card->func;
770 struct lbs_private *priv = card->priv; 767 struct lbs_private *priv = card->priv;
771 struct mmc_host *host = func->card->host;
772 int ret; 768 int ret;
773 769
774 sdio_claim_host(func); 770 sdio_claim_host(func);
775 771 sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE);
776 ret = sdio_enable_func(func);
777 if (ret)
778 goto release;
779
780 /* For 1-bit transfers to the 8686 model, we need to enable the
781 * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
782 * bit to allow access to non-vendor registers. */
783 if ((card->model == MODEL_8686) &&
784 (host->caps & MMC_CAP_SDIO_IRQ) &&
785 (host->ios.bus_width == MMC_BUS_WIDTH_1)) {
786 u8 reg;
787
788 func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
789 reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret);
790 if (ret)
791 goto disable;
792
793 reg |= SDIO_BUS_ECSI;
794 sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret);
795 if (ret)
796 goto disable;
797 }
798
799 card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret);
800 if (ret)
801 goto disable;
802
803 card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8;
804 if (ret)
805 goto disable;
806
807 card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16;
808 if (ret)
809 goto disable;
810
811 sdio_release_host(func);
812 ret = if_sdio_prog_firmware(card);
813 sdio_claim_host(func);
814 if (ret)
815 goto disable;
816 772
817 /* 773 /*
818 * Get rx_unit if the chip is SD8688 or newer. 774 * Get rx_unit if the chip is SD8688 or newer.
@@ -837,7 +793,7 @@ static int if_sdio_power_on(struct if_sdio_card *card)
837 */ 793 */
838 ret = sdio_claim_irq(func, if_sdio_interrupt); 794 ret = sdio_claim_irq(func, if_sdio_interrupt);
839 if (ret) 795 if (ret)
840 goto disable; 796 goto release;
841 797
842 /* 798 /*
843 * Enable interrupts now that everything is set up 799 * Enable interrupts now that everything is set up
@@ -863,11 +819,79 @@ static int if_sdio_power_on(struct if_sdio_card *card)
863 } 819 }
864 820
865 priv->fw_ready = 1; 821 priv->fw_ready = 1;
822 wake_up(&card->pwron_waitq);
866 823
867 return 0; 824 if (!card->started) {
825 ret = lbs_start_card(priv);
826 if_sdio_power_off(card);
827 if (ret == 0) {
828 card->started = true;
829 /* Tell PM core that we don't need the card to be
830 * powered now */
831 pm_runtime_put_noidle(&func->dev);
832 }
833 }
834
835 return;
868 836
869release_irq: 837release_irq:
870 sdio_release_irq(func); 838 sdio_release_irq(func);
839release:
840 sdio_release_host(func);
841}
842
843static int if_sdio_power_on(struct if_sdio_card *card)
844{
845 struct sdio_func *func = card->func;
846 struct mmc_host *host = func->card->host;
847 int ret;
848
849 sdio_claim_host(func);
850
851 ret = sdio_enable_func(func);
852 if (ret)
853 goto release;
854
855 /* For 1-bit transfers to the 8686 model, we need to enable the
856 * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
857 * bit to allow access to non-vendor registers. */
858 if ((card->model == MODEL_8686) &&
859 (host->caps & MMC_CAP_SDIO_IRQ) &&
860 (host->ios.bus_width == MMC_BUS_WIDTH_1)) {
861 u8 reg;
862
863 func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
864 reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret);
865 if (ret)
866 goto disable;
867
868 reg |= SDIO_BUS_ECSI;
869 sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret);
870 if (ret)
871 goto disable;
872 }
873
874 card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret);
875 if (ret)
876 goto disable;
877
878 card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8;
879 if (ret)
880 goto disable;
881
882 card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16;
883 if (ret)
884 goto disable;
885
886 sdio_release_host(func);
887 ret = if_sdio_prog_firmware(card);
888 if (ret) {
889 sdio_disable_func(func);
890 return ret;
891 }
892
893 return 0;
894
871disable: 895disable:
872 sdio_disable_func(func); 896 sdio_disable_func(func);
873release: 897release:
@@ -1074,11 +1098,17 @@ static int if_sdio_power_save(struct lbs_private *priv)
1074static int if_sdio_power_restore(struct lbs_private *priv) 1098static int if_sdio_power_restore(struct lbs_private *priv)
1075{ 1099{
1076 struct if_sdio_card *card = priv->card; 1100 struct if_sdio_card *card = priv->card;
1101 int r;
1077 1102
1078 /* Make sure the card will not be powered off by runtime PM */ 1103 /* Make sure the card will not be powered off by runtime PM */
1079 pm_runtime_get_sync(&card->func->dev); 1104 pm_runtime_get_sync(&card->func->dev);
1080 1105
1081 return if_sdio_power_on(card); 1106 r = if_sdio_power_on(card);
1107 if (r)
1108 return r;
1109
1110 wait_event(card->pwron_waitq, priv->fw_ready);
1111 return 0;
1082} 1112}
1083 1113
1084 1114
@@ -1179,6 +1209,7 @@ static int if_sdio_probe(struct sdio_func *func,
1179 spin_lock_init(&card->lock); 1209 spin_lock_init(&card->lock);
1180 card->workqueue = create_workqueue("libertas_sdio"); 1210 card->workqueue = create_workqueue("libertas_sdio");
1181 INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); 1211 INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker);
1212 init_waitqueue_head(&card->pwron_waitq);
1182 1213
1183 /* Check if we support this card */ 1214 /* Check if we support this card */
1184 for (i = 0; i < ARRAY_SIZE(fw_table); i++) { 1215 for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
@@ -1220,14 +1251,6 @@ static int if_sdio_probe(struct sdio_func *func,
1220 if (ret) 1251 if (ret)
1221 goto err_activate_card; 1252 goto err_activate_card;
1222 1253
1223 ret = lbs_start_card(priv);
1224 if_sdio_power_off(card);
1225 if (ret)
1226 goto err_activate_card;
1227
1228 /* Tell PM core that we don't need the card to be powered now */
1229 pm_runtime_put_noidle(&func->dev);
1230
1231out: 1254out:
1232 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); 1255 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
1233 1256
@@ -1244,10 +1267,6 @@ free:
1244 kfree(packet); 1267 kfree(packet);
1245 } 1268 }
1246 1269
1247 if (card->helper_allocated)
1248 kfree(card->helper);
1249 if (card->firmware_allocated)
1250 kfree(card->firmware);
1251 kfree(card); 1270 kfree(card);
1252 1271
1253 goto out; 1272 goto out;
@@ -1295,12 +1314,6 @@ static void if_sdio_remove(struct sdio_func *func)
1295 kfree(packet); 1314 kfree(packet);
1296 } 1315 }
1297 1316
1298 if (card->helper_allocated)
1299 kfree(card->helper);
1300 if (card->firmware_allocated)
1301 kfree(card->firmware);
1302 kfree(card);
1303
1304 lbs_deb_leave(LBS_DEB_SDIO); 1317 lbs_deb_leave(LBS_DEB_SDIO);
1305} 1318}
1306 1319