aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDong Aisheng <b29396@freescale.com>2013-11-04 03:38:27 -0500
committerChris Ball <chris@printf.net>2014-01-13 12:48:08 -0500
commit8b2bb0adce2c0cb63fcb77f4e54ac11ae54d84c0 (patch)
tree97a64d4ef884a62ce8603937e54fe399ce3649bb
parentd131a71c951088704eabe1529de99188c9e2c22c (diff)
mmc: esdhc-imx: clearing SDHCI_CTRL_EXEC_TUNING should not affect other bits
Current code will clear all turning related bits like ESDHC_STD_TUNING_EN and ESDHC_MIX_CTRL_FBCLK_SEL when clear SDHCI_CTRL_EXEC_TUNING. This may cause the card which has already passed the turning to become unwork since the turning status lost. We observed this failure when enable runtime pm. BTW, imx needs to enable ESDHC_MIX_CTRL_FBCLK_SEL bit for turned clock. The FBCLK_SEL will be cleared when SDHCI_CTRL_TUNED_CLK is cleared and SDHCI_CTRL_EXEC_TUNING is not set. This is used in case we change to another normal card from a UHS card in the same slot. FBCLK_SEL is not needed for normal card. After that, SDHCI_CTRL_EXEC_TUNING will only affect ESDHC_MIX_CTRL_EXE_TUNE. Clearing it does not affect the turned card to remain working on UHS mode. Signed-off-by: Dong Aisheng <b29396@freescale.com> Acked-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c24
1 files changed, 13 insertions, 11 deletions
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index d85a6a6f9e29..b1544a786eb6 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -439,24 +439,20 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
439 } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { 439 } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
440 u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR); 440 u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR);
441 u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); 441 u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL);
442 new_val = readl(host->ioaddr + ESDHC_TUNING_CTRL); 442 if (val & SDHCI_CTRL_TUNED_CLK) {
443 v |= ESDHC_MIX_CTRL_SMPCLK_SEL;
444 } else {
445 v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
446 m &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
447 }
448
443 if (val & SDHCI_CTRL_EXEC_TUNING) { 449 if (val & SDHCI_CTRL_EXEC_TUNING) {
444 new_val |= ESDHC_STD_TUNING_EN |
445 ESDHC_TUNING_START_TAP;
446 v |= ESDHC_MIX_CTRL_EXE_TUNE; 450 v |= ESDHC_MIX_CTRL_EXE_TUNE;
447 m |= ESDHC_MIX_CTRL_FBCLK_SEL; 451 m |= ESDHC_MIX_CTRL_FBCLK_SEL;
448 } else { 452 } else {
449 new_val &= ~ESDHC_STD_TUNING_EN;
450 v &= ~ESDHC_MIX_CTRL_EXE_TUNE; 453 v &= ~ESDHC_MIX_CTRL_EXE_TUNE;
451 m &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
452 } 454 }
453 455
454 if (val & SDHCI_CTRL_TUNED_CLK)
455 v |= ESDHC_MIX_CTRL_SMPCLK_SEL;
456 else
457 v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
458
459 writel(new_val, host->ioaddr + ESDHC_TUNING_CTRL);
460 writel(v, host->ioaddr + SDHCI_ACMD12_ERR); 456 writel(v, host->ioaddr + SDHCI_ACMD12_ERR);
461 writel(m, host->ioaddr + ESDHC_MIX_CTRL); 457 writel(m, host->ioaddr + ESDHC_MIX_CTRL);
462 } 458 }
@@ -1038,6 +1034,12 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
1038 if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) 1034 if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
1039 sdhci_esdhc_ops.platform_execute_tuning = 1035 sdhci_esdhc_ops.platform_execute_tuning =
1040 esdhc_executing_tuning; 1036 esdhc_executing_tuning;
1037
1038 if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING)
1039 writel(readl(host->ioaddr + ESDHC_TUNING_CTRL) |
1040 ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP,
1041 host->ioaddr + ESDHC_TUNING_CTRL);
1042
1041 boarddata = &imx_data->boarddata; 1043 boarddata = &imx_data->boarddata;
1042 if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) { 1044 if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) {
1043 if (!host->mmc->parent->platform_data) { 1045 if (!host->mmc->parent->platform_data) {