sdhci: tegra: Enabling power rails when card present
naveenk [Tue, 17 Jan 2012 09:39:09 +0000 (14:39 +0530)]
Enabling power rails when the card is present
which reduces power consumption

Bug 924888
Reviewed-on: http://git-master/r/75653

Change-Id: If9cbd02b49821954646845bd889501e9159c7b8c
Signed-off-by: naveen kumar arepalli <naveenk@nvidia.com>
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Reviewed-on: http://git-master/r/78023
Reviewed-by: Automatic_Commit_Validation_User

drivers/mmc/host/sdhci-tegra.c

index 39a8dd0..a0b5e43 100644 (file)
@@ -74,13 +74,17 @@ struct tegra_sdhci_hw_ops{
        void    (*sdhost_init)(struct sdhci_host *sdhci);
 };
 
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
 static struct tegra_sdhci_hw_ops tegra_2x_sdhci_ops = {
 };
+#endif
 
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
 static struct tegra_sdhci_hw_ops tegra_3x_sdhci_ops = {
        .set_card_clock = tegra_3x_sdhci_set_card_clock,
        .sdhost_init = tegra3_sdhci_post_reset_init,
 };
+#endif
 
 struct tegra_sdhci_host {
        bool    clk_enabled;
@@ -97,6 +101,8 @@ struct tegra_sdhci_host {
        /* max clk supported by the platform */
        unsigned int max_clk_limit;
        struct tegra_io_dpd *dpd;
+       bool card_present;
+       bool is_rail_enabled;
 };
 
 static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg)
@@ -274,6 +280,32 @@ static void sdhci_status_notify_cb(int card_present, void *dev_id)
 static irqreturn_t carddetect_irq(int irq, void *data)
 {
        struct sdhci_host *sdhost = (struct sdhci_host *)data;
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhost);
+       struct tegra_sdhci_host *tegra_host = pltfm_host->priv;
+       struct platform_device *pdev = to_platform_device(mmc_dev(sdhost->mmc));
+       struct tegra_sdhci_platform_data *plat;
+
+       plat = pdev->dev.platform_data;
+
+       tegra_host->card_present = (gpio_get_value(plat->cd_gpio) == 0);
+
+       if (tegra_host->card_present) {
+               if (!tegra_host->is_rail_enabled) {
+                       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;
+               }
+       } else {
+               if (tegra_host->is_rail_enabled) {
+                       if (tegra_host->vdd_io_reg)
+                               regulator_disable(tegra_host->vdd_io_reg);
+                       if (tegra_host->vdd_slot_reg)
+                               regulator_disable(tegra_host->vdd_slot_reg);
+                       tegra_host->is_rail_enabled = 0;
+                }
+       }
 
        tasklet_schedule(&sdhost->card_tasklet);
        return IRQ_HANDLED;
@@ -528,6 +560,16 @@ static int tegra_sdhci_suspend(struct sdhci_host *sdhci, pm_message_t state)
                regulator_disable(tegra_host->vdd_slot_reg);
        if (tegra_host->vdd_io_reg)
                regulator_disable(tegra_host->vdd_io_reg);
+       if (tegra_host->card_present) {
+               if (tegra_host->is_rail_enabled) {
+                       if (tegra_host->vdd_io_reg)
+                               regulator_disable(tegra_host->vdd_io_reg);
+                       if (tegra_host->vdd_slot_reg)
+                               regulator_disable(tegra_host->vdd_slot_reg);
+                       tegra_host->is_rail_enabled = 0;
+               }
+       }
+
        return 0;
 }
 
@@ -538,10 +580,17 @@ static int tegra_sdhci_resume(struct sdhci_host *sdhci)
        unsigned long timeout;
 
        /* Enable the power rails if any */
-       if (tegra_host->vdd_io_reg)
-               regulator_enable(tegra_host->vdd_io_reg);
-       if (tegra_host->vdd_slot_reg)
-               regulator_enable(tegra_host->vdd_slot_reg);
+       if (tegra_host->card_present) {
+               if (!tegra_host->is_rail_enabled) {
+                       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_sdhci_signal_voltage_switch(sdhci, MMC_SIGNAL_VOLTAGE_330);
+                       }
+                       tegra_host->is_rail_enabled = 1;
+               }
+       }
 
        /* Setting the min identification clock of freq 400KHz */
        tegra_sdhci_set_clock(sdhci, 400000);
@@ -660,7 +709,10 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
                tegra_gpio_enable(plat->cd_gpio);
                gpio_direction_input(plat->cd_gpio);
 
-               rc = request_irq(gpio_to_irq(plat->cd_gpio), carddetect_irq,
+               tegra_host->card_present = (gpio_get_value(plat->cd_gpio) == 0);
+
+               rc = request_threaded_irq(gpio_to_irq(plat->cd_gpio), NULL,
+                                carddetect_irq,
                                 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
                                 mmc_hostname(host->mmc), host);
 
@@ -718,8 +770,6 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
                        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);
                        }
                }
 
@@ -729,7 +779,13 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
                                "vddio_sd_slot", PTR_ERR(tegra_host->vdd_slot_reg));
                        tegra_host->vdd_slot_reg = NULL;
                } else {
-                       regulator_enable(tegra_host->vdd_slot_reg);
+                       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;
+                       }
                }
        }