aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/if_sdio.c
diff options
context:
space:
mode:
authorAmitkumar Karwar <akarwar@marvell.com>2009-09-30 20:04:38 -0700
committerJohn W. Linville <linville@tuxdriver.com>2009-10-07 16:39:43 -0400
commit4912545472d71e3dd546b18b397aec4c89fd7403 (patch)
treeb7b0d520cdbee35303caf69881f7898e38966bc7 /drivers/net/wireless/libertas/if_sdio.c
parentstaging: Add proper selection of WIRELESS_EXT and WEXT_PRIV (diff)
downloadlinux-dev-4912545472d71e3dd546b18b397aec4c89fd7403.tar.xz
linux-dev-4912545472d71e3dd546b18b397aec4c89fd7403.zip
libertas: Add auto deep sleep support for SD8385/SD8686/SD8688
Add timer based auto deep sleep feature in libertas driver which can be configured using iwconfig command. This is tested on SD8688, SD8686 cards with firmware versions 10.38.1.p25, 9.70.4.p0 respectively on 32-bit and 64-bit platforms. Tests have been done for USB/CS cards to make sure that the patch won't break USB/CS code. We didn't test the if_spi driver. Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Acked-by: Dan Williams <dcbw@redhat.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.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 485a8d406525..9716728a33cb 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -831,6 +831,58 @@ out:
return ret;
}
+static int if_sdio_enter_deep_sleep(struct lbs_private *priv)
+{
+ int ret = -1;
+ struct cmd_header cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ lbs_deb_sdio("send DEEP_SLEEP command\n");
+ ret = __lbs_cmd(priv, CMD_802_11_DEEP_SLEEP, &cmd, sizeof(cmd),
+ lbs_cmd_copyback, (unsigned long) &cmd);
+ if (ret)
+ lbs_pr_err("DEEP_SLEEP cmd failed\n");
+
+ mdelay(200);
+ return ret;
+}
+
+static int if_sdio_exit_deep_sleep(struct lbs_private *priv)
+{
+ struct if_sdio_card *card = priv->card;
+ int ret = -1;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+ sdio_claim_host(card->func);
+
+ sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
+ if (ret)
+ lbs_pr_err("sdio_writeb failed!\n");
+
+ sdio_release_host(card->func);
+ lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+ return ret;
+}
+
+static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv)
+{
+ struct if_sdio_card *card = priv->card;
+ int ret = -1;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+ sdio_claim_host(card->func);
+
+ sdio_writeb(card->func, 0, CONFIGURATION_REG, &ret);
+ if (ret)
+ lbs_pr_err("sdio_writeb failed!\n");
+
+ sdio_release_host(card->func);
+ lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+ return ret;
+
+}
+
/*******************************************************************/
/* SDIO callbacks */
/*******************************************************************/
@@ -859,6 +911,7 @@ static void if_sdio_interrupt(struct sdio_func *func)
* Ignore the define name, this really means the card has
* successfully received the command.
*/
+ card->priv->is_activity_detected = 1;
if (cause & IF_SDIO_H_INT_DNLD)
lbs_host_to_card_done(card->priv);
@@ -998,6 +1051,9 @@ static int if_sdio_probe(struct sdio_func *func,
priv->card = card;
priv->hw_host_to_card = if_sdio_host_to_card;
+ priv->enter_deep_sleep = if_sdio_enter_deep_sleep;
+ priv->exit_deep_sleep = if_sdio_exit_deep_sleep;
+ priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup;
priv->fw_ready = 1;