[PATCH 1/2] libertas_spi: Implement deep sleep for SPI interface

Thomas Pedersen thomas at cozybit.com
Wed Jul 6 22:29:10 EDT 2011


This patch implements deep sleep functionality for the 8686 SPI
interface. Currently, only the SPI register wakeup trigger is used.

Signed-off-by: Thomas Pedersen <thomas at cozybit.com>
---
 drivers/net/wireless/libertas/if_spi.c |   60 ++++++++++++++++++++++++++++++--
 1 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index d041bb2..d2026cc 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -32,6 +32,7 @@
 #include "decl.h"
 #include "defs.h"
 #include "dev.h"
+#include "cmd.h"
 #include "if_spi.h"
 
 struct if_spi_packet {
@@ -875,6 +876,8 @@ static void if_spi_host_to_card_worker(struct work_struct *work)
 
 	lbs_deb_enter(LBS_DEB_SPI);
 
+	card->priv->is_activity_detected = 1;
+
 	/*
 	 * Read the host interrupt status register to see what we
 	 * can do.
@@ -1029,6 +1032,57 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)
  * SPI callbacks
  */
 
+static int if_spi_enter_deep_sleep(struct lbs_private *priv)
+{
+	int ret = -1;
+	struct cmd_header cmd;
+
+	memset(&cmd, 0, sizeof(cmd));
+
+	lbs_deb_spi("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)
+		netdev_err(priv->dev, "DEEP_SLEEP cmd failed\n");
+
+	mdelay(200);
+	return ret;
+}
+
+static int if_spi_exit_deep_sleep(struct lbs_private *priv)
+{
+	struct if_spi_card *card = priv->card;
+	int ret = -1;
+
+	lbs_deb_enter(LBS_DEB_SPI);
+
+	ret = spu_write_u16(card, IF_SPI_HOST_INT_CTRL_REG,
+				  IF_SPI_HICT_WAKE_UP);
+	if (ret)
+		netdev_err(priv->dev, "spu write failed!\n");
+
+	lbs_deb_leave_args(LBS_DEB_SPI, "ret %d", ret);
+	return ret;
+}
+
+static int if_spi_reset_deep_sleep_wakeup(struct lbs_private *priv)
+{
+	struct if_spi_card *card = priv->card;
+	int ret = -1;
+
+	lbs_deb_enter(LBS_DEB_SPI);
+
+	ret = spu_write_u16(card, IF_SPI_HOST_INT_CTRL_REG, 0);
+	if (ret)
+		netdev_err(priv->dev, "spu write failed!\n");
+	/* FW seems to forget which interrupts were enabled */
+	spu_set_interrupt_mode(card, 0, 1);
+
+	lbs_deb_leave_args(LBS_DEB_SPI, "ret %d", ret);
+	return ret;
+
+}
+
 static int if_spi_init_card(struct if_spi_card *card)
 {
 	struct lbs_private *priv = card->priv;
@@ -1183,9 +1237,9 @@ static int __devinit if_spi_probe(struct spi_device *spi)
 	priv->setup_fw_on_resume = 1;
 	priv->card = card;
 	priv->hw_host_to_card = if_spi_host_to_card;
-	priv->enter_deep_sleep = NULL;
-	priv->exit_deep_sleep = NULL;
-	priv->reset_deep_sleep_wakeup = NULL;
+	priv->enter_deep_sleep = if_spi_enter_deep_sleep;
+	priv->exit_deep_sleep = if_spi_exit_deep_sleep;
+	priv->reset_deep_sleep_wakeup = if_spi_reset_deep_sleep_wakeup;
 	priv->fw_ready = 1;
 
 	/* Initialize interrupt handling stuff. */
-- 
1.7.6




More information about the libertas-dev mailing list