Hi Adrian, > -----Original Message----- > From: Adrian Hunter <adrian.hunter@xxxxxxxxx> > Sent: Friday, October 16, 2020 5:06 PM > To: Y.b. Lu <yangbo.lu@xxxxxxx>; linux-mmc@xxxxxxxxxxxxxxx > Cc: Ulf Hansson <ulf.hansson@xxxxxxxxxx> > Subject: Re: [PATCH] mmc: sdhci-of-esdhc: make sure delay chain locked for > HS400 > > On 16/10/20 7:25 am, Yangbo Lu wrote: > > For eMMC HS400 mode initialization, the DLL reset is a required step > > if DLL is enabled to use previously, like in bootloader. > > This step has not been documented in reference manual, but the RM will > > be fixed sooner or later. > > > > This patch is to add the step of DLL reset, and make sure delay chain > > locked for HS400. > > > > Signed-off-by: Yangbo Lu <yangbo.lu@xxxxxxx> > > --- > > drivers/mmc/host/sdhci-esdhc.h | 2 ++ > > drivers/mmc/host/sdhci-of-esdhc.c | 24 ++++++++++++++++++++++++ > > 2 files changed, 26 insertions(+) > > > > diff --git a/drivers/mmc/host/sdhci-esdhc.h > b/drivers/mmc/host/sdhci-esdhc.h > > index a30796e..6de02f0 100644 > > --- a/drivers/mmc/host/sdhci-esdhc.h > > +++ b/drivers/mmc/host/sdhci-esdhc.h > > @@ -5,6 +5,7 @@ > > * Copyright (c) 2007 Freescale Semiconductor, Inc. > > * Copyright (c) 2009 MontaVista Software, Inc. > > * Copyright (c) 2010 Pengutronix e.K. > > + * Copyright 2020 NXP > > * Author: Wolfram Sang <kernel@xxxxxxxxxxxxxx> > > */ > > > > @@ -88,6 +89,7 @@ > > /* DLL Config 0 Register */ > > #define ESDHC_DLLCFG0 0x160 > > #define ESDHC_DLL_ENABLE 0x80000000 > > +#define ESDHC_DLL_RESET 0x40000000 > > #define ESDHC_DLL_FREQ_SEL 0x08000000 > > > > /* DLL Config 1 Register */ > > diff --git a/drivers/mmc/host/sdhci-of-esdhc.c > b/drivers/mmc/host/sdhci-of-esdhc.c > > index 0b45eff..a39ff86 100644 > > --- a/drivers/mmc/host/sdhci-of-esdhc.c > > +++ b/drivers/mmc/host/sdhci-of-esdhc.c > > @@ -4,6 +4,7 @@ > > * > > * Copyright (c) 2007, 2010, 2012 Freescale Semiconductor, Inc. > > * Copyright (c) 2009 MontaVista Software, Inc. > > + * Copyright 2020 NXP > > * > > * Authors: Xiaobo Xie <X.Xie@xxxxxxxxxxxxx> > > * Anton Vorontsov <avorontsov@xxxxxxxxxxxxx> > > @@ -743,6 +744,29 @@ static void esdhc_of_set_clock(struct sdhci_host > *host, unsigned int clock) > > if (host->mmc->actual_clock == MMC_HS200_MAX_DTR) > > temp |= ESDHC_DLL_FREQ_SEL; > > sdhci_writel(host, temp, ESDHC_DLLCFG0); > > + > > + temp |= ESDHC_DLL_RESET; > > + sdhci_writel(host, temp, ESDHC_DLLCFG0); > > + udelay(1); > > + temp &= ~ESDHC_DLL_RESET; > > + sdhci_writel(host, temp, ESDHC_DLLCFG0); > > + > > + /* Wait max 20 ms */ > > + timeout = ktime_add_ms(ktime_get(), 20); > > + while (1) { > > + bool timedout = ktime_after(ktime_get(), timeout); > > + > > + if (sdhci_readl(host, ESDHC_DLLSTAT0) & > > + ESDHC_DLL_STS_SLV_LOCK) > > + break; > > + if (timedout) { > > + pr_err("%s: timeout for delay chain lock.\n", > > + mmc_hostname(host->mmc)); > > + break; > > + } > > + usleep_range(10, 20); > > + } > > It is possible now to do these loops using read_poll_timeout > e.g. something like this: > > if (read_poll_timeout(sdhci_readl, temp, temp & > ESDHC_DLL_STS_SLV_LOCK, > 10, 20000, false, host, ESDHC_DLLSTAT0)) > pr_err("%s: timeout for delay chain lock.\n", > mmc_hostname(host->mmc)); Thank you very much. I sent out v2 converting to use it. > > > > > + > > temp = sdhci_readl(host, ESDHC_TBCTL); > > sdhci_writel(host, temp | ESDHC_HS400_WNDW_ADJUST, > ESDHC_TBCTL); > > > >