uclient: update to Git HEAD (2024-04-19)
[openwrt/openwrt.git] / target / linux / layerscape / patches-4.14 / 819-sdhc-support-layerscape.patch
1 From 6ca94d2e7dc72b21703e6d9be4e8ec3ad4a26f41 Mon Sep 17 00:00:00 2001
2 From: Biwen Li <biwen.li@nxp.com>
3 Date: Wed, 17 Apr 2019 18:59:02 +0800
4 Subject: [PATCH] sdhc: support layerscape
5
6 This is an integrated patch of sdhc for layerscape
7
8 Signed-off-by: Biwen Li <biwen.li@nxp.com>
9 Signed-off-by: Mathew McBride <matt@traverse.com.au>
10 Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
11 Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
12 Signed-off-by: Yinbo Zhu <yinbo.zhu@nxp.com>
13 ---
14 drivers/mmc/core/mmc.c | 3 +
15 drivers/mmc/host/sdhci-esdhc.h | 25 +++
16 drivers/mmc/host/sdhci-of-esdhc.c | 270 ++++++++++++++++++++++++++----
17 drivers/mmc/host/sdhci.c | 9 +-
18 drivers/mmc/host/sdhci.h | 1 +
19 include/linux/mmc/card.h | 1 +
20 include/linux/mmc/host.h | 2 +
21 7 files changed, 272 insertions(+), 39 deletions(-)
22
23 --- a/drivers/mmc/core/mmc.c
24 +++ b/drivers/mmc/core/mmc.c
25 @@ -1174,6 +1174,9 @@ static int mmc_select_hs400(struct mmc_c
26 goto out_err;
27
28 /* Switch card to DDR */
29 + if (host->ops->prepare_ddr_to_hs400)
30 + host->ops->prepare_ddr_to_hs400(host);
31 +
32 err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
33 EXT_CSD_BUS_WIDTH,
34 EXT_CSD_DDR_BUS_WIDTH_8,
35 --- a/drivers/mmc/host/sdhci-esdhc.h
36 +++ b/drivers/mmc/host/sdhci-esdhc.h
37 @@ -59,7 +59,32 @@
38
39 /* Tuning Block Control Register */
40 #define ESDHC_TBCTL 0x120
41 +#define ESDHC_HS400_WNDW_ADJUST 0x00000040
42 +#define ESDHC_HS400_MODE 0x00000010
43 #define ESDHC_TB_EN 0x00000004
44 +#define ESDHC_TBPTR 0x128
45 +
46 +/* SD Clock Control Register */
47 +#define ESDHC_SDCLKCTL 0x144
48 +#define ESDHC_LPBK_CLK_SEL 0x80000000
49 +#define ESDHC_CMD_CLK_CTL 0x00008000
50 +
51 +/* SD Timing Control Register */
52 +#define ESDHC_SDTIMNGCTL 0x148
53 +#define ESDHC_FLW_CTL_BG 0x00008000
54 +
55 +/* DLL Config 0 Register */
56 +#define ESDHC_DLLCFG0 0x160
57 +#define ESDHC_DLL_ENABLE 0x80000000
58 +#define ESDHC_DLL_FREQ_SEL 0x08000000
59 +
60 +/* DLL Config 1 Register */
61 +#define ESDHC_DLLCFG1 0x164
62 +#define ESDHC_DLL_PD_PULSE_STRETCH_SEL 0x80000000
63 +
64 +/* DLL Status 0 Register */
65 +#define ESDHC_DLLSTAT0 0x170
66 +#define ESDHC_DLL_STS_SLV_LOCK 0x08000000
67
68 /* Control Register for DMA transfer */
69 #define ESDHC_DMA_SYSCTL 0x40c
70 --- a/drivers/mmc/host/sdhci-of-esdhc.c
71 +++ b/drivers/mmc/host/sdhci-of-esdhc.c
72 @@ -30,11 +30,61 @@
73 #define VENDOR_V_22 0x12
74 #define VENDOR_V_23 0x13
75
76 +#define MMC_TIMING_NUM (MMC_TIMING_MMC_HS400 + 1)
77 +
78 +struct esdhc_clk_fixup {
79 + const unsigned int sd_dflt_max_clk;
80 + const unsigned int max_clk[MMC_TIMING_NUM];
81 +};
82 +
83 +static const struct esdhc_clk_fixup ls1021a_esdhc_clk = {
84 + .sd_dflt_max_clk = 25000000,
85 + .max_clk[MMC_TIMING_MMC_HS] = 46500000,
86 + .max_clk[MMC_TIMING_SD_HS] = 46500000,
87 +};
88 +
89 +static const struct esdhc_clk_fixup ls1046a_esdhc_clk = {
90 + .sd_dflt_max_clk = 25000000,
91 + .max_clk[MMC_TIMING_UHS_SDR104] = 167000000,
92 + .max_clk[MMC_TIMING_MMC_HS200] = 167000000,
93 +};
94 +
95 +static const struct esdhc_clk_fixup ls1012a_esdhc_clk = {
96 + .sd_dflt_max_clk = 25000000,
97 + .max_clk[MMC_TIMING_UHS_SDR104] = 125000000,
98 + .max_clk[MMC_TIMING_MMC_HS200] = 125000000,
99 +};
100 +
101 +static const struct esdhc_clk_fixup p1010_esdhc_clk = {
102 + .sd_dflt_max_clk = 20000000,
103 + .max_clk[MMC_TIMING_LEGACY] = 20000000,
104 + .max_clk[MMC_TIMING_MMC_HS] = 42000000,
105 + .max_clk[MMC_TIMING_SD_HS] = 40000000,
106 +};
107 +
108 +static const struct of_device_id sdhci_esdhc_of_match[] = {
109 + { .compatible = "fsl,ls1021a-esdhc", .data = &ls1021a_esdhc_clk},
110 + { .compatible = "fsl,ls1046a-esdhc", .data = &ls1046a_esdhc_clk},
111 + { .compatible = "fsl,ls1012a-esdhc", .data = &ls1012a_esdhc_clk},
112 + { .compatible = "fsl,p1010-esdhc", .data = &p1010_esdhc_clk},
113 + { .compatible = "fsl,mpc8379-esdhc" },
114 + { .compatible = "fsl,mpc8536-esdhc" },
115 + { .compatible = "fsl,esdhc" },
116 + { }
117 +};
118 +MODULE_DEVICE_TABLE(of, sdhci_esdhc_of_match);
119 +
120 struct sdhci_esdhc {
121 u8 vendor_ver;
122 u8 spec_ver;
123 bool quirk_incorrect_hostver;
124 + bool quirk_limited_clk_division;
125 + bool quirk_unreliable_pulse_detection;
126 + bool quirk_fixup_tuning;
127 + bool quirk_incorrect_delay_chain;
128 unsigned int peripheral_clock;
129 + const struct esdhc_clk_fixup *clk_fixup;
130 + u32 div_ratio;
131 };
132
133 /**
134 @@ -500,13 +550,20 @@ static void esdhc_clock_enable(struct sd
135 }
136 }
137
138 +static struct soc_device_attribute soc_incorrect_delay_chain[] = {
139 + { .family = "QorIQ LX2160A", .revision = "1.0", },
140 + { },
141 +};
142 +
143 static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
144 {
145 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
146 struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
147 int pre_div = 1;
148 int div = 1;
149 + int division;
150 ktime_t timeout;
151 + long fixup = 0;
152 u32 temp;
153
154 host->mmc->actual_clock = 0;
155 @@ -520,27 +577,14 @@ static void esdhc_of_set_clock(struct sd
156 if (esdhc->vendor_ver < VENDOR_V_23)
157 pre_div = 2;
158
159 - /*
160 - * Limit SD clock to 167MHz for ls1046a according to its datasheet
161 - */
162 - if (clock > 167000000 &&
163 - of_find_compatible_node(NULL, NULL, "fsl,ls1046a-esdhc"))
164 - clock = 167000000;
165 + if (host->mmc->card && mmc_card_sd(host->mmc->card) &&
166 + esdhc->clk_fixup && host->mmc->ios.timing == MMC_TIMING_LEGACY)
167 + fixup = esdhc->clk_fixup->sd_dflt_max_clk;
168 + else if (esdhc->clk_fixup)
169 + fixup = esdhc->clk_fixup->max_clk[host->mmc->ios.timing];
170
171 - /*
172 - * Limit SD clock to 125MHz for ls1012a according to its datasheet
173 - */
174 - if (clock > 125000000 &&
175 - of_find_compatible_node(NULL, NULL, "fsl,ls1012a-esdhc"))
176 - clock = 125000000;
177 -
178 - /* Workaround to reduce the clock frequency for p1010 esdhc */
179 - if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) {
180 - if (clock > 20000000)
181 - clock -= 5000000;
182 - if (clock > 40000000)
183 - clock -= 5000000;
184 - }
185 + if (fixup && clock > fixup)
186 + clock = fixup;
187
188 temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
189 temp &= ~(ESDHC_CLOCK_SDCLKEN | ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN |
190 @@ -553,9 +597,30 @@ static void esdhc_of_set_clock(struct sd
191 while (host->max_clk / pre_div / div > clock && div < 16)
192 div++;
193
194 + if (esdhc->quirk_limited_clk_division &&
195 + clock == MMC_HS200_MAX_DTR &&
196 + (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 ||
197 + host->flags & SDHCI_HS400_TUNING)) {
198 + division = pre_div * div;
199 + if (division <= 4) {
200 + pre_div = 4;
201 + div = 1;
202 + } else if (division <= 8) {
203 + pre_div = 4;
204 + div = 2;
205 + } else if (division <= 12) {
206 + pre_div = 4;
207 + div = 3;
208 + } else {
209 + pr_warn("%s: using upsupported clock division.\n",
210 + mmc_hostname(host->mmc));
211 + }
212 + }
213 +
214 dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
215 clock, host->max_clk / pre_div / div);
216 host->mmc->actual_clock = host->max_clk / pre_div / div;
217 + esdhc->div_ratio = pre_div * div;
218 pre_div >>= 1;
219 div--;
220
221 @@ -565,6 +630,29 @@ static void esdhc_of_set_clock(struct sd
222 | (pre_div << ESDHC_PREDIV_SHIFT));
223 sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
224
225 + if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 &&
226 + clock == MMC_HS200_MAX_DTR) {
227 + temp = sdhci_readl(host, ESDHC_TBCTL);
228 + sdhci_writel(host, temp | ESDHC_HS400_MODE, ESDHC_TBCTL);
229 + temp = sdhci_readl(host, ESDHC_SDCLKCTL);
230 + sdhci_writel(host, temp | ESDHC_CMD_CLK_CTL, ESDHC_SDCLKCTL);
231 + esdhc_clock_enable(host, true);
232 +
233 + temp = sdhci_readl(host, ESDHC_DLLCFG0);
234 + temp |= ESDHC_DLL_ENABLE;
235 + if (host->mmc->actual_clock == MMC_HS200_MAX_DTR ||
236 + esdhc->quirk_incorrect_delay_chain == false)
237 + temp |= ESDHC_DLL_FREQ_SEL;
238 + sdhci_writel(host, temp, ESDHC_DLLCFG0);
239 + temp = sdhci_readl(host, ESDHC_TBCTL);
240 + sdhci_writel(host, temp | ESDHC_HS400_WNDW_ADJUST, ESDHC_TBCTL);
241 +
242 + esdhc_clock_enable(host, false);
243 + temp = sdhci_readl(host, ESDHC_DMA_SYSCTL);
244 + temp |= ESDHC_FLUSH_ASYNC_FIFO;
245 + sdhci_writel(host, temp, ESDHC_DMA_SYSCTL);
246 + }
247 +
248 /* Wait max 20 ms */
249 timeout = ktime_add_ms(ktime_get(), 20);
250 while (1) {
251 @@ -580,6 +668,7 @@ static void esdhc_of_set_clock(struct sd
252 udelay(10);
253 }
254
255 + temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
256 temp |= ESDHC_CLOCK_SDCLKEN;
257 sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
258 }
259 @@ -608,6 +697,8 @@ static void esdhc_pltfm_set_bus_width(st
260
261 static void esdhc_reset(struct sdhci_host *host, u8 mask)
262 {
263 + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
264 + struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
265 u32 val;
266
267 sdhci_reset(host, mask);
268 @@ -622,6 +713,12 @@ static void esdhc_reset(struct sdhci_hos
269 val = sdhci_readl(host, ESDHC_TBCTL);
270 val &= ~ESDHC_TB_EN;
271 sdhci_writel(host, val, ESDHC_TBCTL);
272 +
273 + if (esdhc->quirk_unreliable_pulse_detection) {
274 + val = sdhci_readl(host, ESDHC_DLLCFG1);
275 + val &= ~ESDHC_DLL_PD_PULSE_STRETCH_SEL;
276 + sdhci_writel(host, val, ESDHC_DLLCFG1);
277 + }
278 }
279 }
280
281 @@ -633,6 +730,7 @@ static void esdhc_reset(struct sdhci_hos
282 static const struct of_device_id scfg_device_ids[] = {
283 { .compatible = "fsl,t1040-scfg", },
284 { .compatible = "fsl,ls1012a-scfg", },
285 + { .compatible = "fsl,ls1043a-scfg", },
286 { .compatible = "fsl,ls1046a-scfg", },
287 {}
288 };
289 @@ -695,23 +793,91 @@ static int esdhc_signal_voltage_switch(s
290 }
291 }
292
293 -static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
294 +static struct soc_device_attribute soc_fixup_tuning[] = {
295 + { .family = "QorIQ T1040", .revision = "1.0", },
296 + { .family = "QorIQ T2080", .revision = "1.0", },
297 + { .family = "QorIQ T1023", .revision = "1.0", },
298 + { .family = "QorIQ LS1021A", .revision = "1.0", },
299 + { .family = "QorIQ LS1080A", .revision = "1.0", },
300 + { .family = "QorIQ LS2080A", .revision = "1.0", },
301 + { .family = "QorIQ LS1012A", .revision = "1.0", },
302 + { .family = "QorIQ LS1043A", .revision = "1.*", },
303 + { .family = "QorIQ LS1046A", .revision = "1.0", },
304 + { },
305 +};
306 +
307 +static void esdhc_tuning_block_enable(struct sdhci_host *host, bool enable)
308 {
309 - struct sdhci_host *host = mmc_priv(mmc);
310 u32 val;
311
312 - /* Use tuning block for tuning procedure */
313 esdhc_clock_enable(host, false);
314 +
315 val = sdhci_readl(host, ESDHC_DMA_SYSCTL);
316 val |= ESDHC_FLUSH_ASYNC_FIFO;
317 sdhci_writel(host, val, ESDHC_DMA_SYSCTL);
318
319 val = sdhci_readl(host, ESDHC_TBCTL);
320 - val |= ESDHC_TB_EN;
321 + if (enable)
322 + val |= ESDHC_TB_EN;
323 + else
324 + val &= ~ESDHC_TB_EN;
325 sdhci_writel(host, val, ESDHC_TBCTL);
326 +
327 esdhc_clock_enable(host, true);
328 +}
329 +
330 +static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
331 +{
332 + struct sdhci_host *host = mmc_priv(mmc);
333 + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
334 + struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
335 + bool hs400_tuning;
336 + u32 val;
337 + int ret;
338 +
339 + if (esdhc->quirk_limited_clk_division &&
340 + host->flags & SDHCI_HS400_TUNING)
341 + esdhc_of_set_clock(host, host->clock);
342 +
343 + esdhc_tuning_block_enable(host, true);
344 +
345 + hs400_tuning = host->flags & SDHCI_HS400_TUNING;
346 + ret = sdhci_execute_tuning(mmc, opcode);
347 +
348 + if (hs400_tuning) {
349 + val = sdhci_readl(host, ESDHC_SDTIMNGCTL);
350 + val |= ESDHC_FLW_CTL_BG;
351 + sdhci_writel(host, val, ESDHC_SDTIMNGCTL);
352 + }
353
354 - return sdhci_execute_tuning(mmc, opcode);
355 + if (host->tuning_err == -EAGAIN && esdhc->quirk_fixup_tuning) {
356 +
357 + /* program TBPTR[TB_WNDW_END_PTR] = 3*DIV_RATIO and
358 + * program TBPTR[TB_WNDW_START_PTR] = 5*DIV_RATIO
359 + */
360 + val = sdhci_readl(host, ESDHC_TBPTR);
361 + val = (val & ~((0x7f << 8) | 0x7f)) |
362 + (3 * esdhc->div_ratio) | ((5 * esdhc->div_ratio) << 8);
363 + sdhci_writel(host, val, ESDHC_TBPTR);
364 +
365 + /* program the software tuning mode by setting
366 + * TBCTL[TB_MODE]=2'h3
367 + */
368 + val = sdhci_readl(host, ESDHC_TBCTL);
369 + val |= 0x3;
370 + sdhci_writel(host, val, ESDHC_TBCTL);
371 + sdhci_execute_tuning(mmc, opcode);
372 + }
373 + return ret;
374 +}
375 +
376 +static void esdhc_set_uhs_signaling(struct sdhci_host *host,
377 + unsigned int timing)
378 +{
379 + if (timing == MMC_TIMING_MMC_HS400)
380 + esdhc_tuning_block_enable(host, true);
381 + else
382 + sdhci_set_uhs_signaling(host, timing);
383 }
384
385 #ifdef CONFIG_PM_SLEEP
386 @@ -760,7 +926,7 @@ static const struct sdhci_ops sdhci_esdh
387 .adma_workaround = esdhc_of_adma_workaround,
388 .set_bus_width = esdhc_pltfm_set_bus_width,
389 .reset = esdhc_reset,
390 - .set_uhs_signaling = sdhci_set_uhs_signaling,
391 + .set_uhs_signaling = esdhc_set_uhs_signaling,
392 };
393
394 static const struct sdhci_ops sdhci_esdhc_le_ops = {
395 @@ -777,7 +943,7 @@ static const struct sdhci_ops sdhci_esdh
396 .adma_workaround = esdhc_of_adma_workaround,
397 .set_bus_width = esdhc_pltfm_set_bus_width,
398 .reset = esdhc_reset,
399 - .set_uhs_signaling = sdhci_set_uhs_signaling,
400 + .set_uhs_signaling = esdhc_set_uhs_signaling,
401 };
402
403 static const struct sdhci_pltfm_data sdhci_esdhc_be_pdata = {
404 @@ -803,8 +969,20 @@ static struct soc_device_attribute soc_i
405 { },
406 };
407
408 +static struct soc_device_attribute soc_fixup_sdhc_clkdivs[] = {
409 + { .family = "QorIQ LX2160A", .revision = "1.0", },
410 + { .family = "QorIQ LX2160A", .revision = "2.0", },
411 + { },
412 +};
413 +
414 +static struct soc_device_attribute soc_unreliable_pulse_detection[] = {
415 + { .family = "QorIQ LX2160A", .revision = "1.0", },
416 + { },
417 +};
418 +
419 static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
420 {
421 + const struct of_device_id *match;
422 struct sdhci_pltfm_host *pltfm_host;
423 struct sdhci_esdhc *esdhc;
424 struct device_node *np;
425 @@ -824,6 +1002,24 @@ static void esdhc_init(struct platform_d
426 else
427 esdhc->quirk_incorrect_hostver = false;
428
429 + if (soc_device_match(soc_fixup_sdhc_clkdivs))
430 + esdhc->quirk_limited_clk_division = true;
431 + else
432 + esdhc->quirk_limited_clk_division = false;
433 +
434 + if (soc_device_match(soc_unreliable_pulse_detection))
435 + esdhc->quirk_unreliable_pulse_detection = true;
436 + else
437 + esdhc->quirk_unreliable_pulse_detection = false;
438 +
439 + if (soc_device_match(soc_incorrect_delay_chain))
440 + esdhc->quirk_incorrect_delay_chain = true;
441 + else
442 + esdhc->quirk_incorrect_delay_chain = false;
443 +
444 + match = of_match_node(sdhci_esdhc_of_match, pdev->dev.of_node);
445 + if (match)
446 + esdhc->clk_fixup = match->data;
447 np = pdev->dev.of_node;
448 clk = of_clk_get(np, 0);
449 if (!IS_ERR(clk)) {
450 @@ -851,6 +1047,12 @@ static void esdhc_init(struct platform_d
451 }
452 }
453
454 +static int esdhc_prepare_ddr_to_hs400(struct mmc_host *mmc)
455 +{
456 + esdhc_tuning_block_enable(mmc_priv(mmc), false);
457 + return 0;
458 +}
459 +
460 static int sdhci_esdhc_probe(struct platform_device *pdev)
461 {
462 struct sdhci_host *host;
463 @@ -874,6 +1076,7 @@ static int sdhci_esdhc_probe(struct plat
464 host->mmc_host_ops.start_signal_voltage_switch =
465 esdhc_signal_voltage_switch;
466 host->mmc_host_ops.execute_tuning = esdhc_execute_tuning;
467 + host->mmc_host_ops.prepare_ddr_to_hs400 = esdhc_prepare_ddr_to_hs400;
468 host->tuning_delay = 1;
469
470 esdhc_init(pdev, host);
471 @@ -882,6 +1085,11 @@ static int sdhci_esdhc_probe(struct plat
472
473 pltfm_host = sdhci_priv(host);
474 esdhc = sdhci_pltfm_priv(pltfm_host);
475 + if (soc_device_match(soc_fixup_tuning))
476 + esdhc->quirk_fixup_tuning = true;
477 + else
478 + esdhc->quirk_fixup_tuning = false;
479 +
480 if (esdhc->vendor_ver == VENDOR_V_22)
481 host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
482
483 @@ -928,14 +1136,6 @@ static int sdhci_esdhc_probe(struct plat
484 return ret;
485 }
486
487 -static const struct of_device_id sdhci_esdhc_of_match[] = {
488 - { .compatible = "fsl,mpc8379-esdhc" },
489 - { .compatible = "fsl,mpc8536-esdhc" },
490 - { .compatible = "fsl,esdhc" },
491 - { }
492 -};
493 -MODULE_DEVICE_TABLE(of, sdhci_esdhc_of_match);
494 -
495 static struct platform_driver sdhci_esdhc_driver = {
496 .driver = {
497 .name = "sdhci-esdhc",
498 --- a/drivers/mmc/host/sdhci.c
499 +++ b/drivers/mmc/host/sdhci.c
500 @@ -2150,7 +2150,7 @@ static void sdhci_send_tuning(struct sdh
501
502 }
503
504 -static void __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
505 +static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
506 {
507 int i;
508
509 @@ -2167,13 +2167,13 @@ static void __sdhci_execute_tuning(struc
510 pr_info("%s: Tuning timeout, falling back to fixed sampling clock\n",
511 mmc_hostname(host->mmc));
512 sdhci_abort_tuning(host, opcode);
513 - return;
514 + return -ETIMEDOUT;
515 }
516
517 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
518 if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) {
519 if (ctrl & SDHCI_CTRL_TUNED_CLK)
520 - return; /* Success! */
521 + return 0; /* Success! */
522 break;
523 }
524
525 @@ -2185,6 +2185,7 @@ static void __sdhci_execute_tuning(struc
526 pr_info("%s: Tuning failed, falling back to fixed sampling clock\n",
527 mmc_hostname(host->mmc));
528 sdhci_reset_tuning(host);
529 + return -EAGAIN;
530 }
531
532 int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
533 @@ -2246,7 +2247,7 @@ int sdhci_execute_tuning(struct mmc_host
534
535 sdhci_start_tuning(host);
536
537 - __sdhci_execute_tuning(host, opcode);
538 + host->tuning_err = __sdhci_execute_tuning(host, opcode);
539
540 sdhci_end_tuning(host);
541 out:
542 --- a/drivers/mmc/host/sdhci.h
543 +++ b/drivers/mmc/host/sdhci.h
544 @@ -545,6 +545,7 @@ struct sdhci_host {
545
546 unsigned int tuning_count; /* Timer count for re-tuning */
547 unsigned int tuning_mode; /* Re-tuning mode supported by host */
548 + unsigned int tuning_err; /* Error code for re-tuning */
549 #define SDHCI_TUNING_MODE_1 0
550 #define SDHCI_TUNING_MODE_2 1
551 #define SDHCI_TUNING_MODE_3 2
552 --- a/include/linux/mmc/card.h
553 +++ b/include/linux/mmc/card.h
554 @@ -156,6 +156,7 @@ struct sd_switch_caps {
555 #define UHS_DDR50_MAX_DTR 50000000
556 #define UHS_SDR25_MAX_DTR UHS_DDR50_MAX_DTR
557 #define UHS_SDR12_MAX_DTR 25000000
558 +#define DEFAULT_SPEED_MAX_DTR UHS_SDR12_MAX_DTR
559 unsigned int sd3_bus_mode;
560 #define UHS_SDR12_BUS_SPEED 0
561 #define HIGH_SPEED_BUS_SPEED 1
562 --- a/include/linux/mmc/host.h
563 +++ b/include/linux/mmc/host.h
564 @@ -145,6 +145,8 @@ struct mmc_host_ops {
565
566 /* Prepare HS400 target operating frequency depending host driver */
567 int (*prepare_hs400_tuning)(struct mmc_host *host, struct mmc_ios *ios);
568 + int (*prepare_ddr_to_hs400)(struct mmc_host *host);
569 +
570 /* Prepare enhanced strobe depending host driver */
571 void (*hs400_enhanced_strobe)(struct mmc_host *host,
572 struct mmc_ios *ios);