summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authornaveenk <naveenk@nvidia.com>2012-01-17 15:09:09 +0530
committerRohan Somvanshi <rsomvanshi@nvidia.com>2012-01-31 04:30:29 -0800
commitdf93df7fe7293e30c7c7ee43edd6146b7dbbfdf8 (patch)
tree58b734a32ef3e4bc5983e4bd2ac135c600b154b9 /drivers/mmc
parentadd428230ff36f19b41d028587fcce7fdf2f228f (diff)
sdhci: tegra: Enabling power rails when card present
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
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/sdhci-tegra.c72
1 files changed, 64 insertions, 8 deletions
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 39a8dd088fb1..a0b5e4394514 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -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;
+ }
}
}