summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorHaibo Chen <haibo.chen@nxp.com>2017-03-23 15:54:20 +0800
committerAnson Huang <Anson.Huang@nxp.com>2017-06-09 22:18:30 +0800
commit0bdcac7f9184fa46aff9af2e8fc1c77997407170 (patch)
treedb4706edb8e539c4d311ac19c26908fb81ec6a12 /drivers/mmc
parentaa365df34d83541cd2c4a85e0b32a94de7a710c7 (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.c53
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;