From b7e4837f5ddc96a150a87be1ae9895738332d899 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 26 May 2009 22:35:34 -0400 Subject: [PATCH] --- yaml --- r: 145525 b: refs/heads/master c: a6d297f008e124d0bb4312369191b012c10a1a4e h: refs/heads/master i: 145523: 9d97ea75969a2579e3be540709991c20a4bb00d5 v: v3 --- [refs] | 2 +- trunk/drivers/mmc/host/mvsdio.c | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 60a7125e451a..db8e9505db92 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9ca6944cbfad11f2368cf10292e7f3eb036386c2 +refs/heads/master: a6d297f008e124d0bb4312369191b012c10a1a4e diff --git a/trunk/drivers/mmc/host/mvsdio.c b/trunk/drivers/mmc/host/mvsdio.c index 9d3cfa9909c9..b56d72ff06e9 100644 --- a/trunk/drivers/mmc/host/mvsdio.c +++ b/trunk/drivers/mmc/host/mvsdio.c @@ -64,6 +64,31 @@ static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data) unsigned int tmout; int tmout_index; + /* + * Hardware weirdness. The FIFO_EMPTY bit of the HW_STATE + * register is sometimes not set before a while when some + * "unusual" data block sizes are used (such as with the SWITCH + * command), even despite the fact that the XFER_DONE interrupt + * was raised. And if another data transfer starts before + * this bit comes to good sense (which eventually happens by + * itself) then the new transfer simply fails with a timeout. + */ + if (!(mvsd_read(MVSD_HW_STATE) & (1 << 13))) { + unsigned long t = jiffies + HZ; + unsigned int hw_state, count = 0; + do { + if (time_after(jiffies, t)) { + dev_warn(host->dev, "FIFO_EMPTY bit missing\n"); + break; + } + hw_state = mvsd_read(MVSD_HW_STATE); + count++; + } while (!(hw_state & (1 << 13))); + dev_dbg(host->dev, "*** wait for FIFO_EMPTY bit " + "(hw=0x%04x, count=%d, jiffies=%ld)\n", + hw_state, count, jiffies - (t - HZ)); + } + /* If timeout=0 then maximum timeout index is used. */ tmout = DIV_ROUND_UP(data->timeout_ns, host->ns_per_clk); tmout += data->timeout_clks;