summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorHaibo Chen <haibo.chen@nxp.com>2016-02-01 18:15:27 +0800
committerHaibo Chen <haibo.chen@nxp.com>2016-02-16 17:41:27 +0800
commit6a983bfb6fe5c15745efff8084d1c6e19309082d (patch)
tree11022a635336165e872ba2920a39cb3841162dc2 /drivers
parent2a9c6188294a06d888af9b6af703ceaf0b9cb34a (diff)
MLK-12345 mmc: sdhci-esdhc-imx: reset tuning circurt when insert sd card
Current driver do not clear the tuning related register setting, this will impact the timing and let the card inserted later meet CRC error. Take the DDR50 card as example, if plug out an SDR104 card and then plug in this DDR50 card, we will meet the following error log: mmc2: new ultra high speed DDR50 SDHC card at address aaaa mmcblk2: mmc2:aaaa SE08G 7.40 GiB mmcblk2: error -84 transferring data, sector 0, nr 8, cmd response 0x900, card status 0xb00 mmc2: tried to reset card mmcblk2: p1 p2 Logictally, we should reset the tuning circurt everytime when we plug in a sd card. Signed-off-by: Haibo Chen <haibo.chen@nxp.com> (cherry picked from commit 1f47730e8e30f37ed0289b2900e524db60456ae4)
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index b96dff3961c8..81040d1f315d 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -939,6 +939,30 @@ 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 = pltfm_host->priv;
+ 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);
@@ -972,6 +996,7 @@ 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 = {
@@ -1196,7 +1221,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;
+ host->mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_HW_RESET;
/*
* ROM code will change the bit burst_length_enable setting