diff mbox

[v2,1/1] sdhci-pxa: support tune_timming for various cards

Message ID AANLkTi=h1p98z542H=EzFaqnHmEDkQDPZ5QmCQGo4Cik@mail.gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Zhangfei Gao Nov. 11, 2010, 1:19 p.m. UTC
None
diff mbox

Patch

From 553b84abee56f36ee166564f7ce3c617950e194f Mon Sep 17 00:00:00 2001
From: Zhangfei Gao <zhangfei.gao@marvell.com>
Date: Tue, 2 Nov 2010 07:37:44 -0400
Subject: [PATCH] sdhci-pxa: support tune_timing for various cards

	1. Add pdata check, in case pdata is NULL
	2. Add tune_timing to adjust read data/command timing without performance impact when crc error, as a result
		a, sd could work at 50M
		b, emmc could work at ddr50 mode
	3. Remove clock_enable checking, since clock gating is still on-going in core stack.

Signed-off-by: Zhangfei Gao <zhangfei.gao@marvell.com>
---
 arch/arm/plat-pxa/include/plat/sdhci.h |    2 +
 drivers/mmc/host/sdhci-pxa.c           |   47 +++++++++++++++++++++++--------
 2 files changed, 37 insertions(+), 12 deletions(-)

diff --git a/arch/arm/plat-pxa/include/plat/sdhci.h b/arch/arm/plat-pxa/include/plat/sdhci.h
index fc5ceab..f6f46db 100644
--- a/arch/arm/plat-pxa/include/plat/sdhci.h
+++ b/arch/arm/plat-pxa/include/plat/sdhci.h
@@ -24,11 +24,13 @@ 
  * @max_speed: the maximum speed supported
  * @quirks: quirks of specific device
  * @flags: flags for platform requirement
+ * @clk_delay_cycles: 1 ~ 0x1f, each step is roughly 100ps, for tuning timing
  */
 struct sdhci_pxa_platdata {
 	unsigned int	max_speed;
 	unsigned int	quirks;
 	unsigned int	flags;
+	unsigned int	clk_delay_cycles;
 };
 
 #endif /* __PLAT_PXA_SDHCI_H */
diff --git a/drivers/mmc/host/sdhci-pxa.c b/drivers/mmc/host/sdhci-pxa.c
index 8455c46..2b665e4 100644
--- a/drivers/mmc/host/sdhci-pxa.c
+++ b/drivers/mmc/host/sdhci-pxa.c
@@ -32,6 +32,11 @@ 
 #define SD_FIFO_PARAM		0x104
 #define DIS_PAD_SD_CLK_GATE	0x400
 
+#define SD_CLOCK_AND_BURST_SIZE_SETUP		0x10A
+#define SDCLK_SEL	0x100
+#define SDCLK_DELAY_SHIFT	9
+#define SDCLK_DELAY_MASK	0x1f
+
 struct sdhci_pxa {
 	struct sdhci_host		*host;
 	struct sdhci_pxa_platdata	*pdata;
@@ -46,9 +51,28 @@  struct sdhci_pxa {
  * SDHCI core callbacks                                                      *
  *                                                                           *
 \*****************************************************************************/
+static inline void tune_timing(struct sdhci_host *host,
+				struct sdhci_pxa_platdata *pdata)
+{
+	/*
+	 * tune timing of read data/command when crc error happen
+	 * no performance impact
+	 */
+	if (pdata && 0 != pdata->clk_delay_cycles) {
+		u16 tmp;
+
+		tmp = readw(host->ioaddr + SD_CLOCK_AND_BURST_SIZE_SETUP);
+		tmp |= (pdata->clk_delay_cycles & SDCLK_DELAY_MASK)
+					<< SDCLK_DELAY_SHIFT;
+		tmp |= SDCLK_SEL;
+		writew(tmp, host->ioaddr + SD_CLOCK_AND_BURST_SIZE_SETUP);
+	}
+}
+
 static void set_clock(struct sdhci_host *host, unsigned int clock)
 {
 	struct sdhci_pxa *pxa = sdhci_priv(host);
+	struct sdhci_pxa_platdata *pdata = pxa->pdata;
 	u32 tmp = 0;
 
 	if (clock == 0) {
@@ -57,15 +81,14 @@  static void set_clock(struct sdhci_host *host, unsigned int clock)
 			pxa->clk_enable = 0;
 		}
 	} else {
-		if (0 == pxa->clk_enable) {
-			if (pxa->pdata->flags & PXA_FLAG_DISABLE_CLOCK_GATING) {
-				tmp = readl(host->ioaddr + SD_FIFO_PARAM);
-				tmp |= DIS_PAD_SD_CLK_GATE;
-				writel(tmp, host->ioaddr + SD_FIFO_PARAM);
-			}
-			clk_enable(pxa->clk);
-			pxa->clk_enable = 1;
+		tune_timing(host, pdata);
+		if (pdata && pdata->flags & PXA_FLAG_DISABLE_CLOCK_GATING) {
+			tmp = readl(host->ioaddr + SD_FIFO_PARAM);
+			tmp |= DIS_PAD_SD_CLK_GATE;
+			writel(tmp, host->ioaddr + SD_FIFO_PARAM);
 		}
+		clk_enable(pxa->clk);
+		pxa->clk_enable = 1;
 	}
 }
 
@@ -138,13 +161,13 @@  static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
 	host->irq = irq;
 	host->quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 
-	if (pxa->pdata->flags & PXA_FLAG_CARD_PERMANENT) {
+	if (pdata && pdata->flags & PXA_FLAG_CARD_PERMANENT) {
 		/* on-chip device */
 		host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
 		host->mmc->caps |= MMC_CAP_NONREMOVABLE;
 	}
 
-	if (pdata->quirks)
+	if (pdata && pdata->quirks)
 		host->quirks |= pdata->quirks;
 
 	ret = sdhci_add_host(host);
@@ -153,8 +176,8 @@  static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
 		goto out;
 	}
 
-	if (pxa->pdata->max_speed)
-		host->mmc->f_max = pxa->pdata->max_speed;
+	if (pdata && pdata->max_speed)
+		host->mmc->f_max = pdata->max_speed;
 
 	platform_set_drvdata(pdev, host);
 
-- 
1.7.0.4