summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorRyan QIAN <b32804@freescale.com>2012-02-29 14:23:49 +0800
committerRyan QIAN <b32804@freescale.com>2012-02-29 15:32:05 +0800
commit406c4f67b0ca2e0911eb3424602bb4337a3a8da7 (patch)
treecb61073aac219a34874787de40700ceb4bea0f31 /drivers/mmc
parenta01c6f81a679dc7c2a8e841454fde21e3481994c (diff)
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 <b32804@freescale.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c41
1 files changed, 39 insertions, 2 deletions
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 042bfc73c78a..e76ef23e1f2a 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);
@@ -584,8 +614,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;
};