summaryrefslogtreecommitdiff
path: root/drivers/clk
diff options
context:
space:
mode:
authorRahul Sharma <rahul.sharma@samsung.com>2013-12-24 14:41:34 +0100
committerChanho Park <chanho61.park@samsung.com>2014-11-18 12:00:08 +0900
commit543248143de24d5d60cbb56663806fea6841678a (patch)
tree16802f6e9dc7c3f10adfb58ffbaae59bae987d46 /drivers/clk
parent6d8bf4a1b0c69a68c905bb8617c9b73e0ea49079 (diff)
downloadlinux-3.10-543248143de24d5d60cbb56663806fea6841678a.tar.gz
linux-3.10-543248143de24d5d60cbb56663806fea6841678a.tar.bz2
linux-3.10-543248143de24d5d60cbb56663806fea6841678a.zip
clk/samsung: add support for multuple 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 mulitple clock providers and are forced to bypass this layer. This layer is modified acordingly to enable the support. Clockfile for exynos4, exynos5250, exynos5420, exynos5440 and S3c64xx are also modified as per changed helper functions. Signed-off-by: Rahul Sharma <rahul.sharma@samsung.com> [t.figa: Backported to 3.10 kernel] Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/samsung/clk-exynos4.c56
-rw-r--r--drivers/clk/samsung/clk-exynos5250.c18
-rw-r--r--drivers/clk/samsung/clk-exynos5440.c18
-rw-r--r--drivers/clk/samsung/clk.c161
-rw-r--r--drivers/clk/samsung/clk.h38
5 files changed, 178 insertions, 113 deletions
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index e37793ededd..96de2b4a303 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -984,7 +984,8 @@ static unsigned long exynos4_get_xom(void)
return xom;
}
-static void __init exynos4_clk_register_finpll(unsigned long xom)
+static void __init exynos4_clk_register_finpll(struct samsung_clk_provider *ctx,
+ unsigned long xom)
{
struct samsung_fixed_rate_clock fclk;
struct clk *clk;
@@ -1006,7 +1007,7 @@ static void __init exynos4_clk_register_finpll(unsigned long xom)
fclk.parent_name = NULL;
fclk.flags = CLK_IS_ROOT;
fclk.fixed_rate = finpll_f;
- samsung_clk_register_fixed_rate(&fclk, 1);
+ samsung_clk_register_fixed_rate(ctx, &fclk, 1);
}
@@ -1015,12 +1016,13 @@ static void __init exynos4_clk_register_finpll(unsigned long xom)
* xxti and xusbxti clocks. These clocks are then registered with the specified
* clock speed.
*/
-void __init exynos4_clk_register_fixed_ext(unsigned long xxti_f,
+void __init exynos4_clk_register_fixed_ext(struct samsung_clk_provider *ctx,
+ unsigned long xxti_f,
unsigned long xusbxti_f)
{
exynos4_fixed_rate_ext_clks[0].fixed_rate = xxti_f;
exynos4_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f;
- samsung_clk_register_fixed_rate(exynos4_fixed_rate_ext_clks,
+ samsung_clk_register_fixed_rate(ctx, exynos4_fixed_rate_ext_clks,
ARRAY_SIZE(exynos4_fixed_rate_ext_clks));
}
@@ -1091,6 +1093,7 @@ struct pll_pms pll45xx_exynos4210_pll45xx_pms[] = {
void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_soc, void __iomem *reg_base, unsigned long xom)
{
struct clk *apll, *mpll, *epll, *vpll;
+ struct samsung_clk_provider *ctx;
if (np) {
reg_base = of_iomap(np, 0);
@@ -1099,25 +1102,28 @@ void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_so
}
if (exynos4_soc == EXYNOS4210)
- samsung_clk_init(np, reg_base, nr_clks,
+ ctx = samsung_clk_init(np, reg_base, nr_clks,
exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs),
exynos4210_clk_save, ARRAY_SIZE(exynos4210_clk_save));
else
- samsung_clk_init(np, reg_base, nr_clks,
+ ctx = samsung_clk_init(np, reg_base, nr_clks,
exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs),
exynos4x12_clk_save, ARRAY_SIZE(exynos4x12_clk_save));
+ if (!ctx)
+ panic("%s: unable to allocate context.\n", __func__);
if (np)
- samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks,
+ samsung_clk_of_register_fixed_ext(ctx,
+ exynos4_fixed_rate_ext_clks,
ARRAY_SIZE(exynos4_fixed_rate_ext_clks),
ext_clk_match);
- exynos4_clk_register_finpll(xom);
- samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
+ exynos4_clk_register_finpll(ctx, xom);
+ samsung_clk_register_fixed_rate(ctx, exynos4_fixed_rate_clks,
ARRAY_SIZE(exynos4_fixed_rate_clks));
if (exynos4_soc == EXYNOS4210) {
- samsung_clk_register_mux(exynos4210_mux_clks,
+ samsung_clk_register_mux(ctx, exynos4210_mux_clks,
ARRAY_SIZE(exynos4210_mux_clks));
apll = samsung_clk_register_pll45xx("fout_apll", "fin_pll",
@@ -1143,31 +1149,31 @@ void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_so
reg_base + VPLL_LOCK, exynos4_vpll_pms);
}
- samsung_clk_add_lookup(apll, fout_apll);
- samsung_clk_add_lookup(mpll, fout_mpll);
- samsung_clk_add_lookup(epll, fout_epll);
- samsung_clk_add_lookup(vpll, fout_vpll);
+ samsung_clk_add_lookup(ctx, apll, fout_apll);
+ samsung_clk_add_lookup(ctx, mpll, fout_mpll);
+ samsung_clk_add_lookup(ctx, epll, fout_epll);
+ samsung_clk_add_lookup(ctx, vpll, fout_vpll);
- samsung_clk_register_mux(exynos4_mux_clks,
+ samsung_clk_register_mux(ctx, exynos4_mux_clks,
ARRAY_SIZE(exynos4_mux_clks));
- samsung_clk_register_div(exynos4_div_clks,
+ samsung_clk_register_div(ctx, exynos4_div_clks,
ARRAY_SIZE(exynos4_div_clks));
- samsung_clk_register_gate(exynos4_gate_clks,
+ samsung_clk_register_gate(ctx, exynos4_gate_clks,
ARRAY_SIZE(exynos4_gate_clks));
if (exynos4_soc == EXYNOS4210) {
- samsung_clk_register_fixed_rate(exynos4210_fixed_rate_clks,
+ samsung_clk_register_fixed_rate(ctx, exynos4210_fixed_rate_clks,
ARRAY_SIZE(exynos4210_fixed_rate_clks));
- samsung_clk_register_div(exynos4210_div_clks,
+ samsung_clk_register_div(ctx, exynos4210_div_clks,
ARRAY_SIZE(exynos4210_div_clks));
- samsung_clk_register_gate(exynos4210_gate_clks,
+ samsung_clk_register_gate(ctx, exynos4210_gate_clks,
ARRAY_SIZE(exynos4210_gate_clks));
} else {
- samsung_clk_register_mux(exynos4x12_mux_clks,
+ samsung_clk_register_mux(ctx, exynos4x12_mux_clks,
ARRAY_SIZE(exynos4x12_mux_clks));
- samsung_clk_register_div(exynos4x12_div_clks,
+ samsung_clk_register_div(ctx, exynos4x12_div_clks,
ARRAY_SIZE(exynos4x12_div_clks));
- samsung_clk_register_gate(exynos4x12_gate_clks,
+ samsung_clk_register_gate(ctx, exynos4x12_gate_clks,
ARRAY_SIZE(exynos4x12_gate_clks));
}
@@ -1192,7 +1198,7 @@ void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_so
goto clkout_fail;
}
- samsung_clk_add_lookup(clk, mout_clkout);
+ samsung_clk_add_lookup(ctx, clk, mout_clkout);
clk = clk_register_gate(NULL, "clkout", "mout_clkout",
0, clkout_base, 0, CLK_GATE_SET_TO_DISABLE,
@@ -1203,7 +1209,7 @@ void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_so
goto clkout_fail;
}
- samsung_clk_add_lookup(clk, clkout);
+ samsung_clk_add_lookup(ctx, clk, clkout);
}
clkout_fail:
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index f09b423d539..63a3f315b92 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -513,6 +513,7 @@ static __initdata struct of_device_id ext_clk_match[] = {
void __init exynos5250_clk_init(struct device_node *np)
{
void __iomem *reg_base;
+ struct samsung_clk_provider *ctx;
struct clk *apll, *mpll, *epll, *vpll, *bpll, *gpll, *cpll;
if (np) {
@@ -523,10 +524,13 @@ void __init exynos5250_clk_init(struct device_node *np)
panic("%s: unable to determine soc\n", __func__);
}
- samsung_clk_init(np, reg_base, nr_clks,
+ ctx = samsung_clk_init(np, reg_base, nr_clks,
exynos5250_clk_regs, ARRAY_SIZE(exynos5250_clk_regs),
NULL, 0);
- 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),
ext_clk_match);
@@ -545,15 +549,15 @@ void __init exynos5250_clk_init(struct device_node *np)
vpll = samsung_clk_register_pll36xx("fout_vpll", "mout_vpllsrc",
reg_base + 0x10140);
- samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
+ samsung_clk_register_fixed_rate(ctx, exynos5250_fixed_rate_clks,
ARRAY_SIZE(exynos5250_fixed_rate_clks));
- samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks,
+ samsung_clk_register_fixed_factor(ctx, exynos5250_fixed_factor_clks,
ARRAY_SIZE(exynos5250_fixed_factor_clks));
- samsung_clk_register_mux(exynos5250_mux_clks,
+ samsung_clk_register_mux(ctx, exynos5250_mux_clks,
ARRAY_SIZE(exynos5250_mux_clks));
- samsung_clk_register_div(exynos5250_div_clks,
+ samsung_clk_register_div(ctx, exynos5250_div_clks,
ARRAY_SIZE(exynos5250_div_clks));
- samsung_clk_register_gate(exynos5250_gate_clks,
+ samsung_clk_register_gate(ctx, exynos5250_gate_clks,
ARRAY_SIZE(exynos5250_gate_clks));
pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c
index 7d5434167a9..4e6fc0fc7c1 100644
--- a/drivers/clk/samsung/clk-exynos5440.c
+++ b/drivers/clk/samsung/clk-exynos5440.c
@@ -106,6 +106,7 @@ static __initdata struct of_device_id ext_clk_match[] = {
void __init exynos5440_clk_init(struct device_node *np)
{
void __iomem *reg_base;
+ struct samsung_clk_provider *ctx;
reg_base = of_iomap(np, 0);
if (!reg_base) {
@@ -114,22 +115,25 @@ void __init exynos5440_clk_init(struct device_node *np)
return;
}
- samsung_clk_init(np, reg_base, nr_clks, NULL, 0, NULL, 0);
- samsung_clk_of_register_fixed_ext(exynos5440_fixed_rate_ext_clks,
+ ctx = samsung_clk_init(np, reg_base, nr_clks, NULL, 0, NULL, 0);
+ if (!ctx)
+ panic("%s: unable to allocate context.\n", __func__);
+
+ samsung_clk_of_register_fixed_ext(ctx, exynos5440_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match);
samsung_clk_register_pll2550x("cplla", "xtal", reg_base + 0x1c, 0x10);
samsung_clk_register_pll2550x("cpllb", "xtal", reg_base + 0x20, 0x10);
- samsung_clk_register_fixed_rate(exynos5440_fixed_rate_clks,
+ samsung_clk_register_fixed_rate(ctx, exynos5440_fixed_rate_clks,
ARRAY_SIZE(exynos5440_fixed_rate_clks));
- samsung_clk_register_fixed_factor(exynos5440_fixed_factor_clks,
+ samsung_clk_register_fixed_factor(ctx, exynos5440_fixed_factor_clks,
ARRAY_SIZE(exynos5440_fixed_factor_clks));
- samsung_clk_register_mux(exynos5440_mux_clks,
+ samsung_clk_register_mux(ctx, exynos5440_mux_clks,
ARRAY_SIZE(exynos5440_mux_clks));
- samsung_clk_register_div(exynos5440_div_clks,
+ samsung_clk_register_div(ctx, exynos5440_div_clks,
ARRAY_SIZE(exynos5440_div_clks));
- samsung_clk_register_gate(exynos5440_gate_clks,
+ samsung_clk_register_gate(ctx, exynos5440_gate_clks,
ARRAY_SIZE(exynos5440_gate_clks));
pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("armclk"));
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index cd3c40ab50f..ae15ba51808 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -14,35 +14,43 @@
#include <linux/syscore_ops.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
+static LIST_HEAD(samsung_clk_providers);
#ifdef CONFIG_PM_SLEEP
-static struct samsung_clk_reg_dump *reg_dump;
-static unsigned long nr_reg_dump;
+static void samsung_clk_suspend_provider(struct samsung_clk_provider *ctx)
+{
+ struct samsung_clk_reg_dump *rd = ctx->reg_dump;
+ unsigned long i;
-static int samsung_clk_suspend(void)
+ for (i = 0; i < ctx->nr_reg_dump; i++, rd++)
+ rd->value = __raw_readl(ctx->reg_base + rd->offset);
+}
+
+static void samsung_clk_resume_provider(struct samsung_clk_provider *ctx)
{
- struct samsung_clk_reg_dump *rd = reg_dump;
+ struct samsung_clk_reg_dump *rd = ctx->reg_dump;
unsigned long i;
- for (i = 0; i < nr_reg_dump; i++, rd++)
- rd->value = __raw_readl(reg_base + rd->offset);
+ for (i = 0; i < ctx->nr_reg_dump; i++, rd++)
+ __raw_writel(rd->value, ctx->reg_base + rd->offset);
+}
+
+static int samsung_clk_suspend(void)
+{
+ struct samsung_clk_provider *ctx;
+
+ list_for_each_entry(ctx, &samsung_clk_providers, list)
+ samsung_clk_suspend_provider(ctx);
return 0;
}
static void samsung_clk_resume(void)
{
- struct samsung_clk_reg_dump *rd = reg_dump;
- unsigned long i;
+ struct samsung_clk_provider *ctx;
- for (i = 0; i < nr_reg_dump; i++, rd++)
- __raw_writel(rd->value, reg_base + rd->offset);
+ list_for_each_entry(ctx, &samsung_clk_providers, list)
+ samsung_clk_resume_provider(ctx);
}
static struct syscore_ops samsung_clk_syscore_ops = {
@@ -52,62 +60,79 @@ static struct syscore_ops samsung_clk_syscore_ops = {
#endif /* CONFIG_PM_SLEEP */
/* 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,
+ void __iomem *base,
unsigned long nr_clks, unsigned long *rdump,
unsigned long nr_rdump, unsigned long *soc_rdump,
unsigned long nr_soc_rdump)
{
- reg_base = base;
+ struct samsung_clk_provider *ctx;
+
+ ctx = kzalloc(sizeof(struct samsung_clk_provider), GFP_KERNEL);
+ if (!ctx)
+ return NULL;
+
+ ctx->reg_base = base;
#ifdef CONFIG_PM_SLEEP
if (rdump && nr_rdump) {
unsigned int idx;
- reg_dump = kzalloc(sizeof(struct samsung_clk_reg_dump)
+ ctx->reg_dump = kzalloc(sizeof(struct samsung_clk_reg_dump)
* (nr_rdump + nr_soc_rdump), GFP_KERNEL);
- if (!reg_dump) {
+ if (!ctx->reg_dump) {
pr_err("%s: memory alloc for register dump failed\n",
__func__);
- return;
+ kfree(ctx);
+ return NULL;
}
for (idx = 0; idx < nr_rdump; idx++)
- reg_dump[idx].offset = rdump[idx];
+ ctx->reg_dump[idx].offset = rdump[idx];
for (idx = 0; idx < nr_soc_rdump; idx++)
- reg_dump[nr_rdump + idx].offset = soc_rdump[idx];
- nr_reg_dump = nr_rdump + nr_soc_rdump;
- register_syscore_ops(&samsung_clk_syscore_ops);
+ ctx->reg_dump[nr_rdump + idx].offset = soc_rdump[idx];
+ ctx->nr_reg_dump = nr_rdump + nr_soc_rdump;
+
+ if (list_empty(&samsung_clk_providers))
+ register_syscore_ops(&samsung_clk_syscore_ops);
}
#endif
- clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL);
- if (!clk_table)
+ ctx->clk_table = kzalloc(sizeof(struct clk *) * nr_clks,
+ GFP_KERNEL);
+ if (!ctx->clk_table)
panic("could not allocate clock lookup table\n");
+ list_add_tail(&ctx->list, &samsung_clk_providers);
+
if (!np)
- return;
+ return ctx;
#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);
+ ctx->clk_data.clks = ctx->clk_table;
+ ctx->clk_data.clk_num = nr_clks;
+ of_clk_add_provider(np, of_clk_src_onecell_get, &ctx->clk_data);
#endif
+
+ return ctx;
}
/* add a clock instance to the clock lookup table used for dt based lookup */
-void samsung_clk_add_lookup(struct clk *clk, unsigned int id)
+void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
+ struct clk *clk, unsigned int id)
{
- if (clk_table && id)
- clk_table[id] = clk;
+ if (ctx->clk_table && id)
+ ctx->clk_table[id] = clk;
}
/* 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,
+ struct samsung_clock_alias *list,
unsigned int nr_clk)
{
struct clk *clk;
unsigned int idx, ret;
- if (!clk_table) {
+ if (!ctx->clk_table) {
pr_err("%s: clock table missing\n", __func__);
return;
}
@@ -119,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);
@@ -134,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 samsung_clk_provider *ctx,
struct samsung_fixed_rate_clock *list, unsigned int nr_clk)
{
struct clk *clk;
@@ -149,7 +174,7 @@ void __init samsung_clk_register_fixed_rate(
continue;
}
- samsung_clk_add_lookup(clk, list->id);
+ samsung_clk_add_lookup(ctx, clk, list->id);
/*
* Unconditionally add a clock lookup for the fixed rate clocks.
@@ -163,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 samsung_clk_provider *ctx,
struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
{
struct clk *clk;
@@ -178,28 +203,30 @@ void __init samsung_clk_register_fixed_factor(
continue;
}
- samsung_clk_add_lookup(clk, list->id);
+ samsung_clk_add_lookup(ctx, clk, list->id);
}
}
/* register a list of mux clocks */
-void __init samsung_clk_register_mux(struct samsung_mux_clock *list,
- unsigned int nr_clk)
+void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
+ struct samsung_mux_clock *list,
+ unsigned int nr_clk)
{
struct clk *clk;
unsigned int idx, ret;
for (idx = 0; idx < nr_clk; idx++, list++) {
clk = clk_register_mux(NULL, list->name, list->parent_names,
- list->num_parents, list->flags, reg_base + list->offset,
- list->shift, list->width, list->mux_flags, &lock);
+ list->num_parents, list->flags,
+ ctx->reg_base + list->offset,
+ list->shift, list->width, list->mux_flags, &ctx->lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
continue;
}
- samsung_clk_add_lookup(clk, list->id);
+ samsung_clk_add_lookup(ctx, clk, list->id);
/* register a clock lookup only if a clock alias is specified */
if (list->alias) {
@@ -213,8 +240,9 @@ void __init samsung_clk_register_mux(struct samsung_mux_clock *list,
}
/* register a list of div clocks */
-void __init samsung_clk_register_div(struct samsung_div_clock *list,
- unsigned int nr_clk)
+void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
+ struct samsung_div_clock *list,
+ unsigned int nr_clk)
{
struct clk *clk;
unsigned int idx, ret;
@@ -222,22 +250,22 @@ void __init samsung_clk_register_div(struct samsung_div_clock *list,
for (idx = 0; idx < nr_clk; idx++, list++) {
if (list->table)
clk = clk_register_divider_table(NULL, list->name,
- list->parent_name, list->flags,
- reg_base + list->offset, list->shift,
- list->width, list->div_flags,
- list->table, &lock);
+ list->parent_name, list->flags,
+ ctx->reg_base + list->offset,
+ list->shift, list->width, list->div_flags,
+ list->table, &ctx->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, &ctx->lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
continue;
}
- samsung_clk_add_lookup(clk, list->id);
+ samsung_clk_add_lookup(ctx, clk, list->id);
/* register a clock lookup only if a clock alias is specified */
if (list->alias) {
@@ -251,16 +279,17 @@ void __init samsung_clk_register_div(struct samsung_div_clock *list,
}
/* register a list of gate clocks */
-void __init samsung_clk_register_gate(struct samsung_gate_clock *list,
- unsigned int nr_clk)
+void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
+ struct samsung_gate_clock *list,
+ unsigned int nr_clk)
{
struct clk *clk;
unsigned int idx, ret;
for (idx = 0; idx < nr_clk; idx++, list++) {
clk = clk_register_gate(NULL, list->name, list->parent_name,
- list->flags, reg_base + list->offset,
- list->bit_idx, list->gate_flags, &lock);
+ list->flags, ctx->reg_base + list->offset,
+ list->bit_idx, list->gate_flags, &ctx->lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
@@ -276,7 +305,7 @@ void __init samsung_clk_register_gate(struct samsung_gate_clock *list,
__func__, list->alias);
}
- samsung_clk_add_lookup(clk, list->id);
+ samsung_clk_add_lookup(ctx, clk, list->id);
}
}
@@ -285,21 +314,21 @@ void __init samsung_clk_register_gate(struct samsung_gate_clock *list,
* tree and register it
*/
#ifdef CONFIG_OF
-void __init samsung_clk_of_register_fixed_ext(
+void __init samsung_clk_of_register_fixed_ext(struct samsung_clk_provider *ctx,
struct samsung_fixed_rate_clock *fixed_rate_clk,
unsigned int nr_fixed_rate_clk,
struct of_device_id *clk_matches)
{
const struct of_device_id *match;
- struct device_node *np;
+ struct device_node *clk_np;
u32 freq;
- for_each_matching_node_and_match(np, clk_matches, &match) {
- if (of_property_read_u32(np, "clock-frequency", &freq))
+ for_each_matching_node_and_match(clk_np, clk_matches, &match) {
+ if (of_property_read_u32(clk_np, "clock-frequency", &freq))
continue;
fixed_rate_clk[(u32)match->data].fixed_rate = freq;
}
- samsung_clk_register_fixed_rate(fixed_rate_clk, nr_fixed_rate_clk);
+ samsung_clk_register_fixed_rate(ctx, fixed_rate_clk, nr_fixed_rate_clk);
}
#endif
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index e4ad6ea9aa7..8df13712219 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -20,6 +20,22 @@
#include <linux/of.h>
#include <linux/of_address.h>
+/* Context node which holds information about the clock provider. */
+/**
+ * struct samsung_clk_provider: information about clock plovider
+ * @reg_base: virtual address for the register base.
+ * @clk_data: holds clock related data like clk* and number of clocks.
+ */
+struct samsung_clk_provider {
+ void __iomem *reg_base;
+ struct clk **clk_table;
+ struct clk_onecell_data clk_data;
+ spinlock_t lock;
+ struct samsung_clk_reg_dump *reg_dump;
+ unsigned long nr_reg_dump;
+ struct list_head list;
+};
+
/**
* struct samsung_clock_alias: information about mux clock
* @id: platform specific id of the clock.
@@ -258,28 +274,34 @@ struct samsung_clk_reg_dump {
u32 value;
};
-extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
+extern struct samsung_clk_provider *__init samsung_clk_init(
+ struct device_node *np, void __iomem *base,
unsigned long nr_clks, unsigned long *rdump,
unsigned long nr_rdump, unsigned long *soc_rdump,
unsigned long nr_soc_rdump);
extern void __init samsung_clk_of_register_fixed_ext(
+ struct samsung_clk_provider *ctx,
struct samsung_fixed_rate_clock *fixed_rate_clk,
unsigned int nr_fixed_rate_clk,
struct of_device_id *clk_matches);
-extern void samsung_clk_add_lookup(struct clk *clk, unsigned int id);
+extern void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
+ struct clk *clk, unsigned int id);
-extern void samsung_clk_register_alias(struct samsung_clock_alias *list,
+extern void samsung_clk_register_alias(struct samsung_clk_provider *ctx,
+ struct samsung_clock_alias *list,
unsigned int nr_clk);
extern void __init samsung_clk_register_fixed_rate(
+ struct samsung_clk_provider *ctx,
struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk);
extern void __init samsung_clk_register_fixed_factor(
+ struct samsung_clk_provider *ctx,
struct samsung_fixed_factor_clock *list, unsigned int nr_clk);
-extern void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
- unsigned int nr_clk);
-extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
- unsigned int nr_clk);
-extern void __init samsung_clk_register_gate(
+extern void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
+ struct samsung_mux_clock *clk_list, unsigned int nr_clk);
+extern void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
+ struct samsung_div_clock *clk_list, 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 unsigned long _get_rate(const char *clk_name);