diff options
Diffstat (limited to 'target/linux/layerscape/patches-4.9/812-mmc-layerscape-support.patch')
-rw-r--r-- | target/linux/layerscape/patches-4.9/812-mmc-layerscape-support.patch | 594 |
1 files changed, 0 insertions, 594 deletions
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 index 4b32417379..0000000000 --- a/target/linux/layerscape/patches-4.9/812-mmc-layerscape-support.patch +++ /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); |