On Thu, Nov 11, 2010 at 9:19 PM, zhangfei gao <zhangfei.gao@xxxxxxxxx> wrote: > Hi, Chirs & Eric > > Thanks for review, here is updated version. > 1. After clk_gating is enabled, set_clock will transfer clock=0, so > clk_disable will be called, currently set_clock will never transfer > clock=0. > Later tune_timing only occurs once clock is started, currently it will > happen when clock is changed. > > 2. if pdata is NULL, on-chip device can not be detected, but SD card > is workable, though some card may have crc error at 50M. > > > From 553b84abee56f36ee166564f7ce3c617950e194f Mon Sep 17 00:00:00 2001 > From: Zhangfei Gao <zhangfei.gao@xxxxxxxxxxx> > 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@xxxxxxxxxxx> > --- > 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 > Acked. -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html