RE: [PATCH 5/5 v3] ESDHC: Fix DMA errors in kernel booting on P1010

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

 



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


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

  Powered by Linux