public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2] mmc: omap: timeout counter fix
@ 2010-10-26  1:02 Nishanth Menon
  2010-10-26  1:14 ` Reinhard Meyer
  2010-10-26  4:36 ` Wolfgang Denk
  0 siblings, 2 replies; 32+ messages in thread
From: Nishanth Menon @ 2010-10-26  1:02 UTC (permalink / raw)
  To: u-boot

Having a loop with a counter is no timing guarentee for timing
accuracy or compiler optimizations. For e.g. the same loop counter
which runs when the MPU is running at 600MHz will timeout in around
half the time when running at 1GHz. or the example where GCC 4.5
compiles with different optimization compared to GCC 4.4.
use a udelay(10) to ensure we have a predictable delay.
use an emperical number - 100000 uSec ~= 1sec for a worst case timeout.
This should never happen, and is adequate imaginary condition for us
to fail with timeout.

Signed-off-by: Nishanth Menon <nm@ti.com>
---
V2: additional cleanups + made MAX_RETRY a macro for reuse throughout
the file. tested on PandaBoard with 1GHz boot frequency and GCC4.5 on
u-boot 2010.09 + mmc patches. Requesting testing on other platforms

V1: http://www.mail-archive.com/u-boot at lists.denx.de/msg40969.html

 drivers/mmc/omap_hsmmc.c |  114 +++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 97 insertions(+), 17 deletions(-)

diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 9271470..f7bdfe9 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -30,6 +30,7 @@
 #include <twl4030.h>
 #include <asm/io.h>
 #include <asm/arch/mmc_host_def.h>
+#define MAX_RETRY	100000
 
 static int mmc_read_data(hsmmc_t *mmc_base, char *buf, unsigned int size);
 static int mmc_write_data(hsmmc_t *mmc_base, const char *buf, unsigned int siz);
@@ -70,18 +71,32 @@ unsigned char mmc_board_init(hsmmc_t *mmc_base)
 
 void mmc_init_stream(hsmmc_t *mmc_base)
 {
+	int retry = MAX_RETRY;
 
 	writel(readl(&mmc_base->con) | INIT_INITSTREAM, &mmc_base->con);
 
 	writel(MMC_CMD0, &mmc_base->cmd);
-	while (!(readl(&mmc_base->stat) & CC_MASK))
-		;
+	while (!(readl(&mmc_base->stat) & CC_MASK)) {
+		retry--;
+		udelay(10);
+		if (!retry) {
+			printf("%s: timedout waiting for cc!\n", __func__);
+			return;
+		}
+	}
 	writel(CC_MASK, &mmc_base->stat)
 		;
 	writel(MMC_CMD0, &mmc_base->cmd)
 		;
-	while (!(readl(&mmc_base->stat) & CC_MASK))
-		;
+	retry = MAX_RETRY;
+	while (!(readl(&mmc_base->stat) & CC_MASK)) {
+		retry--;
+		udelay(10);
+		if (!retry) {
+			printf("%s: timedout waiting for cc2!\n", __func__);
+			return;
+		}
+	}
 	writel(readl(&mmc_base->con) & ~INIT_INITSTREAM, &mmc_base->con);
 }
 
@@ -91,16 +106,31 @@ static int mmc_init_setup(struct mmc *mmc)
 	hsmmc_t *mmc_base = (hsmmc_t *)mmc->priv;
 	unsigned int reg_val;
 	unsigned int dsor;
+	int retry = MAX_RETRY;
 
 	mmc_board_init(mmc_base);
 
 	writel(readl(&mmc_base->sysconfig) | MMC_SOFTRESET,
 		&mmc_base->sysconfig);
-	while ((readl(&mmc_base->sysstatus) & RESETDONE) == 0)
-		;
+	while ((readl(&mmc_base->sysstatus) & RESETDONE) == 0) {
+		retry--;
+		udelay(10);
+		if (!retry) {
+			printf("%s: timedout waiting for cc2!\n", __func__);
+			return TIMEOUT;
+		}
+	}
 	writel(readl(&mmc_base->sysctl) | SOFTRESETALL, &mmc_base->sysctl);
-	while ((readl(&mmc_base->sysctl) & SOFTRESETALL) != 0x0)
-		;
+	retry = MAX_RETRY;
+	while ((readl(&mmc_base->sysctl) & SOFTRESETALL) != 0x0) {
+		retry--;
+		udelay(10);
+		if (!retry) {
+			printf("%s: timedout waiting for softresetall!\n",
+				__func__);
+			return TIMEOUT;
+		}
+	}
 	writel(DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V0, &mmc_base->hctl);
 	writel(readl(&mmc_base->capa) | VS30_3V0SUP | VS18_1V8SUP,
 		&mmc_base->capa);
@@ -116,8 +146,15 @@ static int mmc_init_setup(struct mmc *mmc)
 		(ICE_STOP | DTO_15THDTO | CEN_DISABLE));
 	mmc_reg_out(&mmc_base->sysctl, ICE_MASK | CLKD_MASK,
 		(dsor << CLKD_OFFSET) | ICE_OSCILLATE);
-	while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY)
-		;
+	retry = MAX_RETRY;
+	while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) {
+		retry--;
+		udelay(10);
+		if (!retry) {
+			printf("%s: timedout waiting for ics!\n", __func__);
+			return TIMEOUT;
+		}
+	}
 	writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl);
 
 	writel(readl(&mmc_base->hctl) | SDBP_PWRON, &mmc_base->hctl);
@@ -137,14 +174,27 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 {
 	hsmmc_t *mmc_base = (hsmmc_t *)mmc->priv;
 	unsigned int flags, mmc_stat;
-	unsigned int retry = 0x100000;
+	int retry = MAX_RETRY;
 
 
-	while ((readl(&mmc_base->pstate) & DATI_MASK) == DATI_CMDDIS)
-		;
+	while ((readl(&mmc_base->pstate) & DATI_MASK) == DATI_CMDDIS) {
+		retry--;
+		udelay(10);
+		if (!retry) {
+			printf("%s: timedout waiting for cmddis!\n", __func__);
+			return TIMEOUT;
+		}
+	}
 	writel(0xFFFFFFFF, &mmc_base->stat);
-	while (readl(&mmc_base->stat))
-		;
+	retry = MAX_RETRY;
+	while (readl(&mmc_base->stat)) {
+		retry--;
+		udelay(10);
+		if (!retry) {
+			printf("%s: timedout waiting for stat!\n", __func__);
+			return TIMEOUT;
+		}
+	}
 	/*
 	 * CMDREG
 	 * CMDIDX[13:8]	: Command index
@@ -200,8 +250,11 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 	writel(cmd->cmdarg, &mmc_base->arg);
 	writel((cmd->cmdidx << 24) | flags, &mmc_base->cmd);
 
+	retry = MAX_RETRY;
 	do {
 		mmc_stat = readl(&mmc_base->stat);
+		if (!mmc_stat)
+			udelay(10);
 		retry--;
 	} while ((mmc_stat == 0) && (retry > 0));
 
@@ -253,8 +306,18 @@ static int mmc_read_data(hsmmc_t *mmc_base, char *buf, unsigned int size)
 	count /= 4;
 
 	while (size) {
+		int retry = MAX_RETRY;
 		do {
 			mmc_stat = readl(&mmc_base->stat);
+			if (!mmc_stat) {
+				retry--;
+				udelay(10);
+			}
+			if (!retry) {
+				printf("%s: timedout waiting for status!\n",
+						__func__);
+				return TIMEOUT;
+			}
 		} while (mmc_stat == 0);
 
 		if ((mmc_stat & ERRI_MASK) != 0)
@@ -298,8 +361,18 @@ static int mmc_write_data(hsmmc_t *mmc_base, const char *buf, unsigned int size)
 	count /= 4;
 
 	while (size) {
+		int retry = MAX_RETRY;
 		do {
 			mmc_stat = readl(&mmc_base->stat);
+			if (!mmc_stat) {
+				retry--;
+				udelay(10);
+			}
+			if (!retry) {
+				printf("%s: timedout waiting for status!\n",
+						__func__);
+				return TIMEOUT;
+			}
 		} while (mmc_stat == 0);
 
 		if ((mmc_stat & ERRI_MASK) != 0)
@@ -334,6 +407,7 @@ static void mmc_set_ios(struct mmc *mmc)
 {
 	hsmmc_t *mmc_base = (hsmmc_t *)mmc->priv;
 	unsigned int dsor = 0;
+	int retry = MAX_RETRY;
 
 	/* configue bus width */
 	switch (mmc->bus_width) {
@@ -372,8 +446,14 @@ static void mmc_set_ios(struct mmc *mmc)
 	mmc_reg_out(&mmc_base->sysctl, ICE_MASK | CLKD_MASK,
 				(dsor << CLKD_OFFSET) | ICE_OSCILLATE);
 
-	while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY)
-		;
+	while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) {
+		retry--;
+		udelay(10);
+		if (!retry) {
+			printf("%s: timedout waiting for ics!\n", __func__);
+			return;
+		}
+	}
 	writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl);
 }
 
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2010-11-01 20:15 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-26  1:02 [U-Boot] [PATCH v2] mmc: omap: timeout counter fix Nishanth Menon
2010-10-26  1:14 ` Reinhard Meyer
2010-10-26  1:18   ` Nishanth Menon
2010-10-26  5:29     ` Wolfgang Denk
2010-10-26  5:28   ` Wolfgang Denk
2010-10-26  5:34     ` Ghorai, Sukumar
2010-10-26 13:58       ` Nishanth Menon
2010-10-26  5:43     ` Reinhard Meyer
2010-10-26  5:48       ` Wolfgang Denk
2010-10-26  6:01         ` Reinhard Meyer
2010-10-26  7:00           ` [U-Boot] Timer implementations (was: Re: [PATCH v2] mmc: omap: timeout counter fix) Reinhard Meyer
2010-10-26  7:41             ` Wolfgang Denk
2010-10-26  7:57               ` [U-Boot] Timer implementations Reinhard Meyer
2010-10-26  9:33                 ` Wolfgang Denk
2010-10-26 10:18                   ` Reinhard Meyer
2010-10-26 13:05                     ` Wolfgang Denk
2010-10-26 13:33                       ` Reinhard Meyer
2010-10-26 21:19                         ` J. William Campbell
2010-10-28  6:02                           ` Reinhard Meyer
2010-11-01 13:47                             ` J. William Campbell
2010-11-01 20:01                               ` Reinhard Meyer
2010-11-01 20:15                                 ` Wolfgang Denk
2010-10-26 15:11                 ` Nishanth Menon
2010-10-26 15:17                   ` Wolfgang Denk
2010-10-26 15:22                     ` Nishanth Menon
2010-10-26 16:26                       ` Wolfgang Denk
2010-10-26 18:36                         ` Reinhard Meyer
2010-10-26  7:03           ` [U-Boot] [PATCH v2] mmc: omap: timeout counter fix J. William Campbell
2010-10-26  7:36           ` Wolfgang Denk
2010-10-26  7:48             ` Reinhard Meyer
2010-10-26  4:36 ` Wolfgang Denk
2010-10-26  5:26   ` Ghorai, Sukumar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox