sunxi: add support for 4.1
[openwrt.git] / target / linux / sunxi / patches-4.1 / 140-mmc-sdio-reliability-fix.patch
1 From 8a7013f47196abed7e6a40e93d1de1639cd46228 Mon Sep 17 00:00:00 2001
2 From: Hans de Goede <hdegoede@redhat.com>
3 Date: Fri, 10 Jul 2015 17:03:03 +0200
4 Subject: [PATCH] mmc: sunxi: Don't start commands while the card is busy
5
6 Some sdio wifi modules have not been working reliable with the sunxi-mmc
7 host code. This turns out to be caused by it starting new commands while
8 the card signals that it is still busy processing a previous command.
9
10 This commit fixes this, thereby fixing the wifi reliability issues on
11 the Cubietruck and other sunxi boards using sdio wifi.
12
13 Reported-by: Eugene K <sigintmailru@gmail.com>
14 Suggested-by: Eugene K <sigintmailru@gmail.com>
15 Cc: Eugene K <sigintmailru@gmail.com>
16 Cc: Arend van Spriel <arend@broadcom.com>
17 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
18 ---
19 Changes in v2:
20 -Properly accredit Eugene K for coming up with the fix for this
21 ---
22  drivers/mmc/host/sunxi-mmc.c | 32 ++++++++++++++++++++++++++++++++
23  1 file changed, 32 insertions(+)
24
25 diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
26 index 4d3e1ff..daa90b7 100644
27 --- a/drivers/mmc/host/sunxi-mmc.c
28 +++ b/drivers/mmc/host/sunxi-mmc.c
29 @@ -289,6 +289,24 @@ static int sunxi_mmc_init_host(struct mmc_host *mmc)
30         return 0;
31  }
32  
33 +/* Wait for card to report ready before starting a new cmd */
34 +static int sunxi_mmc_wait_card_ready(struct sunxi_mmc_host *host)
35 +{
36 +       unsigned long expire = jiffies + msecs_to_jiffies(500);
37 +       u32 rval;
38 +
39 +       do {
40 +               rval = mmc_readl(host, REG_STAS);
41 +       } while (time_before(jiffies, expire) && (rval & SDXC_CARD_DATA_BUSY));
42 +
43 +       if (rval & SDXC_CARD_DATA_BUSY) {
44 +               dev_err(mmc_dev(host->mmc), "Error R1 ready timeout\n");
45 +               return -EIO;
46 +       }
47 +
48 +       return 0;
49 +}
50 +
51  static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host,
52                                     struct mmc_data *data)
53  {
54 @@ -383,6 +401,8 @@ static void sunxi_mmc_send_manual_stop(struct sunxi_mmc_host *host,
55         u32 arg, cmd_val, ri;
56         unsigned long expire = jiffies + msecs_to_jiffies(1000);
57  
58 +       sunxi_mmc_wait_card_ready(host);
59 +
60         cmd_val = SDXC_START | SDXC_RESP_EXPIRE |
61                   SDXC_STOP_ABORT_CMD | SDXC_CHECK_RESPONSE_CRC;
62  
63 @@ -597,6 +617,11 @@ static int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
64  {
65         unsigned long expire = jiffies + msecs_to_jiffies(250);
66         u32 rval;
67 +       int ret;
68 +
69 +       ret = sunxi_mmc_wait_card_ready(host);
70 +       if (ret)
71 +               return ret;
72  
73         rval = mmc_readl(host, REG_CLKCR);
74         rval &= ~(SDXC_CARD_CLOCK_ON | SDXC_LOW_POWER_ON);
75 @@ -785,6 +810,13 @@ static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
76                 return;
77         }
78  
79 +       ret = sunxi_mmc_wait_card_ready(host);
80 +       if (ret) {
81 +               mrq->cmd->error = ret;
82 +               mmc_request_done(mmc, mrq);
83 +               return;
84 +       }
85 +
86         if (data) {
87                 ret = sunxi_mmc_map_dma(host, data);
88                 if (ret < 0) {