* [PATCH V2 0/3] clk: exynos-audss: Adapt to exising clock framework
@ 2014-07-11 12:00 ` Tushar Behera
0 siblings, 0 replies; 12+ messages in thread
From: Tushar Behera @ 2014-07-11 12:00 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel, linux-samsung-soc
Cc: kgene.kim, mturquette, t.figa, trblinux
Generic cleanup and usage of samsung clock register/unregister APIs.
The patches are tested on Exynos5800 based Peach-Pi board. More tests are
welcome.
Tushar Behera (3):
clk: exynos-audss: Simplify code to get clock names
clk: samsung: Add API to unregister clocks
clk: exynos-audss: Use samsung clock APIs to register/unregister
clocks
drivers/clk/samsung/clk-exynos-audss.c | 179 +++++++++++++-------------------
drivers/clk/samsung/clk.c | 19 ++++
drivers/clk/samsung/clk.h | 2 +
3 files changed, 95 insertions(+), 105 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH V2 0/3] clk: exynos-audss: Adapt to exising clock framework @ 2014-07-11 12:00 ` Tushar Behera 0 siblings, 0 replies; 12+ messages in thread From: Tushar Behera @ 2014-07-11 12:00 UTC (permalink / raw) To: linux-arm-kernel Generic cleanup and usage of samsung clock register/unregister APIs. The patches are tested on Exynos5800 based Peach-Pi board. More tests are welcome. Tushar Behera (3): clk: exynos-audss: Simplify code to get clock names clk: samsung: Add API to unregister clocks clk: exynos-audss: Use samsung clock APIs to register/unregister clocks drivers/clk/samsung/clk-exynos-audss.c | 179 +++++++++++++------------------- drivers/clk/samsung/clk.c | 19 ++++ drivers/clk/samsung/clk.h | 2 + 3 files changed, 95 insertions(+), 105 deletions(-) -- 1.7.9.5 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V2 1/3] clk: exynos-audss: Simplify code to get clock names 2014-07-11 12:00 ` Tushar Behera @ 2014-07-11 12:00 ` Tushar Behera -1 siblings, 0 replies; 12+ messages in thread From: Tushar Behera @ 2014-07-11 12:00 UTC (permalink / raw) To: linux-arm-kernel, linux-kernel, linux-samsung-soc Cc: kgene.kim, mturquette, t.figa, trblinux Instead of getting the clock names individually, it would be good to put the logic within a loop. Signed-off-by: Tushar Behera <tushar.b@samsung.com> --- Changes for V2: * Calling clk_put as soon as the clock is not required anymore drivers/clk/samsung/clk-exynos-audss.c | 35 +++++++++++++++++--------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index 13eae14c..1a5294c 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -80,10 +80,14 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) { int i, ret = 0; struct resource *res; + struct clk *tmp; + const char *clk_name_ref[] = { + "pll_ref", "pll_in", "cdclk", "sclk_audio", "sclk_pcm_in" }; + const char *clk_name_actual[] = { + "fin_pll", "fout_epll", "cdclk0", "sclk_audio0", "sclk_pcm0"}; const char *mout_audss_p[] = {"fin_pll", "fout_epll"}; const char *mout_i2s_p[] = {"mout_audss", "cdclk0", "sclk_audio0"}; const char *sclk_pcm_p = "sclk_pcm0"; - struct clk *pll_ref, *pll_in, *cdclk, *sclk_audio, *sclk_pcm_in; const struct of_device_id *match; enum exynos_audss_clk_type variant; @@ -111,23 +115,25 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) else clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS - 1; - pll_ref = devm_clk_get(&pdev->dev, "pll_ref"); - pll_in = devm_clk_get(&pdev->dev, "pll_in"); - if (!IS_ERR(pll_ref)) - mout_audss_p[0] = __clk_get_name(pll_ref); - if (!IS_ERR(pll_in)) - mout_audss_p[1] = __clk_get_name(pll_in); + for (i = 0; i < ARRAY_SIZE(clk_name_ref); i++) { + tmp = clk_get(&pdev->dev, clk_name_ref[i]); + if (!IS_ERR(tmp)) { + clk_name_actual[i] = __clk_get_name(tmp); + clk_put(tmp); + } + } + + mout_audss_p[0] = clk_name_actual[0]; + mout_audss_p[1] = clk_name_actual[1]; + mout_i2s_p[1] = clk_name_actual[2]; + mout_i2s_p[2] = clk_name_actual[3]; + sclk_pcm_p = clk_name_actual[4]; + clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss", mout_audss_p, ARRAY_SIZE(mout_audss_p), CLK_SET_RATE_NO_REPARENT, reg_base + ASS_CLK_SRC, 0, 1, 0, &lock); - cdclk = devm_clk_get(&pdev->dev, "cdclk"); - sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio"); - if (!IS_ERR(cdclk)) - mout_i2s_p[1] = __clk_get_name(cdclk); - if (!IS_ERR(sclk_audio)) - mout_i2s_p[2] = __clk_get_name(sclk_audio); clk_table[EXYNOS_MOUT_I2S] = clk_register_mux(NULL, "mout_i2s", mout_i2s_p, ARRAY_SIZE(mout_i2s_p), CLK_SET_RATE_NO_REPARENT, @@ -161,9 +167,6 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) "sclk_pcm", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 4, 0, &lock); - sclk_pcm_in = devm_clk_get(&pdev->dev, "sclk_pcm_in"); - if (!IS_ERR(sclk_pcm_in)) - sclk_pcm_p = __clk_get_name(sclk_pcm_in); clk_table[EXYNOS_SCLK_PCM] = clk_register_gate(NULL, "sclk_pcm", sclk_pcm_p, CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 5, 0, &lock); -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH V2 1/3] clk: exynos-audss: Simplify code to get clock names @ 2014-07-11 12:00 ` Tushar Behera 0 siblings, 0 replies; 12+ messages in thread From: Tushar Behera @ 2014-07-11 12:00 UTC (permalink / raw) To: linux-arm-kernel Instead of getting the clock names individually, it would be good to put the logic within a loop. Signed-off-by: Tushar Behera <tushar.b@samsung.com> --- Changes for V2: * Calling clk_put as soon as the clock is not required anymore drivers/clk/samsung/clk-exynos-audss.c | 35 +++++++++++++++++--------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index 13eae14c..1a5294c 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -80,10 +80,14 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) { int i, ret = 0; struct resource *res; + struct clk *tmp; + const char *clk_name_ref[] = { + "pll_ref", "pll_in", "cdclk", "sclk_audio", "sclk_pcm_in" }; + const char *clk_name_actual[] = { + "fin_pll", "fout_epll", "cdclk0", "sclk_audio0", "sclk_pcm0"}; const char *mout_audss_p[] = {"fin_pll", "fout_epll"}; const char *mout_i2s_p[] = {"mout_audss", "cdclk0", "sclk_audio0"}; const char *sclk_pcm_p = "sclk_pcm0"; - struct clk *pll_ref, *pll_in, *cdclk, *sclk_audio, *sclk_pcm_in; const struct of_device_id *match; enum exynos_audss_clk_type variant; @@ -111,23 +115,25 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) else clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS - 1; - pll_ref = devm_clk_get(&pdev->dev, "pll_ref"); - pll_in = devm_clk_get(&pdev->dev, "pll_in"); - if (!IS_ERR(pll_ref)) - mout_audss_p[0] = __clk_get_name(pll_ref); - if (!IS_ERR(pll_in)) - mout_audss_p[1] = __clk_get_name(pll_in); + for (i = 0; i < ARRAY_SIZE(clk_name_ref); i++) { + tmp = clk_get(&pdev->dev, clk_name_ref[i]); + if (!IS_ERR(tmp)) { + clk_name_actual[i] = __clk_get_name(tmp); + clk_put(tmp); + } + } + + mout_audss_p[0] = clk_name_actual[0]; + mout_audss_p[1] = clk_name_actual[1]; + mout_i2s_p[1] = clk_name_actual[2]; + mout_i2s_p[2] = clk_name_actual[3]; + sclk_pcm_p = clk_name_actual[4]; + clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss", mout_audss_p, ARRAY_SIZE(mout_audss_p), CLK_SET_RATE_NO_REPARENT, reg_base + ASS_CLK_SRC, 0, 1, 0, &lock); - cdclk = devm_clk_get(&pdev->dev, "cdclk"); - sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio"); - if (!IS_ERR(cdclk)) - mout_i2s_p[1] = __clk_get_name(cdclk); - if (!IS_ERR(sclk_audio)) - mout_i2s_p[2] = __clk_get_name(sclk_audio); clk_table[EXYNOS_MOUT_I2S] = clk_register_mux(NULL, "mout_i2s", mout_i2s_p, ARRAY_SIZE(mout_i2s_p), CLK_SET_RATE_NO_REPARENT, @@ -161,9 +167,6 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) "sclk_pcm", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 4, 0, &lock); - sclk_pcm_in = devm_clk_get(&pdev->dev, "sclk_pcm_in"); - if (!IS_ERR(sclk_pcm_in)) - sclk_pcm_p = __clk_get_name(sclk_pcm_in); clk_table[EXYNOS_SCLK_PCM] = clk_register_gate(NULL, "sclk_pcm", sclk_pcm_p, CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 5, 0, &lock); -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH V2 2/3] clk: samsung: Add API to unregister clocks 2014-07-11 12:00 ` Tushar Behera @ 2014-07-11 12:00 ` Tushar Behera -1 siblings, 0 replies; 12+ messages in thread From: Tushar Behera @ 2014-07-11 12:00 UTC (permalink / raw) To: linux-arm-kernel, linux-kernel, linux-samsung-soc Cc: kgene.kim, mturquette, t.figa, trblinux Added an API to unregister all the clocks defined within a context. This is helpful in case where the clock is registered through a platform driver and we want to unregister the clocks during remove callback. Signed-off-by: Tushar Behera <tushar.b@samsung.com> --- Changelog: This is new patch required because of changes to patch 3/3. drivers/clk/samsung/clk.c | 19 +++++++++++++++++++ drivers/clk/samsung/clk.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index 49629c7..b9310b9 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -83,6 +83,25 @@ struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np, return ctx; } +/* API to remove a clock provider */ +void samsung_clk_exit(struct device_node *np, struct samsung_clk_provider *ctx) +{ + int i; + + if (np) + of_clk_del_provider(np); + + if (!ctx) + return; + + for (i = 0; i < ctx->clk_data.clk_num; i++) + if (!IS_ERR(ctx->clk_data.clks[i])) + clk_unregister(ctx->clk_data.clks[i]); + + kfree(ctx->clk_data.clks); + kfree(ctx); +} + /* add a clock instance to the clock lookup table used for dt based lookup */ void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, struct clk *clk, unsigned int id) diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index 9693b80..8ecc85a 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -327,6 +327,8 @@ struct samsung_pll_clock { extern struct samsung_clk_provider *__init samsung_clk_init( struct device_node *np, void __iomem *base, unsigned long nr_clks); +extern void samsung_clk_exit(struct device_node *np, + struct samsung_clk_provider *ctx); extern void __init samsung_clk_of_register_fixed_ext( struct samsung_clk_provider *ctx, struct samsung_fixed_rate_clock *fixed_rate_clk, -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH V2 2/3] clk: samsung: Add API to unregister clocks @ 2014-07-11 12:00 ` Tushar Behera 0 siblings, 0 replies; 12+ messages in thread From: Tushar Behera @ 2014-07-11 12:00 UTC (permalink / raw) To: linux-arm-kernel Added an API to unregister all the clocks defined within a context. This is helpful in case where the clock is registered through a platform driver and we want to unregister the clocks during remove callback. Signed-off-by: Tushar Behera <tushar.b@samsung.com> --- Changelog: This is new patch required because of changes to patch 3/3. drivers/clk/samsung/clk.c | 19 +++++++++++++++++++ drivers/clk/samsung/clk.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index 49629c7..b9310b9 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -83,6 +83,25 @@ struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np, return ctx; } +/* API to remove a clock provider */ +void samsung_clk_exit(struct device_node *np, struct samsung_clk_provider *ctx) +{ + int i; + + if (np) + of_clk_del_provider(np); + + if (!ctx) + return; + + for (i = 0; i < ctx->clk_data.clk_num; i++) + if (!IS_ERR(ctx->clk_data.clks[i])) + clk_unregister(ctx->clk_data.clks[i]); + + kfree(ctx->clk_data.clks); + kfree(ctx); +} + /* add a clock instance to the clock lookup table used for dt based lookup */ void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, struct clk *clk, unsigned int id) diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index 9693b80..8ecc85a 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -327,6 +327,8 @@ struct samsung_pll_clock { extern struct samsung_clk_provider *__init samsung_clk_init( struct device_node *np, void __iomem *base, unsigned long nr_clks); +extern void samsung_clk_exit(struct device_node *np, + struct samsung_clk_provider *ctx); extern void __init samsung_clk_of_register_fixed_ext( struct samsung_clk_provider *ctx, struct samsung_fixed_rate_clock *fixed_rate_clk, -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH V2 3/3] clk: exynos-audss: Use samsung clock APIs to register/unregister clocks 2014-07-11 12:00 ` Tushar Behera @ 2014-07-11 12:00 ` Tushar Behera -1 siblings, 0 replies; 12+ messages in thread From: Tushar Behera @ 2014-07-11 12:00 UTC (permalink / raw) To: linux-arm-kernel, linux-kernel, linux-samsung-soc Cc: kgene.kim, mturquette, t.figa, trblinux Using samsung clock APIs to register/unregister clocks will save some lines of code. Signed-off-by: Tushar Behera <tushar.b@samsung.com> --- Changes of v2: * Retain platform driver structure. drivers/clk/samsung/clk-exynos-audss.c | 146 ++++++++++++-------------------- 1 file changed, 56 insertions(+), 90 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index 1a5294c..2b90967 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -19,16 +19,16 @@ #include <dt-bindings/clock/exynos-audss-clk.h> +#include "clk.h" + enum exynos_audss_clk_type { TYPE_EXYNOS4210, TYPE_EXYNOS5250, TYPE_EXYNOS5420, }; -static DEFINE_SPINLOCK(lock); -static struct clk **clk_table; +static struct samsung_clk_provider *ctx; static void __iomem *reg_base; -static struct clk_onecell_data clk_data; #define ASS_CLK_SRC 0x0 #define ASS_CLK_DIV 0x4 @@ -78,7 +78,7 @@ static const struct of_device_id exynos_audss_clk_of_match[] = { /* register exynos_audss clocks */ static int exynos_audss_clk_probe(struct platform_device *pdev) { - int i, ret = 0; + int i; struct resource *res; struct clk *tmp; const char *clk_name_ref[] = { @@ -87,14 +87,51 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) "fin_pll", "fout_epll", "cdclk0", "sclk_audio0", "sclk_pcm0"}; const char *mout_audss_p[] = {"fin_pll", "fout_epll"}; const char *mout_i2s_p[] = {"mout_audss", "cdclk0", "sclk_audio0"}; - const char *sclk_pcm_p = "sclk_pcm0"; + char sclk_pcm_p[32]; const struct of_device_id *match; enum exynos_audss_clk_type variant; + struct samsung_mux_clock exynos_audss_mux_clks[] = { + MUX(EXYNOS_MOUT_AUDSS, "mout_audss", mout_audss_p, + ASS_CLK_SRC, 0, 1), + MUX(EXYNOS_MOUT_I2S, "mout_i2s", mout_i2s_p, + ASS_CLK_SRC, 2, 2), + }; + + struct samsung_div_clock exynos_audss_div_clks[] = { + DIV(EXYNOS_DOUT_SRP, "dout_srp", "mout_audss", + ASS_CLK_DIV, 0, 4), + DIV(EXYNOS_DOUT_AUD_BUS, "dout_aud_bus", "dout_srp", + ASS_CLK_DIV, 4, 4), + DIV(EXYNOS_DOUT_I2S, "dout_i2s", "mout_i2s", ASS_CLK_DIV, 8, 4), + }; + + struct samsung_gate_clock exynos_audss_gate_clks[] = { + GATE(EXYNOS_SRP_CLK, "srp_clk", "dout_srp", + ASS_CLK_GATE, 0, CLK_SET_RATE_PARENT, 0), + GATE(EXYNOS_I2S_BUS, "i2s_bus", "dout_aud_bus", + ASS_CLK_GATE, 2, CLK_SET_RATE_PARENT, 0), + GATE(EXYNOS_SCLK_I2S, "sclk_i2s", "dout_i2s", + ASS_CLK_GATE, 3, CLK_SET_RATE_PARENT, 0), + GATE(EXYNOS_PCM_BUS, "pcm_bus", "sclk_pcm", + ASS_CLK_GATE, 4, CLK_SET_RATE_PARENT, 0), + GATE(EXYNOS_SCLK_PCM, "sclk_pcm", sclk_pcm_p, + ASS_CLK_GATE, 5, CLK_SET_RATE_PARENT, 0), + }; + + struct samsung_gate_clock exynos5420_audss_gate_clks[] = { + GATE(EXYNOS_ADMA, "adma", "dout_srp", + ASS_CLK_GATE, 9, CLK_SET_RATE_PARENT, 0), + }; + + int nr_clks = EXYNOS_AUDSS_MAX_CLKS; + match = of_match_node(exynos_audss_clk_of_match, pdev->dev.of_node); if (!match) return -EINVAL; variant = (enum exynos_audss_clk_type)match->data; + if (variant != TYPE_EXYNOS5420) + nr_clks--; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); reg_base = devm_ioremap_resource(&pdev->dev, res); @@ -103,17 +140,11 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) return PTR_ERR(reg_base); } - clk_table = devm_kzalloc(&pdev->dev, - sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS, - GFP_KERNEL); - if (!clk_table) + ctx = samsung_clk_init(pdev->dev.of_node, reg_base, nr_clks); + if (!ctx) { + dev_err(&pdev->dev, "failed to get clock provier context\n"); return -ENOMEM; - - clk_data.clks = clk_table; - if (variant == TYPE_EXYNOS5420) - clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS; - else - clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS - 1; + } for (i = 0; i < ARRAY_SIZE(clk_name_ref); i++) { tmp = clk_get(&pdev->dev, clk_name_ref[i]); @@ -127,69 +158,20 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) mout_audss_p[1] = clk_name_actual[1]; mout_i2s_p[1] = clk_name_actual[2]; mout_i2s_p[2] = clk_name_actual[3]; - sclk_pcm_p = clk_name_actual[4]; - - clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss", - mout_audss_p, ARRAY_SIZE(mout_audss_p), - CLK_SET_RATE_NO_REPARENT, - reg_base + ASS_CLK_SRC, 0, 1, 0, &lock); - - clk_table[EXYNOS_MOUT_I2S] = clk_register_mux(NULL, "mout_i2s", - mout_i2s_p, ARRAY_SIZE(mout_i2s_p), - CLK_SET_RATE_NO_REPARENT, - reg_base + ASS_CLK_SRC, 2, 2, 0, &lock); + strncpy(sclk_pcm_p, clk_name_actual[4], strlen(clk_name_actual[4])); - clk_table[EXYNOS_DOUT_SRP] = clk_register_divider(NULL, "dout_srp", - "mout_audss", 0, reg_base + ASS_CLK_DIV, 0, 4, - 0, &lock); + samsung_clk_register_mux(ctx, exynos_audss_mux_clks, + ARRAY_SIZE(exynos_audss_mux_clks)); - clk_table[EXYNOS_DOUT_AUD_BUS] = clk_register_divider(NULL, - "dout_aud_bus", "dout_srp", 0, - reg_base + ASS_CLK_DIV, 4, 4, 0, &lock); + samsung_clk_register_div(ctx, exynos_audss_div_clks, + ARRAY_SIZE(exynos_audss_div_clks)); - clk_table[EXYNOS_DOUT_I2S] = clk_register_divider(NULL, "dout_i2s", - "mout_i2s", 0, reg_base + ASS_CLK_DIV, 8, 4, 0, - &lock); - - clk_table[EXYNOS_SRP_CLK] = clk_register_gate(NULL, "srp_clk", - "dout_srp", CLK_SET_RATE_PARENT, - reg_base + ASS_CLK_GATE, 0, 0, &lock); - - clk_table[EXYNOS_I2S_BUS] = clk_register_gate(NULL, "i2s_bus", - "dout_aud_bus", CLK_SET_RATE_PARENT, - reg_base + ASS_CLK_GATE, 2, 0, &lock); - - clk_table[EXYNOS_SCLK_I2S] = clk_register_gate(NULL, "sclk_i2s", - "dout_i2s", CLK_SET_RATE_PARENT, - reg_base + ASS_CLK_GATE, 3, 0, &lock); - - clk_table[EXYNOS_PCM_BUS] = clk_register_gate(NULL, "pcm_bus", - "sclk_pcm", CLK_SET_RATE_PARENT, - reg_base + ASS_CLK_GATE, 4, 0, &lock); - - clk_table[EXYNOS_SCLK_PCM] = clk_register_gate(NULL, "sclk_pcm", - sclk_pcm_p, CLK_SET_RATE_PARENT, - reg_base + ASS_CLK_GATE, 5, 0, &lock); + samsung_clk_register_gate(ctx, exynos_audss_gate_clks, + ARRAY_SIZE(exynos_audss_gate_clks)); if (variant == TYPE_EXYNOS5420) { - clk_table[EXYNOS_ADMA] = clk_register_gate(NULL, "adma", - "dout_srp", CLK_SET_RATE_PARENT, - reg_base + ASS_CLK_GATE, 9, 0, &lock); - } - - for (i = 0; i < clk_data.clk_num; i++) { - if (IS_ERR(clk_table[i])) { - dev_err(&pdev->dev, "failed to register clock %d\n", i); - ret = PTR_ERR(clk_table[i]); - goto unregister; - } - } - - ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get, - &clk_data); - if (ret) { - dev_err(&pdev->dev, "failed to add clock provider\n"); - goto unregister; + samsung_clk_register_gate(ctx, exynos5420_audss_gate_clks, + ARRAY_SIZE(exynos5420_audss_gate_clks)); } #ifdef CONFIG_PM_SLEEP @@ -199,27 +181,11 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) dev_info(&pdev->dev, "setup completed\n"); return 0; - -unregister: - for (i = 0; i < clk_data.clk_num; i++) { - if (!IS_ERR(clk_table[i])) - clk_unregister(clk_table[i]); - } - - return ret; } static int exynos_audss_clk_remove(struct platform_device *pdev) { - int i; - - of_clk_del_provider(pdev->dev.of_node); - - for (i = 0; i < clk_data.clk_num; i++) { - if (!IS_ERR(clk_table[i])) - clk_unregister(clk_table[i]); - } - + samsung_clk_exit(pdev->dev.of_node, ctx); return 0; } -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH V2 3/3] clk: exynos-audss: Use samsung clock APIs to register/unregister clocks @ 2014-07-11 12:00 ` Tushar Behera 0 siblings, 0 replies; 12+ messages in thread From: Tushar Behera @ 2014-07-11 12:00 UTC (permalink / raw) To: linux-arm-kernel Using samsung clock APIs to register/unregister clocks will save some lines of code. Signed-off-by: Tushar Behera <tushar.b@samsung.com> --- Changes of v2: * Retain platform driver structure. drivers/clk/samsung/clk-exynos-audss.c | 146 ++++++++++++-------------------- 1 file changed, 56 insertions(+), 90 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index 1a5294c..2b90967 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -19,16 +19,16 @@ #include <dt-bindings/clock/exynos-audss-clk.h> +#include "clk.h" + enum exynos_audss_clk_type { TYPE_EXYNOS4210, TYPE_EXYNOS5250, TYPE_EXYNOS5420, }; -static DEFINE_SPINLOCK(lock); -static struct clk **clk_table; +static struct samsung_clk_provider *ctx; static void __iomem *reg_base; -static struct clk_onecell_data clk_data; #define ASS_CLK_SRC 0x0 #define ASS_CLK_DIV 0x4 @@ -78,7 +78,7 @@ static const struct of_device_id exynos_audss_clk_of_match[] = { /* register exynos_audss clocks */ static int exynos_audss_clk_probe(struct platform_device *pdev) { - int i, ret = 0; + int i; struct resource *res; struct clk *tmp; const char *clk_name_ref[] = { @@ -87,14 +87,51 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) "fin_pll", "fout_epll", "cdclk0", "sclk_audio0", "sclk_pcm0"}; const char *mout_audss_p[] = {"fin_pll", "fout_epll"}; const char *mout_i2s_p[] = {"mout_audss", "cdclk0", "sclk_audio0"}; - const char *sclk_pcm_p = "sclk_pcm0"; + char sclk_pcm_p[32]; const struct of_device_id *match; enum exynos_audss_clk_type variant; + struct samsung_mux_clock exynos_audss_mux_clks[] = { + MUX(EXYNOS_MOUT_AUDSS, "mout_audss", mout_audss_p, + ASS_CLK_SRC, 0, 1), + MUX(EXYNOS_MOUT_I2S, "mout_i2s", mout_i2s_p, + ASS_CLK_SRC, 2, 2), + }; + + struct samsung_div_clock exynos_audss_div_clks[] = { + DIV(EXYNOS_DOUT_SRP, "dout_srp", "mout_audss", + ASS_CLK_DIV, 0, 4), + DIV(EXYNOS_DOUT_AUD_BUS, "dout_aud_bus", "dout_srp", + ASS_CLK_DIV, 4, 4), + DIV(EXYNOS_DOUT_I2S, "dout_i2s", "mout_i2s", ASS_CLK_DIV, 8, 4), + }; + + struct samsung_gate_clock exynos_audss_gate_clks[] = { + GATE(EXYNOS_SRP_CLK, "srp_clk", "dout_srp", + ASS_CLK_GATE, 0, CLK_SET_RATE_PARENT, 0), + GATE(EXYNOS_I2S_BUS, "i2s_bus", "dout_aud_bus", + ASS_CLK_GATE, 2, CLK_SET_RATE_PARENT, 0), + GATE(EXYNOS_SCLK_I2S, "sclk_i2s", "dout_i2s", + ASS_CLK_GATE, 3, CLK_SET_RATE_PARENT, 0), + GATE(EXYNOS_PCM_BUS, "pcm_bus", "sclk_pcm", + ASS_CLK_GATE, 4, CLK_SET_RATE_PARENT, 0), + GATE(EXYNOS_SCLK_PCM, "sclk_pcm", sclk_pcm_p, + ASS_CLK_GATE, 5, CLK_SET_RATE_PARENT, 0), + }; + + struct samsung_gate_clock exynos5420_audss_gate_clks[] = { + GATE(EXYNOS_ADMA, "adma", "dout_srp", + ASS_CLK_GATE, 9, CLK_SET_RATE_PARENT, 0), + }; + + int nr_clks = EXYNOS_AUDSS_MAX_CLKS; + match = of_match_node(exynos_audss_clk_of_match, pdev->dev.of_node); if (!match) return -EINVAL; variant = (enum exynos_audss_clk_type)match->data; + if (variant != TYPE_EXYNOS5420) + nr_clks--; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); reg_base = devm_ioremap_resource(&pdev->dev, res); @@ -103,17 +140,11 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) return PTR_ERR(reg_base); } - clk_table = devm_kzalloc(&pdev->dev, - sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS, - GFP_KERNEL); - if (!clk_table) + ctx = samsung_clk_init(pdev->dev.of_node, reg_base, nr_clks); + if (!ctx) { + dev_err(&pdev->dev, "failed to get clock provier context\n"); return -ENOMEM; - - clk_data.clks = clk_table; - if (variant == TYPE_EXYNOS5420) - clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS; - else - clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS - 1; + } for (i = 0; i < ARRAY_SIZE(clk_name_ref); i++) { tmp = clk_get(&pdev->dev, clk_name_ref[i]); @@ -127,69 +158,20 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) mout_audss_p[1] = clk_name_actual[1]; mout_i2s_p[1] = clk_name_actual[2]; mout_i2s_p[2] = clk_name_actual[3]; - sclk_pcm_p = clk_name_actual[4]; - - clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss", - mout_audss_p, ARRAY_SIZE(mout_audss_p), - CLK_SET_RATE_NO_REPARENT, - reg_base + ASS_CLK_SRC, 0, 1, 0, &lock); - - clk_table[EXYNOS_MOUT_I2S] = clk_register_mux(NULL, "mout_i2s", - mout_i2s_p, ARRAY_SIZE(mout_i2s_p), - CLK_SET_RATE_NO_REPARENT, - reg_base + ASS_CLK_SRC, 2, 2, 0, &lock); + strncpy(sclk_pcm_p, clk_name_actual[4], strlen(clk_name_actual[4])); - clk_table[EXYNOS_DOUT_SRP] = clk_register_divider(NULL, "dout_srp", - "mout_audss", 0, reg_base + ASS_CLK_DIV, 0, 4, - 0, &lock); + samsung_clk_register_mux(ctx, exynos_audss_mux_clks, + ARRAY_SIZE(exynos_audss_mux_clks)); - clk_table[EXYNOS_DOUT_AUD_BUS] = clk_register_divider(NULL, - "dout_aud_bus", "dout_srp", 0, - reg_base + ASS_CLK_DIV, 4, 4, 0, &lock); + samsung_clk_register_div(ctx, exynos_audss_div_clks, + ARRAY_SIZE(exynos_audss_div_clks)); - clk_table[EXYNOS_DOUT_I2S] = clk_register_divider(NULL, "dout_i2s", - "mout_i2s", 0, reg_base + ASS_CLK_DIV, 8, 4, 0, - &lock); - - clk_table[EXYNOS_SRP_CLK] = clk_register_gate(NULL, "srp_clk", - "dout_srp", CLK_SET_RATE_PARENT, - reg_base + ASS_CLK_GATE, 0, 0, &lock); - - clk_table[EXYNOS_I2S_BUS] = clk_register_gate(NULL, "i2s_bus", - "dout_aud_bus", CLK_SET_RATE_PARENT, - reg_base + ASS_CLK_GATE, 2, 0, &lock); - - clk_table[EXYNOS_SCLK_I2S] = clk_register_gate(NULL, "sclk_i2s", - "dout_i2s", CLK_SET_RATE_PARENT, - reg_base + ASS_CLK_GATE, 3, 0, &lock); - - clk_table[EXYNOS_PCM_BUS] = clk_register_gate(NULL, "pcm_bus", - "sclk_pcm", CLK_SET_RATE_PARENT, - reg_base + ASS_CLK_GATE, 4, 0, &lock); - - clk_table[EXYNOS_SCLK_PCM] = clk_register_gate(NULL, "sclk_pcm", - sclk_pcm_p, CLK_SET_RATE_PARENT, - reg_base + ASS_CLK_GATE, 5, 0, &lock); + samsung_clk_register_gate(ctx, exynos_audss_gate_clks, + ARRAY_SIZE(exynos_audss_gate_clks)); if (variant == TYPE_EXYNOS5420) { - clk_table[EXYNOS_ADMA] = clk_register_gate(NULL, "adma", - "dout_srp", CLK_SET_RATE_PARENT, - reg_base + ASS_CLK_GATE, 9, 0, &lock); - } - - for (i = 0; i < clk_data.clk_num; i++) { - if (IS_ERR(clk_table[i])) { - dev_err(&pdev->dev, "failed to register clock %d\n", i); - ret = PTR_ERR(clk_table[i]); - goto unregister; - } - } - - ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get, - &clk_data); - if (ret) { - dev_err(&pdev->dev, "failed to add clock provider\n"); - goto unregister; + samsung_clk_register_gate(ctx, exynos5420_audss_gate_clks, + ARRAY_SIZE(exynos5420_audss_gate_clks)); } #ifdef CONFIG_PM_SLEEP @@ -199,27 +181,11 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) dev_info(&pdev->dev, "setup completed\n"); return 0; - -unregister: - for (i = 0; i < clk_data.clk_num; i++) { - if (!IS_ERR(clk_table[i])) - clk_unregister(clk_table[i]); - } - - return ret; } static int exynos_audss_clk_remove(struct platform_device *pdev) { - int i; - - of_clk_del_provider(pdev->dev.of_node); - - for (i = 0; i < clk_data.clk_num; i++) { - if (!IS_ERR(clk_table[i])) - clk_unregister(clk_table[i]); - } - + samsung_clk_exit(pdev->dev.of_node, ctx); return 0; } -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH V2 3/3] clk: exynos-audss: Use samsung clock APIs to register/unregister clocks 2014-07-11 12:00 ` Tushar Behera @ 2014-07-14 15:34 ` Sylwester Nawrocki -1 siblings, 0 replies; 12+ messages in thread From: Sylwester Nawrocki @ 2014-07-14 15:34 UTC (permalink / raw) To: Tushar Behera Cc: linux-arm-kernel, linux-kernel, linux-samsung-soc, kgene.kim, mturquette, t.figa, trblinux On 11/07/14 14:00, Tushar Behera wrote: > @@ -103,17 +140,11 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) > return PTR_ERR(reg_base); > } > > - clk_table = devm_kzalloc(&pdev->dev, > - sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS, > - GFP_KERNEL); > - if (!clk_table) > + ctx = samsung_clk_init(pdev->dev.of_node, reg_base, nr_clks); There is an issue here that this registers the clk provider before all its clocks are registered with the clk core. Therefore it introduces a race condition. Please have a look at patch [1], you may want to rebase this series onto that patch. > + samsung_clk_register_div(ctx, exynos_audss_div_clks, > + ARRAY_SIZE(exynos_audss_div_clks)); [...] > + samsung_clk_register_gate(ctx, exynos_audss_gate_clks, > + ARRAY_SIZE(exynos_audss_gate_clks)); [...] > - ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get, > - &clk_data); > - if (ret) { > - dev_err(&pdev->dev, "failed to add clock provider\n"); > - goto unregister; > + samsung_clk_register_gate(ctx, exynos5420_audss_gate_clks, > + ARRAY_SIZE(exynos5420_audss_gate_clks)); > } [1] https://git.kernel.org/cgit/linux/kernel/git/tfiga/samsung-clk.git/commit/?h=samsung-clk-next&id=d5e136a21b2028fb1f45143ea7112d5869bfc6c7 -- Regards, Sylwester ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V2 3/3] clk: exynos-audss: Use samsung clock APIs to register/unregister clocks @ 2014-07-14 15:34 ` Sylwester Nawrocki 0 siblings, 0 replies; 12+ messages in thread From: Sylwester Nawrocki @ 2014-07-14 15:34 UTC (permalink / raw) To: linux-arm-kernel On 11/07/14 14:00, Tushar Behera wrote: > @@ -103,17 +140,11 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) > return PTR_ERR(reg_base); > } > > - clk_table = devm_kzalloc(&pdev->dev, > - sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS, > - GFP_KERNEL); > - if (!clk_table) > + ctx = samsung_clk_init(pdev->dev.of_node, reg_base, nr_clks); There is an issue here that this registers the clk provider before all its clocks are registered with the clk core. Therefore it introduces a race condition. Please have a look at patch [1], you may want to rebase this series onto that patch. > + samsung_clk_register_div(ctx, exynos_audss_div_clks, > + ARRAY_SIZE(exynos_audss_div_clks)); [...] > + samsung_clk_register_gate(ctx, exynos_audss_gate_clks, > + ARRAY_SIZE(exynos_audss_gate_clks)); [...] > - ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get, > - &clk_data); > - if (ret) { > - dev_err(&pdev->dev, "failed to add clock provider\n"); > - goto unregister; > + samsung_clk_register_gate(ctx, exynos5420_audss_gate_clks, > + ARRAY_SIZE(exynos5420_audss_gate_clks)); > } [1] https://git.kernel.org/cgit/linux/kernel/git/tfiga/samsung-clk.git/commit/?h=samsung-clk-next&id=d5e136a21b2028fb1f45143ea7112d5869bfc6c7 -- Regards, Sylwester ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH V2 3/3] clk: exynos-audss: Use samsung clock APIs to register/unregister clocks 2014-07-14 15:34 ` Sylwester Nawrocki @ 2014-07-15 3:02 ` Tushar Behera -1 siblings, 0 replies; 12+ messages in thread From: Tushar Behera @ 2014-07-15 3:02 UTC (permalink / raw) To: Sylwester Nawrocki Cc: ML Arch-Arm, lkml, linux-samsung-soc, Kukjin Kim, Mike Turquette, Tomasz Figa On Mon, Jul 14, 2014 at 9:04 PM, Sylwester Nawrocki <s.nawrocki@samsung.com> wrote: > On 11/07/14 14:00, Tushar Behera wrote: >> @@ -103,17 +140,11 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) >> return PTR_ERR(reg_base); >> } >> >> - clk_table = devm_kzalloc(&pdev->dev, >> - sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS, >> - GFP_KERNEL); >> - if (!clk_table) >> + ctx = samsung_clk_init(pdev->dev.of_node, reg_base, nr_clks); > > There is an issue here that this registers the clk provider before all > its clocks are registered with the clk core. Therefore it introduces > a race condition. > > Please have a look at patch [1], you may want to rebase this series > onto that patch. > Thanks for the pointer. I will re-post. >> + samsung_clk_register_div(ctx, exynos_audss_div_clks, >> + ARRAY_SIZE(exynos_audss_div_clks)); > [...] >> + samsung_clk_register_gate(ctx, exynos_audss_gate_clks, >> + ARRAY_SIZE(exynos_audss_gate_clks)); > [...] >> - ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get, >> - &clk_data); >> - if (ret) { >> - dev_err(&pdev->dev, "failed to add clock provider\n"); >> - goto unregister; >> + samsung_clk_register_gate(ctx, exynos5420_audss_gate_clks, >> + ARRAY_SIZE(exynos5420_audss_gate_clks)); >> } > > [1] > https://git.kernel.org/cgit/linux/kernel/git/tfiga/samsung-clk.git/commit/?h=samsung-clk-next&id=d5e136a21b2028fb1f45143ea7112d5869bfc6c7 > > -- > Regards, > Sylwester ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V2 3/3] clk: exynos-audss: Use samsung clock APIs to register/unregister clocks @ 2014-07-15 3:02 ` Tushar Behera 0 siblings, 0 replies; 12+ messages in thread From: Tushar Behera @ 2014-07-15 3:02 UTC (permalink / raw) To: linux-arm-kernel On Mon, Jul 14, 2014 at 9:04 PM, Sylwester Nawrocki <s.nawrocki@samsung.com> wrote: > On 11/07/14 14:00, Tushar Behera wrote: >> @@ -103,17 +140,11 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) >> return PTR_ERR(reg_base); >> } >> >> - clk_table = devm_kzalloc(&pdev->dev, >> - sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS, >> - GFP_KERNEL); >> - if (!clk_table) >> + ctx = samsung_clk_init(pdev->dev.of_node, reg_base, nr_clks); > > There is an issue here that this registers the clk provider before all > its clocks are registered with the clk core. Therefore it introduces > a race condition. > > Please have a look at patch [1], you may want to rebase this series > onto that patch. > Thanks for the pointer. I will re-post. >> + samsung_clk_register_div(ctx, exynos_audss_div_clks, >> + ARRAY_SIZE(exynos_audss_div_clks)); > [...] >> + samsung_clk_register_gate(ctx, exynos_audss_gate_clks, >> + ARRAY_SIZE(exynos_audss_gate_clks)); > [...] >> - ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get, >> - &clk_data); >> - if (ret) { >> - dev_err(&pdev->dev, "failed to add clock provider\n"); >> - goto unregister; >> + samsung_clk_register_gate(ctx, exynos5420_audss_gate_clks, >> + ARRAY_SIZE(exynos5420_audss_gate_clks)); >> } > > [1] > https://git.kernel.org/cgit/linux/kernel/git/tfiga/samsung-clk.git/commit/?h=samsung-clk-next&id=d5e136a21b2028fb1f45143ea7112d5869bfc6c7 > > -- > Regards, > Sylwester ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2014-07-15 3:02 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-07-11 12:00 [PATCH V2 0/3] clk: exynos-audss: Adapt to exising clock framework Tushar Behera 2014-07-11 12:00 ` Tushar Behera 2014-07-11 12:00 ` [PATCH V2 1/3] clk: exynos-audss: Simplify code to get clock names Tushar Behera 2014-07-11 12:00 ` Tushar Behera 2014-07-11 12:00 ` [PATCH V2 2/3] clk: samsung: Add API to unregister clocks Tushar Behera 2014-07-11 12:00 ` Tushar Behera 2014-07-11 12:00 ` [PATCH V2 3/3] clk: exynos-audss: Use samsung clock APIs to register/unregister clocks Tushar Behera 2014-07-11 12:00 ` Tushar Behera 2014-07-14 15:34 ` Sylwester Nawrocki 2014-07-14 15:34 ` Sylwester Nawrocki 2014-07-15 3:02 ` Tushar Behera 2014-07-15 3:02 ` Tushar Behera
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.