diff options
author | John Stultz <john.stultz@linaro.org> | 2016-08-02 21:14:57 -0700 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2016-08-02 21:14:57 -0700 |
commit | 1cf5bdda8da6a99c395ce9d3a4611467086ec777 (patch) | |
tree | e81d3bbba4fd99d1c8d1b4239f358c1e09955ba1 | |
parent | 9b75322471725713a3f36685404c1494a5059a72 (diff) | |
download | OpenPlatformPkg-1cf5bdda8da6a99c395ce9d3a4611467086ec777.tar.gz |
DwSdDxe: Use a timeout counter to avoid uSD hang waiting for idle
This is a tweaked version of a patch earlier applied by Haojian.
In some cases, we're seeing bootup hang while polling SD_STATUS register,
and it seems to be stuck with the DATA_BUSY signal.
This patch tries to resolve this quirk by using a max loop counter
which will break out of the wait for idle loops if they run for
too long.
This can introduce small delays on boot when a uSD card is present
but is better then a hang, and avoids potential issues where we proceed
before the card is ready if the loop was just removed.
This patch also addresses both wait-for-idle loops.
Change-Id: I4be39e11eb42b611ab4ae50c4bc42324b00de9ee
Signed-off-by: John Stultz <john.stultz@linaro.org>
-rw-r--r-- | Drivers/Mmc/DwSdDxe/DwSdDxe.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/Drivers/Mmc/DwSdDxe/DwSdDxe.c b/Drivers/Mmc/DwSdDxe/DwSdDxe.c index 3eb8b1e..cbe6b77 100644 --- a/Drivers/Mmc/DwSdDxe/DwSdDxe.c +++ b/Drivers/Mmc/DwSdDxe/DwSdDxe.c @@ -37,6 +37,8 @@ #define DWSD_DMA_THRESHOLD 16 +#define MAX_IDLE_LOOPS 1000000 + typedef struct { UINT32 Des0; UINT32 Des1; @@ -165,7 +167,7 @@ DwSdSetClock ( IN UINTN ClockFreq ) { - UINT32 Divider, Rate, Data; + UINT32 Divider, Rate, Data, Count; EFI_STATUS Status; BOOLEAN Found = FALSE; @@ -180,8 +182,11 @@ DwSdSetClock ( return EFI_NOT_FOUND; // Wait until MMC is idle + Count = 0; do { Data = MmioRead32 (DWSD_STATUS); + if (Count++ > MAX_IDLE_LOOPS) + break; } while (Data & DWSD_STS_DATA_BUSY); // Disable MMC clock first @@ -282,14 +287,17 @@ SendCommand ( IN UINT32 Argument ) { - UINT32 Data, ErrMask; + UINT32 Data, ErrMask, Count; MmioWrite32 (DWSD_RINTSTS, ~0); MmioWrite32 (DWSD_CMDARG, Argument); MicroSecondDelay(500); // Wait until MMC is idle + Count = 0; do { Data = MmioRead32 (DWSD_STATUS); + if (Count++ > MAX_IDLE_LOOPS) + break; } while (Data & DWSD_STS_DATA_BUSY); MmioWrite32 (DWSD_CMD, MmcCmd); |