Merge tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck...
[linux-drm-fsl-dcu.git] / drivers / mmc / core / core.c
index bf18b6bfce487b2dd6a77917344c1514dc1aa7a8..57a2b403bf8e9107204c3cda03671a5a1c8bd87d 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/log2.h>
 #include <linux/regulator/consumer.h>
 #include <linux/pm_runtime.h>
+#include <linux/pm_wakeup.h>
 #include <linux/suspend.h>
 #include <linux/fault-inject.h>
 #include <linux/random.h>
@@ -301,7 +302,7 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception)
        }
 
        err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                       EXT_CSD_BKOPS_START, 1, timeout, use_busy_signal);
+                       EXT_CSD_BKOPS_START, 1, timeout, use_busy_signal, true);
        if (err) {
                pr_warn("%s: Error %d starting bkops\n",
                        mmc_hostname(card->host), err);
@@ -917,31 +918,6 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
 
 EXPORT_SYMBOL(__mmc_claim_host);
 
-/**
- *     mmc_try_claim_host - try exclusively to claim a host
- *     @host: mmc host to claim
- *
- *     Returns %1 if the host is claimed, %0 otherwise.
- */
-int mmc_try_claim_host(struct mmc_host *host)
-{
-       int claimed_host = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&host->lock, flags);
-       if (!host->claimed || host->claimer == current) {
-               host->claimed = 1;
-               host->claimer = current;
-               host->claim_cnt += 1;
-               claimed_host = 1;
-       }
-       spin_unlock_irqrestore(&host->lock, flags);
-       if (host->ops->enable && claimed_host && host->claim_cnt == 1)
-               host->ops->enable(host);
-       return claimed_host;
-}
-EXPORT_SYMBOL(mmc_try_claim_host);
-
 /**
  *     mmc_release_host - release a host
  *     @host: mmc host to release
@@ -1382,22 +1358,31 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
 {
        int bit;
 
-       ocr &= host->ocr_avail;
+       /*
+        * Sanity check the voltages that the card claims to
+        * support.
+        */
+       if (ocr & 0x7F) {
+               dev_warn(mmc_dev(host),
+               "card claims to support voltages below defined range\n");
+               ocr &= ~0x7F;
+       }
 
-       bit = ffs(ocr);
-       if (bit) {
-               bit -= 1;
+       ocr &= host->ocr_avail;
+       if (!ocr) {
+               dev_warn(mmc_dev(host), "no support for card's volts\n");
+               return 0;
+       }
 
+       if (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) {
+               bit = ffs(ocr) - 1;
                ocr &= 3 << bit;
-
-               mmc_host_clk_hold(host);
-               host->ios.vdd = bit;
-               mmc_set_ios(host);
-               mmc_host_clk_release(host);
+               mmc_power_cycle(host, ocr);
        } else {
-               pr_warning("%s: host doesn't support card's voltages\n",
-                               mmc_hostname(host));
-               ocr = 0;
+               bit = fls(ocr) - 1;
+               ocr &= 3 << bit;
+               if (bit != host->ios.vdd)
+                       dev_warn(mmc_dev(host), "exceeding card's volts\n");
        }
 
        return ocr;
@@ -1422,7 +1407,7 @@ int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage)
 
 }
 
-int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage)
+int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr)
 {
        struct mmc_command cmd = {0};
        int err = 0;
@@ -1504,7 +1489,7 @@ power_cycle:
        if (err) {
                pr_debug("%s: Signal voltage switch failed, "
                        "power cycling card\n", mmc_hostname(host));
-               mmc_power_cycle(host);
+               mmc_power_cycle(host, ocr);
        }
 
        mmc_host_clk_release(host);
@@ -1545,22 +1530,14 @@ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type)
  * If a host does all the power sequencing itself, ignore the
  * initial MMC_POWER_UP stage.
  */
-void mmc_power_up(struct mmc_host *host)
+void mmc_power_up(struct mmc_host *host, u32 ocr)
 {
-       int bit;
-
        if (host->ios.power_mode == MMC_POWER_ON)
                return;
 
        mmc_host_clk_hold(host);
 
-       /* If ocr is set, we use it */
-       if (host->ocr)
-               bit = ffs(host->ocr) - 1;
-       else
-               bit = fls(host->ocr_avail) - 1;
-
-       host->ios.vdd = bit;
+       host->ios.vdd = fls(ocr) - 1;
        if (mmc_host_is_spi(host))
                host->ios.chip_select = MMC_CS_HIGH;
        else
@@ -1604,13 +1581,6 @@ void mmc_power_off(struct mmc_host *host)
        host->ios.clock = 0;
        host->ios.vdd = 0;
 
-
-       /*
-        * Reset ocr mask to be the highest possible voltage supported for
-        * this mmc host. This value will be used at next power up.
-        */
-       host->ocr = 1 << (fls(host->ocr_avail) - 1);
-
        if (!mmc_host_is_spi(host)) {
                host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
                host->ios.chip_select = MMC_CS_DONTCARE;
@@ -1630,12 +1600,12 @@ void mmc_power_off(struct mmc_host *host)
        mmc_host_clk_release(host);
 }
 
-void mmc_power_cycle(struct mmc_host *host)
+void mmc_power_cycle(struct mmc_host *host, u32 ocr)
 {
        mmc_power_off(host);
        /* Wait at least 1 ms according to SD spec */
        mmc_delay(1);
-       mmc_power_up(host);
+       mmc_power_up(host, ocr);
 }
 
 /*
@@ -1723,6 +1693,28 @@ void mmc_detach_bus(struct mmc_host *host)
        mmc_bus_put(host);
 }
 
+static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
+                               bool cd_irq)
+{
+#ifdef CONFIG_MMC_DEBUG
+       unsigned long flags;
+       spin_lock_irqsave(&host->lock, flags);
+       WARN_ON(host->removed);
+       spin_unlock_irqrestore(&host->lock, flags);
+#endif
+
+       /*
+        * If the device is configured as wakeup, we prevent a new sleep for
+        * 5 s to give provision for user space to consume the event.
+        */
+       if (cd_irq && !(host->caps & MMC_CAP_NEEDS_POLL) &&
+               device_can_wakeup(mmc_dev(host)))
+               pm_wakeup_event(mmc_dev(host), 5000);
+
+       host->detect_change = 1;
+       mmc_schedule_delayed_work(&host->detect, delay);
+}
+
 /**
  *     mmc_detect_change - process change of state on a MMC socket
  *     @host: host which changed state.
@@ -1735,16 +1727,8 @@ void mmc_detach_bus(struct mmc_host *host)
  */
 void mmc_detect_change(struct mmc_host *host, unsigned long delay)
 {
-#ifdef CONFIG_MMC_DEBUG
-       unsigned long flags;
-       spin_lock_irqsave(&host->lock, flags);
-       WARN_ON(host->removed);
-       spin_unlock_irqrestore(&host->lock, flags);
-#endif
-       host->detect_change = 1;
-       mmc_schedule_delayed_work(&host->detect, delay);
+       _mmc_detect_change(host, delay, true);
 }
-
 EXPORT_SYMBOL(mmc_detect_change);
 
 void mmc_init_erase(struct mmc_card *card)
@@ -2334,7 +2318,7 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
        pr_info("%s: %s: trying to init card at %u Hz\n",
                mmc_hostname(host), __func__, host->f_init);
 #endif
-       mmc_power_up(host);
+       mmc_power_up(host, host->ocr_avail);
 
        /*
         * Some eMMCs (with VCCQ always on) may not be reset after power up, so
@@ -2423,7 +2407,7 @@ int mmc_detect_card_removed(struct mmc_host *host)
                         * rescan handle the card removal.
                         */
                        cancel_delayed_work(&host->detect);
-                       mmc_detect_change(host, 0);
+                       _mmc_detect_change(host, 0, false);
                }
        }
 
@@ -2504,8 +2488,8 @@ void mmc_start_host(struct mmc_host *host)
        if (host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)
                mmc_power_off(host);
        else
-               mmc_power_up(host);
-       mmc_detect_change(host, 0);
+               mmc_power_up(host, host->ocr_avail);
+       _mmc_detect_change(host, 0, false);
 }
 
 void mmc_stop_host(struct mmc_host *host)
@@ -2583,7 +2567,7 @@ int mmc_power_restore_host(struct mmc_host *host)
                return -EINVAL;
        }
 
-       mmc_power_up(host);
+       mmc_power_up(host, host->card->ocr);
        ret = host->bus_ops->power_restore(host);
 
        mmc_bus_put(host);
@@ -2657,28 +2641,6 @@ EXPORT_SYMBOL(mmc_cache_ctrl);
 
 #ifdef CONFIG_PM
 
-/**
- *     mmc_suspend_host - suspend a host
- *     @host: mmc host
- */
-int mmc_suspend_host(struct mmc_host *host)
-{
-       /* This function is deprecated */
-       return 0;
-}
-EXPORT_SYMBOL(mmc_suspend_host);
-
-/**
- *     mmc_resume_host - resume a previously suspended host
- *     @host: mmc host
- */
-int mmc_resume_host(struct mmc_host *host)
-{
-       /* This function is deprecated */
-       return 0;
-}
-EXPORT_SYMBOL(mmc_resume_host);
-
 /* Do the card removal on suspend if card is assumed removeable
  * Do that in pm notifier while userspace isn't yet frozen, so we will be able
    to sync the card.
@@ -2724,7 +2686,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
                spin_lock_irqsave(&host->lock, flags);
                host->rescan_disable = 0;
                spin_unlock_irqrestore(&host->lock, flags);
-               mmc_detect_change(host, 0);
+               _mmc_detect_change(host, 0, false);
 
        }