|
@@ -529,6 +529,18 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
|
|
|
data->timeout_clks = 0;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Some cards require longer data read timeout than indicated in CSD.
|
|
|
+ * Address this by setting the read timeout to a "reasonably high"
|
|
|
+ * value. For the cards tested, 300ms has proven enough. If necessary,
|
|
|
+ * this value can be increased if other problematic cards require this.
|
|
|
+ */
|
|
|
+ if (mmc_card_long_read_time(card) && data->flags & MMC_DATA_READ) {
|
|
|
+ data->timeout_ns = 300000000;
|
|
|
+ data->timeout_clks = 0;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* Some cards need very high timeouts if driven in SPI mode.
|
|
|
* The worst observed timeout was 900ms after writing a
|
|
@@ -1213,6 +1225,46 @@ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type)
|
|
|
mmc_host_clk_release(host);
|
|
|
}
|
|
|
|
|
|
+static void mmc_poweroff_notify(struct mmc_host *host)
|
|
|
+{
|
|
|
+ struct mmc_card *card;
|
|
|
+ unsigned int timeout;
|
|
|
+ unsigned int notify_type = EXT_CSD_NO_POWER_NOTIFICATION;
|
|
|
+ int err = 0;
|
|
|
+
|
|
|
+ card = host->card;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Send power notify command only if card
|
|
|
+ * is mmc and notify state is powered ON
|
|
|
+ */
|
|
|
+ if (card && mmc_card_mmc(card) &&
|
|
|
+ (card->poweroff_notify_state == MMC_POWERED_ON)) {
|
|
|
+
|
|
|
+ if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) {
|
|
|
+ notify_type = EXT_CSD_POWER_OFF_SHORT;
|
|
|
+ timeout = card->ext_csd.generic_cmd6_time;
|
|
|
+ card->poweroff_notify_state = MMC_POWEROFF_SHORT;
|
|
|
+ } else {
|
|
|
+ notify_type = EXT_CSD_POWER_OFF_LONG;
|
|
|
+ timeout = card->ext_csd.power_off_longtime;
|
|
|
+ card->poweroff_notify_state = MMC_POWEROFF_LONG;
|
|
|
+ }
|
|
|
+
|
|
|
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
|
+ EXT_CSD_POWER_OFF_NOTIFICATION,
|
|
|
+ notify_type, timeout);
|
|
|
+
|
|
|
+ if (err && err != -EBADMSG)
|
|
|
+ pr_err("Device failed to respond within %d poweroff "
|
|
|
+ "time. Forcefully powering down the device\n",
|
|
|
+ timeout);
|
|
|
+
|
|
|
+ /* Set the card state to no notification after the poweroff */
|
|
|
+ card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Apply power to the MMC stack. This is a two-stage process.
|
|
|
* First, we enable power to the card without the clock running.
|
|
@@ -1269,42 +1321,12 @@ static void mmc_power_up(struct mmc_host *host)
|
|
|
|
|
|
void mmc_power_off(struct mmc_host *host)
|
|
|
{
|
|
|
- struct mmc_card *card;
|
|
|
- unsigned int notify_type;
|
|
|
- unsigned int timeout;
|
|
|
- int err;
|
|
|
-
|
|
|
mmc_host_clk_hold(host);
|
|
|
|
|
|
- card = host->card;
|
|
|
host->ios.clock = 0;
|
|
|
host->ios.vdd = 0;
|
|
|
|
|
|
- if (card && mmc_card_mmc(card) &&
|
|
|
- (card->poweroff_notify_state == MMC_POWERED_ON)) {
|
|
|
-
|
|
|
- if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) {
|
|
|
- notify_type = EXT_CSD_POWER_OFF_SHORT;
|
|
|
- timeout = card->ext_csd.generic_cmd6_time;
|
|
|
- card->poweroff_notify_state = MMC_POWEROFF_SHORT;
|
|
|
- } else {
|
|
|
- notify_type = EXT_CSD_POWER_OFF_LONG;
|
|
|
- timeout = card->ext_csd.power_off_longtime;
|
|
|
- card->poweroff_notify_state = MMC_POWEROFF_LONG;
|
|
|
- }
|
|
|
-
|
|
|
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
|
- EXT_CSD_POWER_OFF_NOTIFICATION,
|
|
|
- notify_type, timeout);
|
|
|
-
|
|
|
- if (err && err != -EBADMSG)
|
|
|
- pr_err("Device failed to respond within %d poweroff "
|
|
|
- "time. Forcefully powering down the device\n",
|
|
|
- timeout);
|
|
|
-
|
|
|
- /* Set the card state to no notification after the poweroff */
|
|
|
- card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION;
|
|
|
- }
|
|
|
+ mmc_poweroff_notify(host);
|
|
|
|
|
|
/*
|
|
|
* Reset ocr mask to be the highest possible voltage supported for
|
|
@@ -2196,7 +2218,7 @@ int mmc_card_sleep(struct mmc_host *host)
|
|
|
|
|
|
mmc_bus_get(host);
|
|
|
|
|
|
- if (host->bus_ops && !host->bus_dead && host->bus_ops->awake)
|
|
|
+ if (host->bus_ops && !host->bus_dead && host->bus_ops->sleep)
|
|
|
err = host->bus_ops->sleep(host);
|
|
|
|
|
|
mmc_bus_put(host);
|
|
@@ -2302,8 +2324,17 @@ int mmc_suspend_host(struct mmc_host *host)
|
|
|
* pre-claim the host.
|
|
|
*/
|
|
|
if (mmc_try_claim_host(host)) {
|
|
|
- if (host->bus_ops->suspend)
|
|
|
+ if (host->bus_ops->suspend) {
|
|
|
+ /*
|
|
|
+ * For eMMC 4.5 device send notify command
|
|
|
+ * before sleep, because in sleep state eMMC 4.5
|
|
|
+ * devices respond to only RESET and AWAKE cmd
|
|
|
+ */
|
|
|
+ mmc_poweroff_notify(host);
|
|
|
err = host->bus_ops->suspend(host);
|
|
|
+ }
|
|
|
+ mmc_do_release_host(host);
|
|
|
+
|
|
|
if (err == -ENOSYS || !host->bus_ops->resume) {
|
|
|
/*
|
|
|
* We simply "remove" the card in this case.
|
|
@@ -2318,7 +2349,6 @@ int mmc_suspend_host(struct mmc_host *host)
|
|
|
host->pm_flags = 0;
|
|
|
err = 0;
|
|
|
}
|
|
|
- mmc_do_release_host(host);
|
|
|
} else {
|
|
|
err = -EBUSY;
|
|
|
}
|