diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/Kconfig | 12 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 26 | ||||
-rwxr-xr-x[-rw-r--r--] | drivers/mmc/host/sdhci.h | 5 |
3 files changed, 40 insertions, 3 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 3f8a5bb69e42..aca32075e12d 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -37,6 +37,18 @@ config MMC_SDHCI If unsure, say N. +config MMC_SDHCI_DYNAMIC_SDMEM_CLOCK + depends on MMC_SDHCI + bool "Dynamically control the card clock for SD memory devices" + default y + help + On certain embedded devices, leaving the card clock enabled to + SD memory devices with no active transactions can increase power + consumption. Enable this option to automatically disable the card + clock after transfers complete. + + If unsure, say N here. + config MMC_SDHCI_PCI tristate "SDHCI support on PCI bus" depends on MMC_SDHCI && PCI diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 8bb9366bbf0c..a0591db8c152 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -18,6 +18,7 @@ #include <linux/io.h> #include <linux/dma-mapping.h> #include <linux/scatterlist.h> +#include <linux/mmc/card.h> #include <linux/leds.h> @@ -134,6 +135,9 @@ static void sdhci_init(struct sdhci_host *host) writel(intmask, host->ioaddr + SDHCI_INT_ENABLE); writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE); +#ifdef CONFIG_MMC_SDHCI_DYNAMIC_SDMEM_CLOCK + host->last_clock = 0; +#endif } static void sdhci_activate_led(struct sdhci_host *host) @@ -909,7 +913,9 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) if (clock == 0) goto out; - +#ifdef CONFIG_MMC_SDHCI_DYNAMIC_SDMEM_CLOCK + host->last_clock = clock; +#endif div = 0; if (host->ops->set_clock) div = host->ops->set_clock(host, clock); @@ -1010,6 +1016,15 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) unsigned long flags; host = mmc_priv(mmc); +#ifdef CONFIG_MMC_SDHCI_DYNAMIC_SDMEM_CLOCK + if (host->mmc->card != NULL) { + if (host->mmc->card->type != MMC_TYPE_SDIO) { + if (host->last_clock) + /* Enable clock */ + sdhci_set_clock(host, host->last_clock); + } + } +#endif spin_lock_irqsave(&host->lock, flags); @@ -1240,7 +1255,14 @@ static void sdhci_tasklet_finish(unsigned long param) mmiowb(); spin_unlock_irqrestore(&host->lock, flags); - +#ifdef CONFIG_MMC_SDHCI_DYNAMIC_SDMEM_CLOCK + /* Disable clock */ + if (host->mmc->card != NULL) { + if (host->mmc->card->type != MMC_TYPE_SDIO) { + sdhci_set_clock(host, 0); + } + } +#endif mmc_request_done(host->mmc, mrq); } diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 5805e301e604..fe800af6b7d0 100644..100755 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -58,7 +58,7 @@ #define SDHCI_CARD_PRESENT 0x00010000 #define SDHCI_WRITE_PROTECT 0x00080000 -#define SDHCI_HOST_CONTROL 0x28 +#define SDHCI_HOST_CONTROL 0x28 #define SDHCI_CTRL_LED 0x01 #define SDHCI_CTRL_4BITBUS 0x02 #define SDHCI_CTRL_8BITBUS 0x20 @@ -246,6 +246,9 @@ struct sdhci_host { unsigned int timeout_clk; /* Timeout freq (KHz) */ unsigned int clock; /* Current clock (MHz) */ +#ifdef CONFIG_MMC_SDHCI_DYNAMIC_SDMEM_CLOCK + unsigned int last_clock; /* Last used clock (MHz) */ +#endif unsigned short power; /* Current voltage */ struct mmc_request *mrq; /* Current request */ |