Hi all,
  This is a RFC patch that support clock-gating for saving power consumption.
  I found mmc_host_enable/mmc_host_disable function in core.c
  (using MMC_CAP_DSIABLE. i think that use when host enable/disable)
  So, i used that functions and implemented some functions in sdhci-s3c.c & 
sdhci.c

i want any feedback. how do you think about this patch?
Plz let me know...

Thank you all

 Signed-off-by: Jaehoon Chung <[email protected]>
 Signed-off-by: Kyungmin Park <[email protected]>

---
 drivers/mmc/host/sdhci-s3c.c |   36 ++++++++++++++++++++++++++++++++++++
 drivers/mmc/host/sdhci.c     |   30 ++++++++++++++++++++++++++++++
 drivers/mmc/host/sdhci.h     |    4 ++++
 3 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 71ad416..9b430fb 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -47,6 +47,7 @@ struct sdhci_s3c {
        unsigned int            cur_clk;
        int                     ext_cd_irq;
        int                     ext_cd_gpio;
+       int                     flag;
 
        struct clk              *clk_io;
        struct clk              *clk_bus[MAX_BUS_CLK];
@@ -232,10 +233,45 @@ static unsigned int sdhci_s3c_get_min_clock(struct 
sdhci_host *host)
        return min;
 }
 
+static int sdhci_s3c_enable_clk(struct sdhci_host *host)
+{
+       struct sdhci_s3c *sc = to_s3c(host);
+
+       if (sc->flag != 1) {
+               clk_disable(sc->clk_io);
+               clk_disable(sc->clk_bus[sc->cur_clk]);
+       }
+
+       if (sc->host->clk_cnt == 0) {
+               clk_enable(sc->clk_io);
+               clk_enable(sc->clk_bus[sc->cur_clk]);
+               sc->host->clk_cnt++;
+               sc->flag = 1;
+       }
+
+       return 0;
+}
+
+static int sdhci_s3c_disable_clk(struct sdhci_host *host, int lazy)
+{
+       struct sdhci_s3c *sc = to_s3c(host);
+
+       if (sc->host->clk_cnt) {
+               clk_disable(sc->clk_io);
+               clk_disable(sc->clk_bus[sc->cur_clk]);
+               if (sc->host->clk_cnt)
+                       sc->host->clk_cnt--;
+       }
+
+       return 0;
+}
+
 static struct sdhci_ops sdhci_s3c_ops = {
        .get_max_clock          = sdhci_s3c_get_max_clk,
        .set_clock              = sdhci_s3c_set_clock,
        .get_min_clock          = sdhci_s3c_get_min_clock,
+       .enable                 = sdhci_s3c_enable_clk,
+       .disable                = sdhci_s3c_disable_clk,
 };
 
 static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 401527d..fa2e55d 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1245,7 +1245,37 @@ out:
        spin_unlock_irqrestore(&host->lock, flags);
 }
 
+static int sdhci_enable_clk(struct mmc_host *mmc)
+{
+       struct sdhci_host *host = mmc_priv(mmc);
+       int ret = 0;
+
+       if (host->old_clock != 0 && host->clock == 0) {
+               if (host->ops->enable)
+                       ret = host->ops->enable(host);
+               sdhci_set_clock(host, host->old_clock);
+       }
+
+       return ret;
+}
+
+static int sdhci_disable_clk(struct mmc_host *mmc, int lazy)
+{
+       struct sdhci_host *host = mmc_priv(mmc);
+       int ret = 0;
+
+       if (host->clock != 0) {
+               host->old_clock = host->clock;
+               sdhci_set_clock(host, 0);
+               if (host->ops->disable)
+                       ret = host->ops->disable(host, lazy);
+       }
+       return ret;
+}
+
 static const struct mmc_host_ops sdhci_ops = {
+       .enable         = sdhci_enable_clk,
+       .disable        = sdhci_disable_clk,
        .request        = sdhci_request,
        .set_ios        = sdhci_set_ios,
        .get_ro         = sdhci_get_ro,
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index d316bc7..0c6f143 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -278,6 +278,8 @@ struct sdhci_host {
        unsigned int            timeout_clk;    /* Timeout freq (KHz) */
 
        unsigned int            clock;          /* Current clock (MHz) */
+       unsigned int            old_clock;      /* Old clock (MHz) */
+       unsigned int            clk_cnt;        /* Clock user count */
        u8                      pwr;            /* Current voltage */
 
        struct mmc_request      *mrq;           /* Current request */
@@ -323,6 +325,8 @@ struct sdhci_ops {
        unsigned int    (*get_max_clock)(struct sdhci_host *host);
        unsigned int    (*get_min_clock)(struct sdhci_host *host);
        unsigned int    (*get_timeout_clock)(struct sdhci_host *host);
+       int             (*enable)(struct sdhci_host *host);
+       int             (*disable)(struct sdhci_host *host, int lazy);
 };
 
 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
-- 1.6.0.4 
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to