Patchwork [U-Boot] mmc: Add a quirk to add delay during completion of sdhci_send_cmd

login
register
mail settings
Submitter Tushar Behera
Date Sept. 4, 2012, 11:37 a.m.
Message ID <1346758652-13942-1-git-send-email-tushar.behera@linaro.org>
Download mbox | patch
Permalink /patch/181542/
State Superseded
Delegated to: Andy Fleming
Headers show

Comments

Tushar Behera - Sept. 4, 2012, 11:37 a.m.
MMC host controller requires a delay between every sdhci_send_cmd()
execution. In s5p_mmc driver (s5p_sdhci replaces this driver), a delay
of 1000us was provided after every mmc_send_cmd() call. Adding a quirk
in current sdhci driver to replicate the behaviour.

Without this delay, MMC initialization on Origen board fails with
following error messages.

Timeout for status update!
mmc fail to send stop cmd

CC: Jaehoon Chung <jh80.chung@samsung.com>
CC: Andy Fleming <afleming@freescale.com>
Signed-off-by: Tushar Behera <tushar.behera@linaro.org>
---

This patch is applied on v2012.07 and Jaehoon Chung's following patchset.
[PATCH v2 0/4] mmc: sdhci: fixed some problems for Exynos

 drivers/mmc/s5p_sdhci.c |    3 ++-
 drivers/mmc/sdhci.c     |    4 ++++
 include/sdhci.h         |    1 +
 3 files changed, 7 insertions(+), 1 deletions(-)
Tushar Behera - Sept. 4, 2012, 11:51 a.m.
On 09/04/2012 05:07 PM, Tushar Behera wrote:
> MMC host controller requires a delay between every sdhci_send_cmd()
> execution. In s5p_mmc driver (s5p_sdhci replaces this driver), a delay
> of 1000us was provided after every mmc_send_cmd() call. Adding a quirk
> in current sdhci driver to replicate the behaviour.
> 
> Without this delay, MMC initialization on Origen board fails with
> following error messages.
> 
> Timeout for status update!
> mmc fail to send stop cmd
> 
> CC: Jaehoon Chung <jh80.chung@samsung.com>
> CC: Andy Fleming <afleming@freescale.com>
> Signed-off-by: Tushar Behera <tushar.behera@linaro.org>
> ---
> 
> This patch is applied on v2012.07 and Jaehoon Chung's following patchset.
> [PATCH v2 0/4] mmc: sdhci: fixed some problems for Exynos
> 
>  drivers/mmc/s5p_sdhci.c |    3 ++-
>  drivers/mmc/sdhci.c     |    4 ++++
>  include/sdhci.h         |    1 +
>  3 files changed, 7 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c
> index b978236..dc49d37 100644
> --- a/drivers/mmc/s5p_sdhci.c
> +++ b/drivers/mmc/s5p_sdhci.c
> @@ -83,7 +83,8 @@ int s5p_sdhci_init(u32 regbase, int index, int bus_width)
>  	host->ioaddr = (void *)regbase;
>  
>  	host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE |
> -		SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_32BIT_DMA_ADDR;
> +		SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_32BIT_DMA_ADDR |
> +		SDHCI_QUIRK_WAIT_SEND_CMD;
>  	host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
>  	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
>  
> diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
> index d0b8d24..823b1af 100644
> --- a/drivers/mmc/sdhci.c
> +++ b/drivers/mmc/sdhci.c
> @@ -233,12 +233,16 @@ int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
>  	if (!ret && data)
>  		ret = sdhci_transfer_data(host, data, start_addr);
>  
> +	if (host->quirks & SDHCI_QUIRK_WAIT_SEND_CMD)
> +		udelay(1000);
> +
>  	stat = sdhci_readl(host, SDHCI_INT_STATUS);
>  	sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
>  	if (!ret) {
>  		if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) &&
>  				!is_aligned && (data->flags == MMC_DATA_READ))
>  			memcpy(data->dest, aligned_buffer, trans_bytes);
> +

Sorry for this blank line. Will remove that if a resend is required.


>  		return 0;
>  	}
>  
> diff --git a/include/sdhci.h b/include/sdhci.h
> index 4351a62..d38cfd4 100644
> --- a/include/sdhci.h
> +++ b/include/sdhci.h
> @@ -219,6 +219,7 @@
>  #define SDHCI_QUIRK_BROKEN_R1B		(1 << 2)
>  #define SDHCI_QUIRK_NO_HISPD_BIT	(1 << 3)
>  #define SDHCI_QUIRK_BROKEN_VOLTAGE	(1 << 4)
> +#define SDHCI_QUIRK_WAIT_SEND_CMD	(1 << 5)
>  
>  /* to make gcc happy */
>  struct sdhci_host;
>

Patch

diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c
index b978236..dc49d37 100644
--- a/drivers/mmc/s5p_sdhci.c
+++ b/drivers/mmc/s5p_sdhci.c
@@ -83,7 +83,8 @@  int s5p_sdhci_init(u32 regbase, int index, int bus_width)
 	host->ioaddr = (void *)regbase;
 
 	host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE |
-		SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_32BIT_DMA_ADDR;
+		SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_32BIT_DMA_ADDR |
+		SDHCI_QUIRK_WAIT_SEND_CMD;
 	host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
 	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
 
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index d0b8d24..823b1af 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -233,12 +233,16 @@  int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 	if (!ret && data)
 		ret = sdhci_transfer_data(host, data, start_addr);
 
+	if (host->quirks & SDHCI_QUIRK_WAIT_SEND_CMD)
+		udelay(1000);
+
 	stat = sdhci_readl(host, SDHCI_INT_STATUS);
 	sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
 	if (!ret) {
 		if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) &&
 				!is_aligned && (data->flags == MMC_DATA_READ))
 			memcpy(data->dest, aligned_buffer, trans_bytes);
+
 		return 0;
 	}
 
diff --git a/include/sdhci.h b/include/sdhci.h
index 4351a62..d38cfd4 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -219,6 +219,7 @@ 
 #define SDHCI_QUIRK_BROKEN_R1B		(1 << 2)
 #define SDHCI_QUIRK_NO_HISPD_BIT	(1 << 3)
 #define SDHCI_QUIRK_BROKEN_VOLTAGE	(1 << 4)
+#define SDHCI_QUIRK_WAIT_SEND_CMD	(1 << 5)
 
 /* to make gcc happy */
 struct sdhci_host;