[U-Boot] [PATCH] omap: mmc: Raise timeout value to 20ms

With certain SD cards the code detects a timeout when the hardware has not timed out. We change the timeout used to match the kernel which gives software 20ms to detect a timeout. We also define to match the kernel and expand the previously incorrect comment. Finally, we let get_timer() perform subtraction for us as it offers.
Signed-off-by: Tom Rini trini@ti.com --- drivers/mmc/omap_hsmmc.c | 30 +++++++++++++++++------------- 1 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index c38b9e6..378fbda 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -33,8 +33,12 @@ #include <asm/arch/mmc_host_def.h> #include <asm/arch/sys_proto.h>
-/* If we fail after 1 second wait, something is really bad */ -#define MAX_RETRY_MS 1000 +/* + * Set our timeout value to 20ms. This has always been the timeout value + * used by the kernel. We define this in terms of usec since we check + * against get_timer calls which returns a usec value. + */ +#define MMC_TIMEOUT_USEC 20000
static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size); static int mmc_write_data(struct hsmmc *mmc_base, const char *buf, @@ -107,7 +111,7 @@ void mmc_init_stream(struct hsmmc *mmc_base) writel(MMC_CMD0, &mmc_base->cmd); start = get_timer(0); while (!(readl(&mmc_base->stat) & CC_MASK)) { - if (get_timer(0) - start > MAX_RETRY_MS) { + if (get_timer(start) > MMC_TIMEOUT_USEC) { printf("%s: timedout waiting for cc!\n", __func__); return; } @@ -118,7 +122,7 @@ void mmc_init_stream(struct hsmmc *mmc_base) ; start = get_timer(0); while (!(readl(&mmc_base->stat) & CC_MASK)) { - if (get_timer(0) - start > MAX_RETRY_MS) { + if (get_timer(start) > MMC_TIMEOUT_USEC) { printf("%s: timedout waiting for cc2!\n", __func__); return; } @@ -140,7 +144,7 @@ static int mmc_init_setup(struct mmc *mmc) &mmc_base->sysconfig); start = get_timer(0); while ((readl(&mmc_base->sysstatus) & RESETDONE) == 0) { - if (get_timer(0) - start > MAX_RETRY_MS) { + if (get_timer(start) > MMC_TIMEOUT_USEC) { printf("%s: timedout waiting for cc2!\n", __func__); return TIMEOUT; } @@ -148,7 +152,7 @@ static int mmc_init_setup(struct mmc *mmc) writel(readl(&mmc_base->sysctl) | SOFTRESETALL, &mmc_base->sysctl); start = get_timer(0); while ((readl(&mmc_base->sysctl) & SOFTRESETALL) != 0x0) { - if (get_timer(0) - start > MAX_RETRY_MS) { + if (get_timer(start) > MMC_TIMEOUT_USEC) { printf("%s: timedout waiting for softresetall!\n", __func__); return TIMEOUT; @@ -171,7 +175,7 @@ static int mmc_init_setup(struct mmc *mmc) (dsor << CLKD_OFFSET) | ICE_OSCILLATE); start = get_timer(0); while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) { - if (get_timer(0) - start > MAX_RETRY_MS) { + if (get_timer(start) > MMC_TIMEOUT_USEC) { printf("%s: timedout waiting for ics!\n", __func__); return TIMEOUT; } @@ -199,7 +203,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
start = get_timer(0); while ((readl(&mmc_base->pstate) & DATI_MASK) == DATI_CMDDIS) { - if (get_timer(0) - start > MAX_RETRY_MS) { + if (get_timer(start) > MMC_TIMEOUT_USEC) { printf("%s: timedout waiting for cmddis!\n", __func__); return TIMEOUT; } @@ -207,7 +211,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, writel(0xFFFFFFFF, &mmc_base->stat); start = get_timer(0); while (readl(&mmc_base->stat)) { - if (get_timer(0) - start > MAX_RETRY_MS) { + if (get_timer(start) > MMC_TIMEOUT_USEC) { printf("%s: timedout waiting for stat!\n", __func__); return TIMEOUT; } @@ -270,7 +274,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, start = get_timer(0); do { mmc_stat = readl(&mmc_base->stat); - if (get_timer(0) - start > MAX_RETRY_MS) { + if (get_timer(start) > MMC_TIMEOUT_USEC) { printf("%s : timeout: No status update\n", __func__); return TIMEOUT; } @@ -322,7 +326,7 @@ static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size) ulong start = get_timer(0); do { mmc_stat = readl(&mmc_base->stat); - if (get_timer(0) - start > MAX_RETRY_MS) { + if (get_timer(start) > MMC_TIMEOUT_USEC) { printf("%s: timedout waiting for status!\n", __func__); return TIMEOUT; @@ -374,7 +378,7 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf, ulong start = get_timer(0); do { mmc_stat = readl(&mmc_base->stat); - if (get_timer(0) - start > MAX_RETRY_MS) { + if (get_timer(start) > MMC_TIMEOUT_USEC) { printf("%s: timedout waiting for status!\n", __func__); return TIMEOUT; @@ -454,7 +458,7 @@ static void mmc_set_ios(struct mmc *mmc)
start = get_timer(0); while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) { - if (get_timer(0) - start > MAX_RETRY_MS) { + if (get_timer(start) > MMC_TIMEOUT_USEC) { printf("%s: timedout waiting for ics!\n", __func__); return; }

On Tue, Jan 3, 2012 at 2:24 PM, Tom Rini trini@ti.com wrote:
With certain SD cards the code detects a timeout when the hardware has not timed out. We change the timeout used to match the kernel which gives software 20ms to detect a timeout. We also define to match the kernel and expand the previously incorrect comment. Finally, we let get_timer() perform subtraction for us as it offers.
This doesn't work for me with the SanDisk 4GB card on the BeagleBoard-xM. I updated the recipe to remove Andreas' original patch, substituted the new one, and I get the following, which is the behavior before I used Andreas' patch except that now it takes about 20 seconds for each timeout message to print.
Peter
SD/MMC found on device 0 reading uEnv.txt mmc_send_cmd: timedout waiting for stat!
294 bytes read Loaded environment from uEnv.txt Importing environment from mmc ... Running uenvcmd ... Setting bus to 1 Loading file "/boot/uImage" from mmc device 0:2 (xxa2) mmc_send_cmd: timedout waiting for stat! mmc_send_cmd: timedout waiting for stat!
Signed-off-by: Tom Rini trini@ti.com
drivers/mmc/omap_hsmmc.c | 30 +++++++++++++++++------------- 1 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index c38b9e6..378fbda 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -33,8 +33,12 @@ #include <asm/arch/mmc_host_def.h> #include <asm/arch/sys_proto.h>
-/* If we fail after 1 second wait, something is really bad */ -#define MAX_RETRY_MS 1000 +/*
- Set our timeout value to 20ms. This has always been the timeout value
- used by the kernel. We define this in terms of usec since we check
- against get_timer calls which returns a usec value.
- */
+#define MMC_TIMEOUT_USEC 20000
static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size); static int mmc_write_data(struct hsmmc *mmc_base, const char *buf, @@ -107,7 +111,7 @@ void mmc_init_stream(struct hsmmc *mmc_base) writel(MMC_CMD0, &mmc_base->cmd); start = get_timer(0); while (!(readl(&mmc_base->stat) & CC_MASK)) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- if (get_timer(start) > MMC_TIMEOUT_USEC) {
printf("%s: timedout waiting for cc!\n", __func__); return; } @@ -118,7 +122,7 @@ void mmc_init_stream(struct hsmmc *mmc_base) ; start = get_timer(0); while (!(readl(&mmc_base->stat) & CC_MASK)) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- if (get_timer(start) > MMC_TIMEOUT_USEC) {
printf("%s: timedout waiting for cc2!\n", __func__); return; } @@ -140,7 +144,7 @@ static int mmc_init_setup(struct mmc *mmc) &mmc_base->sysconfig); start = get_timer(0); while ((readl(&mmc_base->sysstatus) & RESETDONE) == 0) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- if (get_timer(start) > MMC_TIMEOUT_USEC) {
printf("%s: timedout waiting for cc2!\n", __func__); return TIMEOUT; } @@ -148,7 +152,7 @@ static int mmc_init_setup(struct mmc *mmc) writel(readl(&mmc_base->sysctl) | SOFTRESETALL, &mmc_base->sysctl); start = get_timer(0); while ((readl(&mmc_base->sysctl) & SOFTRESETALL) != 0x0) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- if (get_timer(start) > MMC_TIMEOUT_USEC) {
printf("%s: timedout waiting for softresetall!\n", __func__); return TIMEOUT; @@ -171,7 +175,7 @@ static int mmc_init_setup(struct mmc *mmc) (dsor << CLKD_OFFSET) | ICE_OSCILLATE); start = get_timer(0); while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- if (get_timer(start) > MMC_TIMEOUT_USEC) {
printf("%s: timedout waiting for ics!\n", __func__); return TIMEOUT; } @@ -199,7 +203,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
start = get_timer(0); while ((readl(&mmc_base->pstate) & DATI_MASK) == DATI_CMDDIS) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- if (get_timer(start) > MMC_TIMEOUT_USEC) {
printf("%s: timedout waiting for cmddis!\n", __func__); return TIMEOUT; } @@ -207,7 +211,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, writel(0xFFFFFFFF, &mmc_base->stat); start = get_timer(0); while (readl(&mmc_base->stat)) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- if (get_timer(start) > MMC_TIMEOUT_USEC) {
printf("%s: timedout waiting for stat!\n", __func__); return TIMEOUT; } @@ -270,7 +274,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, start = get_timer(0); do { mmc_stat = readl(&mmc_base->stat);
- if (get_timer(0) - start > MAX_RETRY_MS) {
- if (get_timer(start) > MMC_TIMEOUT_USEC) {
printf("%s : timeout: No status update\n", __func__); return TIMEOUT; } @@ -322,7 +326,7 @@ static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size) ulong start = get_timer(0); do { mmc_stat = readl(&mmc_base->stat);
- if (get_timer(0) - start > MAX_RETRY_MS) {
- if (get_timer(start) > MMC_TIMEOUT_USEC) {
printf("%s: timedout waiting for status!\n", __func__); return TIMEOUT; @@ -374,7 +378,7 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf, ulong start = get_timer(0); do { mmc_stat = readl(&mmc_base->stat);
- if (get_timer(0) - start > MAX_RETRY_MS) {
- if (get_timer(start) > MMC_TIMEOUT_USEC) {
printf("%s: timedout waiting for status!\n", __func__); return TIMEOUT; @@ -454,7 +458,7 @@ static void mmc_set_ios(struct mmc *mmc)
start = get_timer(0); while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- if (get_timer(start) > MMC_TIMEOUT_USEC) {
printf("%s: timedout waiting for ics!\n", __func__); return; } -- 1.7.0.4

On 01/03/2012 01:50 PM, Peter Bigot wrote:
On Tue, Jan 3, 2012 at 2:24 PM, Tom Rini trini@ti.com wrote:
With certain SD cards the code detects a timeout when the hardware has not timed out. We change the timeout used to match the kernel which gives software 20ms to detect a timeout. We also define to match the kernel and expand the previously incorrect comment. Finally, we let get_timer() perform subtraction for us as it offers.
This doesn't work for me with the SanDisk 4GB card on the BeagleBoard-xM. I updated the recipe to remove Andreas' original patch, substituted the new one, and I get the following, which is the behavior before I used Andreas' patch except that now it takes about 20 seconds for each timeout message to print.
Dang. Is your card a class 6 card by chance? I'm going to go and see if I can pick one up locally real quick.

On Tue, Jan 3, 2012 at 3:03 PM, Tom Rini trini@ti.com wrote:
On 01/03/2012 01:50 PM, Peter Bigot wrote:
On Tue, Jan 3, 2012 at 2:24 PM, Tom Rini trini@ti.com wrote:
With certain SD cards the code detects a timeout when the hardware has not timed out. We change the timeout used to match the kernel which gives software 20ms to detect a timeout. We also define to match the kernel and expand the previously incorrect comment. Finally, we let get_timer() perform subtraction for us as it offers.
This doesn't work for me with the SanDisk 4GB card on the BeagleBoard-xM. I updated the recipe to remove Andreas' original patch, substituted the new one, and I get the following, which is the behavior before I used Andreas' patch except that now it takes about 20 seconds for each timeout message to print.
Dang. Is your card a class 6 card by chance? I'm going to go and see if I can pick one up locally real quick.
It claims to be a class 4 card.
Peter

On Tue, Jan 3, 2012 at 2:50 PM, Peter Bigot bigotp@acm.org wrote:
On Tue, Jan 3, 2012 at 2:24 PM, Tom Rini trini@ti.com wrote:
With certain SD cards the code detects a timeout when the hardware has not timed out. We change the timeout used to match the kernel which gives software 20ms to detect a timeout. We also define to match the kernel and expand the previously incorrect comment. Finally, we let get_timer() perform subtraction for us as it offers.
This doesn't work for me with the SanDisk 4GB card on the BeagleBoard-xM. I updated the recipe to remove Andreas' original patch, substituted the new one, and I get the following, which is the behavior before I used Andreas' patch except that now it takes about 20 seconds for each timeout message to print.
I got this to work with two changes:
* s/MMC_TIMEOUT_USEC/MMC_TIMEOUT_MSEC/g and define MMC_TIMEOUT_MSEC 20, since get_timer does operate on msec in the current meta-ti BeagleBoard-xM
* The patch below, which is what I think fixes the real problem (that PSTATE.CMDI is still lit up when the function is entered).
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index c38b9e6..62b659a 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -198,7 +198,8 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, ulong start;
start = get_timer(0); - while ((readl(&mmc_base->pstate) & DATI_MASK) == DATI_CMDDIS) { +#define CMDI_MASK (0x1 << 0) + while ((readl(&mmc_base->pstate) & (DATI_MASK | CMDI_MASK))) { if (get_timer(0) - start > MAX_RETRY_MS) { printf("%s: timedout waiting for cmddis!\n", __func__); return TIMEOUT;
Peter

On Wednesday, January 04, 2012 01:22:29 AM you wrote:
On Tue, Jan 3, 2012 at 2:50 PM, Peter Bigot bigotp@acm.org wrote:
On Tue, Jan 3, 2012 at 2:24 PM, Tom Rini trini@ti.com wrote:
With certain SD cards the code detects a timeout when the hardware has not timed out. We change the timeout used to match the kernel which gives software 20ms to detect a timeout. We also define to match the kernel and expand the previously incorrect comment. Finally, we let get_timer() perform subtraction for us as it offers.
This doesn't work for me with the SanDisk 4GB card on the BeagleBoard-xM. I updated the recipe to remove Andreas' original patch, substituted the new one, and I get the following, which is the behavior before I used Andreas' patch except that now it takes about 20 seconds for each timeout message to print.
(*)
I got this to work with two changes:
- s/MMC_TIMEOUT_USEC/MMC_TIMEOUT_MSEC/g and define MMC_TIMEOUT_MSEC
20, since get_timer does operate on msec in the current meta-ti BeagleBoard-xM
- The patch below, which is what I think fixes the real problem (that
PSTATE.CMDI is still lit up when the function is entered).
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index c38b9e6..62b659a 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -198,7 +198,8 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, ulong start;
start = get_timer(0);
while ((readl(&mmc_base->pstate) & DATI_MASK) == DATI_CMDDIS) {
+#define CMDI_MASK (0x1 << 0)
while ((readl(&mmc_base->pstate) & (DATI_MASK | CMDI_MASK))) { if (get_timer(0) - start > MAX_RETRY_MS) { printf("%s: timedout waiting for cmddis!\n",
__func__); return TIMEOUT;
Peter
Without having tested (have the hardware causing errors on monday next week): This version seems correct direction: We need to wait longer _before_ write action otherwise it is never finished - see (*). I am not an expert here but since this patch affects all mmc_cmds: Does this reduce performance?
Andreas
participants (3)
-
Andreas Müller
-
Peter Bigot
-
Tom Rini