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>
This commit is contained in:
committed by
John W. Linville
parent
b136a1414c
commit
d26285f873
@@ -61,6 +61,7 @@ struct if_sdio_model {
|
||||
int model;
|
||||
const char *helper;
|
||||
const char *firmware;
|
||||
struct if_sdio_card *card;
|
||||
};
|
||||
|
||||
static struct if_sdio_model if_sdio_models[] = {
|
||||
@@ -69,18 +70,21 @@ static struct if_sdio_model if_sdio_models[] = {
|
||||
.model = IF_SDIO_MODEL_8385,
|
||||
.helper = "sd8385_helper.bin",
|
||||
.firmware = "sd8385.bin",
|
||||
.card = NULL,
|
||||
},
|
||||
{
|
||||
/* 8686 */
|
||||
.model = IF_SDIO_MODEL_8686,
|
||||
.helper = "sd8686_helper.bin",
|
||||
.firmware = "sd8686.bin",
|
||||
.card = NULL,
|
||||
},
|
||||
{
|
||||
/* 8688 */
|
||||
.model = IF_SDIO_MODEL_8688,
|
||||
.helper = "sd8688_helper.bin",
|
||||
.firmware = "sd8688.bin",
|
||||
.card = NULL,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -539,7 +543,6 @@ static int if_sdio_prog_helper(struct if_sdio_card *card)
|
||||
ret = 0;
|
||||
|
||||
release:
|
||||
sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE);
|
||||
sdio_release_host(card->func);
|
||||
kfree(chunk_buffer);
|
||||
release_fw:
|
||||
@@ -675,7 +678,6 @@ static int if_sdio_prog_real(struct if_sdio_card *card)
|
||||
ret = 0;
|
||||
|
||||
release:
|
||||
sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE);
|
||||
sdio_release_host(card->func);
|
||||
kfree(chunk_buffer);
|
||||
release_fw:
|
||||
@@ -718,6 +720,9 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
|
||||
goto out;
|
||||
|
||||
success:
|
||||
sdio_claim_host(card->func);
|
||||
sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE);
|
||||
sdio_release_host(card->func);
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
@@ -903,6 +908,8 @@ static int if_sdio_probe(struct sdio_func *func,
|
||||
goto free;
|
||||
}
|
||||
|
||||
if_sdio_models[i].card = card;
|
||||
|
||||
card->helper = if_sdio_models[i].helper;
|
||||
card->firmware = if_sdio_models[i].firmware;
|
||||
|
||||
@@ -985,6 +992,12 @@ static int if_sdio_probe(struct sdio_func *func,
|
||||
if (ret)
|
||||
goto reclaim;
|
||||
|
||||
/*
|
||||
* FUNC_INIT is required for SD8688 WLAN/BT multiple functions
|
||||
*/
|
||||
priv->fn_init_required =
|
||||
(card->model == IF_SDIO_MODEL_8688) ? 1 : 0;
|
||||
|
||||
ret = lbs_start_card(priv);
|
||||
if (ret)
|
||||
goto err_activate_card;
|
||||
@@ -1025,23 +1038,30 @@ static void if_sdio_remove(struct sdio_func *func)
|
||||
{
|
||||
struct if_sdio_card *card;
|
||||
struct if_sdio_packet *packet;
|
||||
int ret;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_SDIO);
|
||||
|
||||
card = sdio_get_drvdata(func);
|
||||
|
||||
lbs_stop_card(card->priv);
|
||||
|
||||
card->priv->surpriseremoved = 1;
|
||||
|
||||
lbs_deb_sdio("call remove card\n");
|
||||
lbs_stop_card(card->priv);
|
||||
lbs_remove_card(card->priv);
|
||||
|
||||
flush_workqueue(card->workqueue);
|
||||
destroy_workqueue(card->workqueue);
|
||||
|
||||
sdio_claim_host(func);
|
||||
|
||||
/* Disable interrupts */
|
||||
sdio_writeb(func, 0x00, IF_SDIO_H_INT_MASK, &ret);
|
||||
|
||||
sdio_release_irq(func);
|
||||
sdio_disable_func(func);
|
||||
|
||||
sdio_release_host(func);
|
||||
|
||||
while (card->packets) {
|
||||
@@ -1084,8 +1104,23 @@ static int __init if_sdio_init_module(void)
|
||||
|
||||
static void __exit if_sdio_exit_module(void)
|
||||
{
|
||||
int i;
|
||||
struct if_sdio_card *card;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_SDIO);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(if_sdio_models); i++) {
|
||||
card = if_sdio_models[i].card;
|
||||
|
||||
/*
|
||||
* FUNC_SHUTDOWN is required for SD8688 WLAN/BT
|
||||
* multiple functions
|
||||
*/
|
||||
if (card && card->priv)
|
||||
card->priv->fn_shutdown_required =
|
||||
(card->model == IF_SDIO_MODEL_8688) ? 1 : 0;
|
||||
}
|
||||
|
||||
sdio_unregister_driver(&if_sdio_driver);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_SDIO);
|
||||
|
Reference in New Issue
Block a user