[PATCH 2/2] libertas_spi: Deep sleep wakeup workaround

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


After waking from deep sleep, the SPI 8686 fails to set the
CMD_DOWNLOAD_RDY bit in the Host Interrupt Status Register. Use a simple
flag, set right after deep sleep wakeup event is received, to indicate
to host the card is ready to receive commands. This is only needed for
the first command, as subsequent transactions proceed properly

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

diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index d2026cc..c497c2c 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -75,6 +75,13 @@ struct if_spi_card {
 
 	/* True is card suspended */
 	u8				suspended;
+
+	/* Deep Sleep workaround: The SPI card has trouble fully waking from
+	 * deep sleep. IF_SPI_HIST_CMD_DOWNLOAD_RDY is not set until first
+	 * command is received. Use this flag to take the command download path
+	 * in the SPI ISR, after which the card operates normally.
+	 * */
+	int ds_cmd_rdy;
 };
 
 static void free_if_spi_card(struct if_spi_card *card)
@@ -903,10 +910,14 @@ static void if_spi_host_to_card_worker(struct work_struct *work)
 	/*
 	 * workaround: in PS mode, the card does not set the Command
 	 * Download Ready bit, but it sets TX Download Ready.
+	 * This is also true when waking from deep sleep, before
+	 * the first command is received.
 	 */
 	if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY ||
 	   (card->priv->psstate != PS_STATE_FULL_POWER &&
-	    (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) {
+	    (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY)) ||
+	    card->ds_cmd_rdy) {
+		card->ds_cmd_rdy = 0;
 		/*
 		 * This means two things. First of all,
 		 * if there was a previous command sent, the card has
@@ -1078,6 +1089,8 @@ static int if_spi_reset_deep_sleep_wakeup(struct lbs_private *priv)
 	/* FW seems to forget which interrupts were enabled */
 	spu_set_interrupt_mode(card, 0, 1);
 
+	card->ds_cmd_rdy = 1;
+
 	lbs_deb_leave_args(LBS_DEB_SPI, "ret %d", ret);
 	return ret;
 
-- 
1.7.6




More information about the libertas-dev mailing list