|
@@ -1212,11 +1212,43 @@ 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;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* Reset ocr mask to be the highest possible voltage supported for
|
|
|
* this mmc host. This value will be used at next power up.
|
|
@@ -2208,6 +2240,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
|
|
|
|
|
|
spin_lock_irqsave(&host->lock, flags);
|
|
|
host->rescan_disable = 1;
|
|
|
+ host->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
|
|
|
spin_unlock_irqrestore(&host->lock, flags);
|
|
|
cancel_delayed_work_sync(&host->detect);
|
|
|
|
|
@@ -2231,6 +2264,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
|
|
|
|
|
|
spin_lock_irqsave(&host->lock, flags);
|
|
|
host->rescan_disable = 0;
|
|
|
+ host->power_notify_type = MMC_HOST_PW_NOTIFY_LONG;
|
|
|
spin_unlock_irqrestore(&host->lock, flags);
|
|
|
mmc_detect_change(host, 0);
|
|
|
|