Hi Andrzej, On Tue, Feb 10, 2015 at 7:59 PM, Andrzej Hajda <a.hajda@xxxxxxxxxxx> wrote: > According to specs for version 250A, status register should be > tested before clock update. Otherwise in case MMC card is missing > mci_send_cmd timeouts and subsequent CTYPE registry write causes system hang. > This behavior has been observed on Exynos5422/Odroid-XU3. > A similar patch was posted recently[1], did you check that? [1] http://www.spinics.net/lists/linux-doc/msg28092.html > Signed-off-by: Andrzej Hajda <a.hajda@xxxxxxxxxxx> > --- > Hi, > > This version corrects usleep to usleep_range function call. > > Regards > Andrzej > --- > drivers/mmc/host/dw_mmc.c | 26 ++++++++++++++++++++++++-- > drivers/mmc/host/dw_mmc.h | 1 + > 2 files changed, 25 insertions(+), 2 deletions(-) > > diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c > index 67c0451..6619c8a 100644 > --- a/drivers/mmc/host/dw_mmc.c > +++ b/drivers/mmc/host/dw_mmc.c > @@ -878,6 +878,25 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg) > cmd, arg, cmd_status); > } > > +static bool dw_mci_wait_busy(struct dw_mci *host) > +{ > + unsigned long timeout; > + > + if (host->verid < DW_MMC_250A) > + return true; > + I wonder this might be true for 240A as well. > + timeout = jiffies + msecs_to_jiffies(500); > + while (time_before(jiffies, timeout)) { > + if (!(mci_readl(host, STATUS) & SDMMC_STATUS_BUSY)) > + return true; > + > + usleep_range(1000, 2000); > + } > + dev_err(host->dev, "Busy timeout\n"); Probably you need a controller reset here to bring back controller is original state. > + > + return false; > +} > + > static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) > { > struct dw_mci *host = slot->host; > @@ -891,8 +910,11 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) > sdmmc_cmd_bits |= SDMMC_CMD_VOLT_SWITCH; > > if (!clock) { > - mci_writel(host, CLKENA, 0); > - mci_send_cmd(slot, sdmmc_cmd_bits, 0); > + if (dw_mci_wait_busy(host)) { > + mci_writel(host, CLKENA, 0); > + mci_send_cmd(slot, sdmmc_cmd_bits, 0); > + } else > + return; > } else if (clock != host->current_speed || force_clkinit) { > div = host->bus_hz / clock; > if (host->bus_hz % clock && host->bus_hz > clock) > diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h > index 0d0f7a27..ea6d4d1 100644 > --- a/drivers/mmc/host/dw_mmc.h > +++ b/drivers/mmc/host/dw_mmc.h > @@ -15,6 +15,7 @@ > #define _DW_MMC_H_ > > #define DW_MMC_240A 0x240a > +#define DW_MMC_250A 0x250a > > #define SDMMC_CTRL 0x000 > #define SDMMC_PWREN 0x004 > -- > 1.9.1 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-mmc" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Regards, Alim -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html