layerscape: drop kernel 4.9 support
[openwrt/staging/wigyori.git] / target / linux / layerscape / patches-4.9 / 812-mmc-layerscape-support.patch
diff --git a/target/linux/layerscape/patches-4.9/812-mmc-layerscape-support.patch b/target/linux/layerscape/patches-4.9/812-mmc-layerscape-support.patch
deleted file mode 100644 (file)
index 4b32417..0000000
+++ /dev/null
@@ -1,594 +0,0 @@
-From 4215d5757595e7ec7ca146c2b901beb177f415d8 Mon Sep 17 00:00:00 2001
-From: Yangbo Lu <yangbo.lu@nxp.com>
-Date: Wed, 17 Jan 2018 15:37:13 +0800
-Subject: [PATCH 24/30] mmc: layerscape support
-
-This is an integrated patch for layerscape mmc support.
-
-Adrian Hunter <adrian.hunter@intel.com>
-Jaehoon Chung <jh80.chung@samsung.com>
-Masahiro Yamada <yamada.masahiro@socionext.com>
-Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
----
- drivers/mmc/host/Kconfig          |   1 +
- drivers/mmc/host/sdhci-esdhc.h    |  52 +++++---
- drivers/mmc/host/sdhci-of-esdhc.c | 265 ++++++++++++++++++++++++++++++++++++--
- drivers/mmc/host/sdhci.c          |  45 ++++---
- drivers/mmc/host/sdhci.h          |   3 +
- 5 files changed, 320 insertions(+), 46 deletions(-)
-
---- a/drivers/mmc/host/Kconfig
-+++ b/drivers/mmc/host/Kconfig
-@@ -144,6 +144,7 @@ config MMC_SDHCI_OF_ESDHC
-       depends on MMC_SDHCI_PLTFM
-       depends on PPC || ARCH_MXC || ARCH_LAYERSCAPE
-       select MMC_SDHCI_IO_ACCESSORS
-+      select FSL_GUTS
-       help
-         This selects the Freescale eSDHC controller support.
---- a/drivers/mmc/host/sdhci-esdhc.h
-+++ b/drivers/mmc/host/sdhci-esdhc.h
-@@ -24,30 +24,46 @@
-                               SDHCI_QUIRK_PIO_NEEDS_DELAY | \
-                               SDHCI_QUIRK_NO_HISPD_BIT)
--#define ESDHC_PROCTL          0x28
--
--#define ESDHC_SYSTEM_CONTROL  0x2c
--#define ESDHC_CLOCK_MASK      0x0000fff0
--#define ESDHC_PREDIV_SHIFT    8
--#define ESDHC_DIVIDER_SHIFT   4
--#define ESDHC_CLOCK_PEREN     0x00000004
--#define ESDHC_CLOCK_HCKEN     0x00000002
--#define ESDHC_CLOCK_IPGEN     0x00000001
--
- /* pltfm-specific */
- #define ESDHC_HOST_CONTROL_LE 0x20
- /*
-- * P2020 interpretation of the SDHCI_HOST_CONTROL register
-+ * eSDHC register definition
-  */
--#define ESDHC_CTRL_4BITBUS          (0x1 << 1)
--#define ESDHC_CTRL_8BITBUS          (0x2 << 1)
--#define ESDHC_CTRL_BUSWIDTH_MASK    (0x3 << 1)
--
--/* OF-specific */
--#define ESDHC_DMA_SYSCTL      0x40c
--#define ESDHC_DMA_SNOOP               0x00000040
--#define ESDHC_HOST_CONTROL_RES        0x01
-+/* Present State Register */
-+#define ESDHC_PRSSTAT                 0x24
-+#define ESDHC_CLOCK_STABLE            0x00000008
-+
-+/* Protocol Control Register */
-+#define ESDHC_PROCTL                  0x28
-+#define ESDHC_VOLT_SEL                        0x00000400
-+#define ESDHC_CTRL_4BITBUS            (0x1 << 1)
-+#define ESDHC_CTRL_8BITBUS            (0x2 << 1)
-+#define ESDHC_CTRL_BUSWIDTH_MASK      (0x3 << 1)
-+#define ESDHC_HOST_CONTROL_RES                0x01
-+
-+/* System Control Register */
-+#define ESDHC_SYSTEM_CONTROL          0x2c
-+#define ESDHC_CLOCK_MASK              0x0000fff0
-+#define ESDHC_PREDIV_SHIFT            8
-+#define ESDHC_DIVIDER_SHIFT           4
-+#define ESDHC_CLOCK_SDCLKEN           0x00000008
-+#define ESDHC_CLOCK_PEREN             0x00000004
-+#define ESDHC_CLOCK_HCKEN             0x00000002
-+#define ESDHC_CLOCK_IPGEN             0x00000001
-+
-+/* Host Controller Capabilities Register 2 */
-+#define ESDHC_CAPABILITIES_1          0x114
-+
-+/* Tuning Block Control Register */
-+#define ESDHC_TBCTL                   0x120
-+#define ESDHC_TB_EN                   0x00000004
-+
-+/* Control Register for DMA transfer */
-+#define ESDHC_DMA_SYSCTL              0x40c
-+#define ESDHC_PERIPHERAL_CLK_SEL      0x00080000
-+#define ESDHC_FLUSH_ASYNC_FIFO                0x00040000
-+#define ESDHC_DMA_SNOOP                       0x00000040
- #endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */
---- a/drivers/mmc/host/sdhci-of-esdhc.c
-+++ b/drivers/mmc/host/sdhci-of-esdhc.c
-@@ -16,8 +16,12 @@
- #include <linux/err.h>
- #include <linux/io.h>
- #include <linux/of.h>
-+#include <linux/of_address.h>
- #include <linux/delay.h>
- #include <linux/module.h>
-+#include <linux/sys_soc.h>
-+#include <linux/clk.h>
-+#include <linux/ktime.h>
- #include <linux/mmc/host.h>
- #include "sdhci-pltfm.h"
- #include "sdhci-esdhc.h"
-@@ -28,8 +32,12 @@
- struct sdhci_esdhc {
-       u8 vendor_ver;
-       u8 spec_ver;
-+      bool quirk_incorrect_hostver;
-+      unsigned int peripheral_clock;
- };
-+static void esdhc_clock_enable(struct sdhci_host *host, bool enable);
-+
- /**
-  * esdhc_read*_fixup - Fixup the value read from incompatible eSDHC register
-  *                   to make it compatible with SD spec.
-@@ -80,6 +88,17 @@ static u32 esdhc_readl_fixup(struct sdhc
-               return ret;
-       }
-+      /*
-+       * DTS properties of mmc host are used to enable each speed mode
-+       * according to soc and board capability. So clean up
-+       * SDR50/SDR104/DDR50 support bits here.
-+       */
-+      if (spec_reg == SDHCI_CAPABILITIES_1) {
-+              ret = value & (~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 |
-+                               SDHCI_SUPPORT_DDR50));
-+              return ret;
-+      }
-+
-       ret = value;
-       return ret;
- }
-@@ -87,6 +106,8 @@ static u32 esdhc_readl_fixup(struct sdhc
- static u16 esdhc_readw_fixup(struct sdhci_host *host,
-                                    int spec_reg, u32 value)
- {
-+      struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-+      struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
-       u16 ret;
-       int shift = (spec_reg & 0x2) * 8;
-@@ -94,6 +115,12 @@ static u16 esdhc_readw_fixup(struct sdhc
-               ret = value & 0xffff;
-       else
-               ret = (value >> shift) & 0xffff;
-+      /* Workaround for T4240-R1.0-R2.0 eSDHC which has incorrect
-+       * vendor version and spec version information.
-+       */
-+      if ((spec_reg == SDHCI_HOST_VERSION) &&
-+          (esdhc->quirk_incorrect_hostver))
-+              ret = (VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) | SDHCI_SPEC_200;
-       return ret;
- }
-@@ -235,7 +262,11 @@ static u32 esdhc_be_readl(struct sdhci_h
-       u32 ret;
-       u32 value;
--      value = ioread32be(host->ioaddr + reg);
-+      if (reg == SDHCI_CAPABILITIES_1)
-+              value = ioread32be(host->ioaddr + ESDHC_CAPABILITIES_1);
-+      else
-+              value = ioread32be(host->ioaddr + reg);
-+
-       ret = esdhc_readl_fixup(host, reg, value);
-       return ret;
-@@ -246,7 +277,11 @@ static u32 esdhc_le_readl(struct sdhci_h
-       u32 ret;
-       u32 value;
--      value = ioread32(host->ioaddr + reg);
-+      if (reg == SDHCI_CAPABILITIES_1)
-+              value = ioread32(host->ioaddr + ESDHC_CAPABILITIES_1);
-+      else
-+              value = ioread32(host->ioaddr + reg);
-+
-       ret = esdhc_readl_fixup(host, reg, value);
-       return ret;
-@@ -404,15 +439,25 @@ static int esdhc_of_enable_dma(struct sd
- static unsigned int esdhc_of_get_max_clock(struct sdhci_host *host)
- {
-       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-+      struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
--      return pltfm_host->clock;
-+      if (esdhc->peripheral_clock)
-+              return esdhc->peripheral_clock;
-+      else
-+              return pltfm_host->clock;
- }
- static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
- {
-       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-+      struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
-+      unsigned int clock;
--      return pltfm_host->clock / 256 / 16;
-+      if (esdhc->peripheral_clock)
-+              clock = esdhc->peripheral_clock;
-+      else
-+              clock = pltfm_host->clock;
-+      return clock / 256 / 16;
- }
- static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
-@@ -421,12 +466,15 @@ static void esdhc_of_set_clock(struct sd
-       struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
-       int pre_div = 1;
-       int div = 1;
-+      ktime_t timeout;
-       u32 temp;
-       host->mmc->actual_clock = 0;
--      if (clock == 0)
-+      if (clock == 0) {
-+              esdhc_clock_enable(host, false);
-               return;
-+      }
-       /* Workaround to start pre_div at 2 for VNN < VENDOR_V_23 */
-       if (esdhc->vendor_ver < VENDOR_V_23)
-@@ -454,9 +502,15 @@ static void esdhc_of_set_clock(struct sd
-                       clock -= 5000000;
-       }
-+      /* Workaround to reduce the clock frequency for ls1021a esdhc */
-+      if (of_find_compatible_node(NULL, NULL, "fsl,ls1021a-esdhc")) {
-+              if (clock == 50000000)
-+                      clock = 46500000;
-+      }
-+
-       temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
--      temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
--              | ESDHC_CLOCK_MASK);
-+      temp &= ~(ESDHC_CLOCK_SDCLKEN | ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN |
-+                ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK);
-       sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
-       while (host->max_clk / pre_div / 16 > clock && pre_div < 256)
-@@ -476,7 +530,20 @@ static void esdhc_of_set_clock(struct sd
-               | (div << ESDHC_DIVIDER_SHIFT)
-               | (pre_div << ESDHC_PREDIV_SHIFT));
-       sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
--      mdelay(1);
-+
-+      /* Wait max 20 ms */
-+      timeout = ktime_add_ms(ktime_get(), 20);
-+      while (!(sdhci_readl(host, ESDHC_PRSSTAT) & ESDHC_CLOCK_STABLE)) {
-+              if (ktime_after(ktime_get(), timeout)) {
-+                      pr_err("%s: Internal clock never stabilised.\n",
-+                              mmc_hostname(host->mmc));
-+                      return;
-+              }
-+              udelay(10);
-+      }
-+
-+      temp |= ESDHC_CLOCK_SDCLKEN;
-+      sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
- }
- static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
-@@ -501,12 +568,136 @@ static void esdhc_pltfm_set_bus_width(st
-       sdhci_writel(host, ctrl, ESDHC_PROCTL);
- }
-+static void esdhc_clock_enable(struct sdhci_host *host, bool enable)
-+{
-+      u32 val;
-+      ktime_t timeout;
-+
-+      val = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
-+
-+      if (enable)
-+              val |= ESDHC_CLOCK_SDCLKEN;
-+      else
-+              val &= ~ESDHC_CLOCK_SDCLKEN;
-+
-+      sdhci_writel(host, val, ESDHC_SYSTEM_CONTROL);
-+
-+      /* Wait max 20 ms */
-+      timeout = ktime_add_ms(ktime_get(), 20);
-+      val = ESDHC_CLOCK_STABLE;
-+      while (!(sdhci_readl(host, ESDHC_PRSSTAT) & val)) {
-+              if (ktime_after(ktime_get(), timeout)) {
-+                      pr_err("%s: Internal clock never stabilised.\n",
-+                              mmc_hostname(host->mmc));
-+                      break;
-+              }
-+              udelay(10);
-+      }
-+}
-+
- static void esdhc_reset(struct sdhci_host *host, u8 mask)
- {
-+      u32 val;
-+
-       sdhci_reset(host, mask);
-       sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
-       sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
-+
-+      if (mask & SDHCI_RESET_ALL) {
-+              val = sdhci_readl(host, ESDHC_TBCTL);
-+              val &= ~ESDHC_TB_EN;
-+              sdhci_writel(host, val, ESDHC_TBCTL);
-+      }
-+}
-+
-+/* The SCFG, Supplemental Configuration Unit, provides SoC specific
-+ * configuration and status registers for the device. There is a
-+ * SDHC IO VSEL control register on SCFG for some platforms. It's
-+ * used to support SDHC IO voltage switching.
-+ */
-+static const struct of_device_id scfg_device_ids[] = {
-+      { .compatible = "fsl,t1040-scfg", },
-+      { .compatible = "fsl,ls1012a-scfg", },
-+      { .compatible = "fsl,ls1046a-scfg", },
-+      {}
-+};
-+
-+/* SDHC IO VSEL control register definition */
-+#define SCFG_SDHCIOVSELCR     0x408
-+#define SDHCIOVSELCR_TGLEN    0x80000000
-+#define SDHCIOVSELCR_VSELVAL  0x60000000
-+#define SDHCIOVSELCR_SDHC_VS  0x00000001
-+
-+static int esdhc_signal_voltage_switch(struct mmc_host *mmc,
-+                                     struct mmc_ios *ios)
-+{
-+      struct sdhci_host *host = mmc_priv(mmc);
-+      struct device_node *scfg_node;
-+      void __iomem *scfg_base = NULL;
-+      u32 sdhciovselcr;
-+      u32 val;
-+
-+      /*
-+       * Signal Voltage Switching is only applicable for Host Controllers
-+       * v3.00 and above.
-+       */
-+      if (host->version < SDHCI_SPEC_300)
-+              return 0;
-+
-+      val = sdhci_readl(host, ESDHC_PROCTL);
-+
-+      switch (ios->signal_voltage) {
-+      case MMC_SIGNAL_VOLTAGE_330:
-+              val &= ~ESDHC_VOLT_SEL;
-+              sdhci_writel(host, val, ESDHC_PROCTL);
-+              return 0;
-+      case MMC_SIGNAL_VOLTAGE_180:
-+              scfg_node = of_find_matching_node(NULL, scfg_device_ids);
-+              if (scfg_node)
-+                      scfg_base = of_iomap(scfg_node, 0);
-+              if (scfg_base) {
-+                      sdhciovselcr = SDHCIOVSELCR_TGLEN |
-+                                     SDHCIOVSELCR_VSELVAL;
-+                      iowrite32be(sdhciovselcr,
-+                              scfg_base + SCFG_SDHCIOVSELCR);
-+
-+                      val |= ESDHC_VOLT_SEL;
-+                      sdhci_writel(host, val, ESDHC_PROCTL);
-+                      mdelay(5);
-+
-+                      sdhciovselcr = SDHCIOVSELCR_TGLEN |
-+                                     SDHCIOVSELCR_SDHC_VS;
-+                      iowrite32be(sdhciovselcr,
-+                              scfg_base + SCFG_SDHCIOVSELCR);
-+                      iounmap(scfg_base);
-+              } else {
-+                      val |= ESDHC_VOLT_SEL;
-+                      sdhci_writel(host, val, ESDHC_PROCTL);
-+              }
-+              return 0;
-+      default:
-+              return 0;
-+      }
-+}
-+
-+static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
-+{
-+      struct sdhci_host *host = mmc_priv(mmc);
-+      u32 val;
-+
-+      /* Use tuning block for tuning procedure */
-+      esdhc_clock_enable(host, false);
-+      val = sdhci_readl(host, ESDHC_DMA_SYSCTL);
-+      val |= ESDHC_FLUSH_ASYNC_FIFO;
-+      sdhci_writel(host, val, ESDHC_DMA_SYSCTL);
-+
-+      val = sdhci_readl(host, ESDHC_TBCTL);
-+      val |= ESDHC_TB_EN;
-+      sdhci_writel(host, val, ESDHC_TBCTL);
-+      esdhc_clock_enable(host, true);
-+
-+      return sdhci_execute_tuning(mmc, opcode);
- }
- #ifdef CONFIG_PM_SLEEP
-@@ -589,10 +780,19 @@ static const struct sdhci_pltfm_data sdh
-       .ops = &sdhci_esdhc_le_ops,
- };
-+static struct soc_device_attribute soc_incorrect_hostver[] = {
-+      { .family = "QorIQ T4240", .revision = "1.0", },
-+      { .family = "QorIQ T4240", .revision = "2.0", },
-+      { },
-+};
-+
- static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
- {
-       struct sdhci_pltfm_host *pltfm_host;
-       struct sdhci_esdhc *esdhc;
-+      struct device_node *np;
-+      struct clk *clk;
-+      u32 val;
-       u16 host_ver;
-       pltfm_host = sdhci_priv(host);
-@@ -602,6 +802,36 @@ static void esdhc_init(struct platform_d
-       esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >>
-                            SDHCI_VENDOR_VER_SHIFT;
-       esdhc->spec_ver = host_ver & SDHCI_SPEC_VER_MASK;
-+      if (soc_device_match(soc_incorrect_hostver))
-+              esdhc->quirk_incorrect_hostver = true;
-+      else
-+              esdhc->quirk_incorrect_hostver = false;
-+
-+      np = pdev->dev.of_node;
-+      clk = of_clk_get(np, 0);
-+      if (!IS_ERR(clk)) {
-+              /*
-+               * esdhc->peripheral_clock would be assigned with a value
-+               * which is eSDHC base clock when use periperal clock.
-+               * For ls1046a, the clock value got by common clk API is
-+               * peripheral clock while the eSDHC base clock is 1/2
-+               * peripheral clock.
-+               */
-+              if (of_device_is_compatible(np, "fsl,ls1046a-esdhc"))
-+                      esdhc->peripheral_clock = clk_get_rate(clk) / 2;
-+              else
-+                      esdhc->peripheral_clock = clk_get_rate(clk);
-+
-+              clk_put(clk);
-+      }
-+
-+      if (esdhc->peripheral_clock) {
-+              esdhc_clock_enable(host, false);
-+              val = sdhci_readl(host, ESDHC_DMA_SYSCTL);
-+              val |= ESDHC_PERIPHERAL_CLK_SEL;
-+              sdhci_writel(host, val, ESDHC_DMA_SYSCTL);
-+              esdhc_clock_enable(host, true);
-+      }
- }
- static int sdhci_esdhc_probe(struct platform_device *pdev)
-@@ -624,6 +854,11 @@ static int sdhci_esdhc_probe(struct plat
-       if (IS_ERR(host))
-               return PTR_ERR(host);
-+      host->mmc_host_ops.start_signal_voltage_switch =
-+              esdhc_signal_voltage_switch;
-+      host->mmc_host_ops.execute_tuning = esdhc_execute_tuning;
-+      host->tuning_delay = 1;
-+
-       esdhc_init(pdev, host);
-       sdhci_get_of_property(pdev);
---- a/drivers/mmc/host/sdhci.c
-+++ b/drivers/mmc/host/sdhci.c
-@@ -1631,26 +1631,24 @@ static void sdhci_set_ios(struct mmc_hos
-       ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
--      if ((ios->timing == MMC_TIMING_SD_HS ||
--           ios->timing == MMC_TIMING_MMC_HS)
--          && !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT))
--              ctrl |= SDHCI_CTRL_HISPD;
--      else
--              ctrl &= ~SDHCI_CTRL_HISPD;
-+      if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) {
-+              if ((ios->timing == MMC_TIMING_SD_HS ||
-+                   ios->timing == MMC_TIMING_MMC_HS ||
-+                   ios->timing == MMC_TIMING_MMC_HS400 ||
-+                   ios->timing == MMC_TIMING_MMC_HS200 ||
-+                   ios->timing == MMC_TIMING_MMC_DDR52 ||
-+                   ios->timing == MMC_TIMING_UHS_SDR50 ||
-+                   ios->timing == MMC_TIMING_UHS_SDR104 ||
-+                   ios->timing == MMC_TIMING_UHS_DDR50 ||
-+                   ios->timing == MMC_TIMING_UHS_SDR25))
-+                      ctrl |= SDHCI_CTRL_HISPD;
-+              else
-+                      ctrl &= ~SDHCI_CTRL_HISPD;
-+      }
-       if (host->version >= SDHCI_SPEC_300) {
-               u16 clk, ctrl_2;
--              /* In case of UHS-I modes, set High Speed Enable */
--              if ((ios->timing == MMC_TIMING_MMC_HS400) ||
--                  (ios->timing == MMC_TIMING_MMC_HS200) ||
--                  (ios->timing == MMC_TIMING_MMC_DDR52) ||
--                  (ios->timing == MMC_TIMING_UHS_SDR50) ||
--                  (ios->timing == MMC_TIMING_UHS_SDR104) ||
--                  (ios->timing == MMC_TIMING_UHS_DDR50) ||
--                  (ios->timing == MMC_TIMING_UHS_SDR25))
--                      ctrl |= SDHCI_CTRL_HISPD;
--
-               if (!host->preset_enabled) {
-                       sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-                       /*
-@@ -1963,7 +1961,7 @@ static int sdhci_prepare_hs400_tuning(st
-       return 0;
- }
--static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
-+int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
- {
-       struct sdhci_host *host = mmc_priv(mmc);
-       u16 ctrl;
-@@ -2022,6 +2020,9 @@ static int sdhci_execute_tuning(struct m
-               return err;
-       }
-+      if (host->tuning_delay < 0)
-+      host->tuning_delay = opcode == MMC_SEND_TUNING_BLOCK;
-+
-       ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-       ctrl |= SDHCI_CTRL_EXEC_TUNING;
-       if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND)
-@@ -2134,9 +2135,10 @@ static int sdhci_execute_tuning(struct m
-               ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
--              /* eMMC spec does not require a delay between tuning cycles */
--              if (opcode == MMC_SEND_TUNING_BLOCK)
--                      mdelay(1);
-+              /* Spec does not require a delay between tuning cycles */
-+              if (host->tuning_delay > 0)
-+              mdelay(host->tuning_delay);
-+
-       } while (ctrl & SDHCI_CTRL_EXEC_TUNING);
-       /*
-@@ -2172,6 +2174,7 @@ out_unlock:
-       spin_unlock_irqrestore(&host->lock, flags);
-       return err;
- }
-+EXPORT_SYMBOL_GPL(sdhci_execute_tuning);
- static int sdhci_select_drive_strength(struct mmc_card *card,
-                                      unsigned int max_dtr, int host_drv,
-@@ -3004,6 +3007,8 @@ struct sdhci_host *sdhci_alloc_host(stru
-       host->flags = SDHCI_SIGNALING_330;
-+      host->tuning_delay = -1;
-+
-       return host;
- }
---- a/drivers/mmc/host/sdhci.h
-+++ b/drivers/mmc/host/sdhci.h
-@@ -524,6 +524,8 @@ struct sdhci_host {
- #define SDHCI_TUNING_MODE_1   0
- #define SDHCI_TUNING_MODE_2   1
- #define SDHCI_TUNING_MODE_3   2
-+      /* Delay (ms) between tuning commands */
-+      int                     tuning_delay;
-       unsigned long private[0] ____cacheline_aligned;
- };
-@@ -689,6 +691,7 @@ void sdhci_set_power_noreg(struct sdhci_
- void sdhci_set_bus_width(struct sdhci_host *host, int width);
- void sdhci_reset(struct sdhci_host *host, u8 mask);
- void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
-+int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
- #ifdef CONFIG_PM
- extern int sdhci_suspend_host(struct sdhci_host *host);