]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/mmc/host/sdhci.c
Merge tag 'mmc-updates-for-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel...
[karo-tx-linux.git] / drivers / mmc / host / sdhci.c
index 6f0bfc0c8c9ca96479165dfc6918228f63a9c9ce..51bbba486f381238c9f2dc26e4da1bdecb866d08 100644 (file)
@@ -53,6 +53,7 @@ static void sdhci_send_command(struct sdhci_host *, struct mmc_command *);
 static void sdhci_finish_command(struct sdhci_host *);
 static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
 static void sdhci_tuning_timer(unsigned long data);
+static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
 
 #ifdef CONFIG_PM_RUNTIME
 static int sdhci_runtime_pm_get(struct sdhci_host *host);
@@ -1082,6 +1083,37 @@ static void sdhci_finish_command(struct sdhci_host *host)
        }
 }
 
+static u16 sdhci_get_preset_value(struct sdhci_host *host)
+{
+       u16 ctrl, preset = 0;
+
+       ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+
+       switch (ctrl & SDHCI_CTRL_UHS_MASK) {
+       case SDHCI_CTRL_UHS_SDR12:
+               preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);
+               break;
+       case SDHCI_CTRL_UHS_SDR25:
+               preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR25);
+               break;
+       case SDHCI_CTRL_UHS_SDR50:
+               preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR50);
+               break;
+       case SDHCI_CTRL_UHS_SDR104:
+               preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104);
+               break;
+       case SDHCI_CTRL_UHS_DDR50:
+               preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50);
+               break;
+       default:
+               pr_warn("%s: Invalid UHS-I mode selected\n",
+                       mmc_hostname(host->mmc));
+               preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);
+               break;
+       }
+       return preset;
+}
+
 static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 {
        int div = 0; /* Initialized for compiler warning */
@@ -1106,35 +1138,43 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
                goto out;
 
        if (host->version >= SDHCI_SPEC_300) {
+               if (sdhci_readw(host, SDHCI_HOST_CONTROL2) &
+                       SDHCI_CTRL_PRESET_VAL_ENABLE) {
+                       u16 pre_val;
+
+                       clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+                       pre_val = sdhci_get_preset_value(host);
+                       div = (pre_val & SDHCI_PRESET_SDCLK_FREQ_MASK)
+                               >> SDHCI_PRESET_SDCLK_FREQ_SHIFT;
+                       if (host->clk_mul &&
+                               (pre_val & SDHCI_PRESET_CLKGEN_SEL_MASK)) {
+                               clk = SDHCI_PROG_CLOCK_MODE;
+                               real_div = div + 1;
+                               clk_mul = host->clk_mul;
+                       } else {
+                               real_div = max_t(int, 1, div << 1);
+                       }
+                       goto clock_set;
+               }
+
                /*
                 * Check if the Host Controller supports Programmable Clock
                 * Mode.
                 */
                if (host->clk_mul) {
-                       u16 ctrl;
-
+                       for (div = 1; div <= 1024; div++) {
+                               if ((host->max_clk * host->clk_mul / div)
+                                       <= clock)
+                                       break;
+                       }
                        /*
-                        * We need to figure out whether the Host Driver needs
-                        * to select Programmable Clock Mode, or the value can
-                        * be set automatically by the Host Controller based on
-                        * the Preset Value registers.
+                        * Set Programmable Clock Mode in the Clock
+                        * Control register.
                         */
-                       ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-                       if (!(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
-                               for (div = 1; div <= 1024; div++) {
-                                       if (((host->max_clk * host->clk_mul) /
-                                             div) <= clock)
-                                               break;
-                               }
-                               /*
-                                * Set Programmable Clock Mode in the Clock
-                                * Control register.
-                                */
-                               clk = SDHCI_PROG_CLOCK_MODE;
-                               real_div = div;
-                               clk_mul = host->clk_mul;
-                               div--;
-                       }
+                       clk = SDHCI_PROG_CLOCK_MODE;
+                       real_div = div;
+                       clk_mul = host->clk_mul;
+                       div--;
                } else {
                        /* Version 3.00 divisors must be a multiple of 2. */
                        if (host->max_clk <= clock)
@@ -1159,6 +1199,7 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
                div >>= 1;
        }
 
+clock_set:
        if (real_div)
                host->mmc->actual_clock = (host->max_clk * clk_mul) / real_div;
 
@@ -1189,6 +1230,15 @@ out:
        host->clock = clock;
 }
 
+static inline void sdhci_update_clock(struct sdhci_host *host)
+{
+       unsigned int clock;
+
+       clock = host->clock;
+       host->clock = 0;
+       sdhci_set_clock(host, clock);
+}
+
 static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
 {
        u8 pwr = 0;
@@ -1258,7 +1308,7 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
 static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
        struct sdhci_host *host;
-       bool present;
+       int present;
        unsigned long flags;
        u32 tuning_opcode;
 
@@ -1287,18 +1337,21 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
        host->mrq = mrq;
 
-       /* If polling, assume that the card is always present. */
-       if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
-               present = true;
-       else
-               present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
-                               SDHCI_CARD_PRESENT;
-
-       /* If we're using a cd-gpio, testing the presence bit might fail. */
-       if (!present) {
-               int ret = mmc_gpio_get_cd(host->mmc);
-               if (ret > 0)
-                       present = true;
+       /*
+        * Firstly check card presence from cd-gpio.  The return could
+        * be one of the following possibilities:
+        *     negative: cd-gpio is not available
+        *     zero: cd-gpio is used, and card is removed
+        *     one: cd-gpio is used, and card is present
+        */
+       present = mmc_gpio_get_cd(host->mmc);
+       if (present < 0) {
+               /* If polling, assume that the card is always present. */
+               if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
+                       present = 1;
+               else
+                       present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
+                                       SDHCI_CARD_PRESENT;
        }
 
        if (!present || host->flags & SDHCI_DEVICE_DEAD) {
@@ -1364,6 +1417,10 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
                sdhci_reinit(host);
        }
 
+       if (host->version >= SDHCI_SPEC_300 &&
+               (ios->power_mode == MMC_POWER_UP))
+               sdhci_enable_preset_value(host, false);
+
        sdhci_set_clock(host, ios->clock);
 
        if (ios->power_mode == MMC_POWER_OFF)
@@ -1383,11 +1440,11 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
        /*
         * If your platform has 8-bit width support but is not a v3 controller,
         * or if it requires special setup code, you should implement that in
-        * platform_8bit_width().
+        * platform_bus_width().
         */
-       if (host->ops->platform_8bit_width)
-               host->ops->platform_8bit_width(host, ios->bus_width);
-       else {
+       if (host->ops->platform_bus_width) {
+               host->ops->platform_bus_width(host, ios->bus_width);
+       else {
                ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
                if (ios->bus_width == MMC_BUS_WIDTH_8) {
                        ctrl &= ~SDHCI_CTRL_4BITBUS;
@@ -1415,7 +1472,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 
        if (host->version >= SDHCI_SPEC_300) {
                u16 clk, ctrl_2;
-               unsigned int clock;
 
                /* In case of UHS-I modes, set High Speed Enable */
                if ((ios->timing == MMC_TIMING_MMC_HS200) ||
@@ -1455,9 +1511,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
                        sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 
                        /* Re-enable SD Clock */
-                       clock = host->clock;
-                       host->clock = 0;
-                       sdhci_set_clock(host, clock);
+                       sdhci_update_clock(host);
                }
 
 
@@ -1487,10 +1541,22 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
                        sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
                }
 
+               if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&
+                               ((ios->timing == MMC_TIMING_UHS_SDR12) ||
+                                (ios->timing == MMC_TIMING_UHS_SDR25) ||
+                                (ios->timing == MMC_TIMING_UHS_SDR50) ||
+                                (ios->timing == MMC_TIMING_UHS_SDR104) ||
+                                (ios->timing == MMC_TIMING_UHS_DDR50))) {
+                       u16 preset;
+
+                       sdhci_enable_preset_value(host, true);
+                       preset = sdhci_get_preset_value(host);
+                       ios->drv_type = (preset & SDHCI_PRESET_DRV_MASK)
+                               >> SDHCI_PRESET_DRV_SHIFT;
+               }
+
                /* Re-enable SD Clock */
-               clock = host->clock;
-               host->clock = 0;
-               sdhci_set_clock(host, clock);
+               sdhci_update_clock(host);
        } else
                sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 
@@ -1608,141 +1674,91 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
        spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static int sdhci_do_3_3v_signal_voltage_switch(struct sdhci_host *host,
-                                               u16 ctrl)
+static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
+                                               struct mmc_ios *ios)
 {
+       u16 ctrl;
        int ret;
 
-       /* Set 1.8V Signal Enable in the Host Control2 register to 0 */
-       ctrl &= ~SDHCI_CTRL_VDD_180;
-       sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-
-       if (host->vqmmc) {
-               ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000);
-               if (ret) {
-                       pr_warning("%s: Switching to 3.3V signalling voltage "
-                                  " failed\n", mmc_hostname(host->mmc));
-                       return -EIO;
-               }
-       }
-       /* Wait for 5ms */
-       usleep_range(5000, 5500);
+       /*
+        * Signal Voltage Switching is only applicable for Host Controllers
+        * v3.00 and above.
+        */
+       if (host->version < SDHCI_SPEC_300)
+               return 0;
 
-       /* 3.3V regulator output should be stable within 5 ms */
        ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-       if (!(ctrl & SDHCI_CTRL_VDD_180))
-               return 0;
 
-       pr_warning("%s: 3.3V regulator output did not became stable\n",
-                  mmc_hostname(host->mmc));
+       switch (ios->signal_voltage) {
+       case MMC_SIGNAL_VOLTAGE_330:
+               /* Set 1.8V Signal Enable in the Host Control2 register to 0 */
+               ctrl &= ~SDHCI_CTRL_VDD_180;
+               sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
-       return -EIO;
-}
+               if (host->vqmmc) {
+                       ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000);
+                       if (ret) {
+                               pr_warning("%s: Switching to 3.3V signalling voltage "
+                                               " failed\n", mmc_hostname(host->mmc));
+                               return -EIO;
+                       }
+               }
+               /* Wait for 5ms */
+               usleep_range(5000, 5500);
 
-static int sdhci_do_1_8v_signal_voltage_switch(struct sdhci_host *host,
-                                               u16 ctrl)
-{
-       u8 pwr;
-       u16 clk;
-       u32 present_state;
-       int ret;
+               /* 3.3V regulator output should be stable within 5 ms */
+               ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+               if (!(ctrl & SDHCI_CTRL_VDD_180))
+                       return 0;
 
-       /* Stop SDCLK */
-       clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-       clk &= ~SDHCI_CLOCK_CARD_EN;
-       sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+               pr_warning("%s: 3.3V regulator output did not became stable\n",
+                               mmc_hostname(host->mmc));
+
+               return -EAGAIN;
+       case MMC_SIGNAL_VOLTAGE_180:
+               if (host->vqmmc) {
+                       ret = regulator_set_voltage(host->vqmmc,
+                                       1700000, 1950000);
+                       if (ret) {
+                               pr_warning("%s: Switching to 1.8V signalling voltage "
+                                               " failed\n", mmc_hostname(host->mmc));
+                               return -EIO;
+                       }
+               }
 
-       /* Check whether DAT[3:0] is 0000 */
-       present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
-       if (!((present_state & SDHCI_DATA_LVL_MASK) >>
-              SDHCI_DATA_LVL_SHIFT)) {
                /*
                 * Enable 1.8V Signal Enable in the Host Control2
                 * register
                 */
-               if (host->vqmmc)
-                       ret = regulator_set_voltage(host->vqmmc,
-                               1700000, 1950000);
-               else
-                       ret = 0;
+               ctrl |= SDHCI_CTRL_VDD_180;
+               sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
-               if (!ret) {
-                       ctrl |= SDHCI_CTRL_VDD_180;
-                       sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+               /* Wait for 5ms */
+               usleep_range(5000, 5500);
 
-                       /* Wait for 5ms */
-                       usleep_range(5000, 5500);
+               /* 1.8V regulator output should be stable within 5 ms */
+               ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+               if (ctrl & SDHCI_CTRL_VDD_180)
+                       return 0;
 
-                       ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-                       if (ctrl & SDHCI_CTRL_VDD_180) {
-                               /* Provide SDCLK again and wait for 1ms */
-                               clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-                               clk |= SDHCI_CLOCK_CARD_EN;
-                               sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-                               usleep_range(1000, 1500);
+               pr_warning("%s: 1.8V regulator output did not became stable\n",
+                               mmc_hostname(host->mmc));
 
-                               /*
-                                * If DAT[3:0] level is 1111b, then the card
-                                * was successfully switched to 1.8V signaling.
-                                */
-                               present_state = sdhci_readl(host,
-                                                       SDHCI_PRESENT_STATE);
-                               if ((present_state & SDHCI_DATA_LVL_MASK) ==
-                                    SDHCI_DATA_LVL_MASK)
-                                       return 0;
+               return -EAGAIN;
+       case MMC_SIGNAL_VOLTAGE_120:
+               if (host->vqmmc) {
+                       ret = regulator_set_voltage(host->vqmmc, 1100000, 1300000);
+                       if (ret) {
+                               pr_warning("%s: Switching to 1.2V signalling voltage "
+                                               " failed\n", mmc_hostname(host->mmc));
+                               return -EIO;
                        }
                }
-       }
-
-       /*
-        * If we are here, that means the switch to 1.8V signaling
-        * failed. We power cycle the card, and retry initialization
-        * sequence by setting S18R to 0.
-        */
-       pwr = sdhci_readb(host, SDHCI_POWER_CONTROL);
-       pwr &= ~SDHCI_POWER_ON;
-       sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
-       if (host->vmmc)
-               regulator_disable(host->vmmc);
-
-       /* Wait for 1ms as per the spec */
-       usleep_range(1000, 1500);
-       pwr |= SDHCI_POWER_ON;
-       sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
-       if (host->vmmc)
-               regulator_enable(host->vmmc);
-
-       pr_warning("%s: Switching to 1.8V signalling voltage failed, "
-                  "retrying with S18R set to 0\n", mmc_hostname(host->mmc));
-
-       return -EAGAIN;
-}
-
-static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
-                                               struct mmc_ios *ios)
-{
-       u16 ctrl;
-
-       /*
-        * Signal Voltage Switching is only applicable for Host Controllers
-        * v3.00 and above.
-        */
-       if (host->version < SDHCI_SPEC_300)
                return 0;
-
-       /*
-        * We first check whether the request is to set signalling voltage
-        * to 3.3V. If so, we change the voltage to 3.3V and return quickly.
-        */
-       ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-       if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330)
-               return sdhci_do_3_3v_signal_voltage_switch(host, ctrl);
-       else if (!(ctrl & SDHCI_CTRL_VDD_180) &&
-                       (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180))
-               return sdhci_do_1_8v_signal_voltage_switch(host, ctrl);
-       else
+       default:
                /* No signal voltage switch required */
                return 0;
+       }
 }
 
 static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
@@ -1759,6 +1775,19 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
        return err;
 }
 
+static int sdhci_card_busy(struct mmc_host *mmc)
+{
+       struct sdhci_host *host = mmc_priv(mmc);
+       u32 present_state;
+
+       sdhci_runtime_pm_get(host);
+       /* Check whether DAT[3:0] is 0000 */
+       present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
+       sdhci_runtime_pm_put(host);
+
+       return !(present_state & SDHCI_DATA_LVL_MASK);
+}
+
 static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
        struct sdhci_host *host;
@@ -1955,17 +1984,15 @@ out:
        return err;
 }
 
-static void sdhci_do_enable_preset_value(struct sdhci_host *host, bool enable)
+
+static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)
 {
        u16 ctrl;
-       unsigned long flags;
 
        /* Host Controller v3.00 defines preset value registers */
        if (host->version < SDHCI_SPEC_300)
                return;
 
-       spin_lock_irqsave(&host->lock, flags);
-
        ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 
        /*
@@ -1981,17 +2008,6 @@ static void sdhci_do_enable_preset_value(struct sdhci_host *host, bool enable)
                sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
                host->flags &= ~SDHCI_PV_ENABLED;
        }
-
-       spin_unlock_irqrestore(&host->lock, flags);
-}
-
-static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable)
-{
-       struct sdhci_host *host = mmc_priv(mmc);
-
-       sdhci_runtime_pm_get(host);
-       sdhci_do_enable_preset_value(host, enable);
-       sdhci_runtime_pm_put(host);
 }
 
 static void sdhci_card_event(struct mmc_host *mmc)
@@ -2027,8 +2043,8 @@ static const struct mmc_host_ops sdhci_ops = {
        .enable_sdio_irq = sdhci_enable_sdio_irq,
        .start_signal_voltage_switch    = sdhci_start_signal_voltage_switch,
        .execute_tuning                 = sdhci_execute_tuning,
-       .enable_preset_value            = sdhci_enable_preset_value,
        .card_event                     = sdhci_card_event,
+       .card_busy      = sdhci_card_busy,
 };
 
 /*****************************************************************************\
@@ -2080,14 +2096,9 @@ static void sdhci_tasklet_finish(unsigned long param)
                   (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) {
 
                /* Some controllers need this kick or reset won't work here */
-               if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) {
-                       unsigned int clock;
-
+               if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
                        /* This is to force an update */
-                       clock = host->clock;
-                       host->clock = 0;
-                       sdhci_set_clock(host, clock);
-               }
+                       sdhci_update_clock(host);
 
                /* Spec says we should do both at the same time, but Ricoh
                   controllers do not like that. */
@@ -2455,6 +2466,32 @@ out:
 \*****************************************************************************/
 
 #ifdef CONFIG_PM
+void sdhci_enable_irq_wakeups(struct sdhci_host *host)
+{
+       u8 val;
+       u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE
+                       | SDHCI_WAKE_ON_INT;
+
+       val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL);
+       val |= mask ;
+       /* Avoid fake wake up */
+       if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
+               val &= ~(SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE);
+       sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL);
+}
+EXPORT_SYMBOL_GPL(sdhci_enable_irq_wakeups);
+
+void sdhci_disable_irq_wakeups(struct sdhci_host *host)
+{
+       u8 val;
+       u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE
+                       | SDHCI_WAKE_ON_INT;
+
+       val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL);
+       val &= ~mask;
+       sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL);
+}
+EXPORT_SYMBOL_GPL(sdhci_disable_irq_wakeups);
 
 int sdhci_suspend_host(struct sdhci_host *host)
 {
@@ -2484,8 +2521,13 @@ int sdhci_suspend_host(struct sdhci_host *host)
                return ret;
        }
 
-       free_irq(host->irq, host);
-
+       if (!device_may_wakeup(mmc_dev(host->mmc))) {
+               sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
+               free_irq(host->irq, host);
+       } else {
+               sdhci_enable_irq_wakeups(host);
+               enable_irq_wake(host->irq);
+       }
        return ret;
 }
 
@@ -2500,10 +2542,15 @@ int sdhci_resume_host(struct sdhci_host *host)
                        host->ops->enable_dma(host);
        }
 
-       ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
-                         mmc_hostname(host->mmc), host);
-       if (ret)
-               return ret;
+       if (!device_may_wakeup(mmc_dev(host->mmc))) {
+               ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
+                                 mmc_hostname(host->mmc), host);
+               if (ret)
+                       return ret;
+       } else {
+               sdhci_disable_irq_wakeups(host);
+               disable_irq_wake(host->irq);
+       }
 
        if ((host->mmc->pm_flags & MMC_PM_KEEP_POWER) &&
            (host->quirks2 & SDHCI_QUIRK2_HOST_OFF_CARD_ON)) {
@@ -2531,17 +2578,6 @@ int sdhci_resume_host(struct sdhci_host *host)
 }
 
 EXPORT_SYMBOL_GPL(sdhci_resume_host);
-
-void sdhci_enable_irq_wakeups(struct sdhci_host *host)
-{
-       u8 val;
-       val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL);
-       val |= SDHCI_WAKE_ON_INT;
-       sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL);
-}
-
-EXPORT_SYMBOL_GPL(sdhci_enable_irq_wakeups);
-
 #endif /* CONFIG_PM */
 
 #ifdef CONFIG_PM_RUNTIME
@@ -2600,8 +2636,12 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
        sdhci_do_set_ios(host, &host->mmc->ios);
 
        sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios);
-       if (host_flags & SDHCI_PV_ENABLED)
-               sdhci_do_enable_preset_value(host, true);
+       if ((host_flags & SDHCI_PV_ENABLED) &&
+               !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) {
+               spin_lock_irqsave(&host->lock, flags);
+               sdhci_enable_preset_value(host, true);
+               spin_unlock_irqrestore(&host->lock, flags);
+       }
 
        /* Set the re-tuning expiration flag */
        if (host->flags & SDHCI_USING_RETUNING_TIMER)
@@ -2936,7 +2976,11 @@ int sdhci_add_host(struct sdhci_host *host)
        }
 
 #ifdef CONFIG_REGULATOR
-       if (host->vmmc) {
+       /*
+        * Voltage range check makes sense only if regulator reports
+        * any voltage value.
+        */
+       if (host->vmmc && regulator_get_voltage(host->vmmc) > 0) {
                ret = regulator_is_supported_voltage(host->vmmc, 2700000,
                        3600000);
                if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_330)))
@@ -3139,6 +3183,7 @@ int sdhci_add_host(struct sdhci_host *host)
 #ifdef SDHCI_USE_LEDS_CLASS
 reset:
        sdhci_reset(host, SDHCI_RESET_ALL);
+       sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
        free_irq(host->irq, host);
 #endif
 untasklet:
@@ -3181,6 +3226,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
        if (!dead)
                sdhci_reset(host, SDHCI_RESET_ALL);
 
+       sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
        free_irq(host->irq, host);
 
        del_timer_sync(&host->timer);