diff mbox series

[v3,1/2] mmc: sdhci-esdhc-imx: simplify the auto tuning logic

Message ID 20221223025022.1893102-2-haibo.chen@nxp.com
State New
Headers show
Series fix the sdio device DATA/CMD CRC and Timeout issue after tuning | expand

Commit Message

Bough Chen Dec. 23, 2022, 2:50 a.m. UTC
From: Haibo Chen <haibo.chen@nxp.com>

Clear auto tuning bit when reset tuning, and enable auto tuning
only after tuning done successfully for both standard tuning and
manual tuning.

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

Comments

Adrian Hunter Dec. 29, 2022, 2:03 p.m. UTC | #1
On 23/12/22 04:50, haibo.chen@nxp.com wrote:
> From: Haibo Chen <haibo.chen@nxp.com>
> 
> Clear auto tuning bit when reset tuning, and enable auto tuning
> only after tuning done successfully for both standard tuning and
> manual tuning.
> 
> Signed-off-by: Haibo Chen <haibo.chen@nxp.com>

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

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 25 ++++++++++++++++---------
>  1 file changed, 16 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 89ef0c80ac37..bf8d6f60a9ee 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -429,9 +429,10 @@ static inline void esdhc_wait_for_card_clock_gate_off(struct sdhci_host *host)
>  }
>  
>  /* Enable the auto tuning circuit to check the CMD line and BUS line */
> -static inline void usdhc_auto_tuning_mode_sel(struct sdhci_host *host)
> +static inline void usdhc_auto_tuning_mode_sel_and_en(struct sdhci_host *host)
>  {
>  	u32 buswidth, auto_tune_buswidth;
> +	u32 reg;
>  
>  	buswidth = USDHC_GET_BUSWIDTH(readl(host->ioaddr + SDHCI_HOST_CONTROL));
>  
> @@ -450,6 +451,10 @@ static inline void usdhc_auto_tuning_mode_sel(struct sdhci_host *host)
>  	esdhc_clrset_le(host, ESDHC_VEND_SPEC2_AUTO_TUNE_MODE_MASK,
>  			auto_tune_buswidth | ESDHC_VEND_SPEC2_AUTO_TUNE_CMD_EN,
>  			ESDHC_VEND_SPEC2);
> +
> +	reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
> +	reg |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
> +	writel(reg, host->ioaddr + ESDHC_MIX_CTRL);
>  }
>  
>  static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
> @@ -681,14 +686,11 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  			} else {
>  				v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
>  				m &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
> -				m &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
>  			}
>  
>  			if (val & SDHCI_CTRL_EXEC_TUNING) {
>  				v |= ESDHC_MIX_CTRL_EXE_TUNE;
>  				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
> -				m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
> -				usdhc_auto_tuning_mode_sel(host);
>  			} else {
>  				v &= ~ESDHC_MIX_CTRL_EXE_TUNE;
>  			}
> @@ -1022,13 +1024,15 @@ static void esdhc_reset_tuning(struct sdhci_host *host)
>  
>  	/* Reset the tuning circuit */
>  	if (esdhc_is_usdhc(imx_data)) {
> +		ctrl = readl(host->ioaddr + ESDHC_MIX_CTRL);
> +		ctrl &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
>  		if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
> -			ctrl = readl(host->ioaddr + ESDHC_MIX_CTRL);
>  			ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
>  			ctrl &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
>  			writel(ctrl, host->ioaddr + ESDHC_MIX_CTRL);
>  			writel(0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
>  		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
> +			writel(ctrl, host->ioaddr + ESDHC_MIX_CTRL);
>  			ctrl = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS);
>  			ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
>  			ctrl &= ~ESDHC_MIX_CTRL_EXE_TUNE;
> @@ -1054,6 +1058,7 @@ static void esdhc_reset_tuning(struct sdhci_host *host)
>  static int usdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
>  {
>  	struct sdhci_host *host = mmc_priv(mmc);
> +	int err;
>  
>  	/*
>  	 * i.MX uSDHC internally already uses a fixed optimized timing for
> @@ -1068,7 +1073,12 @@ static int usdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
>  	 * correct delay cell.
>  	 */
>  	esdhc_reset_tuning(host);
> -	return sdhci_execute_tuning(mmc, opcode);
> +	err = sdhci_execute_tuning(mmc, opcode);
> +	/* If tuning done, enable auto tuning */
> +	if (!err && !host->tuning_err)
> +		usdhc_auto_tuning_mode_sel_and_en(host);
> +
> +	return err;
>  }
>  
>  static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
> @@ -1102,11 +1112,8 @@ static void esdhc_post_tuning(struct sdhci_host *host)
>  {
>  	u32 reg;
>  
> -	usdhc_auto_tuning_mode_sel(host);
> -
>  	reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
>  	reg &= ~ESDHC_MIX_CTRL_EXE_TUNE;
> -	reg |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
>  	writel(reg, host->ioaddr + ESDHC_MIX_CTRL);
>  }
>
diff mbox series

Patch

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 89ef0c80ac37..bf8d6f60a9ee 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -429,9 +429,10 @@  static inline void esdhc_wait_for_card_clock_gate_off(struct sdhci_host *host)
 }
 
 /* Enable the auto tuning circuit to check the CMD line and BUS line */
-static inline void usdhc_auto_tuning_mode_sel(struct sdhci_host *host)
+static inline void usdhc_auto_tuning_mode_sel_and_en(struct sdhci_host *host)
 {
 	u32 buswidth, auto_tune_buswidth;
+	u32 reg;
 
 	buswidth = USDHC_GET_BUSWIDTH(readl(host->ioaddr + SDHCI_HOST_CONTROL));
 
@@ -450,6 +451,10 @@  static inline void usdhc_auto_tuning_mode_sel(struct sdhci_host *host)
 	esdhc_clrset_le(host, ESDHC_VEND_SPEC2_AUTO_TUNE_MODE_MASK,
 			auto_tune_buswidth | ESDHC_VEND_SPEC2_AUTO_TUNE_CMD_EN,
 			ESDHC_VEND_SPEC2);
+
+	reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
+	reg |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
+	writel(reg, host->ioaddr + ESDHC_MIX_CTRL);
 }
 
 static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
@@ -681,14 +686,11 @@  static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 			} else {
 				v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
 				m &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
-				m &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
 			}
 
 			if (val & SDHCI_CTRL_EXEC_TUNING) {
 				v |= ESDHC_MIX_CTRL_EXE_TUNE;
 				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
-				m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
-				usdhc_auto_tuning_mode_sel(host);
 			} else {
 				v &= ~ESDHC_MIX_CTRL_EXE_TUNE;
 			}
@@ -1022,13 +1024,15 @@  static void esdhc_reset_tuning(struct sdhci_host *host)
 
 	/* Reset the tuning circuit */
 	if (esdhc_is_usdhc(imx_data)) {
+		ctrl = readl(host->ioaddr + ESDHC_MIX_CTRL);
+		ctrl &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
 		if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
-			ctrl = readl(host->ioaddr + ESDHC_MIX_CTRL);
 			ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
 			ctrl &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
 			writel(ctrl, host->ioaddr + ESDHC_MIX_CTRL);
 			writel(0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
 		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
+			writel(ctrl, host->ioaddr + ESDHC_MIX_CTRL);
 			ctrl = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS);
 			ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
 			ctrl &= ~ESDHC_MIX_CTRL_EXE_TUNE;
@@ -1054,6 +1058,7 @@  static void esdhc_reset_tuning(struct sdhci_host *host)
 static int usdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
+	int err;
 
 	/*
 	 * i.MX uSDHC internally already uses a fixed optimized timing for
@@ -1068,7 +1073,12 @@  static int usdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	 * correct delay cell.
 	 */
 	esdhc_reset_tuning(host);
-	return sdhci_execute_tuning(mmc, opcode);
+	err = sdhci_execute_tuning(mmc, opcode);
+	/* If tuning done, enable auto tuning */
+	if (!err && !host->tuning_err)
+		usdhc_auto_tuning_mode_sel_and_en(host);
+
+	return err;
 }
 
 static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
@@ -1102,11 +1112,8 @@  static void esdhc_post_tuning(struct sdhci_host *host)
 {
 	u32 reg;
 
-	usdhc_auto_tuning_mode_sel(host);
-
 	reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
 	reg &= ~ESDHC_MIX_CTRL_EXE_TUNE;
-	reg |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
 	writel(reg, host->ioaddr + ESDHC_MIX_CTRL);
 }