diff options
author | Ken Chang <kenc@nvidia.com> | 2013-03-12 15:42:27 +0800 |
---|---|---|
committer | Mrutyunjay Sawant <msawant@nvidia.com> | 2013-04-02 04:08:27 -0700 |
commit | b0807dbe9318dd396b99e91e671ddadbb4c2f745 (patch) | |
tree | b253518ddded44a5dad5c9689715149176e0feaf /drivers/mmc | |
parent | 99c727f3e4a8a6544bdd676ef37fda36f592ed69 (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.c | 36 |
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; |