summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorKen Chang <kenc@nvidia.com>2013-03-12 15:42:27 +0800
committerMrutyunjay Sawant <msawant@nvidia.com>2013-04-02 04:08:27 -0700
commitb0807dbe9318dd396b99e91e671ddadbb4c2f745 (patch)
treeb253518ddded44a5dad5c9689715149176e0feaf /drivers/mmc
parent99c727f3e4a8a6544bdd676ef37fda36f592ed69 (diff)
mmc: tegra: Support sdhci rails off before reboot
Bug 1222606 Bug 1242658 Change-Id: I1f6aeab31d42d953fe73cecacb7a3d117054090c Signed-off-by: Ken Chang <kenc@nvidia.com> (cherry picked from commit b00f8fbe8a3ce474d6f64a9aed9ef7f592ea8e77) Reviewed-on: http://git-master/r/208324 Reviewed-on: http://git-master/r/213886 GVS: Gerrit_Virtual_Submit Reviewed-by: Pavan Kunapuli <pkunapuli@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/sdhci-tegra.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index d94677d6f773..1b03765e3634 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -35,6 +35,7 @@
#include <asm/gpio.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/reboot.h>
#include <mach/gpio-tegra.h>
#include <mach/sdhci.h>
@@ -245,6 +246,7 @@ struct sdhci_tegra {
/* Freq tuning information for each sampling clock freq */
struct tegra_tuning_data tuning_data;
bool is_parent_pllc;
+ struct notifier_block reboot_notify;
};
static struct clk *pll_c;
@@ -1801,6 +1803,32 @@ static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata(
return plat;
}
+static void tegra_sdhci_rail_off(struct sdhci_tegra *tegra_host)
+{
+ if (tegra_host->is_rail_enabled) {
+ if (tegra_host->vdd_slot_reg)
+ regulator_disable(tegra_host->vdd_slot_reg);
+ if (tegra_host->vdd_io_reg)
+ regulator_disable(tegra_host->vdd_io_reg);
+ tegra_host->is_rail_enabled = false;
+ }
+}
+
+static int tegra_sdhci_reboot_notify(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct sdhci_tegra *tegra_host =
+ container_of(nb, struct sdhci_tegra, reboot_notify);
+
+ switch (event) {
+ case SYS_RESTART:
+ case SYS_POWER_OFF:
+ tegra_sdhci_rail_off(tegra_host);
+ return NOTIFY_OK;
+ }
+ return NOTIFY_DONE;
+}
+
static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
@@ -2066,6 +2094,11 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
/* Enable async suspend/resume to reduce LP0 latency */
device_enable_async_suspend(&pdev->dev);
+ if (plat->power_off_rail) {
+ tegra_host->reboot_notify.notifier_call =
+ tegra_sdhci_reboot_notify;
+ register_reboot_notifier(&tegra_host->reboot_notify);
+ }
return 0;
err_add_host:
@@ -2131,6 +2164,9 @@ static int __devexit sdhci_tegra_remove(struct platform_device *pdev)
}
clk_put(pltfm_host->clk);
+ if (plat->power_off_rail)
+ unregister_reboot_notifier(&tegra_host->reboot_notify);
+
sdhci_pltfm_free(pdev);
return 0;