diff mbox

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

Message ID 1385963716-20045-1-git-send-email-rahul.sharma@samsung.com (mailing list archive)
State New, archived
Headers show

Commit Message

Rahul Sharma Dec. 2, 2013, 5:55 a.m. UTC
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 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@samsung.com>
---
This patch is based on the following series from
Tomasz Figa <t.figa@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(-)

Comments

Tomasz Figa Dec. 2, 2013, 2:09 p.m. UTC | #1
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?

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.

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.

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@samsung.com>
> ---
> This patch is based on the following series from
> Tomasz Figa <t.figa@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);
>  
>
Rahul Sharma Dec. 2, 2013, 2:49 p.m. UTC | #2
Thanks Tomasz,

On 2 December 2013 19:39, Tomasz Figa <t.figa@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@samsung.com>
>> ---
>> This patch is based on the following series from
>> Tomasz Figa <t.figa@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);
>>
>>
>
Tomasz Figa Dec. 2, 2013, 3:06 p.m. UTC | #3
On Monday 02 of December 2013 20:19:52 Rahul Sharma wrote:
> Thanks Tomasz,
> 
> On 2 December 2013 19:39, Tomasz Figa <t.figa@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.

OK, thanks for the explanation. So I guess support for the SoC itself
is coming to the mainline too?

> 
> > 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.

OK.

> 
> > 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.

OK.

Best regards,
Tomasz
diff mbox

Patch

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);