From f2663f7c17f1af71a0381ccd2136df83457ede1b Mon Sep 17 00:00:00 2001 From: Haibo Chen Date: Tue, 19 Dec 2017 14:46:55 +0800 Subject: MLK-17239 mmc: fsl_esdhc: fix sd/mmc ddr mode clock setting issue When sd/mmc work at DDR mode, like HS400/HS400ES/DDR52/DDR50 mode, the actual clock rate is just half of the expected clock. This patch set the DDR_EN bit first for DDR mode, hardware divide the usdhc clock automatically, then follow the original sdr clock setting method. This patch also remove the unused variable 'is_ddr'. Acked-by: Li Ye Signed-off-by: Haibo Chen (cherry picked from commit 2f1eed596782be19eb2c14e708e6db8596876346) --- drivers/mmc/fsl_esdhc.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index c5f7ccb63c..179b1c004e 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -137,7 +137,6 @@ struct fsl_esdhc_priv { int non_removable; int wp_enable; int vs18_enable; - int is_ddr; u32 tuning_step; u32 tuning_start_tap; u32 strobe_dll_delay_target; @@ -620,6 +619,15 @@ static void set_sysctl(struct mmc *mmc, uint clock) int sdhc_clk = priv->sdhc_clk; uint clk; + /* + * For ddr mode, usdhc need to enable DDR mode first, after select + * this DDR mode, usdhc will automatically divide the usdhc clock + */ + if (mmc->ddr_mode) { + writel(readl(®s->mixctrl) | MIX_CTRL_DDREN, ®s->mixctrl); + sdhc_clk >>= 1; + } + if (clock < mmc->cfg->f_min) clock = mmc->cfg->f_min; @@ -634,7 +642,7 @@ static void set_sysctl(struct mmc *mmc, uint clock) if ((sdhc_clk / (div * pre_div)) <= clock) break; - pre_div >>= mmc->ddr_mode ? 2 : 1; + pre_div >>= 1; div -= 1; clk = (pre_div << 8) | (div << 4); @@ -766,7 +774,6 @@ static int esdhc_set_timing(struct mmc *mmc) m = readl(®s->mixctrl); m &= ~(MIX_CTRL_DDREN | MIX_CTRL_HS400_EN); - priv->is_ddr = 0; switch (mmc->selected_mode) { case MMC_LEGACY: @@ -777,7 +784,6 @@ static int esdhc_set_timing(struct mmc *mmc) case MMC_HS_400_ES: m |= MIX_CTRL_DDREN | MIX_CTRL_HS400_EN; writel(m, ®s->mixctrl); - priv->is_ddr = 1; esdhc_set_strobe_dll(mmc); break; case MMC_HS: @@ -794,7 +800,6 @@ static int esdhc_set_timing(struct mmc *mmc) case MMC_DDR_52: m |= MIX_CTRL_DDREN; writel(m, ®s->mixctrl); - priv->is_ddr = 1; break; default: printf("Not supported %d\n", mmc->selected_mode); -- cgit v1.2.3