Patchwork [U-Boot] mmc:sdhci: Fix card ready status timeout.

login
register
mail settings
Submitter Przemyslaw Marczak
Date Sept. 9, 2013, 12:58 p.m.
Message ID <1378731514-12564-1-git-send-email-p.marczak@samsung.com>
Download mbox | patch
Permalink /patch/273563/
State Changes Requested
Delegated to: Pantelis Antoniou
Headers show

Comments

Przemyslaw Marczak - Sept. 9, 2013, 12:58 p.m.
According to JEDEC eMMC specification, after data transfer
(multiple or single block) host must wait for card ready
status. This is done by waiting for command and data lines
to be at idle state after transfer. JEDEC does not specify
maximum timeout.

Before this change max timeout was 10 ms but in case of UMS
- when system does multiple read/write operations on random
card blocks - timeout causes I/O errors.
The timeout has been increased to 200ms after data transfer.
For other transfers it stays unchanged. Default values are
now defined with "if defined" directive so it can be redefined
at board config if needed.

Tested on Goni and Trats.

Signed-off-by: Przemyslaw Marczak <p.marczak@samsung.com>
Cc: Pantelis Antoniou <panto@antoniou-consulting.com>
---
 drivers/mmc/sdhci.c |   20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)
Przemyslaw Marczak - Sept. 13, 2013, 12:59 p.m.
Dear Pantelis,

On 09/09/2013 02:58 PM, Przemyslaw Marczak wrote:
> According to JEDEC eMMC specification, after data transfer
> (multiple or single block) host must wait for card ready
> status. This is done by waiting for command and data lines
> to be at idle state after transfer. JEDEC does not specify
> maximum timeout.
>
> Before this change max timeout was 10 ms but in case of UMS
> - when system does multiple read/write operations on random
> card blocks - timeout causes I/O errors.
> The timeout has been increased to 200ms after data transfer.
> For other transfers it stays unchanged. Default values are
> now defined with "if defined" directive so it can be redefined
> at board config if needed.
>
> Tested on Goni and Trats.
>
> Signed-off-by: Przemyslaw Marczak <p.marczak@samsung.com>
> Cc: Pantelis Antoniou <panto@antoniou-consulting.com>

Please do not apply this patch yet due to still not enough results on 
some targets.
Timeout value should depends on internal cards operations execution time 
but this time is unpredictably and that is why JEDEC not specifies it. 
Maybe u-boot sdhci driver needs some more changes to be more flexible 
for such operations. In example sdhci background operations timeout at 
kernel is specified to 4 minutes.
I need to make more research.

Regards,
Pantelis Antoniou - Sept. 16, 2013, 4:34 p.m.
Hi there,

On Sep 13, 2013, at 3:59 PM, Przemyslaw Marczak wrote:

> Dear Pantelis,
> 
> On 09/09/2013 02:58 PM, Przemyslaw Marczak wrote:
>> According to JEDEC eMMC specification, after data transfer
>> (multiple or single block) host must wait for card ready
>> status. This is done by waiting for command and data lines
>> to be at idle state after transfer. JEDEC does not specify
>> maximum timeout.
>> 
>> Before this change max timeout was 10 ms but in case of UMS
>> - when system does multiple read/write operations on random
>> card blocks - timeout causes I/O errors.
>> The timeout has been increased to 200ms after data transfer.
>> For other transfers it stays unchanged. Default values are
>> now defined with "if defined" directive so it can be redefined
>> at board config if needed.
>> 
>> Tested on Goni and Trats.
>> 
>> Signed-off-by: Przemyslaw Marczak <p.marczak@samsung.com>
>> Cc: Pantelis Antoniou <panto@antoniou-consulting.com>
> 
> Please do not apply this patch yet due to still not enough results on some targets.
> Timeout value should depends on internal cards operations execution time but this time is unpredictably and that is why JEDEC not specifies it. Maybe u-boot sdhci driver needs some more changes to be more flexible for such operations. In example sdhci background operations timeout at kernel is specified to 4 minutes.
> I need to make more research.
> 

OK, this need to be fleshed out a bit more.

Please keep me in the loop cause this sounds board-specific.
Perhaps the CONFIG_* option is a sound idea; real world is messy like that.

> Regards,
> 
> -- 
> Przemyslaw Marczak
> Samsung R&D Institute Poland
> Samsung Electronics
> p.marczak@samsung.com

Regards

-- Pantelis

Patch

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 4261991..35bdb37 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -110,6 +110,20 @@  static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
 	return 0;
 }
 
+#if !defined(SDHCI_DATA_CMD_TIMEOUT)
+#define SDHCI_DATA_CMD_TIMEOUT		10
+#endif
+#if !defined(SDHCI_STATUS_CMD_TIMEOUT)
+#define SDHCI_STATUS_CMD_TIMEOUT	200
+#endif
+/*
+ * For some commands this function is called with NULL mmc_data
+ * pointer. One of those is CMD13 - send card status.
+ * After read/write data transfer or block erase commands - host sends
+ * CMD13 and is waiting for card ready status with some timeout.
+ * According to some internal cards operations after those commands
+ * this time must be increased.
+ */
 int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 		       struct mmc_data *data)
 {
@@ -121,8 +135,10 @@  int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 	unsigned int timeout, start_addr = 0;
 	unsigned int retry = 10000;
 
-	/* Wait max 10 ms */
-	timeout = 10;
+	if (data)
+		timeout = SDHCI_DATA_CMD_TIMEOUT; /* ms */
+	else
+		timeout = SDHCI_STATUS_CMD_TIMEOUT;
 
 	sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
 	mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT;