@@ -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)
@@ -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,
@@ -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