diff options
| -rw-r--r-- | drivers/mmc/host/mvsdio.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index 9d3cfa9909c9..b56d72ff06e9 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c | |||
| @@ -64,6 +64,31 @@ static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data) | |||
| 64 | unsigned int tmout; | 64 | unsigned int tmout; |
| 65 | int tmout_index; | 65 | int tmout_index; |
| 66 | 66 | ||
| 67 | /* | ||
| 68 | * Hardware weirdness. The FIFO_EMPTY bit of the HW_STATE | ||
| 69 | * register is sometimes not set before a while when some | ||
| 70 | * "unusual" data block sizes are used (such as with the SWITCH | ||
| 71 | * command), even despite the fact that the XFER_DONE interrupt | ||
| 72 | * was raised. And if another data transfer starts before | ||
| 73 | * this bit comes to good sense (which eventually happens by | ||
| 74 | * itself) then the new transfer simply fails with a timeout. | ||
| 75 | */ | ||
| 76 | if (!(mvsd_read(MVSD_HW_STATE) & (1 << 13))) { | ||
| 77 | unsigned long t = jiffies + HZ; | ||
| 78 | unsigned int hw_state, count = 0; | ||
| 79 | do { | ||
| 80 | if (time_after(jiffies, t)) { | ||
| 81 | dev_warn(host->dev, "FIFO_EMPTY bit missing\n"); | ||
| 82 | break; | ||
| 83 | } | ||
| 84 | hw_state = mvsd_read(MVSD_HW_STATE); | ||
| 85 | count++; | ||
| 86 | } while (!(hw_state & (1 << 13))); | ||
| 87 | dev_dbg(host->dev, "*** wait for FIFO_EMPTY bit " | ||
| 88 | "(hw=0x%04x, count=%d, jiffies=%ld)\n", | ||
| 89 | hw_state, count, jiffies - (t - HZ)); | ||
| 90 | } | ||
| 91 | |||
| 67 | /* If timeout=0 then maximum timeout index is used. */ | 92 | /* If timeout=0 then maximum timeout index is used. */ |
| 68 | tmout = DIV_ROUND_UP(data->timeout_ns, host->ns_per_clk); | 93 | tmout = DIV_ROUND_UP(data->timeout_ns, host->ns_per_clk); |
| 69 | tmout += data->timeout_clks; | 94 | tmout += data->timeout_clks; |
