sdhci: tegra: Enable power rails for ext sd card
Pavan Kunapuli [Thu, 15 Sep 2011 09:46:12 +0000 (14:46 +0530)]
Enable the vdd_io and vdd_slot power rails for
removable devices.

Bug 873188

Change-Id: Ib759e381cbca226069d1a9941a20b4bfcdb2ae3f
Reviewed-on: http://git-master/r/52588
Tested-by: Pavan Kunapuli <pkunapuli@nvidia.com>
Reviewed-by: Dan Willemsen <dwillemsen@nvidia.com>

Rebase-Id: Ra8732bb0b01fd8415b75ca7965e8a8451f278001

drivers/mmc/host/sdhci-tegra.c

index d5bb5a9..d6fae9f 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
+#include <linux/regulator/consumer.h>
 
 #include <mach/gpio.h>
 #include <mach/sdhci.h>
@@ -31,6 +32,8 @@
 
 struct tegra_sdhci_host {
        bool    clk_enabled;
+       struct regulator *vdd_io_reg;
+       struct regulator *vdd_slot_reg;
 };
 
 static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg)
@@ -303,6 +306,33 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
                gpio_direction_input(plat->wp_gpio);
        }
 
+       if (!plat->mmc_data.built_in) {
+               tegra_host->vdd_io_reg = regulator_get(mmc_dev(host->mmc), "vddio_sdmmc");
+               if (WARN_ON(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));
+                       tegra_host->vdd_io_reg = NULL;
+               } else {
+                       rc = regulator_set_voltage(tegra_host->vdd_io_reg,
+                               3280000, 3320000);
+                       if (rc) {
+                               dev_err(mmc_dev(host->mmc), "%s regulator_set_voltage failed: %d",
+                                       "vddio_sdmmc", rc);
+                       } else {
+                               regulator_enable(tegra_host->vdd_io_reg);
+                       }
+               }
+
+               tegra_host->vdd_slot_reg = regulator_get(mmc_dev(host->mmc), "vddio_sd_slot");
+               if (WARN_ON(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));
+                       tegra_host->vdd_slot_reg = NULL;
+               } else {
+                       regulator_enable(tegra_host->vdd_slot_reg);
+               }
+       }
+
        clk = clk_get(mmc_dev(host->mmc), NULL);
        if (IS_ERR(clk)) {
                dev_err(mmc_dev(host->mmc), "clk err\n");
@@ -373,6 +403,16 @@ static int __devexit sdhci_tegra_remove(struct platform_device *pdev)
 
        plat = pdev->dev.platform_data;
 
+       if (tegra_host->vdd_slot_reg) {
+               regulator_disable(tegra_host->vdd_slot_reg);
+               regulator_put(tegra_host->vdd_slot_reg);
+       }
+
+       if (tegra_host->vdd_io_reg) {
+               regulator_disable(tegra_host->vdd_io_reg);
+               regulator_put(tegra_host->vdd_io_reg);
+       }
+
        if (gpio_is_valid(plat->wp_gpio)) {
                tegra_gpio_disable(plat->wp_gpio);
                gpio_free(plat->wp_gpio);