On 22/05/20 6:12 am, Yangbo Lu wrote: > The eSDHC HS400 timing requires many specific registers setting, > unlike other speed modes which need to set only host controller 2 > register. When driver needs to downgrade HS400 mode to other speed > mode, the controller have to exit HS400 timing properly first. > This patch is to support the procedure of HS400 exiting at the > beginning of esdhc_set_uhs_signaling. > > Signed-off-by: Yangbo Lu <yangbo.lu@xxxxxxx> Acked-by: Adrian Hunter <adrian.hunter@xxxxxxxxx> > --- > drivers/mmc/host/sdhci-of-esdhc.c | 34 ++++++++++++++++++++++++++++++++++ > 1 file changed, 34 insertions(+) > > diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c > index 5d8dd87..7c73d24 100644 > --- a/drivers/mmc/host/sdhci-of-esdhc.c > +++ b/drivers/mmc/host/sdhci-of-esdhc.c > @@ -1135,6 +1135,40 @@ static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode) > static void esdhc_set_uhs_signaling(struct sdhci_host *host, > unsigned int timing) > { > + u32 val; > + > + /* > + * There are specific registers setting for HS400 mode. > + * Clean all of them if controller is in HS400 mode to > + * exit HS400 mode before re-setting any speed mode. > + */ > + val = sdhci_readl(host, ESDHC_TBCTL); > + if (val & ESDHC_HS400_MODE) { > + val = sdhci_readl(host, ESDHC_SDTIMNGCTL); > + val &= ~ESDHC_FLW_CTL_BG; > + sdhci_writel(host, val, ESDHC_SDTIMNGCTL); > + > + val = sdhci_readl(host, ESDHC_SDCLKCTL); > + val &= ~ESDHC_CMD_CLK_CTL; > + sdhci_writel(host, val, ESDHC_SDCLKCTL); > + > + esdhc_clock_enable(host, false); > + val = sdhci_readl(host, ESDHC_TBCTL); > + val &= ~ESDHC_HS400_MODE; > + sdhci_writel(host, val, ESDHC_TBCTL); > + esdhc_clock_enable(host, true); > + > + val = sdhci_readl(host, ESDHC_DLLCFG0); > + val &= ~(ESDHC_DLL_ENABLE | ESDHC_DLL_FREQ_SEL); > + sdhci_writel(host, val, ESDHC_DLLCFG0); > + > + val = sdhci_readl(host, ESDHC_TBCTL); > + val &= ~ESDHC_HS400_WNDW_ADJUST; > + sdhci_writel(host, val, ESDHC_TBCTL); > + > + esdhc_tuning_block_enable(host, false); > + } > + > if (timing == MMC_TIMING_MMC_HS400) > esdhc_tuning_block_enable(host, true); > else >