diff options
Diffstat (limited to 'target/linux/sunxi/patches-4.1/140-mmc-sdio-reliability-fix.patch')
-rw-r--r-- | target/linux/sunxi/patches-4.1/140-mmc-sdio-reliability-fix.patch | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/target/linux/sunxi/patches-4.1/140-mmc-sdio-reliability-fix.patch b/target/linux/sunxi/patches-4.1/140-mmc-sdio-reliability-fix.patch new file mode 100644 index 0000000000..295865bbe5 --- /dev/null +++ b/target/linux/sunxi/patches-4.1/140-mmc-sdio-reliability-fix.patch @@ -0,0 +1,88 @@ +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) { |