[PATCH 2/2] Modify MMCI/PL180 to handle agressive clocking v7

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This removes the default clocking for the MMCI controller so that
the external MCI card clock does not activate until the first
.set_ios() call is issued. It will further handle the transitions
from a clock != 0 to 0 and vice versa by gating/ungating the
clock with clk_disable()/clk_enable().

This assures that the MCI clock will not be active unless there
is a card in the MMC slot.

By default the MMC core will not gate off the clock to a card
once it's enabled, but with the separate patch for aggressive
clocking this can optionally be enabled for the system.

Signed-off-by: Linus Walleij <linus.walleij@xxxxxxxxxxxxxx>
---
This complements the agressive clocking patch. The patches are
actually independent and this patch is good on its own since it
removes the unnecessary clocking of the MCI clock to slots with
no cards in them, but it also has the side effect of enabling
aggressive clocking introduced with a separate patch.
---
 drivers/mmc/host/mmci.c |   35 +++++++++++++++++++++++------------
 drivers/mmc/host/mmci.h |    1 +
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 743d497..3fa4c4f 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -924,7 +924,23 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
 	spin_lock_irqsave(&host->lock, flags);
 
-	mmci_set_clkreg(host, ios->clock);
+	/*
+	 * Turn on clock whenever ios->clock transitions
+	 * from 0 to !=0 and gate it off whenever ios->clock
+	 * transitions from !=0 to 0.
+	 */
+	if (host->iosclock == 0 && ios->clock != 0) {
+		dev_dbg(mmc_dev(mmc), "enable clock f=%d\n", ios->clock);
+		clk_enable(host->clk);
+		mmci_set_clkreg(host, ios->clock);
+	} else if (host->iosclock != 0 && ios->clock == 0) {
+		dev_dbg(mmc_dev(mmc), "disable clock\n");
+		clk_disable(host->clk);
+	} else if (ios->clock != 0) {
+		mmci_set_clkreg(host, ios->clock);
+		dev_dbg(mmc_dev(mmc), "set clock f=%d\n", ios->clock);
+	}
+	host->iosclock = ios->clock;
 
 	if (host->pwr != pwr) {
 		host->pwr = pwr;
@@ -1009,6 +1025,8 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
 
 	host = mmc_priv(mmc);
 	host->mmc = mmc;
+	host->plat = plat;
+	host->variant = variant;
 
 	host->gpio_wp = -ENOSYS;
 	host->gpio_cd = -ENOSYS;
@@ -1019,19 +1037,14 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
 	dev_dbg(mmc_dev(mmc), "designer ID = 0x%02x\n", host->hw_designer);
 	dev_dbg(mmc_dev(mmc), "revision = 0x%01x\n", host->hw_revision);
 
+	/* This clock will be enabled/disabled by set_ios() calls later */
 	host->clk = clk_get(&dev->dev, NULL);
 	if (IS_ERR(host->clk)) {
 		ret = PTR_ERR(host->clk);
 		host->clk = NULL;
 		goto host_free;
 	}
-
-	ret = clk_enable(host->clk);
-	if (ret)
-		goto clk_free;
-
-	host->plat = plat;
-	host->variant = variant;
+	host->iosclock = 0;
 	host->mclk = clk_get_rate(host->clk);
 	/*
 	 * According to the spec, mclk is max 100 MHz,
@@ -1041,7 +1054,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
 	if (host->mclk > 100000000) {
 		ret = clk_set_rate(host->clk, 100000000);
 		if (ret < 0)
-			goto clk_disable;
+			goto clk_free;
 		host->mclk = clk_get_rate(host->clk);
 		dev_dbg(mmc_dev(mmc), "eventual mclk rate: %u Hz\n",
 			host->mclk);
@@ -1050,7 +1063,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
 	host->base = ioremap(dev->res.start, resource_size(&dev->res));
 	if (!host->base) {
 		ret = -ENOMEM;
-		goto clk_disable;
+		goto clk_free;
 	}
 
 	mmc->ops = &mmci_ops;
@@ -1203,8 +1216,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
 		gpio_free(host->gpio_cd);
  err_gpio_cd:
 	iounmap(host->base);
- clk_disable:
-	clk_disable(host->clk);
  clk_free:
 	clk_put(host->clk);
  host_free:
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index bc3b71e..5701d33 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -170,6 +170,7 @@ struct mmci_host {
 
 	unsigned int		mclk;
 	unsigned int		cclk;
+	unsigned int		iosclock;
 	u32			pwr;
 	struct mmci_platform_data *plat;
 	struct variant_data	*variant;
-- 
1.7.2.3

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux