mmc: sdhci-of-esdhc: add tuning support
authoryangbo lu <yangbo.lu@nxp.com>
Thu, 20 Apr 2017 08:14:42 +0000 (16:14 +0800)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 24 Apr 2017 19:42:26 +0000 (21:42 +0200)
eSDHC uses tuning block for tuning procedure. So the tuning
block control register must be configured properly before tuning.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/host/sdhci-esdhc.h
drivers/mmc/host/sdhci-of-esdhc.c

index 6869567..c4bbd74 100644 (file)
 #define ESDHC_CLOCK_HCKEN              0x00000002
 #define ESDHC_CLOCK_IPGEN              0x00000001
 
+/* Tuning Block Control Register */
+#define ESDHC_TBCTL                    0x120
+#define ESDHC_TB_EN                    0x00000004
+
 /* Control Register for DMA transfer */
 #define ESDHC_DMA_SYSCTL               0x40c
 #define ESDHC_PERIPHERAL_CLK_SEL       0x00080000
+#define ESDHC_FLUSH_ASYNC_FIFO         0x00040000
 #define ESDHC_DMA_SNOOP                        0x00000040
 
 #endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */
index f2d7002..607e512 100644 (file)
@@ -631,6 +631,25 @@ static int esdhc_signal_voltage_switch(struct mmc_host *mmc,
        }
 }
 
+static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+       struct sdhci_host *host = mmc_priv(mmc);
+       u32 val;
+
+       /* Use tuning block for tuning procedure */
+       esdhc_clock_enable(host, false);
+       val = sdhci_readl(host, ESDHC_DMA_SYSCTL);
+       val |= ESDHC_FLUSH_ASYNC_FIFO;
+       sdhci_writel(host, val, ESDHC_DMA_SYSCTL);
+
+       val = sdhci_readl(host, ESDHC_TBCTL);
+       val |= ESDHC_TB_EN;
+       sdhci_writel(host, val, ESDHC_TBCTL);
+       esdhc_clock_enable(host, true);
+
+       return sdhci_execute_tuning(mmc, opcode);
+}
+
 #ifdef CONFIG_PM_SLEEP
 static u32 esdhc_proctl;
 static int esdhc_of_suspend(struct device *dev)
@@ -790,6 +809,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;
 
        esdhc_init(pdev, host);