[1/5] mmc: sdhci-esdhc-imx: remove the 100MHz limitation for Strobe DLL
diff mbox series

Message ID 20190107101757.27647-1-haibo.chen@nxp.com
State New
Headers show
Series
  • [1/5] mmc: sdhci-esdhc-imx: remove the 100MHz limitation for Strobe DLL
Related show

Commit Message

BOUGH CHEN Jan. 7, 2019, 10:11 a.m. UTC
For some eMMC, after switch to HS400ES mode, it need to config the strobe
dll target dealy even if the clock is 50MHZ or 25MHz, otherwise will meet
CMD index/crc error when send CMD13 to check the switch status.

[    2.473915] IRQ status 0x000a8001
[    2.473934] mmc2: mmc_select_hs400es failed, error -84
[    2.473938] mmc2: error -84 whilst initialising MMC card

Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 55 +++++++++++++-----------------
 1 file changed, 24 insertions(+), 31 deletions(-)

Comments

Hunter, Adrian Jan. 14, 2019, 8:47 a.m. UTC | #1
On 7/01/19 12:11 PM, BOUGH CHEN wrote:
> For some eMMC, after switch to HS400ES mode, it need to config the strobe
> dll target dealy even if the clock is 50MHZ or 25MHz, otherwise will meet
> CMD index/crc error when send CMD13 to check the switch status.
> 
> [    2.473915] IRQ status 0x000a8001
> [    2.473934] mmc2: mmc_select_hs400es failed, error -84
> [    2.473938] mmc2: error -84 whilst initialising MMC card
> 
> Signed-off-by: Haibo Chen <haibo.chen@nxp.com>

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 55 +++++++++++++-----------------
>  1 file changed, 24 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index cf187f8dbc6c..0489b60b8eb4 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -141,9 +141,6 @@
>  /* The IP supports HS400 mode */
>  #define ESDHC_FLAG_HS400		BIT(9)
>  
> -/* A clock frequency higher than this rate requires strobe dll control */
> -#define ESDHC_STROBE_DLL_CLK_FREQ	100000000
> -
>  struct esdhc_soc_data {
>  	u32 flags;
>  };
> @@ -907,39 +904,35 @@ static int esdhc_change_pinstate(struct sdhci_host *host,
>   * edge of data_strobe line. Due to the time delay between CLK line and
>   * data_strobe line, if the delay time is larger than one clock cycle,
>   * then CLK and data_strobe line will be misaligned, read error shows up.
> - * So when the CLK is higher than 100MHz, each clock cycle is short enough,
> - * host should configure the delay target.
>   */
>  static void esdhc_set_strobe_dll(struct sdhci_host *host)
>  {
>  	u32 v;
>  
> -	if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) {
> -		/* disable clock before enabling strobe dll */
> -		writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
> -		       ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
> -		       host->ioaddr + ESDHC_VENDOR_SPEC);
> -
> -		/* force a reset on strobe dll */
> -		writel(ESDHC_STROBE_DLL_CTRL_RESET,
> -			host->ioaddr + ESDHC_STROBE_DLL_CTRL);
> -		/*
> -		 * enable strobe dll ctrl and adjust the delay target
> -		 * for the uSDHC loopback read clock
> -		 */
> -		v = ESDHC_STROBE_DLL_CTRL_ENABLE |
> -			(7 << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT);
> -		writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL);
> -		/* wait 1us to make sure strobe dll status register stable */
> -		udelay(1);
> -		v = readl(host->ioaddr + ESDHC_STROBE_DLL_STATUS);
> -		if (!(v & ESDHC_STROBE_DLL_STS_REF_LOCK))
> -			dev_warn(mmc_dev(host->mmc),
> -				"warning! HS400 strobe DLL status REF not lock!\n");
> -		if (!(v & ESDHC_STROBE_DLL_STS_SLV_LOCK))
> -			dev_warn(mmc_dev(host->mmc),
> -				"warning! HS400 strobe DLL status SLV not lock!\n");
> -	}
> +	/* disable clock before enabling strobe dll */
> +	writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
> +		~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
> +		host->ioaddr + ESDHC_VENDOR_SPEC);
> +
> +	/* force a reset on strobe dll */
> +	writel(ESDHC_STROBE_DLL_CTRL_RESET,
> +		host->ioaddr + ESDHC_STROBE_DLL_CTRL);
> +	/*
> +	 * enable strobe dll ctrl and adjust the delay target
> +	 * for the uSDHC loopback read clock
> +	 */
> +	v = ESDHC_STROBE_DLL_CTRL_ENABLE |
> +		(7 << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT);
> +	writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL);
> +	/* wait 1us to make sure strobe dll status register stable */
> +	udelay(1);
> +	v = readl(host->ioaddr + ESDHC_STROBE_DLL_STATUS);
> +	if (!(v & ESDHC_STROBE_DLL_STS_REF_LOCK))
> +		dev_warn(mmc_dev(host->mmc),
> +		"warning! HS400 strobe DLL status REF not lock!\n");
> +	if (!(v & ESDHC_STROBE_DLL_STS_SLV_LOCK))
> +		dev_warn(mmc_dev(host->mmc),
> +		"warning! HS400 strobe DLL status SLV not lock!\n");
>  }
>  
>  static void esdhc_reset_tuning(struct sdhci_host *host)
>
Ulf Hansson Jan. 14, 2019, 11:45 a.m. UTC | #2
On Mon, 7 Jan 2019 at 11:11, BOUGH CHEN <haibo.chen@nxp.com> wrote:
>
> For some eMMC, after switch to HS400ES mode, it need to config the strobe
> dll target dealy even if the clock is 50MHZ or 25MHz, otherwise will meet
> CMD index/crc error when send CMD13 to check the switch status.
>
> [    2.473915] IRQ status 0x000a8001
> [    2.473934] mmc2: mmc_select_hs400es failed, error -84
> [    2.473938] mmc2: error -84 whilst initialising MMC card
>
> Signed-off-by: Haibo Chen <haibo.chen@nxp.com>

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 55 +++++++++++++-----------------
>  1 file changed, 24 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index cf187f8dbc6c..0489b60b8eb4 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -141,9 +141,6 @@
>  /* The IP supports HS400 mode */
>  #define ESDHC_FLAG_HS400               BIT(9)
>
> -/* A clock frequency higher than this rate requires strobe dll control */
> -#define ESDHC_STROBE_DLL_CLK_FREQ      100000000
> -
>  struct esdhc_soc_data {
>         u32 flags;
>  };
> @@ -907,39 +904,35 @@ static int esdhc_change_pinstate(struct sdhci_host *host,
>   * edge of data_strobe line. Due to the time delay between CLK line and
>   * data_strobe line, if the delay time is larger than one clock cycle,
>   * then CLK and data_strobe line will be misaligned, read error shows up.
> - * So when the CLK is higher than 100MHz, each clock cycle is short enough,
> - * host should configure the delay target.
>   */
>  static void esdhc_set_strobe_dll(struct sdhci_host *host)
>  {
>         u32 v;
>
> -       if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) {
> -               /* disable clock before enabling strobe dll */
> -               writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
> -                      ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
> -                      host->ioaddr + ESDHC_VENDOR_SPEC);
> -
> -               /* force a reset on strobe dll */
> -               writel(ESDHC_STROBE_DLL_CTRL_RESET,
> -                       host->ioaddr + ESDHC_STROBE_DLL_CTRL);
> -               /*
> -                * enable strobe dll ctrl and adjust the delay target
> -                * for the uSDHC loopback read clock
> -                */
> -               v = ESDHC_STROBE_DLL_CTRL_ENABLE |
> -                       (7 << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT);
> -               writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL);
> -               /* wait 1us to make sure strobe dll status register stable */
> -               udelay(1);
> -               v = readl(host->ioaddr + ESDHC_STROBE_DLL_STATUS);
> -               if (!(v & ESDHC_STROBE_DLL_STS_REF_LOCK))
> -                       dev_warn(mmc_dev(host->mmc),
> -                               "warning! HS400 strobe DLL status REF not lock!\n");
> -               if (!(v & ESDHC_STROBE_DLL_STS_SLV_LOCK))
> -                       dev_warn(mmc_dev(host->mmc),
> -                               "warning! HS400 strobe DLL status SLV not lock!\n");
> -       }
> +       /* disable clock before enabling strobe dll */
> +       writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
> +               ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
> +               host->ioaddr + ESDHC_VENDOR_SPEC);
> +
> +       /* force a reset on strobe dll */
> +       writel(ESDHC_STROBE_DLL_CTRL_RESET,
> +               host->ioaddr + ESDHC_STROBE_DLL_CTRL);
> +       /*
> +        * enable strobe dll ctrl and adjust the delay target
> +        * for the uSDHC loopback read clock
> +        */
> +       v = ESDHC_STROBE_DLL_CTRL_ENABLE |
> +               (7 << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT);
> +       writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL);
> +       /* wait 1us to make sure strobe dll status register stable */
> +       udelay(1);
> +       v = readl(host->ioaddr + ESDHC_STROBE_DLL_STATUS);
> +       if (!(v & ESDHC_STROBE_DLL_STS_REF_LOCK))
> +               dev_warn(mmc_dev(host->mmc),
> +               "warning! HS400 strobe DLL status REF not lock!\n");
> +       if (!(v & ESDHC_STROBE_DLL_STS_SLV_LOCK))
> +               dev_warn(mmc_dev(host->mmc),
> +               "warning! HS400 strobe DLL status SLV not lock!\n");
>  }
>
>  static void esdhc_reset_tuning(struct sdhci_host *host)
> --
> 2.17.1
>

Patch
diff mbox series

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index cf187f8dbc6c..0489b60b8eb4 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -141,9 +141,6 @@ 
 /* The IP supports HS400 mode */
 #define ESDHC_FLAG_HS400		BIT(9)
 
-/* A clock frequency higher than this rate requires strobe dll control */
-#define ESDHC_STROBE_DLL_CLK_FREQ	100000000
-
 struct esdhc_soc_data {
 	u32 flags;
 };
@@ -907,39 +904,35 @@  static int esdhc_change_pinstate(struct sdhci_host *host,
  * edge of data_strobe line. Due to the time delay between CLK line and
  * data_strobe line, if the delay time is larger than one clock cycle,
  * then CLK and data_strobe line will be misaligned, read error shows up.
- * So when the CLK is higher than 100MHz, each clock cycle is short enough,
- * host should configure the delay target.
  */
 static void esdhc_set_strobe_dll(struct sdhci_host *host)
 {
 	u32 v;
 
-	if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) {
-		/* disable clock before enabling strobe dll */
-		writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
-		       ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
-		       host->ioaddr + ESDHC_VENDOR_SPEC);
-
-		/* force a reset on strobe dll */
-		writel(ESDHC_STROBE_DLL_CTRL_RESET,
-			host->ioaddr + ESDHC_STROBE_DLL_CTRL);
-		/*
-		 * enable strobe dll ctrl and adjust the delay target
-		 * for the uSDHC loopback read clock
-		 */
-		v = ESDHC_STROBE_DLL_CTRL_ENABLE |
-			(7 << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT);
-		writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL);
-		/* wait 1us to make sure strobe dll status register stable */
-		udelay(1);
-		v = readl(host->ioaddr + ESDHC_STROBE_DLL_STATUS);
-		if (!(v & ESDHC_STROBE_DLL_STS_REF_LOCK))
-			dev_warn(mmc_dev(host->mmc),
-				"warning! HS400 strobe DLL status REF not lock!\n");
-		if (!(v & ESDHC_STROBE_DLL_STS_SLV_LOCK))
-			dev_warn(mmc_dev(host->mmc),
-				"warning! HS400 strobe DLL status SLV not lock!\n");
-	}
+	/* disable clock before enabling strobe dll */
+	writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
+		~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
+		host->ioaddr + ESDHC_VENDOR_SPEC);
+
+	/* force a reset on strobe dll */
+	writel(ESDHC_STROBE_DLL_CTRL_RESET,
+		host->ioaddr + ESDHC_STROBE_DLL_CTRL);
+	/*
+	 * enable strobe dll ctrl and adjust the delay target
+	 * for the uSDHC loopback read clock
+	 */
+	v = ESDHC_STROBE_DLL_CTRL_ENABLE |
+		(7 << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT);
+	writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL);
+	/* wait 1us to make sure strobe dll status register stable */
+	udelay(1);
+	v = readl(host->ioaddr + ESDHC_STROBE_DLL_STATUS);
+	if (!(v & ESDHC_STROBE_DLL_STS_REF_LOCK))
+		dev_warn(mmc_dev(host->mmc),
+		"warning! HS400 strobe DLL status REF not lock!\n");
+	if (!(v & ESDHC_STROBE_DLL_STS_SLV_LOCK))
+		dev_warn(mmc_dev(host->mmc),
+		"warning! HS400 strobe DLL status SLV not lock!\n");
 }
 
 static void esdhc_reset_tuning(struct sdhci_host *host)