diff mbox

[18/23] Alternative mmc structure to support pxa168, pxa910, mmp2 family SD

Message ID 2892BF36-424E-4620-93B9-000CA5222F82@marvell.com (mailing list archive)
State New, archived
Headers show

Commit Message

Philip Rakity Dec. 22, 2010, 7:10 a.m. UTC
None
diff mbox

Patch

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index a8e89f3..259bd0d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -683,10 +683,35 @@  void mmc_ungate_clock(struct mmc_host *host)
 	}
 }
 
+/*
+ * Let hardware automatically gate the clock when the card becomes idle
+ */
+void mmc_hwgate_clock(struct mmc_host *host)
+{
+	if (host->caps & MMC_CAP_HW_CLOCK_GATING) {
+		host->clk_gated = true;
+		mmc_set_ios(host);
+	}
+}
+
+/*
+ * This ungates the clock by turning off h/w gating
+ */
+void mmc_hwungate_clock(struct mmc_host *host)
+{
+	if (host->caps & MMC_CAP_HW_CLOCK_GATING) {
+		host->clk_gated = false;
+		mmc_set_ios(host);
+	}
+}
+
+
 void mmc_set_ungated(struct mmc_host *host)
 {
 	unsigned long flags;
 
+	if (host->caps & MMC_CAP_HW_CLOCK_GATING)
+		return;
 	/*
 	 * We've been given a new frequency while the clock is gated,
 	 * so make sure we regard this as ungating it.
@@ -1553,6 +1578,7 @@  void mmc_rescan(struct work_struct *work)
 			mmc_hostname(host), __func__, host->f_init);
 #endif
 		mmc_power_up(host);
+		mmc_hwungate_clock(host);
 		sdio_reset(host);
 		mmc_go_idle(host);
 
@@ -1577,6 +1603,9 @@  void mmc_rescan(struct work_struct *work)
 				if (mmc_send_app_op_cond(host, 0, &ocr))
 					goto out_fail;
 
+				/* hw clock gating is off when we get here */
+				/* do not enable clock gating for sdio cards */
+				/* sdio cards can miss interrupts */
 				if (mmc_attach_sd(host, ocr))
 					mmc_power_off(host);
 			}
@@ -1590,6 +1619,8 @@  void mmc_rescan(struct work_struct *work)
 		if (!err) {
 			if (mmc_attach_sd(host, ocr))
 				mmc_power_off(host);
+			else
+				mmc_hwgate_clock(host);
 			goto out;
 		}
 
@@ -1600,6 +1631,8 @@  void mmc_rescan(struct work_struct *work)
 		if (!err) {
 			if (mmc_attach_mmc(host, ocr))
 				mmc_power_off(host);
+			else
+				mmc_hwgate_clock(host);
 			goto out;
 		}
 
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 026c975..3810e28 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -35,6 +35,19 @@  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
+void mmc_hwgate_clock(struct mmc_host *host);
+void mmc_hwungate_clock(struct mmc_host *host);
+#else
+static inline void mmc_hwgate_clock(struct mmc_host *host)
+{
+}
+
+static inline void mmc_hwungate_clock(struct mmc_host *host)
+{
+}
+#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);
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 92e3370..eebabde 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -130,6 +130,9 @@  void mmc_host_clk_ungate(struct mmc_host *host)
 {
 	unsigned long flags;
 
+	if (host->caps & MMC_CAP_HW_CLOCK_GATING)
+		return;
+
 	mutex_lock(&host->clk_gate_mutex);
 	spin_lock_irqsave(&host->clk_lock, flags);
 	if (host->clk_gated) {
@@ -178,6 +181,9 @@  void mmc_host_clk_gate(struct mmc_host *host)
 {
 	unsigned long flags;
 
+	if (host->caps & MMC_CAP_HW_CLOCK_GATING)
+		return;
+
 	spin_lock_irqsave(&host->clk_lock, flags);
 	host->clk_requests--;
 	if (mmc_host_may_gate_card(host->card) &&
@@ -198,7 +204,10 @@  unsigned int mmc_host_clk_rate(struct mmc_host *host)
 	unsigned long flags;
 
 	spin_lock_irqsave(&host->clk_lock, flags);
-	if (host->clk_gated)
+		freq = host->ios.clock;
+	if (host->caps & MMC_CAP_HW_CLOCK_GATING)
+		freq = host->ios.clock;
+	else if (host->clk_gated)
 		freq = host->clk_old;
 	else
 		freq = host->ios.clock;
@@ -212,6 +221,9 @@  unsigned int mmc_host_clk_rate(struct mmc_host *host)
  */
 static inline void mmc_host_clk_init(struct mmc_host *host)
 {
+	if (host->caps & MMC_CAP_HW_CLOCK_GATING)
+		return;
+
 	host->clk_requests = 0;
 	/* Hold MCI clock for 8 cycles by default */
 	host->clk_delay = 8;
@@ -227,6 +239,9 @@  static inline void mmc_host_clk_init(struct mmc_host *host)
  */
 static inline void mmc_host_clk_exit(struct mmc_host *host)
 {
+	if (host->caps & MMC_CAP_HW_CLOCK_GATING)
+		return;
+
 	/*
 	 * Wait for any outstanding gate and then make sure we're
 	 * ungated before exiting.
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index bcb793e..4e4baff 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -173,6 +173,7 @@  struct mmc_host {
 						/* DDR mode at 1.2V */
 #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_HW_CLOCK_GATING	(1 << 15)	/* h/w supports clock gating */
 
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */