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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Yangbo Lu <yangbo.lu@xxxxxxx>

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@xxxxxxx>
Signed-off-by: Yinbo Zhu <yinbo.zhu@xxxxxxx>
---
 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);
+
 	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);
-- 
1.7.1




[Index of Archives]     [Linux Memonry Technology]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux