From patchwork Wed Nov 3 09:23:01 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 298612 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oA39Nfdl017336 for ; Wed, 3 Nov 2010 09:23:41 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751940Ab0KCJXj (ORCPT ); Wed, 3 Nov 2010 05:23:39 -0400 Received: from mail.df.lth.se ([194.47.250.12]:46773 "EHLO df.lth.se" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752523Ab0KCJXh (ORCPT ); Wed, 3 Nov 2010 05:23:37 -0400 Received: from mer.df.lth.se (mer.df.lth.se [194.47.250.37]) by df.lth.se (8.14.2/8.13.7) with ESMTP id oA39N3E9000165 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 3 Nov 2010 10:23:03 +0100 (CET) Received: from mer.df.lth.se (triad@localhost.localdomain [127.0.0.1]) by mer.df.lth.se (8.14.3/8.14.3/Debian-9.1) with ESMTP id oA39N3xR010660; Wed, 3 Nov 2010 10:23:03 +0100 Received: (from triad@localhost) by mer.df.lth.se (8.14.3/8.14.3/Submit) id oA39N37h010659; Wed, 3 Nov 2010 10:23:03 +0100 From: Linus Walleij To: linux-mmc@vger.kernel.org Cc: Ghorai Sukumar , Chris Ball , Nicolas Pitre , Adrian Hunter , David Vrabel , Kyungmin Park , jh80.chung@samsung.com, Linus Walleij Subject: [PATCH 2/2] mmci: handle clock frequency 0 properly v8 Date: Wed, 3 Nov 2010 10:23:01 +0100 Message-Id: <1288776181-10407-1-git-send-email-linus.walleij@stericsson.com> X-Mailer: git-send-email 1.7.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Wed, 03 Nov 2010 09:23:42 +0000 (UTC) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index d4081d5..ea5e320 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;