[PATCH V3 2/2] sdhci-s3c: Add support no internal clock divider in host controller

Kyungmin Park kmpark at infradead.org
Sun Oct 10 22:54:36 EDT 2010


On Fri, Oct 8, 2010 at 5:46 PM, Kukjin Kim <kgene.kim at samsung.com> wrote:
> From: Jeongbae Seo <jeongbae.seo at samsung.com>
>
> This patch adds to support no internal clock divider in SDHCI.
> The external clock divider can be used to make a proper clock
> because SDHCI doesn't support internal clock divider by itself.
>
> If external clock divider type is selected, some functions related
> with clock control will be overridened by other functions.
>
> The current clock control index is added to let you know which
> clock bus is used for SDHCI when using overriding functions.
>
> The checking functions is added into sdhci_s3c_consider_clock,
> because clock divider step is different from that of host controller.
>
> Signed-off-by: Jeongbae Seo <jeongbae.seo at samsung.com>
> Cc: Jaehoon Chung <jh80.chung at samsung.com>
> Cc: Ben Dooks <ben-linux at fluff.org>
> Signed-off-by: Kukjin Kim <kgene.kim at samsung.com>
> ---
> Changes since v2:
> - Changed clock control method to overriding from using quirk
> - This patch is referred from that of Jaehoon Chung's support non-standard clock setting

I don't know how to handle this case. Just "CC" the Jaehoon is enough?
>
> Changes since v1:
> - Separated to each topic
>
> NOTE :
> - This patch depends on following.
>  [PATCH 4/5] ARM: SAMSUNG : Add clock types into platform data
>
>  drivers/mmc/host/sdhci-s3c.c |   62 ++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 62 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
> index a7710f5..1720358 100644
> --- a/drivers/mmc/host/sdhci-s3c.c
> +++ b/drivers/mmc/host/sdhci-s3c.c
> @@ -130,6 +130,15 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
>        if (!clksrc)
>                return UINT_MAX;
>
> +       /*
> +        * Clock divider's step is different as 1 from that of host controller
> +        * when 'clk_type' is S3C_SDHCI_CLK_DIV_EXTERNAL.
> +        */
> +       if (ourhost->pdata->clk_type) {
I'm still confusing the 'clk_type" word, if you assume it's just two
values, 0, and 1 at this time. then compare it with CLK_DIV_EXTERNAL.
or change it as clk_exteranl  it's more clear.
> +               rate = clk_round_rate(clksrc, wanted);
> +               return wanted - rate;
> +       }
> +
>        rate = clk_get_rate(clksrc);
>
>        for (div = 1; div < 256; div *= 2) {
> @@ -232,6 +241,42 @@ static unsigned int sdhci_s3c_get_min_clock(struct sdhci_host *host)
>        return min;
>  }
>
> +/* sdhci_cmu_get_max_clk - callback to get maximum clock frequency.*/
> +static unsigned int sdhci_cmu_get_max_clock(struct sdhci_host *host)
> +{
> +       struct sdhci_s3c *ourhost = to_s3c(host);
> +
> +       return clk_round_rate(ourhost->clk_bus[ourhost->cur_clk], UINT_MAX);
> +}
> +
> +/* sdhci_cmu_get_min_clock - callback to get minimal supported clock value. */
> +static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host)
> +{
> +       struct sdhci_s3c *ourhost = to_s3c(host);
> +
> +       /*
> +        * initial clock can be in the frequency range of
> +        * 100KHz-400KHz, so we set it as max value.
> +        */
> +       return clk_round_rate(ourhost->clk_bus[ourhost->cur_clk], 400000);
> +}
> +
> +/* sdhci_cmu_set_clock - callback on clock change.*/
> +static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
> +{
> +       struct sdhci_s3c *ourhost = to_s3c(host);
> +
> +       /* don't bother if the clock is going off */
> +       if (clock == 0)
> +               return;
> +
> +       sdhci_s3c_set_clock(host, clock);
> +
> +       clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);
> +
> +       host->clock = clock;
> +}
> +
>  static struct sdhci_ops sdhci_s3c_ops = {
>        .get_max_clock          = sdhci_s3c_get_max_clk,
>        .set_clock              = sdhci_s3c_set_clock,
> @@ -361,6 +406,13 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
>
>                clks++;
>                sc->clk_bus[ptr] = clk;
> +
> +               /*
> +                * save current clock index to know which clock bus
> +                * is used later in overriding functions.
> +                */
> +               sc->cur_clk = ptr;
> +
>                clk_enable(clk);
>
>                dev_info(dev, "clock source %d: %s (%ld Hz)\n",
> @@ -427,6 +479,16 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
>        /* HSMMC on Samsung SoCs uses SDCLK as timeout clock */
>        host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK;
>
> +       /*
> +        * If controller does not have internal clock divider,
> +        * we can use overriding functions instead of default.
> +        */
> +       if (pdata->clk_type) {
> +               sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock;
> +               sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock;
> +               sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock;
> +       }
> +
>        /* It supports additional host capabilities if needed */
>        if (pdata->host_caps)
>                host->mmc->caps |= pdata->host_caps;
> --
> 1.6.2.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>



More information about the linux-arm-kernel mailing list