aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/if_sdio.c
diff options
context:
space:
mode:
authorBing Zhao <bzhao@marvell.com>2009-05-19 22:48:20 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-22 14:06:01 -0400
commitd26285f873c3066fefe648b47b9ecf3ec18bcfbc (patch)
treec98fd544dcf32c71ff13bbb8cdf0e80602b460b7 /drivers/net/wireless/libertas/if_sdio.c
parentb136a1414c94b4bda1057b4ffde26253d2527628 (diff)
libertas: implement function init/shutdown commands for SD8688
SD8688 is a WLAN/Bluetooth combo chip and both functions are supported in a single firmware image. FUNC_INIT and FUNC_SHUTDOWN commands are implemented to utilize the multiple function feature. When SD8688 card is inserted, the firmware image should be downloaded only once through either WLAN function (Libertas driver) or Bluetooth function (Bluetooth driver). This patch adds function init/shutdown for SD8688 WLAN function only. Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas/if_sdio.c')
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c41
1 files changed, 38 insertions, 3 deletions
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index e998c123e0c..478d766abf8 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -61,6 +61,7 @@ struct if_sdio_model {
61 int model; 61 int model;
62 const char *helper; 62 const char *helper;
63 const char *firmware; 63 const char *firmware;
64 struct if_sdio_card *card;
64}; 65};
65 66
66static struct if_sdio_model if_sdio_models[] = { 67static struct if_sdio_model if_sdio_models[] = {
@@ -69,18 +70,21 @@ static struct if_sdio_model if_sdio_models[] = {
69 .model = IF_SDIO_MODEL_8385, 70 .model = IF_SDIO_MODEL_8385,
70 .helper = "sd8385_helper.bin", 71 .helper = "sd8385_helper.bin",
71 .firmware = "sd8385.bin", 72 .firmware = "sd8385.bin",
73 .card = NULL,
72 }, 74 },
73 { 75 {
74 /* 8686 */ 76 /* 8686 */
75 .model = IF_SDIO_MODEL_8686, 77 .model = IF_SDIO_MODEL_8686,
76 .helper = "sd8686_helper.bin", 78 .helper = "sd8686_helper.bin",
77 .firmware = "sd8686.bin", 79 .firmware = "sd8686.bin",
80 .card = NULL,
78 }, 81 },
79 { 82 {
80 /* 8688 */ 83 /* 8688 */
81 .model = IF_SDIO_MODEL_8688, 84 .model = IF_SDIO_MODEL_8688,
82 .helper = "sd8688_helper.bin", 85 .helper = "sd8688_helper.bin",
83 .firmware = "sd8688.bin", 86 .firmware = "sd8688.bin",
87 .card = NULL,
84 }, 88 },
85}; 89};
86 90
@@ -539,7 +543,6 @@ static int if_sdio_prog_helper(struct if_sdio_card *card)
539 ret = 0; 543 ret = 0;
540 544
541release: 545release:
542 sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE);
543 sdio_release_host(card->func); 546 sdio_release_host(card->func);
544 kfree(chunk_buffer); 547 kfree(chunk_buffer);
545release_fw: 548release_fw:
@@ -675,7 +678,6 @@ static int if_sdio_prog_real(struct if_sdio_card *card)
675 ret = 0; 678 ret = 0;
676 679
677release: 680release:
678 sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE);
679 sdio_release_host(card->func); 681 sdio_release_host(card->func);
680 kfree(chunk_buffer); 682 kfree(chunk_buffer);
681release_fw: 683release_fw:
@@ -718,6 +720,9 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
718 goto out; 720 goto out;
719 721
720success: 722success:
723 sdio_claim_host(card->func);
724 sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE);
725 sdio_release_host(card->func);
721 ret = 0; 726 ret = 0;
722 727
723out: 728out:
@@ -903,6 +908,8 @@ static int if_sdio_probe(struct sdio_func *func,
903 goto free; 908 goto free;
904 } 909 }
905 910
911 if_sdio_models[i].card = card;
912
906 card->helper = if_sdio_models[i].helper; 913 card->helper = if_sdio_models[i].helper;
907 card->firmware = if_sdio_models[i].firmware; 914 card->firmware = if_sdio_models[i].firmware;
908 915
@@ -985,6 +992,12 @@ static int if_sdio_probe(struct sdio_func *func,
985 if (ret) 992 if (ret)
986 goto reclaim; 993 goto reclaim;
987 994
995 /*
996 * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
997 */
998 priv->fn_init_required =
999 (card->model == IF_SDIO_MODEL_8688) ? 1 : 0;
1000
988 ret = lbs_start_card(priv); 1001 ret = lbs_start_card(priv);
989 if (ret) 1002 if (ret)
990 goto err_activate_card; 1003 goto err_activate_card;
@@ -1025,23 +1038,30 @@ static void if_sdio_remove(struct sdio_func *func)
1025{ 1038{
1026 struct if_sdio_card *card; 1039 struct if_sdio_card *card;
1027 struct if_sdio_packet *packet; 1040 struct if_sdio_packet *packet;
1041 int ret;
1028 1042
1029 lbs_deb_enter(LBS_DEB_SDIO); 1043 lbs_deb_enter(LBS_DEB_SDIO);
1030 1044
1031 card = sdio_get_drvdata(func); 1045 card = sdio_get_drvdata(func);
1032 1046
1047 lbs_stop_card(card->priv);
1048
1033 card->priv->surpriseremoved = 1; 1049 card->priv->surpriseremoved = 1;
1034 1050
1035 lbs_deb_sdio("call remove card\n"); 1051 lbs_deb_sdio("call remove card\n");
1036 lbs_stop_card(card->priv);
1037 lbs_remove_card(card->priv); 1052 lbs_remove_card(card->priv);
1038 1053
1039 flush_workqueue(card->workqueue); 1054 flush_workqueue(card->workqueue);
1040 destroy_workqueue(card->workqueue); 1055 destroy_workqueue(card->workqueue);
1041 1056
1042 sdio_claim_host(func); 1057 sdio_claim_host(func);
1058
1059 /* Disable interrupts */
1060 sdio_writeb(func, 0x00, IF_SDIO_H_INT_MASK, &ret);
1061
1043 sdio_release_irq(func); 1062 sdio_release_irq(func);
1044 sdio_disable_func(func); 1063 sdio_disable_func(func);
1064
1045 sdio_release_host(func); 1065 sdio_release_host(func);
1046 1066
1047 while (card->packets) { 1067 while (card->packets) {
@@ -1084,8 +1104,23 @@ static int __init if_sdio_init_module(void)
1084 1104
1085static void __exit if_sdio_exit_module(void) 1105static void __exit if_sdio_exit_module(void)
1086{ 1106{
1107 int i;
1108 struct if_sdio_card *card;
1109
1087 lbs_deb_enter(LBS_DEB_SDIO); 1110 lbs_deb_enter(LBS_DEB_SDIO);
1088 1111
1112 for (i = 0; i < ARRAY_SIZE(if_sdio_models); i++) {
1113 card = if_sdio_models[i].card;
1114
1115 /*
1116 * FUNC_SHUTDOWN is required for SD8688 WLAN/BT
1117 * multiple functions
1118 */
1119 if (card && card->priv)
1120 card->priv->fn_shutdown_required =
1121 (card->model == IF_SDIO_MODEL_8688) ? 1 : 0;
1122 }
1123
1089 sdio_unregister_driver(&if_sdio_driver); 1124 sdio_unregister_driver(&if_sdio_driver);
1090 1125
1091 lbs_deb_leave(LBS_DEB_SDIO); 1126 lbs_deb_leave(LBS_DEB_SDIO);