From patchwork Tue Nov 16 17:17:49 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 328792 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 oAGHLE9L005258 for ; Tue, 16 Nov 2010 17:21:14 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754829Ab0KPRVN (ORCPT ); Tue, 16 Nov 2010 12:21:13 -0500 Received: from eu1sys200aog103.obsmtp.com ([207.126.144.115]:48020 "EHLO eu1sys200aog103.obsmtp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753372Ab0KPRVN (ORCPT ); Tue, 16 Nov 2010 12:21:13 -0500 Received: from source ([167.4.1.35]) (using TLSv1) by eu1sys200aob103.postini.com ([207.126.147.11]) with SMTP ID DSNKTOK88M8yZAXqDUHJ3feGykProUniSb6S@postini.com; Tue, 16 Nov 2010 17:21:12 UTC Received: from zeta.dmz-us.st.com (ns4.st.com [167.4.80.115]) by beta.dmz-us.st.com (STMicroelectronics) with ESMTP id 54FC4DA; Tue, 16 Nov 2010 17:17:53 +0000 (GMT) Received: from relay1.stm.gmessaging.net (unknown [10.230.100.17]) by zeta.dmz-us.st.com (STMicroelectronics) with ESMTP id 0B53F236; Tue, 16 Nov 2010 17:17:53 +0000 (GMT) Received: from exdcvycastm004.EQ1STM.local (alteon-source-exch [10.230.100.61]) (using TLSv1 with cipher RC4-MD5 (128/128 bits)) (Client CN "exdcvycastm004", Issuer "exdcvycastm004" (not verified)) by relay1.stm.gmessaging.net (Postfix) with ESMTPS id 2C80724C07C; Tue, 16 Nov 2010 18:17:44 +0100 (CET) Received: from localhost.localdomain (10.230.100.153) by smtp.stericsson.com (10.230.100.2) with Microsoft SMTP Server (TLS) id 8.2.254.0; Tue, 16 Nov 2010 18:17:52 +0100 From: Linus Walleij To: , , Cc: , Linus Walleij , Chris Ball , Russell King Subject: [PATCH] mmci: handle clock frequency 0 properly Date: Tue, 16 Nov 2010 18:17:49 +0100 Message-ID: <1289927869-14519-1-git-send-email-linus.walleij@stericsson.com> X-Mailer: git-send-email 1.6.3.3 MIME-Version: 1.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]); Tue, 16 Nov 2010 17:21:14 +0000 (UTC) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 0814b88..3709ab3 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -689,6 +689,22 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 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); + } 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) { + dev_dbg(mmc_dev(mmc), "set clock f=%d\n", ios->clock); + } + host->iosclock = ios->clock; + if (host->pwr != pwr) { host->pwr = pwr; writel(pwr, host->base + MMCIPOWER); @@ -772,6 +788,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; @@ -782,19 +800,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, @@ -804,7 +817,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); @@ -812,7 +825,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; @@ -961,8 +974,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 df06f01..4791a2b 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -167,6 +167,7 @@ struct mmci_host { unsigned int mclk; unsigned int cclk; + unsigned int iosclock; u32 pwr; struct mmci_platform_data *plat; struct variant_data *variant;