@@ -131,7 +131,10 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
if (mrq->done)
mrq->done(mrq);
- mmc_host_clk_gate(host);
+#ifdef CONFIG_MMC_CLKGATE
+ if ((host->caps & MMC_CAP_CLOCK_GATING_HW) == 0)
+ mmc_host_clk_gate(host);
+#endif
}
}
@@ -192,7 +195,10 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
mrq->stop->mrq = mrq;
}
}
- mmc_host_clk_ungate(host);
+#ifdef CONFIG_MMC_CLKGATE
+ if ((host->caps & MMC_CAP_CLOCK_GATING_HW) == 0)
+ mmc_host_clk_ungate(host);
+#endif
host->ops->request(host, mrq);
}
@@ -1547,8 +1553,14 @@ void mmc_rescan(struct work_struct *work)
pr_info("%s: %s: trying to init card at %u Hz\n",
mmc_hostname(host), __func__, host->f_init);
#endif
- mmc_power_up(host);
+
+#ifdef CONFIG_MMC_CLKGATE
+ if (host->caps & MMC_CAP_CLOCK_GATING_HW)
+ mmc_hwungate_clock(host);
+#endif
sdio_reset(host);
+ mmc_power_up(host);
+
mmc_go_idle(host);
mmc_send_if_cond(host, host->ocr_avail);
@@ -35,6 +35,25 @@ void mmc_set_chip_select(struct mmc_host *host, int mode);
void mmc_set_clock(struct mmc_host *host, unsigned int hz);
void mmc_gate_clock(struct mmc_host *host);
void mmc_ungate_clock(struct mmc_host *host);
+
+#ifdef CONFIG_MMC_CLKGATE
+/*
+ * This gates the clock by enabling driver h/w gating
+ */
+static inline void mmc_hwgate_clock(struct mmc_host *host)
+{
+ host->clk_gated = true;
+}
+
+/*
+ * This ungates the clock by turning off h/w gating
+ */
+static inline void mmc_hwungate_clock(struct mmc_host *host)
+{
+ host->clk_gated = false;
+}
+#endif
+
void mmc_set_ungated(struct mmc_host *host);
void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode);
void mmc_set_bus_width(struct mmc_host *host, unsigned int width);
@@ -282,7 +282,10 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
host->class_dev.class = &mmc_host_class;
device_initialize(&host->class_dev);
- mmc_host_clk_init(host);
+#ifdef CONFIG_MMC_CLKGATE
+ if ((host->caps & MMC_CAP_CLOCK_GATING_HW) == 0)
+ mmc_host_clk_init(host);
+#endif
spin_lock_init(&host->lock);
init_waitqueue_head(&host->wq);
@@ -366,7 +369,10 @@ void mmc_remove_host(struct mmc_host *host)
led_trigger_unregister_simple(host->led);
- mmc_host_clk_exit(host);
+#ifdef CONFIG_MMC_CLKGATE
+ if ((host->caps & MMC_CAP_CLOCK_GATING_HW) == 0)
+ mmc_host_clk_exit(host);
+#endif
}
EXPORT_SYMBOL(mmc_remove_host);
@@ -517,6 +517,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
mmc_set_clock(host, max_dtr);
+#ifdef CONFIG_MMC_CLKGATE
+ if (host->caps & MMC_CAP_CLOCK_GATING_HW)
+ mmc_hwgate_clock(host);
+#endif
+
/*
* Indicate DDR mode (if supported).
*/
@@ -618,6 +618,10 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
else if (err)
goto free_card;
+#ifdef CONFIG_MMC_CLKGATE
+ if (host->caps & MMC_CAP_CLOCK_GATING_HW)
+ mmc_hwgate_clock(host);
+#endif
/*
* Set bus speed.
*/
@@ -488,6 +488,11 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
else if (err)
goto remove;
+#ifdef CONFIG_MMC_CLKGATE
+ if (host->caps & MMC_CAP_CLOCK_GATING_HW)
+ mmc_hwungate_clock(host);
+#endif
+
/*
* Change to the card's maximum speed.
*/
@@ -171,6 +171,7 @@ struct mmc_host {
#define MMC_CAP_POWER_OFF_CARD (1 << 13) /* Can power off after boot */
#define MMC_CAP_BUS_WIDTH_TEST (1 << 14) /* CMD14/CMD19 bus width ok */
+#define MMC_CAP_CLOCK_GATING_HW (1 << 15) /* h/w supports clock gating */
mmc_pm_flag_t pm_caps; /* supported pm features */
#ifdef CONFIG_MMC_CLKGATE