Hi, Jerry I think this patch is the same as I post here: http://patchwork.ozlabs.org/patch/103184/ We need to consider the comment from Anton http://lists.ozlabs.org/pipermail/linuxppc-dev/2011-August/092402.html Thanks. Roy > -----Original Message----- > From: linux-mmc-owner@xxxxxxxxxxxxxxx [mailto:linux-mmc- > owner@xxxxxxxxxxxxxxx] On Behalf Of r66093@xxxxxxxxxxxxx > Sent: Tuesday, December 27, 2011 15:53 PM > To: linux-mmc@xxxxxxxxxxxxxxx > Cc: Huang Changming-R66093; Jain Priyanka-B32167; Chris Ball > Subject: [PATCH 5/5 v3] ESDHC: Fix DMA errors in kernel booting on P1010 > > From: Jerry Huang <Chang-Ming.Huang@xxxxxxxxxxxxx> > > When linux is booted with DMA mode enabled in esdhc module on P1010, > there were following errors: > > mmc0: ADMA error > mmc0: error -5 whilst initialising SD card > > It is because FSL ESDHC controller has different bit setting for PROCTL > register, when kernel sets Power Control Register by method for standard > SD Host Specification, it would overwritten FSL ESDHC PROCTL[DMAS]; > when it set Host Control Registers[DMAS], it sets PROCTL[EMODE] and > PROCTL[D3CD]. These operations will set bad bits for PROCTL Register > on FSL ESDHC Controller and cause errors, so this patch will make esdhc > driver access FSL PROCTL Register according to block guide instead of > standard SD Host Specification. > > For some FSL chips, such as MPC8536/P2020, PROCTL[VOLT_SEL] and PROCTL[DMAS] > bits are reserved and even if they are set to wrong bits there is no error. > But considering that all FSL ESDHC Controller register map is not fully > compliant to standard SD Host Specification, we put the patch to all of > FSL ESDHC Controllers. > > Signed-off-by: Priyanka Jain <Priyanka.Jain@xxxxxxxxxxxxx> > Signed-off-by: Jerry Huang <Chang-Ming.Huang@xxxxxxxxxxxxx> > CC: Chris Ball <cjb@xxxxxxxxxx> > --- > changes for v2: > - change the property to compatible for quirks > changes for v3: > - fix one compile error > > drivers/mmc/host/sdhci-pltfm.c | 3 ++ > drivers/mmc/host/sdhci.c | 61 ++++++++++++++++++++++++++++++++---- > --- > include/linux/mmc/sdhci.h | 2 + > 3 files changed, 55 insertions(+), 11 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci- > pltfm.c > index 06f4ab9..f712218 100644 > --- a/drivers/mmc/host/sdhci-pltfm.c > +++ b/drivers/mmc/host/sdhci-pltfm.c > @@ -86,6 +86,9 @@ void sdhci_get_of_property(struct platform_device *pdev) > if (of_device_is_compatible(np, "fsl,p1010-esdhc")) > host->quirks2 |= SDHCI_QUIRK2_RELAX_FREQ; > > + if (of_device_is_compatible(np, "fsl,esdhc")) > + host->quirks2 |= SDHCI_QUIRK2_QORIQ_PROCTL_WEIRD; > + > #ifdef CONFIG_PM > if (of_device_is_compatible(np, "fsl,p1022-esdhc") > sdhc_pmsaveproctlreg = 1; > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c > index 4b231fa..df2acc0 100644 > --- a/drivers/mmc/host/sdhci.c > +++ b/drivers/mmc/host/sdhci.c > @@ -832,14 +832,29 @@ static void sdhci_prepare_data(struct sdhci_host > *host, struct mmc_command *cmd) > * is ADMA. > */ > if (host->version >= SDHCI_SPEC_200) { > - ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); > - ctrl &= ~SDHCI_CTRL_DMA_MASK; > - if ((host->flags & SDHCI_REQ_USE_DMA) && > - (host->flags & SDHCI_USE_ADMA)) > - ctrl |= SDHCI_CTRL_ADMA32; > - else > - ctrl |= SDHCI_CTRL_SDMA; > - sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); > + if (host->quirks2 & SDHCI_QUIRK2_QORIQ_PROCTL_WEIRD) { > +#define ESDHCI_PROCTL_DMAS_MASK 0x00000300 > +#define ESDHCI_PROCTL_ADMA32 0x00000200 > +#define ESDHCI_PROCTL_SDMA 0x00000000 > + u32 ctrl; > + ctrl = sdhci_readl(host, SDHCI_HOST_CONTROL); > + ctrl &= ~ESDHCI_PROCTL_DMAS_MASK; > + if ((host->flags & SDHCI_REQ_USE_DMA) && > + (host->flags & SDHCI_USE_ADMA)) > + ctrl |= ESDHCI_PROCTL_ADMA32; > + else > + ctrl |= ESDHCI_PROCTL_SDMA; > + sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL); > + } else { > + ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); > + ctrl &= ~SDHCI_CTRL_DMA_MASK; > + if ((host->flags & SDHCI_REQ_USE_DMA) && > + (host->flags & SDHCI_USE_ADMA)) > + ctrl |= SDHCI_CTRL_ADMA32; > + else > + ctrl |= SDHCI_CTRL_SDMA; > + sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); > + } > } > > if (!(host->flags & SDHCI_REQ_USE_DMA)) { > @@ -1175,17 +1190,29 @@ static void sdhci_set_power(struct sdhci_host *host, > unsigned short power) > u8 pwr = 0; > > if (power != (unsigned short)-1) { > +#define ESDHCI_FSL_POWER_MASK 0x40 > +#define ESDHCI_FSL_POWER_180 0x00 > +#define ESDHCI_FSL_POWER_300 0x40 > switch (1 << power) { > case MMC_VDD_165_195: > - pwr = SDHCI_POWER_180; > + if (host->quirks2 & SDHCI_QUIRK2_QORIQ_PROCTL_WEIRD) > + pwr = ESDHCI_FSL_POWER_180; > + else > + pwr = SDHCI_POWER_180; > break; > case MMC_VDD_29_30: > case MMC_VDD_30_31: > - pwr = SDHCI_POWER_300; > + if (host->quirks2 & SDHCI_QUIRK2_QORIQ_PROCTL_WEIRD) > + pwr = ESDHCI_FSL_POWER_300; > + else > + pwr = SDHCI_POWER_300; > break; > case MMC_VDD_32_33: > case MMC_VDD_33_34: > - pwr = SDHCI_POWER_330; > + if (host->quirks2 & SDHCI_QUIRK2_QORIQ_PROCTL_WEIRD) > + pwr = ESDHCI_FSL_POWER_300; > + else > + pwr = SDHCI_POWER_330; > break; > default: > BUG(); > @@ -1195,6 +1222,18 @@ static void sdhci_set_power(struct sdhci_host *host, > unsigned short power) > if (host->pwr == pwr) > return; > > + /* Now FSL ESDHC Controller has no Bus Power bit, > + * and PROCTL[21] bit is for voltage selection */ > + if (host->quirks2 & SDHCI_QUIRK2_QORIQ_PROCTL_WEIRD) { > + u8 volt = 0; > + volt = sdhci_readb(host, SDHCI_POWER_CONTROL); > + volt &= ~ESDHCI_FSL_POWER_MASK; > + volt |= pwr; > + sdhci_writeb(host, volt, SDHCI_POWER_CONTROL); > + > + return; > + } > + > host->pwr = pwr; > > if (pwr == 0) { > diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h > index f7c1e13..d025134 100644 > --- a/include/linux/mmc/sdhci.h > +++ b/include/linux/mmc/sdhci.h > @@ -93,6 +93,8 @@ struct sdhci_host { > #define SDHCI_QUIRK2_OWN_CARD_DETECTION (1<<0) > /* Controller operates the cards at reduced frequency */ > #define SDHCI_QUIRK2_RELAX_FREQ (1<<1) > +/* Controller has weird bit setting for Protocol Control Register */ > +#define SDHCI_QUIRK2_QORIQ_PROCTL_WEIRD (1<<2) > > int irq; /* Device IRQ */ > void __iomem *ioaddr; /* Mapped address */ > -- > 1.7.5.4 > > > -- > 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 -- 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