diff options
Diffstat (limited to 'drivers/mmc/host/mvsdio.c')
-rw-r--r-- | drivers/mmc/host/mvsdio.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index c643d0fe118f..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; |
@@ -620,9 +645,18 @@ static void mvsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
620 | if (ios->bus_width == MMC_BUS_WIDTH_4) | 645 | if (ios->bus_width == MMC_BUS_WIDTH_4) |
621 | ctrl_reg |= MVSD_HOST_CTRL_DATA_WIDTH_4_BITS; | 646 | ctrl_reg |= MVSD_HOST_CTRL_DATA_WIDTH_4_BITS; |
622 | 647 | ||
648 | /* | ||
649 | * The HI_SPEED_EN bit is causing trouble with many (but not all) | ||
650 | * high speed SD, SDHC and SDIO cards. Not enabling that bit | ||
651 | * makes all cards work. So let's just ignore that bit for now | ||
652 | * and revisit this issue if problems for not enabling this bit | ||
653 | * are ever reported. | ||
654 | */ | ||
655 | #if 0 | ||
623 | if (ios->timing == MMC_TIMING_MMC_HS || | 656 | if (ios->timing == MMC_TIMING_MMC_HS || |
624 | ios->timing == MMC_TIMING_SD_HS) | 657 | ios->timing == MMC_TIMING_SD_HS) |
625 | ctrl_reg |= MVSD_HOST_CTRL_HI_SPEED_EN; | 658 | ctrl_reg |= MVSD_HOST_CTRL_HI_SPEED_EN; |
659 | #endif | ||
626 | 660 | ||
627 | host->ctrl = ctrl_reg; | 661 | host->ctrl = ctrl_reg; |
628 | mvsd_write(MVSD_HOST_CTRL, ctrl_reg); | 662 | mvsd_write(MVSD_HOST_CTRL, ctrl_reg); |
@@ -882,3 +916,4 @@ module_param(nodma, int, 0); | |||
882 | MODULE_AUTHOR("Maen Suleiman, Nicolas Pitre"); | 916 | MODULE_AUTHOR("Maen Suleiman, Nicolas Pitre"); |
883 | MODULE_DESCRIPTION("Marvell MMC,SD,SDIO Host Controller driver"); | 917 | MODULE_DESCRIPTION("Marvell MMC,SD,SDIO Host Controller driver"); |
884 | MODULE_LICENSE("GPL"); | 918 | MODULE_LICENSE("GPL"); |
919 | MODULE_ALIAS("platform:mvsdio"); | ||