diff options
author | Ryan QIAN <b32804@freescale.com> | 2012-02-29 14:23:49 +0800 |
---|---|---|
committer | Ryan QIAN <b32804@freescale.com> | 2012-02-29 15:32:05 +0800 |
commit | 406c4f67b0ca2e0911eb3424602bb4337a3a8da7 (patch) | |
tree | cb61073aac219a34874787de40700ceb4bea0f31 /drivers/mmc | |
parent | a01c6f81a679dc7c2a8e841454fde21e3481994c (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.c | 41 |
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; }; |