Commit 976face4 authored by Rahul Sharma's avatar Rahul Sharma Committed by Tomasz Figa

clk/samsung: add support for multiple clock providers

Samsung CCF helper functions do not provide support to
register multiple Clock Providers for a given SoC. Due to
this limitation, SoC platforms are not able to use these
helpers for registering multiple clock providers and are
forced to bypass this layer.

This layer is modified accordingly to enable the support
for multiple clock providers.

Clock file for exynos4, exynos5250, exynos5420, exynos5440,
S3c64xx, S3c24xx are also modified as per changed helper functions.
Signed-off-by: default avatarRahul Sharma <rahul.sharma@samsung.com>
[t.figa: Modified s3c2410 clock driver as well]
Signed-off-by: default avatarTomasz Figa <t.figa@samsung.com>
parent 2916f9a2
...@@ -1043,7 +1043,7 @@ static unsigned long exynos4_get_xom(void) ...@@ -1043,7 +1043,7 @@ static unsigned long exynos4_get_xom(void)
return xom; return xom;
} }
static void __init exynos4_clk_register_finpll(void) static void __init exynos4_clk_register_finpll(struct samsung_clk_provider *ctx)
{ {
struct samsung_fixed_rate_clock fclk; struct samsung_fixed_rate_clock fclk;
struct clk *clk; struct clk *clk;
...@@ -1066,7 +1066,7 @@ static void __init exynos4_clk_register_finpll(void) ...@@ -1066,7 +1066,7 @@ static void __init exynos4_clk_register_finpll(void)
fclk.parent_name = NULL; fclk.parent_name = NULL;
fclk.flags = CLK_IS_ROOT; fclk.flags = CLK_IS_ROOT;
fclk.fixed_rate = finpll_f; fclk.fixed_rate = finpll_f;
samsung_clk_register_fixed_rate(&fclk, 1); samsung_clk_register_fixed_rate(ctx, &fclk, 1);
} }
...@@ -1176,22 +1176,25 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = { ...@@ -1176,22 +1176,25 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = {
static void __init exynos4_clk_init(struct device_node *np, static void __init exynos4_clk_init(struct device_node *np,
enum exynos4_soc soc) enum exynos4_soc soc)
{ {
struct samsung_clk_provider *ctx;
exynos4_soc = soc; exynos4_soc = soc;
reg_base = of_iomap(np, 0); reg_base = of_iomap(np, 0);
if (!reg_base) if (!reg_base)
panic("%s: failed to map registers\n", __func__); panic("%s: failed to map registers\n", __func__);
samsung_clk_init(np, reg_base, CLK_NR_CLKS); ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks, samsung_clk_of_register_fixed_ext(ctx, exynos4_fixed_rate_ext_clks,
ARRAY_SIZE(exynos4_fixed_rate_ext_clks), ARRAY_SIZE(exynos4_fixed_rate_ext_clks),
ext_clk_match); ext_clk_match);
exynos4_clk_register_finpll(); exynos4_clk_register_finpll(ctx);
if (exynos4_soc == EXYNOS4210) { if (exynos4_soc == EXYNOS4210) {
samsung_clk_register_mux(exynos4210_mux_early, samsung_clk_register_mux(ctx, exynos4210_mux_early,
ARRAY_SIZE(exynos4210_mux_early)); ARRAY_SIZE(exynos4210_mux_early));
if (_get_rate("fin_pll") == 24000000) { if (_get_rate("fin_pll") == 24000000) {
...@@ -1205,7 +1208,7 @@ static void __init exynos4_clk_init(struct device_node *np, ...@@ -1205,7 +1208,7 @@ static void __init exynos4_clk_init(struct device_node *np,
exynos4210_plls[vpll].rate_table = exynos4210_plls[vpll].rate_table =
exynos4210_vpll_rates; exynos4210_vpll_rates;
samsung_clk_register_pll(exynos4210_plls, samsung_clk_register_pll(ctx, exynos4210_plls,
ARRAY_SIZE(exynos4210_plls), reg_base); ARRAY_SIZE(exynos4210_plls), reg_base);
} else { } else {
if (_get_rate("fin_pll") == 24000000) { if (_get_rate("fin_pll") == 24000000) {
...@@ -1217,42 +1220,42 @@ static void __init exynos4_clk_init(struct device_node *np, ...@@ -1217,42 +1220,42 @@ static void __init exynos4_clk_init(struct device_node *np,
exynos4x12_vpll_rates; exynos4x12_vpll_rates;
} }
samsung_clk_register_pll(exynos4x12_plls, samsung_clk_register_pll(ctx, exynos4x12_plls,
ARRAY_SIZE(exynos4x12_plls), reg_base); ARRAY_SIZE(exynos4x12_plls), reg_base);
} }
samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks, samsung_clk_register_fixed_rate(ctx, exynos4_fixed_rate_clks,
ARRAY_SIZE(exynos4_fixed_rate_clks)); ARRAY_SIZE(exynos4_fixed_rate_clks));
samsung_clk_register_mux(exynos4_mux_clks, samsung_clk_register_mux(ctx, exynos4_mux_clks,
ARRAY_SIZE(exynos4_mux_clks)); ARRAY_SIZE(exynos4_mux_clks));
samsung_clk_register_div(exynos4_div_clks, samsung_clk_register_div(ctx, exynos4_div_clks,
ARRAY_SIZE(exynos4_div_clks)); ARRAY_SIZE(exynos4_div_clks));
samsung_clk_register_gate(exynos4_gate_clks, samsung_clk_register_gate(ctx, exynos4_gate_clks,
ARRAY_SIZE(exynos4_gate_clks)); ARRAY_SIZE(exynos4_gate_clks));
if (exynos4_soc == EXYNOS4210) { if (exynos4_soc == EXYNOS4210) {
samsung_clk_register_fixed_rate(exynos4210_fixed_rate_clks, samsung_clk_register_fixed_rate(ctx, exynos4210_fixed_rate_clks,
ARRAY_SIZE(exynos4210_fixed_rate_clks)); ARRAY_SIZE(exynos4210_fixed_rate_clks));
samsung_clk_register_mux(exynos4210_mux_clks, samsung_clk_register_mux(ctx, exynos4210_mux_clks,
ARRAY_SIZE(exynos4210_mux_clks)); ARRAY_SIZE(exynos4210_mux_clks));
samsung_clk_register_div(exynos4210_div_clks, samsung_clk_register_div(ctx, exynos4210_div_clks,
ARRAY_SIZE(exynos4210_div_clks)); ARRAY_SIZE(exynos4210_div_clks));
samsung_clk_register_gate(exynos4210_gate_clks, samsung_clk_register_gate(ctx, exynos4210_gate_clks,
ARRAY_SIZE(exynos4210_gate_clks)); ARRAY_SIZE(exynos4210_gate_clks));
samsung_clk_register_alias(exynos4210_aliases, samsung_clk_register_alias(ctx, exynos4210_aliases,
ARRAY_SIZE(exynos4210_aliases)); ARRAY_SIZE(exynos4210_aliases));
} else { } else {
samsung_clk_register_mux(exynos4x12_mux_clks, samsung_clk_register_mux(ctx, exynos4x12_mux_clks,
ARRAY_SIZE(exynos4x12_mux_clks)); ARRAY_SIZE(exynos4x12_mux_clks));
samsung_clk_register_div(exynos4x12_div_clks, samsung_clk_register_div(ctx, exynos4x12_div_clks,
ARRAY_SIZE(exynos4x12_div_clks)); ARRAY_SIZE(exynos4x12_div_clks));
samsung_clk_register_gate(exynos4x12_gate_clks, samsung_clk_register_gate(ctx, exynos4x12_gate_clks,
ARRAY_SIZE(exynos4x12_gate_clks)); ARRAY_SIZE(exynos4x12_gate_clks));
samsung_clk_register_alias(exynos4x12_aliases, samsung_clk_register_alias(ctx, exynos4x12_aliases,
ARRAY_SIZE(exynos4x12_aliases)); ARRAY_SIZE(exynos4x12_aliases));
} }
samsung_clk_register_alias(exynos4_aliases, samsung_clk_register_alias(ctx, exynos4_aliases,
ARRAY_SIZE(exynos4_aliases)); ARRAY_SIZE(exynos4_aliases));
exynos4_clk_sleep_init(); exynos4_clk_sleep_init();
......
...@@ -686,6 +686,8 @@ static struct of_device_id ext_clk_match[] __initdata = { ...@@ -686,6 +686,8 @@ static struct of_device_id ext_clk_match[] __initdata = {
/* register exynox5250 clocks */ /* register exynox5250 clocks */
static void __init exynos5250_clk_init(struct device_node *np) static void __init exynos5250_clk_init(struct device_node *np)
{ {
struct samsung_clk_provider *ctx;
if (np) { if (np) {
reg_base = of_iomap(np, 0); reg_base = of_iomap(np, 0);
if (!reg_base) if (!reg_base)
...@@ -694,11 +696,13 @@ static void __init exynos5250_clk_init(struct device_node *np) ...@@ -694,11 +696,13 @@ static void __init exynos5250_clk_init(struct device_node *np)
panic("%s: unable to determine soc\n", __func__); panic("%s: unable to determine soc\n", __func__);
} }
samsung_clk_init(np, reg_base, CLK_NR_CLKS); ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks, if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
samsung_clk_of_register_fixed_ext(ctx, exynos5250_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5250_fixed_rate_ext_clks), ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
ext_clk_match); ext_clk_match);
samsung_clk_register_mux(exynos5250_pll_pmux_clks, samsung_clk_register_mux(ctx, exynos5250_pll_pmux_clks,
ARRAY_SIZE(exynos5250_pll_pmux_clks)); ARRAY_SIZE(exynos5250_pll_pmux_clks));
if (_get_rate("fin_pll") == 24 * MHZ) { if (_get_rate("fin_pll") == 24 * MHZ) {
...@@ -709,17 +713,18 @@ static void __init exynos5250_clk_init(struct device_node *np) ...@@ -709,17 +713,18 @@ static void __init exynos5250_clk_init(struct device_node *np)
if (_get_rate("mout_vpllsrc") == 24 * MHZ) if (_get_rate("mout_vpllsrc") == 24 * MHZ)
exynos5250_plls[vpll].rate_table = vpll_24mhz_tbl; exynos5250_plls[vpll].rate_table = vpll_24mhz_tbl;
samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls), samsung_clk_register_pll(ctx, exynos5250_plls,
reg_base); ARRAY_SIZE(exynos5250_plls),
samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks, reg_base);
samsung_clk_register_fixed_rate(ctx, exynos5250_fixed_rate_clks,
ARRAY_SIZE(exynos5250_fixed_rate_clks)); ARRAY_SIZE(exynos5250_fixed_rate_clks));
samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks, samsung_clk_register_fixed_factor(ctx, exynos5250_fixed_factor_clks,
ARRAY_SIZE(exynos5250_fixed_factor_clks)); ARRAY_SIZE(exynos5250_fixed_factor_clks));
samsung_clk_register_mux(exynos5250_mux_clks, samsung_clk_register_mux(ctx, exynos5250_mux_clks,
ARRAY_SIZE(exynos5250_mux_clks)); ARRAY_SIZE(exynos5250_mux_clks));
samsung_clk_register_div(exynos5250_div_clks, samsung_clk_register_div(ctx, exynos5250_div_clks,
ARRAY_SIZE(exynos5250_div_clks)); ARRAY_SIZE(exynos5250_div_clks));
samsung_clk_register_gate(exynos5250_gate_clks, samsung_clk_register_gate(ctx, exynos5250_gate_clks,
ARRAY_SIZE(exynos5250_gate_clks)); ARRAY_SIZE(exynos5250_gate_clks));
exynos5250_clk_sleep_init(); exynos5250_clk_sleep_init();
......
...@@ -778,6 +778,8 @@ static struct of_device_id ext_clk_match[] __initdata = { ...@@ -778,6 +778,8 @@ static struct of_device_id ext_clk_match[] __initdata = {
/* register exynos5420 clocks */ /* register exynos5420 clocks */
static void __init exynos5420_clk_init(struct device_node *np) static void __init exynos5420_clk_init(struct device_node *np)
{ {
struct samsung_clk_provider *ctx;
if (np) { if (np) {
reg_base = of_iomap(np, 0); reg_base = of_iomap(np, 0);
if (!reg_base) if (!reg_base)
...@@ -786,21 +788,25 @@ static void __init exynos5420_clk_init(struct device_node *np) ...@@ -786,21 +788,25 @@ static void __init exynos5420_clk_init(struct device_node *np)
panic("%s: unable to determine soc\n", __func__); panic("%s: unable to determine soc\n", __func__);
} }
samsung_clk_init(np, reg_base, CLK_NR_CLKS); ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks, if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
samsung_clk_of_register_fixed_ext(ctx, exynos5420_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5420_fixed_rate_ext_clks), ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
ext_clk_match); ext_clk_match);
samsung_clk_register_pll(exynos5420_plls, ARRAY_SIZE(exynos5420_plls), samsung_clk_register_pll(ctx, exynos5420_plls,
reg_base); ARRAY_SIZE(exynos5420_plls),
samsung_clk_register_fixed_rate(exynos5420_fixed_rate_clks, reg_base);
samsung_clk_register_fixed_rate(ctx, exynos5420_fixed_rate_clks,
ARRAY_SIZE(exynos5420_fixed_rate_clks)); ARRAY_SIZE(exynos5420_fixed_rate_clks));
samsung_clk_register_fixed_factor(exynos5420_fixed_factor_clks, samsung_clk_register_fixed_factor(ctx, exynos5420_fixed_factor_clks,
ARRAY_SIZE(exynos5420_fixed_factor_clks)); ARRAY_SIZE(exynos5420_fixed_factor_clks));
samsung_clk_register_mux(exynos5420_mux_clks, samsung_clk_register_mux(ctx, exynos5420_mux_clks,
ARRAY_SIZE(exynos5420_mux_clks)); ARRAY_SIZE(exynos5420_mux_clks));
samsung_clk_register_div(exynos5420_div_clks, samsung_clk_register_div(ctx, exynos5420_div_clks,
ARRAY_SIZE(exynos5420_div_clks)); ARRAY_SIZE(exynos5420_div_clks));
samsung_clk_register_gate(exynos5420_gate_clks, samsung_clk_register_gate(ctx, exynos5420_gate_clks,
ARRAY_SIZE(exynos5420_gate_clks)); ARRAY_SIZE(exynos5420_gate_clks));
exynos5420_clk_sleep_init(); exynos5420_clk_sleep_init();
......
...@@ -93,6 +93,7 @@ static struct of_device_id ext_clk_match[] __initdata = { ...@@ -93,6 +93,7 @@ static struct of_device_id ext_clk_match[] __initdata = {
static void __init exynos5440_clk_init(struct device_node *np) static void __init exynos5440_clk_init(struct device_node *np)
{ {
void __iomem *reg_base; void __iomem *reg_base;
struct samsung_clk_provider *ctx;
reg_base = of_iomap(np, 0); reg_base = of_iomap(np, 0);
if (!reg_base) { if (!reg_base) {
...@@ -101,22 +102,25 @@ static void __init exynos5440_clk_init(struct device_node *np) ...@@ -101,22 +102,25 @@ static void __init exynos5440_clk_init(struct device_node *np)
return; return;
} }
samsung_clk_init(np, reg_base, CLK_NR_CLKS); ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
samsung_clk_of_register_fixed_ext(exynos5440_fixed_rate_ext_clks, if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
samsung_clk_of_register_fixed_ext(ctx, exynos5440_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match); ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match);
samsung_clk_register_pll2550x("cplla", "xtal", reg_base + 0x1c, 0x10); samsung_clk_register_pll2550x("cplla", "xtal", reg_base + 0x1c, 0x10);
samsung_clk_register_pll2550x("cpllb", "xtal", reg_base + 0x20, 0x10); samsung_clk_register_pll2550x("cpllb", "xtal", reg_base + 0x20, 0x10);
samsung_clk_register_fixed_rate(exynos5440_fixed_rate_clks, samsung_clk_register_fixed_rate(ctx, exynos5440_fixed_rate_clks,
ARRAY_SIZE(exynos5440_fixed_rate_clks)); ARRAY_SIZE(exynos5440_fixed_rate_clks));
samsung_clk_register_fixed_factor(exynos5440_fixed_factor_clks, samsung_clk_register_fixed_factor(ctx, exynos5440_fixed_factor_clks,
ARRAY_SIZE(exynos5440_fixed_factor_clks)); ARRAY_SIZE(exynos5440_fixed_factor_clks));
samsung_clk_register_mux(exynos5440_mux_clks, samsung_clk_register_mux(ctx, exynos5440_mux_clks,
ARRAY_SIZE(exynos5440_mux_clks)); ARRAY_SIZE(exynos5440_mux_clks));
samsung_clk_register_div(exynos5440_div_clks, samsung_clk_register_div(ctx, exynos5440_div_clks,
ARRAY_SIZE(exynos5440_div_clks)); ARRAY_SIZE(exynos5440_div_clks));
samsung_clk_register_gate(exynos5440_gate_clks, samsung_clk_register_gate(ctx, exynos5440_gate_clks,
ARRAY_SIZE(exynos5440_gate_clks)); ARRAY_SIZE(exynos5440_gate_clks));
pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk")); pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk"));
......
...@@ -947,8 +947,9 @@ struct clk * __init samsung_clk_register_pll2550x(const char *name, ...@@ -947,8 +947,9 @@ struct clk * __init samsung_clk_register_pll2550x(const char *name,
return clk; return clk;
} }
static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
void __iomem *base) struct samsung_pll_clock *pll_clk,
void __iomem *base)
{ {
struct samsung_clk_pll *pll; struct samsung_clk_pll *pll;
struct clk *clk; struct clk *clk;
...@@ -1066,7 +1067,7 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, ...@@ -1066,7 +1067,7 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
return; return;
} }
samsung_clk_add_lookup(clk, pll_clk->id); samsung_clk_add_lookup(ctx, clk, pll_clk->id);
if (!pll_clk->alias) if (!pll_clk->alias)
return; return;
...@@ -1077,11 +1078,12 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, ...@@ -1077,11 +1078,12 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
__func__, pll_clk->name, ret); __func__, pll_clk->name, ret);
} }
void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list, void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
unsigned int nr_pll, void __iomem *base) struct samsung_pll_clock *pll_list,
unsigned int nr_pll, void __iomem *base)
{ {
int cnt; int cnt;
for (cnt = 0; cnt < nr_pll; cnt++) for (cnt = 0; cnt < nr_pll; cnt++)
_samsung_clk_register_pll(&pll_list[cnt], base); _samsung_clk_register_pll(ctx, &pll_list[cnt], base);
} }
...@@ -344,21 +344,24 @@ struct samsung_fixed_rate_clock s3c2410_common_frate_clks[] __initdata = { ...@@ -344,21 +344,24 @@ struct samsung_fixed_rate_clock s3c2410_common_frate_clks[] __initdata = {
FRATE(XTI, "xti", NULL, CLK_IS_ROOT, 0), FRATE(XTI, "xti", NULL, CLK_IS_ROOT, 0),
}; };
static void __init s3c2410_common_clk_register_fixed_ext(unsigned long xti_f) static void __init s3c2410_common_clk_register_fixed_ext(
struct samsung_clk_provider *ctx,
unsigned long xti_f)
{ {
struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal"); struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal");
s3c2410_common_frate_clks[0].fixed_rate = xti_f; s3c2410_common_frate_clks[0].fixed_rate = xti_f;
samsung_clk_register_fixed_rate(s3c2410_common_frate_clks, samsung_clk_register_fixed_rate(ctx, s3c2410_common_frate_clks,
ARRAY_SIZE(s3c2410_common_frate_clks)); ARRAY_SIZE(s3c2410_common_frate_clks));
samsung_clk_register_alias(&xti_alias, 1); samsung_clk_register_alias(ctx, &xti_alias, 1);
} }
void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,
int current_soc, int current_soc,
void __iomem *base) void __iomem *base)
{ {
struct samsung_clk_provider *ctx;
reg_base = base; reg_base = base;
if (np) { if (np) {
...@@ -367,11 +370,13 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, ...@@ -367,11 +370,13 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,
panic("%s: failed to map registers\n", __func__); panic("%s: failed to map registers\n", __func__);
} }
samsung_clk_init(np, reg_base, NR_CLKS); ctx = samsung_clk_init(np, reg_base, NR_CLKS);
if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
/* Register external clocks only in non-dt cases */ /* Register external clocks only in non-dt cases */
if (!np) if (!np)
s3c2410_common_clk_register_fixed_ext(xti_f); s3c2410_common_clk_register_fixed_ext(ctx, xti_f);
if (current_soc == 2410) { if (current_soc == 2410) {
if (_get_rate("xti") == 12 * MHZ) { if (_get_rate("xti") == 12 * MHZ) {
...@@ -380,7 +385,7 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, ...@@ -380,7 +385,7 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,
} }
/* Register PLLs. */ /* Register PLLs. */
samsung_clk_register_pll(s3c2410_plls, samsung_clk_register_pll(ctx, s3c2410_plls,
ARRAY_SIZE(s3c2410_plls), reg_base); ARRAY_SIZE(s3c2410_plls), reg_base);
} else { /* S3C2440, S3C2442 */ } else { /* S3C2440, S3C2442 */
...@@ -396,49 +401,49 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, ...@@ -396,49 +401,49 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,
} }
/* Register PLLs. */ /* Register PLLs. */
samsung_clk_register_pll(s3c244x_common_plls, samsung_clk_register_pll(ctx, s3c244x_common_plls,
ARRAY_SIZE(s3c244x_common_plls), reg_base); ARRAY_SIZE(s3c244x_common_plls), reg_base);
} }
/* Register common internal clocks. */ /* Register common internal clocks. */
samsung_clk_register_mux(s3c2410_common_muxes, samsung_clk_register_mux(ctx, s3c2410_common_muxes,
ARRAY_SIZE(s3c2410_common_muxes)); ARRAY_SIZE(s3c2410_common_muxes));
samsung_clk_register_div(s3c2410_common_dividers, samsung_clk_register_div(ctx, s3c2410_common_dividers,
ARRAY_SIZE(s3c2410_common_dividers)); ARRAY_SIZE(s3c2410_common_dividers));
samsung_clk_register_gate(s3c2410_common_gates, samsung_clk_register_gate(ctx, s3c2410_common_gates,
ARRAY_SIZE(s3c2410_common_gates)); ARRAY_SIZE(s3c2410_common_gates));
if (current_soc == S3C2440 || current_soc == S3C2442) { if (current_soc == S3C2440 || current_soc == S3C2442) {
samsung_clk_register_div(s3c244x_common_dividers, samsung_clk_register_div(ctx, s3c244x_common_dividers,
ARRAY_SIZE(s3c244x_common_dividers)); ARRAY_SIZE(s3c244x_common_dividers));
samsung_clk_register_gate(s3c244x_common_gates, samsung_clk_register_gate(ctx, s3c244x_common_gates,
ARRAY_SIZE(s3c244x_common_gates)); ARRAY_SIZE(s3c244x_common_gates));
samsung_clk_register_mux(s3c244x_common_muxes, samsung_clk_register_mux(ctx, s3c244x_common_muxes,
ARRAY_SIZE(s3c244x_common_muxes)); ARRAY_SIZE(s3c244x_common_muxes));
samsung_clk_register_fixed_factor(s3c244x_common_ffactor, samsung_clk_register_fixed_factor(ctx, s3c244x_common_ffactor,
ARRAY_SIZE(s3c244x_common_ffactor)); ARRAY_SIZE(s3c244x_common_ffactor));
} }
/* Register SoC-specific clocks. */ /* Register SoC-specific clocks. */
switch (current_soc) { switch (current_soc) {
case S3C2410: case S3C2410:
samsung_clk_register_div(s3c2410_dividers, samsung_clk_register_div(ctx, s3c2410_dividers,
ARRAY_SIZE(s3c2410_dividers)); ARRAY_SIZE(s3c2410_dividers));
samsung_clk_register_fixed_factor(s3c2410_ffactor, samsung_clk_register_fixed_factor(ctx, s3c2410_ffactor,
ARRAY_SIZE(s3c2410_ffactor)); ARRAY_SIZE(s3c2410_ffactor));
samsung_clk_register_alias(s3c2410_aliases, samsung_clk_register_alias(ctx, s3c2410_aliases,
ARRAY_SIZE(s3c2410_common_aliases)); ARRAY_SIZE(s3c2410_common_aliases));
break; break;
case S3C2440: case S3C2440:
samsung_clk_register_mux(s3c2440_muxes, samsung_clk_register_mux(ctx, s3c2440_muxes,
ARRAY_SIZE(s3c2440_muxes)); ARRAY_SIZE(s3c2440_muxes));
samsung_clk_register_gate(s3c2440_gates, samsung_clk_register_gate(ctx, s3c2440_gates,
ARRAY_SIZE(s3c2440_gates)); ARRAY_SIZE(s3c2440_gates));
break; break;
case S3C2442: case S3C2442:
samsung_clk_register_mux(s3c2442_muxes, samsung_clk_register_mux(ctx, s3c2442_muxes,
ARRAY_SIZE(s3c2442_muxes)); ARRAY_SIZE(s3c2442_muxes));
samsung_clk_register_fixed_factor(s3c2442_ffactor, samsung_clk_register_fixed_factor(ctx, s3c2442_ffactor,
ARRAY_SIZE(s3c2442_ffactor)); ARRAY_SIZE(s3c2442_ffactor));
break; break;
} }
...@@ -447,11 +452,11 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, ...@@ -447,11 +452,11 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,
* Register common aliases at the end, as some of the aliased clocks * Register common aliases at the end, as some of the aliased clocks
* are SoC specific. * are SoC specific.
*/ */
samsung_clk_register_alias(s3c2410_common_aliases, samsung_clk_register_alias(ctx, s3c2410_common_aliases,
ARRAY_SIZE(s3c2410_common_aliases)); ARRAY_SIZE(s3c2410_common_aliases));
if (current_soc == S3C2440 || current_soc == S3C2442) { if (current_soc == S3C2440 || current_soc == S3C2442) {
samsung_clk_register_alias(s3c244x_common_aliases, samsung_clk_register_alias(ctx, s3c244x_common_aliases,
ARRAY_SIZE(s3c244x_common_aliases)); ARRAY_SIZE(s3c244x_common_aliases));
} }
......
...@@ -214,23 +214,25 @@ struct samsung_fixed_rate_clock s3c2412_common_frate_clks[] __initdata = { ...@@ -214,23 +214,25 @@ struct samsung_fixed_rate_clock s3c2412_common_frate_clks[] __initdata = {
FRATE(0, "ext", NULL, CLK_IS_ROOT, 0), FRATE(0, "ext", NULL, CLK_IS_ROOT, 0),
}; };
static void __init s3c2412_common_clk_register_fixed_ext(unsigned long xti_f, static void __init s3c2412_common_clk_register_fixed_ext(
unsigned long ext_f) struct samsung_clk_provider *ctx,
unsigned long xti_f, unsigned long ext_f)
{ {
/* xtal alias is necessary for the current cpufreq driver */ /* xtal alias is necessary for the current cpufreq driver */
struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal"); struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal");
s3c2412_common_frate_clks[0].fixed_rate = xti_f; s3c2412_common_frate_clks[0].fixed_rate = xti_f;
s3c2412_common_frate_clks[1].fixed_rate = ext_f; s3c2412_common_frate_clks[1].fixed_rate = ext_f;
samsung_clk_register_fixed_rate(s3c2412_common_frate_clks, samsung_clk_register_fixed_rate(ctx, s3c2412_common_frate_clks,
ARRAY_SIZE(s3c2412_common_frate_clks)); ARRAY_SIZE(s3c2412_common_frate_clks));
samsung_clk_register_alias(&xti_alias, 1); samsung_clk_register_alias(ctx, &xti_alias, 1);
} }
void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
unsigned long ext_f, void __iomem *base) unsigned long ext_f, void __iomem *base)
{ {
struct samsung_clk_provider *ctx;
reg_base = base; reg_base = base;
if (np) { if (np) {
...@@ -239,24 +241,27 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, ...@@ -239,24 +241,27 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
panic("%s: failed to map registers\n", __func__); panic("%s: failed to map registers\n", __func__);
} }
samsung_clk_init(np, reg_base, NR_CLKS); ctx = samsung_clk_init(np, reg_base, NR_CLKS);
if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
/* Register external clocks only in non-dt cases */ /* Register external clocks only in non-dt cases */
if (!np) if (!np)
s3c2412_common_clk_register_fixed_ext(xti_f, ext_f); s3c2412_common_clk_register_fixed_ext(ctx, xti_f, ext_f);
/* Register PLLs. */ /* Register PLLs. */
samsung_clk_register_pll(s3c2412_plls, ARRAY_SIZE(s3c2412_plls), samsung_clk_register_pll(ctx, s3c2412_plls, ARRAY_SIZE(s3c2412_plls),
reg_base); reg_base);
/* Register common internal clocks. */ /* Register common internal clocks. */
samsung_clk_register_mux(s3c2412_muxes, ARRAY_SIZE(s3c2412_muxes)); samsung_clk_register_mux(ctx, s3c2412_muxes, ARRAY_SIZE(s3c2412_muxes));
samsung_clk_register_div(s3c2412_dividers, samsung_clk_register_div(ctx, s3c2412_dividers,
ARRAY_SIZE(s3c2412_dividers)); ARRAY_SIZE(s3c2412_dividers));
samsung_clk_register_gate(s3c2412_gates, ARRAY_SIZE(s3c2412_gates)); samsung_clk_register_gate(ctx, s3c2412_gates,
samsung_clk_register_fixed_factor(s3c2412_ffactor, ARRAY_SIZE(s3c2412_gates));
samsung_clk_register_fixed_factor(ctx, s3c2412_ffactor,
ARRAY_SIZE(s3c2412_ffactor)); ARRAY_SIZE(s3c2412_ffactor));
samsung_clk_register_alias(s3c2412_aliases, samsung_clk_register_alias(ctx, s3c2412_aliases,
ARRAY_SIZE(s3c2412_aliases)); ARRAY_SIZE(s3c2412_aliases));
s3c2412_clk_sleep_init(); s3c2412_clk_sleep_init();
......
...@@ -365,10 +365,11 @@ struct samsung_fixed_rate_clock s3c2443_common_frate_clks[] __initdata = { ...@@ -365,10 +365,11 @@ struct samsung_fixed_rate_clock s3c2443_common_frate_clks[] __initdata = {
FRATE(0, "ext_uart", NULL, CLK_IS_ROOT, 0), FRATE(0, "ext_uart", NULL, CLK_IS_ROOT, 0),
}; };
static void __init s3c2443_common_clk_register_fixed_ext(unsigned long xti_f) static void __init s3c2443_common_clk_register_fixed_ext(
struct samsung_clk_provider *ctx, unsigned long xti_f)
{ {
s3c2443_common_frate_clks[0].fixed_rate = xti_f; s3c2443_common_frate_clks[0].fixed_rate = xti_f;
samsung_clk_register_fixed_rate(s3c2443_common_frate_clks, samsung_clk_register_fixed_rate(ctx, s3c2443_common_frate_clks,
ARRAY_SIZE(s3c2443_common_frate_clks)); ARRAY_SIZE(s3c2443_common_frate_clks));
} }
...@@ -376,6 +377,7 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f, ...@@ -376,6 +377,7 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
int current_soc, int current_soc,
void __iomem *base) void __iomem *base)
{ {
struct samsung_clk_provider *ctx;
reg_base = base; reg_base = base;
if (np) { if (np) {
...@@ -384,58 +386,60 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f, ...@@ -384,58 +386,60 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
panic("%s: failed to map registers\n", __func__); panic("%s: failed to map registers\n", __func__);
} }
samsung_clk_init(np, reg_base, NR_CLKS); ctx = samsung_clk_init(np, reg_base, NR_CLKS);
if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
/* Register external clocks only in non-dt cases */ /* Register external clocks only in non-dt cases */
if (!np) if (!np)
s3c2443_common_clk_register_fixed_ext(xti_f); s3c2443_common_clk_register_fixed_ext(ctx, xti_f);
/* Register PLLs. */ /* Register PLLs. */
if (current_soc == S3C2416 || current_soc == S3C2450) if (current_soc == S3C2416 || current_soc == S3C2450)
samsung_clk_register_pll(s3c2416_pll_clks, samsung_clk_register_pll(ctx, s3c2416_pll_clks,
ARRAY_SIZE(s3c2416_pll_clks), reg_base); ARRAY_SIZE(s3c2416_pll_clks), reg_base);
else else
samsung_clk_register_pll(s3c2443_pll_clks, samsung_clk_register_pll(ctx, s3c2443_pll_clks,
ARRAY_SIZE(s3c2443_pll_clks), reg_base); ARRAY_SIZE(s3c2443_pll_clks), reg_base);
/* Register common internal clocks. */ /* Register common internal clocks. */
samsung_clk_register_mux(s3c2443_common_muxes, samsung_clk_register_mux(ctx, s3c2443_common_muxes,
ARRAY_SIZE(s3c2443_common_muxes)); ARRAY_SIZE(s3c2443_common_muxes));
samsung_clk_register_div(s3c2443_common_dividers, samsung_clk_register_div(ctx, s3c2443_common_dividers,
ARRAY_SIZE(s3c2443_common_dividers)); ARRAY_SIZE(s3c2443_common_dividers));
samsung_clk_register_gate(s3c2443_common_gates, samsung_clk_register_gate(ctx, s3c2443_common_gates,
ARRAY_SIZE(s3c2443_common_gates)); ARRAY_SIZE(s3c2443_common_gates));
samsung_clk_register_alias(s3c2443_common_aliases, samsung_clk_register_alias(ctx, s3c2443_common_aliases,
ARRAY_SIZE(s3c2443_common_aliases)); ARRAY_SIZE(s3c2443_common_aliases));
/* Register SoC-specific clocks. */ /* Register SoC-specific clocks. */
switch (current_soc) { switch (current_soc) {
case S3C2450: case S3C2450:
samsung_clk_register_div(s3c2450_dividers, samsung_clk_register_div(ctx, s3c2450_dividers,
ARRAY_SIZE(s3c2450_dividers)); ARRAY_SIZE(s3c2450_dividers));
samsung_clk_register_mux(s3c2450_muxes, samsung_clk_register_mux(ctx, s3c2450_muxes,
ARRAY_SIZE(s3c2450_muxes)); ARRAY_SIZE(s3c2450_muxes));
samsung_clk_register_gate(s3c2450_gates, samsung_clk_register_gate(ctx, s3c2450_gates,
ARRAY_SIZE(s3c2450_gates)); ARRAY_SIZE(s3c2450_gates));
samsung_clk_register_alias(s3c2450_aliases, samsung_clk_register_alias(ctx, s3c2450_aliases,
ARRAY_SIZE(s3c2450_aliases)); ARRAY_SIZE(s3c2450_aliases));
/* fall through, as s3c2450 extends the s3c2416 clocks */ /* fall through, as s3c2450 extends the s3c2416 clocks */
case S3C2416: case S3C2416:
samsung_clk_register_div(s3c2416_dividers, samsung_clk_register_div(ctx, s3c2416_dividers,
ARRAY_SIZE(s3c2416_dividers)); ARRAY_SIZE(s3c2416_dividers));
samsung_clk_register_mux(s3c2416_muxes, samsung_clk_register_mux(ctx, s3c2416_muxes,
ARRAY_SIZE(s3c2416_muxes)); ARRAY_SIZE(s3c2416_muxes));
samsung_clk_register_gate(s3c2416_gates, samsung_clk_register_gate(ctx, s3c2416_gates,
ARRAY_SIZE(s3c2416_gates)); ARRAY_SIZE(s3c2416_gates));
samsung_clk_register_alias(s3c2416_aliases, samsung_clk_register_alias(ctx, s3c2416_aliases,
ARRAY_SIZE(s3c2416_aliases)); ARRAY_SIZE(s3c2416_aliases));
break; break;
case S3C2443: case S3C2443:
samsung_clk_register_div(s3c2443_dividers, samsung_clk_register_div(ctx, s3c2443_dividers,
ARRAY_SIZE(s3c2443_dividers)); ARRAY_SIZE(s3c2443_dividers));
samsung_clk_register_gate(s3c2443_gates, samsung_clk_register_gate(ctx, s3c2443_gates,
ARRAY_SIZE(s3c2443_gates)); ARRAY_SIZE(s3c2443_gates));
samsung_clk_register_alias(s3c2443_aliases, samsung_clk_register_alias(ctx, s3c2443_aliases,
ARRAY_SIZE(s3c2443_aliases)); ARRAY_SIZE(s3c2443_aliases));
break; break;
} }
......
...@@ -442,12 +442,14 @@ static struct samsung_clock_alias s3c6410_clock_aliases[] = { ...@@ -442,12 +442,14 @@ static struct samsung_clock_alias s3c6410_clock_aliases[] = {
ALIAS(MEM0_SROM, NULL, "srom"), ALIAS(MEM0_SROM, NULL, "srom"),
}; };
static void __init s3c64xx_clk_register_fixed_ext(unsigned long fin_pll_f, static void __init s3c64xx_clk_register_fixed_ext(
unsigned long xusbxti_f) struct samsung_clk_provider *ctx,
unsigned long fin_pll_f,
unsigned long xusbxti_f)
{ {
s3c64xx_fixed_rate_ext_clks[0].fixed_rate = fin_pll_f; s3c64xx_fixed_rate_ext_clks[0].fixed_rate = fin_pll_f;
s3c64xx_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f; s3c64xx_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f;
samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_ext_clks, samsung_clk_register_fixed_rate(ctx, s3c64xx_fixed_rate_ext_clks,
ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks)); ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks));
} }
...@@ -456,6 +458,8 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, ...@@ -456,6 +458,8 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
unsigned long xusbxti_f, bool s3c6400, unsigned long xusbxti_f, bool s3c6400,
void __iomem *base) void __iomem *base)
{ {
struct samsung_clk_provider *ctx;
reg_base = base; reg_base = base;
is_s3c6400 = s3c6400; is_s3c6400 = s3c6400;
...@@ -465,48 +469,50 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, ...@@ -465,48 +469,50 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
panic("%s: failed to map registers\n", __func__); panic("%s: failed to map registers\n", __func__);
} }
samsung_clk_init(np, reg_base, NR_CLKS); ctx = samsung_clk_init(np, reg_base, NR_CLKS);
if (!ctx)
panic("%s: unable to allocate context.\n", __func__);
/* Register external clocks. */ /* Register external clocks. */
if (!np) if (!np)
s3c64xx_clk_register_fixed_ext(xtal_f, xusbxti_f); s3c64xx_clk_register_fixed_ext(ctx, xtal_f, xusbxti_f);
/* Register PLLs. */ /* Register PLLs. */
samsung_clk_register_pll(s3c64xx_pll_clks, samsung_clk_register_pll(ctx, s3c64xx_pll_clks,
ARRAY_SIZE(s3c64xx_pll_clks), reg_base); ARRAY_SIZE(s3c64xx_pll_clks), reg_base);
/* Register common internal clocks. */ /* Register common internal clocks. */
samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_clks, samsung_clk_register_fixed_rate(ctx, s3c64xx_fixed_rate_clks,
ARRAY_SIZE(s3c64xx_fixed_rate_clks)); ARRAY_SIZE(s3c64xx_fixed_rate_clks));
samsung_clk_register_mux(s3c64xx_mux_clks, samsung_clk_register_mux(ctx, s3c64xx_mux_clks,
ARRAY_SIZE(s3c64xx_mux_clks)); ARRAY_SIZE(s3c64xx_mux_clks));
samsung_clk_register_div(s3c64xx_div_clks, samsung_clk_register_div(ctx, s3c64xx_div_clks,
ARRAY_SIZE(s3c64xx_div_clks)); ARRAY_SIZE(s3c64xx_div_clks));
samsung_clk_register_gate(s3c64xx_gate_clks, samsung_clk_register_gate(ctx, s3c64xx_gate_clks,
ARRAY_SIZE(s3c64xx_gate_clks)); ARRAY_SIZE(s3c64xx_gate_clks));
/* Register SoC-specific clocks. */ /* Register SoC-specific clocks. */
if (is_s3c6400) { if (is_s3c6400) {
samsung_clk_register_mux(s3c6400_mux_clks, samsung_clk_register_mux(ctx, s3c6400_mux_clks,
ARRAY_SIZE(s3c6400_mux_clks)); ARRAY_SIZE(s3c6400_mux_clks));
samsung_clk_register_div(s3c6400_div_clks, samsung_clk_register_div(ctx, s3c6400_div_clks,
ARRAY_SIZE(s3c6400_div_clks)); ARRAY_SIZE(s3c6400_div_clks));
samsung_clk_register_gate(s3c6400_gate_clks, samsung_clk_register_gate(ctx, s3c6400_gate_clks,
ARRAY_SIZE(s3c6400_gate_clks)); ARRAY_SIZE(s3c6400_gate_clks));
samsung_clk_register_alias(s3c6400_clock_aliases, samsung_clk_register_alias(ctx, s3c6400_clock_aliases,
ARRAY_SIZE(s3c6400_clock_aliases)); ARRAY_SIZE(s3c6400_clock_aliases));
} else { } else {
samsung_clk_register_mux(s3c6410_mux_clks, samsung_clk_register_mux(ctx, s3c6410_mux_clks,
ARRAY_SIZE(s3c6410_mux_clks)); ARRAY_SIZE(s3c6410_mux_clks));
samsung_clk_register_div(s3c6410_div_clks, samsung_clk_register_div(ctx, s3c6410_div_clks,
ARRAY_SIZE(s3c6410_div_clks)); ARRAY_SIZE(s3c6410_div_clks));
samsung_clk_register_gate(s3c6410_gate_clks, samsung_clk_register_gate(ctx, s3c6410_gate_clks,
ARRAY_SIZE(s3c6410_gate_clks)); ARRAY_SIZE(s3c6410_gate_clks));
samsung_clk_register_alias(s3c6410_clock_aliases, samsung_clk_register_alias(ctx, s3c6410_clock_aliases,
ARRAY_SIZE(s3c6410_clock_aliases)); ARRAY_SIZE(s3c6410_clock_aliases));
} }
samsung_clk_register_alias(s3c64xx_clock_aliases, samsung_clk_register_alias(ctx, s3c64xx_clock_aliases,
ARRAY_SIZE(s3c64xx_clock_aliases)); ARRAY_SIZE(s3c64xx_clock_aliases));
s3c64xx_clk_sleep_init(); s3c64xx_clk_sleep_init();
......
...@@ -14,13 +14,6 @@ ...@@ -14,13 +14,6 @@
#include <linux/syscore_ops.h> #include <linux/syscore_ops.h>
#include "clk.h" #include "clk.h"
static DEFINE_SPINLOCK(lock);
static struct clk **clk_table;
static void __iomem *reg_base;
#ifdef CONFIG_OF
static struct clk_onecell_data clk_data;
#endif
void samsung_clk_save(void __iomem *base, void samsung_clk_save(void __iomem *base,
struct samsung_clk_reg_dump *rd, struct samsung_clk_reg_dump *rd,
unsigned int num_regs) unsigned int num_regs)
...@@ -55,40 +48,53 @@ struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump( ...@@ -55,40 +48,53 @@ struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
} }
/* setup the essentials required to support clock lookup using ccf */ /* setup the essentials required to support clock lookup using ccf */
void __init samsung_clk_init(struct device_node *np, void __iomem *base, struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np,
unsigned long nr_clks) void __iomem *base, unsigned long nr_clks)
{ {
reg_base = base; struct samsung_clk_provider *ctx;
struct clk **clk_table;
int ret;
ctx = kzalloc(sizeof(struct samsung_clk_provider), GFP_KERNEL);
if (!ctx)
panic("could not allocate clock provider context.\n");
clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL); clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL);
if (!clk_table) if (!clk_table)
panic("could not allocate clock lookup table\n"); panic("could not allocate clock lookup table\n");
ctx->reg_base = base;
ctx->clk_data.clks = clk_table;
ctx->clk_data.clk_num = nr_clks;
spin_lock_init(&ctx->lock);
if (!np) if (!np)
return; return ctx;
#ifdef CONFIG_OF ret = of_clk_add_provider(np, of_clk_src_onecell_get,
clk_data.clks = clk_table; &ctx->clk_data);
clk_data.clk_num = nr_clks; if (ret)
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); panic("could not register clock provide\n");
#endif
return ctx;
} }
/* add a clock instance to the clock lookup table used for dt based lookup */ /* add a clock instance to the clock lookup table used for dt based lookup */
void samsung_clk_add_lookup(struct clk *clk, unsigned int id) void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, struct clk *clk,
unsigned int id)
{ {
if (clk_table && id) if (ctx->clk_data.clks && id)
clk_table[id] = clk; ctx->clk_data.clks[id] = clk;
} }
/* register a list of aliases */ /* register a list of aliases */
void __init samsung_clk_register_alias(struct samsung_clock_alias *list, void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
unsigned int nr_clk) struct samsung_clock_alias *list,
unsigned int nr_clk)
{ {
struct clk *clk; struct clk *clk;
unsigned int idx, ret; unsigned int idx, ret;
if (!clk_table) { if (!ctx->clk_data.clks) {
pr_err("%s: clock table missing\n", __func__); pr_err("%s: clock table missing\n", __func__);
return; return;
} }
...@@ -100,7 +106,7 @@ void __init samsung_clk_register_alias(struct samsung_clock_alias *list, ...@@ -100,7 +106,7 @@ void __init samsung_clk_register_alias(struct samsung_clock_alias *list,
continue; continue;
} }
clk = clk_table[list->id]; clk = ctx->clk_data.clks[list->id];
if (!clk) { if (!clk) {
pr_err("%s: failed to find clock %d\n", __func__, pr_err("%s: failed to find clock %d\n", __func__,
list->id); list->id);
...@@ -115,7 +121,7 @@ void __init samsung_clk_register_alias(struct samsung_clock_alias *list, ...@@ -115,7 +121,7 @@ void __init samsung_clk_register_alias(struct samsung_clock_alias *list,
} }
/* register a list of fixed clocks */ /* register a list of fixed clocks */
void __init samsung_clk_register_fixed_rate( void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
struct samsung_fixed_rate_clock *list, unsigned int nr_clk) struct samsung_fixed_rate_clock *list, unsigned int nr_clk)
{ {
struct clk *clk; struct clk *clk;
...@@ -130,7 +136,7 @@ void __init samsung_clk_register_fixed_rate( ...@@ -130,7 +136,7 @@ void __init samsung_clk_register_fixed_rate(
continue; continue;
} }
samsung_clk_add_lookup(clk, list->id); samsung_clk_add_lookup(ctx, clk, list->id);
/* /*
* Unconditionally add a clock lookup for the fixed rate clocks. * Unconditionally add a clock lookup for the fixed rate clocks.
...@@ -144,7 +150,7 @@ void __init samsung_clk_register_fixed_rate( ...@@ -144,7 +150,7 @@ void __init samsung_clk_register_fixed_rate(
} }
/* register a list of fixed factor clocks */ /* register a list of fixed factor clocks */
void __init samsung_clk_register_fixed_factor( void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx,
struct samsung_fixed_factor_clock *list, unsigned int nr_clk) struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
{ {
struct clk *clk; struct clk *clk;
...@@ -159,28 +165,30 @@ void __init samsung_clk_register_fixed_factor( ...@@ -159,28 +165,30 @@ void __init samsung_clk_register_fixed_factor(
continue; continue;
} }
samsung_clk_add_lookup(clk, list->id); samsung_clk_add_lookup(ctx, clk, list->id);
} }
} }
/* register a list of mux clocks */ /* register a list of mux clocks */
void __init samsung_clk_register_mux(struct samsung_mux_clock *list, void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
unsigned int nr_clk) struct samsung_mux_clock *list,
unsigned int nr_clk)
{ {
struct clk *clk; struct clk *clk;
unsigned int idx, ret; unsigned int idx, ret;
for (idx = 0; idx < nr_clk; idx++, list++) { for (idx = 0; idx < nr_clk; idx++, list++) {
clk = clk_register_mux(NULL, list->name, list->parent_names, clk = clk_register_mux(NULL, list->name, list->parent_names,
list->num_parents, list->flags, reg_base + list->offset, list->num_parents, list->flags,
list->shift, list->width, list->mux_flags, &lock); ctx->reg_base + list->offset,
list->shift, list->width, list->mux_flags, &ctx->lock);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__, pr_err("%s: failed to register clock %s\n", __func__,
list->name); list->name);
continue; continue;
} }
samsung_clk_add_lookup(clk, list->id); samsung_clk_add_lookup(ctx, clk, list->id);
/* register a clock lookup only if a clock alias is specified */ /* register a clock lookup only if a clock alias is specified */
if (list->alias) { if (list->alias) {
...@@ -194,8 +202,9 @@ void __init samsung_clk_register_mux(struct samsung_mux_clock *list, ...@@ -194,8 +202,9 @@ void __init samsung_clk_register_mux(struct samsung_mux_clock *list,
} }
/* register a list of div clocks */ /* register a list of div clocks */
void __init samsung_clk_register_div(struct samsung_div_clock *list, void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
unsigned int nr_clk) struct samsung_div_clock *list,
unsigned int nr_clk)
{ {
struct clk *clk; struct clk *clk;
unsigned int idx, ret; unsigned int idx, ret;
...@@ -203,22 +212,22 @@ void __init samsung_clk_register_div(struct samsung_div_clock *list, ...@@ -203,22 +212,22 @@ void __init samsung_clk_register_div(struct samsung_div_clock *list,
for (idx = 0; idx < nr_clk; idx++, list++) { for (idx = 0; idx < nr_clk; idx++, list++) {
if (list->table) if (list->table)
clk = clk_register_divider_table(NULL, list->name, clk = clk_register_divider_table(NULL, list->name,
list->parent_name, list->flags, list->parent_name, list->flags,
reg_base + list->offset, list->shift, ctx->reg_base + list->offset,
list->width, list->div_flags, list->shift, list->width, list->div_flags,
list->table, &lock); list->table, &ctx->lock);
else else
clk = clk_register_divider(NULL, list->name, clk = clk_register_divider(NULL, list->name,
list->parent_name, list->flags, list->parent_name, list->flags,
reg_base + list->offset, list->shift, ctx->reg_base + list->offset, list->shift,
list->width, list->div_flags, &lock); list->width, list->div_flags, &ctx->lock);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__, pr_err("%s: failed to register clock %s\n", __func__,
list->name); list->name);
continue; continue;
} }
samsung_clk_add_lookup(clk, list->id); samsung_clk_add_lookup(ctx, clk, list->id);
/* register a clock lookup only if a clock alias is specified */ /* register a clock lookup only if a clock alias is specified */
if (list->alias) { if (list->alias) {
...@@ -232,16 +241,17 @@ void __init samsung_clk_register_div(struct samsung_div_clock *list, ...@@ -232,16 +241,17 @@ void __init samsung_clk_register_div(struct samsung_div_clock *list,
} }
/* register a list of gate clocks */ /* register a list of gate clocks */
void __init samsung_clk_register_gate(struct samsung_gate_clock *list, void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
unsigned int nr_clk) struct samsung_gate_clock *list,
unsigned int nr_clk)
{ {
struct clk *clk; struct clk *clk;
unsigned int idx, ret; unsigned int idx, ret;
for (idx = 0; idx < nr_clk; idx++, list++) { for (idx = 0; idx < nr_clk; idx++, list++) {
clk = clk_register_gate(NULL, list->name, list->parent_name, 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); list->bit_idx, list->gate_flags, &ctx->lock);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__, pr_err("%s: failed to register clock %s\n", __func__,
list->name); list->name);
...@@ -257,7 +267,7 @@ void __init samsung_clk_register_gate(struct samsung_gate_clock *list, ...@@ -257,7 +267,7 @@ void __init samsung_clk_register_gate(struct samsung_gate_clock *list,
__func__, list->alias); __func__, list->alias);
} }
samsung_clk_add_lookup(clk, list->id); samsung_clk_add_lookup(ctx, clk, list->id);
} }
} }
...@@ -266,21 +276,21 @@ void __init samsung_clk_register_gate(struct samsung_gate_clock *list, ...@@ -266,21 +276,21 @@ void __init samsung_clk_register_gate(struct samsung_gate_clock *list,
* tree and register it * tree and register it
*/ */
#ifdef CONFIG_OF #ifdef CONFIG_OF
void __init samsung_clk_of_register_fixed_ext( void __init samsung_clk_of_register_fixed_ext(struct samsung_clk_provider *ctx,
struct samsung_fixed_rate_clock *fixed_rate_clk, struct samsung_fixed_rate_clock *fixed_rate_clk,
unsigned int nr_fixed_rate_clk, unsigned int nr_fixed_rate_clk,
struct of_device_id *clk_matches) struct of_device_id *clk_matches)
{ {
const struct of_device_id *match; const struct of_device_id *match;
struct device_node *np; struct device_node *clk_np;
u32 freq; u32 freq;
for_each_matching_node_and_match(np, clk_matches, &match) { for_each_matching_node_and_match(clk_np, clk_matches, &match) {
if (of_property_read_u32(np, "clock-frequency", &freq)) if (of_property_read_u32(clk_np, "clock-frequency", &freq))
continue; continue;
fixed_rate_clk[(u32)match->data].fixed_rate = freq; fixed_rate_clk[(u32)match->data].fixed_rate = freq;
} }
samsung_clk_register_fixed_rate(fixed_rate_clk, nr_fixed_rate_clk); samsung_clk_register_fixed_rate(ctx, fixed_rate_clk, nr_fixed_rate_clk);
} }
#endif #endif
......
...@@ -21,6 +21,18 @@ ...@@ -21,6 +21,18 @@
#include <linux/of_address.h> #include <linux/of_address.h>
#include "clk-pll.h" #include "clk-pll.h"
/**
* struct samsung_clk_provider: information about clock provider
* @reg_base: virtual address for the register base.
* @clk_data: holds clock related data like clk* and number of clocks.
* @lock: maintains exclusion bwtween callbacks for a given clock-provider.
*/
struct samsung_clk_provider {
void __iomem *reg_base;
struct clk_onecell_data clk_data;
spinlock_t lock;
};
/** /**
* struct samsung_clock_alias: information about mux clock * struct samsung_clock_alias: information about mux clock
* @id: platform specific id of the clock. * @id: platform specific id of the clock.
...@@ -312,40 +324,52 @@ struct samsung_pll_clock { ...@@ -312,40 +324,52 @@ struct samsung_pll_clock {
__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \
_lock, _con, _rtable, _alias) _lock, _con, _rtable, _alias)
extern void __init samsung_clk_init(struct device_node *np, void __iomem *base, extern struct samsung_clk_provider *__init samsung_clk_init(
unsigned long nr_clks); struct device_node *np, void __iomem *base,
unsigned long nr_clks);
extern void __init samsung_clk_of_register_fixed_ext( extern void __init samsung_clk_of_register_fixed_ext(
struct samsung_fixed_rate_clock *fixed_rate_clk, struct samsung_clk_provider *ctx,
unsigned int nr_fixed_rate_clk, struct samsung_fixed_rate_clock *fixed_rate_clk,
struct of_device_id *clk_matches); unsigned int nr_fixed_rate_clk,
struct of_device_id *clk_matches);
extern void samsung_clk_add_lookup(struct clk *clk, unsigned int id); extern void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
struct clk *clk, unsigned int id);
extern void samsung_clk_register_alias(struct samsung_clock_alias *list, extern void samsung_clk_register_alias(struct samsung_clk_provider *ctx,
unsigned int nr_clk); struct samsung_clock_alias *list,
unsigned int nr_clk);
extern void __init samsung_clk_register_fixed_rate( extern void __init samsung_clk_register_fixed_rate(
struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk); struct samsung_clk_provider *ctx,
struct samsung_fixed_rate_clock *clk_list,
unsigned int nr_clk);
extern void __init samsung_clk_register_fixed_factor( extern void __init samsung_clk_register_fixed_factor(
struct samsung_fixed_factor_clock *list, unsigned int nr_clk); struct samsung_clk_provider *ctx,
extern void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list, struct samsung_fixed_factor_clock *list,
unsigned int nr_clk); unsigned int nr_clk);
extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list, extern void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
unsigned int nr_clk); struct samsung_mux_clock *clk_list,
extern void __init samsung_clk_register_gate( unsigned int nr_clk);
struct samsung_gate_clock *clk_list, unsigned int nr_clk); extern void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
extern void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list, struct samsung_div_clock *clk_list,
unsigned int nr_clk, void __iomem *base); unsigned int nr_clk);
extern void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
struct samsung_gate_clock *clk_list,
unsigned int nr_clk);
extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
struct samsung_pll_clock *pll_list,
unsigned int nr_clk, void __iomem *base);
extern unsigned long _get_rate(const char *clk_name); extern unsigned long _get_rate(const char *clk_name);
extern void samsung_clk_save(void __iomem *base, extern void samsung_clk_save(void __iomem *base,
struct samsung_clk_reg_dump *rd, struct samsung_clk_reg_dump *rd,
unsigned int num_regs); unsigned int num_regs);
extern void samsung_clk_restore(void __iomem *base, extern void samsung_clk_restore(void __iomem *base,
const struct samsung_clk_reg_dump *rd, const struct samsung_clk_reg_dump *rd,
unsigned int num_regs); unsigned int num_regs);
extern struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump( extern struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
const unsigned long *rdump, const unsigned long *rdump,
unsigned long nr_rdump); unsigned long nr_rdump);
#endif /* __SAMSUNG_CLK_H */ #endif /* __SAMSUNG_CLK_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment