diff options
-rw-r--r-- | drivers/mmc/imx_esdhc.c | 51 | ||||
-rw-r--r-- | include/fsl_esdhc.h | 4 |
2 files changed, 46 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) diff --git a/include/fsl_esdhc.h b/include/fsl_esdhc.h index a0b1f5c..e32d7d2 100644 --- a/include/fsl_esdhc.h +++ b/include/fsl_esdhc.h @@ -155,6 +155,10 @@ #define ESDHC_DLLCTRL_SLV_OVERRIDE_VAL_MASK 0x0000FC00 #define ESDHC_DLLCTRL_SLV_OVERRIDE_VAL_SHIFT 10 #define ESDHC_DLLCTRL_SLV_OVERRIDE 0x200 +#define ESDHC_DLLCTRL_TARGET_MASK 0x00000078 +#define ESDHC_DLLCTRL_TARGET_SHIFT 3 +#define ESDHC_DLL_TARGET_DEFAULT_VAL 4 +#define ESDHC_DLLSTS_SLV_LOCK_MASK 0x00000001 struct fsl_esdhc_cfg { u32 esdhc_base; |