diff options
Diffstat (limited to 'drivers/mmc/imx_esdhc.c')
-rw-r--r-- | drivers/mmc/imx_esdhc.c | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/drivers/mmc/imx_esdhc.c b/drivers/mmc/imx_esdhc.c index a57aa74..f9a3ad6 100644 --- a/drivers/mmc/imx_esdhc.c +++ b/drivers/mmc/imx_esdhc.c @@ -337,16 +337,49 @@ static void esdhc_dll_setup(struct mmc *mmc) { struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; + uint dll_control; + + /* For i.MX50 TO1, need to force slave override mode */ + if (get_board_rev() == (0x50000 | CHIP_REV_1_0)) { + dll_control = readl(®s->dllctrl); + + dll_control &= ~(ESDHC_DLLCTRL_SLV_OVERRIDE_VAL_MASK | + ESDHC_DLLCTRL_SLV_OVERRIDE); + dll_control |= ((ESDHC_DLLCTRL_SLV_OVERRIDE_VAL << + ESDHC_DLLCTRL_SLV_OVERRIDE_VAL_SHIFT) | + ESDHC_DLLCTRL_SLV_OVERRIDE); + + writel(dll_control, ®s->dllctrl); + } else { + /* Disable auto clock gating for PERCLK, HCLK, and IPGCLK */ + writel(readl(®s->sysctl) | 0x7, ®s->sysctl); + /* Stop SDCLK while delay line is calibrated */ + writel(readl(®s->sysctl) &= ~SYSCTL_SDCLKEN, ®s->sysctl); + + /* Reset DLL */ + writel(readl(®s->dllctrl) | 0x2, ®s->dllctrl); + + /* Enable DLL */ + writel(readl(®s->dllctrl) | 0x1, ®s->dllctrl); + + dll_control = readl(®s->dllctrl); + + /* Set target delay */ + dll_control &= ~ESDHC_DLLCTRL_TARGET_MASK; + dll_control |= (ESDHC_DLL_TARGET_DEFAULT_VAL << + ESDHC_DLLCTRL_TARGET_SHIFT); + writel(dll_control, ®s->dllctrl); + + /* Wait for slave lock */ + while ((readl(®s->dllstatus) & ESDHC_DLLSTS_SLV_LOCK_MASK) != + ESDHC_DLLSTS_SLV_LOCK_MASK) + ; - uint dll_control = readl(®s->dllctrl); - dll_control &= ~(ESDHC_DLLCTRL_SLV_OVERRIDE_VAL_MASK | - ESDHC_DLLCTRL_SLV_OVERRIDE); - dll_control |= ((ESDHC_DLLCTRL_SLV_OVERRIDE_VAL << - ESDHC_DLLCTRL_SLV_OVERRIDE_VAL_SHIFT) | - ESDHC_DLLCTRL_SLV_OVERRIDE); - - writel(dll_control, ®s->dllctrl); - + /* Re-enable auto clock gating */ + writel(readl(®s->sysctl) | SYSCTL_SDCLKEN, ®s->sysctl); + /* Re-enable SDCLK */ + writel(readl(®s->sysctl) &= ~0x7, ®s->sysctl); + } } static void esdhc_set_ios(struct mmc *mmc) |