* [PATCH 1/3 ] mmc: add support for h/w clock gating of sd controller
@ 2010-12-03 19:26 Philip Rakity
2010-12-03 22:18 ` Nicolas Pitre
2010-12-04 21:02 ` Wolfram Sang
0 siblings, 2 replies; 4+ messages in thread
From: Philip Rakity @ 2010-12-03 19:26 UTC (permalink / raw)
To: linux-mmc@vger.kernel.org; +Cc: Nicolas Pitre, Linus Walleij
This code extends software clock gating in the mmc layer
by adding the ability to indicate that controller support
hardware clock gating.
hardware clock gating is enabled by setting the mmc quirk
MMC_CAP_CLOCK_GATING_HW
in the sd driver.
eg: host->mmc->caps |= MMC_CAP_CLOCK_GATING_HW
The approach follows the suggestion of Nico Pitre.
sd/mmc/eMMC cards use dynmamic clocks
sdio uses continuous clocks
The code has been test using marvell linux for mmp2. The marvell
controller support h/w clock gating.
Signed-off-by: Philip Rakity <prakity@marvell.com>
---
drivers/mmc/core/core.c | 18 +++++++++++++++---
drivers/mmc/core/core.h | 19 +++++++++++++++++++
drivers/mmc/core/host.c | 10 ++++++++--
drivers/mmc/core/mmc.c | 5 +++++
drivers/mmc/core/sd.c | 4 ++++
drivers/mmc/core/sdio.c | 5 +++++
include/linux/mmc/host.h | 1 +
7 files changed, 57 insertions(+), 5 deletions(-)
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
--
1.6.0.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 1/3 ] mmc: add support for h/w clock gating of sd controller
2010-12-03 19:26 [PATCH 1/3 ] mmc: add support for h/w clock gating of sd controller Philip Rakity
@ 2010-12-03 22:18 ` Nicolas Pitre
2010-12-04 21:02 ` Wolfram Sang
1 sibling, 0 replies; 4+ messages in thread
From: Nicolas Pitre @ 2010-12-03 22:18 UTC (permalink / raw)
To: Philip Rakity; +Cc: linux-mmc@vger.kernel.org, Linus Walleij
On Fri, 3 Dec 2010, Philip Rakity wrote:
> This code extends software clock gating in the mmc layer
> by adding the ability to indicate that controller support
> hardware clock gating.
>
> hardware clock gating is enabled by setting the mmc quirk
> MMC_CAP_CLOCK_GATING_HW
> in the sd driver.
> eg: host->mmc->caps |= MMC_CAP_CLOCK_GATING_HW
>
> The approach follows the suggestion of Nico Pitre.
>
> sd/mmc/eMMC cards use dynmamic clocks
> sdio uses continuous clocks
>
> The code has been test using marvell linux for mmp2. The marvell
> controller support h/w clock gating.
>
> Signed-off-by: Philip Rakity <prakity@marvell.com>
Comments below.
> 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
This is a needless proliferation of #ifdef's, since you could just test
for MMC_CAP_CLOCK_GATING_HW inside mmc_host_clk_gate() instead, and
return early if set.
> }
>
> @@ -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
Same thing here.
> 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
Here you should do just like what is done for mmc_host_clk_gate() in
host.h: provide an empty inline version when CONFIG_MMC_CLKGATE is not
defined and get rid of the #ifdef here.
> sdio_reset(host);
> + mmc_power_up(host);
Why did you move down this mmc_power_up()?
> mmc_go_idle(host);
>
> mmc_send_if_cond(host, host->ocr_avail);
[...]
> 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
Same comment as above: why don't you check for MMC_CAP_CLOCK_GATING_HW
inside mmc_host_clk_init()?
Granted, here mmc_host_clk_init() appears to be misnomed (maybe
mmc_host_clk_gating_init() would have been clearer).
> 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
Ditto here.
> }
>
> 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
And here I seriously begin to dislike this patch. The sw gating code is
centralized while the hw one is spread across all card type drivers.
Why not calling mmc_hwgate_clock() at the appropriate location within
mmc_rescan() (that would be where it is determined that only anew card
might be present) and call mmc_hwgate_clock() at the end of mmc_rescan()
and only if mmc_host_may_gate_card() is true?
Nicolas
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 1/3 ] mmc: add support for h/w clock gating of sd controller
2010-12-03 19:26 [PATCH 1/3 ] mmc: add support for h/w clock gating of sd controller Philip Rakity
2010-12-03 22:18 ` Nicolas Pitre
@ 2010-12-04 21:02 ` Wolfram Sang
2010-12-06 1:48 ` Philip Rakity
1 sibling, 1 reply; 4+ messages in thread
From: Wolfram Sang @ 2010-12-04 21:02 UTC (permalink / raw)
To: Philip Rakity; +Cc: linux-mmc@vger.kernel.org, Nicolas Pitre, Linus Walleij
[-- Attachment #1: Type: text/plain, Size: 498 bytes --]
Hi,
minor comments in addition to Nicolas:
On Fri, Dec 03, 2010 at 11:26:50AM -0800, Philip Rakity wrote:
> hardware clock gating is enabled by setting the mmc quirk
It's not a quirk, it's a capability :)
> MMC_CAP_CLOCK_GATING_HW
Why not MMC_CAP_HW_CLOCK_GATING? Might be a mileage, though...
Regards,
Wolfram
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 1/3 ] mmc: add support for h/w clock gating of sd controller
2010-12-04 21:02 ` Wolfram Sang
@ 2010-12-06 1:48 ` Philip Rakity
0 siblings, 0 replies; 4+ messages in thread
From: Philip Rakity @ 2010-12-06 1:48 UTC (permalink / raw)
To: Wolfram Sang; +Cc: linux-mmc@vger.kernel.org, Nicolas Pitre, Linus Walleij
will change tomorrow with other changes Nico Suggested.
Philip
On Dec 4, 2010, at 1:02 PM, Wolfram Sang wrote:
> Hi,
>
> minor comments in addition to Nicolas:
>
> On Fri, Dec 03, 2010 at 11:26:50AM -0800, Philip Rakity wrote:
>
>> hardware clock gating is enabled by setting the mmc quirk
>
> It's not a quirk, it's a capability :)
>
>> MMC_CAP_CLOCK_GATING_HW
>
> Why not MMC_CAP_HW_CLOCK_GATING? Might be a mileage, though...
>
> Regards,
>
> Wolfram
>
> --
> Pengutronix e.K. | Wolfram Sang |
> Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2010-12-06 1:48 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-12-03 19:26 [PATCH 1/3 ] mmc: add support for h/w clock gating of sd controller Philip Rakity
2010-12-03 22:18 ` Nicolas Pitre
2010-12-04 21:02 ` Wolfram Sang
2010-12-06 1:48 ` Philip Rakity
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox