#include <linux/delay.h>
 #include <linux/capability.h>
 #include <linux/compat.h>
+#include <linux/pm_runtime.h>
 
 #include <linux/mmc/ioctl.h>
 #include <linux/mmc/card.h>
        md = mmc_blk_get(dev_to_disk(dev));
        card = md->queue.card;
 
-       mmc_claim_host(card->host);
+       mmc_get_card(card);
 
        ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
                                card->ext_csd.boot_ro_lock |
        else
                card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN;
 
-       mmc_release_host(card->host);
+       mmc_put_card(card);
 
        if (!ret) {
                pr_info("%s: Locking boot partition ro until next power on\n",
 
        mrq.cmd = &cmd;
 
-       mmc_claim_host(card->host);
+       mmc_get_card(card);
 
        err = mmc_blk_part_switch(card, md);
        if (err)
        }
 
 cmd_rel_host:
-       mmc_release_host(card->host);
+       mmc_put_card(card);
 
 cmd_done:
        mmc_blk_put(md);
 
        if (req && !mq->mqrq_prev->req)
                /* claim host only for the first request */
-               mmc_claim_host(card->host);
+               mmc_get_card(card);
 
        ret = mmc_blk_part_switch(card, md);
        if (ret) {
                 * In case sepecial request, there is no reentry to
                 * the 'mmc_blk_issue_rq' with 'mqrq_prev->req'.
                 */
-               mmc_release_host(card->host);
+               mmc_put_card(card);
        return ret;
 }
 
                if (mmc_add_disk(part_md))
                        goto out;
        }
+
+       pm_runtime_set_autosuspend_delay(&card->dev, 3000);
+       pm_runtime_use_autosuspend(&card->dev);
+
+       /*
+        * Don't enable runtime PM for SD-combo cards here. Leave that
+        * decision to be taken during the SDIO init sequence instead.
+        */
+       if (card->type != MMC_TYPE_SD_COMBO) {
+               pm_runtime_set_active(&card->dev);
+               pm_runtime_enable(&card->dev);
+       }
+
        return 0;
 
  out:
        struct mmc_blk_data *md = mmc_get_drvdata(card);
 
        mmc_blk_remove_parts(card, md);
+       pm_runtime_get_sync(&card->dev);
        mmc_claim_host(card->host);
        mmc_blk_part_switch(card, md);
        mmc_release_host(card->host);
+       if (card->type != MMC_TYPE_SD_COMBO)
+               pm_runtime_disable(&card->dev);
+       pm_runtime_put_noidle(&card->dev);
        mmc_blk_remove_req(md);
        mmc_set_drvdata(card, NULL);
 }
        struct mmc_blk_data *md = mmc_get_drvdata(card);
 
        if (md) {
+               pm_runtime_get_sync(&card->dev);
                mmc_queue_suspend(&md->queue);
                list_for_each_entry(part_md, &md->part, part) {
                        mmc_queue_suspend(&part_md->queue);
                list_for_each_entry(part_md, &md->part, part) {
                        mmc_queue_resume(&part_md->queue);
                }
+               pm_runtime_put(&card->dev);
        }
        return 0;
 }
 
 }
 EXPORT_SYMBOL(mmc_release_host);
 
+/*
+ * This is a helper function, which fetches a runtime pm reference for the
+ * card device and also claims the host.
+ */
+void mmc_get_card(struct mmc_card *card)
+{
+       pm_runtime_get_sync(&card->dev);
+       mmc_claim_host(card->host);
+}
+EXPORT_SYMBOL(mmc_get_card);
+
+/*
+ * This is a helper function, which releases the host and drops the runtime
+ * pm reference for the card device.
+ */
+void mmc_put_card(struct mmc_card *card)
+{
+       mmc_release_host(card->host);
+       pm_runtime_mark_last_busy(&card->dev);
+       pm_runtime_put_autosuspend(&card->dev);
+}
+EXPORT_SYMBOL(mmc_put_card);
+
 /*
  * Internal function that does the actual ios call to the host driver,
  * optionally printing some debug output.