diff mbox series

[v1] mmc: mmc: add hs400 mode support for lx2160a

Message ID 20181015110104.21483-1-yinbo.zhu@nxp.com (mailing list archive)
State New, archived
Headers show
Series [v1] mmc: mmc: add hs400 mode support for lx2160a | expand

Commit Message

Yinbo Zhu Oct. 15, 2018, 11:01 a.m. UTC
From: Yangbo Lu <yangbo.lu@nxp.com>

1. Set SDTIMNGCTL[FLW_CTL_BG] just after HS400 tuning.
2. Clear TBCTL[TB_EN] before switching from DDR to HS400.
3. Re-set TBCTL[TB_EN] when switching to HS400.
4. Remove useless controller DDR timing setting for HS400.
5. add prepare_ddr_to_hs400 callback.
6. improve tuning block enabling/disabling.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Signed-off-by: Yinbo Zhu <yinbo.zhu@nxp.com>
---
 drivers/mmc/core/mmc.c            |    3 +++
 drivers/mmc/host/sdhci-of-esdhc.c |   32 +++++++++++++++++++++++---------
 include/linux/mmc/host.h          |    1 +
 3 files changed, 27 insertions(+), 9 deletions(-)

Comments

Leo Li Oct. 22, 2018, 10:44 p.m. UTC | #1
On Mon, Oct 15, 2018 at 6:05 AM Yinbo Zhu <yinbo.zhu@nxp.com> wrote:
>
> From: Yangbo Lu <yangbo.lu@nxp.com>
>

The prefix to the title probably should just be "mmc:". The changes
below seems to be generic, but the title mentioned specifically
LX2160a.  Is this change breaking anything for other modes or devices?
 You probably should explain it more in the commit message.

> 1. Set SDTIMNGCTL[FLW_CTL_BG] just after HS400 tuning.
> 2. Clear TBCTL[TB_EN] before switching from DDR to HS400.
> 3. Re-set TBCTL[TB_EN] when switching to HS400.
> 4. Remove useless controller DDR timing setting for HS400.
> 5. add prepare_ddr_to_hs400 callback.
> 6. improve tuning block enabling/disabling.
>
> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
> Signed-off-by: Yinbo Zhu <yinbo.zhu@nxp.com>
> ---
>  drivers/mmc/core/mmc.c            |    3 +++
>  drivers/mmc/host/sdhci-of-esdhc.c |   32 +++++++++++++++++++++++---------
>  include/linux/mmc/host.h          |    1 +
>  3 files changed, 27 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 4f4a627..a5a3b3b 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -1148,6 +1148,9 @@ static int mmc_select_hs400(struct mmc_card *card)
>                 goto out_err;
>
>         /* Switch card to DDR */
> +       if (host->ops->prepare_ddr_to_hs400)
> +               host->ops->prepare_ddr_to_hs400(host);
> +
>         err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>                          EXT_CSD_BUS_WIDTH,
>                          EXT_CSD_DDR_BUS_WIDTH_8,
> diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
> index efae07c..dea6611 100644
> --- a/drivers/mmc/host/sdhci-of-esdhc.c
> +++ b/drivers/mmc/host/sdhci-of-esdhc.c
> @@ -738,6 +738,7 @@ static void esdhc_tuning_block_enable(struct sdhci_host *host, bool enable)
>         u32 val;
>
>         esdhc_clock_enable(host, false);
> +

No need to add new line.

>         val = sdhci_readl(host, ESDHC_DMA_SYSCTL);
>         val |= ESDHC_FLUSH_ASYNC_FIFO;
>         sdhci_writel(host, val, ESDHC_DMA_SYSCTL);
> @@ -748,6 +749,7 @@ static void esdhc_tuning_block_enable(struct sdhci_host *host, bool enable)
>         else
>                 val &= ~ESDHC_TB_EN;
>         sdhci_writel(host, val, ESDHC_TBCTL);
> +

No need to add new line.

>         esdhc_clock_enable(host, true);
>  }
>
> @@ -756,13 +758,26 @@ static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
>         struct sdhci_host *host = mmc_priv(mmc);
>         struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>         struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
> +       bool hs400_tuning;
> +       u32 val;
> +       int ret;
>
>         if (esdhc->quirk_limited_clk_division &&
>             host->flags & SDHCI_HS400_TUNING)
>                 esdhc_of_set_clock(host, host->clock);
>
>         esdhc_tuning_block_enable(host, true);
> -       return sdhci_execute_tuning(mmc, opcode);
> +
> +       hs400_tuning = host->flags & SDHCI_HS400_TUNING;
> +       ret = sdhci_execute_tuning(mmc, opcode);
> +
> +       if (hs400_tuning) {
> +               val = sdhci_readl(host, ESDHC_SDTIMNGCTL);
> +               val |= ESDHC_FLW_CTL_BG;
> +               sdhci_writel(host, val, ESDHC_SDTIMNGCTL);
> +       }
> +
> +       return ret;
>  }
>
>  static void esdhc_set_ddr_signaling(struct sdhci_host *host)
> @@ -791,18 +806,10 @@ static void esdhc_set_ddr_signaling(struct sdhci_host *host)
>  static void esdhc_set_uhs_signaling(struct sdhci_host *host,
>                                     unsigned int timing)
>  {
> -       u32 val;
> -
>         if (timing == MMC_TIMING_MMC_DDR52 ||
>             timing == MMC_TIMING_UHS_DDR50) {
>                 esdhc_set_ddr_signaling(host);
>         } else if (timing == MMC_TIMING_MMC_HS400) {
> -               val = sdhci_readl(host, ESDHC_SDTIMNGCTL);
> -               val |= ESDHC_FLW_CTL_BG;
> -               sdhci_writel(host, val, ESDHC_SDTIMNGCTL);
> -
> -               esdhc_tuning_block_enable(host, false);
> -               esdhc_set_ddr_signaling(host);
>                 esdhc_tuning_block_enable(host, true);
>         } else {
>                 sdhci_set_uhs_signaling(host, timing);
> @@ -963,6 +970,12 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
>         }
>  }
>
> +static int esdhc_prepare_ddr_to_hs400(struct mmc_host *mmc)
> +{
> +       esdhc_tuning_block_enable(mmc_priv(mmc), false);
> +       return 0;
> +}
> +
>  static int sdhci_esdhc_probe(struct platform_device *pdev)
>  {
>         struct sdhci_host *host;
> @@ -986,6 +999,7 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
>         host->mmc_host_ops.start_signal_voltage_switch =
>                 esdhc_signal_voltage_switch;
>         host->mmc_host_ops.execute_tuning = esdhc_execute_tuning;
> +       host->mmc_host_ops.prepare_ddr_to_hs400 = esdhc_prepare_ddr_to_hs400;
>         host->tuning_delay = 1;
>
>         esdhc_init(pdev, host);
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index 0b24394..c97ffd6 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -146,6 +146,7 @@ struct mmc_host_ops {
>
>         /* Prepare HS400 target operating frequency depending host driver */
>         int     (*prepare_hs400_tuning)(struct mmc_host *host, struct mmc_ios *ios);
> +       int     (*prepare_ddr_to_hs400)(struct mmc_host *host);
>         /* Prepare enhanced strobe depending host driver */
>         void    (*hs400_enhanced_strobe)(struct mmc_host *host,
>                                          struct mmc_ios *ios);
> --
> 1.7.1
>
diff mbox series

Patch

diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 4f4a627..a5a3b3b 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1148,6 +1148,9 @@  static int mmc_select_hs400(struct mmc_card *card)
 		goto out_err;
 
 	/* Switch card to DDR */
+	if (host->ops->prepare_ddr_to_hs400)
+		host->ops->prepare_ddr_to_hs400(host);
+
 	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			 EXT_CSD_BUS_WIDTH,
 			 EXT_CSD_DDR_BUS_WIDTH_8,
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index efae07c..dea6611 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -738,6 +738,7 @@  static void esdhc_tuning_block_enable(struct sdhci_host *host, bool enable)
 	u32 val;
 
 	esdhc_clock_enable(host, false);
+
 	val = sdhci_readl(host, ESDHC_DMA_SYSCTL);
 	val |= ESDHC_FLUSH_ASYNC_FIFO;
 	sdhci_writel(host, val, ESDHC_DMA_SYSCTL);
@@ -748,6 +749,7 @@  static void esdhc_tuning_block_enable(struct sdhci_host *host, bool enable)
 	else
 		val &= ~ESDHC_TB_EN;
 	sdhci_writel(host, val, ESDHC_TBCTL);
+
 	esdhc_clock_enable(host, true);
 }
 
@@ -756,13 +758,26 @@  static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	struct sdhci_host *host = mmc_priv(mmc);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
+	bool hs400_tuning;
+	u32 val;
+	int ret;
 
 	if (esdhc->quirk_limited_clk_division &&
 	    host->flags & SDHCI_HS400_TUNING)
 		esdhc_of_set_clock(host, host->clock);
 
 	esdhc_tuning_block_enable(host, true);
-	return sdhci_execute_tuning(mmc, opcode);
+
+	hs400_tuning = host->flags & SDHCI_HS400_TUNING;
+	ret = sdhci_execute_tuning(mmc, opcode);
+
+	if (hs400_tuning) {
+		val = sdhci_readl(host, ESDHC_SDTIMNGCTL);
+		val |= ESDHC_FLW_CTL_BG;
+		sdhci_writel(host, val, ESDHC_SDTIMNGCTL);
+	}
+
+	return ret;
 }
 
 static void esdhc_set_ddr_signaling(struct sdhci_host *host)
@@ -791,18 +806,10 @@  static void esdhc_set_ddr_signaling(struct sdhci_host *host)
 static void esdhc_set_uhs_signaling(struct sdhci_host *host,
 				    unsigned int timing)
 {
-	u32 val;
-
 	if (timing == MMC_TIMING_MMC_DDR52 ||
 	    timing == MMC_TIMING_UHS_DDR50) {
 		esdhc_set_ddr_signaling(host);
 	} else if (timing == MMC_TIMING_MMC_HS400) {
-		val = sdhci_readl(host, ESDHC_SDTIMNGCTL);
-		val |= ESDHC_FLW_CTL_BG;
-		sdhci_writel(host, val, ESDHC_SDTIMNGCTL);
-
-		esdhc_tuning_block_enable(host, false);
-		esdhc_set_ddr_signaling(host);
 		esdhc_tuning_block_enable(host, true);
 	} else {
 		sdhci_set_uhs_signaling(host, timing);
@@ -963,6 +970,12 @@  static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
 	}
 }
 
+static int esdhc_prepare_ddr_to_hs400(struct mmc_host *mmc)
+{
+	esdhc_tuning_block_enable(mmc_priv(mmc), false);
+	return 0;
+}
+
 static int sdhci_esdhc_probe(struct platform_device *pdev)
 {
 	struct sdhci_host *host;
@@ -986,6 +999,7 @@  static int sdhci_esdhc_probe(struct platform_device *pdev)
 	host->mmc_host_ops.start_signal_voltage_switch =
 		esdhc_signal_voltage_switch;
 	host->mmc_host_ops.execute_tuning = esdhc_execute_tuning;
+	host->mmc_host_ops.prepare_ddr_to_hs400 = esdhc_prepare_ddr_to_hs400;
 	host->tuning_delay = 1;
 
 	esdhc_init(pdev, host);
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 0b24394..c97ffd6 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -146,6 +146,7 @@  struct mmc_host_ops {
 
 	/* Prepare HS400 target operating frequency depending host driver */
 	int	(*prepare_hs400_tuning)(struct mmc_host *host, struct mmc_ios *ios);
+	int	(*prepare_ddr_to_hs400)(struct mmc_host *host);
 	/* Prepare enhanced strobe depending host driver */
 	void	(*hs400_enhanced_strobe)(struct mmc_host *host,
 					 struct mmc_ios *ios);