Skip to content

Commit adc40a5

Browse files
masahir0ystorulf
authored andcommitted
mmc: sdhci-cadence: do not use hardware tuning for SD mode
As commit ef6b756 ("mmc: sdhci-cadence: send tune request twice to work around errata") stated, this IP has an errata. This commit applies the second workaround for the SD mode. Due to the errata, it is not possible to use the hardware tuning provided by SDHCI_HOST_CONTROL2. Use the software-controlled tuning like the eMMC mode. Set sdhci_host_ops::platform_execute_tuning instead of overriding mmc_host_ops::execute_tuning. Signed-off-by: Masahiro Yamada <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ulf Hansson <[email protected]>
1 parent 786d33c commit adc40a5

File tree

1 file changed

+62
-61
lines changed

1 file changed

+62
-61
lines changed

drivers/mmc/host/sdhci-cadence.c

Lines changed: 62 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -202,57 +202,6 @@ static u32 sdhci_cdns_get_emmc_mode(struct sdhci_cdns_priv *priv)
202202
return FIELD_GET(SDHCI_CDNS_HRS06_MODE, tmp);
203203
}
204204

205-
static void sdhci_cdns_set_uhs_signaling(struct sdhci_host *host,
206-
unsigned int timing)
207-
{
208-
struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
209-
u32 mode;
210-
211-
switch (timing) {
212-
case MMC_TIMING_MMC_HS:
213-
mode = SDHCI_CDNS_HRS06_MODE_MMC_SDR;
214-
break;
215-
case MMC_TIMING_MMC_DDR52:
216-
mode = SDHCI_CDNS_HRS06_MODE_MMC_DDR;
217-
break;
218-
case MMC_TIMING_MMC_HS200:
219-
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS200;
220-
break;
221-
case MMC_TIMING_MMC_HS400:
222-
if (priv->enhanced_strobe)
223-
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400ES;
224-
else
225-
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
226-
break;
227-
default:
228-
mode = SDHCI_CDNS_HRS06_MODE_SD;
229-
break;
230-
}
231-
232-
sdhci_cdns_set_emmc_mode(priv, mode);
233-
234-
/* For SD, fall back to the default handler */
235-
if (mode == SDHCI_CDNS_HRS06_MODE_SD)
236-
sdhci_set_uhs_signaling(host, timing);
237-
}
238-
239-
static const struct sdhci_ops sdhci_cdns_ops = {
240-
.set_clock = sdhci_set_clock,
241-
.get_timeout_clock = sdhci_cdns_get_timeout_clock,
242-
.set_bus_width = sdhci_set_bus_width,
243-
.reset = sdhci_reset,
244-
.set_uhs_signaling = sdhci_cdns_set_uhs_signaling,
245-
};
246-
247-
static const struct sdhci_pltfm_data sdhci_cdns_uniphier_pltfm_data = {
248-
.ops = &sdhci_cdns_ops,
249-
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
250-
};
251-
252-
static const struct sdhci_pltfm_data sdhci_cdns_pltfm_data = {
253-
.ops = &sdhci_cdns_ops,
254-
};
255-
256205
static int sdhci_cdns_set_tune_val(struct sdhci_host *host, unsigned int val)
257206
{
258207
struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
@@ -286,23 +235,24 @@ static int sdhci_cdns_set_tune_val(struct sdhci_host *host, unsigned int val)
286235
return 0;
287236
}
288237

289-
static int sdhci_cdns_execute_tuning(struct mmc_host *mmc, u32 opcode)
238+
/*
239+
* In SD mode, software must not use the hardware tuning and instead perform
240+
* an almost identical procedure to eMMC.
241+
*/
242+
static int sdhci_cdns_execute_tuning(struct sdhci_host *host, u32 opcode)
290243
{
291-
struct sdhci_host *host = mmc_priv(mmc);
292244
int cur_streak = 0;
293245
int max_streak = 0;
294246
int end_of_streak = 0;
295247
int i;
296248

297249
/*
298-
* This handler only implements the eMMC tuning that is specific to
299-
* this controller. Fall back to the standard method for SD timing.
250+
* Do not execute tuning for UHS_SDR50 or UHS_DDR50.
251+
* The delay is set by probe, based on the DT properties.
300252
*/
301-
if (host->timing != MMC_TIMING_MMC_HS200)
302-
return sdhci_execute_tuning(mmc, opcode);
303-
304-
if (WARN_ON(opcode != MMC_SEND_TUNING_BLOCK_HS200))
305-
return -EINVAL;
253+
if (host->timing != MMC_TIMING_MMC_HS200 &&
254+
host->timing != MMC_TIMING_UHS_SDR104)
255+
return 0;
306256

307257
for (i = 0; i < SDHCI_CDNS_MAX_TUNING_LOOP; i++) {
308258
if (sdhci_cdns_set_tune_val(host, i) ||
@@ -325,6 +275,58 @@ static int sdhci_cdns_execute_tuning(struct mmc_host *mmc, u32 opcode)
325275
return sdhci_cdns_set_tune_val(host, end_of_streak - max_streak / 2);
326276
}
327277

278+
static void sdhci_cdns_set_uhs_signaling(struct sdhci_host *host,
279+
unsigned int timing)
280+
{
281+
struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
282+
u32 mode;
283+
284+
switch (timing) {
285+
case MMC_TIMING_MMC_HS:
286+
mode = SDHCI_CDNS_HRS06_MODE_MMC_SDR;
287+
break;
288+
case MMC_TIMING_MMC_DDR52:
289+
mode = SDHCI_CDNS_HRS06_MODE_MMC_DDR;
290+
break;
291+
case MMC_TIMING_MMC_HS200:
292+
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS200;
293+
break;
294+
case MMC_TIMING_MMC_HS400:
295+
if (priv->enhanced_strobe)
296+
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400ES;
297+
else
298+
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
299+
break;
300+
default:
301+
mode = SDHCI_CDNS_HRS06_MODE_SD;
302+
break;
303+
}
304+
305+
sdhci_cdns_set_emmc_mode(priv, mode);
306+
307+
/* For SD, fall back to the default handler */
308+
if (mode == SDHCI_CDNS_HRS06_MODE_SD)
309+
sdhci_set_uhs_signaling(host, timing);
310+
}
311+
312+
static const struct sdhci_ops sdhci_cdns_ops = {
313+
.set_clock = sdhci_set_clock,
314+
.get_timeout_clock = sdhci_cdns_get_timeout_clock,
315+
.set_bus_width = sdhci_set_bus_width,
316+
.reset = sdhci_reset,
317+
.platform_execute_tuning = sdhci_cdns_execute_tuning,
318+
.set_uhs_signaling = sdhci_cdns_set_uhs_signaling,
319+
};
320+
321+
static const struct sdhci_pltfm_data sdhci_cdns_uniphier_pltfm_data = {
322+
.ops = &sdhci_cdns_ops,
323+
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
324+
};
325+
326+
static const struct sdhci_pltfm_data sdhci_cdns_pltfm_data = {
327+
.ops = &sdhci_cdns_ops,
328+
};
329+
328330
static void sdhci_cdns_hs400_enhanced_strobe(struct mmc_host *mmc,
329331
struct mmc_ios *ios)
330332
{
@@ -385,7 +387,6 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
385387
priv->hrs_addr = host->ioaddr;
386388
priv->enhanced_strobe = false;
387389
host->ioaddr += SDHCI_CDNS_SRS_BASE;
388-
host->mmc_host_ops.execute_tuning = sdhci_cdns_execute_tuning;
389390
host->mmc_host_ops.hs400_enhanced_strobe =
390391
sdhci_cdns_hs400_enhanced_strobe;
391392
sdhci_enable_v4_mode(host);

0 commit comments

Comments
 (0)