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 <[email protected]>
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
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html