mmc: dw_mmc: check fifo status with a timeout in fifo mode
While trying to enable the dw_mmc on rk3188 I managed to confuse and hang the dw_mmc controller into not delivering further data. The fifo state never became ready and the driver was iterating in the while loop reading 0-byte packets forever. So inspired by how other implementations handle this, check the fifo- state beforhand and add a timeout to catch any glaring fifo issues without hanging uboot altogether. Signed-off-by: Heiko Stuebner <heiko@sntech.de> Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com> Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
This commit is contained in:
parent
2ba8bf2074
commit
05fa06b960
@ -92,6 +92,24 @@ static void dwmci_prepare_data(struct dwmci_host *host,
|
||||
dwmci_writel(host, DWMCI_BYTCNT, data->blocksize * data->blocks);
|
||||
}
|
||||
|
||||
static int dwmci_fifo_ready(struct dwmci_host *host, u32 bit, u32 *len)
|
||||
{
|
||||
u32 timeout = 20000;
|
||||
|
||||
*len = dwmci_readl(host, DWMCI_STATUS);
|
||||
while (--timeout && (*len & bit)) {
|
||||
udelay(200);
|
||||
*len = dwmci_readl(host, DWMCI_STATUS);
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
debug("%s: FIFO underflow timeout\n", __func__);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data)
|
||||
{
|
||||
int ret = 0;
|
||||
@ -122,7 +140,12 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data)
|
||||
if (data->flags == MMC_DATA_READ &&
|
||||
(mask & DWMCI_INTMSK_RXDR)) {
|
||||
while (size) {
|
||||
len = dwmci_readl(host, DWMCI_STATUS);
|
||||
ret = dwmci_fifo_ready(host,
|
||||
DWMCI_FIFO_EMPTY,
|
||||
&len);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
len = (len >> DWMCI_FIFO_SHIFT) &
|
||||
DWMCI_FIFO_MASK;
|
||||
len = min(size, len);
|
||||
@ -136,7 +159,12 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data)
|
||||
} else if (data->flags == MMC_DATA_WRITE &&
|
||||
(mask & DWMCI_INTMSK_TXDR)) {
|
||||
while (size) {
|
||||
len = dwmci_readl(host, DWMCI_STATUS);
|
||||
ret = dwmci_fifo_ready(host,
|
||||
DWMCI_FIFO_FULL,
|
||||
&len);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
len = fifo_depth - ((len >>
|
||||
DWMCI_FIFO_SHIFT) &
|
||||
DWMCI_FIFO_MASK);
|
||||
|
@ -103,6 +103,8 @@
|
||||
#define DWMCI_CTYPE_8BIT (1 << 16)
|
||||
|
||||
/* Status Register */
|
||||
#define DWMCI_FIFO_EMPTY (1 << 2)
|
||||
#define DWMCI_FIFO_FULL (1 << 3)
|
||||
#define DWMCI_BUSY (1 << 9)
|
||||
#define DWMCI_FIFO_MASK 0x1fff
|
||||
#define DWMCI_FIFO_SHIFT 17
|
||||
|
Loading…
Reference in New Issue
Block a user