diff mbox

[4/7] clk/samsung: add support for multuple clock providers

Message ID 1386345391-23482-5-git-send-email-rahul.sharma@samsung.com (mailing list archive)
State New, archived
Headers show

Commit Message

Rahul Sharma Dec. 6, 2013, 3:56 p.m. UTC
Samsung CCF helper functions do not 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 mulitple clock providers and are
forced to bypass this layer.

This layer is modified acordingly to enable the support.

Clockfile for exynos4, exynos5250, exynos5420, exynos5440
and S3c64xx are also modified as per changed helper functions.

Signed-off-by: Rahul Sharma <rahul.sharma@samsung.com>
---
 drivers/clk/samsung/clk-exynos4.c    |   47 ++++++++-------
 drivers/clk/samsung/clk-exynos5250.c |   26 ++++----
 drivers/clk/samsung/clk-exynos5420.c |   24 +++++---
 drivers/clk/samsung/clk-exynos5440.c |   18 +++---
 drivers/clk/samsung/clk-pll.c        |   14 +++--
 drivers/clk/samsung/clk-s3c64xx.c    |   44 ++++++++------
 drivers/clk/samsung/clk.c            |  110 +++++++++++++++++++---------------
 drivers/clk/samsung/clk.h            |   46 ++++++++++----
 8 files changed, 195 insertions(+), 134 deletions(-)

Comments

Tomasz Figa Dec. 11, 2013, 11:15 a.m. UTC | #1
Hi Rahul,

Please see my comments inline.

On Friday 06 of December 2013 21:26:28 Rahul Sharma wrote:
> Samsung CCF helper functions do not 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 mulitple clock providers and are
> forced to bypass this layer.
> 
> This layer is modified acordingly to enable the support.
> 
> Clockfile for exynos4, exynos5250, exynos5420, exynos5440
> and S3c64xx are also modified as per changed helper functions.
[snip]
> diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
> index 91bec3e..20de446 100644
> --- a/drivers/clk/samsung/clk.c
> +++ b/drivers/clk/samsung/clk.c
> @@ -15,11 +15,6 @@
>  #include "clk.h"
>  
>  static DEFINE_SPINLOCK(lock);

IMHO you can also move the spinlock into samsung_clk_provider struct, to
have more fine grained locking, as you shouldn't need to lock between
particular providers, just multiple requests for one.

> -static struct clk **clk_table;
> -static void __iomem *reg_base;
> -#ifdef CONFIG_OF
> -static struct clk_onecell_data clk_data;
> -#endif
>  
>  void samsung_clk_save(void __iomem *base,
>  				    struct samsung_clk_reg_dump *rd,
> @@ -55,40 +50,53 @@ struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
>  }
>  
>  /* setup the essentials required to support clock lookup using ccf */
> -void __init samsung_clk_init(struct device_node *np, void __iomem *base,
> -			     unsigned long nr_clks)
> +struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np,
> +			void __iomem *base, unsigned long nr_clks)
>  {
> -	reg_base = base;
> +	struct samsung_clk_provider *ctx;
> +	struct clk **clk_table;
> +	int ret;
> +
> +	if (!np)
> +		return NULL;

This check is incorrect. It's completely correct to call this function
with NULL np, when booted without DT and this was handled correctly
before this patch. Please keep the same behavior.

> +
> +	ctx = kzalloc(sizeof(struct samsung_clk_provider), 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->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");
> +
> +	return ctx;
>  }
[snip]
> diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
> index c7141ba..433bab3 100644
> --- a/drivers/clk/samsung/clk.h
> +++ b/drivers/clk/samsung/clk.h
> @@ -21,6 +21,17 @@
>  #include <linux/of_address.h>
>  #include "clk-pll.h"
>  
> +/* Context node which holds information about the clock provider. */
> +/**
> + * struct samsung_clk_provider: information about clock plovider

typo: s/plovider/provider/

> + * @reg_base: virtual address for the register base.
> + * @clk_data: holds clock related data like clk* and number of clocks.
> + */

Why two comments? The kerneldoc one should be enough.

> +struct samsung_clk_provider {
> +	void __iomem *reg_base;
> +	struct clk_onecell_data clk_data;
> +};
> +
>  /**
>   * struct samsung_clock_alias: information about mux clock
>   * @id: platform specific id of the clock.
> @@ -312,29 +323,40 @@ struct samsung_pll_clock {
>  	__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE,	\
>  		_lock, _con, _rtable, _alias)
>  
> -extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
> -				    unsigned long nr_clks);
> +extern struct samsung_clk_provider *__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 samsung_clk_provider *ctx,
>  		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 samsung_clk_provider *ctx,
> +			struct clk *clk, unsigned int id);
>  
> -extern void samsung_clk_register_alias(struct samsung_clock_alias *list,
> -		unsigned int nr_clk);
> +extern void samsung_clk_register_alias(struct samsung_clk_provider *ctx,
> +			struct samsung_clock_alias *list,
> +			unsigned int nr_clk);
>  extern void __init samsung_clk_register_fixed_rate(
> -		struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk);
> +			struct samsung_clk_provider *ctx,
> +			struct samsung_fixed_rate_clock *clk_list,
> +			unsigned int nr_clk);
>  extern void __init samsung_clk_register_fixed_factor(
> -		struct samsung_fixed_factor_clock *list, unsigned int nr_clk);
> -extern void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
> +			struct samsung_clk_provider *ctx,
> +			struct samsung_fixed_factor_clock *list,
> +			unsigned int nr_clk);
> +extern void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
> +		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 samsung_clk_provider *ctx,
> +		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 samsung_clk_provider *ctx,
>  		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 samsung_clk_provider *ctx,
> +			struct samsung_pll_clock *pll_list,
> +			unsigned int nr_clk, void __iomem *base);
>  
>  extern unsigned long _get_rate(const char *clk_name);
>  

nit: Please keep the indentation consistent in all the function prototypes
above.

Best regards,
Tomasz

--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rahul Sharma Jan. 6, 2014, 11:35 a.m. UTC | #2
Hi Tomasz,

On 11 December 2013 16:45, Tomasz Figa <t.figa@samsung.com> wrote:
> Hi Rahul,
>
> Please see my comments inline.
>
> On Friday 06 of December 2013 21:26:28 Rahul Sharma wrote:
>> Samsung CCF helper functions do not 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 mulitple clock providers and are
>> forced to bypass this layer.
>>
>> This layer is modified acordingly to enable the support.
>>
>> Clockfile for exynos4, exynos5250, exynos5420, exynos5440
>> and S3c64xx are also modified as per changed helper functions.
> [snip]
>> diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
>> index 91bec3e..20de446 100644
>> --- a/drivers/clk/samsung/clk.c
>> +++ b/drivers/clk/samsung/clk.c
>> @@ -15,11 +15,6 @@
>>  #include "clk.h"
>>
>>  static DEFINE_SPINLOCK(lock);
>
> IMHO you can also move the spinlock into samsung_clk_provider struct, to
> have more fine grained locking, as you shouldn't need to lock between
> particular providers, just multiple requests for one.
>
Done.

>> -static struct clk **clk_table;
>> -static void __iomem *reg_base;
>> -#ifdef CONFIG_OF
>> -static struct clk_onecell_data clk_data;
>> -#endif
>>
>>  void samsung_clk_save(void __iomem *base,
>>                                   struct samsung_clk_reg_dump *rd,
>> @@ -55,40 +50,53 @@ struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
>>  }
>>
>>  /* setup the essentials required to support clock lookup using ccf */
>> -void __init samsung_clk_init(struct device_node *np, void __iomem *base,
>> -                          unsigned long nr_clks)
>> +struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np,
>> +                     void __iomem *base, unsigned long nr_clks)
>>  {
>> -     reg_base = base;
>> +     struct samsung_clk_provider *ctx;
>> +     struct clk **clk_table;
>> +     int ret;
>> +
>> +     if (!np)
>> +             return NULL;
>
> This check is incorrect. It's completely correct to call this function
> with NULL np, when booted without DT and this was handled correctly
> before this patch. Please keep the same behavior.
>

Done.

>> +
>> +     ctx = kzalloc(sizeof(struct samsung_clk_provider), 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->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");
>> +
>> +     return ctx;
>>  }
> [snip]
>> diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
>> index c7141ba..433bab3 100644
>> --- a/drivers/clk/samsung/clk.h
>> +++ b/drivers/clk/samsung/clk.h
>> @@ -21,6 +21,17 @@
>>  #include <linux/of_address.h>
>>  #include "clk-pll.h"
>>
>> +/* Context node which holds information about the clock provider. */
>> +/**
>> + * struct samsung_clk_provider: information about clock plovider
>
> typo: s/plovider/provider/

Ok.
>
>> + * @reg_base: virtual address for the register base.
>> + * @clk_data: holds clock related data like clk* and number of clocks.
>> + */
>
> Why two comments? The kerneldoc one should be enough.
>
>> +struct samsung_clk_provider {
>> +     void __iomem *reg_base;
>> +     struct clk_onecell_data clk_data;
>> +};
>> +
>>  /**
>>   * struct samsung_clock_alias: information about mux clock
>>   * @id: platform specific id of the clock.
>> @@ -312,29 +323,40 @@ struct samsung_pll_clock {
>>       __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE,     \
>>               _lock, _con, _rtable, _alias)
>>
>> -extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
>> -                                 unsigned long nr_clks);
>> +extern struct samsung_clk_provider *__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 samsung_clk_provider *ctx,
>>               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 samsung_clk_provider *ctx,
>> +                     struct clk *clk, unsigned int id);
>>
>> -extern void samsung_clk_register_alias(struct samsung_clock_alias *list,
>> -             unsigned int nr_clk);
>> +extern void samsung_clk_register_alias(struct samsung_clk_provider *ctx,
>> +                     struct samsung_clock_alias *list,
>> +                     unsigned int nr_clk);
>>  extern void __init samsung_clk_register_fixed_rate(
>> -             struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk);
>> +                     struct samsung_clk_provider *ctx,
>> +                     struct samsung_fixed_rate_clock *clk_list,
>> +                     unsigned int nr_clk);
>>  extern void __init samsung_clk_register_fixed_factor(
>> -             struct samsung_fixed_factor_clock *list, unsigned int nr_clk);
>> -extern void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
>> +                     struct samsung_clk_provider *ctx,
>> +                     struct samsung_fixed_factor_clock *list,
>> +                     unsigned int nr_clk);
>> +extern void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
>> +             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 samsung_clk_provider *ctx,
>> +             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 samsung_clk_provider *ctx,
>>               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 samsung_clk_provider *ctx,
>> +                     struct samsung_pll_clock *pll_list,
>> +                     unsigned int nr_clk, void __iomem *base);
>>
>>  extern unsigned long _get_rate(const char *clk_name);
>>
>
> nit: Please keep the indentation consistent in all the function prototypes
> above.

ok.

regards,
Rahul Sharma.

>
> Best regards,
> Tomasz
>
--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index ca2a940..e634ba9 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 samsung_clk_provider *ctx)
 {
 	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(ctx, &fclk, 1);
 
 }
 
@@ -1226,22 +1226,25 @@  static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = {
 static void __init exynos4_clk_init(struct device_node *np,
 				    enum exynos4_soc soc)
 {
+	struct samsung_clk_provider *ctx;
 	exynos4_soc = soc;
 
 	reg_base = of_iomap(np, 0);
 	if (!reg_base)
 		panic("%s: failed to map registers\n", __func__);
 
-	samsung_clk_init(np, reg_base, nr_clks);
+	ctx = samsung_clk_init(np, reg_base, nr_clks);
+	if (!ctx)
+		panic("%s: unable to allocate context.\n", __func__);
 
-	samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks,
+	samsung_clk_of_register_fixed_ext(ctx, exynos4_fixed_rate_ext_clks,
 			ARRAY_SIZE(exynos4_fixed_rate_ext_clks),
 			ext_clk_match);
 
-	exynos4_clk_register_finpll();
+	exynos4_clk_register_finpll(ctx);
 
 	if (exynos4_soc == EXYNOS4210) {
-		samsung_clk_register_mux(exynos4210_mux_early,
+		samsung_clk_register_mux(ctx, exynos4210_mux_early,
 					ARRAY_SIZE(exynos4210_mux_early));
 
 		if (_get_rate("fin_pll") == 24000000) {
@@ -1255,7 +1258,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(ctx, exynos4210_plls,
 					ARRAY_SIZE(exynos4210_plls), reg_base);
 	} else {
 		if (_get_rate("fin_pll") == 24000000) {
@@ -1267,42 +1270,42 @@  static void __init exynos4_clk_init(struct device_node *np,
 							exynos4x12_vpll_rates;
 		}
 
-		samsung_clk_register_pll(exynos4x12_plls,
+		samsung_clk_register_pll(ctx, exynos4x12_plls,
 					ARRAY_SIZE(exynos4x12_plls), reg_base);
 	}
 
-	samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
+	samsung_clk_register_fixed_rate(ctx, exynos4_fixed_rate_clks,
 			ARRAY_SIZE(exynos4_fixed_rate_clks));
-	samsung_clk_register_mux(exynos4_mux_clks,
+	samsung_clk_register_mux(ctx, exynos4_mux_clks,
 			ARRAY_SIZE(exynos4_mux_clks));
-	samsung_clk_register_div(exynos4_div_clks,
+	samsung_clk_register_div(ctx, exynos4_div_clks,
 			ARRAY_SIZE(exynos4_div_clks));
-	samsung_clk_register_gate(exynos4_gate_clks,
+	samsung_clk_register_gate(ctx, 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(ctx, exynos4210_fixed_rate_clks,
 			ARRAY_SIZE(exynos4210_fixed_rate_clks));
-		samsung_clk_register_mux(exynos4210_mux_clks,
+		samsung_clk_register_mux(ctx, exynos4210_mux_clks,
 			ARRAY_SIZE(exynos4210_mux_clks));
-		samsung_clk_register_div(exynos4210_div_clks,
+		samsung_clk_register_div(ctx, exynos4210_div_clks,
 			ARRAY_SIZE(exynos4210_div_clks));
-		samsung_clk_register_gate(exynos4210_gate_clks,
+		samsung_clk_register_gate(ctx, exynos4210_gate_clks,
 			ARRAY_SIZE(exynos4210_gate_clks));
-		samsung_clk_register_alias(exynos4210_aliases,
+		samsung_clk_register_alias(ctx, exynos4210_aliases,
 			ARRAY_SIZE(exynos4210_aliases));
 	} else {
-		samsung_clk_register_mux(exynos4x12_mux_clks,
+		samsung_clk_register_mux(ctx, exynos4x12_mux_clks,
 			ARRAY_SIZE(exynos4x12_mux_clks));
-		samsung_clk_register_div(exynos4x12_div_clks,
+		samsung_clk_register_div(ctx, exynos4x12_div_clks,
 			ARRAY_SIZE(exynos4x12_div_clks));
-		samsung_clk_register_gate(exynos4x12_gate_clks,
+		samsung_clk_register_gate(ctx, exynos4x12_gate_clks,
 			ARRAY_SIZE(exynos4x12_gate_clks));
-		samsung_clk_register_alias(exynos4x12_aliases,
+		samsung_clk_register_alias(ctx, exynos4x12_aliases,
 			ARRAY_SIZE(exynos4x12_aliases));
 	}
 
-	samsung_clk_register_alias(exynos4_aliases,
+	samsung_clk_register_alias(ctx, 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..af4f7fd 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -583,6 +583,8 @@  static struct of_device_id ext_clk_match[] __initdata = {
 /* register exynox5250 clocks */
 static void __init exynos5250_clk_init(struct device_node *np)
 {
+	struct samsung_clk_provider *ctx;
+
 	if (np) {
 		reg_base = of_iomap(np, 0);
 		if (!reg_base)
@@ -591,11 +593,14 @@  static void __init exynos5250_clk_init(struct device_node *np)
 		panic("%s: unable to determine soc\n", __func__);
 	}
 
-	samsung_clk_init(np, reg_base, nr_clks);
-	samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
+	ctx = samsung_clk_init(np, reg_base, nr_clks);
+	if (!ctx)
+		panic("%s: unable to allocate context.\n", __func__);
+
+	samsung_clk_of_register_fixed_ext(ctx, 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(ctx, exynos5250_pll_pmux_clks,
 				ARRAY_SIZE(exynos5250_pll_pmux_clks));
 
 	if (_get_rate("fin_pll") == 24 * MHZ)
@@ -604,17 +609,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(ctx, exynos5250_plls,
+			ARRAY_SIZE(exynos5250_plls),
+			reg_base);
+	samsung_clk_register_fixed_rate(ctx, exynos5250_fixed_rate_clks,
 			ARRAY_SIZE(exynos5250_fixed_rate_clks));
-	samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks,
+	samsung_clk_register_fixed_factor(ctx, exynos5250_fixed_factor_clks,
 			ARRAY_SIZE(exynos5250_fixed_factor_clks));
-	samsung_clk_register_mux(exynos5250_mux_clks,
+	samsung_clk_register_mux(ctx, exynos5250_mux_clks,
 			ARRAY_SIZE(exynos5250_mux_clks));
-	samsung_clk_register_div(exynos5250_div_clks,
+	samsung_clk_register_div(ctx, exynos5250_div_clks,
 			ARRAY_SIZE(exynos5250_div_clks));
-	samsung_clk_register_gate(exynos5250_gate_clks,
+	samsung_clk_register_gate(ctx, 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..e5493cf 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -808,6 +808,8 @@  static struct of_device_id ext_clk_match[] __initdata = {
 /* register exynos5420 clocks */
 static void __init exynos5420_clk_init(struct device_node *np)
 {
+	struct samsung_clk_provider *ctx;
+
 	if (np) {
 		reg_base = of_iomap(np, 0);
 		if (!reg_base)
@@ -816,21 +818,25 @@  static void __init exynos5420_clk_init(struct device_node *np)
 		panic("%s: unable to determine soc\n", __func__);
 	}
 
-	samsung_clk_init(np, reg_base, nr_clks);
-	samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
+	ctx = samsung_clk_init(np, reg_base, nr_clks);
+	if (!ctx)
+		panic("%s: unable to allocate context.\n", __func__);
+
+	samsung_clk_of_register_fixed_ext(ctx, 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(ctx, exynos5420_plls,
+			ARRAY_SIZE(exynos5420_plls),
+			reg_base);
+	samsung_clk_register_fixed_rate(ctx, exynos5420_fixed_rate_clks,
 			ARRAY_SIZE(exynos5420_fixed_rate_clks));
-	samsung_clk_register_fixed_factor(exynos5420_fixed_factor_clks,
+	samsung_clk_register_fixed_factor(ctx, exynos5420_fixed_factor_clks,
 			ARRAY_SIZE(exynos5420_fixed_factor_clks));
-	samsung_clk_register_mux(exynos5420_mux_clks,
+	samsung_clk_register_mux(ctx, exynos5420_mux_clks,
 			ARRAY_SIZE(exynos5420_mux_clks));
-	samsung_clk_register_div(exynos5420_div_clks,
+	samsung_clk_register_div(ctx, exynos5420_div_clks,
 			ARRAY_SIZE(exynos5420_div_clks));
-	samsung_clk_register_gate(exynos5420_gate_clks,
+	samsung_clk_register_gate(ctx, 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..c2f5d3c 100644
--- a/drivers/clk/samsung/clk-exynos5440.c
+++ b/drivers/clk/samsung/clk-exynos5440.c
@@ -106,6 +106,7 @@  static struct of_device_id ext_clk_match[] __initdata = {
 static void __init exynos5440_clk_init(struct device_node *np)
 {
 	void __iomem *reg_base;
+	struct samsung_clk_provider *ctx;
 
 	reg_base = of_iomap(np, 0);
 	if (!reg_base) {
@@ -114,22 +115,25 @@  static void __init exynos5440_clk_init(struct device_node *np)
 		return;
 	}
 
-	samsung_clk_init(np, reg_base, nr_clks);
-	samsung_clk_of_register_fixed_ext(exynos5440_fixed_rate_ext_clks,
+	ctx = samsung_clk_init(np, reg_base, nr_clks);
+	if (!ctx)
+		panic("%s: unable to allocate context.\n", __func__);
+
+	samsung_clk_of_register_fixed_ext(ctx, 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(ctx, exynos5440_fixed_rate_clks,
 			ARRAY_SIZE(exynos5440_fixed_rate_clks));
-	samsung_clk_register_fixed_factor(exynos5440_fixed_factor_clks,
+	samsung_clk_register_fixed_factor(ctx, exynos5440_fixed_factor_clks,
 			ARRAY_SIZE(exynos5440_fixed_factor_clks));
-	samsung_clk_register_mux(exynos5440_mux_clks,
+	samsung_clk_register_mux(ctx, exynos5440_mux_clks,
 			ARRAY_SIZE(exynos5440_mux_clks));
-	samsung_clk_register_div(exynos5440_div_clks,
+	samsung_clk_register_div(ctx, exynos5440_div_clks,
 			ARRAY_SIZE(exynos5440_div_clks));
-	samsung_clk_register_gate(exynos5440_gate_clks,
+	samsung_clk_register_gate(ctx, 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..e8e8953 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 samsung_clk_provider *ctx,
+				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(ctx, 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 samsung_clk_provider *ctx,
+			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(ctx, &pll_list[cnt], base);
 }
diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c
index a43cbde..b7d06ae 100644
--- a/drivers/clk/samsung/clk-s3c64xx.c
+++ b/drivers/clk/samsung/clk-s3c64xx.c
@@ -442,12 +442,14 @@  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 samsung_clk_provider *ctx,
+				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(ctx, s3c64xx_fixed_rate_ext_clks,
 				ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks));
 }
 
@@ -456,6 +458,8 @@  void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
 			     unsigned long xusbxti_f, bool s3c6400,
 			     void __iomem *base)
 {
+	struct samsung_clk_provider *ctx;
+
 	reg_base = base;
 	is_s3c6400 = s3c6400;
 
@@ -465,48 +469,50 @@  void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
 			panic("%s: failed to map registers\n", __func__);
 	}
 
-	samsung_clk_init(np, reg_base, NR_CLKS);
+	ctx = samsung_clk_init(np, reg_base, NR_CLKS);
+	if (!ctx)
+		panic("%s: unable to allocate context.\n", __func__);
 
 	/* Register external clocks. */
 	if (!np)
-		s3c64xx_clk_register_fixed_ext(xtal_f, xusbxti_f);
+		s3c64xx_clk_register_fixed_ext(ctx, xtal_f, xusbxti_f);
 
 	/* Register PLLs. */
-	samsung_clk_register_pll(s3c64xx_pll_clks,
+	samsung_clk_register_pll(ctx, 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(ctx, s3c64xx_fixed_rate_clks,
 					ARRAY_SIZE(s3c64xx_fixed_rate_clks));
-	samsung_clk_register_mux(s3c64xx_mux_clks,
+	samsung_clk_register_mux(ctx, s3c64xx_mux_clks,
 					ARRAY_SIZE(s3c64xx_mux_clks));
-	samsung_clk_register_div(s3c64xx_div_clks,
+	samsung_clk_register_div(ctx, s3c64xx_div_clks,
 					ARRAY_SIZE(s3c64xx_div_clks));
-	samsung_clk_register_gate(s3c64xx_gate_clks,
+	samsung_clk_register_gate(ctx, 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(ctx, s3c6400_mux_clks,
 					ARRAY_SIZE(s3c6400_mux_clks));
-		samsung_clk_register_div(s3c6400_div_clks,
+		samsung_clk_register_div(ctx, s3c6400_div_clks,
 					ARRAY_SIZE(s3c6400_div_clks));
-		samsung_clk_register_gate(s3c6400_gate_clks,
+		samsung_clk_register_gate(ctx, s3c6400_gate_clks,
 					ARRAY_SIZE(s3c6400_gate_clks));
-		samsung_clk_register_alias(s3c6400_clock_aliases,
+		samsung_clk_register_alias(ctx, s3c6400_clock_aliases,
 					ARRAY_SIZE(s3c6400_clock_aliases));
 	} else {
-		samsung_clk_register_mux(s3c6410_mux_clks,
+		samsung_clk_register_mux(ctx, s3c6410_mux_clks,
 					ARRAY_SIZE(s3c6410_mux_clks));
-		samsung_clk_register_div(s3c6410_div_clks,
+		samsung_clk_register_div(ctx, s3c6410_div_clks,
 					ARRAY_SIZE(s3c6410_div_clks));
-		samsung_clk_register_gate(s3c6410_gate_clks,
+		samsung_clk_register_gate(ctx, s3c6410_gate_clks,
 					ARRAY_SIZE(s3c6410_gate_clks));
-		samsung_clk_register_alias(s3c6410_clock_aliases,
+		samsung_clk_register_alias(ctx, s3c6410_clock_aliases,
 					ARRAY_SIZE(s3c6410_clock_aliases));
 	}
 
-	samsung_clk_register_alias(s3c64xx_clock_aliases,
+	samsung_clk_register_alias(ctx, 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..20de446 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -15,11 +15,6 @@ 
 #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
 
 void samsung_clk_save(void __iomem *base,
 				    struct samsung_clk_reg_dump *rd,
@@ -55,40 +50,53 @@  struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
 }
 
 /* setup the essentials required to support clock lookup using ccf */
-void __init samsung_clk_init(struct device_node *np, void __iomem *base,
-			     unsigned long nr_clks)
+struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np,
+			void __iomem *base, unsigned long nr_clks)
 {
-	reg_base = base;
+	struct samsung_clk_provider *ctx;
+	struct clk **clk_table;
+	int ret;
+
+	if (!np)
+		return NULL;
+
+	ctx = kzalloc(sizeof(struct samsung_clk_provider), 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->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");
+
+	return ctx;
 }
 
 /* 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 samsung_clk_provider *ctx, struct clk *clk,
+				unsigned int id)
 {
-	if (clk_table && id)
-		clk_table[id] = clk;
+	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 samsung_clk_provider *ctx,
+				struct samsung_clock_alias *list,
+				unsigned int nr_clk)
 {
 	struct clk *clk;
 	unsigned int idx, ret;
 
-	if (!clk_table) {
+	if (!ctx->clk_data.clks) {
 		pr_err("%s: clock table missing\n", __func__);
 		return;
 	}
@@ -100,7 +108,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 +123,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 samsung_clk_provider *ctx,
 		struct samsung_fixed_rate_clock *list, unsigned int nr_clk)
 {
 	struct clk *clk;
@@ -130,7 +138,7 @@  void __init samsung_clk_register_fixed_rate(
 			continue;
 		}
 
-		samsung_clk_add_lookup(clk, list->id);
+		samsung_clk_add_lookup(ctx, clk, list->id);
 
 		/*
 		 * Unconditionally add a clock lookup for the fixed rate clocks.
@@ -144,7 +152,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 samsung_clk_provider *ctx,
 		struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
 {
 	struct clk *clk;
@@ -159,20 +167,22 @@  void __init samsung_clk_register_fixed_factor(
 			continue;
 		}
 
-		samsung_clk_add_lookup(clk, list->id);
+		samsung_clk_add_lookup(ctx, 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 samsung_clk_provider *ctx,
+				struct samsung_mux_clock *list,
+				unsigned int nr_clk)
 {
 	struct clk *clk;
 	unsigned int idx, ret;
 
 	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 +190,7 @@  void __init samsung_clk_register_mux(struct samsung_mux_clock *list,
 			continue;
 		}
 
-		samsung_clk_add_lookup(clk, list->id);
+		samsung_clk_add_lookup(ctx, clk, list->id);
 
 		/* register a clock lookup only if a clock alias is specified */
 		if (list->alias) {
@@ -194,8 +204,9 @@  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 samsung_clk_provider *ctx,
+				struct samsung_div_clock *list,
+				unsigned int nr_clk)
 {
 	struct clk *clk;
 	unsigned int idx, ret;
@@ -203,22 +214,22 @@  void __init samsung_clk_register_div(struct samsung_div_clock *list,
 	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(ctx, clk, list->id);
 
 		/* register a clock lookup only if a clock alias is specified */
 		if (list->alias) {
@@ -232,15 +243,16 @@  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 samsung_clk_provider *ctx,
+				struct samsung_gate_clock *list,
+				unsigned int nr_clk)
 {
 	struct clk *clk;
 	unsigned int idx, ret;
 
 	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 +269,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(ctx, clk, list->id);
 	}
 }
 
@@ -266,21 +278,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 samsung_clk_provider *ctx,
 			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(ctx, fixed_rate_clk, nr_fixed_rate_clk);
 }
 #endif
 
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index c7141ba..433bab3 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -21,6 +21,17 @@ 
 #include <linux/of_address.h>
 #include "clk-pll.h"
 
+/* Context node which holds information about the clock provider. */
+/**
+ * struct samsung_clk_provider: information about clock plovider
+ * @reg_base: virtual address for the register base.
+ * @clk_data: holds clock related data like clk* and number of clocks.
+ */
+struct samsung_clk_provider {
+	void __iomem *reg_base;
+	struct clk_onecell_data clk_data;
+};
+
 /**
  * struct samsung_clock_alias: information about mux clock
  * @id: platform specific id of the clock.
@@ -312,29 +323,40 @@  struct samsung_pll_clock {
 	__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE,	\
 		_lock, _con, _rtable, _alias)
 
-extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
-				    unsigned long nr_clks);
+extern struct samsung_clk_provider *__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 samsung_clk_provider *ctx,
 		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 samsung_clk_provider *ctx,
+			struct clk *clk, unsigned int id);
 
-extern void samsung_clk_register_alias(struct samsung_clock_alias *list,
-		unsigned int nr_clk);
+extern void samsung_clk_register_alias(struct samsung_clk_provider *ctx,
+			struct samsung_clock_alias *list,
+			unsigned int nr_clk);
 extern void __init samsung_clk_register_fixed_rate(
-		struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk);
+			struct samsung_clk_provider *ctx,
+			struct samsung_fixed_rate_clock *clk_list,
+			unsigned int nr_clk);
 extern void __init samsung_clk_register_fixed_factor(
-		struct samsung_fixed_factor_clock *list, unsigned int nr_clk);
-extern void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
+			struct samsung_clk_provider *ctx,
+			struct samsung_fixed_factor_clock *list,
+			unsigned int nr_clk);
+extern void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
+		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 samsung_clk_provider *ctx,
+		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 samsung_clk_provider *ctx,
 		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 samsung_clk_provider *ctx,
+			struct samsung_pll_clock *pll_list,
+			unsigned int nr_clk, void __iomem *base);
 
 extern unsigned long _get_rate(const char *clk_name);