From 703aaced2b9c9a98285f265f3444c2f89d9d4d19 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 9 May 2009 01:03:52 -0400 Subject: mvsdio: allow automatic loading when modular Signed-off-by: Nicolas Pitre Tested-by: Martin Michlmayr Signed-off-by: Pierre Ossman --- drivers/mmc/host/mvsdio.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mmc/host/mvsdio.c') diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index c643d0fe118..1783043a26a 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -882,3 +882,4 @@ module_param(nodma, int, 0); MODULE_AUTHOR("Maen Suleiman, Nicolas Pitre"); MODULE_DESCRIPTION("Marvell MMC,SD,SDIO Host Controller driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:mvsdio"); -- cgit v1.2.3 From 9ca6944cbfad11f2368cf10292e7f3eb036386c2 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 14 May 2009 21:28:05 -0400 Subject: mvsdio: ignore high speed timing requests from the core Empirical evidences show that this is causing far more problems than it solves when this mode is enabled in the host hardware. Amongst those cards that are known to be non functional when this bit is set are: A-Data "Speedy" 2GB SD card Kodak 512MB SD card Ativa 1GB MicroSD card Marvell 8688 (WIFI/Bluetooth) SDIO card Since those cards do work on other host controllers which do honnor the hs timing, the issue must be with this particular host hardware. Signed-off-by: Nicolas Pitre Signed-off-by: Pierre Ossman --- drivers/mmc/host/mvsdio.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/mmc/host/mvsdio.c') diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index 1783043a26a..9d3cfa9909c 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -620,9 +620,18 @@ static void mvsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (ios->bus_width == MMC_BUS_WIDTH_4) ctrl_reg |= MVSD_HOST_CTRL_DATA_WIDTH_4_BITS; + /* + * The HI_SPEED_EN bit is causing trouble with many (but not all) + * high speed SD, SDHC and SDIO cards. Not enabling that bit + * makes all cards work. So let's just ignore that bit for now + * and revisit this issue if problems for not enabling this bit + * are ever reported. + */ +#if 0 if (ios->timing == MMC_TIMING_MMC_HS || ios->timing == MMC_TIMING_SD_HS) ctrl_reg |= MVSD_HOST_CTRL_HI_SPEED_EN; +#endif host->ctrl = ctrl_reg; mvsd_write(MVSD_HOST_CTRL, ctrl_reg); -- cgit v1.2.3 From a6d297f008e124d0bb4312369191b012c10a1a4e Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 26 May 2009 22:35:34 -0400 Subject: mvsdio: fix config failure with some high speed SDHC cards Especially with Sandisk SDHC cards, the second SWITCH command was failing with a timeout and the card was not recognized at all. However if the system was busy, or debugging was enabled, or a udelay(100) was inserted before the second SWITCH command in the core code, then the timing was so that the card started to work. With some unusual block sizes, the data FIFO status doesn't indicate a "empty" state right away when the data transfer is done. Queuing another data transfer in that condition results in a transfer timeout. The empty FIFO bit eventually get set by itself in less than 50 usecs when it is not set right away. So let's just poll for that bit before configuring the controller with a new data transfer. Signed-off-by: Nicolas Pitre Signed-off-by: Pierre Ossman --- drivers/mmc/host/mvsdio.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers/mmc/host/mvsdio.c') diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index 9d3cfa9909c..b56d72ff06e 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) 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; -- cgit v1.2.3