summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeepesh Gujarathi <dgujarathi@nvidia.com>2010-03-12 18:03:11 +0530
committerGary King <gking@nvidia.com>2010-03-18 17:02:26 -0800
commitac687aba0d16b99818f8ca86f35dc0503fb7a46e (patch)
tree3c4728f87fbf323c32cb62e2126f35ed7240d019
parent88547baef53e45e1fe5ffa8cb1fd79314f7b07ab (diff)
tegra pm: add suspend/resume to tegra-sdhci driver
Implement suspend/resume functionality for the tegra-sdhci driver. Call the sdhci_suspend/resume functions which handles the power off and re-enumeration of sd memory cards. We ignore suspend/resume requests for all sdio devices asssuming that the individual drivers will manage their own power. For tegra devices, the wifi driver implements its own early suspend model and hence is ignored by the sdhci driver. Change-Id: I5041d314123bac958da7775ee24bd2dc1be55ab5 Change-Id: I5041d314123bac958da7775ee24bd2dc1be55ab5 Reviewed-on: http://git-master/r/852 Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Reviewed-by: Gary King <gking@nvidia.com> Tested-by: Bharat Nihalani <bnihalani@nvidia.com> Reviewed-by: Rahul Bansal <rbansal@nvidia.com> Tested-by: Rahul Bansal <rbansal@nvidia.com> Reviewed-by: Venkata (Muni) Anda <vanda@nvidia.com>
-rwxr-xr-x[-rw-r--r--]drivers/mmc/host/sdhci-tegra.c45
-rwxr-xr-xdrivers/mmc/host/sdhci.c7
-rwxr-xr-xdrivers/mmc/host/sdhci.h3
3 files changed, 52 insertions, 3 deletions
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index c4cbb60fd07c..9e5798674f9d 100644..100755
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -24,6 +24,7 @@
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/tegra_devices.h>
+#include <linux/mmc/card.h>
#include "sdhci.h"
#include "mach/nvrm_linux.h"
@@ -370,11 +371,51 @@ static int __devexit tegra_sdhci_remove(struct platform_device *pdev)
return 0;
}
+#if defined(CONFIG_PM)
+
+static int tegra_sdhci_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ int ret = 0;
+ struct tegra_sdhci *t_sdhci;
+
+ t_sdhci = platform_get_drvdata(pdev);
+
+ if (t_sdhci->sdhost->card_type != MMC_TYPE_SDIO) {
+ ret = sdhci_suspend_host(t_sdhci->sdhost,state);
+ if (ret)
+ printk("sdhci_suspend_host failed with error %d\n", ret);
+ }
+
+ return ret;
+}
+
+static int tegra_sdhci_resume(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct tegra_sdhci *t_sdhci;
+
+ t_sdhci = platform_get_drvdata(pdev);
+
+ if (t_sdhci->sdhost->card_type != MMC_TYPE_SDIO) {
+ ret = sdhci_resume_host(t_sdhci->sdhost);
+ if (ret)
+ printk("sdhci_resume_host failed with error %d\n", ret);
+ }
+
+ return ret;
+}
+#endif
+
struct platform_driver tegra_sdhci_driver = {
.probe = tegra_sdhci_probe,
.remove = __devexit_p(tegra_sdhci_remove),
- .suspend = NULL,
- .resume = NULL,
+#if defined(CONFIG_PM)
+ .suspend = tegra_sdhci_suspend,
+ .resume = tegra_sdhci_resume,
+#else
+ .suspend = NULL,
+ .resume = NULL,
+#endif
.driver = {
.name = "tegra-sdhci",
.owner = THIS_MODULE,
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index e38467a0a3e3..df4c4bcfe431 100755
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -923,6 +923,11 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
u16 clk;
unsigned long timeout;
+ if (host->card_type == SDHCI_CARD_UNKNKOWN) {
+ if (host->mmc->card != NULL)
+ host->card_type = host->mmc->card->type;
+ }
+
if (clock == host->clock)
return;
@@ -1608,7 +1613,7 @@ struct sdhci_host *sdhci_alloc_host(struct device *dev,
host = mmc_priv(mmc);
host->mmc = mmc;
-
+ host->card_type = SDHCI_CARD_UNKNKOWN;
return host;
}
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 3466515a9f56..2ed1fe9b0734 100755
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -277,6 +277,9 @@ struct sdhci_host {
struct timer_list timer; /* Timer for timeouts */
+#define SDHCI_CARD_UNKNKOWN 0xFF
+ unsigned int card_type;
+
#ifdef CONFIG_EMBEDDED_MMC_START_OFFSET
unsigned int start_offset; /* Zero-offset for MBR */
#endif