aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-4.14/819-sdhc-support-layerscape.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/layerscape/patches-4.14/819-sdhc-support-layerscape.patch')
-rw-r--r--target/linux/layerscape/patches-4.14/819-sdhc-support-layerscape.patch572
1 files changed, 0 insertions, 572 deletions
diff --git a/target/linux/layerscape/patches-4.14/819-sdhc-support-layerscape.patch b/target/linux/layerscape/patches-4.14/819-sdhc-support-layerscape.patch
deleted file mode 100644
index 02688c74cd..0000000000
--- a/target/linux/layerscape/patches-4.14/819-sdhc-support-layerscape.patch
+++ /dev/null
@@ -1,572 +0,0 @@
-From 6ca94d2e7dc72b21703e6d9be4e8ec3ad4a26f41 Mon Sep 17 00:00:00 2001
-From: Biwen Li <biwen.li@nxp.com>
-Date: Wed, 17 Apr 2019 18:59:02 +0800
-Subject: [PATCH] sdhc: support layerscape
-
-This is an integrated patch of sdhc for layerscape
-
-Signed-off-by: Biwen Li <biwen.li@nxp.com>
-Signed-off-by: Mathew McBride <matt@traverse.com.au>
-Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
-Signed-off-by: Yinbo Zhu <yinbo.zhu@nxp.com>
----
- drivers/mmc/core/mmc.c | 3 +
- drivers/mmc/host/sdhci-esdhc.h | 25 +++
- drivers/mmc/host/sdhci-of-esdhc.c | 270 ++++++++++++++++++++++++++----
- drivers/mmc/host/sdhci.c | 9 +-
- drivers/mmc/host/sdhci.h | 1 +
- include/linux/mmc/card.h | 1 +
- include/linux/mmc/host.h | 2 +
- 7 files changed, 272 insertions(+), 39 deletions(-)
-
---- a/drivers/mmc/core/mmc.c
-+++ b/drivers/mmc/core/mmc.c
-@@ -1174,6 +1174,9 @@ static int mmc_select_hs400(struct mmc_c
- goto out_err;
-
- /* Switch card to DDR */
-+ if (host->ops->prepare_ddr_to_hs400)
-+ host->ops->prepare_ddr_to_hs400(host);
-+
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_BUS_WIDTH,
- EXT_CSD_DDR_BUS_WIDTH_8,
---- a/drivers/mmc/host/sdhci-esdhc.h
-+++ b/drivers/mmc/host/sdhci-esdhc.h
-@@ -59,7 +59,32 @@
-
- /* Tuning Block Control Register */
- #define ESDHC_TBCTL 0x120
-+#define ESDHC_HS400_WNDW_ADJUST 0x00000040
-+#define ESDHC_HS400_MODE 0x00000010
- #define ESDHC_TB_EN 0x00000004
-+#define ESDHC_TBPTR 0x128
-+
-+/* SD Clock Control Register */
-+#define ESDHC_SDCLKCTL 0x144
-+#define ESDHC_LPBK_CLK_SEL 0x80000000
-+#define ESDHC_CMD_CLK_CTL 0x00008000
-+
-+/* SD Timing Control Register */
-+#define ESDHC_SDTIMNGCTL 0x148
-+#define ESDHC_FLW_CTL_BG 0x00008000
-+
-+/* DLL Config 0 Register */
-+#define ESDHC_DLLCFG0 0x160
-+#define ESDHC_DLL_ENABLE 0x80000000
-+#define ESDHC_DLL_FREQ_SEL 0x08000000
-+
-+/* DLL Config 1 Register */
-+#define ESDHC_DLLCFG1 0x164
-+#define ESDHC_DLL_PD_PULSE_STRETCH_SEL 0x80000000
-+
-+/* DLL Status 0 Register */
-+#define ESDHC_DLLSTAT0 0x170
-+#define ESDHC_DLL_STS_SLV_LOCK 0x08000000
-
- /* Control Register for DMA transfer */
- #define ESDHC_DMA_SYSCTL 0x40c
---- a/drivers/mmc/host/sdhci-of-esdhc.c
-+++ b/drivers/mmc/host/sdhci-of-esdhc.c
-@@ -30,11 +30,61 @@
- #define VENDOR_V_22 0x12
- #define VENDOR_V_23 0x13
-
-+#define MMC_TIMING_NUM (MMC_TIMING_MMC_HS400 + 1)
-+
-+struct esdhc_clk_fixup {
-+ const unsigned int sd_dflt_max_clk;
-+ const unsigned int max_clk[MMC_TIMING_NUM];
-+};
-+
-+static const struct esdhc_clk_fixup ls1021a_esdhc_clk = {
-+ .sd_dflt_max_clk = 25000000,
-+ .max_clk[MMC_TIMING_MMC_HS] = 46500000,
-+ .max_clk[MMC_TIMING_SD_HS] = 46500000,
-+};
-+
-+static const struct esdhc_clk_fixup ls1046a_esdhc_clk = {
-+ .sd_dflt_max_clk = 25000000,
-+ .max_clk[MMC_TIMING_UHS_SDR104] = 167000000,
-+ .max_clk[MMC_TIMING_MMC_HS200] = 167000000,
-+};
-+
-+static const struct esdhc_clk_fixup ls1012a_esdhc_clk = {
-+ .sd_dflt_max_clk = 25000000,
-+ .max_clk[MMC_TIMING_UHS_SDR104] = 125000000,
-+ .max_clk[MMC_TIMING_MMC_HS200] = 125000000,
-+};
-+
-+static const struct esdhc_clk_fixup p1010_esdhc_clk = {
-+ .sd_dflt_max_clk = 20000000,
-+ .max_clk[MMC_TIMING_LEGACY] = 20000000,
-+ .max_clk[MMC_TIMING_MMC_HS] = 42000000,
-+ .max_clk[MMC_TIMING_SD_HS] = 40000000,
-+};
-+
-+static const struct of_device_id sdhci_esdhc_of_match[] = {
-+ { .compatible = "fsl,ls1021a-esdhc", .data = &ls1021a_esdhc_clk},
-+ { .compatible = "fsl,ls1046a-esdhc", .data = &ls1046a_esdhc_clk},
-+ { .compatible = "fsl,ls1012a-esdhc", .data = &ls1012a_esdhc_clk},
-+ { .compatible = "fsl,p1010-esdhc", .data = &p1010_esdhc_clk},
-+ { .compatible = "fsl,mpc8379-esdhc" },
-+ { .compatible = "fsl,mpc8536-esdhc" },
-+ { .compatible = "fsl,esdhc" },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(of, sdhci_esdhc_of_match);
-+
- struct sdhci_esdhc {
- u8 vendor_ver;
- u8 spec_ver;
- bool quirk_incorrect_hostver;
-+ bool quirk_limited_clk_division;
-+ bool quirk_unreliable_pulse_detection;
-+ bool quirk_fixup_tuning;
-+ bool quirk_incorrect_delay_chain;
- unsigned int peripheral_clock;
-+ const struct esdhc_clk_fixup *clk_fixup;
-+ u32 div_ratio;
- };
-
- /**
-@@ -500,13 +550,20 @@ static void esdhc_clock_enable(struct sd
- }
- }
-
-+static struct soc_device_attribute soc_incorrect_delay_chain[] = {
-+ { .family = "QorIQ LX2160A", .revision = "1.0", },
-+ { },
-+};
-+
- static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
- {
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
- int pre_div = 1;
- int div = 1;
-+ int division;
- ktime_t timeout;
-+ long fixup = 0;
- u32 temp;
-
- host->mmc->actual_clock = 0;
-@@ -520,27 +577,14 @@ static void esdhc_of_set_clock(struct sd
- if (esdhc->vendor_ver < VENDOR_V_23)
- pre_div = 2;
-
-- /*
-- * Limit SD clock to 167MHz for ls1046a according to its datasheet
-- */
-- if (clock > 167000000 &&
-- of_find_compatible_node(NULL, NULL, "fsl,ls1046a-esdhc"))
-- clock = 167000000;
-+ if (host->mmc->card && mmc_card_sd(host->mmc->card) &&
-+ esdhc->clk_fixup && host->mmc->ios.timing == MMC_TIMING_LEGACY)
-+ fixup = esdhc->clk_fixup->sd_dflt_max_clk;
-+ else if (esdhc->clk_fixup)
-+ fixup = esdhc->clk_fixup->max_clk[host->mmc->ios.timing];
-
-- /*
-- * Limit SD clock to 125MHz for ls1012a according to its datasheet
-- */
-- if (clock > 125000000 &&
-- of_find_compatible_node(NULL, NULL, "fsl,ls1012a-esdhc"))
-- clock = 125000000;
--
-- /* Workaround to reduce the clock frequency for p1010 esdhc */
-- if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) {
-- if (clock > 20000000)
-- clock -= 5000000;
-- if (clock > 40000000)
-- clock -= 5000000;
-- }
-+ if (fixup && clock > fixup)
-+ clock = fixup;
-
- temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
- temp &= ~(ESDHC_CLOCK_SDCLKEN | ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN |
-@@ -553,9 +597,30 @@ static void esdhc_of_set_clock(struct sd
- while (host->max_clk / pre_div / div > clock && div < 16)
- div++;
-
-+ if (esdhc->quirk_limited_clk_division &&
-+ clock == MMC_HS200_MAX_DTR &&
-+ (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 ||
-+ host->flags & SDHCI_HS400_TUNING)) {
-+ division = pre_div * div;
-+ if (division <= 4) {
-+ pre_div = 4;
-+ div = 1;
-+ } else if (division <= 8) {
-+ pre_div = 4;
-+ div = 2;
-+ } else if (division <= 12) {
-+ pre_div = 4;
-+ div = 3;
-+ } else {
-+ pr_warn("%s: using upsupported clock division.\n",
-+ mmc_hostname(host->mmc));
-+ }
-+ }
-+
- dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
- clock, host->max_clk / pre_div / div);
- host->mmc->actual_clock = host->max_clk / pre_div / div;
-+ esdhc->div_ratio = pre_div * div;
- pre_div >>= 1;
- div--;
-
-@@ -565,6 +630,29 @@ static void esdhc_of_set_clock(struct sd
- | (pre_div << ESDHC_PREDIV_SHIFT));
- sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
-
-+ if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 &&
-+ clock == MMC_HS200_MAX_DTR) {
-+ temp = sdhci_readl(host, ESDHC_TBCTL);
-+ sdhci_writel(host, temp | ESDHC_HS400_MODE, ESDHC_TBCTL);
-+ temp = sdhci_readl(host, ESDHC_SDCLKCTL);
-+ sdhci_writel(host, temp | ESDHC_CMD_CLK_CTL, ESDHC_SDCLKCTL);
-+ esdhc_clock_enable(host, true);
-+
-+ temp = sdhci_readl(host, ESDHC_DLLCFG0);
-+ temp |= ESDHC_DLL_ENABLE;
-+ if (host->mmc->actual_clock == MMC_HS200_MAX_DTR ||
-+ esdhc->quirk_incorrect_delay_chain == false)
-+ temp |= ESDHC_DLL_FREQ_SEL;
-+ sdhci_writel(host, temp, ESDHC_DLLCFG0);
-+ temp = sdhci_readl(host, ESDHC_TBCTL);
-+ sdhci_writel(host, temp | ESDHC_HS400_WNDW_ADJUST, ESDHC_TBCTL);
-+
-+ esdhc_clock_enable(host, false);
-+ temp = sdhci_readl(host, ESDHC_DMA_SYSCTL);
-+ temp |= ESDHC_FLUSH_ASYNC_FIFO;
-+ sdhci_writel(host, temp, ESDHC_DMA_SYSCTL);
-+ }
-+
- /* Wait max 20 ms */
- timeout = ktime_add_ms(ktime_get(), 20);
- while (1) {
-@@ -580,6 +668,7 @@ static void esdhc_of_set_clock(struct sd
- udelay(10);
- }
-
-+ temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
- temp |= ESDHC_CLOCK_SDCLKEN;
- sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
- }
-@@ -608,6 +697,8 @@ static void esdhc_pltfm_set_bus_width(st
-
- static void esdhc_reset(struct sdhci_host *host, u8 mask)
- {
-+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-+ struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
- u32 val;
-
- sdhci_reset(host, mask);
-@@ -619,6 +710,12 @@ static void esdhc_reset(struct sdhci_hos
- val = sdhci_readl(host, ESDHC_TBCTL);
- val &= ~ESDHC_TB_EN;
- sdhci_writel(host, val, ESDHC_TBCTL);
-+
-+ if (esdhc->quirk_unreliable_pulse_detection) {
-+ val = sdhci_readl(host, ESDHC_DLLCFG1);
-+ val &= ~ESDHC_DLL_PD_PULSE_STRETCH_SEL;
-+ sdhci_writel(host, val, ESDHC_DLLCFG1);
-+ }
- }
- }
-
-@@ -630,6 +727,7 @@ static void esdhc_reset(struct sdhci_hos
- static const struct of_device_id scfg_device_ids[] = {
- { .compatible = "fsl,t1040-scfg", },
- { .compatible = "fsl,ls1012a-scfg", },
-+ { .compatible = "fsl,ls1043a-scfg", },
- { .compatible = "fsl,ls1046a-scfg", },
- {}
- };
-@@ -692,23 +790,91 @@ static int esdhc_signal_voltage_switch(s
- }
- }
-
--static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
-+static struct soc_device_attribute soc_fixup_tuning[] = {
-+ { .family = "QorIQ T1040", .revision = "1.0", },
-+ { .family = "QorIQ T2080", .revision = "1.0", },
-+ { .family = "QorIQ T1023", .revision = "1.0", },
-+ { .family = "QorIQ LS1021A", .revision = "1.0", },
-+ { .family = "QorIQ LS1080A", .revision = "1.0", },
-+ { .family = "QorIQ LS2080A", .revision = "1.0", },
-+ { .family = "QorIQ LS1012A", .revision = "1.0", },
-+ { .family = "QorIQ LS1043A", .revision = "1.*", },
-+ { .family = "QorIQ LS1046A", .revision = "1.0", },
-+ { },
-+};
-+
-+static void esdhc_tuning_block_enable(struct sdhci_host *host, bool enable)
- {
-- 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;
-+ if (enable)
-+ val |= ESDHC_TB_EN;
-+ else
-+ val &= ~ESDHC_TB_EN;
- sdhci_writel(host, val, ESDHC_TBCTL);
-+
- esdhc_clock_enable(host, true);
-+}
-+
-+static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
-+{
-+ struct sdhci_host *host = mmc_priv(mmc);
-+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-+ struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
-+ bool hs400_tuning;
-+ u32 val;
-+ int ret;
-+
-+ if (esdhc->quirk_limited_clk_division &&
-+ host->flags & SDHCI_HS400_TUNING)
-+ esdhc_of_set_clock(host, host->clock);
-+
-+ esdhc_tuning_block_enable(host, true);
-+
-+ hs400_tuning = host->flags & SDHCI_HS400_TUNING;
-+ ret = sdhci_execute_tuning(mmc, opcode);
-+
-+ if (hs400_tuning) {
-+ val = sdhci_readl(host, ESDHC_SDTIMNGCTL);
-+ val |= ESDHC_FLW_CTL_BG;
-+ sdhci_writel(host, val, ESDHC_SDTIMNGCTL);
-+ }
-
-- return sdhci_execute_tuning(mmc, opcode);
-+ if (host->tuning_err == -EAGAIN && esdhc->quirk_fixup_tuning) {
-+
-+ /* program TBPTR[TB_WNDW_END_PTR] = 3*DIV_RATIO and
-+ * program TBPTR[TB_WNDW_START_PTR] = 5*DIV_RATIO
-+ */
-+ val = sdhci_readl(host, ESDHC_TBPTR);
-+ val = (val & ~((0x7f << 8) | 0x7f)) |
-+ (3 * esdhc->div_ratio) | ((5 * esdhc->div_ratio) << 8);
-+ sdhci_writel(host, val, ESDHC_TBPTR);
-+
-+ /* program the software tuning mode by setting
-+ * TBCTL[TB_MODE]=2'h3
-+ */
-+ val = sdhci_readl(host, ESDHC_TBCTL);
-+ val |= 0x3;
-+ sdhci_writel(host, val, ESDHC_TBCTL);
-+ sdhci_execute_tuning(mmc, opcode);
-+ }
-+ return ret;
-+}
-+
-+static void esdhc_set_uhs_signaling(struct sdhci_host *host,
-+ unsigned int timing)
-+{
-+ if (timing == MMC_TIMING_MMC_HS400)
-+ esdhc_tuning_block_enable(host, true);
-+ else
-+ sdhci_set_uhs_signaling(host, timing);
- }
-
- #ifdef CONFIG_PM_SLEEP
-@@ -757,7 +923,7 @@ static const struct sdhci_ops sdhci_esdh
- .adma_workaround = esdhc_of_adma_workaround,
- .set_bus_width = esdhc_pltfm_set_bus_width,
- .reset = esdhc_reset,
-- .set_uhs_signaling = sdhci_set_uhs_signaling,
-+ .set_uhs_signaling = esdhc_set_uhs_signaling,
- };
-
- static const struct sdhci_ops sdhci_esdhc_le_ops = {
-@@ -774,7 +940,7 @@ static const struct sdhci_ops sdhci_esdh
- .adma_workaround = esdhc_of_adma_workaround,
- .set_bus_width = esdhc_pltfm_set_bus_width,
- .reset = esdhc_reset,
-- .set_uhs_signaling = sdhci_set_uhs_signaling,
-+ .set_uhs_signaling = esdhc_set_uhs_signaling,
- };
-
- static const struct sdhci_pltfm_data sdhci_esdhc_be_pdata = {
-@@ -800,8 +966,20 @@ static struct soc_device_attribute soc_i
- { },
- };
-
-+static struct soc_device_attribute soc_fixup_sdhc_clkdivs[] = {
-+ { .family = "QorIQ LX2160A", .revision = "1.0", },
-+ { .family = "QorIQ LX2160A", .revision = "2.0", },
-+ { },
-+};
-+
-+static struct soc_device_attribute soc_unreliable_pulse_detection[] = {
-+ { .family = "QorIQ LX2160A", .revision = "1.0", },
-+ { },
-+};
-+
- static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
- {
-+ const struct of_device_id *match;
- struct sdhci_pltfm_host *pltfm_host;
- struct sdhci_esdhc *esdhc;
- struct device_node *np;
-@@ -821,6 +999,24 @@ static void esdhc_init(struct platform_d
- else
- esdhc->quirk_incorrect_hostver = false;
-
-+ if (soc_device_match(soc_fixup_sdhc_clkdivs))
-+ esdhc->quirk_limited_clk_division = true;
-+ else
-+ esdhc->quirk_limited_clk_division = false;
-+
-+ if (soc_device_match(soc_unreliable_pulse_detection))
-+ esdhc->quirk_unreliable_pulse_detection = true;
-+ else
-+ esdhc->quirk_unreliable_pulse_detection = false;
-+
-+ if (soc_device_match(soc_incorrect_delay_chain))
-+ esdhc->quirk_incorrect_delay_chain = true;
-+ else
-+ esdhc->quirk_incorrect_delay_chain = false;
-+
-+ match = of_match_node(sdhci_esdhc_of_match, pdev->dev.of_node);
-+ if (match)
-+ esdhc->clk_fixup = match->data;
- np = pdev->dev.of_node;
- clk = of_clk_get(np, 0);
- if (!IS_ERR(clk)) {
-@@ -848,6 +1044,12 @@ static void esdhc_init(struct platform_d
- }
- }
-
-+static int esdhc_prepare_ddr_to_hs400(struct mmc_host *mmc)
-+{
-+ esdhc_tuning_block_enable(mmc_priv(mmc), false);
-+ return 0;
-+}
-+
- static int sdhci_esdhc_probe(struct platform_device *pdev)
- {
- struct sdhci_host *host;
-@@ -871,6 +1073,7 @@ static int sdhci_esdhc_probe(struct plat
- host->mmc_host_ops.start_signal_voltage_switch =
- esdhc_signal_voltage_switch;
- host->mmc_host_ops.execute_tuning = esdhc_execute_tuning;
-+ host->mmc_host_ops.prepare_ddr_to_hs400 = esdhc_prepare_ddr_to_hs400;
- host->tuning_delay = 1;
-
- esdhc_init(pdev, host);
-@@ -879,6 +1082,11 @@ static int sdhci_esdhc_probe(struct plat
-
- pltfm_host = sdhci_priv(host);
- esdhc = sdhci_pltfm_priv(pltfm_host);
-+ if (soc_device_match(soc_fixup_tuning))
-+ esdhc->quirk_fixup_tuning = true;
-+ else
-+ esdhc->quirk_fixup_tuning = false;
-+
- if (esdhc->vendor_ver == VENDOR_V_22)
- host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
-
-@@ -925,14 +1133,6 @@ static int sdhci_esdhc_probe(struct plat
- return ret;
- }
-
--static const struct of_device_id sdhci_esdhc_of_match[] = {
-- { .compatible = "fsl,mpc8379-esdhc" },
-- { .compatible = "fsl,mpc8536-esdhc" },
-- { .compatible = "fsl,esdhc" },
-- { }
--};
--MODULE_DEVICE_TABLE(of, sdhci_esdhc_of_match);
--
- static struct platform_driver sdhci_esdhc_driver = {
- .driver = {
- .name = "sdhci-esdhc",
---- a/drivers/mmc/host/sdhci.c
-+++ b/drivers/mmc/host/sdhci.c
-@@ -2148,7 +2148,7 @@ static void sdhci_send_tuning(struct sdh
-
- }
-
--static void __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
-+static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
- {
- int i;
-
-@@ -2165,13 +2165,13 @@ static void __sdhci_execute_tuning(struc
- pr_debug("%s: Tuning timeout, falling back to fixed sampling clock\n",
- mmc_hostname(host->mmc));
- sdhci_abort_tuning(host, opcode);
-- return;
-+ return -ETIMEDOUT;
- }
-
- ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) {
- if (ctrl & SDHCI_CTRL_TUNED_CLK)
-- return; /* Success! */
-+ return 0; /* Success! */
- break;
- }
-
-@@ -2183,6 +2183,7 @@ static void __sdhci_execute_tuning(struc
- pr_info("%s: Tuning failed, falling back to fixed sampling clock\n",
- mmc_hostname(host->mmc));
- sdhci_reset_tuning(host);
-+ return -EAGAIN;
- }
-
- int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
-@@ -2244,7 +2245,7 @@ int sdhci_execute_tuning(struct mmc_host
-
- sdhci_start_tuning(host);
-
-- __sdhci_execute_tuning(host, opcode);
-+ host->tuning_err = __sdhci_execute_tuning(host, opcode);
-
- sdhci_end_tuning(host);
- out:
---- a/drivers/mmc/host/sdhci.h
-+++ b/drivers/mmc/host/sdhci.h
-@@ -545,6 +545,7 @@ struct sdhci_host {
-
- unsigned int tuning_count; /* Timer count for re-tuning */
- unsigned int tuning_mode; /* Re-tuning mode supported by host */
-+ unsigned int tuning_err; /* Error code for re-tuning */
- #define SDHCI_TUNING_MODE_1 0
- #define SDHCI_TUNING_MODE_2 1
- #define SDHCI_TUNING_MODE_3 2
---- a/include/linux/mmc/card.h
-+++ b/include/linux/mmc/card.h
-@@ -156,6 +156,7 @@ struct sd_switch_caps {
- #define UHS_DDR50_MAX_DTR 50000000
- #define UHS_SDR25_MAX_DTR UHS_DDR50_MAX_DTR
- #define UHS_SDR12_MAX_DTR 25000000
-+#define DEFAULT_SPEED_MAX_DTR UHS_SDR12_MAX_DTR
- unsigned int sd3_bus_mode;
- #define UHS_SDR12_BUS_SPEED 0
- #define HIGH_SPEED_BUS_SPEED 1
---- a/include/linux/mmc/host.h
-+++ b/include/linux/mmc/host.h
-@@ -145,6 +145,8 @@ struct mmc_host_ops {
-
- /* Prepare HS400 target operating frequency depending host driver */
- int (*prepare_hs400_tuning)(struct mmc_host *host, struct mmc_ios *ios);
-+ int (*prepare_ddr_to_hs400)(struct mmc_host *host);
-+
- /* Prepare enhanced strobe depending host driver */
- void (*hs400_enhanced_strobe)(struct mmc_host *host,
- struct mmc_ios *ios);