mmc: host: sdhci: Support runtime enable/disable of clock
authorGreg Meiste <w30289@motorola.com>
Thu, 9 Jun 2011 17:37:34 +0000 (10:37 -0700)
committerTodd Poynor <toddpoynor@google.com>
Thu, 9 Jun 2011 22:29:24 +0000 (15:29 -0700)
Currently the SD card clock is running any time the AP is not in
LP0. This patch allows the clock to only be enabled when the card
is being accessed.

Based on an nVidia patch:
http://nv-tegra.nvidia.com/gitweb/?p=linux-2.6.git;a=commit;h=8c0f23b7e65ebdb6d1c160517e9ba509b16ec83f

Conflicts:

drivers/mmc/host/sdhci.c

Change-Id: Id188a783ca9ce7046bf2ca526cafcd91a6fab507
Signed-off-by: Greg Meiste <w30289@motorola.com>
Signed-off-by: Todd Poynor <toddpoynor@google.com>
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h

index f7695c4c169e46fe930bdee7df46dd94fd60e039..52718cf13e56bed006e7fcfada84d0374a99047c 100644 (file)
@@ -1223,6 +1223,31 @@ static int sdhci_get_ro(struct mmc_host *mmc)
        return !(present & SDHCI_WRITE_PROTECT);
 }
 
+static int sdhci_enable(struct mmc_host *mmc)
+{
+       struct sdhci_host *host = mmc_priv(mmc);
+
+       if (!mmc->card || mmc->card->type == MMC_TYPE_SDIO)
+               return 0;
+
+       if (mmc->ios.clock)
+               sdhci_set_clock(host, mmc->ios.clock);
+
+       return 0;
+}
+
+static int sdhci_disable(struct mmc_host *mmc, int lazy)
+{
+       struct sdhci_host *host = mmc_priv(mmc);
+
+       if (!mmc->card || mmc->card->type == MMC_TYPE_SDIO)
+               return 0;
+
+       sdhci_set_clock(host, 0);
+
+       return 0;
+}
+
 static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
 {
        struct sdhci_host *host;
@@ -1249,6 +1274,8 @@ static const struct mmc_host_ops sdhci_ops = {
        .request        = sdhci_request,
        .set_ios        = sdhci_set_ios,
        .get_ro         = sdhci_get_ro,
+       .enable         = sdhci_enable,
+       .disable        = sdhci_disable,
        .enable_sdio_irq = sdhci_enable_sdio_irq,
 };
 
@@ -1829,6 +1856,13 @@ int sdhci_add_host(struct sdhci_host *host)
        if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
                mmc->caps |= MMC_CAP_NEEDS_POLL;
 
+       if (host->quirks & SDHCI_QUIRK_RUNTIME_DISABLE) {
+               mmc->caps |= MMC_CAP_DISABLE;
+               mmc_set_disable_delay(mmc, 50);
+       }
+
+       mmc->caps |= MMC_CAP_ERASE;
+
        mmc->ocr_avail = 0;
        if (caps & SDHCI_CAN_VDD_330)
                mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
index e866164c141337ceb91a58d18c43b5f391349ecc..ee99628635b8a62a2c68b51b06bae32ca63b599c 100644 (file)
@@ -263,6 +263,8 @@ struct sdhci_host {
 #define SDHCI_QUIRK_NO_SDIO_IRQ                                (1LL<<36)
 /* Controller should only use high-speed mode */
 #define SDHCI_QUIRK_FORCE_HIGH_SPEED_MODE              (1LL<<37)
+/* Controller allows runtime enable / disable */
+#define SDHCI_QUIRK_RUNTIME_DISABLE                    (1LL<<38)
 
        int                     irq;            /* Device IRQ */
        void __iomem *          ioaddr;         /* Mapped address */