From patchwork Fri Dec 3 19:26:50 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philip Rakity X-Patchwork-Id: 378771 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 oB3JVHpa024448 for ; Fri, 3 Dec 2010 19:31:19 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753016Ab0LCTbN (ORCPT ); Fri, 3 Dec 2010 14:31:13 -0500 Received: from na3sys009aog114.obsmtp.com ([74.125.149.211]:40504 "HELO na3sys009aog114.obsmtp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1752996Ab0LCTbM convert rfc822-to-8bit (ORCPT ); Fri, 3 Dec 2010 14:31:12 -0500 Received: from source ([65.219.4.130]) (using TLSv1) by na3sys009aob114.postini.com ([74.125.148.12]) with SMTP ID DSNKTPlFfaUTjoQ8o4BEvQvH0byNB7LuA89d@postini.com; Fri, 03 Dec 2010 11:31:12 PST Received: from SC-vEXCH3.marvell.com ([10.93.76.133]) by sc-owa02.marvell.com ([10.93.76.22]) with mapi; Fri, 3 Dec 2010 11:26:52 -0800 From: Philip Rakity To: "linux-mmc@vger.kernel.org" CC: Nicolas Pitre , Linus Walleij Date: Fri, 3 Dec 2010 11:26:50 -0800 Subject: [PATCH 1/3 ] mmc: add support for h/w clock gating of sd controller Thread-Topic: [PATCH 1/3 ] mmc: add support for h/w clock gating of sd controller Thread-Index: AcuTIAlNY7FNNH58QxWiCP8caeqcjQ== Message-ID: <3C50EC54-F380-4AE8-A417-4D3557FEB588@marvell.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: acceptlanguage: en-US 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]); Fri, 03 Dec 2010 19:31:20 +0000 (UTC) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 6286898..c8bba7d 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -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); diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 026c975..184d56b 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -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); diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 92e3370..ace748e 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -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); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 0eccd96..195e557 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -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). */ diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 49da4df..04e0d6f 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -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. */ diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index efef5f9..52fbbb7 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -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. */ diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 078cff7..30ce755 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -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