diff options
Diffstat (limited to 'drivers/mmc/core/core.c')
-rw-r--r-- | drivers/mmc/core/core.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 1445ea8f10a6..264911732756 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -298,6 +298,21 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) data->timeout_clks = 0; } } + /* + * Some cards need very high timeouts if driven in SPI mode. + * The worst observed timeout was 900ms after writing a + * continuous stream of data until the internal logic + * overflowed. + */ + if (mmc_host_is_spi(card->host)) { + if (data->flags & MMC_DATA_WRITE) { + if (data->timeout_ns < 1000000000) + data->timeout_ns = 1000000000; /* 1s */ + } else { + if (data->timeout_ns < 100000000) + data->timeout_ns = 100000000; /* 100ms */ + } + } } EXPORT_SYMBOL(mmc_set_data_timeout); @@ -691,7 +706,7 @@ static void mmc_power_up(struct mmc_host *host) * This delay should be sufficient to allow the power supply * to reach the minimum voltage. */ - mmc_delay(2); + mmc_delay(10); host->ios.clock = host->f_min; host->ios.power_mode = MMC_POWER_ON; @@ -701,7 +716,7 @@ static void mmc_power_up(struct mmc_host *host) * This delay must be at least 74 clock sizes, or 1 ms, or the * time required to reach a stable voltage. */ - mmc_delay(2); + mmc_delay(10); } static void mmc_power_off(struct mmc_host *host) @@ -915,6 +930,7 @@ void mmc_stop_host(struct mmc_host *host) spin_unlock_irqrestore(&host->lock, flags); #endif + cancel_delayed_work(&host->detect); mmc_flush_scheduled_work(); mmc_bus_get(host); @@ -942,6 +958,7 @@ void mmc_stop_host(struct mmc_host *host) */ int mmc_suspend_host(struct mmc_host *host, pm_message_t state) { + cancel_delayed_work(&host->detect); mmc_flush_scheduled_work(); mmc_bus_get(host); @@ -975,6 +992,7 @@ int mmc_resume_host(struct mmc_host *host) mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { mmc_power_up(host); + mmc_select_voltage(host, host->ocr); BUG_ON(!host->bus_ops->resume); host->bus_ops->resume(host); } |