]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
mmc: sdhci: Add quirk to disable HW timeout
authorAdrian Hunter <adrian.hunter@intel.com>
Fri, 27 Apr 2018 11:47:15 +0000 (17:17 +0530)
committerUlf Hansson <ulf.hansson@linaro.org>
Thu, 3 May 2018 07:36:19 +0000 (09:36 +0200)
Add quirk to disable HW timeout if the requested timeout is more than the
maximum obtainable timeout.

Also, if the quirk is set and ->get_max_timeout_count() is not implemented,
max_busy_timeout is set to zero.

Based-on-patch-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h

index 0f3cdca3e769a7732aad038f453898ada5e620b7..8da118d0d2c450c38c654074f05938ffe4e4a4fa 100644 (file)
@@ -709,12 +709,15 @@ static u32 sdhci_sdma_address(struct sdhci_host *host)
                return sg_dma_address(host->data->sg);
 }
 
-static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
+static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd,
+                            bool *too_big)
 {
        u8 count;
        struct mmc_data *data = cmd->data;
        unsigned target_timeout, current_timeout;
 
+       *too_big = true;
+
        /*
         * If the host controller provides us with an incorrect timeout
         * value, just skip the check and use 0xE.  The hardware may take
@@ -768,9 +771,12 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
        }
 
        if (count >= 0xF) {
-               DBG("Too large timeout 0x%x requested for CMD%d!\n",
-                   count, cmd->opcode);
+               if (!(host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT))
+                       DBG("Too large timeout 0x%x requested for CMD%d!\n",
+                           count, cmd->opcode);
                count = 0xE;
+       } else {
+               *too_big = false;
        }
 
        return count;
@@ -790,6 +796,16 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host)
        sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
 }
 
+static void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable)
+{
+       if (enable)
+               host->ier |= SDHCI_INT_DATA_TIMEOUT;
+       else
+               host->ier &= ~SDHCI_INT_DATA_TIMEOUT;
+       sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+       sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+}
+
 static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
 {
        u8 count;
@@ -797,7 +813,17 @@ static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
        if (host->ops->set_timeout) {
                host->ops->set_timeout(host, cmd);
        } else {
-               count = sdhci_calc_timeout(host, cmd);
+               bool too_big = false;
+
+               count = sdhci_calc_timeout(host, cmd, &too_big);
+
+               if (too_big &&
+                   host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT) {
+                       sdhci_set_data_timeout_irq(host, false);
+               } else if (!(host->ier & SDHCI_INT_DATA_TIMEOUT)) {
+                       sdhci_set_data_timeout_irq(host, true);
+               }
+
                sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL);
        }
 }
@@ -3616,6 +3642,10 @@ int sdhci_setup_host(struct sdhci_host *host)
                mmc->max_busy_timeout /= host->timeout_clk;
        }
 
+       if (host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT &&
+           !host->ops->get_max_timeout_count)
+               mmc->max_busy_timeout = 0;
+
        mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
        mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
 
index c95b0a4a759467898985a5058eed9e5ec0dd63bd..f6555c0f4ad3359eadada3a47d5970b5d1ea140f 100644 (file)
@@ -437,6 +437,11 @@ struct sdhci_host {
 #define SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN             (1<<15)
 /* Controller has CRC in 136 bit Command Response */
 #define SDHCI_QUIRK2_RSP_136_HAS_CRC                   (1<<16)
+/*
+ * Disable HW timeout if the requested timeout is more than the maximum
+ * obtainable timeout.
+ */
+#define SDHCI_QUIRK2_DISABLE_HW_TIMEOUT                        (1<<17)
 
        int irq;                /* Device IRQ */
        void __iomem *ioaddr;   /* Mapped address */