mmc: host: Disable SDIO card clock when idle
Pavan Kunapuli [Wed, 18 Apr 2012 13:32:38 +0000 (18:32 +0530)]
Disable SDIO card clock when there are no commands/
data transfers on the SD bus.

Bug 958954
Bug 955742
Bug 952344

Change-Id: I7390be0406f7e46c0eb88ede2ae6f904b2181306
Signed-off-by: Pavan Kunapuli <pkunapuli@nvidia.com>
Reviewed-on: http://git-master/r/95390
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>

drivers/mmc/host/sdhci.c

index a58deb9..ec735bb 100644 (file)
@@ -1970,14 +1970,21 @@ static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable)
 int sdhci_enable(struct mmc_host *mmc)
 {
        struct sdhci_host *host = mmc_priv(mmc);
+       u16 clk;
 
-       if (!mmc->card || mmc->card->type == MMC_TYPE_SDIO)
+       if (!mmc->card)
                return 0;
 
        if (mmc->ios.clock) {
-               if (host->ops->set_clock)
-                       host->ops->set_clock(host, mmc->ios.clock);
-               sdhci_set_clock(host, mmc->ios.clock);
+               if (mmc->card->type != MMC_TYPE_SDIO) {
+                       if (host->ops->set_clock)
+                               host->ops->set_clock(host, mmc->ios.clock);
+                       sdhci_set_clock(host, mmc->ios.clock);
+               } else {
+                       clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+                       clk |= SDHCI_CLOCK_CARD_EN;
+                       sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+               }
        }
 
        return 0;
@@ -1986,13 +1993,21 @@ int sdhci_enable(struct mmc_host *mmc)
 int sdhci_disable(struct mmc_host *mmc, int lazy)
 {
        struct sdhci_host *host = mmc_priv(mmc);
+       u16 clk;
 
-       if (!mmc->card || mmc->card->type == MMC_TYPE_SDIO)
+       if (!mmc->card)
                return 0;
 
-       sdhci_set_clock(host, 0);
-       if (host->ops->set_clock)
-               host->ops->set_clock(host, 0);
+       /* For SDIO cards, only disable the card clock. */
+       if (mmc->card->type != MMC_TYPE_SDIO) {
+               sdhci_set_clock(host, 0);
+               if (host->ops->set_clock)
+                       host->ops->set_clock(host, 0);
+       } else {
+               clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+               clk &= ~SDHCI_CLOCK_CARD_EN;
+               sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+       }
 
        return 0;
 }