mmc: host: loglevel of a message to KERN_INFO
[linux-2.6.git] / drivers / mmc / host / sdhci-tegra.c
index 344f9af..d6ed03d 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/sd.h>
 #include <linux/regulator/consumer.h>
 #include <linux/delay.h>
 
 #define SDHCI_VENDOR_CLOCK_CNTRL       0x100
 #define SDHCI_VENDOR_CLOCK_CNTRL_SDMMC_CLK     0x1
 #define SDHCI_VENDOR_CLOCK_CNTRL_PADPIPE_CLKEN_OVERRIDE        0x8
+#define SDHCI_VENDOR_CLOCK_CNTRL_SPI_MODE_CLKEN_OVERRIDE       0x4
 #define SDHCI_VENDOR_CLOCK_CNTRL_BASE_CLK_FREQ_SHIFT   8
 #define SDHCI_VENDOR_CLOCK_CNTRL_TAP_VALUE_SHIFT       16
+#define SDHCI_VENDOR_CLOCK_CNTRL_SDR50_TUNING          0x20
 
 #define SDHCI_VENDOR_MISC_CNTRL                0x120
 #define SDHCI_VENDOR_MISC_CNTRL_ENABLE_SDR104_SUPPORT  0x8
 #define SDHCI_VENDOR_MISC_CNTRL_ENABLE_SDR50_SUPPORT   0x10
 #define SDHCI_VENDOR_MISC_CNTRL_ENABLE_SD_3_0  0x20
 
+#define SDMMC_SDMEMCOMPPADCTRL 0x1E0
+#define SDMMC_SDMEMCOMPPADCTRL_VREF_SEL_MASK   0xF
+
 #define SDMMC_AUTO_CAL_CONFIG  0x1E4
 #define SDMMC_AUTO_CAL_CONFIG_AUTO_CAL_ENABLE  0x20000000
 #define SDMMC_AUTO_CAL_CONFIG_AUTO_CAL_PD_OFFSET_SHIFT 0x8
 #define TEGRA2_SDHOST_STD_FREQ 50000000
 #define TEGRA3_SDHOST_STD_FREQ 104000000
 
+#define SD_SEND_TUNING_PATTERN 19
+#define MAX_TAP_VALUES 256
+
 static unsigned int tegra_sdhost_min_freq;
 static unsigned int tegra_sdhost_std_freq;
+
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
 static void tegra_3x_sdhci_set_card_clock(struct sdhci_host *sdhci, unsigned int clock);
 static void tegra3_sdhci_post_reset_init(struct sdhci_host *sdhci);
 
 static unsigned int tegra3_sdhost_max_clk[4] = {
        208000000,      104000000,      208000000,      104000000 };
+#endif
 
 struct tegra_sdhci_hw_ops{
        /* Set the internal clk and card clk.*/
@@ -153,6 +165,14 @@ static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg)
 #endif
 }
 
+static unsigned int tegra_sdhci_get_cd(struct sdhci_host *sdhci)
+{
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
+       struct tegra_sdhci_host *tegra_host = pltfm_host->priv;
+
+       return tegra_host->card_present;
+}
+
 static unsigned int tegra_sdhci_get_ro(struct sdhci_host *sdhci)
 {
        struct platform_device *pdev = to_platform_device(mmc_dev(sdhci->mmc));
@@ -166,6 +186,7 @@ static unsigned int tegra_sdhci_get_ro(struct sdhci_host *sdhci)
        return gpio_get_value(plat->wp_gpio);
 }
 
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
 static void tegra3_sdhci_post_reset_init(struct sdhci_host *sdhci)
 {
        u16 misc_ctrl;
@@ -182,6 +203,8 @@ static void tegra3_sdhci_post_reset_init(struct sdhci_host *sdhci)
        vendor_ctrl |= (tegra3_sdhost_max_clk[tegra_host->instance] / 1000000) <<
                SDHCI_VENDOR_CLOCK_CNTRL_BASE_CLK_FREQ_SHIFT;
        vendor_ctrl |= SDHCI_VENDOR_CLOCK_CNTRL_PADPIPE_CLKEN_OVERRIDE;
+       vendor_ctrl &= ~SDHCI_VENDOR_CLOCK_CNTRL_SPI_MODE_CLKEN_OVERRIDE;
+
        /* Set tap delay */
        if (plat->tap_delay) {
                vendor_ctrl &= ~(0xFF <<
@@ -189,6 +212,8 @@ static void tegra3_sdhci_post_reset_init(struct sdhci_host *sdhci)
                vendor_ctrl |= (plat->tap_delay <<
                        SDHCI_VENDOR_CLOCK_CNTRL_TAP_VALUE_SHIFT);
        }
+       /* Enable frequency tuning for SDR50 mode */
+       vendor_ctrl |= SDHCI_VENDOR_CLOCK_CNTRL_SDR50_TUNING;
        sdhci_writel(sdhci, vendor_ctrl, SDHCI_VENDOR_CLOCK_CNTRL);
 
        /* Enable SDHOST v3.0 support */
@@ -198,6 +223,7 @@ static void tegra3_sdhci_post_reset_init(struct sdhci_host *sdhci)
                SDHCI_VENDOR_MISC_CNTRL_ENABLE_SDR50_SUPPORT;
        sdhci_writew(sdhci, misc_ctrl, SDHCI_VENDOR_MISC_CNTRL);
 }
+#endif
 
 static int tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
                unsigned int uhs)
@@ -355,6 +381,15 @@ static void tegra_sdhci_set_clk_rate(struct sdhci_host *sdhci,
                        clk_rate = tegra_sdhost_std_freq;
                else
                        clk_rate = clock;
+
+               /*
+                * In SDR50 mode, run the sdmmc controller at 208MHz to ensure
+                * the core voltage is at 1.2V. If the core voltage is below 1.2V, CRC
+                * errors would occur during data transfers.
+                */
+               if ((sdhci->mmc->ios.timing == MMC_TIMING_UHS_SDR50) &&
+                       (clk_rate == tegra_sdhost_std_freq))
+                       clk_rate <<= 1;
        }
 
        if (tegra_host->max_clk_limit &&
@@ -365,6 +400,7 @@ static void tegra_sdhci_set_clk_rate(struct sdhci_host *sdhci,
        sdhci->max_clk = clk_get_rate(pltfm_host->clk);
 }
 
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
 static void tegra_3x_sdhci_set_card_clock(struct sdhci_host *sdhci, unsigned int clock)
 {
        int div;
@@ -375,6 +411,13 @@ static void tegra_3x_sdhci_set_card_clock(struct sdhci_host *sdhci, unsigned int
        if (clock && clock == sdhci->clock)
                return;
 
+       /*
+        * Disable the card clock before disabling the internal
+        * clock to avoid abnormal clock waveforms.
+        */
+       clk = sdhci_readw(sdhci, SDHCI_CLOCK_CONTROL);
+       clk &= ~SDHCI_CLOCK_CARD_EN;
+       sdhci_writew(sdhci, clk, SDHCI_CLOCK_CONTROL);
        sdhci_writew(sdhci, 0, SDHCI_CLOCK_CONTROL);
 
        if (clock == 0)
@@ -442,6 +485,7 @@ set_clk:
 out:
        sdhci->clock = clock;
 }
+#endif
 
 static void tegra_sdhci_set_clock(struct sdhci_host *sdhci, unsigned int clock)
 {
@@ -486,7 +530,7 @@ static int tegra_sdhci_signal_voltage_switch(struct sdhci_host *sdhci,
        struct tegra_sdhci_host *tegra_host = pltfm_host->priv;
        unsigned int min_uV = SDHOST_HIGH_VOLT_MIN;
        unsigned int max_uV = SDHOST_HIGH_VOLT_MAX;
-       unsigned int rc;
+       unsigned int rc = 0;
        u16 clk, ctrl;
        unsigned int val;
 
@@ -516,7 +560,7 @@ static int tegra_sdhci_signal_voltage_switch(struct sdhci_host *sdhci,
                        regulator_set_voltage(tegra_host->vdd_io_reg,
                                SDHOST_HIGH_VOLT_MIN,
                                SDHOST_HIGH_VOLT_MAX);
-                       return rc;
+                       goto out;
                }
        }
 
@@ -543,9 +587,247 @@ static int tegra_sdhci_signal_voltage_switch(struct sdhci_host *sdhci,
                val &= ~0x7F;
                val |= SDMMC_AUTO_CAL_CONFIG_AUTO_CAL_PU_OFFSET;
                sdhci_writel(sdhci, val, SDMMC_AUTO_CAL_CONFIG);
+
+               val = sdhci_readl(sdhci, SDMMC_SDMEMCOMPPADCTRL);
+               val &= ~SDMMC_SDMEMCOMPPADCTRL_VREF_SEL_MASK;
+               val |= 0x7;
+               sdhci_writel(sdhci, val, SDMMC_SDMEMCOMPPADCTRL);
        }
 
-       return 0;
+       return rc;
+out:
+       /* Enable the card clock */
+       clk |= SDHCI_CLOCK_CARD_EN;
+       sdhci_writew(sdhci, clk, SDHCI_CLOCK_CONTROL);
+
+       /* Wait for 1 msec for the clock to stabilize */
+       mdelay(1);
+
+       return rc;
+}
+
+static void tegra_sdhci_reset(struct sdhci_host *sdhci, u8 mask)
+{
+       unsigned long timeout;
+
+       sdhci_writeb(sdhci, mask, SDHCI_SOFTWARE_RESET);
+
+       /* Wait max 100 ms */
+       timeout = 100;
+
+       /* hw clears the bit when it's done */
+       while (sdhci_readb(sdhci, SDHCI_SOFTWARE_RESET) & mask) {
+               if (timeout == 0) {
+                       dev_err(mmc_dev(sdhci->mmc), "Reset 0x%x never"
+                               "completed.\n", (int)mask);
+                       return;
+               }
+               timeout--;
+               mdelay(1);
+       }
+}
+
+static void sdhci_tegra_set_tap_delay(struct sdhci_host *sdhci,
+       unsigned int tap_delay)
+{
+       u32 vendor_ctrl;
+
+       /* Max tap delay value is 255 */
+       BUG_ON(tap_delay > MAX_TAP_VALUES);
+
+       vendor_ctrl = sdhci_readl(sdhci, SDHCI_VENDOR_CLOCK_CNTRL);
+       vendor_ctrl &= ~(0xFF << SDHCI_VENDOR_CLOCK_CNTRL_TAP_VALUE_SHIFT);
+       vendor_ctrl |= (tap_delay << SDHCI_VENDOR_CLOCK_CNTRL_TAP_VALUE_SHIFT);
+       sdhci_writel(sdhci, vendor_ctrl, SDHCI_VENDOR_CLOCK_CNTRL);
+}
+
+static void sdhci_tegra_clear_set_irqs(struct sdhci_host *host,
+       u32 clear, u32 set)
+{
+       u32 ier;
+
+       ier = sdhci_readl(host, SDHCI_INT_ENABLE);
+       ier &= ~clear;
+       ier |= set;
+       sdhci_writel(host, ier, SDHCI_INT_ENABLE);
+       sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);
+}
+
+static int sdhci_tegra_run_frequency_tuning(struct sdhci_host *sdhci)
+{
+       int err = 0;
+       u8 ctrl;
+       u32 ier;
+       u32 mask;
+       unsigned int timeout = 10;
+       int flags;
+       u32 intstatus;
+
+       /*
+        * As per the Host Controller spec v3.00, tuning command
+        * generates Buffer Read Ready interrupt only, so enable that.
+        */
+       ier = sdhci_readl(sdhci, SDHCI_INT_ENABLE);
+       sdhci_tegra_clear_set_irqs(sdhci, ier, SDHCI_INT_DATA_AVAIL |
+               SDHCI_INT_DATA_CRC);
+
+       mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT;
+       while (sdhci_readl(sdhci, SDHCI_PRESENT_STATE) & mask) {
+               if (timeout == 0) {
+                       dev_err(mmc_dev(sdhci->mmc), "Controller never"
+                               "released inhibit bit(s).\n");
+                       err = -ETIMEDOUT;
+                       goto out;
+               }
+               timeout--;
+               mdelay(1);
+       }
+
+       ctrl = sdhci_readb(sdhci, SDHCI_HOST_CONTROL2);
+       ctrl &= ~SDHCI_CTRL_TUNED_CLK;
+       sdhci_writeb(sdhci, ctrl, SDHCI_HOST_CONTROL2);
+
+       ctrl = sdhci_readb(sdhci, SDHCI_HOST_CONTROL2);
+       ctrl |= SDHCI_CTRL_EXEC_TUNING;
+       sdhci_writeb(sdhci, ctrl, SDHCI_HOST_CONTROL2);
+
+       /*
+        * In response to CMD19, the card sends 64 bytes of tuning
+        * block to the Host Controller. So we set the block size
+        * to 64 here.
+        */
+       sdhci_writew(sdhci, SDHCI_MAKE_BLKSZ(7, 64), SDHCI_BLOCK_SIZE);
+
+       sdhci_writeb(sdhci, 0xE, SDHCI_TIMEOUT_CONTROL);
+
+       sdhci_writeb(sdhci, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
+
+       sdhci_writel(sdhci, 0x0, SDHCI_ARGUMENT);
+
+       /* Set the cmd flags */
+       flags = SDHCI_CMD_RESP_SHORT | SDHCI_CMD_CRC | SDHCI_CMD_DATA;
+       /* Issue the command */
+       sdhci_writew(sdhci, SDHCI_MAKE_CMD(
+               SD_SEND_TUNING_PATTERN, flags), SDHCI_COMMAND);
+
+       timeout = 5;
+       do {
+               timeout--;
+               mdelay(1);
+               intstatus = sdhci_readl(sdhci, SDHCI_INT_STATUS);
+               if (intstatus) {
+                       sdhci_writel(sdhci, intstatus, SDHCI_INT_STATUS);
+                       break;
+               }
+       } while(timeout);
+
+       if ((intstatus & SDHCI_INT_DATA_AVAIL) &&
+               !(intstatus & SDHCI_INT_DATA_CRC)) {
+               err = 0;
+               sdhci->tuning_done = 1;
+       } else {
+               tegra_sdhci_reset(sdhci, SDHCI_RESET_CMD);
+               tegra_sdhci_reset(sdhci, SDHCI_RESET_DATA);
+               err = -EIO;
+       }
+
+       if (sdhci->tuning_done) {
+               sdhci->tuning_done = 0;
+               ctrl = sdhci_readb(sdhci, SDHCI_HOST_CONTROL2);
+               if (!(ctrl & SDHCI_CTRL_EXEC_TUNING) &&
+                       (ctrl & SDHCI_CTRL_TUNED_CLK))
+                       err = 0;
+               else
+                       err = -EIO;
+       }
+       mdelay(1);
+out:
+       sdhci_tegra_clear_set_irqs(sdhci, SDHCI_INT_DATA_AVAIL, ier);
+       return err;
+}
+
+static int sdhci_tegra_execute_tuning(struct sdhci_host *sdhci)
+{
+       int err;
+       u16 ctrl_2;
+       u8 *tap_delay_status;
+       unsigned int i = 0;
+       unsigned int temp_low_pass_tap = 0;
+       unsigned int temp_pass_window = 0;
+       unsigned int best_low_pass_tap = 0;
+       unsigned int best_pass_window = 0;
+
+       /* Tuning is valid only in SDR104 and SDR50 modes */
+       ctrl_2 = sdhci_readw(sdhci, SDHCI_HOST_CONTROL2);
+       if (!(((ctrl_2 & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) ||
+               (((ctrl_2 & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) &&
+               (sdhci->flags & SDHCI_SDR50_NEEDS_TUNING))))
+                       return 0;
+
+       tap_delay_status = kzalloc(MAX_TAP_VALUES, GFP_KERNEL);
+       if (tap_delay_status == NULL) {
+               dev_err(mmc_dev(sdhci->mmc), "failed to allocate memory"
+                       "for storing tap_delay_status\n");
+               err = -ENOMEM;
+               goto out;
+       }
+
+       /*
+        * Set each tap delay value and run frequency tuning. After each
+        * run, update the tap delay status as working or not working.
+        */
+       do {
+               /* Set the tap delay */
+               sdhci_tegra_set_tap_delay(sdhci, i);
+
+               /* Run frequency tuning */
+               err = sdhci_tegra_run_frequency_tuning(sdhci);
+
+               /* Update whether the tap delay worked or not */
+               tap_delay_status[i] = (err) ? 0: 1;
+               i++;
+       } while (i < 0xFF);
+
+       /* Find the best possible tap range */
+       for (i = 0; i < 0xFF; i++) {
+               temp_pass_window = 0;
+
+               /* Find the first passing tap in the current window */
+               if (tap_delay_status[i]) {
+                       temp_low_pass_tap = i;
+
+                       /* Find the pass window */
+                       do {
+                               temp_pass_window++;
+                               i++;
+                               if (i > 0xFF)
+                                       break;
+                       } while (tap_delay_status[i]);
+
+                       if ((temp_pass_window > best_pass_window) && (temp_pass_window > 1)){
+                               best_low_pass_tap = temp_low_pass_tap;
+                               best_pass_window = temp_pass_window;
+                       }
+               }
+       }
+
+
+       pr_debug("%s: best pass tap window: start %d, end %d\n",
+               mmc_hostname(sdhci->mmc), best_low_pass_tap,
+               (best_low_pass_tap + best_pass_window));
+
+       /* Set the best tap */
+       sdhci_tegra_set_tap_delay(sdhci,
+               (best_low_pass_tap + ((best_pass_window * 3) / 4)));
+
+       /* Run frequency tuning */
+       err = sdhci_tegra_run_frequency_tuning(sdhci);
+
+out:
+       if (tap_delay_status)
+               kfree(tap_delay_status);
+
+       return err;
 }
 
 static int tegra_sdhci_suspend(struct sdhci_host *sdhci, pm_message_t state)
@@ -573,7 +855,6 @@ static int tegra_sdhci_resume(struct sdhci_host *sdhci)
 {
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
        struct tegra_sdhci_host *tegra_host = pltfm_host->priv;
-       unsigned long timeout;
 
        /* Enable the power rails if any */
        if (tegra_host->card_present) {
@@ -587,28 +868,12 @@ static int tegra_sdhci_resume(struct sdhci_host *sdhci)
                        tegra_host->is_rail_enabled = 1;
                }
        }
-
        /* Setting the min identification clock of freq 400KHz */
        tegra_sdhci_set_clock(sdhci, 400000);
 
        /* Reset the controller and power on if MMC_KEEP_POWER flag is set*/
        if (sdhci->mmc->pm_flags & MMC_PM_KEEP_POWER) {
-               sdhci_writeb(sdhci, SDHCI_RESET_ALL, SDHCI_SOFTWARE_RESET);
-
-               /* Wait max 100 ms */
-               timeout = 100;
-
-               /* hw clears the bit when it's done */
-               while (sdhci_readb(sdhci, SDHCI_SOFTWARE_RESET) & SDHCI_RESET_ALL) {
-                       if (timeout == 0) {
-                               printk(KERN_ERR "%s: Reset 0x%x never completed.\n",
-                                       mmc_hostname(sdhci->mmc), (int)SDHCI_RESET_ALL);
-                               return -ETIMEDOUT;
-                       }
-                       timeout--;
-                       mdelay(1);
-               }
-
+               tegra_sdhci_reset(sdhci, SDHCI_RESET_ALL);
                sdhci_writeb(sdhci, SDHCI_POWER_ON, SDHCI_POWER_CONTROL);
                sdhci->pwr = 0;
        }
@@ -618,16 +883,21 @@ static int tegra_sdhci_resume(struct sdhci_host *sdhci)
 
 static struct sdhci_ops tegra_sdhci_ops = {
        .get_ro     = tegra_sdhci_get_ro,
+       .get_cd     = tegra_sdhci_get_cd,
        .read_l     = tegra_sdhci_readl,
        .read_w     = tegra_sdhci_readw,
        .write_l    = tegra_sdhci_writel,
        .platform_8bit_width = tegra_sdhci_8bit,
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+       .set_card_clock = tegra_3x_sdhci_set_card_clock,
+#endif
        .set_clock  = tegra_sdhci_set_clock,
        .suspend    = tegra_sdhci_suspend,
        .resume     = tegra_sdhci_resume,
        .platform_reset_exit = tegra_sdhci_reset_exit,
        .set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
        .switch_signal_voltage = tegra_sdhci_signal_voltage_switch,
+       .execute_freq_tuning = sdhci_tegra_execute_tuning,
 };
 
 static struct sdhci_pltfm_data sdhci_tegra_pdata = {
@@ -638,11 +908,13 @@ static struct sdhci_pltfm_data sdhci_tegra_pdata = {
 #endif
 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
                  SDHCI_QUIRK_NONSTANDARD_CLOCK |
+                 SDHCI_QUIRK_NON_STANDARD_TUNING |
 #endif
                  SDHCI_QUIRK_SINGLE_POWER_WRITE |
                  SDHCI_QUIRK_NO_HISPD_BIT |
                  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
-                 SDHCI_QUIRK_NO_CALC_MAX_DISCARD_TO,
+                 SDHCI_QUIRK_NO_CALC_MAX_DISCARD_TO |
+                 SDHCI_QUIRK_BROKEN_CARD_DETECTION,
        .ops  = &tegra_sdhci_ops,
 };
 
@@ -742,6 +1014,12 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
                gpio_direction_input(plat->wp_gpio);
        }
 
+       /*
+        * If there is no card detect gpio, assume that the
+        * card is always present.
+        */
+       if (!gpio_is_valid(plat->cd_gpio))
+               tegra_host->card_present = 1;
 
        if (!plat->mmc_data.built_in) {
                if (plat->mmc_data.ocr_mask & SDHOST_1V8_OCR_MASK) {
@@ -757,8 +1035,9 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
                }
                tegra_host->vdd_io_reg = regulator_get(mmc_dev(host->mmc), "vddio_sdmmc");
                if (IS_ERR_OR_NULL(tegra_host->vdd_io_reg)) {
-                       dev_err(mmc_dev(host->mmc), "%s regulator not found: %ld\n",
-                               "vddio_sdmmc", PTR_ERR(tegra_host->vdd_io_reg));
+                       dev_info(mmc_dev(host->mmc), "%s regulator not found: %ld."
+                               "Assuming vddio_sdmmc is not required.\n",
+                                       "vddio_sdmmc", PTR_ERR(tegra_host->vdd_io_reg));
                        tegra_host->vdd_io_reg = NULL;
                } else {
                        rc = regulator_set_voltage(tegra_host->vdd_io_reg,
@@ -772,17 +1051,18 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
 
                tegra_host->vdd_slot_reg = regulator_get(mmc_dev(host->mmc), "vddio_sd_slot");
                if (IS_ERR_OR_NULL(tegra_host->vdd_slot_reg)) {
-                       dev_err(mmc_dev(host->mmc), "%s regulator not found: %ld\n",
-                               "vddio_sd_slot", PTR_ERR(tegra_host->vdd_slot_reg));
+                       dev_info(mmc_dev(host->mmc), "%s regulator not found: %ld."
+                               " Assuming vddio_sd_slot is not required.\n",
+                                       "vddio_sd_slot", PTR_ERR(tegra_host->vdd_slot_reg));
                        tegra_host->vdd_slot_reg = NULL;
-               } else {
-                       if (tegra_host->card_present) {
-                               if (tegra_host->vdd_slot_reg)
-                                       regulator_enable(tegra_host->vdd_slot_reg);
-                               if (tegra_host->vdd_io_reg)
-                                       regulator_enable(tegra_host->vdd_io_reg);
-                               tegra_host->is_rail_enabled = 1;
-                       }
+               }
+
+               if (tegra_host->card_present) {
+                       if (tegra_host->vdd_slot_reg)
+                               regulator_enable(tegra_host->vdd_slot_reg);
+                       if (tegra_host->vdd_io_reg)
+                               regulator_enable(tegra_host->vdd_io_reg);
+                       tegra_host->is_rail_enabled = 1;
                }
        }
 
@@ -802,7 +1082,8 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
        tegra_host->instance = pdev->id;
        tegra_host->dpd = tegra_io_dpd_get(mmc_dev(host->mmc));
 
-       host->mmc->pm_caps = plat->pm_flags;
+       host->mmc->pm_caps |= plat->pm_caps;
+       host->mmc->pm_flags |= plat->pm_flags;
 
        host->mmc->caps |= MMC_CAP_ERASE;
        host->mmc->caps |= MMC_CAP_DISABLE;
@@ -815,11 +1096,13 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
        host->mmc->pm_caps |= MMC_PM_KEEP_POWER | MMC_PM_IGNORE_PM_NOTIFY;
        if (plat->mmc_data.built_in) {
                host->mmc->caps |= MMC_CAP_NONREMOVABLE;
-               host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY;
        }
+       host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY;
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
        /* Do not turn OFF embedded sdio cards as it support Wake on Wireless */
        if (plat->mmc_data.embedded_sdio)
                host->mmc->pm_flags |= MMC_PM_KEEP_POWER;
+#endif
 
        tegra_sdhost_min_freq = TEGRA_SDHOST_MIN_FREQ;
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC