89 lines
2.7 KiB
Diff
89 lines
2.7 KiB
Diff
|
From 8a7013f47196abed7e6a40e93d1de1639cd46228 Mon Sep 17 00:00:00 2001
|
||
|
From: Hans de Goede <hdegoede@redhat.com>
|
||
|
Date: Fri, 10 Jul 2015 17:03:03 +0200
|
||
|
Subject: [PATCH] mmc: sunxi: Don't start commands while the card is busy
|
||
|
|
||
|
Some sdio wifi modules have not been working reliable with the sunxi-mmc
|
||
|
host code. This turns out to be caused by it starting new commands while
|
||
|
the card signals that it is still busy processing a previous command.
|
||
|
|
||
|
This commit fixes this, thereby fixing the wifi reliability issues on
|
||
|
the Cubietruck and other sunxi boards using sdio wifi.
|
||
|
|
||
|
Reported-by: Eugene K <sigintmailru@gmail.com>
|
||
|
Suggested-by: Eugene K <sigintmailru@gmail.com>
|
||
|
Cc: Eugene K <sigintmailru@gmail.com>
|
||
|
Cc: Arend van Spriel <arend@broadcom.com>
|
||
|
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||
|
---
|
||
|
Changes in v2:
|
||
|
-Properly accredit Eugene K for coming up with the fix for this
|
||
|
---
|
||
|
drivers/mmc/host/sunxi-mmc.c | 32 ++++++++++++++++++++++++++++++++
|
||
|
1 file changed, 32 insertions(+)
|
||
|
|
||
|
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
|
||
|
index 4d3e1ff..daa90b7 100644
|
||
|
--- a/drivers/mmc/host/sunxi-mmc.c
|
||
|
+++ b/drivers/mmc/host/sunxi-mmc.c
|
||
|
@@ -289,6 +289,24 @@ static int sunxi_mmc_init_host(struct mmc_host *mmc)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+/* Wait for card to report ready before starting a new cmd */
|
||
|
+static int sunxi_mmc_wait_card_ready(struct sunxi_mmc_host *host)
|
||
|
+{
|
||
|
+ unsigned long expire = jiffies + msecs_to_jiffies(500);
|
||
|
+ u32 rval;
|
||
|
+
|
||
|
+ do {
|
||
|
+ rval = mmc_readl(host, REG_STAS);
|
||
|
+ } while (time_before(jiffies, expire) && (rval & SDXC_CARD_DATA_BUSY));
|
||
|
+
|
||
|
+ if (rval & SDXC_CARD_DATA_BUSY) {
|
||
|
+ dev_err(mmc_dev(host->mmc), "Error R1 ready timeout\n");
|
||
|
+ return -EIO;
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host,
|
||
|
struct mmc_data *data)
|
||
|
{
|
||
|
@@ -383,6 +401,8 @@ static void sunxi_mmc_send_manual_stop(struct sunxi_mmc_host *host,
|
||
|
u32 arg, cmd_val, ri;
|
||
|
unsigned long expire = jiffies + msecs_to_jiffies(1000);
|
||
|
|
||
|
+ sunxi_mmc_wait_card_ready(host);
|
||
|
+
|
||
|
cmd_val = SDXC_START | SDXC_RESP_EXPIRE |
|
||
|
SDXC_STOP_ABORT_CMD | SDXC_CHECK_RESPONSE_CRC;
|
||
|
|
||
|
@@ -597,6 +617,11 @@ static int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
|
||
|
{
|
||
|
unsigned long expire = jiffies + msecs_to_jiffies(250);
|
||
|
u32 rval;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ ret = sunxi_mmc_wait_card_ready(host);
|
||
|
+ if (ret)
|
||
|
+ return ret;
|
||
|
|
||
|
rval = mmc_readl(host, REG_CLKCR);
|
||
|
rval &= ~(SDXC_CARD_CLOCK_ON | SDXC_LOW_POWER_ON);
|
||
|
@@ -785,6 +810,13 @@ static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
+ ret = sunxi_mmc_wait_card_ready(host);
|
||
|
+ if (ret) {
|
||
|
+ mrq->cmd->error = ret;
|
||
|
+ mmc_request_done(mmc, mrq);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
if (data) {
|
||
|
ret = sunxi_mmc_map_dma(host, data);
|
||
|
if (ret < 0) {
|