diff options
author | Haibo Chen <haibo.chen@nxp.com> | 2017-03-23 15:54:20 +0800 |
---|---|---|
committer | Anson Huang <Anson.Huang@nxp.com> | 2017-06-09 22:18:30 +0800 |
commit | 0bdcac7f9184fa46aff9af2e8fc1c77997407170 (patch) | |
tree | db4706edb8e539c4d311ac19c26908fb81ec6a12 /drivers/mmc | |
parent | aa365df34d83541cd2c4a85e0b32a94de7a710c7 (diff) |
MLK-14381 mmc: sdhci-esdhc-imx: reset tuning circuit when system resume
USDHC tuning circuit should be reset before every time card enumeration
or re-enumeration.
On imx7ulp-evk board, for SDR104 card, when system suspend in standby
mode, and then resume back, the IO timing is still SDR104 which may
result in card re-enumeration fail in low speed mode (400khz) for some
cards. And we did meet the issue that in certain probability, SDR104
card meet mmc command CRC/Timeout error when send CMD2 during mmc bus
resume.
This patch reset the tuning circuit when the ios timing is
MMC_TIMING_LEGACY/MMC_TIMING_MMC_HS/MMC_TIMING_SD_HS, which means both
mmc_power_up() and mmc_power_off() will reset the tuning circuit.
This patch can cover the 'commit 374da688c65a ("MLK-12345 mmc:
sdhci-esdhc-imx: reset tuning circurt when insert sd card")', and is a
better solution. So use this patch instead.
Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
(cherry picked from commit 84a6b78bc4e2ccd433b25a4261194b93e6f83323)
Conflicts:
drivers/mmc/host/sdhci-esdhc-imx.c
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/sdhci-esdhc-imx.c | 53 |
1 files changed, 27 insertions, 26 deletions
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index c3c930c122f5..4f5ee6a86254 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -954,6 +954,28 @@ static void esdhc_set_strobe_dll(struct sdhci_host *host) } } +static void esdhc_reset_tuning(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); + u16 ctrl; + + /* Rest the tuning circurt */ + if (esdhc_is_usdhc(imx_data)) { + if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { + ctrl = readl(host->ioaddr + ESDHC_MIX_CTRL); + ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; + ctrl &= ~ESDHC_MIX_CTRL_FBCLK_SEL; + writel(ctrl, host->ioaddr + ESDHC_MIX_CTRL); + writel(0 << 8, host->ioaddr + ESDHC_TUNE_CTRL_STATUS); + } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { + ctrl = readl(host->ioaddr + SDHCI_ACMD12_ERR); + ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; + writel(ctrl, host->ioaddr + SDHCI_ACMD12_ERR); + } + } +} + static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing) { u32 m; @@ -997,6 +1019,10 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing) host->ops->set_clock(host, host->clock); esdhc_set_strobe_dll(host); break; + case MMC_TIMING_LEGACY: + default: + esdhc_reset_tuning(host); + break; } esdhc_change_pinstate(host, timing); @@ -1010,30 +1036,6 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask) sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); } -static void esdhc_hw_reset(struct sdhci_host *host) -{ - struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); - u16 ctrl; - - sdhci_reset(host, SDHCI_RESET_ALL); - - /* Rest the tuning circurt */ - if (esdhc_is_usdhc(imx_data)) { - if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { - ctrl = readl(host->ioaddr + ESDHC_MIX_CTRL); - ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; - ctrl &= ~ESDHC_MIX_CTRL_FBCLK_SEL; - writel(ctrl, host->ioaddr + ESDHC_MIX_CTRL); - writel(0 << 8, host->ioaddr + ESDHC_TUNE_CTRL_STATUS); - } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { - ctrl = readl(host->ioaddr + SDHCI_ACMD12_ERR); - ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; - writel(ctrl, host->ioaddr + SDHCI_ACMD12_ERR); - } - } -} - static unsigned int esdhc_get_max_timeout_count(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -1070,7 +1072,6 @@ static struct sdhci_ops sdhci_esdhc_ops = { .set_bus_width = esdhc_pltfm_set_bus_width, .set_uhs_signaling = esdhc_set_uhs_signaling, .reset = esdhc_reset, - .hw_reset = esdhc_hw_reset, }; static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { @@ -1350,7 +1351,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) if (esdhc_is_usdhc(imx_data)) { host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; - host->mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_HW_RESET; + host->mmc->caps |= MMC_CAP_1_8V_DDR; if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200)) host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200; |