From: Ryan QIAN Date: Wed, 29 Feb 2012 06:23:49 +0000 (+0800) Subject: ENGR00175692-03 [MX6DL] SD3.0: can not recognize SD3.0 cards on some boards. X-Git-Tag: v3.0.35-fsl_4.1.0~1560 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=dd40c02f22f0d1f10f7f2fd34f0d0e57da8e28af;p=karo-tx-linux.git ENGR00175692-03 [MX6DL] SD3.0: can not recognize SD3.0 cards on some boards. Improve SD3.0 compatibility: reset host controller before changing clk tuning ctrl reg. Signed-off-by: Ryan QIAN --- diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 95b416b9c1c7..893de619afb2 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -37,6 +37,9 @@ #define SDHCI_MIX_CTRL_AUTO_TUNE (1 << 24) #define SDHCI_MIX_CTRL_FBCLK_SEL (1 << 25) +#define SDHCI_SYS_CTRL 0x2C +#define SDHCI_SYS_CTRL_RSTA_LSH 24 + #define SDHCI_DLL_CTRL 0x60 #define SDHCI_DLL_OVERRIDE_OFFSET 0x9 #define SDHCI_DLL_OVERRIDE_EN_OFFSET 0x8 @@ -265,14 +268,41 @@ void esdhc_post_tuning(struct sdhci_host *host) writel(reg, host->ioaddr + SDHCI_MIX_CTRL); } +static void esdhc_reset(struct sdhci_host *host) +{ + unsigned long timeout; + u32 reg; + + reg = readl(host->ioaddr + SDHCI_SYS_CTRL); + reg |= 1 << SDHCI_SYS_CTRL_RSTA_LSH; + writel(reg, host->ioaddr + SDHCI_SYS_CTRL); + + /* Wait max 100ms */ + timeout = 100; + + /* hw clears the bit when it's done */ + while (readl(host->ioaddr + SDHCI_SYS_CTRL) + & (1 << SDHCI_SYS_CTRL_RSTA_LSH)) { + if (timeout == 0) { + printk(KERN_ERR "%s: Reset never completed.\n", + mmc_hostname(host->mmc)); + return; + } + timeout--; + mdelay(1); + } +} + void esdhc_prepare_tuning(struct sdhci_host *host, u32 val) { u32 reg; + esdhc_reset(host); + mdelay(1); + reg = readl(host->ioaddr + SDHCI_MIX_CTRL); reg |= SDHCI_MIX_CTRL_EXE_TUNE | \ SDHCI_MIX_CTRL_SMPCLK_SEL | \ - SDHCI_MIX_CTRL_AUTO_TUNE | \ SDHCI_MIX_CTRL_FBCLK_SEL; writel(reg, host->ioaddr + SDHCI_MIX_CTRL); writel((val << 8), host->ioaddr + SDHCI_TUNE_CTRL_STATUS); @@ -585,8 +615,15 @@ static irqreturn_t cd_irq(int irq, void *data) writel(0, sdhost->ioaddr + SDHCI_MIX_CTRL); writel(0, sdhost->ioaddr + SDHCI_TUNE_CTRL_STATUS); - if (cpu_is_mx6()) + if (cpu_is_mx6()) { imx_data->scratchpad &= ~SDHCI_MIX_CTRL_DDREN; + imx_data->scratchpad &= ~SDHCI_MIX_CTRL_FBCLK_SEL; + imx_data->scratchpad &= ~SDHCI_MIX_CTRL_SMPCLK_SEL; + } + + esdhc_reset(sdhost); + mdelay(1); + tasklet_schedule(&sdhost->card_tasklet); return IRQ_HANDLED; };