[RFC PATCH] clk: samsung: add support for multiple clock providers

Rahul Sharma r.sh.open at gmail.com
Mon Dec 2 09:49:52 EST 2013


Thanks Tomasz,

On 2 December 2013 19:39, Tomasz Figa <t.figa at samsung.com> wrote:
> Hi Rahul,
>
> On Monday 02 of December 2013 11:25:16 Rahul Sharma wrote:
>> Samsung CCF helper functions doesn't provide support to
>> register multiple Clock Providers for a given SoC. Due to
>> this limitation soc platforms are not able to use these
>> helpers for registering multiple clock providers and forced
>> to bypass this layer.
>
> This might make sense indeed, but I don't see any use cases for it
> at the moment. Do you have anything in particular in mind?
>

We had 2 clock providers (cmu and audss ) in 5420. In 5260, we had
12 CMUs (top, egl, kfc, aud ...) which are physically independent and
mapped at non-contiguous phy-addresses. I am going to post the basic
patch set to add support for 5260 including clock file, which based on the
following RFC patch.

> Also this is somehow ugly to require passing device_node to every function
> even when DT is not used. Instead, I would make samsung_clk_init() return
> the context pointer, which would be then passed to other functions. This
> would also eliminate the need to add private infrastructure mapping nodes
> into context pointers.
>

yea correct. Sounds better. I will change it as you suggested.

> One more thing is the name of clk_provider_context struct. It sounds too
> generic for a Samsung specific structure. IMHO samsung_clk_provider would
> be much better.

I named it simple as it is already defined in samsung/clk.c.
samsung_clk_provider
also seems good to me.

regards,
Rahul Sharma.

>
> Best regards,
> Tomasz
>
>>
>> This layer is modified accordingly to enable the support.
>>
>> Clockfile for exynos4, exynos5250, exynos5420.c and
>> exynos5440 are also modified as per changed helper functions.
>>
>> Signed-off-by: Rahul Sharma <rahul.sharma at samsung.com>
>> ---
>> This patch is based on the following series from
>> Tomasz Figa <t.figa at samsung.com>:
>> http://www.spinics.net/lists/arm-kernel/msg280223.html
>>
>> It is rebased on clk-for-linus-3.13 branch in mike's tree.
>>
>>  drivers/clk/samsung/clk-exynos4.c    |   42 ++++-----
>>  drivers/clk/samsung/clk-exynos5250.c |   19 ++--
>>  drivers/clk/samsung/clk-exynos5420.c |   17 ++--
>>  drivers/clk/samsung/clk-exynos5440.c |   12 +--
>>  drivers/clk/samsung/clk-pll.c        |   14 +--
>>  drivers/clk/samsung/clk-s3c64xx.c    |   37 ++++----
>>  drivers/clk/samsung/clk.c            |  163 ++++++++++++++++++++++++----------
>>  drivers/clk/samsung/clk.h            |   26 +++---
>>  8 files changed, 205 insertions(+), 125 deletions(-)
>>
>> diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
>> index ca2a940..b226544 100644
>> --- a/drivers/clk/samsung/clk-exynos4.c
>> +++ b/drivers/clk/samsung/clk-exynos4.c
>> @@ -1093,7 +1093,7 @@ static unsigned long exynos4_get_xom(void)
>>       return xom;
>>  }
>>
>> -static void __init exynos4_clk_register_finpll(void)
>> +static void __init exynos4_clk_register_finpll(struct device_node *np)
>>  {
>>       struct samsung_fixed_rate_clock fclk;
>>       struct clk *clk;
>> @@ -1116,7 +1116,7 @@ static void __init exynos4_clk_register_finpll(void)
>>       fclk.parent_name = NULL;
>>       fclk.flags = CLK_IS_ROOT;
>>       fclk.fixed_rate = finpll_f;
>> -     samsung_clk_register_fixed_rate(&fclk, 1);
>> +     samsung_clk_register_fixed_rate(np, &fclk, 1);
>>
>>  }
>>
>> @@ -1234,14 +1234,14 @@ static void __init exynos4_clk_init(struct device_node *np,
>>
>>       samsung_clk_init(np, reg_base, nr_clks);
>>
>> -     samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks,
>> +     samsung_clk_of_register_fixed_ext(np, exynos4_fixed_rate_ext_clks,
>>                       ARRAY_SIZE(exynos4_fixed_rate_ext_clks),
>>                       ext_clk_match);
>>
>> -     exynos4_clk_register_finpll();
>> +     exynos4_clk_register_finpll(np);
>>
>>       if (exynos4_soc == EXYNOS4210) {
>> -             samsung_clk_register_mux(exynos4210_mux_early,
>> +             samsung_clk_register_mux(np, exynos4210_mux_early,
>>                                       ARRAY_SIZE(exynos4210_mux_early));
>>
>>               if (_get_rate("fin_pll") == 24000000) {
>> @@ -1255,7 +1255,7 @@ static void __init exynos4_clk_init(struct device_node *np,
>>                       exynos4210_plls[vpll].rate_table =
>>                                                       exynos4210_vpll_rates;
>>
>> -             samsung_clk_register_pll(exynos4210_plls,
>> +             samsung_clk_register_pll(np, exynos4210_plls,
>>                                       ARRAY_SIZE(exynos4210_plls), reg_base);
>>       } else {
>>               if (_get_rate("fin_pll") == 24000000) {
>> @@ -1267,42 +1267,42 @@ static void __init exynos4_clk_init(struct device_node *np,
>>                                                       exynos4x12_vpll_rates;
>>               }
>>
>> -             samsung_clk_register_pll(exynos4x12_plls,
>> +             samsung_clk_register_pll(np, exynos4x12_plls,
>>                                       ARRAY_SIZE(exynos4x12_plls), reg_base);
>>       }
>>
>> -     samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
>> +     samsung_clk_register_fixed_rate(np, exynos4_fixed_rate_clks,
>>                       ARRAY_SIZE(exynos4_fixed_rate_clks));
>> -     samsung_clk_register_mux(exynos4_mux_clks,
>> +     samsung_clk_register_mux(np, exynos4_mux_clks,
>>                       ARRAY_SIZE(exynos4_mux_clks));
>> -     samsung_clk_register_div(exynos4_div_clks,
>> +     samsung_clk_register_div(np, exynos4_div_clks,
>>                       ARRAY_SIZE(exynos4_div_clks));
>> -     samsung_clk_register_gate(exynos4_gate_clks,
>> +     samsung_clk_register_gate(np, exynos4_gate_clks,
>>                       ARRAY_SIZE(exynos4_gate_clks));
>>
>>       if (exynos4_soc == EXYNOS4210) {
>> -             samsung_clk_register_fixed_rate(exynos4210_fixed_rate_clks,
>> +             samsung_clk_register_fixed_rate(np, exynos4210_fixed_rate_clks,
>>                       ARRAY_SIZE(exynos4210_fixed_rate_clks));
>> -             samsung_clk_register_mux(exynos4210_mux_clks,
>> +             samsung_clk_register_mux(np, exynos4210_mux_clks,
>>                       ARRAY_SIZE(exynos4210_mux_clks));
>> -             samsung_clk_register_div(exynos4210_div_clks,
>> +             samsung_clk_register_div(np, exynos4210_div_clks,
>>                       ARRAY_SIZE(exynos4210_div_clks));
>> -             samsung_clk_register_gate(exynos4210_gate_clks,
>> +             samsung_clk_register_gate(np, exynos4210_gate_clks,
>>                       ARRAY_SIZE(exynos4210_gate_clks));
>> -             samsung_clk_register_alias(exynos4210_aliases,
>> +             samsung_clk_register_alias(np, exynos4210_aliases,
>>                       ARRAY_SIZE(exynos4210_aliases));
>>       } else {
>> -             samsung_clk_register_mux(exynos4x12_mux_clks,
>> +             samsung_clk_register_mux(np, exynos4x12_mux_clks,
>>                       ARRAY_SIZE(exynos4x12_mux_clks));
>> -             samsung_clk_register_div(exynos4x12_div_clks,
>> +             samsung_clk_register_div(np, exynos4x12_div_clks,
>>                       ARRAY_SIZE(exynos4x12_div_clks));
>> -             samsung_clk_register_gate(exynos4x12_gate_clks,
>> +             samsung_clk_register_gate(np, exynos4x12_gate_clks,
>>                       ARRAY_SIZE(exynos4x12_gate_clks));
>> -             samsung_clk_register_alias(exynos4x12_aliases,
>> +             samsung_clk_register_alias(np, exynos4x12_aliases,
>>                       ARRAY_SIZE(exynos4x12_aliases));
>>       }
>>
>> -     samsung_clk_register_alias(exynos4_aliases,
>> +     samsung_clk_register_alias(np, exynos4_aliases,
>>                       ARRAY_SIZE(exynos4_aliases));
>>
>>       exynos4_clk_sleep_init();
>> diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
>> index 82f14e1..1785a3d 100644
>> --- a/drivers/clk/samsung/clk-exynos5250.c
>> +++ b/drivers/clk/samsung/clk-exynos5250.c
>> @@ -592,10 +592,10 @@ static void __init exynos5250_clk_init(struct device_node *np)
>>       }
>>
>>       samsung_clk_init(np, reg_base, nr_clks);
>> -     samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
>> +     samsung_clk_of_register_fixed_ext(np, exynos5250_fixed_rate_ext_clks,
>>                       ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
>>                       ext_clk_match);
>> -     samsung_clk_register_mux(exynos5250_pll_pmux_clks,
>> +     samsung_clk_register_mux(np, exynos5250_pll_pmux_clks,
>>                               ARRAY_SIZE(exynos5250_pll_pmux_clks));
>>
>>       if (_get_rate("fin_pll") == 24 * MHZ)
>> @@ -604,17 +604,18 @@ static void __init exynos5250_clk_init(struct device_node *np)
>>       if (_get_rate("mout_vpllsrc") == 24 * MHZ)
>>               exynos5250_plls[vpll].rate_table =  vpll_24mhz_tbl;
>>
>> -     samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls),
>> -                                     reg_base);
>> -     samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
>> +     samsung_clk_register_pll(np, exynos5250_plls,
>> +                     ARRAY_SIZE(exynos5250_plls),
>> +                     reg_base);
>> +     samsung_clk_register_fixed_rate(np, exynos5250_fixed_rate_clks,
>>                       ARRAY_SIZE(exynos5250_fixed_rate_clks));
>> -     samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks,
>> +     samsung_clk_register_fixed_factor(np, exynos5250_fixed_factor_clks,
>>                       ARRAY_SIZE(exynos5250_fixed_factor_clks));
>> -     samsung_clk_register_mux(exynos5250_mux_clks,
>> +     samsung_clk_register_mux(np, exynos5250_mux_clks,
>>                       ARRAY_SIZE(exynos5250_mux_clks));
>> -     samsung_clk_register_div(exynos5250_div_clks,
>> +     samsung_clk_register_div(np, exynos5250_div_clks,
>>                       ARRAY_SIZE(exynos5250_div_clks));
>> -     samsung_clk_register_gate(exynos5250_gate_clks,
>> +     samsung_clk_register_gate(np, exynos5250_gate_clks,
>>                       ARRAY_SIZE(exynos5250_gate_clks));
>>
>>       exynos5250_clk_sleep_init();
>> diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
>> index 9de5bfd..44327e3 100644
>> --- a/drivers/clk/samsung/clk-exynos5420.c
>> +++ b/drivers/clk/samsung/clk-exynos5420.c
>> @@ -817,20 +817,21 @@ static void __init exynos5420_clk_init(struct device_node *np)
>>       }
>>
>>       samsung_clk_init(np, reg_base, nr_clks);
>> -     samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
>> +     samsung_clk_of_register_fixed_ext(np, exynos5420_fixed_rate_ext_clks,
>>                       ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
>>                       ext_clk_match);
>> -     samsung_clk_register_pll(exynos5420_plls, ARRAY_SIZE(exynos5420_plls),
>> -                                     reg_base);
>> -     samsung_clk_register_fixed_rate(exynos5420_fixed_rate_clks,
>> +     samsung_clk_register_pll(np, exynos5420_plls,
>> +                     ARRAY_SIZE(exynos5420_plls),
>> +                     reg_base);
>> +     samsung_clk_register_fixed_rate(np, exynos5420_fixed_rate_clks,
>>                       ARRAY_SIZE(exynos5420_fixed_rate_clks));
>> -     samsung_clk_register_fixed_factor(exynos5420_fixed_factor_clks,
>> +     samsung_clk_register_fixed_factor(np, exynos5420_fixed_factor_clks,
>>                       ARRAY_SIZE(exynos5420_fixed_factor_clks));
>> -     samsung_clk_register_mux(exynos5420_mux_clks,
>> +     samsung_clk_register_mux(np, exynos5420_mux_clks,
>>                       ARRAY_SIZE(exynos5420_mux_clks));
>> -     samsung_clk_register_div(exynos5420_div_clks,
>> +     samsung_clk_register_div(np, exynos5420_div_clks,
>>                       ARRAY_SIZE(exynos5420_div_clks));
>> -     samsung_clk_register_gate(exynos5420_gate_clks,
>> +     samsung_clk_register_gate(np, exynos5420_gate_clks,
>>                       ARRAY_SIZE(exynos5420_gate_clks));
>>
>>       exynos5420_clk_sleep_init();
>> diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c
>> index e3e460a..ef90bb7 100644
>> --- a/drivers/clk/samsung/clk-exynos5440.c
>> +++ b/drivers/clk/samsung/clk-exynos5440.c
>> @@ -115,21 +115,21 @@ static void __init exynos5440_clk_init(struct device_node *np)
>>       }
>>
>>       samsung_clk_init(np, reg_base, nr_clks);
>> -     samsung_clk_of_register_fixed_ext(exynos5440_fixed_rate_ext_clks,
>> +     samsung_clk_of_register_fixed_ext(np, exynos5440_fixed_rate_ext_clks,
>>               ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match);
>>
>>       samsung_clk_register_pll2550x("cplla", "xtal", reg_base + 0x1c, 0x10);
>>       samsung_clk_register_pll2550x("cpllb", "xtal", reg_base + 0x20, 0x10);
>>
>> -     samsung_clk_register_fixed_rate(exynos5440_fixed_rate_clks,
>> +     samsung_clk_register_fixed_rate(np, exynos5440_fixed_rate_clks,
>>                       ARRAY_SIZE(exynos5440_fixed_rate_clks));
>> -     samsung_clk_register_fixed_factor(exynos5440_fixed_factor_clks,
>> +     samsung_clk_register_fixed_factor(np, exynos5440_fixed_factor_clks,
>>                       ARRAY_SIZE(exynos5440_fixed_factor_clks));
>> -     samsung_clk_register_mux(exynos5440_mux_clks,
>> +     samsung_clk_register_mux(np, exynos5440_mux_clks,
>>                       ARRAY_SIZE(exynos5440_mux_clks));
>> -     samsung_clk_register_div(exynos5440_div_clks,
>> +     samsung_clk_register_div(np, exynos5440_div_clks,
>>                       ARRAY_SIZE(exynos5440_div_clks));
>> -     samsung_clk_register_gate(exynos5440_gate_clks,
>> +     samsung_clk_register_gate(np, exynos5440_gate_clks,
>>                       ARRAY_SIZE(exynos5440_gate_clks));
>>
>>       pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk"));
>> diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
>> index 529e11d..5b4228e 100644
>> --- a/drivers/clk/samsung/clk-pll.c
>> +++ b/drivers/clk/samsung/clk-pll.c
>> @@ -710,8 +710,9 @@ struct clk * __init samsung_clk_register_pll2550x(const char *name,
>>       return clk;
>>  }
>>
>> -static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
>> -                                             void __iomem *base)
>> +static void __init _samsung_clk_register_pll(struct device_node *np,
>> +                             struct samsung_pll_clock *pll_clk,
>> +                             void __iomem *base)
>>  {
>>       struct samsung_clk_pll *pll;
>>       struct clk *clk;
>> @@ -804,7 +805,7 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
>>               return;
>>       }
>>
>> -     samsung_clk_add_lookup(clk, pll_clk->id);
>> +     samsung_clk_add_lookup(np, clk, pll_clk->id);
>>
>>       if (!pll_clk->alias)
>>               return;
>> @@ -815,11 +816,12 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
>>                       __func__, pll_clk->name, ret);
>>  }
>>
>> -void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list,
>> -                             unsigned int nr_pll, void __iomem *base)
>> +void __init samsung_clk_register_pll(struct device_node *np,
>> +                     struct samsung_pll_clock *pll_list,
>> +                     unsigned int nr_pll, void __iomem *base)
>>  {
>>       int cnt;
>>
>>       for (cnt = 0; cnt < nr_pll; cnt++)
>> -             _samsung_clk_register_pll(&pll_list[cnt], base);
>> +             _samsung_clk_register_pll(np, &pll_list[cnt], base);
>>  }
>> diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c
>> index a43cbde..b12050f 100644
>> --- a/drivers/clk/samsung/clk-s3c64xx.c
>> +++ b/drivers/clk/samsung/clk-s3c64xx.c
>> @@ -442,12 +442,13 @@ static struct samsung_clock_alias s3c6410_clock_aliases[] = {
>>       ALIAS(MEM0_SROM, NULL, "srom"),
>>  };
>>
>> -static void __init s3c64xx_clk_register_fixed_ext(unsigned long fin_pll_f,
>> -                                                     unsigned long xusbxti_f)
>> +static void __init s3c64xx_clk_register_fixed_ext(struct device_node *np,
>> +                                     unsigned long fin_pll_f,
>> +                                     unsigned long xusbxti_f)
>>  {
>>       s3c64xx_fixed_rate_ext_clks[0].fixed_rate = fin_pll_f;
>>       s3c64xx_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f;
>> -     samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_ext_clks,
>> +     samsung_clk_register_fixed_rate(np, s3c64xx_fixed_rate_ext_clks,
>>                               ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks));
>>  }
>>
>> @@ -469,44 +470,44 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
>>
>>       /* Register external clocks. */
>>       if (!np)
>> -             s3c64xx_clk_register_fixed_ext(xtal_f, xusbxti_f);
>> +             s3c64xx_clk_register_fixed_ext(np, xtal_f, xusbxti_f);
>>
>>       /* Register PLLs. */
>> -     samsung_clk_register_pll(s3c64xx_pll_clks,
>> +     samsung_clk_register_pll(np, s3c64xx_pll_clks,
>>                               ARRAY_SIZE(s3c64xx_pll_clks), reg_base);
>>
>>       /* Register common internal clocks. */
>> -     samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_clks,
>> +     samsung_clk_register_fixed_rate(np, s3c64xx_fixed_rate_clks,
>>                                       ARRAY_SIZE(s3c64xx_fixed_rate_clks));
>> -     samsung_clk_register_mux(s3c64xx_mux_clks,
>> +     samsung_clk_register_mux(np, s3c64xx_mux_clks,
>>                                       ARRAY_SIZE(s3c64xx_mux_clks));
>> -     samsung_clk_register_div(s3c64xx_div_clks,
>> +     samsung_clk_register_div(np, s3c64xx_div_clks,
>>                                       ARRAY_SIZE(s3c64xx_div_clks));
>> -     samsung_clk_register_gate(s3c64xx_gate_clks,
>> +     samsung_clk_register_gate(np, s3c64xx_gate_clks,
>>                                       ARRAY_SIZE(s3c64xx_gate_clks));
>>
>>       /* Register SoC-specific clocks. */
>>       if (is_s3c6400) {
>> -             samsung_clk_register_mux(s3c6400_mux_clks,
>> +             samsung_clk_register_mux(np, s3c6400_mux_clks,
>>                                       ARRAY_SIZE(s3c6400_mux_clks));
>> -             samsung_clk_register_div(s3c6400_div_clks,
>> +             samsung_clk_register_div(np, s3c6400_div_clks,
>>                                       ARRAY_SIZE(s3c6400_div_clks));
>> -             samsung_clk_register_gate(s3c6400_gate_clks,
>> +             samsung_clk_register_gate(np, s3c6400_gate_clks,
>>                                       ARRAY_SIZE(s3c6400_gate_clks));
>> -             samsung_clk_register_alias(s3c6400_clock_aliases,
>> +             samsung_clk_register_alias(np, s3c6400_clock_aliases,
>>                                       ARRAY_SIZE(s3c6400_clock_aliases));
>>       } else {
>> -             samsung_clk_register_mux(s3c6410_mux_clks,
>> +             samsung_clk_register_mux(np, s3c6410_mux_clks,
>>                                       ARRAY_SIZE(s3c6410_mux_clks));
>> -             samsung_clk_register_div(s3c6410_div_clks,
>> +             samsung_clk_register_div(np, s3c6410_div_clks,
>>                                       ARRAY_SIZE(s3c6410_div_clks));
>> -             samsung_clk_register_gate(s3c6410_gate_clks,
>> +             samsung_clk_register_gate(np, s3c6410_gate_clks,
>>                                       ARRAY_SIZE(s3c6410_gate_clks));
>> -             samsung_clk_register_alias(s3c6410_clock_aliases,
>> +             samsung_clk_register_alias(np, s3c6410_clock_aliases,
>>                                       ARRAY_SIZE(s3c6410_clock_aliases));
>>       }
>>
>> -     samsung_clk_register_alias(s3c64xx_clock_aliases,
>> +     samsung_clk_register_alias(np, s3c64xx_clock_aliases,
>>                                       ARRAY_SIZE(s3c64xx_clock_aliases));
>>       s3c64xx_clk_sleep_init();
>>
>> diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
>> index 91bec3e..a6fad4f 100644
>> --- a/drivers/clk/samsung/clk.c
>> +++ b/drivers/clk/samsung/clk.c
>> @@ -15,11 +15,15 @@
>>  #include "clk.h"
>>
>>  static DEFINE_SPINLOCK(lock);
>> -static struct clk **clk_table;
>> -static void __iomem *reg_base;
>> -#ifdef CONFIG_OF
>> -static struct clk_onecell_data clk_data;
>> -#endif
>> +static LIST_HEAD(clk_provider_list);
>> +
>> +/* Context node which holds information about the clock provider. */
>> +struct clk_provider_context {
>> +     struct list_head node;
>> +     struct device_node *of_node;
>> +     void __iomem *reg_base;
>> +     struct clk_onecell_data clk_data;
>> +};
>>
>>  void samsung_clk_save(void __iomem *base,
>>                                   struct samsung_clk_reg_dump *rd,
>> @@ -58,37 +62,77 @@ struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
>>  void __init samsung_clk_init(struct device_node *np, void __iomem *base,
>>                            unsigned long nr_clks)
>>  {
>> -     reg_base = base;
>> +     struct clk_provider_context *ctx;
>> +     struct clk **clk_table;
>> +     int ret;
>> +
>> +     if (!np)
>> +             return;
>> +
>> +     ctx = kzalloc(sizeof(struct clk_provider_context), GFP_KERNEL);
>> +     if (!ctx)
>> +             panic("could not allocate clock provider context.\n");
>>
>>       clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL);
>>       if (!clk_table)
>>               panic("could not allocate clock lookup table\n");
>>
>> -     if (!np)
>> -             return;
>> +     ctx->of_node = np;
>> +     ctx->reg_base = base;
>> +     ctx->clk_data.clks = clk_table;
>> +     ctx->clk_data.clk_num = nr_clks;
>>
>> -#ifdef CONFIG_OF
>> -     clk_data.clks = clk_table;
>> -     clk_data.clk_num = nr_clks;
>> -     of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
>> -#endif
>> +     ret = of_clk_add_provider(np, of_clk_src_onecell_get,
>> +                     &ctx->clk_data);
>> +     if (ret)
>> +             panic("could not register clock provide\n");
>> +
>> +     list_add_tail(&ctx->node, &clk_provider_list);
>> +}
>> +
>> +/* static helper function to extract the context from node pointer */
>> +static struct clk_provider_context *_get_clock_provider(struct device_node *np)
>> +{
>> +     struct clk_provider_context *ctx;
>> +
>> +     list_for_each_entry(ctx, &clk_provider_list, node)
>> +             if (ctx->of_node == np)
>> +                     return ctx;
>> +     return NULL;
>>  }
>>
>>  /* add a clock instance to the clock lookup table used for dt based lookup */
>> -void samsung_clk_add_lookup(struct clk *clk, unsigned int id)
>> +void samsung_clk_add_lookup(struct device_node *np, struct clk *clk,
>> +                             unsigned int id)
>>  {
>> -     if (clk_table && id)
>> -             clk_table[id] = clk;
>> +     struct clk_provider_context *ctx;
>> +
>> +     ctx = _get_clock_provider(np);
>> +     if (!ctx) {
>> +             pr_err("invalid node pointer.\n");
>> +             return;
>> +     }
>> +
>> +     if (ctx->clk_data.clks && id)
>> +             ctx->clk_data.clks[id] = clk;
>>  }
>>
>>  /* register a list of aliases */
>> -void __init samsung_clk_register_alias(struct samsung_clock_alias *list,
>> -                                     unsigned int nr_clk)
>> +void __init samsung_clk_register_alias(struct device_node *np,
>> +                             struct samsung_clock_alias *list,
>> +                             unsigned int nr_clk)
>>  {
>> +     struct clk_provider_context *ctx;
>>       struct clk *clk;
>>       unsigned int idx, ret;
>>
>> -     if (!clk_table) {
>> +     ctx = _get_clock_provider(np);
>> +     if (!ctx) {
>> +             pr_err("invalid node pointer.\n");
>> +             return;
>> +     }
>> +
>> +     if (!ctx->clk_data.clks) {
>>               pr_err("%s: clock table missing\n", __func__);
>>               return;
>>       }
>> @@ -100,7 +144,7 @@ void __init samsung_clk_register_alias(struct samsung_clock_alias *list,
>>                       continue;
>>               }
>>
>> -             clk = clk_table[list->id];
>> +             clk = ctx->clk_data.clks[list->id];
>>               if (!clk) {
>>                       pr_err("%s: failed to find clock %d\n", __func__,
>>                               list->id);
>> @@ -115,7 +159,7 @@ void __init samsung_clk_register_alias(struct samsung_clock_alias *list,
>>  }
>>
>>  /* register a list of fixed clocks */
>> -void __init samsung_clk_register_fixed_rate(
>> +void __init samsung_clk_register_fixed_rate(struct device_node *np,
>>               struct samsung_fixed_rate_clock *list, unsigned int nr_clk)
>>  {
>>       struct clk *clk;
>> @@ -130,7 +174,7 @@ void __init samsung_clk_register_fixed_rate(
>>                       continue;
>>               }
>>
>> -             samsung_clk_add_lookup(clk, list->id);
>> +             samsung_clk_add_lookup(np, clk, list->id);
>>
>>               /*
>>                * Unconditionally add a clock lookup for the fixed rate clocks.
>> @@ -144,7 +188,7 @@ void __init samsung_clk_register_fixed_rate(
>>  }
>>
>>  /* register a list of fixed factor clocks */
>> -void __init samsung_clk_register_fixed_factor(
>> +void __init samsung_clk_register_fixed_factor(struct device_node *np,
>>               struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
>>  {
>>       struct clk *clk;
>> @@ -159,20 +203,29 @@ void __init samsung_clk_register_fixed_factor(
>>                       continue;
>>               }
>>
>> -             samsung_clk_add_lookup(clk, list->id);
>> +             samsung_clk_add_lookup(np, clk, list->id);
>>       }
>>  }
>>
>>  /* register a list of mux clocks */
>> -void __init samsung_clk_register_mux(struct samsung_mux_clock *list,
>> -                                     unsigned int nr_clk)
>> +void __init samsung_clk_register_mux(struct device_node *np,
>> +                             struct samsung_mux_clock *list,
>> +                             unsigned int nr_clk)
>>  {
>> +     struct clk_provider_context *ctx;
>>       struct clk *clk;
>>       unsigned int idx, ret;
>>
>> +     ctx = _get_clock_provider(np);
>> +     if (!ctx) {
>> +             pr_err("invalid node pointer.\n");
>> +             return;
>> +     }
>> +
>>       for (idx = 0; idx < nr_clk; idx++, list++) {
>>               clk = clk_register_mux(NULL, list->name, list->parent_names,
>> -                     list->num_parents, list->flags, reg_base + list->offset,
>> +                     list->num_parents, list->flags,
>> +                     ctx->reg_base + list->offset,
>>                       list->shift, list->width, list->mux_flags, &lock);
>>               if (IS_ERR(clk)) {
>>                       pr_err("%s: failed to register clock %s\n", __func__,
>> @@ -180,7 +233,7 @@ void __init samsung_clk_register_mux(struct samsung_mux_clock *list,
>>                       continue;
>>               }
>>
>> -             samsung_clk_add_lookup(clk, list->id);
>> +             samsung_clk_add_lookup(np, clk, list->id);
>>
>>               /* register a clock lookup only if a clock alias is specified */
>>               if (list->alias) {
>> @@ -194,31 +247,39 @@ void __init samsung_clk_register_mux(struct samsung_mux_clock *list,
>>  }
>>
>>  /* register a list of div clocks */
>> -void __init samsung_clk_register_div(struct samsung_div_clock *list,
>> -                                     unsigned int nr_clk)
>> +void __init samsung_clk_register_div(struct device_node *np,
>> +                             struct samsung_div_clock *list,
>> +                             unsigned int nr_clk)
>>  {
>> +     struct clk_provider_context *ctx;
>>       struct clk *clk;
>>       unsigned int idx, ret;
>>
>> +     ctx = _get_clock_provider(np);
>> +     if (!ctx) {
>> +             pr_err("invalid node pointer.\n");
>> +             return;
>> +     }
>> +
>>       for (idx = 0; idx < nr_clk; idx++, list++) {
>>               if (list->table)
>>                       clk = clk_register_divider_table(NULL, list->name,
>> -                                     list->parent_name, list->flags,
>> -                                     reg_base + list->offset, list->shift,
>> -                                     list->width, list->div_flags,
>> -                                     list->table, &lock);
>> +                             list->parent_name, list->flags,
>> +                             ctx->reg_base + list->offset,
>> +                             list->shift, list->width, list->div_flags,
>> +                             list->table, &lock);
>>               else
>>                       clk = clk_register_divider(NULL, list->name,
>> -                                     list->parent_name, list->flags,
>> -                                     reg_base + list->offset, list->shift,
>> -                                     list->width, list->div_flags, &lock);
>> +                             list->parent_name, list->flags,
>> +                             ctx->reg_base + list->offset, list->shift,
>> +                             list->width, list->div_flags, &lock);
>>               if (IS_ERR(clk)) {
>>                       pr_err("%s: failed to register clock %s\n", __func__,
>>                               list->name);
>>                       continue;
>>               }
>>
>> -             samsung_clk_add_lookup(clk, list->id);
>> +             samsung_clk_add_lookup(np, clk, list->id);
>>
>>               /* register a clock lookup only if a clock alias is specified */
>>               if (list->alias) {
>> @@ -232,15 +293,23 @@ void __init samsung_clk_register_div(struct samsung_div_clock *list,
>>  }
>>
>>  /* register a list of gate clocks */
>> -void __init samsung_clk_register_gate(struct samsung_gate_clock *list,
>> -                                             unsigned int nr_clk)
>> +void __init samsung_clk_register_gate(struct device_node *np,
>> +                             struct samsung_gate_clock *list,
>> +                             unsigned int nr_clk)
>>  {
>> +     struct clk_provider_context *ctx;
>>       struct clk *clk;
>>       unsigned int idx, ret;
>>
>> +     ctx = _get_clock_provider(np);
>> +     if (!ctx) {
>> +             pr_err("invalid node pointer.\n");
>> +             return;
>> +     }
>> +
>>       for (idx = 0; idx < nr_clk; idx++, list++) {
>>               clk = clk_register_gate(NULL, list->name, list->parent_name,
>> -                             list->flags, reg_base + list->offset,
>> +                             list->flags, ctx->reg_base + list->offset,
>>                               list->bit_idx, list->gate_flags, &lock);
>>               if (IS_ERR(clk)) {
>>                       pr_err("%s: failed to register clock %s\n", __func__,
>> @@ -257,7 +326,7 @@ void __init samsung_clk_register_gate(struct samsung_gate_clock *list,
>>                                       __func__, list->alias);
>>               }
>>
>> -             samsung_clk_add_lookup(clk, list->id);
>> +             samsung_clk_add_lookup(np, clk, list->id);
>>       }
>>  }
>>
>> @@ -266,21 +335,21 @@ void __init samsung_clk_register_gate(struct samsung_gate_clock *list,
>>   * tree and register it
>>   */
>>  #ifdef CONFIG_OF
>> -void __init samsung_clk_of_register_fixed_ext(
>> +void __init samsung_clk_of_register_fixed_ext(struct device_node *np,
>>                       struct samsung_fixed_rate_clock *fixed_rate_clk,
>>                       unsigned int nr_fixed_rate_clk,
>>                       struct of_device_id *clk_matches)
>>  {
>>       const struct of_device_id *match;
>> -     struct device_node *np;
>> +     struct device_node *clk_np;
>>       u32 freq;
>>
>> -     for_each_matching_node_and_match(np, clk_matches, &match) {
>> -             if (of_property_read_u32(np, "clock-frequency", &freq))
>> +     for_each_matching_node_and_match(clk_np, clk_matches, &match) {
>> +             if (of_property_read_u32(clk_np, "clock-frequency", &freq))
>>                       continue;
>>               fixed_rate_clk[(u32)match->data].fixed_rate = freq;
>>       }
>> -     samsung_clk_register_fixed_rate(fixed_rate_clk, nr_fixed_rate_clk);
>> +     samsung_clk_register_fixed_rate(np, fixed_rate_clk, nr_fixed_rate_clk);
>>  }
>>  #endif
>>
>> diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
>> index c7141ba..620f7b8 100644
>> --- a/drivers/clk/samsung/clk.h
>> +++ b/drivers/clk/samsung/clk.h
>> @@ -315,26 +315,32 @@ struct samsung_pll_clock {
>>  extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
>>                                   unsigned long nr_clks);
>>  extern void __init samsung_clk_of_register_fixed_ext(
>> +             struct device_node *np,
>>               struct samsung_fixed_rate_clock *fixed_rate_clk,
>>               unsigned int nr_fixed_rate_clk,
>>               struct of_device_id *clk_matches);
>>
>> -extern void samsung_clk_add_lookup(struct clk *clk, unsigned int id);
>> +extern void samsung_clk_add_lookup(struct device_node *np,
>> +                     struct clk *clk, unsigned int id);
>>
>> -extern void samsung_clk_register_alias(struct samsung_clock_alias *list,
>> -             unsigned int nr_clk);
>> -extern void __init samsung_clk_register_fixed_rate(
>> +extern void samsung_clk_register_alias(struct device_node *np,
>> +                     struct samsung_clock_alias *list,
>> +                     unsigned int nr_clk);
>> +extern void __init samsung_clk_register_fixed_rate(struct device_node *np,
>>               struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk);
>> -extern void __init samsung_clk_register_fixed_factor(
>> +extern void __init samsung_clk_register_fixed_factor(struct device_node *np,
>>               struct samsung_fixed_factor_clock *list, unsigned int nr_clk);
>> -extern void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
>> +extern void __init samsung_clk_register_mux(struct device_node *np,
>> +             struct samsung_mux_clock *clk_list,
>>               unsigned int nr_clk);
>> -extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
>> +extern void __init samsung_clk_register_div(struct device_node *np,
>> +             struct samsung_div_clock *clk_list,
>>               unsigned int nr_clk);
>> -extern void __init samsung_clk_register_gate(
>> +extern void __init samsung_clk_register_gate(struct device_node *np,
>>               struct samsung_gate_clock *clk_list, unsigned int nr_clk);
>> -extern void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list,
>> -             unsigned int nr_clk, void __iomem *base);
>> +extern void __init samsung_clk_register_pll(struct device_node *np,
>> +                     struct samsung_pll_clock *pll_list,
>> +                     unsigned int nr_clk, void __iomem *base);
>>
>>  extern unsigned long _get_rate(const char *clk_name);
>>
>>
>



More information about the linux-arm-kernel mailing list