diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 68f5f4b..79ced36 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1564,9 +1564,9 @@ void mmc_power_up(struct mmc_host *host, u32 ocr)
 	mmc_host_clk_release(host);
 }
 
-void mmc_power_off(struct mmc_host *host)
+void _mmc_power_off(struct mmc_host *host, unsigned char power_mode)
 {
-	if (host->ios.power_mode == MMC_POWER_OFF)
+	if (host->ios.power_mode == power_mode)
 		return;
 
 	mmc_host_clk_hold(host);
@@ -1579,6 +1579,7 @@ void mmc_power_off(struct mmc_host *host)
 		host->ios.chip_select = MMC_CS_DONTCARE;
 	}
 	host->ios.power_mode = MMC_POWER_OFF;
+	host->ios.power_mode = power_mode;
 	host->ios.bus_width = MMC_BUS_WIDTH_1;
 	host->ios.timing = MMC_TIMING_LEGACY;
 	mmc_set_ios(host);
@@ -1593,9 +1594,20 @@ void mmc_power_off(struct mmc_host *host)
 	mmc_host_clk_release(host);
 }
 
+void mmc_power_off(struct mmc_host *host)
+{
+	_mmc_power_off(host, MMC_POWER_OFF);
+}
+
 void mmc_power_cycle(struct mmc_host *host, u32 ocr)
 {
 	mmc_power_off(host);
+	/* If host normally ignores MMC_POWER_OFF, tell it to pay attention */
+	if (host->caps2 & MMC_CAP2_CD_NEEDS_POWER)
+		_mmc_power_off(host, MMC_POWER_OFF_HARD);
+	else
+		_mmc_power_off(host, MMC_POWER_OFF);
+
 	/* Wait at least 1 ms according to SD spec */
 	mmc_delay(1);
 	mmc_power_up(host, ocr);
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 91eb162..3d9c5a3 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -108,6 +108,9 @@ static int mmc_ios_show(struct seq_file *s, void *data)
 	case MMC_POWER_ON:
 		str = "on";
 		break;
+	case MMC_POWER_OFF_HARD:
+		str = "hard off";
+		break;
 	default:
 		str = "invalid";
 		break;
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
index 0fbc53a..4e26049 100644
--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -17,6 +17,7 @@
 #include <linux/mmc/mmc.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
+#include <linux/mmc/slot-gpio.h>
 #include <linux/slab.h>
 
 #include "dw_mmc.h"
@@ -217,6 +218,16 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
 	}
 }
 
+static void dw_mci_exynos_post_init(struct dw_mci_slot *slot)
+{
+	struct dw_mci_board *brd = slot->host->pdata;
+	struct mmc_host *mmc = slot->mmc;
+
+	if (!(brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) &&
+			IS_ERR_VALUE(mmc_gpio_get_cd(mmc)))
+		mmc->caps2 |= MMC_CAP2_CD_NEEDS_POWER;
+}
+
 static int dw_mci_exynos_parse_dt(struct dw_mci *host)
 {
 	struct dw_mci_exynos_priv_data *priv;
@@ -399,6 +410,7 @@ static const struct dw_mci_drv_data exynos_drv_data = {
 	.prepare_command	= dw_mci_exynos_prepare_command,
 	.set_ios		= dw_mci_exynos_set_ios,
 	.parse_dt		= dw_mci_exynos_parse_dt,
+	.post_init		= dw_mci_exynos_post_init,
 	.execute_tuning		= dw_mci_exynos_execute_tuning,
 };
 
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index f20b4b8..6f2c681 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -972,6 +972,22 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 	spin_unlock_bh(&host->lock);
 }
 
+/*
+ * some of the boards use controller CD line for card detection.Unfortunately
+ * CD line is bind to the same volatge domain as of the IO lines.If we turn off
+ * IO voltage domain, CD line wont work.
+ * Return true when controller CD line is used for card detection or return
+ * false.
+ */
+static bool dw_mci_builtin_cd(struct dw_mci_slot *slot)
+{
+	struct dw_mci_board *brd = slot->host->pdata;
+	struct mmc_host *mmc = slot->mmc;
+
+	return	(!(brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) &&
+			IS_ERR_VALUE(mmc_gpio_get_cd(mmc))) ? 1 : 0;
+}
+
 static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct dw_mci_slot *slot = mmc_priv(mmc);
@@ -1043,6 +1059,10 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		mci_writel(slot->host, PWREN, regs);
 		break;
 	case MMC_POWER_OFF:
+		if (dw_mci_builtin_cd(slot) &&
+				!test_bit(DW_MMC_CARD_PRESENT, &slot->flags))
+			return;
+
 		if (!IS_ERR(mmc->supply.vmmc))
 			mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
 
@@ -1055,6 +1075,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		regs &= ~(1 << slot->id);
 		mci_writel(slot->host, PWREN, regs);
 		break;
+	case MMC_POWER_OFF_HARD:
+		break;
 	default:
 		break;
 	}
@@ -2310,6 +2332,9 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 	else
 		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 
+	if (drv_data && drv_data->post_init)
+		drv_data->post_init(slot);
+
 	ret = mmc_add_host(mmc);
 	if (ret)
 		goto err_setup_bus;
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 01b99e8..a3c2628 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -250,6 +250,7 @@ struct dw_mci_tuning_data {
  * @prepare_command: handle CMD register extensions.
  * @set_ios: handle bus specific extensions.
  * @parse_dt: parse implementation specific device tree properties.
+ * @post_init: implementation specific post initialization.
  * @execute_tuning: implementation specific tuning procedure.
  *
  * Provide controller implementation specific extensions. The usage of this
@@ -263,6 +264,7 @@ struct dw_mci_drv_data {
 	void		(*prepare_command)(struct dw_mci *host, u32 *cmdr);
 	void		(*set_ios)(struct dw_mci *host, struct mmc_ios *ios);
 	int		(*parse_dt)(struct dw_mci *host);
+	void		(*post_init)(struct dw_mci_slot *slot);
 	int		(*execute_tuning)(struct dw_mci_slot *slot, u32 opcode,
 					struct dw_mci_tuning_data *tuning_data);
 };
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 4cbf614..5eb24ff 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -42,6 +42,7 @@ struct mmc_ios {
 #define MMC_POWER_OFF		0
 #define MMC_POWER_UP		1
 #define MMC_POWER_ON		2
+#define MMC_POWER_OFF_HARD	3
 
 	unsigned char	bus_width;		/* data bus width */
 
@@ -283,6 +284,7 @@ struct mmc_host {
 #define MMC_CAP2_HS400		(MMC_CAP2_HS400_1_8V | \
 				 MMC_CAP2_HS400_1_2V)
 #define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17)
+#define MMC_CAP2_CD_NEEDS_POWER (1 << 18)	/* Card detect needs power */
 
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
 
