From 07c2ae9cc6a49bf6403a5a156f897dcb30b5ccf4 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 5 Jul 2013 13:48:01 +0530 Subject: [PATCH 001/102] of/documentation: Fix a typo in exynos5250-clock.txt The clocks should be numbered sequentially as they are represented as enum values in the clock driver. Typo introduced by commit 17d4caccef ("clk: exynos5250: register display block gate clocks to common clock framework") Signed-off-by: Sachin Kamat Signed-off-by: Mike Turquette --- Documentation/devicetree/bindings/clock/exynos5250-clock.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt index 781a6276adf7..1a05761de4bd 100644 --- a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt +++ b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt @@ -154,7 +154,7 @@ clock which they consume. dsim0 341 dp 342 mixer 343 - hdmi 345 + hdmi 344 Example 1: An example of a clock controller node is listed below. From 24ee1a083cbe0b0364a27404dc01a665b31839cb Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sat, 29 Jun 2013 15:14:19 +0200 Subject: [PATCH 002/102] clk: fix typos Signed-off-by: Peter Meerwald Signed-off-by: Mike Turquette --- drivers/clk/Kconfig | 2 +- drivers/clk/clk.c | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 51380d655d1a..cd49096c38fa 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -27,7 +27,7 @@ config COMMON_CLK_DEBUG bool "DebugFS representation of clock tree" select DEBUG_FS ---help--- - Creates a directory hierchy in debugfs for visualizing the clk + Creates a directory hierarchy in debugfs for visualizing the clk tree structure. Each directory contains read-only members that export information specific to that clk node: clk_rate, clk_flags, clk_prepare_count, clk_enable_count & diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 54a191c5bbf0..56a00db61332 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -702,7 +702,7 @@ void __clk_unprepare(struct clk *clk) /** * clk_unprepare - undo preparation of a clock source - * @clk: the clk being unprepare + * @clk: the clk being unprepared * * clk_unprepare may sleep, which differentiates it from clk_disable. In a * simple case, clk_unprepare can be used instead of clk_disable to gate a clk @@ -869,6 +869,7 @@ EXPORT_SYMBOL_GPL(clk_enable); /** * __clk_round_rate - round the given rate for a clk * @clk: round the rate of this clock + * @rate: the rate which is to be rounded * * Caller must hold prepare_lock. Useful for clk_ops such as .set_rate */ @@ -956,7 +957,7 @@ static int __clk_notify(struct clk *clk, unsigned long msg, * * Walks the subtree of clks starting with clk and recalculates rates as it * goes. Note that if a clk does not implement the .recalc_rate callback then - * it is assumed that the clock will take on the rate of it's parent. + * it is assumed that the clock will take on the rate of its parent. * * clk_recalc_rates also propagates the POST_RATE_CHANGE notification, * if necessary. @@ -1026,7 +1027,7 @@ EXPORT_SYMBOL_GPL(clk_get_rate); * pre-rate change notifications and returns early if no clks in the * subtree have subscribed to the notifications. Note that if a clk does not * implement the .recalc_rate callback then it is assumed that the clock will - * take on the rate of it's parent. + * take on the rate of its parent. * * Caller must hold prepare_lock. */ @@ -1198,7 +1199,7 @@ static void clk_change_rate(struct clk *clk) * outcome of clk's .round_rate implementation. If *parent_rate is unchanged * after calling .round_rate then upstream parent propagation is ignored. If * *parent_rate comes back with a new rate for clk's parent then we propagate - * up to clk's parent and set it's rate. Upward propagation will continue + * up to clk's parent and set its rate. Upward propagation will continue * until either a clk does not support the CLK_SET_RATE_PARENT flag or * .round_rate stops requesting changes to clk's parent_rate. * @@ -1648,7 +1649,7 @@ int __clk_init(struct device *dev, struct clk *clk) * The .init callback is not used by any of the basic clock types, but * exists for weird hardware that must perform initialization magic. * Please consider other ways of solving initialization problems before - * using this callback, as it's use is discouraged. + * using this callback, as its use is discouraged. */ if (clk->ops->init) clk->ops->init(clk->hw); @@ -1675,7 +1676,7 @@ out: * very large numbers of clocks that need to be statically initialized. It is * a layering violation to include clk-private.h from any code which implements * a clock's .ops; as such any statically initialized clock data MUST be in a - * separate C file from the logic that implements it's operations. Returns 0 + * separate C file from the logic that implements its operations. Returns 0 * on success, otherwise an error code. */ struct clk *__clk_register(struct device *dev, struct clk_hw *hw) From d75f306378fd328ed8ea5a2a2356e5e57ea4238e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 18 Jul 2013 15:31:17 +0530 Subject: [PATCH 003/102] clk: exynos4: Staticize local symbols Symbols referenced only in this file are made static. Signed-off-by: Sachin Kamat Reviewed-by: Tomasz Figa Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos4.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 1bdb882c845b..5af496cada0c 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -338,24 +338,24 @@ PNAME(mout_user_aclk200_p4x12) = {"fin_pll", "div_aclk200", }; PNAME(mout_user_aclk266_gps_p4x12) = {"fin_pll", "div_aclk266_gps", }; /* fixed rate clocks generated outside the soc */ -struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata = { +static struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata = { FRATE(xxti, "xxti", NULL, CLK_IS_ROOT, 0), FRATE(xusbxti, "xusbxti", NULL, CLK_IS_ROOT, 0), }; /* fixed rate clocks generated inside the soc */ -struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = { +static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = { FRATE(none, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000), FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000), FRATE(none, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000), }; -struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata = { +static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata = { FRATE(none, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000), }; /* list of mux clocks supported in all exynos4 soc's */ -struct samsung_mux_clock exynos4_mux_clks[] __initdata = { +static struct samsung_mux_clock exynos4_mux_clks[] __initdata = { MUX_FA(mout_apll, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, CLK_SET_RATE_PARENT, 0, "mout_apll"), MUX(none, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1), @@ -372,7 +372,7 @@ struct samsung_mux_clock exynos4_mux_clks[] __initdata = { }; /* list of mux clocks supported in exynos4210 soc */ -struct samsung_mux_clock exynos4210_mux_clks[] __initdata = { +static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = { MUX(none, "mout_aclk200", sclk_ampll_p4210, SRC_TOP0, 12, 1), MUX(none, "mout_aclk100", sclk_ampll_p4210, SRC_TOP0, 16, 1), MUX(none, "mout_aclk160", sclk_ampll_p4210, SRC_TOP0, 20, 1), @@ -423,7 +423,7 @@ struct samsung_mux_clock exynos4210_mux_clks[] __initdata = { }; /* list of mux clocks supported in exynos4x12 soc */ -struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = { +static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = { MUX_A(mout_mpll_user_c, "mout_mpll_user_c", mout_mpll_user_p4x12, SRC_CPU, 24, 1, "mout_mpll"), MUX(none, "mout_aclk266_gps", aclk_p4412, SRC_TOP1, 4, 1), @@ -491,7 +491,7 @@ struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = { }; /* list of divider clocks supported in all exynos4 soc's */ -struct samsung_div_clock exynos4_div_clks[] __initdata = { +static struct samsung_div_clock exynos4_div_clks[] __initdata = { DIV(none, "div_core", "mout_core", DIV_CPU0, 0, 3), DIV(none, "div_core2", "div_core", DIV_CPU0, 28, 3), DIV(none, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4), @@ -554,7 +554,7 @@ struct samsung_div_clock exynos4_div_clks[] __initdata = { }; /* list of divider clocks supported in exynos4210 soc */ -struct samsung_div_clock exynos4210_div_clks[] __initdata = { +static struct samsung_div_clock exynos4210_div_clks[] __initdata = { DIV(aclk200, "aclk200", "mout_aclk200", DIV_TOP, 0, 3), DIV(sclk_fimg2d, "sclk_fimg2d", "mout_g2d", DIV_IMAGE, 0, 4), DIV(none, "div_fimd1", "mout_fimd1", E4210_DIV_LCD1, 0, 4), @@ -565,7 +565,7 @@ struct samsung_div_clock exynos4210_div_clks[] __initdata = { }; /* list of divider clocks supported in exynos4x12 soc */ -struct samsung_div_clock exynos4x12_div_clks[] __initdata = { +static struct samsung_div_clock exynos4x12_div_clks[] __initdata = { DIV(none, "div_mdnie0", "mout_mdnie0", DIV_LCD0, 4, 4), DIV(none, "div_mdnie_pwm0", "mout_mdnie_pwm0", DIV_LCD0, 8, 4), DIV(none, "div_mdnie_pwm_pre0", "div_mdnie_pwm0", DIV_LCD0, 12, 4), @@ -590,7 +590,7 @@ struct samsung_div_clock exynos4x12_div_clks[] __initdata = { }; /* list of gate clocks supported in all exynos4 soc's */ -struct samsung_gate_clock exynos4_gate_clks[] __initdata = { +static struct samsung_gate_clock exynos4_gate_clks[] __initdata = { /* * After all Exynos4 based platforms are migrated to use device tree, * the device name and clock alias names specified below for some @@ -782,7 +782,7 @@ struct samsung_gate_clock exynos4_gate_clks[] __initdata = { }; /* list of gate clocks supported in exynos4210 soc */ -struct samsung_gate_clock exynos4210_gate_clks[] __initdata = { +static struct samsung_gate_clock exynos4210_gate_clks[] __initdata = { GATE(tvenc, "tvenc", "aclk160", GATE_IP_TV, 2, 0, 0), GATE(g2d, "g2d", "aclk200", E4210_GATE_IP_IMAGE, 0, 0, 0), GATE(rotator, "rotator", "aclk200", E4210_GATE_IP_IMAGE, 1, 0, 0), @@ -817,7 +817,7 @@ struct samsung_gate_clock exynos4210_gate_clks[] __initdata = { }; /* list of gate clocks supported in exynos4x12 soc */ -struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = { +static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = { GATE(audss, "audss", "sclk_epll", E4X12_GATE_IP_MAUDIO, 0, 0, 0), GATE(mdnie0, "mdnie0", "aclk160", GATE_IP_LCD0, 2, 0, 0), GATE(rotator, "rotator", "aclk200", E4X12_GATE_IP_IMAGE, 1, 0, 0), @@ -990,7 +990,9 @@ static __initdata struct of_device_id ext_clk_match[] = { }; /* register exynos4 clocks */ -void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_soc, void __iomem *reg_base, unsigned long xom) +static 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; From 0ffc767f76820f6bdf1297e0834d8006f07f7cb3 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 18 Jul 2013 15:31:18 +0530 Subject: [PATCH 004/102] clk: exynos4: Remove unused function Subsequent to the cleanup in commit 3c70348c7c ("ARM: EXYNOS: Remove legacy timer initialization code"), this function has no more users. Hence remove it. Signed-off-by: Sachin Kamat Reviewed-by: Tomasz Figa Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos4.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 5af496cada0c..75635eb8a808 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -969,20 +969,6 @@ static void __init exynos4_clk_register_finpll(unsigned long xom) } -/* - * This function allows non-dt platforms to specify the clock speed of the - * 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, - 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, - ARRAY_SIZE(exynos4_fixed_rate_ext_clks)); -} - static __initdata struct of_device_id ext_clk_match[] = { { .compatible = "samsung,clock-xxti", .data = (void *)0, }, { .compatible = "samsung,clock-xusbxti", .data = (void *)1, }, From b95e71c6089be027d676544cc6d91e1672ae9c6b Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 18 Jul 2013 15:31:19 +0530 Subject: [PATCH 005/102] clk: exynos5250: Staticize local symbols Symbols referenced only in this file are made static. Signed-off-by: Sachin Kamat Acked-by: Kukjin Kim Reviewed-by: Tomasz Figa Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos5250.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 6f767c515ec7..6b2b66d4cb10 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -191,24 +191,24 @@ PNAME(mout_spdif_p) = { "sclk_audio0", "sclk_audio1", "sclk_audio2", "spdif_extclk" }; /* fixed rate clocks generated outside the soc */ -struct samsung_fixed_rate_clock exynos5250_fixed_rate_ext_clks[] __initdata = { +static struct samsung_fixed_rate_clock exynos5250_fixed_rate_ext_clks[] __initdata = { FRATE(fin_pll, "fin_pll", NULL, CLK_IS_ROOT, 0), }; /* fixed rate clocks generated inside the soc */ -struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initdata = { +static struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initdata = { FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000), FRATE(none, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000), FRATE(none, "sclk_dptxphy", NULL, CLK_IS_ROOT, 24000000), FRATE(none, "sclk_uhostphy", NULL, CLK_IS_ROOT, 48000000), }; -struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = { +static struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = { FFACTOR(none, "fout_mplldiv2", "fout_mpll", 1, 2, 0), FFACTOR(none, "fout_bplldiv2", "fout_bpll", 1, 2, 0), }; -struct samsung_mux_clock exynos5250_mux_clks[] __initdata = { +static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = { MUX_A(none, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, "mout_apll"), MUX_A(none, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1, "mout_cpu"), MUX(none, "mout_mpll_fout", mout_mpll_fout_p, PLL_DIV2_SEL, 4, 1), @@ -254,7 +254,7 @@ struct samsung_mux_clock exynos5250_mux_clks[] __initdata = { MUX(none, "mout_spi2", mout_group1_p, SRC_PERIC1, 24, 4), }; -struct samsung_div_clock exynos5250_div_clks[] __initdata = { +static struct samsung_div_clock exynos5250_div_clks[] __initdata = { DIV(none, "div_arm", "mout_cpu", DIV_CPU0, 0, 3), DIV(none, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3), DIV(none, "aclk66_pre", "sclk_mpll_user", DIV_TOP1, 24, 3), @@ -314,7 +314,7 @@ struct samsung_div_clock exynos5250_div_clks[] __initdata = { DIV_PERIC2, 8, 8, CLK_SET_RATE_PARENT, 0), }; -struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { +static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { GATE(gscl0, "gscl0", "none", GATE_IP_GSCL, 0, 0, 0), GATE(gscl1, "gscl1", "none", GATE_IP_GSCL, 1, 0, 0), GATE(gscl2, "gscl2", "aclk266", GATE_IP_GSCL, 2, 0, 0), @@ -471,7 +471,7 @@ static __initdata struct of_device_id ext_clk_match[] = { }; /* register exynox5250 clocks */ -void __init exynos5250_clk_init(struct device_node *np) +static void __init exynos5250_clk_init(struct device_node *np) { void __iomem *reg_base; struct clk *apll, *mpll, *epll, *vpll, *bpll, *gpll, *cpll; From c7306229d3c42881fcc7fd707948bbc3e5430662 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 18 Jul 2013 15:31:20 +0530 Subject: [PATCH 006/102] clk: exynos5420: Staticize local symbols Symbols referenced only in this file are made static. Signed-off-by: Sachin Kamat Acked-by: Kukjin Kim Reviewed-by: Tomasz Figa Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos5420.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 68a96cbd4936..125728a3ebb3 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -262,12 +262,12 @@ PNAME(maudio0_p) = { "fin_pll", "maudio_clk", "sclk_dpll", "sclk_mpll", "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; /* fixed rate clocks generated outside the soc */ -struct samsung_fixed_rate_clock exynos5420_fixed_rate_ext_clks[] __initdata = { +static struct samsung_fixed_rate_clock exynos5420_fixed_rate_ext_clks[] __initdata = { FRATE(fin_pll, "fin_pll", NULL, CLK_IS_ROOT, 0), }; /* fixed rate clocks generated inside the soc */ -struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = { +static struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = { FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000), FRATE(none, "sclk_pwi", NULL, CLK_IS_ROOT, 24000000), FRATE(none, "sclk_usbh20", NULL, CLK_IS_ROOT, 48000000), @@ -275,11 +275,11 @@ struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = { FRATE(none, "sclk_usbh20_scan_clk", NULL, CLK_IS_ROOT, 480000000), }; -struct samsung_fixed_factor_clock exynos5420_fixed_factor_clks[] __initdata = { +static struct samsung_fixed_factor_clock exynos5420_fixed_factor_clks[] __initdata = { FFACTOR(none, "sclk_hsic_12m", "fin_pll", 1, 2, 0), }; -struct samsung_mux_clock exynos5420_mux_clks[] __initdata = { +static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = { MUX(none, "mout_mspll_kfc", mspll_cpu_p, SRC_TOP7, 8, 2), MUX(none, "mout_mspll_cpu", mspll_cpu_p, SRC_TOP7, 12, 2), MUX(none, "mout_apll", apll_p, SRC_CPU, 0, 1), @@ -399,7 +399,7 @@ struct samsung_mux_clock exynos5420_mux_clks[] __initdata = { MUX(none, "mout_spi2", group2_p, SRC_PERIC1, 28, 3), }; -struct samsung_div_clock exynos5420_div_clks[] __initdata = { +static struct samsung_div_clock exynos5420_div_clks[] __initdata = { DIV(none, "div_arm", "mout_cpu", DIV_CPU0, 0, 3), DIV(none, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3), DIV(none, "armclk2", "div_arm", DIV_CPU0, 28, 3), @@ -479,7 +479,7 @@ struct samsung_div_clock exynos5420_div_clks[] __initdata = { DIV(none, "dout_pre_spi2", "dout_spi2", DIV_PERIC4, 24, 8), }; -struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { +static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { /* TODO: Re-verify the CG bits for all the gate clocks */ GATE_A(mct, "pclk_st", "aclk66_psgen", GATE_BUS_PERIS1, 2, 0, 0, "mct"), @@ -704,7 +704,7 @@ static __initdata struct of_device_id ext_clk_match[] = { }; /* register exynos5420 clocks */ -void __init exynos5420_clk_init(struct device_node *np) +static void __init exynos5420_clk_init(struct device_node *np) { void __iomem *reg_base; struct clk *apll, *bpll, *cpll, *dpll, *epll, *ipll, *kpll, *mpll; From 901f857605882b9374a1f4150b746932cf527821 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 18 Jul 2013 15:31:21 +0530 Subject: [PATCH 007/102] clk: exynos5440: Staticize local symbols Symbols referenced only in this file are made static. Signed-off-by: Sachin Kamat Acked-by: Kukjin Kim Reviewed-by: Tomasz Figa Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos5440.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c index 7d5434167a96..6d043a285d86 100644 --- a/drivers/clk/samsung/clk-exynos5440.c +++ b/drivers/clk/samsung/clk-exynos5440.c @@ -41,12 +41,12 @@ PNAME(mout_armclk_p) = { "cplla", "cpllb" }; PNAME(mout_spi_p) = { "div125", "div200" }; /* fixed rate clocks generated outside the soc */ -struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initdata = { +static struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initdata = { FRATE(none, "xtal", NULL, CLK_IS_ROOT, 0), }; /* fixed rate clocks */ -struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = { +static struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = { FRATE(none, "ppll", NULL, CLK_IS_ROOT, 1000000000), FRATE(none, "usb_phy0", NULL, CLK_IS_ROOT, 60000000), FRATE(none, "usb_phy1", NULL, CLK_IS_ROOT, 60000000), @@ -55,26 +55,26 @@ struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = { }; /* fixed factor clocks */ -struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initdata = { +static struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initdata = { FFACTOR(none, "div250", "ppll", 1, 4, 0), FFACTOR(none, "div200", "ppll", 1, 5, 0), FFACTOR(none, "div125", "div250", 1, 2, 0), }; /* mux clocks */ -struct samsung_mux_clock exynos5440_mux_clks[] __initdata = { +static struct samsung_mux_clock exynos5440_mux_clks[] __initdata = { MUX(none, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1), MUX_A(arm_clk, "arm_clk", mout_armclk_p, CPU_CLK_STATUS, 0, 1, "armclk"), }; /* divider clocks */ -struct samsung_div_clock exynos5440_div_clks[] __initdata = { +static struct samsung_div_clock exynos5440_div_clks[] __initdata = { DIV(spi_baud, "div_spi", "mout_spi", MISC_DOUT1, 3, 2), }; /* gate clocks */ -struct samsung_gate_clock exynos5440_gate_clks[] __initdata = { +static struct samsung_gate_clock exynos5440_gate_clks[] __initdata = { GATE(pb0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0), GATE(pr0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0), GATE(pr1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0), @@ -103,7 +103,7 @@ static __initdata struct of_device_id ext_clk_match[] = { }; /* register exynos5440 clocks */ -void __init exynos5440_clk_init(struct device_node *np) +static void __init exynos5440_clk_init(struct device_node *np) { void __iomem *reg_base; From 1190338f508a5a0c5144585d71593476c0f12ecd Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 18 Jul 2013 15:31:22 +0530 Subject: [PATCH 008/102] clk: exynos-audss: Staticize exynos_audss_clk_init exynos_audss_clk_init() is used only in this file. Make it static. Signed-off-by: Sachin Kamat Acked-by: Kukjin Kim Reviewed-by: Tomasz Figa Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos-audss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index 9b1bbd52fd1f..51b48daf5c8a 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -62,7 +62,7 @@ static struct syscore_ops exynos_audss_clk_syscore_ops = { #endif /* CONFIG_PM_SLEEP */ /* register exynos_audss clocks */ -void __init exynos_audss_clk_init(struct device_node *np) +static void __init exynos_audss_clk_init(struct device_node *np) { reg_base = of_iomap(np, 0); if (!reg_base) { From 406c5989276967db8721d057ed4b4f51bf9c71c6 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 5 Jul 2013 14:12:27 +0530 Subject: [PATCH 009/102] clk: exynos5250: Add G2D gate clock Adds gate clock for G2D IP for Exynos5250 SoC. Signed-off-by: Sachin Kamat Signed-off-by: Mike Turquette --- Documentation/devicetree/bindings/clock/exynos5250-clock.txt | 1 + drivers/clk/samsung/clk-exynos5250.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt index 1a05761de4bd..7e882429add9 100644 --- a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt +++ b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt @@ -155,6 +155,7 @@ clock which they consume. dp 342 mixer 343 hdmi 344 + g2d 345 Example 1: An example of a clock controller node is listed below. diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 6b2b66d4cb10..e6a4be16272a 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -62,6 +62,7 @@ #define SRC_CDREX 0x20200 #define PLL_DIV2_SEL 0x20a24 #define GATE_IP_DISP1 0x10928 +#define GATE_IP_ACP 0x10000 /* * Let each supported clock get a unique id. This id is used to lookup the clock @@ -99,7 +100,7 @@ enum exynos5250_clks { spi2, i2s1, i2s2, pcm1, pcm2, pwm, spdif, ac97, hsi2c0, hsi2c1, hsi2c2, hsi2c3, chipid, sysreg, pmu, cmu_top, cmu_core, cmu_mem, tzpc0, tzpc1, tzpc2, tzpc3, tzpc4, tzpc5, tzpc6, tzpc7, tzpc8, tzpc9, hdmi_cec, mct, - wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, + wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, g2d, nr_clks, }; @@ -152,6 +153,7 @@ static __initdata unsigned long exynos5250_clk_regs[] = { SRC_CDREX, PLL_DIV2_SEL, GATE_IP_DISP1, + GATE_IP_ACP, }; /* list of all parent clock list */ @@ -463,6 +465,7 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { GATE(dp, "dp", "aclk200", GATE_IP_DISP1, 4, 0, 0), GATE(mixer, "mixer", "aclk200", GATE_IP_DISP1, 5, 0, 0), GATE(hdmi, "hdmi", "aclk200", GATE_IP_DISP1, 6, 0, 0), + GATE(g2d, "g2d", "aclk200", GATE_IP_ACP, 3, 0, 0), }; static __initdata struct of_device_id ext_clk_match[] = { From 93b10d1b94341afc87f1bd0efe9b516b9d0fe00f Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Thu, 25 Jul 2013 10:37:33 +0530 Subject: [PATCH 010/102] Documentation: exynos5250-clock: Add div_i2s1 and div_i2s2 commit 79d743c177f9 ("clk: exynos5250: Add enum entries for divider clock of i2s1 and i2s2") added two new clock entries. Add the clock entry enum numbers to documentation. Signed-off-by: Tushar Behera Signed-off-by: Mike Turquette --- Documentation/devicetree/bindings/clock/exynos5250-clock.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt index 7e882429add9..2d4a7151180b 100644 --- a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt +++ b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt @@ -59,6 +59,8 @@ clock which they consume. sclk_spi0 154 sclk_spi1 155 sclk_spi2 156 + div_i2s1 157 + div_i2s2 158 [Peripheral Clock Gates] From 4a453314883d9d0a500107b508500ffffdca2f6d Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Thu, 25 Jul 2013 10:37:34 +0530 Subject: [PATCH 011/102] clk/exynos5250: add mout_hdmi mux clock for hdmi hdmi driver needs to change the parent of hdmi clock frequently between pixel clock and hdmiphy clock. hdmiphy is not stable after power on and for a short interval while changing the phy configuration. For this duration pixel clock is used to clock hdmi. This patch is exposing the mux for changing parent. Signed-off-by: Rahul Sharma Signed-off-by: Mike Turquette --- .../devicetree/bindings/clock/exynos5250-clock.txt | 8 ++++++++ drivers/clk/samsung/clk-exynos5250.c | 5 ++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt index 2d4a7151180b..76b97c92870c 100644 --- a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt +++ b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt @@ -159,6 +159,14 @@ clock which they consume. hdmi 344 g2d 345 + + [Clock Muxes] + + Clock ID + ---------------------------- + mout_hdmi 1024 + + Example 1: An example of a clock controller node is listed below. clock: clock-controller@0x10010000 { diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index e6a4be16272a..397f1ca41b97 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -102,6 +102,9 @@ enum exynos5250_clks { tzpc2, tzpc3, tzpc4, tzpc5, tzpc6, tzpc7, tzpc8, tzpc9, hdmi_cec, mct, wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, g2d, + /* mux clocks */ + mout_hdmi = 1024, + nr_clks, }; @@ -234,7 +237,7 @@ static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = { MUX(none, "mout_fimd1", mout_group1_p, SRC_DISP1_0, 0, 4), MUX(none, "mout_mipi1", mout_group1_p, SRC_DISP1_0, 12, 4), MUX(none, "mout_dp", mout_group1_p, SRC_DISP1_0, 16, 4), - MUX(none, "mout_hdmi", mout_hdmi_p, SRC_DISP1_0, 20, 1), + MUX(mout_hdmi, "mout_hdmi", mout_hdmi_p, SRC_DISP1_0, 20, 1), MUX(none, "mout_audio0", mout_audio0_p, SRC_MAU, 0, 4), MUX(none, "mout_mmc0", mout_group1_p, SRC_FSYS, 0, 4), MUX(none, "mout_mmc1", mout_group1_p, SRC_FSYS, 4, 4), From b38a5040a66dc4337ed9a06cc7495a42dd684028 Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Thu, 25 Jul 2013 10:37:35 +0530 Subject: [PATCH 012/102] clk/exynos5250: add sclk_hdmiphy in the list of special clocks hdmi driver needs hdmiphy clock which is one of the parent for hdmi mux clock. This is required while changing the parent of mux clock. Signed-off-by: Rahul Sharma Signed-off-by: Mike Turquette --- Documentation/devicetree/bindings/clock/exynos5250-clock.txt | 1 + drivers/clk/samsung/clk-exynos5250.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt index 76b97c92870c..24765c146e31 100644 --- a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt +++ b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt @@ -61,6 +61,7 @@ clock which they consume. sclk_spi2 156 div_i2s1 157 div_i2s2 158 + sclk_hdmiphy 159 [Peripheral Clock Gates] diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 397f1ca41b97..4361f4a0bdb3 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -88,7 +88,7 @@ enum exynos5250_clks { sclk_mmc0, sclk_mmc1, sclk_mmc2, sclk_mmc3, sclk_sata, sclk_usb3, sclk_jpeg, sclk_uart0, sclk_uart1, sclk_uart2, sclk_uart3, sclk_pwm, sclk_audio1, sclk_audio2, sclk_spdif, sclk_spi0, sclk_spi1, sclk_spi2, - div_i2s1, div_i2s2, + div_i2s1, div_i2s2, sclk_hdmiphy, /* gate clocks */ gscl0 = 256, gscl1, gscl2, gscl3, gscl_wa, gscl_wb, smmu_gscl0, @@ -202,7 +202,7 @@ static struct samsung_fixed_rate_clock exynos5250_fixed_rate_ext_clks[] __initda /* fixed rate clocks generated inside the soc */ static struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initdata = { - FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000), + FRATE(sclk_hdmiphy, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000), FRATE(none, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000), FRATE(none, "sclk_dptxphy", NULL, CLK_IS_ROOT, 24000000), FRATE(none, "sclk_uhostphy", NULL, CLK_IS_ROOT, 48000000), From 9f271369f5cf0a1f58709e6c753a6fa4d8c355d3 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 15:39:15 +0530 Subject: [PATCH 013/102] clk: exynos4: Add clock entries for TMU Added clock entries for thermal management unit (TMU) for Exynos4 SoCs. Signed-off-by: Sachin Kamat Signed-off-by: Mike Turquette --- Documentation/devicetree/bindings/clock/exynos4-clock.txt | 1 + drivers/clk/samsung/clk-exynos4.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/exynos4-clock.txt b/Documentation/devicetree/bindings/clock/exynos4-clock.txt index 14d5c2af26f4..c6bf8a6c8f52 100644 --- a/Documentation/devicetree/bindings/clock/exynos4-clock.txt +++ b/Documentation/devicetree/bindings/clock/exynos4-clock.txt @@ -236,6 +236,7 @@ Exynos4 SoC and this is specified where applicable. spi0_isp_sclk 380 Exynos4x12 spi1_isp_sclk 381 Exynos4x12 uart_isp_sclk 382 Exynos4x12 + tmu_apbif 383 [Mux Clocks] diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 75635eb8a808..cee297daec4b 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -169,7 +169,7 @@ enum exynos4_clks { gicisp, smmu_isp, smmu_drc, smmu_fd, smmu_lite0, smmu_lite1, mcuctl_isp, mpwm_isp, i2c0_isp, i2c1_isp, mtcadc_isp, pwm_isp, wdt_isp, uart_isp, asyncaxim, smmu_ispcx, spi0_isp, spi1_isp, pwm_isp_sclk, spi0_isp_sclk, - spi1_isp_sclk, uart_isp_sclk, + spi1_isp_sclk, uart_isp_sclk, tmu_apbif, /* mux clocks */ mout_fimc0 = 384, mout_fimc1, mout_fimc2, mout_fimc3, mout_cam0, @@ -814,6 +814,7 @@ static struct samsung_gate_clock exynos4210_gate_clks[] __initdata = { GATE_A(keyif, "keyif", "aclk100", E4210_GATE_IP_PERIR, 16, 0, 0, "keypad"), GATE_DA(sclk_fimd1, "exynos4-fb.1", "sclk_fimd1", "div_fimd1", E4210_SRC_MASK_LCD1, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimd"), + GATE(tmu_apbif, "tmu_apbif", "aclk100", E4210_GATE_IP_PERIR, 17, 0, 0), }; /* list of gate clocks supported in exynos4x12 soc */ @@ -915,6 +916,7 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = { GATE(spi1_isp, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13, CLK_IGNORE_UNUSED, 0), GATE(g2d, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0), + GATE(tmu_apbif, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0, 0), }; /* From 8f9a5b52bc72143a0bdc304f2cc273295581f722 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 9 Jul 2013 11:59:15 +0530 Subject: [PATCH 014/102] of/documentation: Update G2D documentation Exynos5250 G2D IP requires only the gate clock. Update the binding documentation accordingly. Signed-off-by: Sachin Kamat Cc: Inki Dae Reviewed-by: Tomasz Figa Signed-off-by: Mike Turquette --- Documentation/devicetree/bindings/gpu/samsung-g2d.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/gpu/samsung-g2d.txt b/Documentation/devicetree/bindings/gpu/samsung-g2d.txt index 3f454ffc654a..c4f358dafdaa 100644 --- a/Documentation/devicetree/bindings/gpu/samsung-g2d.txt +++ b/Documentation/devicetree/bindings/gpu/samsung-g2d.txt @@ -11,8 +11,11 @@ Required properties: - interrupts : G2D interrupt number to the CPU. - clocks : from common clock binding: handle to G2D clocks. - - clock-names : from common clock binding: must contain "sclk_fimg2d" and - "fimg2d", corresponding to entries in the clocks property. + - clock-names : names of clocks listed in clocks property, in the same + order, depending on SoC type: + - for S5PV210 and Exynos4 based SoCs: "fimg2d" and + "sclk_fimg2d" + - for Exynos5250 SoC: "fimg2d". Example: g2d@12800000 { From 079dbead49d6a09e4522ad5cedf1bbebbc5f794b Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Tue, 11 Jun 2013 15:01:06 +0530 Subject: [PATCH 015/102] clk: samsung: Introduce a common samsung_clk_pll struct This patch unifies clk strutures used for PLL35xx & PLL36xx and adding an extra member lock_reg, so that common code can be factored out. Reviewed-by: Tomasz Figa Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-pll.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 362f12dcd944..f62f85418488 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -13,6 +13,14 @@ #include "clk.h" #include "clk-pll.h" +struct samsung_clk_pll { + struct clk_hw hw; + void __iomem *lock_reg; + void __iomem *con_reg; +}; + +#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw) + /* * PLL35xx Clock Type */ @@ -24,17 +32,10 @@ #define PLL35XX_PDIV_SHIFT (8) #define PLL35XX_SDIV_SHIFT (0) -struct samsung_clk_pll35xx { - struct clk_hw hw; - const void __iomem *con_reg; -}; - -#define to_clk_pll35xx(_hw) container_of(_hw, struct samsung_clk_pll35xx, hw) - static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct samsung_clk_pll35xx *pll = to_clk_pll35xx(hw); + struct samsung_clk_pll *pll = to_clk_pll(hw); u32 mdiv, pdiv, sdiv, pll_con; u64 fvco = parent_rate; @@ -56,7 +57,7 @@ static const struct clk_ops samsung_pll35xx_clk_ops = { struct clk * __init samsung_clk_register_pll35xx(const char *name, const char *pname, const void __iomem *con_reg) { - struct samsung_clk_pll35xx *pll; + struct samsung_clk_pll *pll; struct clk *clk; struct clk_init_data init; @@ -100,17 +101,10 @@ struct clk * __init samsung_clk_register_pll35xx(const char *name, #define PLL36XX_PDIV_SHIFT (8) #define PLL36XX_SDIV_SHIFT (0) -struct samsung_clk_pll36xx { - struct clk_hw hw; - const void __iomem *con_reg; -}; - -#define to_clk_pll36xx(_hw) container_of(_hw, struct samsung_clk_pll36xx, hw) - static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct samsung_clk_pll36xx *pll = to_clk_pll36xx(hw); + struct samsung_clk_pll *pll = to_clk_pll(hw); u32 mdiv, pdiv, sdiv, pll_con0, pll_con1; s16 kdiv; u64 fvco = parent_rate; @@ -136,7 +130,7 @@ static const struct clk_ops samsung_pll36xx_clk_ops = { struct clk * __init samsung_clk_register_pll36xx(const char *name, const char *pname, const void __iomem *con_reg) { - struct samsung_clk_pll36xx *pll; + struct samsung_clk_pll *pll; struct clk *clk; struct clk_init_data init; From 07dc76fa61a0e76c759011ae224c882ada18e70c Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Tue, 11 Jun 2013 15:01:07 +0530 Subject: [PATCH 016/102] clk: samsung: Define a common samsung_clk_register_pll() This patch defines a common samsung_clk_register_pll() Since pll2550 & pll35xx and pll2650 & pll36xx have exactly same clk ops implementation, added pll2550 and pll2650 also. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-pll.c | 70 +++++++++++++++++++++++++++++++++++ drivers/clk/samsung/clk-pll.h | 7 ++++ drivers/clk/samsung/clk.h | 48 ++++++++++++++++++++++++ 3 files changed, 125 insertions(+) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index f62f85418488..8e2240a58a07 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -17,6 +17,7 @@ struct samsung_clk_pll { struct clk_hw hw; void __iomem *lock_reg; void __iomem *con_reg; + enum samsung_pll_type type; }; #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw) @@ -412,3 +413,72 @@ struct clk * __init samsung_clk_register_pll2550x(const char *name, return clk; } + +static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, + void __iomem *base) +{ + struct samsung_clk_pll *pll; + struct clk *clk; + struct clk_init_data init; + int ret; + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) { + pr_err("%s: could not allocate pll clk %s\n", + __func__, pll_clk->name); + return; + } + + init.name = pll_clk->name; + init.flags = pll_clk->flags; + init.parent_names = &pll_clk->parent_name; + init.num_parents = 1; + + switch (pll_clk->type) { + /* clk_ops for 35xx and 2550 are similar */ + case pll_35xx: + case pll_2550: + init.ops = &samsung_pll35xx_clk_ops; + break; + /* clk_ops for 36xx and 2650 are similar */ + case pll_36xx: + case pll_2650: + init.ops = &samsung_pll36xx_clk_ops; + break; + default: + pr_warn("%s: Unknown pll type for pll clk %s\n", + __func__, pll_clk->name); + } + + pll->hw.init = &init; + pll->type = pll_clk->type; + pll->lock_reg = base + pll_clk->lock_offset; + pll->con_reg = base + pll_clk->con_offset; + + clk = clk_register(NULL, &pll->hw); + if (IS_ERR(clk)) { + pr_err("%s: failed to register pll clock %s : %ld\n", + __func__, pll_clk->name, PTR_ERR(clk)); + kfree(pll); + return; + } + + samsung_clk_add_lookup(clk, pll_clk->id); + + if (!pll_clk->alias) + return; + + ret = clk_register_clkdev(clk, pll_clk->alias, pll_clk->dev_name); + if (ret) + pr_err("%s: failed to register lookup for %s : %d", + __func__, pll_clk->name, ret); +} + +void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list, + unsigned int nr_pll, void __iomem *base) +{ + int cnt; + + for (cnt = 0; cnt < nr_pll; cnt++) + _samsung_clk_register_pll(&pll_list[cnt], base); +} diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index f33786e9a78b..0d86bf0de40c 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -12,6 +12,13 @@ #ifndef __SAMSUNG_CLK_PLL_H #define __SAMSUNG_CLK_PLL_H +enum samsung_pll_type { + pll_35xx, + pll_36xx, + pll_2550, + pll_2650, +}; + enum pll45xx_type { pll_4500, pll_4502, diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index 2f7dba20ced8..4e83e521fe7d 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -19,6 +19,7 @@ #include #include #include +#include "clk-pll.h" /** * struct samsung_clock_alias: information about mux clock @@ -261,6 +262,51 @@ struct samsung_clk_reg_dump { u32 value; }; +/** + * struct samsung_pll_clock: information about pll clock + * @id: platform specific id of the clock. + * @dev_name: name of the device to which this clock belongs. + * @name: name of this pll clock. + * @parent_name: name of the parent clock. + * @flags: optional flags for basic clock. + * @con_offset: offset of the register for configuring the PLL. + * @lock_offset: offset of the register for locking the PLL. + * @type: Type of PLL to be registered. + * @alias: optional clock alias name to be assigned to this clock. + */ +struct samsung_pll_clock { + unsigned int id; + const char *dev_name; + const char *name; + const char *parent_name; + unsigned long flags; + int con_offset; + int lock_offset; + enum samsung_pll_type type; + const char *alias; +}; + +#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con, _alias) \ + { \ + .id = _id, \ + .type = _typ, \ + .dev_name = _dname, \ + .name = _name, \ + .parent_name = _pname, \ + .flags = CLK_GET_RATE_NOCACHE, \ + .con_offset = _con, \ + .lock_offset = _lock, \ + .alias = _alias, \ + } + +#define PLL(_typ, _id, _name, _pname, _lock, _con) \ + __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ + _lock, _con, NULL) + +#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias) \ + __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ + _lock, _con, _alias) + extern void __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, @@ -284,6 +330,8 @@ extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list, unsigned int nr_clk); extern void __init samsung_clk_register_gate( struct samsung_gate_clock *clk_list, unsigned int nr_clk); +extern void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list, + unsigned int nr_clk, void __iomem *base); extern unsigned long _get_rate(const char *clk_name); From 8dac3530c76cc8f9dfbbd7acf3199b2ab5ce977d Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Tue, 11 Jun 2013 15:01:08 +0530 Subject: [PATCH 017/102] clk: samsung: Migrate exynos5250 to use common samsung_clk_register_pll() This patch migrates exynos5250 pll registeration to use common samsung_clk_register_pll() by intialising table of PLLs and adding PLLs to unique id list of clocks. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Vikas Sajjan Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos5250.c | 60 +++++++++++++++++++--------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 4361f4a0bdb3..b9a5f2a22b9a 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -17,11 +17,22 @@ #include #include "clk.h" -#include "clk-pll.h" +#define APLL_LOCK 0x0 +#define APLL_CON0 0x100 #define SRC_CPU 0x200 #define DIV_CPU0 0x500 +#define MPLL_LOCK 0x4000 +#define MPLL_CON0 0x4100 #define SRC_CORE1 0x4204 +#define CPLL_LOCK 0x10020 +#define EPLL_LOCK 0x10030 +#define VPLL_LOCK 0x10040 +#define GPLL_LOCK 0x10050 +#define CPLL_CON0 0x10120 +#define EPLL_CON0 0x10130 +#define VPLL_CON0 0x10140 +#define GPLL_CON0 0x10150 #define SRC_TOP0 0x10210 #define SRC_TOP2 0x10218 #define SRC_GSCL 0x10220 @@ -59,11 +70,19 @@ #define GATE_IP_FSYS 0x10944 #define GATE_IP_PERIC 0x10950 #define GATE_IP_PERIS 0x10960 +#define BPLL_LOCK 0x20010 +#define BPLL_CON0 0x20110 #define SRC_CDREX 0x20200 #define PLL_DIV2_SEL 0x20a24 #define GATE_IP_DISP1 0x10928 #define GATE_IP_ACP 0x10000 +/* list of PLLs to be registered */ +enum exynos5250_plls { + apll, mpll, cpll, epll, vpll, gpll, bpll, + nr_plls /* number of PLLs */ +}; + /* * Let each supported clock get a unique id. This id is used to lookup the clock * for device tree based platforms. The clocks are categorized into three @@ -80,7 +99,8 @@ enum exynos5250_clks { none, /* core clocks */ - fin_pll, + fin_pll, fout_apll, fout_mpll, fout_bpll, fout_gpll, fout_cpll, + fout_epll, fout_vpll, /* gate for special clocks (sclk) */ sclk_cam_bayer = 128, sclk_cam0, sclk_cam1, sclk_gscl_wa, sclk_gscl_wb, @@ -471,6 +491,23 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { GATE(g2d, "g2d", "aclk200", GATE_IP_ACP, 3, 0, 0), }; +struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = { + [apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, + APLL_CON0, "fout_apll"), + [mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK, + MPLL_CON0, "fout_mpll"), + [bpll] = PLL(pll_35xx, fout_bpll, "fout_bpll", "fin_pll", BPLL_LOCK, + BPLL_CON0), + [gpll] = PLL(pll_35xx, fout_gpll, "fout_gpll", "fin_pll", GPLL_LOCK, + GPLL_CON0), + [cpll] = PLL(pll_35xx, fout_cpll, "fout_cpll", "fin_pll", CPLL_LOCK, + CPLL_CON0), + [epll] = PLL(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK, + EPLL_CON0), + [vpll] = PLL(pll_36xx, fout_vpll, "fout_vpll", "mout_vpllsrc", + VPLL_LOCK, VPLL_CON0), +}; + static __initdata struct of_device_id ext_clk_match[] = { { .compatible = "samsung,clock-xxti", .data = (void *)0, }, { }, @@ -480,7 +517,6 @@ static __initdata struct of_device_id ext_clk_match[] = { static void __init exynos5250_clk_init(struct device_node *np) { void __iomem *reg_base; - struct clk *apll, *mpll, *epll, *vpll, *bpll, *gpll, *cpll; if (np) { reg_base = of_iomap(np, 0); @@ -496,22 +532,8 @@ static void __init exynos5250_clk_init(struct device_node *np) samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks, ARRAY_SIZE(exynos5250_fixed_rate_ext_clks), ext_clk_match); - - apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll", - reg_base + 0x100); - mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll", - reg_base + 0x4100); - bpll = samsung_clk_register_pll35xx("fout_bpll", "fin_pll", - reg_base + 0x20110); - gpll = samsung_clk_register_pll35xx("fout_gpll", "fin_pll", - reg_base + 0x10150); - cpll = samsung_clk_register_pll35xx("fout_cpll", "fin_pll", - reg_base + 0x10120); - epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll", - reg_base + 0x10130); - vpll = samsung_clk_register_pll36xx("fout_vpll", "mout_vpllsrc", - reg_base + 0x10140); - + samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls), + reg_base); samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks, ARRAY_SIZE(exynos5250_fixed_rate_clks)); samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks, From 160641e71899d5916a76326a77ce8097c7086bf3 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Tue, 11 Jun 2013 15:01:09 +0530 Subject: [PATCH 018/102] clk: samsung: Migrate exynos4 to use common samsung_clk_register_pll() This patch migrates exynos4 pll registeration to use common samsung_clk_register_pll() by intialising table of PLLs. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Vikas Sajjan Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos4.c | 42 ++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index cee297daec4b..9de7a39b1adf 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -17,7 +17,6 @@ #include #include "clk.h" -#include "clk-pll.h" /* Exynos4 clock controller register offsets */ #define SRC_LEFTBUS 0x4200 @@ -97,12 +96,14 @@ #define GATE_IP_PERIL 0xc950 #define E4210_GATE_IP_PERIR 0xc960 #define GATE_BLOCK 0xc970 +#define E4X12_MPLL_LOCK 0x10008 #define E4X12_MPLL_CON0 0x10108 #define SRC_DMC 0x10200 #define SRC_MASK_DMC 0x10300 #define DIV_DMC0 0x10500 #define DIV_DMC1 0x10504 #define GATE_IP_DMC 0x10900 +#define APLL_LOCK 0x14000 #define APLL_CON0 0x14100 #define E4210_MPLL_CON0 0x14108 #define SRC_CPU 0x14200 @@ -121,6 +122,12 @@ enum exynos4_soc { EXYNOS4X12, }; +/* list of PLLs to be registered */ +enum exynos4_plls { + apll, mpll, epll, vpll, + nr_plls /* number of PLLs */ +}; + /* * Let each supported clock get a unique id. This id is used to lookup the clock * for device tree based platforms. The clocks are categorized into three @@ -977,6 +984,17 @@ static __initdata struct of_device_id ext_clk_match[] = { {}, }; +struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = { + [apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, + APLL_CON0, "fout_apll"), + [mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", + E4X12_MPLL_LOCK, E4X12_MPLL_CON0, "fout_mpll"), + [epll] = PLL_A(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK, + EPLL_CON0, "fout_epll"), + [vpll] = PLL_A(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK, + VPLL_CON0, "fout_vpll"), +}; + /* register exynos4 clocks */ static void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_soc, @@ -1015,21 +1033,15 @@ static void __init exynos4_clk_init(struct device_node *np, reg_base + EPLL_CON0, pll_4600); vpll = samsung_clk_register_pll46xx("fout_vpll", "mout_vpllsrc", reg_base + VPLL_CON0, pll_4650c); - } else { - apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll", - reg_base + APLL_CON0); - mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll", - reg_base + E4X12_MPLL_CON0); - epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll", - reg_base + EPLL_CON0); - vpll = samsung_clk_register_pll36xx("fout_vpll", "fin_pll", - reg_base + VPLL_CON0); - } - 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(apll, fout_apll); + samsung_clk_add_lookup(mpll, fout_mpll); + samsung_clk_add_lookup(epll, fout_epll); + samsung_clk_add_lookup(vpll, fout_vpll); + } else { + samsung_clk_register_pll(exynos4_plls, + ARRAY_SIZE(exynos4_plls), reg_base); + } samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks, ARRAY_SIZE(exynos4_fixed_rate_clks)); From c898c6b7cb79500428c09f28b2979f50ae220564 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Tue, 11 Jun 2013 15:01:10 +0530 Subject: [PATCH 019/102] clk: samsung: Migrate exynos5420 to use common samsung_clk_register_pll() This patch migrates exynos5420 pll registeration to use common samsung_clk_register_pll() by intialising table of PLLs and adding PLLs to unique id list of clocks. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Vikas Sajjan Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos5420.c | 86 +++++++++++++++++++--------- 1 file changed, 58 insertions(+), 28 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 125728a3ebb3..3dbe7a33297e 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -17,13 +17,30 @@ #include #include "clk.h" -#include "clk-pll.h" +#define APLL_LOCK 0x0 +#define APLL_CON0 0x100 #define SRC_CPU 0x200 #define DIV_CPU0 0x500 #define DIV_CPU1 0x504 #define GATE_BUS_CPU 0x700 #define GATE_SCLK_CPU 0x800 +#define CPLL_LOCK 0x10020 +#define DPLL_LOCK 0x10030 +#define EPLL_LOCK 0x10040 +#define RPLL_LOCK 0x10050 +#define IPLL_LOCK 0x10060 +#define SPLL_LOCK 0x10070 +#define VPLL_LOCK 0x10070 +#define MPLL_LOCK 0x10090 +#define CPLL_CON0 0x10120 +#define DPLL_CON0 0x10128 +#define EPLL_CON0 0x10130 +#define RPLL_CON0 0x10140 +#define IPLL_CON0 0x10150 +#define SPLL_CON0 0x10160 +#define VPLL_CON0 0x10170 +#define MPLL_CON0 0x10180 #define SRC_TOP0 0x10200 #define SRC_TOP1 0x10204 #define SRC_TOP2 0x10208 @@ -75,15 +92,27 @@ #define GATE_TOP_SCLK_MAU 0x1083c #define GATE_TOP_SCLK_FSYS 0x10840 #define GATE_TOP_SCLK_PERIC 0x10850 +#define BPLL_LOCK 0x20010 +#define BPLL_CON0 0x20110 #define SRC_CDREX 0x20200 +#define KPLL_LOCK 0x28000 +#define KPLL_CON0 0x28100 #define SRC_KFC 0x28200 #define DIV_KFC0 0x28500 +/* list of PLLs */ +enum exynos5420_plls { + apll, cpll, dpll, epll, rpll, ipll, spll, vpll, mpll, + bpll, kpll, + nr_plls /* number of PLLs */ +}; + enum exynos5420_clks { none, /* core clocks */ - fin_pll, + fin_pll, fout_apll, fout_cpll, fout_dpll, fout_epll, fout_rpll, + fout_ipll, fout_spll, fout_vpll, fout_mpll, fout_bpll, fout_kpll, /* gate for special clocks (sclk) */ sclk_uart0 = 128, sclk_uart1, sclk_uart2, sclk_uart3, sclk_mmc0, @@ -698,6 +727,31 @@ static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { GATE(smmu_mscl2, "smmu_mscl2", "aclk400_mscl", GATE_IP_MSCL, 10, 0, 0), }; +struct __initdata samsung_pll_clock exynos5420_plls[nr_plls] = { + [apll] = PLL(pll_2550, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, + APLL_CON0), + [cpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK, + MPLL_CON0), + [dpll] = PLL(pll_2550, fout_dpll, "fout_dpll", "fin_pll", DPLL_LOCK, + DPLL_CON0), + [epll] = PLL(pll_2650, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK, + EPLL_CON0), + [rpll] = PLL(pll_2650, fout_rpll, "fout_rpll", "fin_pll", RPLL_LOCK, + RPLL_CON0), + [ipll] = PLL(pll_2550, fout_ipll, "fout_ipll", "fin_pll", IPLL_LOCK, + IPLL_CON0), + [spll] = PLL(pll_2550, fout_spll, "fout_spll", "fin_pll", SPLL_LOCK, + SPLL_CON0), + [vpll] = PLL(pll_2550, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK, + VPLL_CON0), + [mpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK, + MPLL_CON0), + [bpll] = PLL(pll_2550, fout_bpll, "fout_bpll", "fin_pll", BPLL_LOCK, + BPLL_CON0), + [kpll] = PLL(pll_2550, fout_kpll, "fout_kpll", "fin_pll", KPLL_LOCK, + KPLL_CON0), +}; + static __initdata struct of_device_id ext_clk_match[] = { { .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, }, { }, @@ -707,8 +761,6 @@ static __initdata struct of_device_id ext_clk_match[] = { static void __init exynos5420_clk_init(struct device_node *np) { void __iomem *reg_base; - struct clk *apll, *bpll, *cpll, *dpll, *epll, *ipll, *kpll, *mpll; - struct clk *rpll, *spll, *vpll; if (np) { reg_base = of_iomap(np, 0); @@ -724,30 +776,8 @@ static void __init exynos5420_clk_init(struct device_node *np) samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks, ARRAY_SIZE(exynos5420_fixed_rate_ext_clks), ext_clk_match); - - apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll", - reg_base + 0x100); - bpll = samsung_clk_register_pll35xx("fout_bpll", "fin_pll", - reg_base + 0x20110); - cpll = samsung_clk_register_pll35xx("fout_cpll", "fin_pll", - reg_base + 0x10120); - dpll = samsung_clk_register_pll35xx("fout_dpll", "fin_pll", - reg_base + 0x10128); - epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll", - reg_base + 0x10130); - ipll = samsung_clk_register_pll35xx("fout_ipll", "fin_pll", - reg_base + 0x10150); - kpll = samsung_clk_register_pll35xx("fout_kpll", "fin_pll", - reg_base + 0x28100); - mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll", - reg_base + 0x10180); - rpll = samsung_clk_register_pll36xx("fout_rpll", "fin_pll", - reg_base + 0x10140); - spll = samsung_clk_register_pll35xx("fout_spll", "fin_pll", - reg_base + 0x10160); - vpll = samsung_clk_register_pll35xx("fout_vpll", "fin_pll", - reg_base + 0x10170); - + samsung_clk_register_pll(exynos5420_plls, ARRAY_SIZE(exynos5420_plls), + reg_base); samsung_clk_register_fixed_rate(exynos5420_fixed_rate_clks, ARRAY_SIZE(exynos5420_fixed_rate_clks)); samsung_clk_register_fixed_factor(exynos5420_fixed_factor_clks, From 5ca8fbd8d1b2650608d0c79bdf5e3f643a2f10e3 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Tue, 11 Jun 2013 15:01:11 +0530 Subject: [PATCH 020/102] clk: samsung: Remove unused pll registeration code for pll35xx and pll36xx This patch removes samsung_clk_register_pll35xx() and samsung_clk_register_pll36xx() registaration functions as users migrated to new samsung_clk_register_pll(). Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-pll.c | 70 ----------------------------------- drivers/clk/samsung/clk-pll.h | 4 -- 2 files changed, 74 deletions(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 8e2240a58a07..dd948f2ffdf7 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -55,41 +55,6 @@ static const struct clk_ops samsung_pll35xx_clk_ops = { .recalc_rate = samsung_pll35xx_recalc_rate, }; -struct clk * __init samsung_clk_register_pll35xx(const char *name, - const char *pname, const void __iomem *con_reg) -{ - struct samsung_clk_pll *pll; - struct clk *clk; - struct clk_init_data init; - - pll = kzalloc(sizeof(*pll), GFP_KERNEL); - if (!pll) { - pr_err("%s: could not allocate pll clk %s\n", __func__, name); - return NULL; - } - - init.name = name; - init.ops = &samsung_pll35xx_clk_ops; - init.flags = CLK_GET_RATE_NOCACHE; - init.parent_names = &pname; - init.num_parents = 1; - - pll->hw.init = &init; - pll->con_reg = con_reg; - - clk = clk_register(NULL, &pll->hw); - if (IS_ERR(clk)) { - pr_err("%s: failed to register pll clock %s\n", __func__, - name); - kfree(pll); - } - - if (clk_register_clkdev(clk, name, NULL)) - pr_err("%s: failed to register lookup for %s", __func__, name); - - return clk; -} - /* * PLL36xx Clock Type */ @@ -128,41 +93,6 @@ static const struct clk_ops samsung_pll36xx_clk_ops = { .recalc_rate = samsung_pll36xx_recalc_rate, }; -struct clk * __init samsung_clk_register_pll36xx(const char *name, - const char *pname, const void __iomem *con_reg) -{ - struct samsung_clk_pll *pll; - struct clk *clk; - struct clk_init_data init; - - pll = kzalloc(sizeof(*pll), GFP_KERNEL); - if (!pll) { - pr_err("%s: could not allocate pll clk %s\n", __func__, name); - return NULL; - } - - init.name = name; - init.ops = &samsung_pll36xx_clk_ops; - init.flags = CLK_GET_RATE_NOCACHE; - init.parent_names = &pname; - init.num_parents = 1; - - pll->hw.init = &init; - pll->con_reg = con_reg; - - clk = clk_register(NULL, &pll->hw); - if (IS_ERR(clk)) { - pr_err("%s: failed to register pll clock %s\n", __func__, - name); - kfree(pll); - } - - if (clk_register_clkdev(clk, name, NULL)) - pr_err("%s: failed to register lookup for %s", __func__, name); - - return clk; -} - /* * PLL45xx Clock Type */ diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index 0d86bf0de40c..1536f2764f8e 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -31,10 +31,6 @@ enum pll46xx_type { pll_4650c, }; -extern struct clk * __init samsung_clk_register_pll35xx(const char *name, - const char *pname, const void __iomem *con_reg); -extern struct clk * __init samsung_clk_register_pll36xx(const char *name, - const char *pname, const void __iomem *con_reg); extern struct clk * __init samsung_clk_register_pll45xx(const char *name, const char *pname, const void __iomem *con_reg, enum pll45xx_type type); From 3ff6e0d8d64d594a551b5c4904e4b617bf7eee22 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Tue, 11 Jun 2013 15:01:12 +0530 Subject: [PATCH 021/102] clk: samsung: Add support to register rate_table for samsung plls This patch defines a common rate_table which will contain recommended p, m, s, k values for supported rates that needs to be changed for changing corresponding PLL's rate. Reviewed-by: Doug Anderson Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos4.c | 8 ++++---- drivers/clk/samsung/clk-exynos5250.c | 14 +++++++------- drivers/clk/samsung/clk-exynos5420.c | 22 +++++++++++----------- drivers/clk/samsung/clk-pll.c | 19 ++++++++++++++++++- drivers/clk/samsung/clk-pll.h | 27 +++++++++++++++++++++++++++ drivers/clk/samsung/clk.h | 13 ++++++++----- 6 files changed, 75 insertions(+), 28 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 9de7a39b1adf..68f9a4a67266 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -986,13 +986,13 @@ static __initdata struct of_device_id ext_clk_match[] = { struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = { [apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, - APLL_CON0, "fout_apll"), + APLL_CON0, "fout_apll", NULL), [mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", - E4X12_MPLL_LOCK, E4X12_MPLL_CON0, "fout_mpll"), + E4X12_MPLL_LOCK, E4X12_MPLL_CON0, "fout_mpll", NULL), [epll] = PLL_A(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK, - EPLL_CON0, "fout_epll"), + EPLL_CON0, "fout_epll", NULL), [vpll] = PLL_A(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK, - VPLL_CON0, "fout_vpll"), + VPLL_CON0, "fout_vpll", NULL), }; /* register exynos4 clocks */ diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index b9a5f2a22b9a..46a16362f9c9 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -493,19 +493,19 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = { [apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, - APLL_CON0, "fout_apll"), + APLL_CON0, "fout_apll", NULL), [mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK, - MPLL_CON0, "fout_mpll"), + MPLL_CON0, "fout_mpll", NULL), [bpll] = PLL(pll_35xx, fout_bpll, "fout_bpll", "fin_pll", BPLL_LOCK, - BPLL_CON0), + BPLL_CON0, NULL), [gpll] = PLL(pll_35xx, fout_gpll, "fout_gpll", "fin_pll", GPLL_LOCK, - GPLL_CON0), + GPLL_CON0, NULL), [cpll] = PLL(pll_35xx, fout_cpll, "fout_cpll", "fin_pll", CPLL_LOCK, - CPLL_CON0), + CPLL_CON0, NULL), [epll] = PLL(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK, - EPLL_CON0), + EPLL_CON0, NULL), [vpll] = PLL(pll_36xx, fout_vpll, "fout_vpll", "mout_vpllsrc", - VPLL_LOCK, VPLL_CON0), + VPLL_LOCK, VPLL_CON0, NULL), }; static __initdata struct of_device_id ext_clk_match[] = { diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 3dbe7a33297e..ca352695a954 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -729,27 +729,27 @@ static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { struct __initdata samsung_pll_clock exynos5420_plls[nr_plls] = { [apll] = PLL(pll_2550, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, - APLL_CON0), + APLL_CON0, NULL), [cpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK, - MPLL_CON0), + MPLL_CON0, NULL), [dpll] = PLL(pll_2550, fout_dpll, "fout_dpll", "fin_pll", DPLL_LOCK, - DPLL_CON0), + DPLL_CON0, NULL), [epll] = PLL(pll_2650, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK, - EPLL_CON0), + EPLL_CON0, NULL), [rpll] = PLL(pll_2650, fout_rpll, "fout_rpll", "fin_pll", RPLL_LOCK, - RPLL_CON0), + RPLL_CON0, NULL), [ipll] = PLL(pll_2550, fout_ipll, "fout_ipll", "fin_pll", IPLL_LOCK, - IPLL_CON0), + IPLL_CON0, NULL), [spll] = PLL(pll_2550, fout_spll, "fout_spll", "fin_pll", SPLL_LOCK, - SPLL_CON0), + SPLL_CON0, NULL), [vpll] = PLL(pll_2550, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK, - VPLL_CON0), + VPLL_CON0, NULL), [mpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK, - MPLL_CON0), + MPLL_CON0, NULL), [bpll] = PLL(pll_2550, fout_bpll, "fout_bpll", "fin_pll", BPLL_LOCK, - BPLL_CON0), + BPLL_CON0, NULL), [kpll] = PLL(pll_2550, fout_kpll, "fout_kpll", "fin_pll", KPLL_LOCK, - KPLL_CON0), + KPLL_CON0, NULL), }; static __initdata struct of_device_id ext_clk_match[] = { diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index dd948f2ffdf7..83942318df13 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -18,6 +18,8 @@ struct samsung_clk_pll { void __iomem *lock_reg; void __iomem *con_reg; enum samsung_pll_type type; + unsigned int rate_count; + const struct samsung_pll_rate_table *rate_table; }; #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw) @@ -350,7 +352,7 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, struct samsung_clk_pll *pll; struct clk *clk; struct clk_init_data init; - int ret; + int ret, len; pll = kzalloc(sizeof(*pll), GFP_KERNEL); if (!pll) { @@ -364,6 +366,21 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, init.parent_names = &pll_clk->parent_name; init.num_parents = 1; + if (pll_clk->rate_table) { + /* find count of rates in rate_table */ + for (len = 0; pll_clk->rate_table[len].rate != 0; ) + len++; + + pll->rate_count = len; + pll->rate_table = kmemdup(pll_clk->rate_table, + pll->rate_count * + sizeof(struct samsung_pll_rate_table), + GFP_KERNEL); + WARN(!pll->rate_table, + "%s: could not allocate rate table for %s\n", + __func__, pll_clk->name); + } + switch (pll_clk->type) { /* clk_ops for 35xx and 2550 are similar */ case pll_35xx: diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index 1536f2764f8e..95ae23d75b3c 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -19,6 +19,33 @@ enum samsung_pll_type { pll_2650, }; +#define PLL_35XX_RATE(_rate, _m, _p, _s) \ + { \ + .rate = (_rate), \ + .mdiv = (_m), \ + .pdiv = (_p), \ + .sdiv = (_s), \ + } + +#define PLL_36XX_RATE(_rate, _m, _p, _s, _k) \ + { \ + .rate = (_rate), \ + .mdiv = (_m), \ + .pdiv = (_p), \ + .sdiv = (_s), \ + .kdiv = (_k), \ + } + +/* NOTE: Rate table should be kept sorted in descending order. */ + +struct samsung_pll_rate_table { + unsigned int rate; + unsigned int pdiv; + unsigned int mdiv; + unsigned int sdiv; + unsigned int kdiv; +}; + enum pll45xx_type { pll_4500, pll_4502, diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index 4e83e521fe7d..b3f2532823d5 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -283,10 +283,12 @@ struct samsung_pll_clock { int con_offset; int lock_offset; enum samsung_pll_type type; + const struct samsung_pll_rate_table *rate_table; const char *alias; }; -#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con, _alias) \ +#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con, \ + _rtable, _alias) \ { \ .id = _id, \ .type = _typ, \ @@ -296,16 +298,17 @@ struct samsung_pll_clock { .flags = CLK_GET_RATE_NOCACHE, \ .con_offset = _con, \ .lock_offset = _lock, \ + .rate_table = _rtable, \ .alias = _alias, \ } -#define PLL(_typ, _id, _name, _pname, _lock, _con) \ +#define PLL(_typ, _id, _name, _pname, _lock, _con, _rtable) \ __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ - _lock, _con, NULL) + _lock, _con, _rtable, _name) -#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias) \ +#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias, _rtable) \ __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ - _lock, _con, _alias) + _lock, _con, _rtable, _alias) extern void __init samsung_clk_init(struct device_node *np, void __iomem *base, unsigned long nr_clks, unsigned long *rdump, From dfa893190d6c3fe2a2fd92bb3b2fb7eab6442e1d Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Tue, 11 Jun 2013 15:01:13 +0530 Subject: [PATCH 022/102] clk: samsung: Add set_rate() clk_ops for PLL35xx This patch add set_rate() and round_rate() for PLL35xx Reviewed-by: Doug Anderson Reviewed-by: Tomasz Figa Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-pll.c | 105 +++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 83942318df13..03486e339b64 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -24,16 +24,51 @@ struct samsung_clk_pll { #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw) +static const struct samsung_pll_rate_table *samsung_get_pll_settings( + struct samsung_clk_pll *pll, unsigned long rate) +{ + const struct samsung_pll_rate_table *rate_table = pll->rate_table; + int i; + + for (i = 0; i < pll->rate_count; i++) { + if (rate == rate_table[i].rate) + return &rate_table[i]; + } + + return NULL; +} + +static long samsung_pll_round_rate(struct clk_hw *hw, + unsigned long drate, unsigned long *prate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + const struct samsung_pll_rate_table *rate_table = pll->rate_table; + int i; + + /* Assumming rate_table is in descending order */ + for (i = 0; i < pll->rate_count; i++) { + if (drate >= rate_table[i].rate) + return rate_table[i].rate; + } + + /* return minimum supported value */ + return rate_table[i - 1].rate; +} + /* * PLL35xx Clock Type */ +/* Maximum lock time can be 270 * PDIV cycles */ +#define PLL35XX_LOCK_FACTOR (270) #define PLL35XX_MDIV_MASK (0x3FF) #define PLL35XX_PDIV_MASK (0x3F) #define PLL35XX_SDIV_MASK (0x7) +#define PLL35XX_LOCK_STAT_MASK (0x1) #define PLL35XX_MDIV_SHIFT (16) #define PLL35XX_PDIV_SHIFT (8) #define PLL35XX_SDIV_SHIFT (0) +#define PLL35XX_LOCK_STAT_SHIFT (29) static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) @@ -53,8 +88,73 @@ static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw, return (unsigned long)fvco; } +static inline bool samsung_pll35xx_mp_change( + const struct samsung_pll_rate_table *rate, u32 pll_con) +{ + u32 old_mdiv, old_pdiv; + + old_mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK; + old_pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK; + + return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv); +} + +static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long prate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + const struct samsung_pll_rate_table *rate; + u32 tmp; + + /* Get required rate settings from table */ + rate = samsung_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, __clk_get_name(hw->clk)); + return -EINVAL; + } + + tmp = __raw_readl(pll->con_reg); + + if (!(samsung_pll35xx_mp_change(rate, tmp))) { + /* If only s change, change just s value only*/ + tmp &= ~(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT); + tmp |= rate->sdiv << PLL35XX_SDIV_SHIFT; + __raw_writel(tmp, pll->con_reg); + + return 0; + } + + /* Set PLL lock time. */ + __raw_writel(rate->pdiv * PLL35XX_LOCK_FACTOR, + pll->lock_reg); + + /* Change PLL PMS values */ + tmp &= ~((PLL35XX_MDIV_MASK << PLL35XX_MDIV_SHIFT) | + (PLL35XX_PDIV_MASK << PLL35XX_PDIV_SHIFT) | + (PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT)); + tmp |= (rate->mdiv << PLL35XX_MDIV_SHIFT) | + (rate->pdiv << PLL35XX_PDIV_SHIFT) | + (rate->sdiv << PLL35XX_SDIV_SHIFT); + __raw_writel(tmp, pll->con_reg); + + /* wait_lock_time */ + do { + cpu_relax(); + tmp = __raw_readl(pll->con_reg); + } while (!(tmp & (PLL35XX_LOCK_STAT_MASK + << PLL35XX_LOCK_STAT_SHIFT))); + return 0; +} + static const struct clk_ops samsung_pll35xx_clk_ops = { .recalc_rate = samsung_pll35xx_recalc_rate, + .round_rate = samsung_pll_round_rate, + .set_rate = samsung_pll35xx_set_rate, +}; + +static const struct clk_ops samsung_pll35xx_clk_min_ops = { + .recalc_rate = samsung_pll35xx_recalc_rate, }; /* @@ -385,7 +485,10 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, /* clk_ops for 35xx and 2550 are similar */ case pll_35xx: case pll_2550: - init.ops = &samsung_pll35xx_clk_ops; + if (!pll->rate_table) + init.ops = &samsung_pll35xx_clk_min_ops; + else + init.ops = &samsung_pll35xx_clk_ops; break; /* clk_ops for 36xx and 2650 are similar */ case pll_36xx: From bb4278dc9a485c109668fe477a37e85c668a739d Mon Sep 17 00:00:00 2001 From: Vikas Sajjan Date: Tue, 11 Jun 2013 15:01:14 +0530 Subject: [PATCH 023/102] clk: samsung: Add set_rate() clk_ops for PLL36xx This patch adds set_rate and round_rate clk_ops for PLL36xx Reviewed-by: Tomasz Figa Reviewed-by: Doug Anderson Signed-off-by: Vikas Sajjan Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-pll.c | 79 ++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 03486e339b64..f80efb6bc0b3 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -160,6 +160,8 @@ static const struct clk_ops samsung_pll35xx_clk_min_ops = { /* * PLL36xx Clock Type */ +/* Maximum lock time can be 3000 * PDIV cycles */ +#define PLL36XX_LOCK_FACTOR (3000) #define PLL36XX_KDIV_MASK (0xFFFF) #define PLL36XX_MDIV_MASK (0x1FF) @@ -168,6 +170,8 @@ static const struct clk_ops samsung_pll35xx_clk_min_ops = { #define PLL36XX_MDIV_SHIFT (16) #define PLL36XX_PDIV_SHIFT (8) #define PLL36XX_SDIV_SHIFT (0) +#define PLL36XX_KDIV_SHIFT (0) +#define PLL36XX_LOCK_STAT_SHIFT (29) static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) @@ -191,8 +195,78 @@ static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw, return (unsigned long)fvco; } +static inline bool samsung_pll36xx_mpk_change( + const struct samsung_pll_rate_table *rate, u32 pll_con0, u32 pll_con1) +{ + u32 old_mdiv, old_pdiv, old_kdiv; + + old_mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK; + old_pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK; + old_kdiv = (pll_con1 >> PLL36XX_KDIV_SHIFT) & PLL36XX_KDIV_MASK; + + return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv || + rate->kdiv != old_kdiv); +} + +static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 tmp, pll_con0, pll_con1; + const struct samsung_pll_rate_table *rate; + + rate = samsung_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, __clk_get_name(hw->clk)); + return -EINVAL; + } + + pll_con0 = __raw_readl(pll->con_reg); + pll_con1 = __raw_readl(pll->con_reg + 4); + + if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) { + /* If only s change, change just s value only*/ + pll_con0 &= ~(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT); + pll_con0 |= (rate->sdiv << PLL36XX_SDIV_SHIFT); + __raw_writel(pll_con0, pll->con_reg); + + return 0; + } + + /* Set PLL lock time. */ + __raw_writel(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg); + + /* Change PLL PMS values */ + pll_con0 &= ~((PLL36XX_MDIV_MASK << PLL36XX_MDIV_SHIFT) | + (PLL36XX_PDIV_MASK << PLL36XX_PDIV_SHIFT) | + (PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT)); + pll_con0 |= (rate->mdiv << PLL36XX_MDIV_SHIFT) | + (rate->pdiv << PLL36XX_PDIV_SHIFT) | + (rate->sdiv << PLL36XX_SDIV_SHIFT); + __raw_writel(pll_con0, pll->con_reg); + + pll_con1 &= ~(PLL36XX_KDIV_MASK << PLL36XX_KDIV_SHIFT); + pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT; + __raw_writel(pll_con1, pll->con_reg + 4); + + /* wait_lock_time */ + do { + cpu_relax(); + tmp = __raw_readl(pll->con_reg); + } while (!(tmp & (1 << PLL36XX_LOCK_STAT_SHIFT))); + + return 0; +} + static const struct clk_ops samsung_pll36xx_clk_ops = { .recalc_rate = samsung_pll36xx_recalc_rate, + .set_rate = samsung_pll36xx_set_rate, + .round_rate = samsung_pll_round_rate, +}; + +static const struct clk_ops samsung_pll36xx_clk_min_ops = { + .recalc_rate = samsung_pll36xx_recalc_rate, }; /* @@ -493,7 +567,10 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, /* clk_ops for 36xx and 2650 are similar */ case pll_36xx: case pll_2650: - init.ops = &samsung_pll36xx_clk_ops; + if (!pll->rate_table) + init.ops = &samsung_pll36xx_clk_min_ops; + else + init.ops = &samsung_pll36xx_clk_ops; break; default: pr_warn("%s: Unknown pll type for pll clk %s\n", From 8bc2eeb83ed9d07c82f2ff22655018eae426fe33 Mon Sep 17 00:00:00 2001 From: Vikas Sajjan Date: Tue, 11 Jun 2013 15:01:15 +0530 Subject: [PATCH 024/102] clk: samsung: Reorder MUX registration for mout_vpllsrc While trying to get rate of "mout_vpllsrc" MUX (parent) for registering the "fout_vpll" (child), we found get rate was failing. So this patch moves the mout_vpllsrc MUX out of the existing common list and registers the mout_vpllsrc MUX before the PLL registrations. Reviewed-by: Tomasz Figa Signed-off-by: Vikas Sajjan Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos5250.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 46a16362f9c9..7404084a3a1d 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -233,6 +233,10 @@ static struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initda FFACTOR(none, "fout_bplldiv2", "fout_bpll", 1, 2, 0), }; +static struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initdata = { + MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1), +}; + static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = { MUX_A(none, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, "mout_apll"), MUX_A(none, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1, "mout_cpu"), @@ -240,7 +244,6 @@ static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = { MUX_A(none, "sclk_mpll", mout_mpll_p, SRC_CORE1, 8, 1, "mout_mpll"), MUX(none, "mout_bpll_fout", mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1), MUX(none, "sclk_bpll", mout_bpll_p, SRC_CDREX, 0, 1), - MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1), MUX(none, "sclk_vpll", mout_vpll_p, SRC_TOP2, 16, 1), MUX(none, "sclk_epll", mout_epll_p, SRC_TOP2, 12, 1), MUX(none, "sclk_cpll", mout_cpll_p, SRC_TOP2, 8, 1), @@ -532,6 +535,8 @@ static void __init exynos5250_clk_init(struct device_node *np) samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks, ARRAY_SIZE(exynos5250_fixed_rate_ext_clks), ext_clk_match); + samsung_clk_register_mux(exynos5250_pll_pmux_clks, + ARRAY_SIZE(exynos5250_pll_pmux_clks)); samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls), reg_base); samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks, From d2127ac4518d81fa5edcaf922fdd34b54a2888a7 Mon Sep 17 00:00:00 2001 From: Vikas Sajjan Date: Tue, 11 Jun 2013 15:01:16 +0530 Subject: [PATCH 025/102] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC Adds the EPLL and VPLL freq table for exynos5250 SoC. Signed-off-by: Vikas Sajjan Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos5250.c | 38 ++++++++++++++++++++++++++++ drivers/clk/samsung/clk.h | 2 ++ 2 files changed, 40 insertions(+) diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 7404084a3a1d..df3628cf2597 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -494,6 +494,29 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { GATE(g2d, "g2d", "aclk200", GATE_IP_ACP, 3, 0, 0), }; +static __initdata struct samsung_pll_rate_table vpll_24mhz_tbl[] = { + /* sorted in descending order */ + /* PLL_36XX_RATE(rate, m, p, s, k) */ + PLL_36XX_RATE(266000000, 266, 3, 3, 0), + /* Not in UM, but need for eDP on snow */ + PLL_36XX_RATE(70500000, 94, 2, 4, 0), + { }, +}; + +static __initdata struct samsung_pll_rate_table epll_24mhz_tbl[] = { + /* sorted in descending order */ + /* PLL_36XX_RATE(rate, m, p, s, k) */ + PLL_36XX_RATE(192000000, 64, 2, 2, 0), + PLL_36XX_RATE(180633600, 90, 3, 2, 20762), + PLL_36XX_RATE(180000000, 90, 3, 2, 0), + PLL_36XX_RATE(73728000, 98, 2, 4, 19923), + PLL_36XX_RATE(67737600, 90, 2, 4, 20762), + PLL_36XX_RATE(49152000, 98, 3, 4, 19923), + PLL_36XX_RATE(45158400, 90, 3, 4, 20762), + PLL_36XX_RATE(32768000, 131, 3, 5, 4719), + { }, +}; + struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = { [apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, "fout_apll", NULL), @@ -520,6 +543,8 @@ static __initdata struct of_device_id ext_clk_match[] = { static void __init exynos5250_clk_init(struct device_node *np) { void __iomem *reg_base; + struct clk *vpllsrc; + unsigned long fin_pll_rate, mout_vpllsrc_rate = 0; if (np) { reg_base = of_iomap(np, 0); @@ -537,6 +562,19 @@ static void __init exynos5250_clk_init(struct device_node *np) ext_clk_match); samsung_clk_register_mux(exynos5250_pll_pmux_clks, ARRAY_SIZE(exynos5250_pll_pmux_clks)); + + fin_pll_rate = _get_rate("fin_pll"); + + if (fin_pll_rate == 24 * MHZ) + exynos5250_plls[epll].rate_table = epll_24mhz_tbl; + + vpllsrc = __clk_lookup("mout_vpllsrc"); + if (vpllsrc) + mout_vpllsrc_rate = clk_get_rate(vpllsrc); + + if (mout_vpllsrc_rate == 24 * MHZ) + exynos5250_plls[vpll].rate_table = vpll_24mhz_tbl; + samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls), reg_base); samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks, diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index b3f2532823d5..e7dfccb5d981 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -40,6 +40,8 @@ struct samsung_clock_alias { .alias = a, \ } +#define MHZ (1000 * 1000) + /** * struct samsung_fixed_rate_clock: information about fixed-rate clock * @id: platform specific id of the clock. From c57acd14ac2d53e40f5c17701c3cc3a092a07b35 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Tue, 23 Jul 2013 01:49:18 +0200 Subject: [PATCH 026/102] clk: mux: Add support for read-only muxes. Some platforms have read-only clock muxes that are preconfigured at reset and cannot be changed at runtime. This patch extends mux clock driver to allow handling such read-only muxes by adding new CLK_MUX_READ_ONLY mux flag. Signed-off-by: Tomasz Figa Signed-off-by: Mike Turquette --- drivers/clk/clk-mux.c | 10 +++++++++- include/linux/clk-provider.h | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 614444ca40cd..92f1a1be5319 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -107,6 +107,11 @@ const struct clk_ops clk_mux_ops = { }; EXPORT_SYMBOL_GPL(clk_mux_ops); +const struct clk_ops clk_mux_ro_ops = { + .get_parent = clk_mux_get_parent, +}; +EXPORT_SYMBOL_GPL(clk_mux_ro_ops); + struct clk *clk_register_mux_table(struct device *dev, const char *name, const char **parent_names, u8 num_parents, unsigned long flags, void __iomem *reg, u8 shift, u32 mask, @@ -133,7 +138,10 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name, } init.name = name; - init.ops = &clk_mux_ops; + if (clk_mux_flags & CLK_MUX_READ_ONLY) + init.ops = &clk_mux_ro_ops; + else + init.ops = &clk_mux_ops; init.flags = flags | CLK_IS_BASIC; init.parent_names = parent_names; init.num_parents = num_parents; diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 1ec14a732176..9487b96939e8 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -327,8 +327,10 @@ struct clk_mux { #define CLK_MUX_INDEX_ONE BIT(0) #define CLK_MUX_INDEX_BIT BIT(1) #define CLK_MUX_HIWORD_MASK BIT(2) +#define CLK_MUX_READ_ONLY BIT(3) /* mux setting cannot be changed */ extern const struct clk_ops clk_mux_ops; +extern const struct clk_ops clk_mux_ro_ops; struct clk *clk_register_mux(struct device *dev, const char *name, const char **parent_names, u8 num_parents, unsigned long flags, From eb5271215b7ed62a3319666986ab47c3bcded6fc Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Tue, 23 Jul 2013 01:49:19 +0200 Subject: [PATCH 027/102] clk: samsung: pll: Add support for PLL6552 and PLL6553 This patch adds support for PLL6552 and PLL6553 PLLs present on Samsung S3C64xx SoCs. Signed-off-by: Tomasz Figa Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-pll.c | 160 ++++++++++++++++++++++++++++++++++ drivers/clk/samsung/clk-pll.h | 4 + 2 files changed, 164 insertions(+) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 362f12dcd944..698e5621b6e7 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -336,6 +336,166 @@ struct clk * __init samsung_clk_register_pll46xx(const char *name, return clk; } +/* + * PLL6552 Clock Type + */ + +#define PLL6552_LOCK_REG 0x00 +#define PLL6552_CON_REG 0x0c + +#define PLL6552_MDIV_MASK 0x3ff +#define PLL6552_PDIV_MASK 0x3f +#define PLL6552_SDIV_MASK 0x7 +#define PLL6552_MDIV_SHIFT 16 +#define PLL6552_PDIV_SHIFT 8 +#define PLL6552_SDIV_SHIFT 0 + +struct samsung_clk_pll6552 { + struct clk_hw hw; + void __iomem *reg_base; +}; + +#define to_clk_pll6552(_hw) container_of(_hw, struct samsung_clk_pll6552, hw) + +static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll6552 *pll = to_clk_pll6552(hw); + u32 mdiv, pdiv, sdiv, pll_con; + u64 fvco = parent_rate; + + pll_con = __raw_readl(pll->reg_base + PLL6552_CON_REG); + mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK; + pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK; + sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK; + + fvco *= mdiv; + do_div(fvco, (pdiv << sdiv)); + + return (unsigned long)fvco; +} + +static const struct clk_ops samsung_pll6552_clk_ops = { + .recalc_rate = samsung_pll6552_recalc_rate, +}; + +struct clk * __init samsung_clk_register_pll6552(const char *name, + const char *pname, void __iomem *base) +{ + struct samsung_clk_pll6552 *pll; + struct clk *clk; + struct clk_init_data init; + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) { + pr_err("%s: could not allocate pll clk %s\n", __func__, name); + return NULL; + } + + init.name = name; + init.ops = &samsung_pll6552_clk_ops; + init.parent_names = &pname; + init.num_parents = 1; + + pll->hw.init = &init; + pll->reg_base = base; + + clk = clk_register(NULL, &pll->hw); + if (IS_ERR(clk)) { + pr_err("%s: failed to register pll clock %s\n", __func__, + name); + kfree(pll); + } + + if (clk_register_clkdev(clk, name, NULL)) + pr_err("%s: failed to register lookup for %s", __func__, name); + + return clk; +} + +/* + * PLL6553 Clock Type + */ + +#define PLL6553_LOCK_REG 0x00 +#define PLL6553_CON0_REG 0x0c +#define PLL6553_CON1_REG 0x10 + +#define PLL6553_MDIV_MASK 0xff +#define PLL6553_PDIV_MASK 0x3f +#define PLL6553_SDIV_MASK 0x7 +#define PLL6553_KDIV_MASK 0xffff +#define PLL6553_MDIV_SHIFT 16 +#define PLL6553_PDIV_SHIFT 8 +#define PLL6553_SDIV_SHIFT 0 +#define PLL6553_KDIV_SHIFT 0 + +struct samsung_clk_pll6553 { + struct clk_hw hw; + void __iomem *reg_base; +}; + +#define to_clk_pll6553(_hw) container_of(_hw, struct samsung_clk_pll6553, hw) + +static unsigned long samsung_pll6553_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll6553 *pll = to_clk_pll6553(hw); + u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1; + u64 fvco = parent_rate; + + pll_con0 = __raw_readl(pll->reg_base + PLL6553_CON0_REG); + pll_con1 = __raw_readl(pll->reg_base + PLL6553_CON1_REG); + mdiv = (pll_con0 >> PLL6553_MDIV_SHIFT) & PLL6553_MDIV_MASK; + pdiv = (pll_con0 >> PLL6553_PDIV_SHIFT) & PLL6553_PDIV_MASK; + sdiv = (pll_con0 >> PLL6553_SDIV_SHIFT) & PLL6553_SDIV_MASK; + kdiv = (pll_con1 >> PLL6553_KDIV_SHIFT) & PLL6553_KDIV_MASK; + + fvco *= (mdiv << 16) + kdiv; + do_div(fvco, (pdiv << sdiv)); + fvco >>= 16; + + return (unsigned long)fvco; +} + +static const struct clk_ops samsung_pll6553_clk_ops = { + .recalc_rate = samsung_pll6553_recalc_rate, +}; + +struct clk * __init samsung_clk_register_pll6553(const char *name, + const char *pname, void __iomem *base) +{ + struct samsung_clk_pll6553 *pll; + struct clk *clk; + struct clk_init_data init; + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) { + pr_err("%s: could not allocate pll clk %s\n", __func__, name); + return NULL; + } + + init.name = name; + init.ops = &samsung_pll6553_clk_ops; + init.parent_names = &pname; + init.num_parents = 1; + + pll->hw.init = &init; + pll->reg_base = base; + + clk = clk_register(NULL, &pll->hw); + if (IS_ERR(clk)) { + pr_err("%s: failed to register pll clock %s\n", __func__, + name); + kfree(pll); + } + + if (clk_register_clkdev(clk, name, NULL)) + pr_err("%s: failed to register lookup for %s", __func__, name); + + return clk; +} + /* * PLL2550x Clock Type */ diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index f33786e9a78b..1d68a68d6c62 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -34,6 +34,10 @@ extern struct clk * __init samsung_clk_register_pll45xx(const char *name, extern struct clk * __init samsung_clk_register_pll46xx(const char *name, const char *pname, const void __iomem *con_reg, enum pll46xx_type type); +extern struct clk *samsung_clk_register_pll6552(const char *name, + const char *pname, void __iomem *base); +extern struct clk *samsung_clk_register_pll6553(const char *name, + const char *pname, void __iomem *base); extern struct clk * __init samsung_clk_register_pll2550x(const char *name, const char *pname, const void __iomem *reg_base, const unsigned long offset); From 06dda9d770063c5fefc0b41c7bfcc1321e2649dd Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Wed, 24 Jul 2013 01:55:15 +0200 Subject: [PATCH 028/102] clk: samsung: Add clock driver for S3C64xx SoCs This patch adds new, Common Clock Framework-based clock driver for Samsung S3C64xx SoCs. The driver is just added, without actually letting the platforms use it yet, since this requires more intermediate steps. Signed-off-by: Tomasz Figa Signed-off-by: Mike Turquette --- .../bindings/clock/samsung,s3c64xx-clock.txt | 77 +++ drivers/clk/samsung/Makefile | 3 + drivers/clk/samsung/clk-s3c64xx.c | 473 ++++++++++++++++++ .../dt-bindings/clock/samsung,s3c64xx-clock.h | 178 +++++++ 4 files changed, 731 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt create mode 100644 drivers/clk/samsung/clk-s3c64xx.c create mode 100644 include/dt-bindings/clock/samsung,s3c64xx-clock.h diff --git a/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt b/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt new file mode 100644 index 000000000000..fa171dc4bd3c --- /dev/null +++ b/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt @@ -0,0 +1,77 @@ +* Samsung S3C64xx Clock Controller + +The S3C64xx clock controller generates and supplies clock to various controllers +within the SoC. The clock binding described here is applicable to all SoCs in +the S3C64xx family. + +Required Properties: + +- compatible: should be one of the following. + - "samsung,s3c6400-clock" - controller compatible with S3C6400 SoC. + - "samsung,s3c6410-clock" - controller compatible with S3C6410 SoC. + +- reg: physical base address of the controller and length of memory mapped + region. + +- #clock-cells: should be 1. + +Each clock is assigned an identifier and client nodes can use this identifier +to specify the clock which they consume. Some of the clocks are available only +on a particular S3C64xx SoC and this is specified where applicable. + +All available clocks are defined as preprocessor macros in +dt-bindings/clock/samsung,s3c64xx-clock.h header and can be used in device +tree sources. + +External clocks: + +There are several clocks that are generated outside the SoC. It is expected +that they are defined using standard clock bindings with following +clock-output-names: + - "fin_pll" - PLL input clock (xtal/extclk) - required, + - "xusbxti" - USB xtal - required, + - "iiscdclk0" - I2S0 codec clock - optional, + - "iiscdclk1" - I2S1 codec clock - optional, + - "iiscdclk2" - I2S2 codec clock - optional, + - "pcmcdclk0" - PCM0 codec clock - optional, + - "pcmcdclk1" - PCM1 codec clock - optional, only S3C6410. + +Example: Clock controller node: + + clock: clock-controller@7e00f000 { + compatible = "samsung,s3c6410-clock"; + reg = <0x7e00f000 0x1000>; + #clock-cells = <1>; + }; + +Example: Required external clocks: + + fin_pll: clock-fin-pll { + compatible = "fixed-clock"; + clock-output-names = "fin_pll"; + clock-frequency = <12000000>; + #clock-cells = <0>; + }; + + xusbxti: clock-xusbxti { + compatible = "fixed-clock"; + clock-output-names = "xusbxti"; + clock-frequency = <48000000>; + #clock-cells = <0>; + }; + +Example: UART controller node that consumes the clock generated by the clock + controller (refer to the standard clock bindings for information about + "clocks" and "clock-names" properties): + + uart0: serial@7f005000 { + compatible = "samsung,s3c6400-uart"; + reg = <0x7f005000 0x100>; + interrupt-parent = <&vic1>; + interrupts = <5>; + clock-names = "uart", "clk_uart_baud2", + "clk_uart_baud3"; + clocks = <&clock PCLK_UART0>, <&clocks PCLK_UART0>, + <&clock SCLK_UART>; + status = "disabled"; + }; diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 5d4d432cc4ac..3413380086d5 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -8,3 +8,6 @@ obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o +ifdef CONFIG_COMMON_CLK +obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o +endif diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c new file mode 100644 index 000000000000..eeda5675bd17 --- /dev/null +++ b/drivers/clk/samsung/clk-s3c64xx.c @@ -0,0 +1,473 @@ +/* + * Copyright (c) 2013 Tomasz Figa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Common Clock Framework support for all S3C64xx SoCs. +*/ + +#include +#include +#include +#include +#include + +#include + +#include "clk.h" +#include "clk-pll.h" + +/* S3C64xx clock controller register offsets. */ +#define APLL_LOCK 0x000 +#define MPLL_LOCK 0x004 +#define EPLL_LOCK 0x008 +#define APLL_CON 0x00c +#define MPLL_CON 0x010 +#define EPLL_CON0 0x014 +#define EPLL_CON1 0x018 +#define CLK_SRC 0x01c +#define CLK_DIV0 0x020 +#define CLK_DIV1 0x024 +#define CLK_DIV2 0x028 +#define HCLK_GATE 0x030 +#define PCLK_GATE 0x034 +#define SCLK_GATE 0x038 +#define MEM0_GATE 0x03c +#define CLK_SRC2 0x10c +#define OTHERS 0x900 + +/* Helper macros to define clock arrays. */ +#define FIXED_RATE_CLOCKS(name) \ + static struct samsung_fixed_rate_clock name[] +#define MUX_CLOCKS(name) \ + static struct samsung_mux_clock name[] +#define DIV_CLOCKS(name) \ + static struct samsung_div_clock name[] +#define GATE_CLOCKS(name) \ + static struct samsung_gate_clock name[] + +/* Helper macros for gate types present on S3C64xx. */ +#define GATE_BUS(_id, cname, pname, o, b) \ + GATE(_id, cname, pname, o, b, 0, 0) +#define GATE_SCLK(_id, cname, pname, o, b) \ + GATE(_id, cname, pname, o, b, CLK_SET_RATE_PARENT, 0) +#define GATE_ON(_id, cname, pname, o, b) \ + GATE(_id, cname, pname, o, b, CLK_IGNORE_UNUSED, 0) + +/* list of PLLs to be registered */ +enum s3c64xx_plls { + apll, mpll, epll, +}; + +/* + * List of controller registers to be saved and restored during + * a suspend/resume cycle. + */ +static __initdata unsigned long s3c64xx_clk_regs[] = { + APLL_LOCK, + MPLL_LOCK, + EPLL_LOCK, + APLL_CON, + MPLL_CON, + EPLL_CON0, + EPLL_CON1, + CLK_SRC, + CLK_DIV0, + CLK_DIV1, + CLK_DIV2, + HCLK_GATE, + PCLK_GATE, + SCLK_GATE, +}; + +static __initdata unsigned long s3c6410_clk_regs[] = { + CLK_SRC2, + MEM0_GATE, +}; + +/* List of parent clocks common for all S3C64xx SoCs. */ +PNAME(spi_mmc_p) = { "mout_epll", "dout_mpll", "fin_pll", "clk27m" }; +PNAME(uart_p) = { "mout_epll", "dout_mpll" }; +PNAME(audio0_p) = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk0", + "pcmcdclk0", "none", "none", "none" }; +PNAME(audio1_p) = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk1", + "pcmcdclk0", "none", "none", "none" }; +PNAME(mfc_p) = { "hclkx2", "mout_epll" }; +PNAME(apll_p) = { "fin_pll", "fout_apll" }; +PNAME(mpll_p) = { "fin_pll", "fout_mpll" }; +PNAME(epll_p) = { "fin_pll", "fout_epll" }; +PNAME(hclkx2_p) = { "mout_mpll", "mout_apll" }; + +/* S3C6400-specific parent clocks. */ +PNAME(scaler_lcd_p6400) = { "mout_epll", "dout_mpll", "none", "none" }; +PNAME(irda_p6400) = { "mout_epll", "dout_mpll", "none", "clk48m" }; +PNAME(uhost_p6400) = { "clk48m", "mout_epll", "dout_mpll", "none" }; + +/* S3C6410-specific parent clocks. */ +PNAME(clk27_p6410) = { "clk27m", "fin_pll" }; +PNAME(scaler_lcd_p6410) = { "mout_epll", "dout_mpll", "fin_pll", "none" }; +PNAME(irda_p6410) = { "mout_epll", "dout_mpll", "fin_pll", "clk48m" }; +PNAME(uhost_p6410) = { "clk48m", "mout_epll", "dout_mpll", "fin_pll" }; +PNAME(audio2_p6410) = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk2", + "pcmcdclk1", "none", "none", "none" }; + +/* Fixed rate clocks generated outside the SoC. */ +FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_ext_clks) __initdata = { + FRATE(0, "fin_pll", NULL, CLK_IS_ROOT, 0), + FRATE(0, "xusbxti", NULL, CLK_IS_ROOT, 0), +}; + +/* Fixed rate clocks generated inside the SoC. */ +FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_clks) __initdata = { + FRATE(CLK27M, "clk27m", NULL, CLK_IS_ROOT, 27000000), + FRATE(CLK48M, "clk48m", NULL, CLK_IS_ROOT, 48000000), +}; + +/* List of clock muxes present on all S3C64xx SoCs. */ +MUX_CLOCKS(s3c64xx_mux_clks) __initdata = { + MUX_F(0, "mout_syncmux", hclkx2_p, OTHERS, 6, 1, 0, CLK_MUX_READ_ONLY), + MUX(MOUT_APLL, "mout_apll", apll_p, CLK_SRC, 0, 1), + MUX(MOUT_MPLL, "mout_mpll", mpll_p, CLK_SRC, 1, 1), + MUX(MOUT_EPLL, "mout_epll", epll_p, CLK_SRC, 2, 1), + MUX(MOUT_MFC, "mout_mfc", mfc_p, CLK_SRC, 4, 1), + MUX(MOUT_AUDIO0, "mout_audio0", audio0_p, CLK_SRC, 7, 3), + MUX(MOUT_AUDIO1, "mout_audio1", audio1_p, CLK_SRC, 10, 3), + MUX(MOUT_UART, "mout_uart", uart_p, CLK_SRC, 13, 1), + MUX(MOUT_SPI0, "mout_spi0", spi_mmc_p, CLK_SRC, 14, 2), + MUX(MOUT_SPI1, "mout_spi1", spi_mmc_p, CLK_SRC, 16, 2), + MUX(MOUT_MMC0, "mout_mmc0", spi_mmc_p, CLK_SRC, 18, 2), + MUX(MOUT_MMC1, "mout_mmc1", spi_mmc_p, CLK_SRC, 20, 2), + MUX(MOUT_MMC2, "mout_mmc2", spi_mmc_p, CLK_SRC, 22, 2), +}; + +/* List of clock muxes present on S3C6400. */ +MUX_CLOCKS(s3c6400_mux_clks) __initdata = { + MUX(MOUT_UHOST, "mout_uhost", uhost_p6400, CLK_SRC, 5, 2), + MUX(MOUT_IRDA, "mout_irda", irda_p6400, CLK_SRC, 24, 2), + MUX(MOUT_LCD, "mout_lcd", scaler_lcd_p6400, CLK_SRC, 26, 2), + MUX(MOUT_SCALER, "mout_scaler", scaler_lcd_p6400, CLK_SRC, 28, 2), +}; + +/* List of clock muxes present on S3C6410. */ +MUX_CLOCKS(s3c6410_mux_clks) __initdata = { + MUX(MOUT_UHOST, "mout_uhost", uhost_p6410, CLK_SRC, 5, 2), + MUX(MOUT_IRDA, "mout_irda", irda_p6410, CLK_SRC, 24, 2), + MUX(MOUT_LCD, "mout_lcd", scaler_lcd_p6410, CLK_SRC, 26, 2), + MUX(MOUT_SCALER, "mout_scaler", scaler_lcd_p6410, CLK_SRC, 28, 2), + MUX(MOUT_DAC27, "mout_dac27", clk27_p6410, CLK_SRC, 30, 1), + MUX(MOUT_TV27, "mout_tv27", clk27_p6410, CLK_SRC, 31, 1), + MUX(MOUT_AUDIO2, "mout_audio2", audio2_p6410, CLK_SRC2, 0, 3), +}; + +/* List of clock dividers present on all S3C64xx SoCs. */ +DIV_CLOCKS(s3c64xx_div_clks) __initdata = { + DIV(DOUT_MPLL, "dout_mpll", "mout_mpll", CLK_DIV0, 4, 1), + DIV(HCLKX2, "hclkx2", "mout_syncmux", CLK_DIV0, 9, 3), + DIV(HCLK, "hclk", "hclkx2", CLK_DIV0, 8, 1), + DIV(PCLK, "pclk", "hclkx2", CLK_DIV0, 12, 4), + DIV(DOUT_SECUR, "dout_secur", "hclkx2", CLK_DIV0, 18, 2), + DIV(DOUT_CAM, "dout_cam", "hclkx2", CLK_DIV0, 20, 4), + DIV(DOUT_JPEG, "dout_jpeg", "hclkx2", CLK_DIV0, 24, 4), + DIV(DOUT_MFC, "dout_mfc", "mout_mfc", CLK_DIV0, 28, 4), + DIV(DOUT_MMC0, "dout_mmc0", "mout_mmc0", CLK_DIV1, 0, 4), + DIV(DOUT_MMC1, "dout_mmc1", "mout_mmc1", CLK_DIV1, 4, 4), + DIV(DOUT_MMC2, "dout_mmc2", "mout_mmc2", CLK_DIV1, 8, 4), + DIV(DOUT_LCD, "dout_lcd", "mout_lcd", CLK_DIV1, 12, 4), + DIV(DOUT_SCALER, "dout_scaler", "mout_scaler", CLK_DIV1, 16, 4), + DIV(DOUT_UHOST, "dout_uhost", "mout_uhost", CLK_DIV1, 20, 4), + DIV(DOUT_SPI0, "dout_spi0", "mout_spi0", CLK_DIV2, 0, 4), + DIV(DOUT_SPI1, "dout_spi1", "mout_spi1", CLK_DIV2, 4, 4), + DIV(DOUT_AUDIO0, "dout_audio0", "mout_audio0", CLK_DIV2, 8, 4), + DIV(DOUT_AUDIO1, "dout_audio1", "mout_audio1", CLK_DIV2, 12, 4), + DIV(DOUT_UART, "dout_uart", "mout_uart", CLK_DIV2, 16, 4), + DIV(DOUT_IRDA, "dout_irda", "mout_irda", CLK_DIV2, 20, 4), +}; + +/* List of clock dividers present on S3C6400. */ +DIV_CLOCKS(s3c6400_div_clks) __initdata = { + DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 3), +}; + +/* List of clock dividers present on S3C6410. */ +DIV_CLOCKS(s3c6410_div_clks) __initdata = { + DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 4), + DIV(DOUT_FIMC, "dout_fimc", "hclk", CLK_DIV1, 24, 4), + DIV(DOUT_AUDIO2, "dout_audio2", "mout_audio2", CLK_DIV2, 24, 4), +}; + +/* List of clock gates present on all S3C64xx SoCs. */ +GATE_CLOCKS(s3c64xx_gate_clks) __initdata = { + GATE_BUS(HCLK_UHOST, "hclk_uhost", "hclk", HCLK_GATE, 29), + GATE_BUS(HCLK_SECUR, "hclk_secur", "hclk", HCLK_GATE, 28), + GATE_BUS(HCLK_SDMA1, "hclk_sdma1", "hclk", HCLK_GATE, 27), + GATE_BUS(HCLK_SDMA0, "hclk_sdma0", "hclk", HCLK_GATE, 26), + GATE_ON(HCLK_DDR1, "hclk_ddr1", "hclk", HCLK_GATE, 24), + GATE_BUS(HCLK_USB, "hclk_usb", "hclk", HCLK_GATE, 20), + GATE_BUS(HCLK_HSMMC2, "hclk_hsmmc2", "hclk", HCLK_GATE, 19), + GATE_BUS(HCLK_HSMMC1, "hclk_hsmmc1", "hclk", HCLK_GATE, 18), + GATE_BUS(HCLK_HSMMC0, "hclk_hsmmc0", "hclk", HCLK_GATE, 17), + GATE_BUS(HCLK_MDP, "hclk_mdp", "hclk", HCLK_GATE, 16), + GATE_BUS(HCLK_DHOST, "hclk_dhost", "hclk", HCLK_GATE, 15), + GATE_BUS(HCLK_IHOST, "hclk_ihost", "hclk", HCLK_GATE, 14), + GATE_BUS(HCLK_DMA1, "hclk_dma1", "hclk", HCLK_GATE, 13), + GATE_BUS(HCLK_DMA0, "hclk_dma0", "hclk", HCLK_GATE, 12), + GATE_BUS(HCLK_JPEG, "hclk_jpeg", "hclk", HCLK_GATE, 11), + GATE_BUS(HCLK_CAMIF, "hclk_camif", "hclk", HCLK_GATE, 10), + GATE_BUS(HCLK_SCALER, "hclk_scaler", "hclk", HCLK_GATE, 9), + GATE_BUS(HCLK_2D, "hclk_2d", "hclk", HCLK_GATE, 8), + GATE_BUS(HCLK_TV, "hclk_tv", "hclk", HCLK_GATE, 7), + GATE_BUS(HCLK_POST0, "hclk_post0", "hclk", HCLK_GATE, 5), + GATE_BUS(HCLK_ROT, "hclk_rot", "hclk", HCLK_GATE, 4), + GATE_BUS(HCLK_LCD, "hclk_lcd", "hclk", HCLK_GATE, 3), + GATE_BUS(HCLK_TZIC, "hclk_tzic", "hclk", HCLK_GATE, 2), + GATE_ON(HCLK_INTC, "hclk_intc", "hclk", HCLK_GATE, 1), + GATE_ON(PCLK_SKEY, "pclk_skey", "pclk", PCLK_GATE, 24), + GATE_ON(PCLK_CHIPID, "pclk_chipid", "pclk", PCLK_GATE, 23), + GATE_BUS(PCLK_SPI1, "pclk_spi1", "pclk", PCLK_GATE, 22), + GATE_BUS(PCLK_SPI0, "pclk_spi0", "pclk", PCLK_GATE, 21), + GATE_BUS(PCLK_HSIRX, "pclk_hsirx", "pclk", PCLK_GATE, 20), + GATE_BUS(PCLK_HSITX, "pclk_hsitx", "pclk", PCLK_GATE, 19), + GATE_ON(PCLK_GPIO, "pclk_gpio", "pclk", PCLK_GATE, 18), + GATE_BUS(PCLK_IIC0, "pclk_iic0", "pclk", PCLK_GATE, 17), + GATE_BUS(PCLK_IIS1, "pclk_iis1", "pclk", PCLK_GATE, 16), + GATE_BUS(PCLK_IIS0, "pclk_iis0", "pclk", PCLK_GATE, 15), + GATE_BUS(PCLK_AC97, "pclk_ac97", "pclk", PCLK_GATE, 14), + GATE_BUS(PCLK_TZPC, "pclk_tzpc", "pclk", PCLK_GATE, 13), + GATE_BUS(PCLK_TSADC, "pclk_tsadc", "pclk", PCLK_GATE, 12), + GATE_BUS(PCLK_KEYPAD, "pclk_keypad", "pclk", PCLK_GATE, 11), + GATE_BUS(PCLK_IRDA, "pclk_irda", "pclk", PCLK_GATE, 10), + GATE_BUS(PCLK_PCM1, "pclk_pcm1", "pclk", PCLK_GATE, 9), + GATE_BUS(PCLK_PCM0, "pclk_pcm0", "pclk", PCLK_GATE, 8), + GATE_BUS(PCLK_PWM, "pclk_pwm", "pclk", PCLK_GATE, 7), + GATE_BUS(PCLK_RTC, "pclk_rtc", "pclk", PCLK_GATE, 6), + GATE_BUS(PCLK_WDT, "pclk_wdt", "pclk", PCLK_GATE, 5), + GATE_BUS(PCLK_UART3, "pclk_uart3", "pclk", PCLK_GATE, 4), + GATE_BUS(PCLK_UART2, "pclk_uart2", "pclk", PCLK_GATE, 3), + GATE_BUS(PCLK_UART1, "pclk_uart1", "pclk", PCLK_GATE, 2), + GATE_BUS(PCLK_UART0, "pclk_uart0", "pclk", PCLK_GATE, 1), + GATE_BUS(PCLK_MFC, "pclk_mfc", "pclk", PCLK_GATE, 0), + GATE_SCLK(SCLK_UHOST, "sclk_uhost", "dout_uhost", SCLK_GATE, 30), + GATE_SCLK(SCLK_MMC2_48, "sclk_mmc2_48", "clk48m", SCLK_GATE, 29), + GATE_SCLK(SCLK_MMC1_48, "sclk_mmc1_48", "clk48m", SCLK_GATE, 28), + GATE_SCLK(SCLK_MMC0_48, "sclk_mmc0_48", "clk48m", SCLK_GATE, 27), + GATE_SCLK(SCLK_MMC2, "sclk_mmc2", "dout_mmc2", SCLK_GATE, 26), + GATE_SCLK(SCLK_MMC1, "sclk_mmc1", "dout_mmc1", SCLK_GATE, 25), + GATE_SCLK(SCLK_MMC0, "sclk_mmc0", "dout_mmc0", SCLK_GATE, 24), + GATE_SCLK(SCLK_SPI1_48, "sclk_spi1_48", "clk48m", SCLK_GATE, 23), + GATE_SCLK(SCLK_SPI0_48, "sclk_spi0_48", "clk48m", SCLK_GATE, 22), + GATE_SCLK(SCLK_SPI1, "sclk_spi1", "dout_spi1", SCLK_GATE, 21), + GATE_SCLK(SCLK_SPI0, "sclk_spi0", "dout_spi0", SCLK_GATE, 20), + GATE_SCLK(SCLK_DAC27, "sclk_dac27", "mout_dac27", SCLK_GATE, 19), + GATE_SCLK(SCLK_TV27, "sclk_tv27", "mout_tv27", SCLK_GATE, 18), + GATE_SCLK(SCLK_SCALER27, "sclk_scaler27", "clk27m", SCLK_GATE, 17), + GATE_SCLK(SCLK_SCALER, "sclk_scaler", "dout_scaler", SCLK_GATE, 16), + GATE_SCLK(SCLK_LCD27, "sclk_lcd27", "clk27m", SCLK_GATE, 15), + GATE_SCLK(SCLK_LCD, "sclk_lcd", "dout_lcd", SCLK_GATE, 14), + GATE_SCLK(SCLK_POST0_27, "sclk_post0_27", "clk27m", SCLK_GATE, 12), + GATE_SCLK(SCLK_POST0, "sclk_post0", "dout_lcd", SCLK_GATE, 10), + GATE_SCLK(SCLK_AUDIO1, "sclk_audio1", "dout_audio1", SCLK_GATE, 9), + GATE_SCLK(SCLK_AUDIO0, "sclk_audio0", "dout_audio0", SCLK_GATE, 8), + GATE_SCLK(SCLK_SECUR, "sclk_secur", "dout_secur", SCLK_GATE, 7), + GATE_SCLK(SCLK_IRDA, "sclk_irda", "dout_irda", SCLK_GATE, 6), + GATE_SCLK(SCLK_UART, "sclk_uart", "dout_uart", SCLK_GATE, 5), + GATE_SCLK(SCLK_MFC, "sclk_mfc", "dout_mfc", SCLK_GATE, 3), + GATE_SCLK(SCLK_CAM, "sclk_cam", "dout_cam", SCLK_GATE, 2), + GATE_SCLK(SCLK_JPEG, "sclk_jpeg", "dout_jpeg", SCLK_GATE, 1), +}; + +/* List of clock gates present on S3C6400. */ +GATE_CLOCKS(s3c6400_gate_clks) __initdata = { + GATE_ON(HCLK_DDR0, "hclk_ddr0", "hclk", HCLK_GATE, 23), + GATE_SCLK(SCLK_ONENAND, "sclk_onenand", "parent", SCLK_GATE, 4), +}; + +/* List of clock gates present on S3C6410. */ +GATE_CLOCKS(s3c6410_gate_clks) __initdata = { + GATE_BUS(HCLK_3DSE, "hclk_3dse", "hclk", HCLK_GATE, 31), + GATE_ON(HCLK_IROM, "hclk_irom", "hclk", HCLK_GATE, 25), + GATE_ON(HCLK_MEM1, "hclk_mem1", "hclk", HCLK_GATE, 22), + GATE_ON(HCLK_MEM0, "hclk_mem0", "hclk", HCLK_GATE, 21), + GATE_BUS(HCLK_MFC, "hclk_mfc", "hclk", HCLK_GATE, 0), + GATE_BUS(PCLK_IIC1, "pclk_iic1", "pclk", PCLK_GATE, 27), + GATE_BUS(PCLK_IIS2, "pclk_iis2", "pclk", PCLK_GATE, 26), + GATE_SCLK(SCLK_FIMC, "sclk_fimc", "dout_fimc", SCLK_GATE, 13), + GATE_SCLK(SCLK_AUDIO2, "sclk_audio2", "dout_audio2", SCLK_GATE, 11), + GATE_BUS(MEM0_CFCON, "mem0_cfcon", "hclk_mem0", MEM0_GATE, 5), + GATE_BUS(MEM0_ONENAND1, "mem0_onenand1", "hclk_mem0", MEM0_GATE, 4), + GATE_BUS(MEM0_ONENAND0, "mem0_onenand0", "hclk_mem0", MEM0_GATE, 3), + GATE_BUS(MEM0_NFCON, "mem0_nfcon", "hclk_mem0", MEM0_GATE, 2), + GATE_ON(MEM0_SROM, "mem0_srom", "hclk_mem0", MEM0_GATE, 1), +}; + +/* List of PLL clocks. */ +static struct samsung_pll_clock s3c64xx_pll_clks[] __initdata = { + [apll] = PLL(pll_6552, FOUT_APLL, "fout_apll", "fin_pll", + APLL_LOCK, APLL_CON, NULL), + [mpll] = PLL(pll_6552, FOUT_MPLL, "fout_mpll", "fin_pll", + MPLL_LOCK, MPLL_CON, NULL), + [epll] = PLL(pll_6553, FOUT_EPLL, "fout_epll", "fin_pll", + EPLL_LOCK, EPLL_CON0, NULL), +}; + +/* Aliases for common s3c64xx clocks. */ +static struct samsung_clock_alias s3c64xx_clock_aliases[] = { + ALIAS(FOUT_APLL, NULL, "fout_apll"), + ALIAS(FOUT_MPLL, NULL, "fout_mpll"), + ALIAS(FOUT_EPLL, NULL, "fout_epll"), + ALIAS(MOUT_EPLL, NULL, "mout_epll"), + ALIAS(DOUT_MPLL, NULL, "dout_mpll"), + ALIAS(HCLKX2, NULL, "hclk2"), + ALIAS(HCLK, NULL, "hclk"), + ALIAS(PCLK, NULL, "pclk"), + ALIAS(PCLK, NULL, "clk_uart_baud2"), + ALIAS(ARMCLK, NULL, "armclk"), + ALIAS(HCLK_UHOST, "s3c2410-ohci", "usb-host"), + ALIAS(HCLK_USB, "s3c-hsotg", "otg"), + ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "hsmmc"), + ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "mmc_busclk.0"), + ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "hsmmc"), + ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"), + ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"), + ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"), + ALIAS(HCLK_DMA1, NULL, "dma1"), + ALIAS(HCLK_DMA0, NULL, "dma0"), + ALIAS(HCLK_CAMIF, "s3c-camif", "camif"), + ALIAS(HCLK_LCD, "s3c-fb", "lcd"), + ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi"), + ALIAS(PCLK_SPI0, "s3c6410-spi.0", "spi"), + ALIAS(PCLK_IIC0, "s3c2440-i2c.0", "i2c"), + ALIAS(PCLK_IIS1, "samsung-i2s.1", "iis"), + ALIAS(PCLK_IIS0, "samsung-i2s.0", "iis"), + ALIAS(PCLK_AC97, "samsung-ac97", "ac97"), + ALIAS(PCLK_TSADC, "s3c64xx-adc", "adc"), + ALIAS(PCLK_KEYPAD, "samsung-keypad", "keypad"), + ALIAS(PCLK_PCM1, "samsung-pcm.1", "pcm"), + ALIAS(PCLK_PCM0, "samsung-pcm.0", "pcm"), + ALIAS(PCLK_PWM, NULL, "timers"), + ALIAS(PCLK_RTC, "s3c64xx-rtc", "rtc"), + ALIAS(PCLK_WDT, NULL, "watchdog"), + ALIAS(PCLK_UART3, "s3c6400-uart.3", "uart"), + ALIAS(PCLK_UART2, "s3c6400-uart.2", "uart"), + ALIAS(PCLK_UART1, "s3c6400-uart.1", "uart"), + ALIAS(PCLK_UART0, "s3c6400-uart.0", "uart"), + ALIAS(SCLK_UHOST, "s3c2410-ohci", "usb-bus-host"), + ALIAS(SCLK_MMC2, "s3c-sdhci.2", "mmc_busclk.2"), + ALIAS(SCLK_MMC1, "s3c-sdhci.1", "mmc_busclk.2"), + ALIAS(SCLK_MMC0, "s3c-sdhci.0", "mmc_busclk.2"), + ALIAS(SCLK_SPI1, "s3c6410-spi.1", "spi-bus"), + ALIAS(SCLK_SPI0, "s3c6410-spi.0", "spi-bus"), + ALIAS(SCLK_AUDIO1, "samsung-pcm.1", "audio-bus"), + ALIAS(SCLK_AUDIO1, "samsung-i2s.1", "audio-bus"), + ALIAS(SCLK_AUDIO0, "samsung-pcm.0", "audio-bus"), + ALIAS(SCLK_AUDIO0, "samsung-i2s.0", "audio-bus"), + ALIAS(SCLK_UART, NULL, "clk_uart_baud3"), + ALIAS(SCLK_CAM, "s3c-camif", "camera"), +}; + +/* Aliases for s3c6400-specific clocks. */ +static struct samsung_clock_alias s3c6400_clock_aliases[] = { + /* Nothing to place here yet. */ +}; + +/* Aliases for s3c6410-specific clocks. */ +static struct samsung_clock_alias s3c6410_clock_aliases[] = { + ALIAS(PCLK_IIC1, "s3c2440-i2c.1", "i2c"), + ALIAS(PCLK_IIS2, "samsung-i2s.2", "iis"), + ALIAS(SCLK_FIMC, "s3c-camif", "fimc"), + ALIAS(SCLK_AUDIO2, "samsung-i2s.2", "audio-bus"), + ALIAS(MEM0_SROM, NULL, "srom"), +}; + +static void __init s3c64xx_clk_register_fixed_ext(unsigned long fin_pll_f, + unsigned long xusbxti_f) +{ + s3c64xx_fixed_rate_ext_clks[0].fixed_rate = fin_pll_f; + s3c64xx_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f; + samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_ext_clks, + ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks)); +} + +/* Register s3c64xx clocks. */ +void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, + unsigned long xusbxti_f, bool is_s3c6400, + void __iomem *reg_base) +{ + unsigned long *soc_regs = NULL; + unsigned long nr_soc_regs = 0; + + if (np) { + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + } + + if (!is_s3c6400) { + soc_regs = s3c6410_clk_regs; + nr_soc_regs = ARRAY_SIZE(s3c6410_clk_regs); + } + + samsung_clk_init(np, reg_base, NR_CLKS, s3c64xx_clk_regs, + ARRAY_SIZE(s3c64xx_clk_regs), soc_regs, nr_soc_regs); + + /* Register external clocks. */ + if (!np) + s3c64xx_clk_register_fixed_ext(xtal_f, xusbxti_f); + + /* Register PLLs. */ + samsung_clk_register_pll(s3c64xx_pll_clks, + ARRAY_SIZE(s3c64xx_pll_clks), reg_base); + + /* Register common internal clocks. */ + samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_clks, + ARRAY_SIZE(s3c64xx_fixed_rate_clks)); + samsung_clk_register_mux(s3c64xx_mux_clks, + ARRAY_SIZE(s3c64xx_mux_clks)); + samsung_clk_register_div(s3c64xx_div_clks, + ARRAY_SIZE(s3c64xx_div_clks)); + samsung_clk_register_gate(s3c64xx_gate_clks, + ARRAY_SIZE(s3c64xx_gate_clks)); + + /* Register SoC-specific clocks. */ + if (is_s3c6400) { + samsung_clk_register_mux(s3c6400_mux_clks, + ARRAY_SIZE(s3c6400_mux_clks)); + samsung_clk_register_div(s3c6400_div_clks, + ARRAY_SIZE(s3c6400_div_clks)); + samsung_clk_register_gate(s3c6400_gate_clks, + ARRAY_SIZE(s3c6400_gate_clks)); + samsung_clk_register_alias(s3c6400_clock_aliases, + ARRAY_SIZE(s3c6400_clock_aliases)); + } else { + samsung_clk_register_mux(s3c6410_mux_clks, + ARRAY_SIZE(s3c6410_mux_clks)); + samsung_clk_register_div(s3c6410_div_clks, + ARRAY_SIZE(s3c6410_div_clks)); + samsung_clk_register_gate(s3c6410_gate_clks, + ARRAY_SIZE(s3c6410_gate_clks)); + samsung_clk_register_alias(s3c6410_clock_aliases, + ARRAY_SIZE(s3c6410_clock_aliases)); + } + + samsung_clk_register_alias(s3c64xx_clock_aliases, + ARRAY_SIZE(s3c64xx_clock_aliases)); + + pr_info("%s clocks: apll = %lu, mpll = %lu\n" + "\tepll = %lu, arm_clk = %lu\n", + is_s3c6400 ? "S3C6400" : "S3C6410", + _get_rate("fout_apll"), _get_rate("fout_mpll"), + _get_rate("fout_epll"), _get_rate("armclk")); +} + +static void __init s3c6400_clk_init(struct device_node *np) +{ + s3c64xx_clk_init(np, 0, 0, true, NULL); +} +CLK_OF_DECLARE(s3c6400_clk, "samsung,s3c6400-clock", s3c6400_clk_init); + +static void __init s3c6410_clk_init(struct device_node *np) +{ + s3c64xx_clk_init(np, 0, 0, false, NULL); +} +CLK_OF_DECLARE(s3c6410_clk, "samsung,s3c6410-clock", s3c6410_clk_init); diff --git a/include/dt-bindings/clock/samsung,s3c64xx-clock.h b/include/dt-bindings/clock/samsung,s3c64xx-clock.h new file mode 100644 index 000000000000..ad95c7f50090 --- /dev/null +++ b/include/dt-bindings/clock/samsung,s3c64xx-clock.h @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2013 Tomasz Figa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Device Tree binding constants for Samsung S3C64xx clock controller. +*/ + +#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H +#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H + +/* + * Let each exported clock get a unique index, which is used on DT-enabled + * platforms to lookup the clock from a clock specifier. These indices are + * therefore considered an ABI and so must not be changed. This implies + * that new clocks should be added either in free spaces between clock groups + * or at the end. + */ + +/* Core clocks. */ +#define CLK27M 1 +#define CLK48M 2 +#define FOUT_APLL 3 +#define FOUT_MPLL 4 +#define FOUT_EPLL 5 +#define ARMCLK 6 +#define HCLKX2 7 +#define HCLK 8 +#define PCLK 9 + +/* HCLK bus clocks. */ +#define HCLK_3DSE 16 +#define HCLK_UHOST 17 +#define HCLK_SECUR 18 +#define HCLK_SDMA1 19 +#define HCLK_SDMA0 20 +#define HCLK_IROM 21 +#define HCLK_DDR1 22 +#define HCLK_MEM1 23 +#define HCLK_MEM0 24 +#define HCLK_USB 25 +#define HCLK_HSMMC2 26 +#define HCLK_HSMMC1 27 +#define HCLK_HSMMC0 28 +#define HCLK_MDP 29 +#define HCLK_DHOST 30 +#define HCLK_IHOST 31 +#define HCLK_DMA1 32 +#define HCLK_DMA0 33 +#define HCLK_JPEG 34 +#define HCLK_CAMIF 35 +#define HCLK_SCALER 36 +#define HCLK_2D 37 +#define HCLK_TV 38 +#define HCLK_POST0 39 +#define HCLK_ROT 40 +#define HCLK_LCD 41 +#define HCLK_TZIC 42 +#define HCLK_INTC 43 +#define HCLK_MFC 44 +#define HCLK_DDR0 45 + +/* PCLK bus clocks. */ +#define PCLK_IIC1 48 +#define PCLK_IIS2 49 +#define PCLK_SKEY 50 +#define PCLK_CHIPID 51 +#define PCLK_SPI1 52 +#define PCLK_SPI0 53 +#define PCLK_HSIRX 54 +#define PCLK_HSITX 55 +#define PCLK_GPIO 56 +#define PCLK_IIC0 57 +#define PCLK_IIS1 58 +#define PCLK_IIS0 59 +#define PCLK_AC97 60 +#define PCLK_TZPC 61 +#define PCLK_TSADC 62 +#define PCLK_KEYPAD 63 +#define PCLK_IRDA 64 +#define PCLK_PCM1 65 +#define PCLK_PCM0 66 +#define PCLK_PWM 67 +#define PCLK_RTC 68 +#define PCLK_WDT 69 +#define PCLK_UART3 70 +#define PCLK_UART2 71 +#define PCLK_UART1 72 +#define PCLK_UART0 73 +#define PCLK_MFC 74 + +/* Special clocks. */ +#define SCLK_UHOST 80 +#define SCLK_MMC2_48 81 +#define SCLK_MMC1_48 82 +#define SCLK_MMC0_48 83 +#define SCLK_MMC2 84 +#define SCLK_MMC1 85 +#define SCLK_MMC0 86 +#define SCLK_SPI1_48 87 +#define SCLK_SPI0_48 88 +#define SCLK_SPI1 89 +#define SCLK_SPI0 90 +#define SCLK_DAC27 91 +#define SCLK_TV27 92 +#define SCLK_SCALER27 93 +#define SCLK_SCALER 94 +#define SCLK_LCD27 95 +#define SCLK_LCD 96 +#define SCLK_FIMC 97 +#define SCLK_POST0_27 98 +#define SCLK_AUDIO2 99 +#define SCLK_POST0 100 +#define SCLK_AUDIO1 101 +#define SCLK_AUDIO0 102 +#define SCLK_SECUR 103 +#define SCLK_IRDA 104 +#define SCLK_UART 105 +#define SCLK_MFC 106 +#define SCLK_CAM 107 +#define SCLK_JPEG 108 +#define SCLK_ONENAND 109 + +/* MEM0 bus clocks - S3C6410-specific. */ +#define MEM0_CFCON 112 +#define MEM0_ONENAND1 113 +#define MEM0_ONENAND0 114 +#define MEM0_NFCON 115 +#define MEM0_SROM 116 + +/* Muxes. */ +#define MOUT_APLL 128 +#define MOUT_MPLL 129 +#define MOUT_EPLL 130 +#define MOUT_MFC 131 +#define MOUT_AUDIO0 132 +#define MOUT_AUDIO1 133 +#define MOUT_UART 134 +#define MOUT_SPI0 135 +#define MOUT_SPI1 136 +#define MOUT_MMC0 137 +#define MOUT_MMC1 138 +#define MOUT_MMC2 139 +#define MOUT_UHOST 140 +#define MOUT_IRDA 141 +#define MOUT_LCD 142 +#define MOUT_SCALER 143 +#define MOUT_DAC27 144 +#define MOUT_TV27 145 +#define MOUT_AUDIO2 146 + +/* Dividers. */ +#define DOUT_MPLL 160 +#define DOUT_SECUR 161 +#define DOUT_CAM 162 +#define DOUT_JPEG 163 +#define DOUT_MFC 164 +#define DOUT_MMC0 165 +#define DOUT_MMC1 166 +#define DOUT_MMC2 167 +#define DOUT_LCD 168 +#define DOUT_SCALER 169 +#define DOUT_UHOST 170 +#define DOUT_SPI0 171 +#define DOUT_SPI1 172 +#define DOUT_AUDIO0 173 +#define DOUT_AUDIO1 174 +#define DOUT_UART 175 +#define DOUT_IRDA 176 +#define DOUT_FIMC 177 +#define DOUT_AUDIO2 178 + +/* Total number of clocks. */ +#define NR_CLKS (DOUT_AUDIO2 + 1) + +#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H */ From 6f9a4894c435bc9919dab31d90f69167d4638997 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 12 Jul 2013 08:53:43 +0530 Subject: [PATCH 029/102] Documentation: clk: Fix a trivial typo in audss Fixes a trivial typo. Signed-off-by: Sachin Kamat Signed-off-by: Mike Turquette --- Documentation/devicetree/bindings/clock/clk-exynos-audss.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt b/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt index a1201802f90d..75e2e1999f87 100644 --- a/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt +++ b/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt @@ -2,7 +2,7 @@ The Samsung Audio Subsystem clock controller generates and supplies clocks to Audio Subsystem block available in the S5PV210 and Exynos SoCs. The clock -binding described here is applicable to all SoC's in Exynos family. +binding described here is applicable to all SoCs in Exynos family. Required Properties: From ee85e9bd25773a30002769c8121b6ae62f23f2b4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 12 Jul 2013 16:15:15 +0800 Subject: [PATCH 030/102] clk: sunxi: Fix checking return value of clk_register_[composite|factors] clk_register_composite() and clk_register_factors() return ERR_PTR on error. Signed-off-by: Axel Lin Acked-by: Maxime Ripard Signed-off-by: Mike Turquette --- drivers/clk/sunxi/clk-sunxi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 412912bbba53..02e440beb3d3 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -64,7 +64,7 @@ static void __init sunxi_osc_clk_setup(struct device_node *node) &gate->hw, &clk_gate_ops, CLK_IS_ROOT); - if (clk) { + if (!IS_ERR(clk)) { of_clk_add_provider(node, of_clk_src_simple_get, clk); clk_register_clkdev(clk, clk_name, NULL); } @@ -221,7 +221,7 @@ static void __init sunxi_factors_clk_setup(struct device_node *node, clk = clk_register_factors(NULL, clk_name, parent, 0, reg, data->table, data->getter, &clk_lock); - if (clk) { + if (!IS_ERR(clk)) { of_clk_add_provider(node, of_clk_src_simple_get, clk); clk_register_clkdev(clk, clk_name, NULL); } From 7274e23e56bbcb57c9d56a5236bd88a6df114f01 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 16 Jul 2013 10:33:43 -0300 Subject: [PATCH 031/102] clk: mxs: clk-imx23: Include Fix the following sparse warning: drivers/clk/mxs/clk-imx23.c:102:12: warning: symbol 'mx23_clocks_init' was not declared. Should it be static? Signed-off-by: Fabio Estevam Acked-by: Shawn Guo Signed-off-by: Mike Turquette --- drivers/clk/mxs/clk-imx23.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c index f6a74872f14e..c396fe361589 100644 --- a/drivers/clk/mxs/clk-imx23.c +++ b/drivers/clk/mxs/clk-imx23.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include From 680681aee84864e1e110ea6480b86ac18206acbd Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 6 Aug 2013 17:01:13 +0530 Subject: [PATCH 032/102] clk: exynos4: Make exynos4_plls static 'exynos4_plls' is used only in this file. Make it static. Signed-off-by: Sachin Kamat Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 68f9a4a67266..fec319d33c24 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -984,7 +984,7 @@ static __initdata struct of_device_id ext_clk_match[] = { {}, }; -struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = { +static struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = { [apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, "fout_apll", NULL), [mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", From ae2329f790ee064b562ab37a2897a047f4d8eaeb Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 6 Aug 2013 17:01:14 +0530 Subject: [PATCH 033/102] clk: exynos5250: Make exynos5250_plls static exynos5250_plls is used only in this file. Make it static. Signed-off-by: Sachin Kamat Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos5250.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index df3628cf2597..5865cefa69f4 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -517,7 +517,7 @@ static __initdata struct samsung_pll_rate_table epll_24mhz_tbl[] = { { }, }; -struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = { +static struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = { [apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, "fout_apll", NULL), [mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK, From a9381b3f9b68027902f5da356064ba186c7a4f59 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 6 Aug 2013 17:01:15 +0530 Subject: [PATCH 034/102] clk: exynos5420: Make exynos5420_plls static 'exynos5420_plls' is used only in this file. Make is static. Signed-off-by: Sachin Kamat Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos5420.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index ca352695a954..872e13d5a444 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -727,7 +727,7 @@ static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { GATE(smmu_mscl2, "smmu_mscl2", "aclk400_mscl", GATE_IP_MSCL, 10, 0, 0), }; -struct __initdata samsung_pll_clock exynos5420_plls[nr_plls] = { +static struct __initdata samsung_pll_clock exynos5420_plls[nr_plls] = { [apll] = PLL(pll_2550, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, NULL), [cpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK, From 7cc560dea4152139e16bea6e56ffa9e1bc461082 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Sun, 7 Jul 2013 17:14:20 +0530 Subject: [PATCH 035/102] clk: s2mps11: Add support for s2mps11 This patch adds support to register three(AP/CP/BT) buffered 32.768 KHz outputs of mfd-s2mps11 with common clock framework. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mike Turquette --- drivers/clk/Kconfig | 6 + drivers/clk/Makefile | 1 + drivers/clk/clk-s2mps11.c | 273 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 280 insertions(+) create mode 100644 drivers/clk/clk-s2mps11.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index cd49096c38fa..279407a36391 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -64,6 +64,12 @@ config COMMON_CLK_SI5351 This driver supports Silicon Labs 5351A/B/C programmable clock generators. +config COMMON_CLK_S2MPS11 + tristate "Clock driver for S2MPS11 MFD" + depends on MFD_SEC_CORE + ---help--- + This driver supports S2MPS11 crystal oscillator clock. + config CLK_TWL6040 tristate "External McPDM functional clock from twl6040" depends on TWL6040_CORE diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 4038c2bdf334..7b111062ccba 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -40,5 +40,6 @@ obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o +obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c new file mode 100644 index 000000000000..7be41e676a64 --- /dev/null +++ b/drivers/clk/clk-s2mps11.c @@ -0,0 +1,273 @@ +/* + * clk-s2mps11.c - Clock driver for S2MPS11. + * + * Copyright (C) 2013 Samsung Electornics + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define s2mps11_name(a) (a->hw.init->name) + +static struct clk **clk_table; +static struct clk_onecell_data clk_data; + +enum { + S2MPS11_CLK_AP = 0, + S2MPS11_CLK_CP, + S2MPS11_CLK_BT, + S2MPS11_CLKS_NUM, +}; + +struct s2mps11_clk { + struct sec_pmic_dev *iodev; + struct clk_hw hw; + struct clk *clk; + struct clk_lookup *lookup; + u32 mask; + bool enabled; +}; + +static struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw) +{ + return container_of(hw, struct s2mps11_clk, hw); +} + +static int s2mps11_clk_prepare(struct clk_hw *hw) +{ + struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw); + int ret; + + ret = regmap_update_bits(s2mps11->iodev->regmap, + S2MPS11_REG_RTC_CTRL, + s2mps11->mask, s2mps11->mask); + if (!ret) + s2mps11->enabled = true; + + return ret; +} + +static void s2mps11_clk_unprepare(struct clk_hw *hw) +{ + struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw); + int ret; + + ret = regmap_update_bits(s2mps11->iodev->regmap, S2MPS11_REG_RTC_CTRL, + s2mps11->mask, ~s2mps11->mask); + + if (!ret) + s2mps11->enabled = false; +} + +static int s2mps11_clk_is_enabled(struct clk_hw *hw) +{ + struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw); + + return s2mps11->enabled; +} + +static unsigned long s2mps11_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw); + if (s2mps11->enabled) + return 32768; + else + return 0; +} + +static struct clk_ops s2mps11_clk_ops = { + .prepare = s2mps11_clk_prepare, + .unprepare = s2mps11_clk_unprepare, + .is_enabled = s2mps11_clk_is_enabled, + .recalc_rate = s2mps11_clk_recalc_rate, +}; + +static struct clk_init_data s2mps11_clks_init[S2MPS11_CLKS_NUM] = { + [S2MPS11_CLK_AP] = { + .name = "s2mps11_ap", + .ops = &s2mps11_clk_ops, + .flags = CLK_IS_ROOT, + }, + [S2MPS11_CLK_CP] = { + .name = "s2mps11_cp", + .ops = &s2mps11_clk_ops, + .flags = CLK_IS_ROOT, + }, + [S2MPS11_CLK_BT] = { + .name = "s2mps11_bt", + .ops = &s2mps11_clk_ops, + .flags = CLK_IS_ROOT, + }, +}; + +static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev) +{ + struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); + struct device_node *clk_np; + int i; + + if (!iodev->dev->of_node) + return NULL; + + clk_np = of_find_node_by_name(iodev->dev->of_node, "clocks"); + if (!clk_np) { + dev_err(&pdev->dev, "could not find clock sub-node\n"); + return ERR_PTR(-EINVAL); + } + + clk_table = devm_kzalloc(&pdev->dev, sizeof(struct clk *) * + S2MPS11_CLKS_NUM, GFP_KERNEL); + if (!clk_table) + return ERR_PTR(-ENOMEM); + + for (i = 0; i < S2MPS11_CLKS_NUM; i++) + of_property_read_string_index(clk_np, "clock-output-names", i, + &s2mps11_clks_init[i].name); + + return clk_np; +} + +static int s2mps11_clk_probe(struct platform_device *pdev) +{ + struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); + struct s2mps11_clk *s2mps11_clks, *s2mps11_clk; + struct device_node *clk_np = NULL; + int i, ret = 0; + u32 val; + + s2mps11_clks = devm_kzalloc(&pdev->dev, sizeof(*s2mps11_clk) * + S2MPS11_CLKS_NUM, GFP_KERNEL); + if (!s2mps11_clks) + return -ENOMEM; + + s2mps11_clk = s2mps11_clks; + + clk_np = s2mps11_clk_parse_dt(pdev); + if (IS_ERR(clk_np)) + return PTR_ERR(clk_np); + + for (i = 0; i < S2MPS11_CLKS_NUM; i++, s2mps11_clk++) { + s2mps11_clk->iodev = iodev; + s2mps11_clk->hw.init = &s2mps11_clks_init[i]; + s2mps11_clk->mask = 1 << i; + + ret = regmap_read(s2mps11_clk->iodev->regmap, + S2MPS11_REG_RTC_CTRL, &val); + if (ret < 0) + goto err_reg; + + s2mps11_clk->enabled = val & s2mps11_clk->mask; + + s2mps11_clk->clk = devm_clk_register(&pdev->dev, + &s2mps11_clk->hw); + if (IS_ERR(s2mps11_clk->clk)) { + dev_err(&pdev->dev, "Fail to register : %s\n", + s2mps11_name(s2mps11_clk)); + ret = PTR_ERR(s2mps11_clk->clk); + goto err_reg; + } + + s2mps11_clk->lookup = devm_kzalloc(&pdev->dev, + sizeof(struct clk_lookup), GFP_KERNEL); + if (!s2mps11_clk->lookup) { + ret = -ENOMEM; + goto err_lup; + } + + s2mps11_clk->lookup->con_id = s2mps11_name(s2mps11_clk); + s2mps11_clk->lookup->clk = s2mps11_clk->clk; + + clkdev_add(s2mps11_clk->lookup); + } + + if (clk_table) { + for (i = 0; i < S2MPS11_CLKS_NUM; i++) + clk_table[i] = s2mps11_clks[i].clk; + + clk_data.clks = clk_table; + clk_data.clk_num = S2MPS11_CLKS_NUM; + of_clk_add_provider(clk_np, of_clk_src_onecell_get, &clk_data); + } + + platform_set_drvdata(pdev, s2mps11_clks); + + return ret; +err_lup: + devm_clk_unregister(&pdev->dev, s2mps11_clk->clk); +err_reg: + while (s2mps11_clk > s2mps11_clks) { + if (s2mps11_clk->lookup) { + clkdev_drop(s2mps11_clk->lookup); + devm_clk_unregister(&pdev->dev, s2mps11_clk->clk); + } + s2mps11_clk--; + } + + return ret; +} + +static int s2mps11_clk_remove(struct platform_device *pdev) +{ + struct s2mps11_clk *s2mps11_clks = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < S2MPS11_CLKS_NUM; i++) + clkdev_drop(s2mps11_clks[i].lookup); + + return 0; +} + +static const struct platform_device_id s2mps11_clk_id[] = { + { "s2mps11-clk", 0}, + { }, +}; +MODULE_DEVICE_TABLE(platform, s2mps11_clk_id); + +static struct platform_driver s2mps11_clk_driver = { + .driver = { + .name = "s2mps11-clk", + .owner = THIS_MODULE, + }, + .probe = s2mps11_clk_probe, + .remove = s2mps11_clk_remove, + .id_table = s2mps11_clk_id, +}; + +static int __init s2mps11_clk_init(void) +{ + return platform_driver_register(&s2mps11_clk_driver); +} +subsys_initcall(s2mps11_clk_init); + +static void __init s2mps11_clk_cleanup(void) +{ + platform_driver_unregister(&s2mps11_clk_driver); +} +module_exit(s2mps11_clk_cleanup); + +MODULE_DESCRIPTION("S2MPS11 Clock Driver"); +MODULE_AUTHOR("Yadwinder Singh Brar "); +MODULE_LICENSE("GPL"); From 3c701c51ef918ce7bbe6ba983ea2e0e0cead5810 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 7 Aug 2013 10:18:37 +0530 Subject: [PATCH 036/102] clk: exynos4: Fix incorrect placement of __initdata __initdata should be placed between the variable name and equal sign for the variable to be placed in the intended section. Signed-off-by: Sachin Kamat Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos4.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index fec319d33c24..742b4c58ced9 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -194,7 +194,7 @@ enum exynos4_clks { * list of controller registers to be saved and restored during a * suspend/resume cycle. */ -static __initdata unsigned long exynos4210_clk_save[] = { +static unsigned long exynos4210_clk_save[] __initdata = { E4210_SRC_IMAGE, E4210_SRC_LCD1, E4210_SRC_MASK_LCD1, @@ -205,7 +205,7 @@ static __initdata unsigned long exynos4210_clk_save[] = { E4210_MPLL_CON0, }; -static __initdata unsigned long exynos4x12_clk_save[] = { +static unsigned long exynos4x12_clk_save[] __initdata = { E4X12_GATE_IP_IMAGE, E4X12_GATE_IP_PERIR, E4X12_SRC_CAM1, @@ -214,7 +214,7 @@ static __initdata unsigned long exynos4x12_clk_save[] = { E4X12_MPLL_CON0, }; -static __initdata unsigned long exynos4_clk_regs[] = { +static unsigned long exynos4_clk_regs[] __initdata = { SRC_LEFTBUS, DIV_LEFTBUS, GATE_IP_LEFTBUS, @@ -978,13 +978,13 @@ static void __init exynos4_clk_register_finpll(unsigned long xom) } -static __initdata struct of_device_id ext_clk_match[] = { +static struct of_device_id ext_clk_match[] __initdata = { { .compatible = "samsung,clock-xxti", .data = (void *)0, }, { .compatible = "samsung,clock-xusbxti", .data = (void *)1, }, {}, }; -static struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = { +static struct samsung_pll_clock exynos4_plls[nr_plls] __initdata = { [apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, "fout_apll", NULL), [mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", From b6993ecb87ac65cf7e718f4f45579e4f78fc1c27 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 7 Aug 2013 10:18:38 +0530 Subject: [PATCH 037/102] clk: exynos5250: Fix incorrect placement of __initdata __initdata should be placed between the variable name and equal sign for the variable to be placed in the intended section. Signed-off-by: Sachin Kamat Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos5250.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 5865cefa69f4..a9916a46e7a7 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -132,7 +132,7 @@ enum exynos5250_clks { * list of controller registers to be saved and restored during a * suspend/resume cycle. */ -static __initdata unsigned long exynos5250_clk_regs[] = { +static unsigned long exynos5250_clk_regs[] __initdata = { SRC_CPU, DIV_CPU0, SRC_CORE1, @@ -494,7 +494,7 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { GATE(g2d, "g2d", "aclk200", GATE_IP_ACP, 3, 0, 0), }; -static __initdata struct samsung_pll_rate_table vpll_24mhz_tbl[] = { +static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = { /* sorted in descending order */ /* PLL_36XX_RATE(rate, m, p, s, k) */ PLL_36XX_RATE(266000000, 266, 3, 3, 0), @@ -503,7 +503,7 @@ static __initdata struct samsung_pll_rate_table vpll_24mhz_tbl[] = { { }, }; -static __initdata struct samsung_pll_rate_table epll_24mhz_tbl[] = { +static struct samsung_pll_rate_table epll_24mhz_tbl[] __initdata = { /* sorted in descending order */ /* PLL_36XX_RATE(rate, m, p, s, k) */ PLL_36XX_RATE(192000000, 64, 2, 2, 0), @@ -517,7 +517,7 @@ static __initdata struct samsung_pll_rate_table epll_24mhz_tbl[] = { { }, }; -static struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = { +static struct samsung_pll_clock exynos5250_plls[nr_plls] __initdata = { [apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, "fout_apll", NULL), [mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK, @@ -534,7 +534,7 @@ static struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = { VPLL_LOCK, VPLL_CON0, NULL), }; -static __initdata struct of_device_id ext_clk_match[] = { +static struct of_device_id ext_clk_match[] __initdata = { { .compatible = "samsung,clock-xxti", .data = (void *)0, }, { }, }; From 202e5ae945ad0662c4abaea38c58ab58a694cc44 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 7 Aug 2013 10:18:39 +0530 Subject: [PATCH 038/102] clk: exynos5420: Fix incorrect placement of __initdata __initdata should be placed between the variable name and equal sign for the variable to be placed in the intended section. Signed-off-by: Sachin Kamat Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos5420.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 872e13d5a444..e035fd0afbc7 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -147,7 +147,7 @@ enum exynos5420_clks { * list of controller registers to be saved and restored during a * suspend/resume cycle. */ -static __initdata unsigned long exynos5420_clk_regs[] = { +static unsigned long exynos5420_clk_regs[] __initdata = { SRC_CPU, DIV_CPU0, DIV_CPU1, @@ -727,7 +727,7 @@ static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { GATE(smmu_mscl2, "smmu_mscl2", "aclk400_mscl", GATE_IP_MSCL, 10, 0, 0), }; -static struct __initdata samsung_pll_clock exynos5420_plls[nr_plls] = { +static struct samsung_pll_clock exynos5420_plls[nr_plls] __initdata = { [apll] = PLL(pll_2550, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, NULL), [cpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK, @@ -752,7 +752,7 @@ static struct __initdata samsung_pll_clock exynos5420_plls[nr_plls] = { KPLL_CON0, NULL), }; -static __initdata struct of_device_id ext_clk_match[] = { +static struct of_device_id ext_clk_match[] __initdata = { { .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, }, { }, }; From 4d1b5e73b92536cd194a36dd4273adc977875ed1 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 7 Aug 2013 10:18:40 +0530 Subject: [PATCH 039/102] clk: exynos5440: Fix incorrect placement of __initdata __initdata should be placed between the variable name and equal sign for the variable to be placed in the intended section. Signed-off-by: Sachin Kamat Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos5440.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c index 6d043a285d86..4ef38e045e39 100644 --- a/drivers/clk/samsung/clk-exynos5440.c +++ b/drivers/clk/samsung/clk-exynos5440.c @@ -97,7 +97,7 @@ static struct samsung_gate_clock exynos5440_gate_clks[] __initdata = { GATE(cs250_o, "cs250_o", "cs250", CLKEN_OV_VAL, 19, 0, 0), }; -static __initdata struct of_device_id ext_clk_match[] = { +static struct of_device_id ext_clk_match[] __initdata = { { .compatible = "samsung,clock-xtal", .data = (void *)0, }, {}, }; From 056dfcf67ebaa9eb3aff5f35ce98c073157f1d5b Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 8 Aug 2013 09:55:47 +0530 Subject: [PATCH 040/102] clk: tegra114: Fix incorrect placement of __initdata __initdata should be placed between the variable name and equal sign for the variable to be placed in the intended section. Signed-off-by: Sachin Kamat Tested-by: Stephen Warren Acked-by: Stephen Warren Signed-off-by: Mike Turquette --- drivers/clk/tegra/clk-tegra114.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index b6015cb4fc01..2d3b3dc5c1ec 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -2156,7 +2156,7 @@ static const struct of_device_id pmc_match[] __initconst = { * dfll_soc/dfll_ref apparently must be kept enabled, otherwise I2C5 * breaks */ -static __initdata struct tegra_clk_init_table init_table[] = { +static struct tegra_clk_init_table init_table[] __initdata = { {uarta, pll_p, 408000000, 0}, {uartb, pll_p, 408000000, 0}, {uartc, pll_p, 408000000, 0}, From a0be7a9e6a63d8b2bd8657f34775d3d369a45624 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 8 Aug 2013 09:55:48 +0530 Subject: [PATCH 041/102] clk: tegra20: Fix incorrect placement of __initdata __initdata should be placed between the variable name and equal sign for the variable to be placed in the intended section. Signed-off-by: Sachin Kamat Acked-by: Stephen Warren Signed-off-by: Mike Turquette --- drivers/clk/tegra/clk-tegra20.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 759ca47be753..ebe94ce0f647 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -1223,7 +1223,7 @@ static struct tegra_cpu_car_ops tegra20_cpu_car_ops = { #endif }; -static __initdata struct tegra_clk_init_table init_table[] = { +static struct tegra_clk_init_table init_table[] __initdata = { {pll_p, clk_max, 216000000, 1}, {pll_p_out1, clk_max, 28800000, 1}, {pll_p_out2, clk_max, 48000000, 1}, From 4c3b2404b4ef4c70f6b8a424fa1e62c86709569f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 8 Aug 2013 09:55:49 +0530 Subject: [PATCH 042/102] clk: tegra30: Fix incorrect placement of __initdata __initdata should be placed between the variable name and equal sign for the variable to be placed in the intended section. Signed-off-by: Sachin Kamat Acked-by: Stephen Warren Signed-off-by: Mike Turquette --- drivers/clk/tegra/clk-tegra30.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index e2c6ca0431d6..ab35040231cd 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -1901,7 +1901,7 @@ static struct tegra_cpu_car_ops tegra30_cpu_car_ops = { #endif }; -static __initdata struct tegra_clk_init_table init_table[] = { +static struct tegra_clk_init_table init_table[] __initdata = { {uarta, pll_p, 408000000, 0}, {uartb, pll_p, 408000000, 0}, {uartc, pll_p, 408000000, 0}, From 18f5863e3be3a5de521f5a35e994a9917450d3c2 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 8 Aug 2013 10:01:26 +0530 Subject: [PATCH 043/102] clk: prima2: Fix incorrect placement of __initdata __initdata should be placed between the variable name and equal sign for the variable to be placed in the intended section. Signed-off-by: Sachin Kamat Signed-off-by: Mike Turquette --- drivers/clk/clk-prima2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-prima2.c b/drivers/clk/clk-prima2.c index 643ca653fef0..5ab95f1ad579 100644 --- a/drivers/clk/clk-prima2.c +++ b/drivers/clk/clk-prima2.c @@ -1034,7 +1034,7 @@ enum prima2_clk_index { usb0, usb1, maxclk, }; -static __initdata struct clk_hw* prima2_clk_hw_array[maxclk] = { +static struct clk_hw *prima2_clk_hw_array[maxclk] __initdata = { NULL, /* dummy */ NULL, &clk_pll1.hw, From 389ae05f8bf5f1e63212baf4a8aa9621148b188a Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 24 Jul 2013 17:43:29 -0700 Subject: [PATCH 044/102] clk: fixed-rate: Export clk_fixed_rate_register() Export this symbol so that modules can register fixed rate clocks. Signed-off-by: Stephen Boyd Signed-off-by: Mike Turquette --- drivers/clk/clk-fixed-rate.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c index dc58fbd8516f..1ed591ab8b1d 100644 --- a/drivers/clk/clk-fixed-rate.c +++ b/drivers/clk/clk-fixed-rate.c @@ -80,6 +80,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name, return clk; } +EXPORT_SYMBOL_GPL(clk_register_fixed_rate); #ifdef CONFIG_OF /** From 4c5eeea9a35a0c46c98539d3c5d77eaea33238ef Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 2 Aug 2013 13:14:07 -0300 Subject: [PATCH 045/102] clk: clk-divider: Export clk_register_divider() clk_register_divider() needs to be exported so that it could be used in a module driver, otherwise we get the following error: ERROR: "clk_register_divider" [sound/soc/mxs/snd-soc-mxs.ko] undefined! Signed-off-by: Fabio Estevam Signed-off-by: Mike Turquette [mturquette@linaro.org: also export clk_register_divider_table] --- drivers/clk/clk-divider.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 6d55eb2cb959..749372f87ec4 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -317,6 +317,7 @@ struct clk *clk_register_divider(struct device *dev, const char *name, return _register_divider(dev, name, parent_name, flags, reg, shift, width, clk_divider_flags, NULL, lock); } +EXPORT_SYMBOL_GPL(clk_register_divider); /** * clk_register_divider_table - register a table based divider clock with @@ -341,3 +342,4 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name, return _register_divider(dev, name, parent_name, flags, reg, shift, width, clk_divider_flags, table, lock); } +EXPORT_SYMBOL_GPL(clk_register_divider_table); From 5cfe10bb00e1b8c0aaa3f0c796c643bb1af6db82 Mon Sep 17 00:00:00 2001 From: Mike Turquette Date: Thu, 15 Aug 2013 19:06:29 -0700 Subject: [PATCH 046/102] clk: export fixed-factor, gate & mux registration These registration calls may be used by loadable modules. Export them. Signed-off-by: Mike Turquette --- drivers/clk/clk-fixed-factor.c | 2 ++ drivers/clk/clk-gate.c | 1 + drivers/clk/clk-mux.c | 2 ++ 3 files changed, 5 insertions(+) diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index 9ff7d510faa3..0e1d89b4321b 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -97,6 +97,8 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name, return clk; } +EXPORT_SYMBOL_GPL(clk_register_fixed_factor); + #ifdef CONFIG_OF /** * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index 790306e921c8..2b28a004c19e 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -161,3 +161,4 @@ struct clk *clk_register_gate(struct device *dev, const char *name, return clk; } +EXPORT_SYMBOL_GPL(clk_register_gate); diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 92f1a1be5319..b918dc370bd0 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -162,6 +162,7 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name, return clk; } +EXPORT_SYMBOL_GPL(clk_register_mux_table); struct clk *clk_register_mux(struct device *dev, const char *name, const char **parent_names, u8 num_parents, unsigned long flags, @@ -174,3 +175,4 @@ struct clk *clk_register_mux(struct device *dev, const char *name, flags, reg, shift, mask, clk_mux_flags, NULL, lock); } +EXPORT_SYMBOL_GPL(clk_register_mux); From 7ef3dcc8145263cb5a8c7059f82d44c948eb46a8 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 29 Jul 2013 12:24:58 +0100 Subject: [PATCH 047/102] clk: abstract parent cache Abstract access to the clock parent cache by defining clk_get_parent_by_index(clk, index). This allows access to parent clocks from clock drivers. Signed-off-by: James Hogan Reviewed-by: Stephen Boyd Cc: Mike Turquette Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Mike Turquette --- drivers/clk/clk.c | 21 ++++++++++++++------- include/linux/clk-provider.h | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 56a00db61332..42c15a8ba34d 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -559,6 +559,19 @@ struct clk *__clk_get_parent(struct clk *clk) return !clk ? NULL : clk->parent; } +struct clk *clk_get_parent_by_index(struct clk *clk, u8 index) +{ + if (!clk || index >= clk->num_parents) + return NULL; + else if (!clk->parents) + return __clk_lookup(clk->parent_names[index]); + else if (!clk->parents[index]) + return clk->parents[index] = + __clk_lookup(clk->parent_names[index]); + else + return clk->parents[index]; +} + unsigned int __clk_get_enable_count(struct clk *clk) { return !clk ? 0 : clk->enable_count; @@ -1316,13 +1329,7 @@ static struct clk *__clk_init_parent(struct clk *clk) kzalloc((sizeof(struct clk*) * clk->num_parents), GFP_KERNEL); - if (!clk->parents) - ret = __clk_lookup(clk->parent_names[index]); - else if (!clk->parents[index]) - ret = clk->parents[index] = - __clk_lookup(clk->parent_names[index]); - else - ret = clk->parents[index]; + ret = clk_get_parent_by_index(clk, index); out: return ret; diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 9487b96939e8..a83409285a7f 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -420,6 +420,7 @@ const char *__clk_get_name(struct clk *clk); struct clk_hw *__clk_get_hw(struct clk *clk); u8 __clk_get_num_parents(struct clk *clk); struct clk *__clk_get_parent(struct clk *clk); +struct clk *clk_get_parent_by_index(struct clk *clk, u8 index); unsigned int __clk_get_enable_count(struct clk *clk); unsigned int __clk_get_prepare_count(struct clk *clk); unsigned long __clk_get_rate(struct clk *clk); From 4935b22c46ea5e2dc44ef0b72db50741649eb3a4 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 29 Jul 2013 12:24:59 +0100 Subject: [PATCH 048/102] clk: move some parent related functions upwards Move some parent related functions up in clk.c so they can be used by the modifications in the following patch which enables clock reparenting during set_rate. No other changes are made so this patch makes no functional difference in isolation. This is separate from the following patch primarily to ease readability of that patch. Signed-off-by: James Hogan Reviewed-by: Stephen Boyd Cc: Mike Turquette Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Mike Turquette --- drivers/clk/clk.c | 208 +++++++++++++++++++++++----------------------- 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 42c15a8ba34d..3d57cf64c9e7 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1028,6 +1028,110 @@ unsigned long clk_get_rate(struct clk *clk) } EXPORT_SYMBOL_GPL(clk_get_rate); +static u8 clk_fetch_parent_index(struct clk *clk, struct clk *parent) +{ + u8 i; + + if (!clk->parents) + clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents), + GFP_KERNEL); + + /* + * find index of new parent clock using cached parent ptrs, + * or if not yet cached, use string name comparison and cache + * them now to avoid future calls to __clk_lookup. + */ + for (i = 0; i < clk->num_parents; i++) { + if (clk->parents && clk->parents[i] == parent) + break; + else if (!strcmp(clk->parent_names[i], parent->name)) { + if (clk->parents) + clk->parents[i] = __clk_lookup(parent->name); + break; + } + } + + return i; +} + +static void clk_reparent(struct clk *clk, struct clk *new_parent) +{ + hlist_del(&clk->child_node); + + if (new_parent) + hlist_add_head(&clk->child_node, &new_parent->children); + else + hlist_add_head(&clk->child_node, &clk_orphan_list); + + clk->parent = new_parent; +} + +static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index) +{ + unsigned long flags; + int ret = 0; + struct clk *old_parent = clk->parent; + + /* + * Migrate prepare state between parents and prevent race with + * clk_enable(). + * + * If the clock is not prepared, then a race with + * clk_enable/disable() is impossible since we already have the + * prepare lock (future calls to clk_enable() need to be preceded by + * a clk_prepare()). + * + * If the clock is prepared, migrate the prepared state to the new + * parent and also protect against a race with clk_enable() by + * forcing the clock and the new parent on. This ensures that all + * future calls to clk_enable() are practically NOPs with respect to + * hardware and software states. + * + * See also: Comment for clk_set_parent() below. + */ + if (clk->prepare_count) { + __clk_prepare(parent); + clk_enable(parent); + clk_enable(clk); + } + + /* update the clk tree topology */ + flags = clk_enable_lock(); + clk_reparent(clk, parent); + clk_enable_unlock(flags); + + /* change clock input source */ + if (parent && clk->ops->set_parent) + ret = clk->ops->set_parent(clk->hw, p_index); + + if (ret) { + flags = clk_enable_lock(); + clk_reparent(clk, old_parent); + clk_enable_unlock(flags); + + if (clk->prepare_count) { + clk_disable(clk); + clk_disable(parent); + __clk_unprepare(parent); + } + return ret; + } + + /* + * Finish the migration of prepare state and undo the changes done + * for preventing a race with clk_enable(). + */ + if (clk->prepare_count) { + clk_disable(clk); + clk_disable(old_parent); + __clk_unprepare(old_parent); + } + + /* update debugfs with new clk tree topology */ + clk_debug_reparent(clk, parent); + return 0; +} + /** * __clk_speculate_rates * @clk: first clk in the subtree @@ -1335,18 +1439,6 @@ out: return ret; } -static void clk_reparent(struct clk *clk, struct clk *new_parent) -{ - hlist_del(&clk->child_node); - - if (new_parent) - hlist_add_head(&clk->child_node, &new_parent->children); - else - hlist_add_head(&clk->child_node, &clk_orphan_list); - - clk->parent = new_parent; -} - void __clk_reparent(struct clk *clk, struct clk *new_parent) { clk_reparent(clk, new_parent); @@ -1354,98 +1446,6 @@ void __clk_reparent(struct clk *clk, struct clk *new_parent) __clk_recalc_rates(clk, POST_RATE_CHANGE); } -static u8 clk_fetch_parent_index(struct clk *clk, struct clk *parent) -{ - u8 i; - - if (!clk->parents) - clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents), - GFP_KERNEL); - - /* - * find index of new parent clock using cached parent ptrs, - * or if not yet cached, use string name comparison and cache - * them now to avoid future calls to __clk_lookup. - */ - for (i = 0; i < clk->num_parents; i++) { - if (clk->parents && clk->parents[i] == parent) - break; - else if (!strcmp(clk->parent_names[i], parent->name)) { - if (clk->parents) - clk->parents[i] = __clk_lookup(parent->name); - break; - } - } - - return i; -} - -static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index) -{ - unsigned long flags; - int ret = 0; - struct clk *old_parent = clk->parent; - - /* - * Migrate prepare state between parents and prevent race with - * clk_enable(). - * - * If the clock is not prepared, then a race with - * clk_enable/disable() is impossible since we already have the - * prepare lock (future calls to clk_enable() need to be preceded by - * a clk_prepare()). - * - * If the clock is prepared, migrate the prepared state to the new - * parent and also protect against a race with clk_enable() by - * forcing the clock and the new parent on. This ensures that all - * future calls to clk_enable() are practically NOPs with respect to - * hardware and software states. - * - * See also: Comment for clk_set_parent() below. - */ - if (clk->prepare_count) { - __clk_prepare(parent); - clk_enable(parent); - clk_enable(clk); - } - - /* update the clk tree topology */ - flags = clk_enable_lock(); - clk_reparent(clk, parent); - clk_enable_unlock(flags); - - /* change clock input source */ - if (parent && clk->ops->set_parent) - ret = clk->ops->set_parent(clk->hw, p_index); - - if (ret) { - flags = clk_enable_lock(); - clk_reparent(clk, old_parent); - clk_enable_unlock(flags); - - if (clk->prepare_count) { - clk_disable(clk); - clk_disable(parent); - __clk_unprepare(parent); - } - return ret; - } - - /* - * Finish the migration of prepare state and undo the changes done - * for preventing a race with clk_enable(). - */ - if (clk->prepare_count) { - clk_disable(clk); - clk_disable(old_parent); - __clk_unprepare(old_parent); - } - - /* update debugfs with new clk tree topology */ - clk_debug_reparent(clk, parent); - return 0; -} - /** * clk_set_parent - switch the parent of a mux clk * @clk: the mux clk whose input we are switching From 71472c0c06cf9a3d1540762ea205654c584e3bc4 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 29 Jul 2013 12:25:00 +0100 Subject: [PATCH 049/102] clk: add support for clock reparent on set_rate Add core support to allow clock implementations to select the best parent clock when rounding a rate, e.g. the one which can provide the closest clock rate to that requested. This is by way of adding a new clock op, determine_rate(), which is like round_rate() but has an extra parameter to allow the clock implementation to optionally select a different parent clock. The core then takes care of reparenting the clock when setting the rate. The parent change takes place with the help of some new private data members. struct clk::new_parent specifies a clock's new parent (NULL indicates no change), and struct clk::new_child specifies a clock's new child (whose new_parent member points back to it). The purpose of these are to allow correct walking of the future tree for notifications prior to actually reparenting any clocks, specifically to skip child clocks who are being reparented to another clock (they will be notified via the new parent), and to include any new child clock. These pointers are set by clk_calc_subtree(), and the new_child pointer gets cleared when a child is actually reparented to avoid duplicate POST_RATE_CHANGE notifications. Each place where round_rate() is called, determine_rate() is checked first and called in preference. This restructures a few of the call sites to simplify the logic into if/else blocks. Signed-off-by: James Hogan Reviewed-by: Stephen Boyd Cc: Mike Turquette Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Mike Turquette --- Documentation/clk.txt | 46 +++++++----- drivers/clk/clk.c | 138 ++++++++++++++++++++++++----------- include/linux/clk-private.h | 3 + include/linux/clk-provider.h | 7 ++ 4 files changed, 130 insertions(+), 64 deletions(-) diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 6f68ba0d1e01..3aeb5c440442 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -70,6 +70,10 @@ the operations defined in clk.h: unsigned long parent_rate); long (*round_rate)(struct clk_hw *hw, unsigned long, unsigned long *); + long (*determine_rate)(struct clk_hw *hw, + unsigned long rate, + unsigned long *best_parent_rate, + struct clk **best_parent_clk); int (*set_parent)(struct clk_hw *hw, u8 index); u8 (*get_parent)(struct clk_hw *hw); int (*set_rate)(struct clk_hw *hw, unsigned long); @@ -179,26 +183,28 @@ mandatory, a cell marked as "n" implies that either including that callback is invalid or otherwise unnecessary. Empty cells are either optional or must be evaluated on a case-by-case basis. - clock hardware characteristics - ----------------------------------------------------------- - | gate | change rate | single parent | multiplexer | root | - |------|-------------|---------------|-------------|------| -.prepare | | | | | | -.unprepare | | | | | | - | | | | | | -.enable | y | | | | | -.disable | y | | | | | -.is_enabled | y | | | | | - | | | | | | -.recalc_rate | | y | | | | -.round_rate | | y | | | | -.set_rate | | y | | | | - | | | | | | -.set_parent | | | n | y | n | -.get_parent | | | n | y | n | - | | | | | | -.init | | | | | | - ----------------------------------------------------------- + clock hardware characteristics + ----------------------------------------------------------- + | gate | change rate | single parent | multiplexer | root | + |------|-------------|---------------|-------------|------| +.prepare | | | | | | +.unprepare | | | | | | + | | | | | | +.enable | y | | | | | +.disable | y | | | | | +.is_enabled | y | | | | | + | | | | | | +.recalc_rate | | y | | | | +.round_rate | | y [1] | | | | +.determine_rate | | y [1] | | | | +.set_rate | | y | | | | + | | | | | | +.set_parent | | | n | y | n | +.get_parent | | | n | y | n | + | | | | | | +.init | | | | | | + ----------------------------------------------------------- +[1] either one of round_rate or determine_rate is required. Finally, register your clock at run-time with a hardware-specific registration function. This function simply populates struct clk_foo's diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 3d57cf64c9e7..f33f1ccf1b2f 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -889,21 +889,24 @@ EXPORT_SYMBOL_GPL(clk_enable); unsigned long __clk_round_rate(struct clk *clk, unsigned long rate) { unsigned long parent_rate = 0; + struct clk *parent; if (!clk) return 0; - if (!clk->ops->round_rate) { - if (clk->flags & CLK_SET_RATE_PARENT) - return __clk_round_rate(clk->parent, rate); - else - return clk->rate; - } + parent = clk->parent; + if (parent) + parent_rate = parent->rate; - if (clk->parent) - parent_rate = clk->parent->rate; - - return clk->ops->round_rate(clk->hw, rate, &parent_rate); + if (clk->ops->determine_rate) + return clk->ops->determine_rate(clk->hw, rate, &parent_rate, + &parent); + else if (clk->ops->round_rate) + return clk->ops->round_rate(clk->hw, rate, &parent_rate); + else if (clk->flags & CLK_SET_RATE_PARENT) + return __clk_round_rate(clk->parent, rate); + else + return clk->rate; } /** @@ -1056,6 +1059,10 @@ static u8 clk_fetch_parent_index(struct clk *clk, struct clk *parent) static void clk_reparent(struct clk *clk, struct clk *new_parent) { + /* avoid duplicate POST_RATE_CHANGE notifications */ + if (new_parent->new_child == clk) + new_parent->new_child = NULL; + hlist_del(&clk->child_node); if (new_parent) @@ -1176,18 +1183,25 @@ out: return ret; } -static void clk_calc_subtree(struct clk *clk, unsigned long new_rate) +static void clk_calc_subtree(struct clk *clk, unsigned long new_rate, + struct clk *new_parent, u8 p_index) { struct clk *child; clk->new_rate = new_rate; + clk->new_parent = new_parent; + clk->new_parent_index = p_index; + /* include clk in new parent's PRE_RATE_CHANGE notifications */ + clk->new_child = NULL; + if (new_parent && new_parent != clk->parent) + new_parent->new_child = clk; hlist_for_each_entry(child, &clk->children, child_node) { if (child->ops->recalc_rate) child->new_rate = child->ops->recalc_rate(child->hw, new_rate); else child->new_rate = new_rate; - clk_calc_subtree(child, child->new_rate); + clk_calc_subtree(child, child->new_rate, NULL, 0); } } @@ -1198,50 +1212,63 @@ static void clk_calc_subtree(struct clk *clk, unsigned long new_rate) static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate) { struct clk *top = clk; + struct clk *old_parent, *parent; unsigned long best_parent_rate = 0; unsigned long new_rate; + u8 p_index = 0; /* sanity */ if (IS_ERR_OR_NULL(clk)) return NULL; /* save parent rate, if it exists */ - if (clk->parent) - best_parent_rate = clk->parent->rate; + parent = old_parent = clk->parent; + if (parent) + best_parent_rate = parent->rate; - /* never propagate up to the parent */ - if (!(clk->flags & CLK_SET_RATE_PARENT)) { - if (!clk->ops->round_rate) { - clk->new_rate = clk->rate; - return NULL; - } - new_rate = clk->ops->round_rate(clk->hw, rate, &best_parent_rate); + /* find the closest rate and parent clk/rate */ + if (clk->ops->determine_rate) { + new_rate = clk->ops->determine_rate(clk->hw, rate, + &best_parent_rate, + &parent); + } else if (clk->ops->round_rate) { + new_rate = clk->ops->round_rate(clk->hw, rate, + &best_parent_rate); + } else if (!parent || !(clk->flags & CLK_SET_RATE_PARENT)) { + /* pass-through clock without adjustable parent */ + clk->new_rate = clk->rate; + return NULL; + } else { + /* pass-through clock with adjustable parent */ + top = clk_calc_new_rates(parent, rate); + new_rate = parent->new_rate; goto out; } - /* need clk->parent from here on out */ - if (!clk->parent) { - pr_debug("%s: %s has NULL parent\n", __func__, clk->name); + /* some clocks must be gated to change parent */ + if (parent != old_parent && + (clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count) { + pr_debug("%s: %s not gated but wants to reparent\n", + __func__, clk->name); return NULL; } - if (!clk->ops->round_rate) { - top = clk_calc_new_rates(clk->parent, rate); - new_rate = clk->parent->new_rate; - - goto out; + /* try finding the new parent index */ + if (parent) { + p_index = clk_fetch_parent_index(clk, parent); + if (p_index == clk->num_parents) { + pr_debug("%s: clk %s can not be parent of clk %s\n", + __func__, parent->name, clk->name); + return NULL; + } } - new_rate = clk->ops->round_rate(clk->hw, rate, &best_parent_rate); - - if (best_parent_rate != clk->parent->rate) { - top = clk_calc_new_rates(clk->parent, best_parent_rate); - - goto out; - } + if ((clk->flags & CLK_SET_RATE_PARENT) && parent && + best_parent_rate != parent->rate) + top = clk_calc_new_rates(parent, best_parent_rate); out: - clk_calc_subtree(clk, new_rate); + clk_calc_subtree(clk, new_rate, parent, p_index); return top; } @@ -1253,7 +1280,7 @@ out: */ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long event) { - struct clk *child, *fail_clk = NULL; + struct clk *child, *tmp_clk, *fail_clk = NULL; int ret = NOTIFY_DONE; if (clk->rate == clk->new_rate) @@ -1266,9 +1293,19 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even } hlist_for_each_entry(child, &clk->children, child_node) { - clk = clk_propagate_rate_change(child, event); - if (clk) - fail_clk = clk; + /* Skip children who will be reparented to another clock */ + if (child->new_parent && child->new_parent != clk) + continue; + tmp_clk = clk_propagate_rate_change(child, event); + if (tmp_clk) + fail_clk = tmp_clk; + } + + /* handle the new child who might not be in clk->children yet */ + if (clk->new_child) { + tmp_clk = clk_propagate_rate_change(clk->new_child, event); + if (tmp_clk) + fail_clk = tmp_clk; } return fail_clk; @@ -1286,6 +1323,10 @@ static void clk_change_rate(struct clk *clk) old_rate = clk->rate; + /* set parent */ + if (clk->new_parent && clk->new_parent != clk->parent) + __clk_set_parent(clk, clk->new_parent, clk->new_parent_index); + if (clk->parent) best_parent_rate = clk->parent->rate; @@ -1300,8 +1341,16 @@ static void clk_change_rate(struct clk *clk) if (clk->notifier_count && old_rate != clk->rate) __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); - hlist_for_each_entry(child, &clk->children, child_node) + hlist_for_each_entry(child, &clk->children, child_node) { + /* Skip children who will be reparented to another clock */ + if (child->new_parent && child->new_parent != clk) + continue; clk_change_rate(child); + } + + /* handle the new child who might not be in clk->children yet */ + if (clk->new_child) + clk_change_rate(clk->new_child); } /** @@ -1552,8 +1601,9 @@ int __clk_init(struct device *dev, struct clk *clk) /* check that clk_ops are sane. See Documentation/clk.txt */ if (clk->ops->set_rate && - !(clk->ops->round_rate && clk->ops->recalc_rate)) { - pr_warning("%s: %s must implement .round_rate & .recalc_rate\n", + !((clk->ops->round_rate || clk->ops->determine_rate) && + clk->ops->recalc_rate)) { + pr_warning("%s: %s must implement .round_rate or .determine_rate in addition to .recalc_rate\n", __func__, clk->name); ret = -EINVAL; goto out; diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h index dd7adff76e81..8138c94409f3 100644 --- a/include/linux/clk-private.h +++ b/include/linux/clk-private.h @@ -33,8 +33,11 @@ struct clk { const char **parent_names; struct clk **parents; u8 num_parents; + u8 new_parent_index; unsigned long rate; unsigned long new_rate; + struct clk *new_parent; + struct clk *new_child; unsigned long flags; unsigned int enable_count; unsigned int prepare_count; diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index a83409285a7f..4f525b37c6fd 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -79,6 +79,10 @@ struct clk_hw; * @round_rate: Given a target rate as input, returns the closest rate actually * supported by the clock. * + * @determine_rate: Given a target rate as input, returns the closest rate + * actually supported by the clock, and optionally the parent clock + * that should be used to provide the clock rate. + * * @get_parent: Queries the hardware to determine the parent of a clock. The * return value is a u8 which specifies the index corresponding to * the parent clock. This index can be applied to either the @@ -126,6 +130,9 @@ struct clk_ops { unsigned long parent_rate); long (*round_rate)(struct clk_hw *hw, unsigned long, unsigned long *); + long (*determine_rate)(struct clk_hw *hw, unsigned long rate, + unsigned long *best_parent_rate, + struct clk **best_parent_clk); int (*set_parent)(struct clk_hw *hw, u8 index); u8 (*get_parent)(struct clk_hw *hw); int (*set_rate)(struct clk_hw *hw, unsigned long, From 819c1de344c5b8350bffd35be9a0fa74541292d3 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 29 Jul 2013 12:25:01 +0100 Subject: [PATCH 050/102] clk: add CLK_SET_RATE_NO_REPARENT flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a CLK_SET_RATE_NO_REPARENT clock flag, which will prevent muxes being reparented during clk_set_rate. To avoid breaking existing platforms, all callers of clk_register_mux() are adjusted to pass the new flag. Platform maintainers are encouraged to remove the flag if they wish to allow mux reparenting on set_rate. Signed-off-by: James Hogan Reviewed-by: Stephen Boyd Cc: Mike Turquette Cc: Russell King Cc: Sascha Hauer Cc: Stephen Warren Cc: Viresh Kumar Cc: Kukjin Kim Cc: Haojian Zhuang Cc: Chao Xie Cc: Arnd Bergmann Cc: "Emilio López" Cc: Gregory CLEMENT Cc: Maxime Ripard Cc: Prashant Gaikwad Cc: Thierry Reding Cc: Peter De Schrijver Cc: Pawel Moll Cc: Catalin Marinas Cc: Andrew Chew Cc: Doug Anderson Cc: Heiko Stuebner Cc: Paul Walmsley Cc: Sylwester Nawrocki Cc: Thomas Abraham Cc: Tomasz Figa Cc: linux-arm-kernel@lists.infradead.org Cc: linux-samsung-soc@vger.kernel.org Cc: spear-devel@list.st.com Cc: linux-tegra@vger.kernel.org Tested-by: Haojian Zhuang Acked-by: Stephen Warren [tegra] Acked-by: Maxime Ripard [sunxi] Acked-by: Sören Brinkmann [Zynq] Signed-off-by: Mike Turquette --- arch/arm/mach-imx/clk.h | 5 +- drivers/clk/mmp/clk-mmp2.c | 39 ++++-- drivers/clk/mmp/clk-pxa168.c | 40 ++++-- drivers/clk/mmp/clk-pxa910.c | 31 +++-- drivers/clk/mxs/clk.h | 4 +- drivers/clk/samsung/clk-exynos-audss.c | 6 +- drivers/clk/samsung/clk.h | 2 +- drivers/clk/spear/spear1310_clock.c | 179 +++++++++++++------------ drivers/clk/spear/spear1340_clock.c | 97 ++++++++------ drivers/clk/spear/spear3xx_clock.c | 57 +++++--- drivers/clk/spear/spear6xx_clock.c | 35 ++--- drivers/clk/sunxi/clk-sunxi.c | 3 +- drivers/clk/tegra/clk-tegra114.c | 36 +++-- drivers/clk/tegra/clk-tegra20.c | 6 +- drivers/clk/tegra/clk-tegra30.c | 33 +++-- drivers/clk/versatile/clk-vexpress.c | 4 +- drivers/clk/zynq/clkc.c | 86 +++++++----- include/linux/clk-provider.h | 1 + 18 files changed, 388 insertions(+), 276 deletions(-) diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h index 0e4e8bb261b9..c8575fb7f717 100644 --- a/arch/arm/mach-imx/clk.h +++ b/arch/arm/mach-imx/clk.h @@ -79,7 +79,8 @@ static inline struct clk *imx_clk_gate(const char *name, const char *parent, static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg, u8 shift, u8 width, const char **parents, int num_parents) { - return clk_register_mux(NULL, name, parents, num_parents, 0, reg, shift, + return clk_register_mux(NULL, name, parents, num_parents, + CLK_SET_RATE_NO_REPARENT, reg, shift, width, 0, &imx_ccm_lock); } @@ -88,7 +89,7 @@ static inline struct clk *imx_clk_mux_flags(const char *name, int num_parents, unsigned long flags) { return clk_register_mux(NULL, name, parents, num_parents, - flags, reg, shift, width, 0, + flags | CLK_SET_RATE_NO_REPARENT, reg, shift, width, 0, &imx_ccm_lock); } diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c index d1f1a19d4351..b2721cae257a 100644 --- a/drivers/clk/mmp/clk-mmp2.c +++ b/drivers/clk/mmp/clk-mmp2.c @@ -248,7 +248,8 @@ void __init mmp2_clk_init(void) clk_register_clkdev(clk, NULL, "mmp2-pwm.3"); clk = clk_register_mux(NULL, "uart0_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uart_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_UART0, 4, 3, 0, &clk_lock); clk_set_parent(clk, vctcxo); clk_register_clkdev(clk, "uart_mux.0", NULL); @@ -258,7 +259,8 @@ void __init mmp2_clk_init(void) clk_register_clkdev(clk, NULL, "pxa2xx-uart.0"); clk = clk_register_mux(NULL, "uart1_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uart_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_UART1, 4, 3, 0, &clk_lock); clk_set_parent(clk, vctcxo); clk_register_clkdev(clk, "uart_mux.1", NULL); @@ -268,7 +270,8 @@ void __init mmp2_clk_init(void) clk_register_clkdev(clk, NULL, "pxa2xx-uart.1"); clk = clk_register_mux(NULL, "uart2_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uart_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_UART2, 4, 3, 0, &clk_lock); clk_set_parent(clk, vctcxo); clk_register_clkdev(clk, "uart_mux.2", NULL); @@ -278,7 +281,8 @@ void __init mmp2_clk_init(void) clk_register_clkdev(clk, NULL, "pxa2xx-uart.2"); clk = clk_register_mux(NULL, "uart3_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uart_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_UART3, 4, 3, 0, &clk_lock); clk_set_parent(clk, vctcxo); clk_register_clkdev(clk, "uart_mux.3", NULL); @@ -288,7 +292,8 @@ void __init mmp2_clk_init(void) clk_register_clkdev(clk, NULL, "pxa2xx-uart.3"); clk = clk_register_mux(NULL, "ssp0_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(ssp_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_SSP0, 4, 3, 0, &clk_lock); clk_register_clkdev(clk, "uart_mux.0", NULL); @@ -297,7 +302,8 @@ void __init mmp2_clk_init(void) clk_register_clkdev(clk, NULL, "mmp-ssp.0"); clk = clk_register_mux(NULL, "ssp1_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(ssp_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_SSP1, 4, 3, 0, &clk_lock); clk_register_clkdev(clk, "ssp_mux.1", NULL); @@ -306,7 +312,8 @@ void __init mmp2_clk_init(void) clk_register_clkdev(clk, NULL, "mmp-ssp.1"); clk = clk_register_mux(NULL, "ssp2_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(ssp_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_SSP2, 4, 3, 0, &clk_lock); clk_register_clkdev(clk, "ssp_mux.2", NULL); @@ -315,7 +322,8 @@ void __init mmp2_clk_init(void) clk_register_clkdev(clk, NULL, "mmp-ssp.2"); clk = clk_register_mux(NULL, "ssp3_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(ssp_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_SSP3, 4, 3, 0, &clk_lock); clk_register_clkdev(clk, "ssp_mux.3", NULL); @@ -324,7 +332,8 @@ void __init mmp2_clk_init(void) clk_register_clkdev(clk, NULL, "mmp-ssp.3"); clk = clk_register_mux(NULL, "sdh_mux", sdh_parent, - ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(sdh_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apmu_base + APMU_SDH0, 8, 2, 0, &clk_lock); clk_register_clkdev(clk, "sdh_mux", NULL); @@ -354,7 +363,8 @@ void __init mmp2_clk_init(void) clk_register_clkdev(clk, "usb_clk", NULL); clk = clk_register_mux(NULL, "disp0_mux", disp_parent, - ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(disp_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apmu_base + APMU_DISP0, 6, 2, 0, &clk_lock); clk_register_clkdev(clk, "disp_mux.0", NULL); @@ -376,7 +386,8 @@ void __init mmp2_clk_init(void) clk_register_clkdev(clk, "disp_sphy.0", NULL); clk = clk_register_mux(NULL, "disp1_mux", disp_parent, - ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(disp_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apmu_base + APMU_DISP1, 6, 2, 0, &clk_lock); clk_register_clkdev(clk, "disp_mux.1", NULL); @@ -394,7 +405,8 @@ void __init mmp2_clk_init(void) clk_register_clkdev(clk, "ccic_arbiter", NULL); clk = clk_register_mux(NULL, "ccic0_mux", ccic_parent, - ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(ccic_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apmu_base + APMU_CCIC0, 6, 2, 0, &clk_lock); clk_register_clkdev(clk, "ccic_mux.0", NULL); @@ -421,7 +433,8 @@ void __init mmp2_clk_init(void) clk_register_clkdev(clk, "sphyclk", "mmp-ccic.0"); clk = clk_register_mux(NULL, "ccic1_mux", ccic_parent, - ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(ccic_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apmu_base + APMU_CCIC1, 6, 2, 0, &clk_lock); clk_register_clkdev(clk, "ccic_mux.1", NULL); diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c index 28b3b51c794b..014396b028a2 100644 --- a/drivers/clk/mmp/clk-pxa168.c +++ b/drivers/clk/mmp/clk-pxa168.c @@ -199,7 +199,8 @@ void __init pxa168_clk_init(void) clk_register_clkdev(clk, NULL, "pxa168-pwm.3"); clk = clk_register_mux(NULL, "uart0_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uart_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_UART0, 4, 3, 0, &clk_lock); clk_set_parent(clk, uart_pll); clk_register_clkdev(clk, "uart_mux.0", NULL); @@ -209,7 +210,8 @@ void __init pxa168_clk_init(void) clk_register_clkdev(clk, NULL, "pxa2xx-uart.0"); clk = clk_register_mux(NULL, "uart1_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uart_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_UART1, 4, 3, 0, &clk_lock); clk_set_parent(clk, uart_pll); clk_register_clkdev(clk, "uart_mux.1", NULL); @@ -219,7 +221,8 @@ void __init pxa168_clk_init(void) clk_register_clkdev(clk, NULL, "pxa2xx-uart.1"); clk = clk_register_mux(NULL, "uart2_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uart_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_UART2, 4, 3, 0, &clk_lock); clk_set_parent(clk, uart_pll); clk_register_clkdev(clk, "uart_mux.2", NULL); @@ -229,7 +232,8 @@ void __init pxa168_clk_init(void) clk_register_clkdev(clk, NULL, "pxa2xx-uart.2"); clk = clk_register_mux(NULL, "ssp0_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(ssp_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_SSP0, 4, 3, 0, &clk_lock); clk_register_clkdev(clk, "uart_mux.0", NULL); @@ -238,7 +242,8 @@ void __init pxa168_clk_init(void) clk_register_clkdev(clk, NULL, "mmp-ssp.0"); clk = clk_register_mux(NULL, "ssp1_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(ssp_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_SSP1, 4, 3, 0, &clk_lock); clk_register_clkdev(clk, "ssp_mux.1", NULL); @@ -247,7 +252,8 @@ void __init pxa168_clk_init(void) clk_register_clkdev(clk, NULL, "mmp-ssp.1"); clk = clk_register_mux(NULL, "ssp2_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(ssp_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_SSP2, 4, 3, 0, &clk_lock); clk_register_clkdev(clk, "ssp_mux.2", NULL); @@ -256,7 +262,8 @@ void __init pxa168_clk_init(void) clk_register_clkdev(clk, NULL, "mmp-ssp.2"); clk = clk_register_mux(NULL, "ssp3_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(ssp_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_SSP3, 4, 3, 0, &clk_lock); clk_register_clkdev(clk, "ssp_mux.3", NULL); @@ -265,7 +272,8 @@ void __init pxa168_clk_init(void) clk_register_clkdev(clk, NULL, "mmp-ssp.3"); clk = clk_register_mux(NULL, "ssp4_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(ssp_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_SSP4, 4, 3, 0, &clk_lock); clk_register_clkdev(clk, "ssp_mux.4", NULL); @@ -278,7 +286,8 @@ void __init pxa168_clk_init(void) clk_register_clkdev(clk, NULL, "pxa3xx-nand.0"); clk = clk_register_mux(NULL, "sdh0_mux", sdh_parent, - ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(sdh_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apmu_base + APMU_SDH0, 6, 1, 0, &clk_lock); clk_register_clkdev(clk, "sdh0_mux", NULL); @@ -287,7 +296,8 @@ void __init pxa168_clk_init(void) clk_register_clkdev(clk, NULL, "sdhci-pxa.0"); clk = clk_register_mux(NULL, "sdh1_mux", sdh_parent, - ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(sdh_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apmu_base + APMU_SDH1, 6, 1, 0, &clk_lock); clk_register_clkdev(clk, "sdh1_mux", NULL); @@ -304,7 +314,8 @@ void __init pxa168_clk_init(void) clk_register_clkdev(clk, "sph_clk", NULL); clk = clk_register_mux(NULL, "disp0_mux", disp_parent, - ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(disp_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apmu_base + APMU_DISP0, 6, 1, 0, &clk_lock); clk_register_clkdev(clk, "disp_mux.0", NULL); @@ -317,7 +328,8 @@ void __init pxa168_clk_init(void) clk_register_clkdev(clk, "hclk", "mmp-disp.0"); clk = clk_register_mux(NULL, "ccic0_mux", ccic_parent, - ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(ccic_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apmu_base + APMU_CCIC0, 6, 1, 0, &clk_lock); clk_register_clkdev(clk, "ccic_mux.0", NULL); @@ -327,8 +339,8 @@ void __init pxa168_clk_init(void) clk = clk_register_mux(NULL, "ccic0_phy_mux", ccic_phy_parent, ARRAY_SIZE(ccic_phy_parent), - CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0, - 7, 1, 0, &clk_lock); + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + apmu_base + APMU_CCIC0, 7, 1, 0, &clk_lock); clk_register_clkdev(clk, "ccic_phy_mux.0", NULL); clk = mmp_clk_register_apmu("ccic0_phy", "ccic0_phy_mux", diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c index 6ec05698ed38..9efc6a47535d 100644 --- a/drivers/clk/mmp/clk-pxa910.c +++ b/drivers/clk/mmp/clk-pxa910.c @@ -204,7 +204,8 @@ void __init pxa910_clk_init(void) clk_register_clkdev(clk, NULL, "pxa910-pwm.3"); clk = clk_register_mux(NULL, "uart0_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uart_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_UART0, 4, 3, 0, &clk_lock); clk_set_parent(clk, uart_pll); clk_register_clkdev(clk, "uart_mux.0", NULL); @@ -214,7 +215,8 @@ void __init pxa910_clk_init(void) clk_register_clkdev(clk, NULL, "pxa2xx-uart.0"); clk = clk_register_mux(NULL, "uart1_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uart_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_UART1, 4, 3, 0, &clk_lock); clk_set_parent(clk, uart_pll); clk_register_clkdev(clk, "uart_mux.1", NULL); @@ -224,7 +226,8 @@ void __init pxa910_clk_init(void) clk_register_clkdev(clk, NULL, "pxa2xx-uart.1"); clk = clk_register_mux(NULL, "uart2_mux", uart_parent, - ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uart_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbcp_base + APBCP_UART2, 4, 3, 0, &clk_lock); clk_set_parent(clk, uart_pll); clk_register_clkdev(clk, "uart_mux.2", NULL); @@ -234,7 +237,8 @@ void __init pxa910_clk_init(void) clk_register_clkdev(clk, NULL, "pxa2xx-uart.2"); clk = clk_register_mux(NULL, "ssp0_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(ssp_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_SSP0, 4, 3, 0, &clk_lock); clk_register_clkdev(clk, "uart_mux.0", NULL); @@ -243,7 +247,8 @@ void __init pxa910_clk_init(void) clk_register_clkdev(clk, NULL, "mmp-ssp.0"); clk = clk_register_mux(NULL, "ssp1_mux", ssp_parent, - ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(ssp_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apbc_base + APBC_SSP1, 4, 3, 0, &clk_lock); clk_register_clkdev(clk, "ssp_mux.1", NULL); @@ -256,7 +261,8 @@ void __init pxa910_clk_init(void) clk_register_clkdev(clk, NULL, "pxa3xx-nand.0"); clk = clk_register_mux(NULL, "sdh0_mux", sdh_parent, - ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(sdh_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apmu_base + APMU_SDH0, 6, 1, 0, &clk_lock); clk_register_clkdev(clk, "sdh0_mux", NULL); @@ -265,7 +271,8 @@ void __init pxa910_clk_init(void) clk_register_clkdev(clk, NULL, "sdhci-pxa.0"); clk = clk_register_mux(NULL, "sdh1_mux", sdh_parent, - ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(sdh_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apmu_base + APMU_SDH1, 6, 1, 0, &clk_lock); clk_register_clkdev(clk, "sdh1_mux", NULL); @@ -282,7 +289,8 @@ void __init pxa910_clk_init(void) clk_register_clkdev(clk, "sph_clk", NULL); clk = clk_register_mux(NULL, "disp0_mux", disp_parent, - ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(disp_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apmu_base + APMU_DISP0, 6, 1, 0, &clk_lock); clk_register_clkdev(clk, "disp_mux.0", NULL); @@ -291,7 +299,8 @@ void __init pxa910_clk_init(void) clk_register_clkdev(clk, NULL, "mmp-disp.0"); clk = clk_register_mux(NULL, "ccic0_mux", ccic_parent, - ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT, + ARRAY_SIZE(ccic_parent), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, apmu_base + APMU_CCIC0, 6, 1, 0, &clk_lock); clk_register_clkdev(clk, "ccic_mux.0", NULL); @@ -301,8 +310,8 @@ void __init pxa910_clk_init(void) clk = clk_register_mux(NULL, "ccic0_phy_mux", ccic_phy_parent, ARRAY_SIZE(ccic_phy_parent), - CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0, - 7, 1, 0, &clk_lock); + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + apmu_base + APMU_CCIC0, 7, 1, 0, &clk_lock); clk_register_clkdev(clk, "ccic_phy_mux.0", NULL); clk = mmp_clk_register_apmu("ccic0_phy", "ccic0_phy_mux", diff --git a/drivers/clk/mxs/clk.h b/drivers/clk/mxs/clk.h index 81421e28e69c..ef10ad9b5daa 100644 --- a/drivers/clk/mxs/clk.h +++ b/drivers/clk/mxs/clk.h @@ -52,8 +52,8 @@ static inline struct clk *mxs_clk_mux(const char *name, void __iomem *reg, u8 shift, u8 width, const char **parent_names, int num_parents) { return clk_register_mux(NULL, name, parent_names, num_parents, - CLK_SET_RATE_PARENT, reg, shift, width, - 0, &mxs_lock); + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + reg, shift, width, 0, &mxs_lock); } static inline struct clk *mxs_clk_fixed_factor(const char *name, diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index 51b48daf5c8a..39b40aaede2b 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -82,11 +82,13 @@ static void __init exynos_audss_clk_init(struct device_node *np) of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss", - mout_audss_p, ARRAY_SIZE(mout_audss_p), 0, + 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), 0, + mout_i2s_p, ARRAY_SIZE(mout_i2s_p), + CLK_SET_RATE_NO_REPARENT, reg_base + ASS_CLK_SRC, 2, 2, 0, &lock); clk_table[EXYNOS_DOUT_SRP] = clk_register_divider(NULL, "dout_srp", diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index e7dfccb5d981..31b4174e7a5b 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -130,7 +130,7 @@ struct samsung_mux_clock { .name = cname, \ .parent_names = pnames, \ .num_parents = ARRAY_SIZE(pnames), \ - .flags = f, \ + .flags = (f) | CLK_SET_RATE_NO_REPARENT, \ .offset = o, \ .shift = s, \ .width = w, \ diff --git a/drivers/clk/spear/spear1310_clock.c b/drivers/clk/spear/spear1310_clock.c index aedbbe12f321..65894f7687ed 100644 --- a/drivers/clk/spear/spear1310_clock.c +++ b/drivers/clk/spear/spear1310_clock.c @@ -416,9 +416,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) /* clock derived from 24 or 25 MHz osc clk */ /* vco-pll */ clk = clk_register_mux(NULL, "vco1_mclk", vco_parents, - ARRAY_SIZE(vco_parents), 0, SPEAR1310_PLL_CFG, - SPEAR1310_PLL1_CLK_SHIFT, SPEAR1310_PLL_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_PLL_CFG, SPEAR1310_PLL1_CLK_SHIFT, + SPEAR1310_PLL_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "vco1_mclk", NULL); clk = clk_register_vco_pll("vco1_clk", "pll1_clk", NULL, "vco1_mclk", 0, SPEAR1310_PLL1_CTR, SPEAR1310_PLL1_FRQ, pll_rtbl, @@ -427,9 +427,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk1, "pll1_clk", NULL); clk = clk_register_mux(NULL, "vco2_mclk", vco_parents, - ARRAY_SIZE(vco_parents), 0, SPEAR1310_PLL_CFG, - SPEAR1310_PLL2_CLK_SHIFT, SPEAR1310_PLL_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_PLL_CFG, SPEAR1310_PLL2_CLK_SHIFT, + SPEAR1310_PLL_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "vco2_mclk", NULL); clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL, "vco2_mclk", 0, SPEAR1310_PLL2_CTR, SPEAR1310_PLL2_FRQ, pll_rtbl, @@ -438,9 +438,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk1, "pll2_clk", NULL); clk = clk_register_mux(NULL, "vco3_mclk", vco_parents, - ARRAY_SIZE(vco_parents), 0, SPEAR1310_PLL_CFG, - SPEAR1310_PLL3_CLK_SHIFT, SPEAR1310_PLL_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_PLL_CFG, SPEAR1310_PLL3_CLK_SHIFT, + SPEAR1310_PLL_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "vco3_mclk", NULL); clk = clk_register_vco_pll("vco3_clk", "pll3_clk", NULL, "vco3_mclk", 0, SPEAR1310_PLL3_CTR, SPEAR1310_PLL3_FRQ, pll_rtbl, @@ -515,9 +515,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) /* gpt clocks */ clk = clk_register_mux(NULL, "gpt0_mclk", gpt_parents, - ARRAY_SIZE(gpt_parents), 0, SPEAR1310_PERIP_CLK_CFG, - SPEAR1310_GPT0_CLK_SHIFT, SPEAR1310_GPT_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GPT0_CLK_SHIFT, + SPEAR1310_GPT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gpt0_mclk", NULL); clk = clk_register_gate(NULL, "gpt0_clk", "gpt0_mclk", 0, SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_GPT0_CLK_ENB, 0, @@ -525,9 +525,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "gpt0"); clk = clk_register_mux(NULL, "gpt1_mclk", gpt_parents, - ARRAY_SIZE(gpt_parents), 0, SPEAR1310_PERIP_CLK_CFG, - SPEAR1310_GPT1_CLK_SHIFT, SPEAR1310_GPT_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GPT1_CLK_SHIFT, + SPEAR1310_GPT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gpt1_mclk", NULL); clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk", 0, SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_GPT1_CLK_ENB, 0, @@ -535,9 +535,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "gpt1"); clk = clk_register_mux(NULL, "gpt2_mclk", gpt_parents, - ARRAY_SIZE(gpt_parents), 0, SPEAR1310_PERIP_CLK_CFG, - SPEAR1310_GPT2_CLK_SHIFT, SPEAR1310_GPT_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GPT2_CLK_SHIFT, + SPEAR1310_GPT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gpt2_mclk", NULL); clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk", 0, SPEAR1310_PERIP2_CLK_ENB, SPEAR1310_GPT2_CLK_ENB, 0, @@ -545,9 +545,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "gpt2"); clk = clk_register_mux(NULL, "gpt3_mclk", gpt_parents, - ARRAY_SIZE(gpt_parents), 0, SPEAR1310_PERIP_CLK_CFG, - SPEAR1310_GPT3_CLK_SHIFT, SPEAR1310_GPT_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GPT3_CLK_SHIFT, + SPEAR1310_GPT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gpt3_mclk", NULL); clk = clk_register_gate(NULL, "gpt3_clk", "gpt3_mclk", 0, SPEAR1310_PERIP2_CLK_ENB, SPEAR1310_GPT3_CLK_ENB, 0, @@ -562,7 +562,8 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk1, "uart_syn_gclk", NULL); clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents, - ARRAY_SIZE(uart0_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uart0_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR1310_PERIP_CLK_CFG, SPEAR1310_UART_CLK_SHIFT, SPEAR1310_UART_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "uart0_mclk", NULL); @@ -602,7 +603,8 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk1, "c3_syn_gclk", NULL); clk = clk_register_mux(NULL, "c3_mclk", c3_parents, - ARRAY_SIZE(c3_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(c3_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR1310_PERIP_CLK_CFG, SPEAR1310_C3_CLK_SHIFT, SPEAR1310_C3_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "c3_mclk", NULL); @@ -614,8 +616,8 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) /* gmac */ clk = clk_register_mux(NULL, "phy_input_mclk", gmac_phy_input_parents, - ARRAY_SIZE(gmac_phy_input_parents), 0, - SPEAR1310_GMAC_CLK_CFG, + ARRAY_SIZE(gmac_phy_input_parents), + CLK_SET_RATE_NO_REPARENT, SPEAR1310_GMAC_CLK_CFG, SPEAR1310_GMAC_PHY_INPUT_CLK_SHIFT, SPEAR1310_GMAC_PHY_INPUT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "phy_input_mclk", NULL); @@ -627,15 +629,16 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk1, "phy_syn_gclk", NULL); clk = clk_register_mux(NULL, "phy_mclk", gmac_phy_parents, - ARRAY_SIZE(gmac_phy_parents), 0, + ARRAY_SIZE(gmac_phy_parents), CLK_SET_RATE_NO_REPARENT, SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GMAC_PHY_CLK_SHIFT, SPEAR1310_GMAC_PHY_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "stmmacphy.0", NULL); /* clcd */ clk = clk_register_mux(NULL, "clcd_syn_mclk", clcd_synth_parents, - ARRAY_SIZE(clcd_synth_parents), 0, - SPEAR1310_CLCD_CLK_SYNT, SPEAR1310_CLCD_SYNT_CLK_SHIFT, + ARRAY_SIZE(clcd_synth_parents), + CLK_SET_RATE_NO_REPARENT, SPEAR1310_CLCD_CLK_SYNT, + SPEAR1310_CLCD_SYNT_CLK_SHIFT, SPEAR1310_CLCD_SYNT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "clcd_syn_mclk", NULL); @@ -645,7 +648,8 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, "clcd_syn_clk", NULL); clk = clk_register_mux(NULL, "clcd_pixel_mclk", clcd_pixel_parents, - ARRAY_SIZE(clcd_pixel_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(clcd_pixel_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR1310_PERIP_CLK_CFG, SPEAR1310_CLCD_CLK_SHIFT, SPEAR1310_CLCD_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "clcd_pixel_mclk", NULL); @@ -657,9 +661,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) /* i2s */ clk = clk_register_mux(NULL, "i2s_src_mclk", i2s_src_parents, - ARRAY_SIZE(i2s_src_parents), 0, SPEAR1310_I2S_CLK_CFG, - SPEAR1310_I2S_SRC_CLK_SHIFT, SPEAR1310_I2S_SRC_CLK_MASK, - 0, &_lock); + ARRAY_SIZE(i2s_src_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_I2S_CLK_CFG, SPEAR1310_I2S_SRC_CLK_SHIFT, + SPEAR1310_I2S_SRC_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "i2s_src_mclk", NULL); clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mclk", 0, @@ -668,7 +672,8 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, "i2s_prs1_clk", NULL); clk = clk_register_mux(NULL, "i2s_ref_mclk", i2s_ref_parents, - ARRAY_SIZE(i2s_ref_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(i2s_ref_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR1310_I2S_CLK_CFG, SPEAR1310_I2S_REF_SHIFT, SPEAR1310_I2S_REF_SEL_MASK, 0, &_lock); clk_register_clkdev(clk, "i2s_ref_mclk", NULL); @@ -806,13 +811,15 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) /* RAS clks */ clk = clk_register_mux(NULL, "gen_syn0_1_mclk", gen_synth0_1_parents, - ARRAY_SIZE(gen_synth0_1_parents), 0, SPEAR1310_PLL_CFG, + ARRAY_SIZE(gen_synth0_1_parents), + CLK_SET_RATE_NO_REPARENT, SPEAR1310_PLL_CFG, SPEAR1310_RAS_SYNT0_1_CLK_SHIFT, SPEAR1310_RAS_SYNT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gen_syn0_1_clk", NULL); clk = clk_register_mux(NULL, "gen_syn2_3_mclk", gen_synth2_3_parents, - ARRAY_SIZE(gen_synth2_3_parents), 0, SPEAR1310_PLL_CFG, + ARRAY_SIZE(gen_synth2_3_parents), + CLK_SET_RATE_NO_REPARENT, SPEAR1310_PLL_CFG, SPEAR1310_RAS_SYNT2_3_CLK_SHIFT, SPEAR1310_RAS_SYNT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gen_syn2_3_clk", NULL); @@ -929,8 +936,8 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk = clk_register_mux(NULL, "smii_rgmii_phy_mclk", smii_rgmii_phy_parents, - ARRAY_SIZE(smii_rgmii_phy_parents), 0, - SPEAR1310_RAS_CTRL_REG1, + ARRAY_SIZE(smii_rgmii_phy_parents), + CLK_SET_RATE_NO_REPARENT, SPEAR1310_RAS_CTRL_REG1, SPEAR1310_SMII_RGMII_PHY_CLK_SHIFT, SPEAR1310_PHY_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "stmmacphy.1", NULL); @@ -938,15 +945,15 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, "stmmacphy.4", NULL); clk = clk_register_mux(NULL, "rmii_phy_mclk", rmii_phy_parents, - ARRAY_SIZE(rmii_phy_parents), 0, + ARRAY_SIZE(rmii_phy_parents), CLK_SET_RATE_NO_REPARENT, SPEAR1310_RAS_CTRL_REG1, SPEAR1310_RMII_PHY_CLK_SHIFT, SPEAR1310_PHY_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "stmmacphy.3", NULL); clk = clk_register_mux(NULL, "uart1_mclk", uart_parents, - ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0, - SPEAR1310_UART1_CLK_SHIFT, SPEAR1310_RAS_UART_CLK_MASK, - 0, &_lock); + ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_RAS_CTRL_REG0, SPEAR1310_UART1_CLK_SHIFT, + SPEAR1310_RAS_UART_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "uart1_mclk", NULL); clk = clk_register_gate(NULL, "uart1_clk", "uart1_mclk", 0, @@ -955,9 +962,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "5c800000.serial"); clk = clk_register_mux(NULL, "uart2_mclk", uart_parents, - ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0, - SPEAR1310_UART2_CLK_SHIFT, SPEAR1310_RAS_UART_CLK_MASK, - 0, &_lock); + ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_RAS_CTRL_REG0, SPEAR1310_UART2_CLK_SHIFT, + SPEAR1310_RAS_UART_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "uart2_mclk", NULL); clk = clk_register_gate(NULL, "uart2_clk", "uart2_mclk", 0, @@ -966,9 +973,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "5c900000.serial"); clk = clk_register_mux(NULL, "uart3_mclk", uart_parents, - ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0, - SPEAR1310_UART3_CLK_SHIFT, SPEAR1310_RAS_UART_CLK_MASK, - 0, &_lock); + ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_RAS_CTRL_REG0, SPEAR1310_UART3_CLK_SHIFT, + SPEAR1310_RAS_UART_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "uart3_mclk", NULL); clk = clk_register_gate(NULL, "uart3_clk", "uart3_mclk", 0, @@ -977,9 +984,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "5ca00000.serial"); clk = clk_register_mux(NULL, "uart4_mclk", uart_parents, - ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0, - SPEAR1310_UART4_CLK_SHIFT, SPEAR1310_RAS_UART_CLK_MASK, - 0, &_lock); + ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_RAS_CTRL_REG0, SPEAR1310_UART4_CLK_SHIFT, + SPEAR1310_RAS_UART_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "uart4_mclk", NULL); clk = clk_register_gate(NULL, "uart4_clk", "uart4_mclk", 0, @@ -988,9 +995,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "5cb00000.serial"); clk = clk_register_mux(NULL, "uart5_mclk", uart_parents, - ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0, - SPEAR1310_UART5_CLK_SHIFT, SPEAR1310_RAS_UART_CLK_MASK, - 0, &_lock); + ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_RAS_CTRL_REG0, SPEAR1310_UART5_CLK_SHIFT, + SPEAR1310_RAS_UART_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "uart5_mclk", NULL); clk = clk_register_gate(NULL, "uart5_clk", "uart5_mclk", 0, @@ -999,9 +1006,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "5cc00000.serial"); clk = clk_register_mux(NULL, "i2c1_mclk", i2c_parents, - ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0, - SPEAR1310_I2C1_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C1_CLK_SHIFT, + SPEAR1310_I2C_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "i2c1_mclk", NULL); clk = clk_register_gate(NULL, "i2c1_clk", "i2c1_mclk", 0, @@ -1010,9 +1017,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "5cd00000.i2c"); clk = clk_register_mux(NULL, "i2c2_mclk", i2c_parents, - ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0, - SPEAR1310_I2C2_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C2_CLK_SHIFT, + SPEAR1310_I2C_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "i2c2_mclk", NULL); clk = clk_register_gate(NULL, "i2c2_clk", "i2c2_mclk", 0, @@ -1021,9 +1028,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "5ce00000.i2c"); clk = clk_register_mux(NULL, "i2c3_mclk", i2c_parents, - ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0, - SPEAR1310_I2C3_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C3_CLK_SHIFT, + SPEAR1310_I2C_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "i2c3_mclk", NULL); clk = clk_register_gate(NULL, "i2c3_clk", "i2c3_mclk", 0, @@ -1032,9 +1039,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "5cf00000.i2c"); clk = clk_register_mux(NULL, "i2c4_mclk", i2c_parents, - ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0, - SPEAR1310_I2C4_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C4_CLK_SHIFT, + SPEAR1310_I2C_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "i2c4_mclk", NULL); clk = clk_register_gate(NULL, "i2c4_clk", "i2c4_mclk", 0, @@ -1043,9 +1050,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "5d000000.i2c"); clk = clk_register_mux(NULL, "i2c5_mclk", i2c_parents, - ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0, - SPEAR1310_I2C5_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C5_CLK_SHIFT, + SPEAR1310_I2C_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "i2c5_mclk", NULL); clk = clk_register_gate(NULL, "i2c5_clk", "i2c5_mclk", 0, @@ -1054,9 +1061,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "5d100000.i2c"); clk = clk_register_mux(NULL, "i2c6_mclk", i2c_parents, - ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0, - SPEAR1310_I2C6_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C6_CLK_SHIFT, + SPEAR1310_I2C_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "i2c6_mclk", NULL); clk = clk_register_gate(NULL, "i2c6_clk", "i2c6_mclk", 0, @@ -1065,9 +1072,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "5d200000.i2c"); clk = clk_register_mux(NULL, "i2c7_mclk", i2c_parents, - ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0, - SPEAR1310_I2C7_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C7_CLK_SHIFT, + SPEAR1310_I2C_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "i2c7_mclk", NULL); clk = clk_register_gate(NULL, "i2c7_clk", "i2c7_mclk", 0, @@ -1076,9 +1083,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "5d300000.i2c"); clk = clk_register_mux(NULL, "ssp1_mclk", ssp1_parents, - ARRAY_SIZE(ssp1_parents), 0, SPEAR1310_RAS_CTRL_REG0, - SPEAR1310_SSP1_CLK_SHIFT, SPEAR1310_SSP1_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(ssp1_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_RAS_CTRL_REG0, SPEAR1310_SSP1_CLK_SHIFT, + SPEAR1310_SSP1_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "ssp1_mclk", NULL); clk = clk_register_gate(NULL, "ssp1_clk", "ssp1_mclk", 0, @@ -1087,9 +1094,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "5d400000.spi"); clk = clk_register_mux(NULL, "pci_mclk", pci_parents, - ARRAY_SIZE(pci_parents), 0, SPEAR1310_RAS_CTRL_REG0, - SPEAR1310_PCI_CLK_SHIFT, SPEAR1310_PCI_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(pci_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_RAS_CTRL_REG0, SPEAR1310_PCI_CLK_SHIFT, + SPEAR1310_PCI_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "pci_mclk", NULL); clk = clk_register_gate(NULL, "pci_clk", "pci_mclk", 0, @@ -1098,9 +1105,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "pci"); clk = clk_register_mux(NULL, "tdm1_mclk", tdm_parents, - ARRAY_SIZE(tdm_parents), 0, SPEAR1310_RAS_CTRL_REG0, - SPEAR1310_TDM1_CLK_SHIFT, SPEAR1310_TDM_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(tdm_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_RAS_CTRL_REG0, SPEAR1310_TDM1_CLK_SHIFT, + SPEAR1310_TDM_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "tdm1_mclk", NULL); clk = clk_register_gate(NULL, "tdm1_clk", "tdm1_mclk", 0, @@ -1109,9 +1116,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) clk_register_clkdev(clk, NULL, "tdm_hdlc.0"); clk = clk_register_mux(NULL, "tdm2_mclk", tdm_parents, - ARRAY_SIZE(tdm_parents), 0, SPEAR1310_RAS_CTRL_REG0, - SPEAR1310_TDM2_CLK_SHIFT, SPEAR1310_TDM_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(tdm_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1310_RAS_CTRL_REG0, SPEAR1310_TDM2_CLK_SHIFT, + SPEAR1310_TDM_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "tdm2_mclk", NULL); clk = clk_register_gate(NULL, "tdm2_clk", "tdm2_mclk", 0, diff --git a/drivers/clk/spear/spear1340_clock.c b/drivers/clk/spear/spear1340_clock.c index 9d0b3949db30..fe835c1845fe 100644 --- a/drivers/clk/spear/spear1340_clock.c +++ b/drivers/clk/spear/spear1340_clock.c @@ -473,9 +473,9 @@ void __init spear1340_clk_init(void __iomem *misc_base) /* clock derived from 24 or 25 MHz osc clk */ /* vco-pll */ clk = clk_register_mux(NULL, "vco1_mclk", vco_parents, - ARRAY_SIZE(vco_parents), 0, SPEAR1340_PLL_CFG, - SPEAR1340_PLL1_CLK_SHIFT, SPEAR1340_PLL_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1340_PLL_CFG, SPEAR1340_PLL1_CLK_SHIFT, + SPEAR1340_PLL_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "vco1_mclk", NULL); clk = clk_register_vco_pll("vco1_clk", "pll1_clk", NULL, "vco1_mclk", 0, SPEAR1340_PLL1_CTR, SPEAR1340_PLL1_FRQ, pll_rtbl, @@ -484,9 +484,9 @@ void __init spear1340_clk_init(void __iomem *misc_base) clk_register_clkdev(clk1, "pll1_clk", NULL); clk = clk_register_mux(NULL, "vco2_mclk", vco_parents, - ARRAY_SIZE(vco_parents), 0, SPEAR1340_PLL_CFG, - SPEAR1340_PLL2_CLK_SHIFT, SPEAR1340_PLL_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1340_PLL_CFG, SPEAR1340_PLL2_CLK_SHIFT, + SPEAR1340_PLL_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "vco2_mclk", NULL); clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL, "vco2_mclk", 0, SPEAR1340_PLL2_CTR, SPEAR1340_PLL2_FRQ, pll_rtbl, @@ -495,9 +495,9 @@ void __init spear1340_clk_init(void __iomem *misc_base) clk_register_clkdev(clk1, "pll2_clk", NULL); clk = clk_register_mux(NULL, "vco3_mclk", vco_parents, - ARRAY_SIZE(vco_parents), 0, SPEAR1340_PLL_CFG, - SPEAR1340_PLL3_CLK_SHIFT, SPEAR1340_PLL_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1340_PLL_CFG, SPEAR1340_PLL3_CLK_SHIFT, + SPEAR1340_PLL_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "vco3_mclk", NULL); clk = clk_register_vco_pll("vco3_clk", "pll3_clk", NULL, "vco3_mclk", 0, SPEAR1340_PLL3_CTR, SPEAR1340_PLL3_FRQ, pll_rtbl, @@ -561,8 +561,8 @@ void __init spear1340_clk_init(void __iomem *misc_base) clk_register_clkdev(clk, "amba_syn_clk", NULL); clk = clk_register_mux(NULL, "sys_mclk", sys_parents, - ARRAY_SIZE(sys_parents), 0, SPEAR1340_SYS_CLK_CTRL, - SPEAR1340_SCLK_SRC_SEL_SHIFT, + ARRAY_SIZE(sys_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1340_SYS_CLK_CTRL, SPEAR1340_SCLK_SRC_SEL_SHIFT, SPEAR1340_SCLK_SRC_SEL_MASK, 0, &_lock); clk_register_clkdev(clk, "sys_mclk", NULL); @@ -583,8 +583,8 @@ void __init spear1340_clk_init(void __iomem *misc_base) clk_register_clkdev(clk, NULL, "smp_twd"); clk = clk_register_mux(NULL, "ahb_clk", ahb_parents, - ARRAY_SIZE(ahb_parents), 0, SPEAR1340_SYS_CLK_CTRL, - SPEAR1340_HCLK_SRC_SEL_SHIFT, + ARRAY_SIZE(ahb_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1340_SYS_CLK_CTRL, SPEAR1340_HCLK_SRC_SEL_SHIFT, SPEAR1340_HCLK_SRC_SEL_MASK, 0, &_lock); clk_register_clkdev(clk, "ahb_clk", NULL); @@ -594,9 +594,9 @@ void __init spear1340_clk_init(void __iomem *misc_base) /* gpt clocks */ clk = clk_register_mux(NULL, "gpt0_mclk", gpt_parents, - ARRAY_SIZE(gpt_parents), 0, SPEAR1340_PERIP_CLK_CFG, - SPEAR1340_GPT0_CLK_SHIFT, SPEAR1340_GPT_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GPT0_CLK_SHIFT, + SPEAR1340_GPT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gpt0_mclk", NULL); clk = clk_register_gate(NULL, "gpt0_clk", "gpt0_mclk", 0, SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_GPT0_CLK_ENB, 0, @@ -604,9 +604,9 @@ void __init spear1340_clk_init(void __iomem *misc_base) clk_register_clkdev(clk, NULL, "gpt0"); clk = clk_register_mux(NULL, "gpt1_mclk", gpt_parents, - ARRAY_SIZE(gpt_parents), 0, SPEAR1340_PERIP_CLK_CFG, - SPEAR1340_GPT1_CLK_SHIFT, SPEAR1340_GPT_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GPT1_CLK_SHIFT, + SPEAR1340_GPT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gpt1_mclk", NULL); clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk", 0, SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_GPT1_CLK_ENB, 0, @@ -614,9 +614,9 @@ void __init spear1340_clk_init(void __iomem *misc_base) clk_register_clkdev(clk, NULL, "gpt1"); clk = clk_register_mux(NULL, "gpt2_mclk", gpt_parents, - ARRAY_SIZE(gpt_parents), 0, SPEAR1340_PERIP_CLK_CFG, - SPEAR1340_GPT2_CLK_SHIFT, SPEAR1340_GPT_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GPT2_CLK_SHIFT, + SPEAR1340_GPT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gpt2_mclk", NULL); clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk", 0, SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_GPT2_CLK_ENB, 0, @@ -624,9 +624,9 @@ void __init spear1340_clk_init(void __iomem *misc_base) clk_register_clkdev(clk, NULL, "gpt2"); clk = clk_register_mux(NULL, "gpt3_mclk", gpt_parents, - ARRAY_SIZE(gpt_parents), 0, SPEAR1340_PERIP_CLK_CFG, - SPEAR1340_GPT3_CLK_SHIFT, SPEAR1340_GPT_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GPT3_CLK_SHIFT, + SPEAR1340_GPT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gpt3_mclk", NULL); clk = clk_register_gate(NULL, "gpt3_clk", "gpt3_mclk", 0, SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_GPT3_CLK_ENB, 0, @@ -641,7 +641,8 @@ void __init spear1340_clk_init(void __iomem *misc_base) clk_register_clkdev(clk1, "uart0_syn_gclk", NULL); clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents, - ARRAY_SIZE(uart0_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uart0_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR1340_PERIP_CLK_CFG, SPEAR1340_UART0_CLK_SHIFT, SPEAR1340_UART_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "uart0_mclk", NULL); @@ -658,9 +659,9 @@ void __init spear1340_clk_init(void __iomem *misc_base) clk_register_clkdev(clk1, "uart1_syn_gclk", NULL); clk = clk_register_mux(NULL, "uart1_mclk", uart1_parents, - ARRAY_SIZE(uart1_parents), 0, SPEAR1340_PERIP_CLK_CFG, - SPEAR1340_UART1_CLK_SHIFT, SPEAR1340_UART_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(uart1_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1340_PERIP_CLK_CFG, SPEAR1340_UART1_CLK_SHIFT, + SPEAR1340_UART_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "uart1_mclk", NULL); clk = clk_register_gate(NULL, "uart1_clk", "uart1_mclk", 0, @@ -698,7 +699,8 @@ void __init spear1340_clk_init(void __iomem *misc_base) clk_register_clkdev(clk1, "c3_syn_gclk", NULL); clk = clk_register_mux(NULL, "c3_mclk", c3_parents, - ARRAY_SIZE(c3_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(c3_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR1340_PERIP_CLK_CFG, SPEAR1340_C3_CLK_SHIFT, SPEAR1340_C3_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "c3_mclk", NULL); @@ -710,8 +712,8 @@ void __init spear1340_clk_init(void __iomem *misc_base) /* gmac */ clk = clk_register_mux(NULL, "phy_input_mclk", gmac_phy_input_parents, - ARRAY_SIZE(gmac_phy_input_parents), 0, - SPEAR1340_GMAC_CLK_CFG, + ARRAY_SIZE(gmac_phy_input_parents), + CLK_SET_RATE_NO_REPARENT, SPEAR1340_GMAC_CLK_CFG, SPEAR1340_GMAC_PHY_INPUT_CLK_SHIFT, SPEAR1340_GMAC_PHY_INPUT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "phy_input_mclk", NULL); @@ -723,15 +725,16 @@ void __init spear1340_clk_init(void __iomem *misc_base) clk_register_clkdev(clk1, "phy_syn_gclk", NULL); clk = clk_register_mux(NULL, "phy_mclk", gmac_phy_parents, - ARRAY_SIZE(gmac_phy_parents), 0, + ARRAY_SIZE(gmac_phy_parents), CLK_SET_RATE_NO_REPARENT, SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GMAC_PHY_CLK_SHIFT, SPEAR1340_GMAC_PHY_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "stmmacphy.0", NULL); /* clcd */ clk = clk_register_mux(NULL, "clcd_syn_mclk", clcd_synth_parents, - ARRAY_SIZE(clcd_synth_parents), 0, - SPEAR1340_CLCD_CLK_SYNT, SPEAR1340_CLCD_SYNT_CLK_SHIFT, + ARRAY_SIZE(clcd_synth_parents), + CLK_SET_RATE_NO_REPARENT, SPEAR1340_CLCD_CLK_SYNT, + SPEAR1340_CLCD_SYNT_CLK_SHIFT, SPEAR1340_CLCD_SYNT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "clcd_syn_mclk", NULL); @@ -741,7 +744,8 @@ void __init spear1340_clk_init(void __iomem *misc_base) clk_register_clkdev(clk, "clcd_syn_clk", NULL); clk = clk_register_mux(NULL, "clcd_pixel_mclk", clcd_pixel_parents, - ARRAY_SIZE(clcd_pixel_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(clcd_pixel_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR1340_PERIP_CLK_CFG, SPEAR1340_CLCD_CLK_SHIFT, SPEAR1340_CLCD_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "clcd_pixel_mclk", NULL); @@ -753,9 +757,9 @@ void __init spear1340_clk_init(void __iomem *misc_base) /* i2s */ clk = clk_register_mux(NULL, "i2s_src_mclk", i2s_src_parents, - ARRAY_SIZE(i2s_src_parents), 0, SPEAR1340_I2S_CLK_CFG, - SPEAR1340_I2S_SRC_CLK_SHIFT, SPEAR1340_I2S_SRC_CLK_MASK, - 0, &_lock); + ARRAY_SIZE(i2s_src_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR1340_I2S_CLK_CFG, SPEAR1340_I2S_SRC_CLK_SHIFT, + SPEAR1340_I2S_SRC_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "i2s_src_mclk", NULL); clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mclk", @@ -765,7 +769,8 @@ void __init spear1340_clk_init(void __iomem *misc_base) clk_register_clkdev(clk, "i2s_prs1_clk", NULL); clk = clk_register_mux(NULL, "i2s_ref_mclk", i2s_ref_parents, - ARRAY_SIZE(i2s_ref_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(i2s_ref_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR1340_I2S_CLK_CFG, SPEAR1340_I2S_REF_SHIFT, SPEAR1340_I2S_REF_SEL_MASK, 0, &_lock); clk_register_clkdev(clk, "i2s_ref_mclk", NULL); @@ -891,13 +896,15 @@ void __init spear1340_clk_init(void __iomem *misc_base) /* RAS clks */ clk = clk_register_mux(NULL, "gen_syn0_1_mclk", gen_synth0_1_parents, - ARRAY_SIZE(gen_synth0_1_parents), 0, SPEAR1340_PLL_CFG, + ARRAY_SIZE(gen_synth0_1_parents), + CLK_SET_RATE_NO_REPARENT, SPEAR1340_PLL_CFG, SPEAR1340_GEN_SYNT0_1_CLK_SHIFT, SPEAR1340_GEN_SYNT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gen_syn0_1_mclk", NULL); clk = clk_register_mux(NULL, "gen_syn2_3_mclk", gen_synth2_3_parents, - ARRAY_SIZE(gen_synth2_3_parents), 0, SPEAR1340_PLL_CFG, + ARRAY_SIZE(gen_synth2_3_parents), + CLK_SET_RATE_NO_REPARENT, SPEAR1340_PLL_CFG, SPEAR1340_GEN_SYNT2_3_CLK_SHIFT, SPEAR1340_GEN_SYNT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gen_syn2_3_mclk", NULL); @@ -938,7 +945,8 @@ void __init spear1340_clk_init(void __iomem *misc_base) clk_register_clkdev(clk, NULL, "spear_cec.1"); clk = clk_register_mux(NULL, "spdif_out_mclk", spdif_out_parents, - ARRAY_SIZE(spdif_out_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(spdif_out_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR1340_PERIP_CLK_CFG, SPEAR1340_SPDIF_OUT_CLK_SHIFT, SPEAR1340_SPDIF_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "spdif_out_mclk", NULL); @@ -949,7 +957,8 @@ void __init spear1340_clk_init(void __iomem *misc_base) clk_register_clkdev(clk, NULL, "d0000000.spdif-out"); clk = clk_register_mux(NULL, "spdif_in_mclk", spdif_in_parents, - ARRAY_SIZE(spdif_in_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(spdif_in_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR1340_PERIP_CLK_CFG, SPEAR1340_SPDIF_IN_CLK_SHIFT, SPEAR1340_SPDIF_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "spdif_in_mclk", NULL); diff --git a/drivers/clk/spear/spear3xx_clock.c b/drivers/clk/spear/spear3xx_clock.c index 080c3c5e33f6..c2d204315546 100644 --- a/drivers/clk/spear/spear3xx_clock.c +++ b/drivers/clk/spear/spear3xx_clock.c @@ -294,7 +294,8 @@ static void __init spear320_clk_init(void __iomem *soc_config_base) clk_register_clkdev(clk, NULL, "a9400000.i2s"); clk = clk_register_mux(NULL, "i2s_ref_clk", i2s_ref_parents, - ARRAY_SIZE(i2s_ref_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(i2s_ref_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR320_CONTROL_REG, I2S_REF_PCLK_SHIFT, I2S_REF_PCLK_MASK, 0, &_lock); clk_register_clkdev(clk, "i2s_ref_clk", NULL); @@ -313,57 +314,66 @@ static void __init spear320_clk_init(void __iomem *soc_config_base) clk_register_clkdev(clk, "hclk", "ab000000.eth"); clk = clk_register_mux(NULL, "rs485_clk", uartx_parents, - ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uartx_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR320_EXT_CTRL_REG, SPEAR320_RS485_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0, &_lock); clk_register_clkdev(clk, NULL, "a9300000.serial"); clk = clk_register_mux(NULL, "sdhci_clk", sdhci_parents, - ARRAY_SIZE(sdhci_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(sdhci_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR320_CONTROL_REG, SDHCI_PCLK_SHIFT, SDHCI_PCLK_MASK, 0, &_lock); clk_register_clkdev(clk, NULL, "70000000.sdhci"); clk = clk_register_mux(NULL, "smii_pclk", smii0_parents, - ARRAY_SIZE(smii0_parents), 0, SPEAR320_CONTROL_REG, - SMII_PCLK_SHIFT, SMII_PCLK_MASK, 0, &_lock); + ARRAY_SIZE(smii0_parents), CLK_SET_RATE_NO_REPARENT, + SPEAR320_CONTROL_REG, SMII_PCLK_SHIFT, SMII_PCLK_MASK, + 0, &_lock); clk_register_clkdev(clk, NULL, "smii_pclk"); clk = clk_register_fixed_factor(NULL, "smii_clk", "smii_pclk", 0, 1, 1); clk_register_clkdev(clk, NULL, "smii"); clk = clk_register_mux(NULL, "uart1_clk", uartx_parents, - ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uartx_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR320_CONTROL_REG, UART1_PCLK_SHIFT, UART1_PCLK_MASK, 0, &_lock); clk_register_clkdev(clk, NULL, "a3000000.serial"); clk = clk_register_mux(NULL, "uart2_clk", uartx_parents, - ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uartx_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR320_EXT_CTRL_REG, SPEAR320_UART2_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0, &_lock); clk_register_clkdev(clk, NULL, "a4000000.serial"); clk = clk_register_mux(NULL, "uart3_clk", uartx_parents, - ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uartx_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR320_EXT_CTRL_REG, SPEAR320_UART3_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0, &_lock); clk_register_clkdev(clk, NULL, "a9100000.serial"); clk = clk_register_mux(NULL, "uart4_clk", uartx_parents, - ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uartx_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR320_EXT_CTRL_REG, SPEAR320_UART4_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0, &_lock); clk_register_clkdev(clk, NULL, "a9200000.serial"); clk = clk_register_mux(NULL, "uart5_clk", uartx_parents, - ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uartx_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR320_EXT_CTRL_REG, SPEAR320_UART5_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0, &_lock); clk_register_clkdev(clk, NULL, "60000000.serial"); clk = clk_register_mux(NULL, "uart6_clk", uartx_parents, - ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uartx_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, SPEAR320_EXT_CTRL_REG, SPEAR320_UART6_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0, &_lock); clk_register_clkdev(clk, NULL, "60100000.serial"); @@ -427,7 +437,8 @@ void __init spear3xx_clk_init(void __iomem *misc_base, void __iomem *soc_config_ clk_register_clkdev(clk1, "uart_syn_gclk", NULL); clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents, - ARRAY_SIZE(uart0_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(uart0_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, PERIP_CLK_CFG, UART_CLK_SHIFT, UART_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "uart0_mclk", NULL); @@ -444,7 +455,8 @@ void __init spear3xx_clk_init(void __iomem *misc_base, void __iomem *soc_config_ clk_register_clkdev(clk1, "firda_syn_gclk", NULL); clk = clk_register_mux(NULL, "firda_mclk", firda_parents, - ARRAY_SIZE(firda_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(firda_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, PERIP_CLK_CFG, FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "firda_mclk", NULL); @@ -458,14 +470,16 @@ void __init spear3xx_clk_init(void __iomem *misc_base, void __iomem *soc_config_ clk_register_gpt("gpt0_syn_clk", "pll1_clk", 0, PRSC0_CLK_CFG, gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock); clk = clk_register_mux(NULL, "gpt0_clk", gpt0_parents, - ARRAY_SIZE(gpt0_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(gpt0_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, PERIP_CLK_CFG, GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, NULL, "gpt0"); clk_register_gpt("gpt1_syn_clk", "pll1_clk", 0, PRSC1_CLK_CFG, gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock); clk = clk_register_mux(NULL, "gpt1_mclk", gpt1_parents, - ARRAY_SIZE(gpt1_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(gpt1_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, PERIP_CLK_CFG, GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gpt1_mclk", NULL); clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk", @@ -476,7 +490,8 @@ void __init spear3xx_clk_init(void __iomem *misc_base, void __iomem *soc_config_ clk_register_gpt("gpt2_syn_clk", "pll1_clk", 0, PRSC2_CLK_CFG, gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock); clk = clk_register_mux(NULL, "gpt2_mclk", gpt2_parents, - ARRAY_SIZE(gpt2_parents), CLK_SET_RATE_PARENT, + ARRAY_SIZE(gpt2_parents), + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, PERIP_CLK_CFG, GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gpt2_mclk", NULL); clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk", @@ -498,9 +513,9 @@ void __init spear3xx_clk_init(void __iomem *misc_base, void __iomem *soc_config_ clk_register_clkdev(clk1, "gen1_syn_gclk", NULL); clk = clk_register_mux(NULL, "gen2_3_par_clk", gen2_3_parents, - ARRAY_SIZE(gen2_3_parents), 0, CORE_CLK_CFG, - GEN_SYNTH2_3_CLK_SHIFT, GEN_SYNTH2_3_CLK_MASK, 0, - &_lock); + ARRAY_SIZE(gen2_3_parents), CLK_SET_RATE_NO_REPARENT, + CORE_CLK_CFG, GEN_SYNTH2_3_CLK_SHIFT, + GEN_SYNTH2_3_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gen2_3_par_clk", NULL); clk = clk_register_aux("gen2_syn_clk", "gen2_syn_gclk", @@ -540,8 +555,8 @@ void __init spear3xx_clk_init(void __iomem *misc_base, void __iomem *soc_config_ clk_register_clkdev(clk, "ahbmult2_clk", NULL); clk = clk_register_mux(NULL, "ddr_clk", ddr_parents, - ARRAY_SIZE(ddr_parents), 0, PLL_CLK_CFG, MCTR_CLK_SHIFT, - MCTR_CLK_MASK, 0, &_lock); + ARRAY_SIZE(ddr_parents), CLK_SET_RATE_NO_REPARENT, + PLL_CLK_CFG, MCTR_CLK_SHIFT, MCTR_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "ddr_clk", NULL); clk = clk_register_divider(NULL, "apb_clk", "ahb_clk", diff --git a/drivers/clk/spear/spear6xx_clock.c b/drivers/clk/spear/spear6xx_clock.c index 9406f2426d64..4f649c9cb094 100644 --- a/drivers/clk/spear/spear6xx_clock.c +++ b/drivers/clk/spear/spear6xx_clock.c @@ -169,8 +169,9 @@ void __init spear6xx_clk_init(void __iomem *misc_base) clk_register_clkdev(clk1, "uart_syn_gclk", NULL); clk = clk_register_mux(NULL, "uart_mclk", uart_parents, - ARRAY_SIZE(uart_parents), 0, PERIP_CLK_CFG, - UART_CLK_SHIFT, UART_CLK_MASK, 0, &_lock); + ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT, + PERIP_CLK_CFG, UART_CLK_SHIFT, UART_CLK_MASK, 0, + &_lock); clk_register_clkdev(clk, "uart_mclk", NULL); clk = clk_register_gate(NULL, "uart0", "uart_mclk", 0, PERIP1_CLK_ENB, @@ -188,8 +189,9 @@ void __init spear6xx_clk_init(void __iomem *misc_base) clk_register_clkdev(clk1, "firda_syn_gclk", NULL); clk = clk_register_mux(NULL, "firda_mclk", firda_parents, - ARRAY_SIZE(firda_parents), 0, PERIP_CLK_CFG, - FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0, &_lock); + ARRAY_SIZE(firda_parents), CLK_SET_RATE_NO_REPARENT, + PERIP_CLK_CFG, FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0, + &_lock); clk_register_clkdev(clk, "firda_mclk", NULL); clk = clk_register_gate(NULL, "firda_clk", "firda_mclk", 0, @@ -203,8 +205,9 @@ void __init spear6xx_clk_init(void __iomem *misc_base) clk_register_clkdev(clk1, "clcd_syn_gclk", NULL); clk = clk_register_mux(NULL, "clcd_mclk", clcd_parents, - ARRAY_SIZE(clcd_parents), 0, PERIP_CLK_CFG, - CLCD_CLK_SHIFT, CLCD_CLK_MASK, 0, &_lock); + ARRAY_SIZE(clcd_parents), CLK_SET_RATE_NO_REPARENT, + PERIP_CLK_CFG, CLCD_CLK_SHIFT, CLCD_CLK_MASK, 0, + &_lock); clk_register_clkdev(clk, "clcd_mclk", NULL); clk = clk_register_gate(NULL, "clcd_clk", "clcd_mclk", 0, @@ -217,13 +220,13 @@ void __init spear6xx_clk_init(void __iomem *misc_base) clk_register_clkdev(clk, "gpt0_1_syn_clk", NULL); clk = clk_register_mux(NULL, "gpt0_mclk", gpt0_1_parents, - ARRAY_SIZE(gpt0_1_parents), 0, PERIP_CLK_CFG, - GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); + ARRAY_SIZE(gpt0_1_parents), CLK_SET_RATE_NO_REPARENT, + PERIP_CLK_CFG, GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, NULL, "gpt0"); clk = clk_register_mux(NULL, "gpt1_mclk", gpt0_1_parents, - ARRAY_SIZE(gpt0_1_parents), 0, PERIP_CLK_CFG, - GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); + ARRAY_SIZE(gpt0_1_parents), CLK_SET_RATE_NO_REPARENT, + PERIP_CLK_CFG, GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gpt1_mclk", NULL); clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk", 0, @@ -235,8 +238,8 @@ void __init spear6xx_clk_init(void __iomem *misc_base) clk_register_clkdev(clk, "gpt2_syn_clk", NULL); clk = clk_register_mux(NULL, "gpt2_mclk", gpt2_parents, - ARRAY_SIZE(gpt2_parents), 0, PERIP_CLK_CFG, - GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); + ARRAY_SIZE(gpt2_parents), CLK_SET_RATE_NO_REPARENT, + PERIP_CLK_CFG, GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gpt2_mclk", NULL); clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk", 0, @@ -248,8 +251,8 @@ void __init spear6xx_clk_init(void __iomem *misc_base) clk_register_clkdev(clk, "gpt3_syn_clk", NULL); clk = clk_register_mux(NULL, "gpt3_mclk", gpt3_parents, - ARRAY_SIZE(gpt3_parents), 0, PERIP_CLK_CFG, - GPT3_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); + ARRAY_SIZE(gpt3_parents), CLK_SET_RATE_NO_REPARENT, + PERIP_CLK_CFG, GPT3_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "gpt3_mclk", NULL); clk = clk_register_gate(NULL, "gpt3_clk", "gpt3_mclk", 0, @@ -277,8 +280,8 @@ void __init spear6xx_clk_init(void __iomem *misc_base) clk_register_clkdev(clk, "ahbmult2_clk", NULL); clk = clk_register_mux(NULL, "ddr_clk", ddr_parents, - ARRAY_SIZE(ddr_parents), 0, PLL_CLK_CFG, MCTR_CLK_SHIFT, - MCTR_CLK_MASK, 0, &_lock); + ARRAY_SIZE(ddr_parents), CLK_SET_RATE_NO_REPARENT, + PLL_CLK_CFG, MCTR_CLK_SHIFT, MCTR_CLK_MASK, 0, &_lock); clk_register_clkdev(clk, "ddr_clk", NULL); clk = clk_register_divider(NULL, "apb_clk", "ahb_clk", diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 02e440beb3d3..323830465d13 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -261,7 +261,8 @@ static void __init sunxi_mux_clk_setup(struct device_node *node, while (i < 5 && (parents[i] = of_clk_get_parent_name(node, i)) != NULL) i++; - clk = clk_register_mux(NULL, clk_name, parents, i, 0, reg, + clk = clk_register_mux(NULL, clk_name, parents, i, + CLK_SET_RATE_NO_REPARENT, reg, data->shift, SUNXI_MUX_GATE_WIDTH, 0, &clk_lock); diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 2d3b3dc5c1ec..be40856a6fa4 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -1558,7 +1558,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) /* audio0 */ clk = clk_register_mux(NULL, "audio0_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), 0, + ARRAY_SIZE(mux_audio_sync_clk), + CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_I2S0, 0, 3, 0, NULL); clks[audio0_mux] = clk; @@ -1570,7 +1571,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) /* audio1 */ clk = clk_register_mux(NULL, "audio1_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), 0, + ARRAY_SIZE(mux_audio_sync_clk), + CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_I2S1, 0, 3, 0, NULL); clks[audio1_mux] = clk; @@ -1582,7 +1584,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) /* audio2 */ clk = clk_register_mux(NULL, "audio2_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), 0, + ARRAY_SIZE(mux_audio_sync_clk), + CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_I2S2, 0, 3, 0, NULL); clks[audio2_mux] = clk; @@ -1594,7 +1597,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) /* audio3 */ clk = clk_register_mux(NULL, "audio3_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), 0, + ARRAY_SIZE(mux_audio_sync_clk), + CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_I2S3, 0, 3, 0, NULL); clks[audio3_mux] = clk; @@ -1606,7 +1610,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) /* audio4 */ clk = clk_register_mux(NULL, "audio4_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), 0, + ARRAY_SIZE(mux_audio_sync_clk), + CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_I2S4, 0, 3, 0, NULL); clks[audio4_mux] = clk; @@ -1618,7 +1623,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base) /* spdif */ clk = clk_register_mux(NULL, "spdif_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), 0, + ARRAY_SIZE(mux_audio_sync_clk), + CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_SPDIF, 0, 3, 0, NULL); clks[spdif_mux] = clk; @@ -1713,7 +1719,8 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base) /* clk_out_1 */ clk = clk_register_mux(NULL, "clk_out_1_mux", clk_out1_parents, - ARRAY_SIZE(clk_out1_parents), 0, + ARRAY_SIZE(clk_out1_parents), + CLK_SET_RATE_NO_REPARENT, pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0, &clk_out_lock); clks[clk_out_1_mux] = clk; @@ -1725,7 +1732,8 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base) /* clk_out_2 */ clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents, - ARRAY_SIZE(clk_out2_parents), 0, + ARRAY_SIZE(clk_out2_parents), + CLK_SET_RATE_NO_REPARENT, pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0, &clk_out_lock); clks[clk_out_2_mux] = clk; @@ -1737,7 +1745,8 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base) /* clk_out_3 */ clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents, - ARRAY_SIZE(clk_out3_parents), 0, + ARRAY_SIZE(clk_out3_parents), + CLK_SET_RATE_NO_REPARENT, pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0, &clk_out_lock); clks[clk_out_3_mux] = clk; @@ -2055,7 +2064,8 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base) /* dsia */ clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0, - ARRAY_SIZE(mux_plld_out0_plld2_out0), 0, + ARRAY_SIZE(mux_plld_out0_plld2_out0), + CLK_SET_RATE_NO_REPARENT, clk_base + PLLD_BASE, 25, 1, 0, &pll_d_lock); clks[dsia_mux] = clk; clk = tegra_clk_register_periph_gate("dsia", "dsia_mux", 0, clk_base, @@ -2065,7 +2075,8 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base) /* dsib */ clk = clk_register_mux(NULL, "dsib_mux", mux_plld_out0_plld2_out0, - ARRAY_SIZE(mux_plld_out0_plld2_out0), 0, + ARRAY_SIZE(mux_plld_out0_plld2_out0), + CLK_SET_RATE_NO_REPARENT, clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock); clks[dsib_mux] = clk; clk = tegra_clk_register_periph_gate("dsib", "dsib_mux", 0, clk_base, @@ -2102,7 +2113,8 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base) /* emc */ clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, - ARRAY_SIZE(mux_pllmcp_clkm), 0, + ARRAY_SIZE(mux_pllmcp_clkm), + CLK_SET_RATE_NO_REPARENT, clk_base + CLK_SOURCE_EMC, 29, 3, 0, NULL); clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index ebe94ce0f647..056f649d0d89 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -778,7 +778,8 @@ static void __init tegra20_audio_clk_init(void) /* audio */ clk = clk_register_mux(NULL, "audio_mux", audio_parents, - ARRAY_SIZE(audio_parents), 0, + ARRAY_SIZE(audio_parents), + CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK, 0, 3, 0, NULL); clk = clk_register_gate(NULL, "audio", "audio_mux", 0, clk_base + AUDIO_SYNC_CLK, 4, @@ -941,7 +942,8 @@ static void __init tegra20_periph_clk_init(void) /* emc */ clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, - ARRAY_SIZE(mux_pllmcp_clkm), 0, + ARRAY_SIZE(mux_pllmcp_clkm), + CLK_SET_RATE_NO_REPARENT, clk_base + CLK_SOURCE_EMC, 30, 2, 0, NULL); clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0, diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index ab35040231cd..b09ebf64cdc8 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -1026,7 +1026,8 @@ static void __init tegra30_pll_init(void) /* PLLE */ clk = clk_register_mux(NULL, "pll_e_mux", pll_e_parents, - ARRAY_SIZE(pll_e_parents), 0, + ARRAY_SIZE(pll_e_parents), + CLK_SET_RATE_NO_REPARENT, clk_base + PLLE_AUX, 2, 1, 0, NULL); clk = tegra_clk_register_plle("pll_e", "pll_e_mux", clk_base, pmc_base, CLK_GET_RATE_NOCACHE, 100000000, &pll_e_params, @@ -1086,7 +1087,8 @@ static void __init tegra30_audio_clk_init(void) /* audio0 */ clk = clk_register_mux(NULL, "audio0_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), 0, + ARRAY_SIZE(mux_audio_sync_clk), + CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_I2S0, 0, 3, 0, NULL); clk = clk_register_gate(NULL, "audio0", "audio0_mux", 0, clk_base + AUDIO_SYNC_CLK_I2S0, 4, @@ -1096,7 +1098,8 @@ static void __init tegra30_audio_clk_init(void) /* audio1 */ clk = clk_register_mux(NULL, "audio1_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), 0, + ARRAY_SIZE(mux_audio_sync_clk), + CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_I2S1, 0, 3, 0, NULL); clk = clk_register_gate(NULL, "audio1", "audio1_mux", 0, clk_base + AUDIO_SYNC_CLK_I2S1, 4, @@ -1106,7 +1109,8 @@ static void __init tegra30_audio_clk_init(void) /* audio2 */ clk = clk_register_mux(NULL, "audio2_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), 0, + ARRAY_SIZE(mux_audio_sync_clk), + CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_I2S2, 0, 3, 0, NULL); clk = clk_register_gate(NULL, "audio2", "audio2_mux", 0, clk_base + AUDIO_SYNC_CLK_I2S2, 4, @@ -1116,7 +1120,8 @@ static void __init tegra30_audio_clk_init(void) /* audio3 */ clk = clk_register_mux(NULL, "audio3_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), 0, + ARRAY_SIZE(mux_audio_sync_clk), + CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_I2S3, 0, 3, 0, NULL); clk = clk_register_gate(NULL, "audio3", "audio3_mux", 0, clk_base + AUDIO_SYNC_CLK_I2S3, 4, @@ -1126,7 +1131,8 @@ static void __init tegra30_audio_clk_init(void) /* audio4 */ clk = clk_register_mux(NULL, "audio4_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), 0, + ARRAY_SIZE(mux_audio_sync_clk), + CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_I2S4, 0, 3, 0, NULL); clk = clk_register_gate(NULL, "audio4", "audio4_mux", 0, clk_base + AUDIO_SYNC_CLK_I2S4, 4, @@ -1136,7 +1142,8 @@ static void __init tegra30_audio_clk_init(void) /* spdif */ clk = clk_register_mux(NULL, "spdif_mux", mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), 0, + ARRAY_SIZE(mux_audio_sync_clk), + CLK_SET_RATE_NO_REPARENT, clk_base + AUDIO_SYNC_CLK_SPDIF, 0, 3, 0, NULL); clk = clk_register_gate(NULL, "spdif", "spdif_mux", 0, clk_base + AUDIO_SYNC_CLK_SPDIF, 4, @@ -1229,7 +1236,8 @@ static void __init tegra30_pmc_clk_init(void) /* clk_out_1 */ clk = clk_register_mux(NULL, "clk_out_1_mux", clk_out1_parents, - ARRAY_SIZE(clk_out1_parents), 0, + ARRAY_SIZE(clk_out1_parents), + CLK_SET_RATE_NO_REPARENT, pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0, &clk_out_lock); clks[clk_out_1_mux] = clk; @@ -1241,7 +1249,8 @@ static void __init tegra30_pmc_clk_init(void) /* clk_out_2 */ clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents, - ARRAY_SIZE(clk_out2_parents), 0, + ARRAY_SIZE(clk_out2_parents), + CLK_SET_RATE_NO_REPARENT, pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0, &clk_out_lock); clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0, @@ -1252,7 +1261,8 @@ static void __init tegra30_pmc_clk_init(void) /* clk_out_3 */ clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents, - ARRAY_SIZE(clk_out3_parents), 0, + ARRAY_SIZE(clk_out3_parents), + CLK_SET_RATE_NO_REPARENT, pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0, &clk_out_lock); clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0, @@ -1679,7 +1689,8 @@ static void __init tegra30_periph_clk_init(void) /* emc */ clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, - ARRAY_SIZE(mux_pllmcp_clkm), 0, + ARRAY_SIZE(mux_pllmcp_clkm), + CLK_SET_RATE_NO_REPARENT, clk_base + CLK_SOURCE_EMC, 30, 2, 0, NULL); clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0, diff --git a/drivers/clk/versatile/clk-vexpress.c b/drivers/clk/versatile/clk-vexpress.c index a4a728d05092..2d5e1b4820e0 100644 --- a/drivers/clk/versatile/clk-vexpress.c +++ b/drivers/clk/versatile/clk-vexpress.c @@ -37,8 +37,8 @@ static void __init vexpress_sp810_init(void __iomem *base) snprintf(name, ARRAY_SIZE(name), "timerclken%d", i); vexpress_sp810_timerclken[i] = clk_register_mux(NULL, name, - parents, 2, 0, base + SCCTRL, - SCCTRL_TIMERENnSEL_SHIFT(i), 1, + parents, 2, CLK_SET_RATE_NO_REPARENT, + base + SCCTRL, SCCTRL_TIMERENnSEL_SHIFT(i), 1, 0, &vexpress_sp810_lock); if (WARN_ON(IS_ERR(vexpress_sp810_timerclken[i]))) diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c index 5c205b60a82a..e05c9e3f1385 100644 --- a/drivers/clk/zynq/clkc.c +++ b/drivers/clk/zynq/clkc.c @@ -124,8 +124,9 @@ static void __init zynq_clk_register_fclk(enum zynq_clk fclk, div0_name = kasprintf(GFP_KERNEL, "%s_div0", clk_name); div1_name = kasprintf(GFP_KERNEL, "%s_div1", clk_name); - clk = clk_register_mux(NULL, mux_name, parents, 4, 0, - fclk_ctrl_reg, 4, 2, 0, fclk_lock); + clk = clk_register_mux(NULL, mux_name, parents, 4, + CLK_SET_RATE_NO_REPARENT, fclk_ctrl_reg, 4, 2, 0, + fclk_lock); clk = clk_register_divider(NULL, div0_name, mux_name, 0, fclk_ctrl_reg, 8, 6, CLK_DIVIDER_ONE_BASED | @@ -167,8 +168,8 @@ static void __init zynq_clk_register_periph_clk(enum zynq_clk clk0, mux_name = kasprintf(GFP_KERNEL, "%s_mux", clk_name0); div_name = kasprintf(GFP_KERNEL, "%s_div", clk_name0); - clk = clk_register_mux(NULL, mux_name, parents, 4, 0, - clk_ctrl, 4, 2, 0, lock); + clk = clk_register_mux(NULL, mux_name, parents, 4, + CLK_SET_RATE_NO_REPARENT, clk_ctrl, 4, 2, 0, lock); clk = clk_register_divider(NULL, div_name, mux_name, 0, clk_ctrl, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, lock); @@ -235,25 +236,26 @@ static void __init zynq_clk_setup(struct device_node *np) clk = clk_register_zynq_pll("armpll_int", "ps_clk", SLCR_ARMPLL_CTRL, SLCR_PLL_STATUS, 0, &armpll_lock); clks[armpll] = clk_register_mux(NULL, clk_output_name[armpll], - armpll_parents, 2, 0, SLCR_ARMPLL_CTRL, 4, 1, 0, - &armpll_lock); + armpll_parents, 2, CLK_SET_RATE_NO_REPARENT, + SLCR_ARMPLL_CTRL, 4, 1, 0, &armpll_lock); clk = clk_register_zynq_pll("ddrpll_int", "ps_clk", SLCR_DDRPLL_CTRL, SLCR_PLL_STATUS, 1, &ddrpll_lock); clks[ddrpll] = clk_register_mux(NULL, clk_output_name[ddrpll], - ddrpll_parents, 2, 0, SLCR_DDRPLL_CTRL, 4, 1, 0, - &ddrpll_lock); + ddrpll_parents, 2, CLK_SET_RATE_NO_REPARENT, + SLCR_DDRPLL_CTRL, 4, 1, 0, &ddrpll_lock); clk = clk_register_zynq_pll("iopll_int", "ps_clk", SLCR_IOPLL_CTRL, SLCR_PLL_STATUS, 2, &iopll_lock); clks[iopll] = clk_register_mux(NULL, clk_output_name[iopll], - iopll_parents, 2, 0, SLCR_IOPLL_CTRL, 4, 1, 0, - &iopll_lock); + iopll_parents, 2, CLK_SET_RATE_NO_REPARENT, + SLCR_IOPLL_CTRL, 4, 1, 0, &iopll_lock); /* CPU clocks */ tmp = readl(SLCR_621_TRUE) & 1; - clk = clk_register_mux(NULL, "cpu_mux", cpu_parents, 4, 0, - SLCR_ARM_CLK_CTRL, 4, 2, 0, &armclk_lock); + clk = clk_register_mux(NULL, "cpu_mux", cpu_parents, 4, + CLK_SET_RATE_NO_REPARENT, SLCR_ARM_CLK_CTRL, 4, 2, 0, + &armclk_lock); clk = clk_register_divider(NULL, "cpu_div", "cpu_mux", 0, SLCR_ARM_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &armclk_lock); @@ -292,8 +294,9 @@ static void __init zynq_clk_setup(struct device_node *np) swdt_ext_clk_mux_parents[i + 1] = dummy_nm; } clks[swdt] = clk_register_mux(NULL, clk_output_name[swdt], - swdt_ext_clk_mux_parents, 2, CLK_SET_RATE_PARENT, - SLCR_SWDT_CLK_SEL, 0, 1, 0, &gem0clk_lock); + swdt_ext_clk_mux_parents, 2, CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT, SLCR_SWDT_CLK_SEL, 0, 1, 0, + &gem0clk_lock); /* DDR clocks */ clk = clk_register_divider(NULL, "ddr2x_div", "ddrpll", 0, @@ -355,8 +358,9 @@ static void __init zynq_clk_setup(struct device_node *np) gem0_mux_parents[i + 1] = of_clk_get_parent_name(np, idx); } - clk = clk_register_mux(NULL, "gem0_mux", periph_parents, 4, 0, - SLCR_GEM0_CLK_CTRL, 4, 2, 0, &gem0clk_lock); + clk = clk_register_mux(NULL, "gem0_mux", periph_parents, 4, + CLK_SET_RATE_NO_REPARENT, SLCR_GEM0_CLK_CTRL, 4, 2, 0, + &gem0clk_lock); clk = clk_register_divider(NULL, "gem0_div0", "gem0_mux", 0, SLCR_GEM0_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &gem0clk_lock); @@ -364,8 +368,9 @@ static void __init zynq_clk_setup(struct device_node *np) CLK_SET_RATE_PARENT, SLCR_GEM0_CLK_CTRL, 20, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &gem0clk_lock); - clk = clk_register_mux(NULL, "gem0_emio_mux", gem0_mux_parents, 2, 0, - SLCR_GEM0_CLK_CTRL, 6, 1, 0, &gem0clk_lock); + clk = clk_register_mux(NULL, "gem0_emio_mux", gem0_mux_parents, 2, + CLK_SET_RATE_NO_REPARENT, SLCR_GEM0_CLK_CTRL, 6, 1, 0, + &gem0clk_lock); clks[gem0] = clk_register_gate(NULL, clk_output_name[gem0], "gem0_emio_mux", CLK_SET_RATE_PARENT, SLCR_GEM0_CLK_CTRL, 0, 0, &gem0clk_lock); @@ -377,8 +382,9 @@ static void __init zynq_clk_setup(struct device_node *np) gem1_mux_parents[i + 1] = of_clk_get_parent_name(np, idx); } - clk = clk_register_mux(NULL, "gem1_mux", periph_parents, 4, 0, - SLCR_GEM1_CLK_CTRL, 4, 2, 0, &gem1clk_lock); + clk = clk_register_mux(NULL, "gem1_mux", periph_parents, 4, + CLK_SET_RATE_NO_REPARENT, SLCR_GEM1_CLK_CTRL, 4, 2, 0, + &gem1clk_lock); clk = clk_register_divider(NULL, "gem1_div0", "gem1_mux", 0, SLCR_GEM1_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &gem1clk_lock); @@ -386,8 +392,9 @@ static void __init zynq_clk_setup(struct device_node *np) CLK_SET_RATE_PARENT, SLCR_GEM1_CLK_CTRL, 20, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &gem1clk_lock); - clk = clk_register_mux(NULL, "gem1_emio_mux", gem1_mux_parents, 2, 0, - SLCR_GEM1_CLK_CTRL, 6, 1, 0, &gem1clk_lock); + clk = clk_register_mux(NULL, "gem1_emio_mux", gem1_mux_parents, 2, + CLK_SET_RATE_NO_REPARENT, SLCR_GEM1_CLK_CTRL, 6, 1, 0, + &gem1clk_lock); clks[gem1] = clk_register_gate(NULL, clk_output_name[gem1], "gem1_emio_mux", CLK_SET_RATE_PARENT, SLCR_GEM1_CLK_CTRL, 0, 0, &gem1clk_lock); @@ -406,8 +413,9 @@ static void __init zynq_clk_setup(struct device_node *np) can_mio_mux_parents[i] = dummy_nm; } kfree(clk_name); - clk = clk_register_mux(NULL, "can_mux", periph_parents, 4, 0, - SLCR_CAN_CLK_CTRL, 4, 2, 0, &canclk_lock); + clk = clk_register_mux(NULL, "can_mux", periph_parents, 4, + CLK_SET_RATE_NO_REPARENT, SLCR_CAN_CLK_CTRL, 4, 2, 0, + &canclk_lock); clk = clk_register_divider(NULL, "can_div0", "can_mux", 0, SLCR_CAN_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &canclk_lock); @@ -422,17 +430,21 @@ static void __init zynq_clk_setup(struct device_node *np) CLK_SET_RATE_PARENT, SLCR_CAN_CLK_CTRL, 1, 0, &canclk_lock); clk = clk_register_mux(NULL, "can0_mio_mux", - can_mio_mux_parents, 54, CLK_SET_RATE_PARENT, - SLCR_CAN_MIOCLK_CTRL, 0, 6, 0, &canmioclk_lock); + can_mio_mux_parents, 54, CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT, SLCR_CAN_MIOCLK_CTRL, 0, 6, 0, + &canmioclk_lock); clk = clk_register_mux(NULL, "can1_mio_mux", - can_mio_mux_parents, 54, CLK_SET_RATE_PARENT, - SLCR_CAN_MIOCLK_CTRL, 16, 6, 0, &canmioclk_lock); + can_mio_mux_parents, 54, CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT, SLCR_CAN_MIOCLK_CTRL, 16, 6, + 0, &canmioclk_lock); clks[can0] = clk_register_mux(NULL, clk_output_name[can0], - can0_mio_mux2_parents, 2, CLK_SET_RATE_PARENT, - SLCR_CAN_MIOCLK_CTRL, 6, 1, 0, &canmioclk_lock); + can0_mio_mux2_parents, 2, CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT, SLCR_CAN_MIOCLK_CTRL, 6, 1, 0, + &canmioclk_lock); clks[can1] = clk_register_mux(NULL, clk_output_name[can1], - can1_mio_mux2_parents, 2, CLK_SET_RATE_PARENT, - SLCR_CAN_MIOCLK_CTRL, 22, 1, 0, &canmioclk_lock); + can1_mio_mux2_parents, 2, CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT, SLCR_CAN_MIOCLK_CTRL, 22, 1, + 0, &canmioclk_lock); for (i = 0; i < ARRAY_SIZE(dbgtrc_emio_input_names); i++) { int idx = of_property_match_string(np, "clock-names", @@ -441,13 +453,15 @@ static void __init zynq_clk_setup(struct device_node *np) dbg_emio_mux_parents[i + 1] = of_clk_get_parent_name(np, idx); } - clk = clk_register_mux(NULL, "dbg_mux", periph_parents, 4, 0, - SLCR_DBG_CLK_CTRL, 4, 2, 0, &dbgclk_lock); + clk = clk_register_mux(NULL, "dbg_mux", periph_parents, 4, + CLK_SET_RATE_NO_REPARENT, SLCR_DBG_CLK_CTRL, 4, 2, 0, + &dbgclk_lock); clk = clk_register_divider(NULL, "dbg_div", "dbg_mux", 0, SLCR_DBG_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &dbgclk_lock); - clk = clk_register_mux(NULL, "dbg_emio_mux", dbg_emio_mux_parents, 2, 0, - SLCR_DBG_CLK_CTRL, 6, 1, 0, &dbgclk_lock); + clk = clk_register_mux(NULL, "dbg_emio_mux", dbg_emio_mux_parents, 2, + CLK_SET_RATE_NO_REPARENT, SLCR_DBG_CLK_CTRL, 6, 1, 0, + &dbgclk_lock); clks[dbg_trc] = clk_register_gate(NULL, clk_output_name[dbg_trc], "dbg_emio_mux", CLK_SET_RATE_PARENT, SLCR_DBG_CLK_CTRL, 0, 0, &dbgclk_lock); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 4f525b37c6fd..5c0bc3904c9b 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -27,6 +27,7 @@ #define CLK_IS_ROOT BIT(4) /* root clk, has no parent */ #define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */ #define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */ +#define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */ struct clk_hw; From e366fdd72529c545ccf327569ee250c1673be221 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 29 Jul 2013 12:25:02 +0100 Subject: [PATCH 051/102] clk: clk-mux: implement remuxing on set_rate Implement clk-mux remuxing if the CLK_SET_RATE_NO_REPARENT flag isn't set. This implements determine_rate for clk-mux to propagate to each parent and to choose the best one (like clk-divider this chooses the parent which provides the fastest rate <= the requested rate). The determine_rate op is implemented as a core helper function so that it can be easily used by more complex clocks which incorporate muxes. Signed-off-by: James Hogan Reviewed-by: Stephen Boyd Cc: Mike Turquette Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Mike Turquette --- drivers/clk/clk-mux.c | 1 + drivers/clk/clk.c | 49 ++++++++++++++++++++++++++++++++++++ include/linux/clk-provider.h | 3 +++ 3 files changed, 53 insertions(+) diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index b918dc370bd0..0811633fcc4d 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -104,6 +104,7 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index) const struct clk_ops clk_mux_ops = { .get_parent = clk_mux_get_parent, .set_parent = clk_mux_set_parent, + .determine_rate = __clk_mux_determine_rate, }; EXPORT_SYMBOL_GPL(clk_mux_ops); diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f33f1ccf1b2f..bc020372106b 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -692,6 +692,55 @@ struct clk *__clk_lookup(const char *name) return NULL; } +/* + * Helper for finding best parent to provide a given frequency. This can be used + * directly as a determine_rate callback (e.g. for a mux), or from a more + * complex clock that may combine a mux with other operations. + */ +long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *best_parent_rate, + struct clk **best_parent_p) +{ + struct clk *clk = hw->clk, *parent, *best_parent = NULL; + int i, num_parents; + unsigned long parent_rate, best = 0; + + /* if NO_REPARENT flag set, pass through to current parent */ + if (clk->flags & CLK_SET_RATE_NO_REPARENT) { + parent = clk->parent; + if (clk->flags & CLK_SET_RATE_PARENT) + best = __clk_round_rate(parent, rate); + else if (parent) + best = __clk_get_rate(parent); + else + best = __clk_get_rate(clk); + goto out; + } + + /* find the parent that can provide the fastest rate <= rate */ + num_parents = clk->num_parents; + for (i = 0; i < num_parents; i++) { + parent = clk_get_parent_by_index(clk, i); + if (!parent) + continue; + if (clk->flags & CLK_SET_RATE_PARENT) + parent_rate = __clk_round_rate(parent, rate); + else + parent_rate = __clk_get_rate(parent); + if (parent_rate <= rate && parent_rate > best) { + best_parent = parent; + best = parent_rate; + } + } + +out: + if (best_parent) + *best_parent_p = best_parent; + *best_parent_rate = best; + + return best; +} + /*** clk api ***/ void __clk_unprepare(struct clk *clk) diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 5c0bc3904c9b..1f0285b2f422 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -436,6 +436,9 @@ unsigned long __clk_get_flags(struct clk *clk); bool __clk_is_prepared(struct clk *clk); bool __clk_is_enabled(struct clk *clk); struct clk *__clk_lookup(const char *name); +long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *best_parent_rate, + struct clk **best_parent_p); /* * FIXME clock api without lock protection From 14924ba288921c536a72e71baeb14322ece44b39 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Fri, 19 Jul 2013 10:16:44 -0700 Subject: [PATCH 052/102] clk/zynq/pll: Fix documentation for PLL register function Signed-off-by: Soren Brinkmann Signed-off-by: Michal Simek --- drivers/clk/zynq/pll.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/clk/zynq/pll.c b/drivers/clk/zynq/pll.c index 47e307c25a7b..6daa7b6702ed 100644 --- a/drivers/clk/zynq/pll.c +++ b/drivers/clk/zynq/pll.c @@ -182,7 +182,13 @@ static const struct clk_ops zynq_pll_ops = { /** * clk_register_zynq_pll() - Register PLL with the clock framework - * @np Pointer to the DT device node + * @name PLL name + * @parent Parent clock name + * @pll_ctrl Pointer to PLL control register + * @pll_status Pointer to PLL status register + * @lock_index Bit index to this PLL's lock status bit in @pll_status + * @lock Register lock + * Returns handle to the registered clock. */ struct clk *clk_register_zynq_pll(const char *name, const char *parent, void __iomem *pll_ctrl, void __iomem *pll_status, u8 lock_index, From 353dc6c47d67c83f7cc20334f8deb251674e6864 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Fri, 19 Jul 2013 10:16:45 -0700 Subject: [PATCH 053/102] clk/zynq/pll: Use #defines for fbdiv min/max values Use more descriptive #defines for the minimum and maximum PLL feedback divider. Signed-off-by: Soren Brinkmann Signed-off-by: Michal Simek --- drivers/clk/zynq/pll.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/clk/zynq/pll.c b/drivers/clk/zynq/pll.c index 6daa7b6702ed..3226f54fa595 100644 --- a/drivers/clk/zynq/pll.c +++ b/drivers/clk/zynq/pll.c @@ -50,6 +50,9 @@ struct zynq_pll { #define PLLCTRL_RESET_MASK 1 #define PLLCTRL_RESET_SHIFT 0 +#define PLL_FBDIV_MIN 13 +#define PLL_FBDIV_MAX 66 + /** * zynq_pll_round_rate() - Round a clock frequency * @hw: Handle between common and hardware-specific interfaces @@ -63,10 +66,10 @@ static long zynq_pll_round_rate(struct clk_hw *hw, unsigned long rate, u32 fbdiv; fbdiv = DIV_ROUND_CLOSEST(rate, *prate); - if (fbdiv < 13) - fbdiv = 13; - else if (fbdiv > 66) - fbdiv = 66; + if (fbdiv < PLL_FBDIV_MIN) + fbdiv = PLL_FBDIV_MIN; + else if (fbdiv > PLL_FBDIV_MAX) + fbdiv = PLL_FBDIV_MAX; return *prate * fbdiv; } From 89ac8d7ae1cde0f8c7a2f85c2e3b475d54aa9163 Mon Sep 17 00:00:00 2001 From: Mike Turquette Date: Wed, 21 Aug 2013 23:58:09 -0700 Subject: [PATCH 054/102] clk: handle NULL struct clk gracefully At some point changes to clk_set_rate and clk_set_parent introduced a bug whereby NULL struct clk pointers were treated as an error. This is in violation of the API in include/linux/clk.h. Reintroduce graceful handling of NULL clk's by bailing from clk_set_rate and clk_set_parent with return codes of zero. Signed-off-by: Mike Turquette --- drivers/clk/clk.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index bc020372106b..7c4376289865 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1428,6 +1428,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate) struct clk *top, *fail_clk; int ret = 0; + if (!clk) + return 0; + /* prevent racing with updates to the clock topology */ clk_prepare_lock(); @@ -1567,7 +1570,10 @@ int clk_set_parent(struct clk *clk, struct clk *parent) u8 p_index = 0; unsigned long p_rate = 0; - if (!clk || !clk->ops) + if (!clk) + return 0; + + if (!clk->ops) return -EINVAL; /* verify ops for for multi-parent clks */ From f98d007d332b819b7777bf280a07fc3d2dfe2f7a Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Fri, 23 Aug 2013 10:34:01 +0800 Subject: [PATCH 055/102] clk: mvebu: add missing iounmap Add missing iounmap to setup error path. Signed-off-by: Jisheng Zhang Signed-off-by: Mike Turquette --- drivers/clk/mvebu/clk-cpu.c | 4 +++- drivers/clk/mvebu/common.c | 18 ++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c index b0fbc0715491..1466865b0743 100644 --- a/drivers/clk/mvebu/clk-cpu.c +++ b/drivers/clk/mvebu/clk-cpu.c @@ -119,7 +119,7 @@ void __init of_cpu_clk_setup(struct device_node *node) cpuclk = kzalloc(ncpus * sizeof(*cpuclk), GFP_KERNEL); if (WARN_ON(!cpuclk)) - return; + goto cpuclk_out; clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL); if (WARN_ON(!clks)) @@ -170,6 +170,8 @@ bail_out: kfree(cpuclk[ncpus].clk_name); clks_out: kfree(cpuclk); +cpuclk_out: + iounmap(clock_complex_base); } CLK_OF_DECLARE(armada_xp_cpu_clock, "marvell,armada-xp-cpu-clock", diff --git a/drivers/clk/mvebu/common.c b/drivers/clk/mvebu/common.c index adaa4a1821b8..25ceccf939ad 100644 --- a/drivers/clk/mvebu/common.c +++ b/drivers/clk/mvebu/common.c @@ -45,8 +45,10 @@ void __init mvebu_coreclk_setup(struct device_node *np, clk_data.clk_num = 2 + desc->num_ratios; clk_data.clks = kzalloc(clk_data.clk_num * sizeof(struct clk *), GFP_KERNEL); - if (WARN_ON(!clk_data.clks)) + if (WARN_ON(!clk_data.clks)) { + iounmap(base); return; + } /* Register TCLK */ of_property_read_string_index(np, "clock-output-names", 0, @@ -134,7 +136,7 @@ void __init mvebu_clk_gating_setup(struct device_node *np, ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); if (WARN_ON(!ctrl)) - return; + goto ctrl_out; spin_lock_init(&ctrl->lock); @@ -145,10 +147,8 @@ void __init mvebu_clk_gating_setup(struct device_node *np, ctrl->num_gates = n; ctrl->gates = kzalloc(ctrl->num_gates * sizeof(struct clk *), GFP_KERNEL); - if (WARN_ON(!ctrl->gates)) { - kfree(ctrl); - return; - } + if (WARN_ON(!ctrl->gates)) + goto gates_out; for (n = 0; n < ctrl->num_gates; n++) { const char *parent = @@ -160,4 +160,10 @@ void __init mvebu_clk_gating_setup(struct device_node *np, } of_clk_add_provider(np, clk_gating_get_src, ctrl); + + return; +gates_out: + kfree(ctrl); +ctrl_out: + iounmap(base); } From 2371dd88b80fc847a451d5eff018e165501f560a Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 16 Jul 2013 11:21:59 +0200 Subject: [PATCH 056/102] clk: sunxi: Add A10s gates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Allwinner A10s has a slightly different gates set than the A10 and A13, so add these gates to the clk driver. Signed-off-by: Maxime Ripard Tested-by: Emilio López Reviewed-by: Emilio López --- .../devicetree/bindings/clock/sunxi.txt | 3 + .../bindings/clock/sunxi/sun5i-a10s-gates.txt | 75 +++++++++++++++++++ drivers/clk/sunxi/clk-sunxi.c | 15 ++++ 3 files changed, 93 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/sunxi/sun5i-a10s-gates.txt diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index d495521a79d2..b24de1003947 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -14,13 +14,16 @@ Required properties: "allwinner,sun4i-ahb-clk" - for the AHB clock "allwinner,sun4i-ahb-gates-clk" - for the AHB gates on A10 "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13 + "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s "allwinner,sun4i-apb0-clk" - for the APB0 clock "allwinner,sun4i-apb0-gates-clk" - for the APB0 gates on A10 "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 + "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s "allwinner,sun4i-apb1-clk" - for the APB1 clock "allwinner,sun4i-apb1-mux-clk" - for the APB1 clock muxing "allwinner,sun4i-apb1-gates-clk" - for the APB1 gates on A10 "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13 + "allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s Required properties for all clocks: - reg : shall be the control register address for the clock. diff --git a/Documentation/devicetree/bindings/clock/sunxi/sun5i-a10s-gates.txt b/Documentation/devicetree/bindings/clock/sunxi/sun5i-a10s-gates.txt new file mode 100644 index 000000000000..d24279fe1429 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/sunxi/sun5i-a10s-gates.txt @@ -0,0 +1,75 @@ +Gate clock outputs +------------------ + + * AXI gates ("allwinner,sun4i-axi-gates-clk") + + DRAM 0 + + * AHB gates ("allwinner,sun5i-a10s-ahb-gates-clk") + + USB0 0 + EHCI0 1 + OHCI0 2 + + SS 5 + DMA 6 + BIST 7 + MMC0 8 + MMC1 9 + MMC2 10 + + NAND 13 + SDRAM 14 + + EMAC 17 + TS 18 + + SPI0 20 + SPI1 21 + SPI2 22 + + GPS 26 + + HSTIMER 28 + + VE 32 + + TVE 34 + + LCD 36 + + CSI 40 + + HDMI 43 + DE_BE 44 + + DE_FE 46 + + IEP 51 + MALI400 52 + + * APB0 gates ("allwinner,sun5i-a10s-apb0-gates-clk") + + CODEC 0 + + IIS 3 + + PIO 5 + IR 6 + + KEYPAD 10 + + * APB1 gates ("allwinner,sun5i-a10s-apb1-gates-clk") + + I2C0 0 + I2C1 1 + I2C2 2 + + UART0 16 + UART1 17 + UART2 18 + UART3 19 + +Notation: + [*]: The datasheet didn't mention these, but they are present on AW code + [**]: The datasheet had this marked as "NC" but they are used on AW code diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 323830465d13..15804c25e038 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -342,6 +342,10 @@ static const __initconst struct gates_data sun4i_ahb_gates_data = { .mask = {0x7F77FFF, 0x14FB3F}, }; +static const __initconst struct gates_data sun5i_a10s_ahb_gates_data = { + .mask = {0x147667e7, 0x185915}, +}; + static const __initconst struct gates_data sun5i_a13_ahb_gates_data = { .mask = {0x107067e7, 0x185111}, }; @@ -350,6 +354,10 @@ static const __initconst struct gates_data sun4i_apb0_gates_data = { .mask = {0x4EF}, }; +static const __initconst struct gates_data sun5i_a10s_apb0_gates_data = { + .mask = {0x469}, +}; + static const __initconst struct gates_data sun5i_a13_apb0_gates_data = { .mask = {0x61}, }; @@ -358,6 +366,10 @@ static const __initconst struct gates_data sun4i_apb1_gates_data = { .mask = {0xFF00F7}, }; +static const __initconst struct gates_data sun5i_a10s_apb1_gates_data = { + .mask = {0xf0007}, +}; + static const __initconst struct gates_data sun5i_a13_apb1_gates_data = { .mask = {0xa0007}, }; @@ -443,10 +455,13 @@ static const __initconst struct of_device_id clk_mux_match[] = { static const __initconst struct of_device_id clk_gates_match[] = { {.compatible = "allwinner,sun4i-axi-gates-clk", .data = &sun4i_axi_gates_data,}, {.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &sun4i_ahb_gates_data,}, + {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,}, {.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,}, {.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &sun4i_apb0_gates_data,}, + {.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,}, {.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,}, {.compatible = "allwinner,sun4i-apb1-gates-clk", .data = &sun4i_apb1_gates_data,}, + {.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,}, {.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,}, {} }; From 431807f0bff97bbfddc7a2497038369ed2b4e508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Mon, 22 Jul 2013 22:01:05 -0300 Subject: [PATCH 057/102] clk: sunxi: fix initialization of basic clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the recent move towards CLK_OF_DECLARE(...), the driver stopped initializing osc32k, which is compatible "fixed-clock". This is because we never called of_clk_init(NULL). Fix this by moving the only other simple clock (osc24M) to use CLK_OF_DECLARE(...) and call of_clk_init(NULL) to initialize both of them. Signed-off-by: Emilio López Signed-off-by: Maxime Ripard Cc: Mike Turquette --- drivers/clk/sunxi/clk-sunxi.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 15804c25e038..12c8dc7fa394 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -69,6 +69,7 @@ static void __init sunxi_osc_clk_setup(struct device_node *node) clk_register_clkdev(clk, clk_name, NULL); } } +CLK_OF_DECLARE(sunxi_osc, "allwinner,sun4i-osc-clk", sunxi_osc_clk_setup); @@ -423,12 +424,6 @@ static void __init sunxi_gates_clk_setup(struct device_node *node, of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); } -/* Matches for of_clk_init */ -static const __initconst struct of_device_id clk_match[] = { - {.compatible = "allwinner,sun4i-osc-clk", .data = sunxi_osc_clk_setup,}, - {} -}; - /* Matches for factors clocks */ static const __initconst struct of_device_id clk_factors_match[] = { {.compatible = "allwinner,sun4i-pll1-clk", .data = &pll1_data,}, @@ -483,8 +478,8 @@ static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_mat void __init sunxi_init_clocks(void) { - /* Register all the simple sunxi clocks on DT */ - of_clk_init(clk_match); + /* Register all the simple and basic clocks on DT */ + of_clk_init(NULL); /* Register factor clocks */ of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup); From 81ba6c5e7b1c995083ccaab1c74ac9e0be6ef4d1 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 22 Jul 2013 18:21:32 +0200 Subject: [PATCH 058/102] clk: sunxi: Rename the structure to prepare the addition of sun6i MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename all the generic-named structure to sun4i to avoid confusion when we will introduce the sun6i (A31) clocks. Signed-off-by: Maxime Ripard Reviewed-by: Emilio López --- drivers/clk/sunxi/clk-sunxi.c | 54 +++++++++++++++++------------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 12c8dc7fa394..5fac1aa87bdb 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -25,12 +25,12 @@ static DEFINE_SPINLOCK(clk_lock); /** - * sunxi_osc_clk_setup() - Setup function for gatable oscillator + * sun4i_osc_clk_setup() - Setup function for gatable oscillator */ #define SUNXI_OSC24M_GATE 0 -static void __init sunxi_osc_clk_setup(struct device_node *node) +static void __init sun4i_osc_clk_setup(struct device_node *node) { struct clk *clk; struct clk_fixed_rate *fixed; @@ -69,18 +69,18 @@ static void __init sunxi_osc_clk_setup(struct device_node *node) clk_register_clkdev(clk, clk_name, NULL); } } -CLK_OF_DECLARE(sunxi_osc, "allwinner,sun4i-osc-clk", sunxi_osc_clk_setup); +CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-osc-clk", sun4i_osc_clk_setup); /** - * sunxi_get_pll1_factors() - calculates n, k, m, p factors for PLL1 + * sun4i_get_pll1_factors() - calculates n, k, m, p factors for PLL1 * PLL1 rate is calculated as follows * rate = (parent_rate * n * (k + 1) >> p) / (m + 1); * parent_rate is always 24Mhz */ -static void sunxi_get_pll1_factors(u32 *freq, u32 parent_rate, +static void sun4i_get_pll1_factors(u32 *freq, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p) { u8 div; @@ -128,12 +128,12 @@ static void sunxi_get_pll1_factors(u32 *freq, u32 parent_rate, /** - * sunxi_get_apb1_factors() - calculates m, p factors for APB1 + * sun4i_get_apb1_factors() - calculates m, p factors for APB1 * APB1 rate is calculated as follows * rate = (parent_rate >> p) / (m + 1); */ -static void sunxi_get_apb1_factors(u32 *freq, u32 parent_rate, +static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p) { u8 calcm, calcp; @@ -179,7 +179,7 @@ struct factors_data { void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p); }; -static struct clk_factors_config pll1_config = { +static struct clk_factors_config sun4i_pll1_config = { .nshift = 8, .nwidth = 5, .kshift = 4, @@ -190,21 +190,21 @@ static struct clk_factors_config pll1_config = { .pwidth = 2, }; -static struct clk_factors_config apb1_config = { +static struct clk_factors_config sun4i_apb1_config = { .mshift = 0, .mwidth = 5, .pshift = 16, .pwidth = 2, }; -static const __initconst struct factors_data pll1_data = { - .table = &pll1_config, - .getter = sunxi_get_pll1_factors, +static const __initconst struct factors_data sun4i_pll1_data = { + .table = &sun4i_pll1_config, + .getter = sun4i_get_pll1_factors, }; -static const __initconst struct factors_data apb1_data = { - .table = &apb1_config, - .getter = sunxi_get_apb1_factors, +static const __initconst struct factors_data sun4i_apb1_data = { + .table = &sun4i_apb1_config, + .getter = sun4i_get_apb1_factors, }; static void __init sunxi_factors_clk_setup(struct device_node *node, @@ -240,11 +240,11 @@ struct mux_data { u8 shift; }; -static const __initconst struct mux_data cpu_mux_data = { +static const __initconst struct mux_data sun4i_cpu_mux_data = { .shift = 16, }; -static const __initconst struct mux_data apb1_mux_data = { +static const __initconst struct mux_data sun4i_apb1_mux_data = { .shift = 24, }; @@ -286,17 +286,17 @@ struct div_data { u8 pow; }; -static const __initconst struct div_data axi_data = { +static const __initconst struct div_data sun4i_axi_data = { .shift = 0, .pow = 0, }; -static const __initconst struct div_data ahb_data = { +static const __initconst struct div_data sun4i_ahb_data = { .shift = 4, .pow = 1, }; -static const __initconst struct div_data apb0_data = { +static const __initconst struct div_data sun4i_apb0_data = { .shift = 8, .pow = 1, }; @@ -426,23 +426,23 @@ static void __init sunxi_gates_clk_setup(struct device_node *node, /* Matches for factors clocks */ static const __initconst struct of_device_id clk_factors_match[] = { - {.compatible = "allwinner,sun4i-pll1-clk", .data = &pll1_data,}, - {.compatible = "allwinner,sun4i-apb1-clk", .data = &apb1_data,}, + {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,}, + {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,}, {} }; /* Matches for divider clocks */ static const __initconst struct of_device_id clk_div_match[] = { - {.compatible = "allwinner,sun4i-axi-clk", .data = &axi_data,}, - {.compatible = "allwinner,sun4i-ahb-clk", .data = &ahb_data,}, - {.compatible = "allwinner,sun4i-apb0-clk", .data = &apb0_data,}, + {.compatible = "allwinner,sun4i-axi-clk", .data = &sun4i_axi_data,}, + {.compatible = "allwinner,sun4i-ahb-clk", .data = &sun4i_ahb_data,}, + {.compatible = "allwinner,sun4i-apb0-clk", .data = &sun4i_apb0_data,}, {} }; /* Matches for mux clocks */ static const __initconst struct of_device_id clk_mux_match[] = { - {.compatible = "allwinner,sun4i-cpu-clk", .data = &cpu_mux_data,}, - {.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &apb1_mux_data,}, + {.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,}, + {.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &sun4i_apb1_mux_data,}, {} }; From 70855bb5c608e4ac9dde5b669c3cf56914b713a2 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 23 Jul 2013 09:25:56 +0200 Subject: [PATCH 059/102] clk: sunxi: Allow to specify the divider width from the dividers data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The divider width used to be hardcoded. Some A31 dividers are no longer with the hardcoded width, so we need to make it specific to each divider and set it in the dividers data. Signed-off-by: Maxime Ripard Reviewed-by: Emilio López --- drivers/clk/sunxi/clk-sunxi.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 5fac1aa87bdb..2cafda88b7f6 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -279,26 +279,28 @@ static void __init sunxi_mux_clk_setup(struct device_node *node, * sunxi_divider_clk_setup() - Setup function for simple divider clocks */ -#define SUNXI_DIVISOR_WIDTH 2 - struct div_data { - u8 shift; - u8 pow; + u8 shift; + u8 pow; + u8 width; }; static const __initconst struct div_data sun4i_axi_data = { - .shift = 0, - .pow = 0, + .shift = 0, + .pow = 0, + .width = 2, }; static const __initconst struct div_data sun4i_ahb_data = { - .shift = 4, - .pow = 1, + .shift = 4, + .pow = 1, + .width = 2, }; static const __initconst struct div_data sun4i_apb0_data = { - .shift = 8, - .pow = 1, + .shift = 8, + .pow = 1, + .width = 2, }; static void __init sunxi_divider_clk_setup(struct device_node *node, @@ -314,7 +316,7 @@ static void __init sunxi_divider_clk_setup(struct device_node *node, clk_parent = of_clk_get_parent_name(node, 0); clk = clk_register_divider(NULL, clk_name, clk_parent, 0, - reg, data->shift, SUNXI_DIVISOR_WIDTH, + reg, data->shift, data->width, data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0, &clk_lock); if (clk) { From 6a721db180a22d8e2d59d864446309bc7a09c26f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 23 Jul 2013 23:34:10 +0200 Subject: [PATCH 060/102] clk: sunxi: Add A31 clocks support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The A31 has a mostly different clock set compared to the other older SoCs currently supported in the Allwinner clock driver. Add support for the basic useful clocks. The other ones will come in eventually. Signed-off-by: Maxime Ripard Reviewed-by: Emilio López --- .../devicetree/bindings/clock/sunxi.txt | 6 + .../bindings/clock/sunxi/sun6i-a31-gates.txt | 83 ++++++++++++ drivers/clk/sunxi/clk-sunxi.c | 124 ++++++++++++++++++ 3 files changed, 213 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/sunxi/sun6i-a31-gates.txt diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index b24de1003947..c383d1259e5c 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -8,6 +8,7 @@ Required properties: - compatible : shall be one of the following: "allwinner,sun4i-osc-clk" - for a gatable oscillator "allwinner,sun4i-pll1-clk" - for the main PLL clock + "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock "allwinner,sun4i-axi-clk" - for the AXI clock "allwinner,sun4i-axi-gates-clk" - for the AXI gates @@ -15,6 +16,8 @@ Required properties: "allwinner,sun4i-ahb-gates-clk" - for the AHB gates on A10 "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13 "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s + "allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31 + "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31 "allwinner,sun4i-apb0-clk" - for the APB0 clock "allwinner,sun4i-apb0-gates-clk" - for the APB0 gates on A10 "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 @@ -24,6 +27,9 @@ Required properties: "allwinner,sun4i-apb1-gates-clk" - for the APB1 gates on A10 "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13 "allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s + "allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31 + "allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31 + "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 Required properties for all clocks: - reg : shall be the control register address for the clock. diff --git a/Documentation/devicetree/bindings/clock/sunxi/sun6i-a31-gates.txt b/Documentation/devicetree/bindings/clock/sunxi/sun6i-a31-gates.txt new file mode 100644 index 000000000000..fe44932b5c6b --- /dev/null +++ b/Documentation/devicetree/bindings/clock/sunxi/sun6i-a31-gates.txt @@ -0,0 +1,83 @@ +Gate clock outputs +------------------ + + * AHB1 gates ("allwinner,sun6i-a31-ahb1-gates-clk") + + MIPI DSI 1 + + SS 5 + DMA 6 + + MMC0 8 + MMC1 9 + MMC2 10 + MMC3 11 + + NAND1 12 + NAND0 13 + SDRAM 14 + + GMAC 17 + TS 18 + HSTIMER 19 + SPI0 20 + SPI1 21 + SPI2 22 + SPI3 23 + USB_OTG 24 + + EHCI0 26 + EHCI1 27 + + OHCI0 29 + OHCI1 30 + OHCI2 31 + VE 32 + + LCD0 36 + LCD1 37 + + CSI 40 + + HDMI 43 + DE_BE0 44 + DE_BE1 45 + DE_FE1 46 + DE_FE1 47 + + MP 50 + + GPU 52 + + DEU0 55 + DEU1 56 + DRC0 57 + DRC1 58 + + * APB1 gates ("allwinner,sun6i-a31-apb1-gates-clk") + + CODEC 0 + + DIGITAL MIC 4 + PIO 5 + + DAUDIO0 12 + DAUDIO1 13 + + * APB2 gates ("allwinner,sun6i-a31-apb2-gates-clk") + + I2C0 0 + I2C1 1 + I2C2 2 + I2C3 3 + + UART0 16 + UART1 17 + UART2 18 + UART3 19 + UART4 20 + UART5 21 + +Notation: + [*]: The datasheet didn't mention these, but they are present on AW code + [**]: The datasheet had this marked as "NC" but they are used on AW code diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 2cafda88b7f6..6fd02042c13b 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -125,7 +125,89 @@ static void sun4i_get_pll1_factors(u32 *freq, u32 parent_rate, *n = div / 4; } +/** + * sun6i_a31_get_pll1_factors() - calculates n, k and m factors for PLL1 + * PLL1 rate is calculated as follows + * rate = parent_rate * (n + 1) * (k + 1) / (m + 1); + * parent_rate should always be 24MHz + */ +static void sun6i_a31_get_pll1_factors(u32 *freq, u32 parent_rate, + u8 *n, u8 *k, u8 *m, u8 *p) +{ + /* + * We can operate only on MHz, this will make our life easier + * later. + */ + u32 freq_mhz = *freq / 1000000; + u32 parent_freq_mhz = parent_rate / 1000000; + /* + * Round down the frequency to the closest multiple of either + * 6 or 16 + */ + u32 round_freq_6 = round_down(freq_mhz, 6); + u32 round_freq_16 = round_down(freq_mhz, 16); + + if (round_freq_6 > round_freq_16) + freq_mhz = round_freq_6; + else + freq_mhz = round_freq_16; + + *freq = freq_mhz * 1000000; + + /* + * If the factors pointer are null, we were just called to + * round down the frequency. + * Exit. + */ + if (n == NULL) + return; + + /* If the frequency is a multiple of 32 MHz, k is always 3 */ + if (!(freq_mhz % 32)) + *k = 3; + /* If the frequency is a multiple of 9 MHz, k is always 2 */ + else if (!(freq_mhz % 9)) + *k = 2; + /* If the frequency is a multiple of 8 MHz, k is always 1 */ + else if (!(freq_mhz % 8)) + *k = 1; + /* Otherwise, we don't use the k factor */ + else + *k = 0; + + /* + * If the frequency is a multiple of 2 but not a multiple of + * 3, m is 3. This is the first time we use 6 here, yet we + * will use it on several other places. + * We use this number because it's the lowest frequency we can + * generate (with n = 0, k = 0, m = 3), so every other frequency + * somehow relates to this frequency. + */ + if ((freq_mhz % 6) == 2 || (freq_mhz % 6) == 4) + *m = 2; + /* + * If the frequency is a multiple of 6MHz, but the factor is + * odd, m will be 3 + */ + else if ((freq_mhz / 6) & 1) + *m = 3; + /* Otherwise, we end up with m = 1 */ + else + *m = 1; + + /* Calculate n thanks to the above factors we already got */ + *n = freq_mhz * (*m + 1) / ((*k + 1) * parent_freq_mhz) - 1; + + /* + * If n end up being outbound, and that we can still decrease + * m, do it. + */ + if ((*n + 1) > 31 && (*m + 1) > 1) { + *n = (*n + 1) / 2 - 1; + *m = (*m + 1) / 2 - 1; + } +} /** * sun4i_get_apb1_factors() - calculates m, p factors for APB1 @@ -190,6 +272,15 @@ static struct clk_factors_config sun4i_pll1_config = { .pwidth = 2, }; +static struct clk_factors_config sun6i_a31_pll1_config = { + .nshift = 8, + .nwidth = 5, + .kshift = 4, + .kwidth = 2, + .mshift = 0, + .mwidth = 2, +}; + static struct clk_factors_config sun4i_apb1_config = { .mshift = 0, .mwidth = 5, @@ -202,6 +293,11 @@ static const __initconst struct factors_data sun4i_pll1_data = { .getter = sun4i_get_pll1_factors, }; +static const __initconst struct factors_data sun6i_a31_pll1_data = { + .table = &sun6i_a31_pll1_config, + .getter = sun6i_a31_get_pll1_factors, +}; + static const __initconst struct factors_data sun4i_apb1_data = { .table = &sun4i_apb1_config, .getter = sun4i_get_apb1_factors, @@ -244,6 +340,10 @@ static const __initconst struct mux_data sun4i_cpu_mux_data = { .shift = 16, }; +static const __initconst struct mux_data sun6i_a31_ahb1_mux_data = { + .shift = 12, +}; + static const __initconst struct mux_data sun4i_apb1_mux_data = { .shift = 24, }; @@ -303,6 +403,12 @@ static const __initconst struct div_data sun4i_apb0_data = { .width = 2, }; +static const __initconst struct div_data sun6i_a31_apb2_div_data = { + .shift = 0, + .pow = 0, + .width = 4, +}; + static void __init sunxi_divider_clk_setup(struct device_node *node, struct div_data *data) { @@ -353,6 +459,10 @@ static const __initconst struct gates_data sun5i_a13_ahb_gates_data = { .mask = {0x107067e7, 0x185111}, }; +static const __initconst struct gates_data sun6i_a31_ahb1_gates_data = { + .mask = {0xEDFE7F62, 0x794F931}, +}; + static const __initconst struct gates_data sun4i_apb0_gates_data = { .mask = {0x4EF}, }; @@ -377,6 +487,14 @@ static const __initconst struct gates_data sun5i_a13_apb1_gates_data = { .mask = {0xa0007}, }; +static const __initconst struct gates_data sun6i_a31_apb1_gates_data = { + .mask = {0x3031}, +}; + +static const __initconst struct gates_data sun6i_a31_apb2_gates_data = { + .mask = {0x3F000F}, +}; + static void __init sunxi_gates_clk_setup(struct device_node *node, struct gates_data *data) { @@ -429,6 +547,7 @@ static void __init sunxi_gates_clk_setup(struct device_node *node, /* Matches for factors clocks */ static const __initconst struct of_device_id clk_factors_match[] = { {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,}, + {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,}, {} }; @@ -438,6 +557,7 @@ static const __initconst struct of_device_id clk_div_match[] = { {.compatible = "allwinner,sun4i-axi-clk", .data = &sun4i_axi_data,}, {.compatible = "allwinner,sun4i-ahb-clk", .data = &sun4i_ahb_data,}, {.compatible = "allwinner,sun4i-apb0-clk", .data = &sun4i_apb0_data,}, + {.compatible = "allwinner,sun6i-a31-apb2-div-clk", .data = &sun6i_a31_apb2_div_data,}, {} }; @@ -445,6 +565,7 @@ static const __initconst struct of_device_id clk_div_match[] = { static const __initconst struct of_device_id clk_mux_match[] = { {.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,}, {.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &sun4i_apb1_mux_data,}, + {.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,}, {} }; @@ -454,12 +575,15 @@ static const __initconst struct of_device_id clk_gates_match[] = { {.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &sun4i_ahb_gates_data,}, {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,}, {.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,}, + {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,}, {.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &sun4i_apb0_gates_data,}, {.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,}, {.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,}, {.compatible = "allwinner,sun4i-apb1-gates-clk", .data = &sun4i_apb1_gates_data,}, {.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,}, {.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,}, + {.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,}, + {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,}, {} }; From 1fb2e4aab8b31b15e6be5debacb4203333360fd2 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 25 Jul 2013 21:06:56 +0200 Subject: [PATCH 061/102] clk: sunxi: Add Allwinner A20 gates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Allwinner A20 is almost identical to the earlier A10 SoC from Allwinner on many aspects, including the clocks tree. However, since the A20 has some additionnal IPs compared to the A10, the clock tree isn't exactly the same, especially when it comes to the gated clocks available. We thus need to register different clock gates for the A20. Signed-off-by: Maxime Ripard Reviewed-by: Emilio López --- .../devicetree/bindings/clock/sunxi.txt | 3 + .../bindings/clock/sunxi/sun7i-a20-gates.txt | 98 +++++++++++++++++++ drivers/clk/sunxi/clk-sunxi.c | 15 +++ 3 files changed, 116 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/sunxi/sun7i-a20-gates.txt diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index c383d1259e5c..00a5c26454eb 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt @@ -16,18 +16,21 @@ Required properties: "allwinner,sun4i-ahb-gates-clk" - for the AHB gates on A10 "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13 "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s + "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20 "allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31 "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31 "allwinner,sun4i-apb0-clk" - for the APB0 clock "allwinner,sun4i-apb0-gates-clk" - for the APB0 gates on A10 "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s + "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 "allwinner,sun4i-apb1-clk" - for the APB1 clock "allwinner,sun4i-apb1-mux-clk" - for the APB1 clock muxing "allwinner,sun4i-apb1-gates-clk" - for the APB1 gates on A10 "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13 "allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s "allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31 + "allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20 "allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31 "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 diff --git a/Documentation/devicetree/bindings/clock/sunxi/sun7i-a20-gates.txt b/Documentation/devicetree/bindings/clock/sunxi/sun7i-a20-gates.txt new file mode 100644 index 000000000000..357f4fdc02ef --- /dev/null +++ b/Documentation/devicetree/bindings/clock/sunxi/sun7i-a20-gates.txt @@ -0,0 +1,98 @@ +Gate clock outputs +------------------ + + * AXI gates ("allwinner,sun4i-axi-gates-clk") + + DRAM 0 + + * AHB gates ("allwinner,sun7i-a20-ahb-gates-clk") + + USB0 0 + EHCI0 1 + OHCI0 2 + EHCI1 3 + OHCI1 4 + SS 5 + DMA 6 + BIST 7 + MMC0 8 + MMC1 9 + MMC2 10 + MMC3 11 + MS 12 + NAND 13 + SDRAM 14 + + ACE 16 + EMAC 17 + TS 18 + + SPI0 20 + SPI1 21 + SPI2 22 + SPI3 23 + + SATA 25 + + HSTIMER 28 + + VE 32 + TVD 33 + TVE0 34 + TVE1 35 + LCD0 36 + LCD1 37 + + CSI0 40 + CSI1 41 + + HDMI1 42 + HDMI0 43 + DE_BE0 44 + DE_BE1 45 + DE_FE1 46 + DE_FE1 47 + + GMAC 49 + MP 50 + + MALI400 52 + + * APB0 gates ("allwinner,sun7i-a20-apb0-gates-clk") + + CODEC 0 + SPDIF 1 + AC97 2 + IIS0 3 + IIS1 4 + PIO 5 + IR0 6 + IR1 7 + IIS2 8 + + KEYPAD 10 + + * APB1 gates ("allwinner,sun7i-a20-apb1-gates-clk") + + I2C0 0 + I2C1 1 + I2C2 2 + I2C3 3 + CAN 4 + SCR 5 + PS20 6 + PS21 7 + + I2C4 15 + UART0 16 + UART1 17 + UART2 18 + UART3 19 + UART4 20 + UART5 21 + UART6 22 + UART7 23 + +Notation: + [*]: The datasheet didn't mention these, but they are present on AW code + [**]: The datasheet had this marked as "NC" but they are used on AW code diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 6fd02042c13b..d39f213f0fbe 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -463,6 +463,10 @@ static const __initconst struct gates_data sun6i_a31_ahb1_gates_data = { .mask = {0xEDFE7F62, 0x794F931}, }; +static const __initconst struct gates_data sun7i_a20_ahb_gates_data = { + .mask = { 0x12f77fff, 0x16ff3f }, +}; + static const __initconst struct gates_data sun4i_apb0_gates_data = { .mask = {0x4EF}, }; @@ -475,6 +479,10 @@ static const __initconst struct gates_data sun5i_a13_apb0_gates_data = { .mask = {0x61}, }; +static const __initconst struct gates_data sun7i_a20_apb0_gates_data = { + .mask = { 0x4ff }, +}; + static const __initconst struct gates_data sun4i_apb1_gates_data = { .mask = {0xFF00F7}, }; @@ -495,6 +503,10 @@ static const __initconst struct gates_data sun6i_a31_apb2_gates_data = { .mask = {0x3F000F}, }; +static const __initconst struct gates_data sun7i_a20_apb1_gates_data = { + .mask = { 0xff80ff }, +}; + static void __init sunxi_gates_clk_setup(struct device_node *node, struct gates_data *data) { @@ -576,13 +588,16 @@ static const __initconst struct of_device_id clk_gates_match[] = { {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,}, {.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,}, {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,}, + {.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,}, {.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &sun4i_apb0_gates_data,}, {.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,}, {.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,}, + {.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,}, {.compatible = "allwinner,sun4i-apb1-gates-clk", .data = &sun4i_apb1_gates_data,}, {.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,}, {.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,}, {.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,}, + {.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,}, {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,}, {} }; From 40ef723c8bf3c675aa210d98fc411e347911829c Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Wed, 21 Aug 2013 02:33:21 +0200 Subject: [PATCH 062/102] clk: samsung: pll: Use new registration method for PLL6552 and PLL6553 This patch modifies PLL6552 and PLL6553 clock drivers to use recently added common Samsung PLL registration method. Signed-off-by: Tomasz Figa Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-pll.c | 105 ++++------------------------------ drivers/clk/samsung/clk-pll.h | 6 +- 2 files changed, 13 insertions(+), 98 deletions(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 077555416ce1..7572d1d4fac1 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -441,9 +441,6 @@ struct clk * __init samsung_clk_register_pll46xx(const char *name, * PLL6552 Clock Type */ -#define PLL6552_LOCK_REG 0x00 -#define PLL6552_CON_REG 0x0c - #define PLL6552_MDIV_MASK 0x3ff #define PLL6552_PDIV_MASK 0x3f #define PLL6552_SDIV_MASK 0x7 @@ -451,21 +448,14 @@ struct clk * __init samsung_clk_register_pll46xx(const char *name, #define PLL6552_PDIV_SHIFT 8 #define PLL6552_SDIV_SHIFT 0 -struct samsung_clk_pll6552 { - struct clk_hw hw; - void __iomem *reg_base; -}; - -#define to_clk_pll6552(_hw) container_of(_hw, struct samsung_clk_pll6552, hw) - static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct samsung_clk_pll6552 *pll = to_clk_pll6552(hw); + struct samsung_clk_pll *pll = to_clk_pll(hw); u32 mdiv, pdiv, sdiv, pll_con; u64 fvco = parent_rate; - pll_con = __raw_readl(pll->reg_base + PLL6552_CON_REG); + pll_con = __raw_readl(pll->con_reg); mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK; pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK; sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK; @@ -480,48 +470,10 @@ static const struct clk_ops samsung_pll6552_clk_ops = { .recalc_rate = samsung_pll6552_recalc_rate, }; -struct clk * __init samsung_clk_register_pll6552(const char *name, - const char *pname, void __iomem *base) -{ - struct samsung_clk_pll6552 *pll; - struct clk *clk; - struct clk_init_data init; - - pll = kzalloc(sizeof(*pll), GFP_KERNEL); - if (!pll) { - pr_err("%s: could not allocate pll clk %s\n", __func__, name); - return NULL; - } - - init.name = name; - init.ops = &samsung_pll6552_clk_ops; - init.parent_names = &pname; - init.num_parents = 1; - - pll->hw.init = &init; - pll->reg_base = base; - - clk = clk_register(NULL, &pll->hw); - if (IS_ERR(clk)) { - pr_err("%s: failed to register pll clock %s\n", __func__, - name); - kfree(pll); - } - - if (clk_register_clkdev(clk, name, NULL)) - pr_err("%s: failed to register lookup for %s", __func__, name); - - return clk; -} - /* * PLL6553 Clock Type */ -#define PLL6553_LOCK_REG 0x00 -#define PLL6553_CON0_REG 0x0c -#define PLL6553_CON1_REG 0x10 - #define PLL6553_MDIV_MASK 0xff #define PLL6553_PDIV_MASK 0x3f #define PLL6553_SDIV_MASK 0x7 @@ -531,22 +483,15 @@ struct clk * __init samsung_clk_register_pll6552(const char *name, #define PLL6553_SDIV_SHIFT 0 #define PLL6553_KDIV_SHIFT 0 -struct samsung_clk_pll6553 { - struct clk_hw hw; - void __iomem *reg_base; -}; - -#define to_clk_pll6553(_hw) container_of(_hw, struct samsung_clk_pll6553, hw) - static unsigned long samsung_pll6553_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct samsung_clk_pll6553 *pll = to_clk_pll6553(hw); + struct samsung_clk_pll *pll = to_clk_pll(hw); u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1; u64 fvco = parent_rate; - pll_con0 = __raw_readl(pll->reg_base + PLL6553_CON0_REG); - pll_con1 = __raw_readl(pll->reg_base + PLL6553_CON1_REG); + pll_con0 = __raw_readl(pll->con_reg); + pll_con1 = __raw_readl(pll->con_reg + 0x4); mdiv = (pll_con0 >> PLL6553_MDIV_SHIFT) & PLL6553_MDIV_MASK; pdiv = (pll_con0 >> PLL6553_PDIV_SHIFT) & PLL6553_PDIV_MASK; sdiv = (pll_con0 >> PLL6553_SDIV_SHIFT) & PLL6553_SDIV_MASK; @@ -563,40 +508,6 @@ static const struct clk_ops samsung_pll6553_clk_ops = { .recalc_rate = samsung_pll6553_recalc_rate, }; -struct clk * __init samsung_clk_register_pll6553(const char *name, - const char *pname, void __iomem *base) -{ - struct samsung_clk_pll6553 *pll; - struct clk *clk; - struct clk_init_data init; - - pll = kzalloc(sizeof(*pll), GFP_KERNEL); - if (!pll) { - pr_err("%s: could not allocate pll clk %s\n", __func__, name); - return NULL; - } - - init.name = name; - init.ops = &samsung_pll6553_clk_ops; - init.parent_names = &pname; - init.num_parents = 1; - - pll->hw.init = &init; - pll->reg_base = base; - - clk = clk_register(NULL, &pll->hw); - if (IS_ERR(clk)) { - pr_err("%s: failed to register pll clock %s\n", __func__, - name); - kfree(pll); - } - - if (clk_register_clkdev(clk, name, NULL)) - pr_err("%s: failed to register lookup for %s", __func__, name); - - return clk; -} - /* * PLL2550x Clock Type */ @@ -732,6 +643,12 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, else init.ops = &samsung_pll36xx_clk_ops; break; + case pll_6552: + init.ops = &samsung_pll6552_clk_ops; + break; + case pll_6553: + init.ops = &samsung_pll6553_clk_ops; + break; default: pr_warn("%s: Unknown pll type for pll clk %s\n", __func__, pll_clk->name); diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index 2f70e88d6104..cd1103784f71 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -17,6 +17,8 @@ enum samsung_pll_type { pll_36xx, pll_2550, pll_2650, + pll_6552, + pll_6553, }; #define PLL_35XX_RATE(_rate, _m, _p, _s) \ @@ -64,10 +66,6 @@ extern struct clk * __init samsung_clk_register_pll45xx(const char *name, extern struct clk * __init samsung_clk_register_pll46xx(const char *name, const char *pname, const void __iomem *con_reg, enum pll46xx_type type); -extern struct clk *samsung_clk_register_pll6552(const char *name, - const char *pname, void __iomem *base); -extern struct clk *samsung_clk_register_pll6553(const char *name, - const char *pname, void __iomem *base); extern struct clk * __init samsung_clk_register_pll2550x(const char *name, const char *pname, const void __iomem *reg_base, const unsigned long offset); From 1ec5502ef20acc0af5c9172aac4652cd7cafd852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Sun, 4 Aug 2013 11:47:29 +0200 Subject: [PATCH 063/102] clk: sunxi: fix initialization of basic clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the recent move towards CLK_OF_DECLARE(...), the driver stopped initializing osc32k, which is compatible "fixed-clock". This is because we never called of_clk_init(NULL). Fix this by moving the only other simple clock (osc24M) to use CLK_OF_DECLARE(...) and call of_clk_init(NULL) to initialize both of them. Signed-off-by: Emilio López Signed-off-by: Maxime Ripard Signed-off-by: Mike Turquette --- drivers/clk/sunxi/clk-sunxi.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 323830465d13..3bbfca5850fd 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -69,6 +69,7 @@ static void __init sunxi_osc_clk_setup(struct device_node *node) clk_register_clkdev(clk, clk_name, NULL); } } +CLK_OF_DECLARE(sunxi_osc, "allwinner,sun4i-osc-clk", sunxi_osc_clk_setup); @@ -411,12 +412,6 @@ static void __init sunxi_gates_clk_setup(struct device_node *node, of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); } -/* Matches for of_clk_init */ -static const __initconst struct of_device_id clk_match[] = { - {.compatible = "allwinner,sun4i-osc-clk", .data = sunxi_osc_clk_setup,}, - {} -}; - /* Matches for factors clocks */ static const __initconst struct of_device_id clk_factors_match[] = { {.compatible = "allwinner,sun4i-pll1-clk", .data = &pll1_data,}, @@ -468,8 +463,8 @@ static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_mat void __init sunxi_init_clocks(void) { - /* Register all the simple sunxi clocks on DT */ - of_clk_init(clk_match); + /* Register all the simple and basic clocks on DT */ + of_clk_init(NULL); /* Register factor clocks */ of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup); From 7f7ed584d11be77a7521d170431bb14bc32a5980 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 22 Aug 2013 11:31:31 -0500 Subject: [PATCH 064/102] clk: get matching entry under lock in of_clk_init() Currently of_clk_init() finds a matching device node while holding the device tree spinlock. When a matching device node is found, the lock is dropped and then re-acquired in order to get a reference to the matching device id structure. Acquiring the spinlock twice is unnecessary (and it opens a vulnerable window that could conceivably lead to errors). There already exists an interface for both finding and taking a reference to a device id under lock, so use it. Signed-off-by: Alex Elder Reviewed-by: Christian Daudt Reviewed-by: Markus Mayer Reviewed-by: Matt Porter Signed-off-by: Mike Turquette --- drivers/clk/clk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 7c4376289865..2db08c01ef51 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2228,13 +2228,13 @@ EXPORT_SYMBOL_GPL(of_clk_get_parent_name); */ void __init of_clk_init(const struct of_device_id *matches) { + const struct of_device_id *match; struct device_node *np; if (!matches) matches = __clk_of_table; - for_each_matching_node(np, matches) { - const struct of_device_id *match = of_match_node(matches, np); + for_each_matching_node_and_match(np, matches, &match) { of_clk_init_cb_t clk_init_cb = match->data; clk_init_cb(np); } From aa514ce34b65e3dc01f95a0b470b39bbb7e09998 Mon Sep 17 00:00:00 2001 From: Gerhard Sittig Date: Mon, 22 Jul 2013 14:14:40 +0200 Subject: [PATCH 065/102] clk: wrap I/O access for improved portability the common clock drivers were motivated/initiated by ARM development and apparently assume little endian peripherals wrap register/peripherals access in the common code (div, gate, mux) in preparation of adding COMMON_CLK support for other platforms Signed-off-by: Gerhard Sittig Signed-off-by: Mike Turquette --- drivers/clk/clk-divider.c | 6 +++--- drivers/clk/clk-gate.c | 6 +++--- drivers/clk/clk-mux.c | 6 +++--- include/linux/clk-provider.h | 17 +++++++++++++++++ 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 749372f87ec4..8d3009e44fba 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, struct clk_divider *divider = to_clk_divider(hw); unsigned int div, val; - val = readl(divider->reg) >> divider->shift; + val = clk_readl(divider->reg) >> divider->shift; val &= div_mask(divider); div = _get_div(divider, val); @@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, if (divider->flags & CLK_DIVIDER_HIWORD_MASK) { val = div_mask(divider) << (divider->shift + 16); } else { - val = readl(divider->reg); + val = clk_readl(divider->reg); val &= ~(div_mask(divider) << divider->shift); } val |= value << divider->shift; - writel(val, divider->reg); + clk_writel(val, divider->reg); if (divider->lock) spin_unlock_irqrestore(divider->lock, flags); diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index 2b28a004c19e..4a58c55255bd 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable) if (set) reg |= BIT(gate->bit_idx); } else { - reg = readl(gate->reg); + reg = clk_readl(gate->reg); if (set) reg |= BIT(gate->bit_idx); @@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable) reg &= ~BIT(gate->bit_idx); } - writel(reg, gate->reg); + clk_writel(reg, gate->reg); if (gate->lock) spin_unlock_irqrestore(gate->lock, flags); @@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw) u32 reg; struct clk_gate *gate = to_clk_gate(hw); - reg = readl(gate->reg); + reg = clk_readl(gate->reg); /* if a set bit disables this clk, flip it before masking */ if (gate->flags & CLK_GATE_SET_TO_DISABLE) diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 0811633fcc4d..4f96ff3ba728 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw) * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so * val = 0x4 really means "bit 2, index starts at bit 0" */ - val = readl(mux->reg) >> mux->shift; + val = clk_readl(mux->reg) >> mux->shift; val &= mux->mask; if (mux->table) { @@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index) if (mux->flags & CLK_MUX_HIWORD_MASK) { val = mux->mask << (mux->shift + 16); } else { - val = readl(mux->reg); + val = clk_readl(mux->reg); val &= ~(mux->mask << mux->shift); } val |= index << mux->shift; - writel(val, mux->reg); + clk_writel(val, mux->reg); if (mux->lock) spin_unlock_irqrestore(mux->lock, flags); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 1f0285b2f422..73bdb69f0c08 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -12,6 +12,7 @@ #define __LINUX_CLK_PROVIDER_H #include +#include #ifdef CONFIG_COMMON_CLK @@ -504,5 +505,21 @@ static inline const char *of_clk_get_parent_name(struct device_node *np, #define of_clk_init(matches) \ { while (0); } #endif /* CONFIG_OF */ + +/* + * wrap access to peripherals in accessor routines + * for improved portability across platforms + */ + +static inline u32 clk_readl(u32 __iomem *reg) +{ + return readl(reg); +} + +static inline void clk_writel(u32 val, u32 __iomem *reg) +{ + writel(val, reg); +} + #endif /* CONFIG_COMMON_CLK */ #endif /* CLK_PROVIDER_H */ From 3bbc55dd1724bcd2d393f767016c3674adb2ede6 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 12 Aug 2013 14:43:59 +0530 Subject: [PATCH 066/102] clk: bcm2835: Fix incorrect placement of __initconst __initconst should be placed between the variable name and equal sign for the variable to be placed in the intended section. Signed-off-by: Sachin Kamat Acked-by: Stephen Warren Signed-off-by: Mike Turquette --- drivers/clk/clk-bcm2835.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-bcm2835.c b/drivers/clk/clk-bcm2835.c index 792bc57a9db7..5fb4ff53d088 100644 --- a/drivers/clk/clk-bcm2835.c +++ b/drivers/clk/clk-bcm2835.c @@ -23,7 +23,7 @@ #include #include -static const __initconst struct of_device_id clk_match[] = { +static const struct of_device_id clk_match[] __initconst = { { .compatible = "fixed-clock", .data = of_fixed_clk_setup, }, { } }; From 330d83b1fb255963dcfd20cbdd0be34c0ed7da89 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 12 Aug 2013 14:44:00 +0530 Subject: [PATCH 067/102] clk: nomadik: Fix incorrect placement of __initconst __initconst should be placed between the variable name and equal sign for the variable to be placed in the intended section. Signed-off-by: Sachin Kamat Acked-by: Linus Walleij Signed-off-by: Mike Turquette --- drivers/clk/clk-nomadik.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk-nomadik.c b/drivers/clk/clk-nomadik.c index 6d819a37f647..51410c2ac2cb 100644 --- a/drivers/clk/clk-nomadik.c +++ b/drivers/clk/clk-nomadik.c @@ -479,12 +479,12 @@ static void __init of_nomadik_src_clk_setup(struct device_node *np) of_clk_add_provider(np, of_clk_src_simple_get, clk); } -static const __initconst struct of_device_id nomadik_src_match[] = { +static const struct of_device_id nomadik_src_match[] __initconst = { { .compatible = "stericsson,nomadik-src" }, { /* sentinel */ } }; -static const __initconst struct of_device_id nomadik_src_clk_match[] = { +static const struct of_device_id nomadik_src_clk_match[] __initconst = { { .compatible = "fixed-clock", .data = of_fixed_clk_setup, From edead9f86c9eb19581dabecf5309a79583c3384f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 12 Aug 2013 14:44:01 +0530 Subject: [PATCH 068/102] clk: u300: Fix incorrect placement of __initconst __initconst should be placed between the variable name and equal sign for the variable to be placed in the intended section. While at it also make 'u300_clk_lookup' static as it is used only in this file. Signed-off-by: Sachin Kamat Acked-by: Linus Walleij Signed-off-by: Mike Turquette --- drivers/clk/clk-u300.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c index 8774e058cb6c..3efbdd078d14 100644 --- a/drivers/clk/clk-u300.c +++ b/drivers/clk/clk-u300.c @@ -746,7 +746,7 @@ struct u300_clock { u16 clk_val; }; -struct u300_clock const __initconst u300_clk_lookup[] = { +static struct u300_clock const u300_clk_lookup[] __initconst = { { .type = U300_CLK_TYPE_REST, .id = 3, @@ -1151,7 +1151,7 @@ static void __init of_u300_syscon_mclk_init(struct device_node *np) of_clk_add_provider(np, of_clk_src_simple_get, clk); } -static const __initconst struct of_device_id u300_clk_match[] = { +static const struct of_device_id u300_clk_match[] __initconst = { { .compatible = "fixed-clock", .data = of_fixed_clk_setup, From 682dfdc019a4a23aff93e63def077abf0d3f53ac Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 12 Aug 2013 14:44:02 +0530 Subject: [PATCH 069/102] clk: armada-370: Fix incorrect placement of __initconst __initconst should be placed between the variable name and equal sign for the variable to be placed in the intended section. Signed-off-by: Sachin Kamat Acked-by: Gregory Clement Signed-off-by: Mike Turquette --- drivers/clk/mvebu/armada-370.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/clk/mvebu/armada-370.c b/drivers/clk/mvebu/armada-370.c index 079960e7c304..fc777bdc1886 100644 --- a/drivers/clk/mvebu/armada-370.c +++ b/drivers/clk/mvebu/armada-370.c @@ -32,13 +32,13 @@ enum { A370_CPU_TO_NBCLK, A370_CPU_TO_HCLK, A370_CPU_TO_DRAMCLK }; -static const struct coreclk_ratio __initconst a370_coreclk_ratios[] = { +static const struct coreclk_ratio a370_coreclk_ratios[] __initconst = { { .id = A370_CPU_TO_NBCLK, .name = "nbclk" }, { .id = A370_CPU_TO_HCLK, .name = "hclk" }, { .id = A370_CPU_TO_DRAMCLK, .name = "dramclk" }, }; -static const u32 __initconst a370_tclk_freqs[] = { +static const u32 a370_tclk_freqs[] __initconst = { 16600000, 20000000, }; @@ -52,7 +52,7 @@ static u32 __init a370_get_tclk_freq(void __iomem *sar) return a370_tclk_freqs[tclk_freq_select]; } -static const u32 __initconst a370_cpu_freqs[] = { +static const u32 a370_cpu_freqs[] __initconst = { 400000000, 533000000, 667000000, @@ -78,7 +78,7 @@ static u32 __init a370_get_cpu_freq(void __iomem *sar) return cpu_freq; } -static const int __initconst a370_nbclk_ratios[32][2] = { +static const int a370_nbclk_ratios[32][2] __initconst = { {0, 1}, {1, 2}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {1, 1}, {2, 3}, {0, 1}, {1, 2}, {2, 4}, {0, 1}, @@ -89,7 +89,7 @@ static const int __initconst a370_nbclk_ratios[32][2] = { {0, 1}, {0, 1}, {0, 1}, {0, 1}, }; -static const int __initconst a370_hclk_ratios[32][2] = { +static const int a370_hclk_ratios[32][2] __initconst = { {0, 1}, {1, 2}, {2, 6}, {2, 3}, {1, 3}, {1, 4}, {1, 2}, {2, 6}, {0, 1}, {1, 6}, {2, 10}, {0, 1}, @@ -100,7 +100,7 @@ static const int __initconst a370_hclk_ratios[32][2] = { {0, 1}, {0, 1}, {0, 1}, {0, 1}, }; -static const int __initconst a370_dramclk_ratios[32][2] = { +static const int a370_dramclk_ratios[32][2] __initconst = { {0, 1}, {1, 2}, {2, 3}, {2, 3}, {1, 3}, {1, 2}, {1, 2}, {2, 6}, {0, 1}, {1, 3}, {2, 5}, {0, 1}, @@ -152,7 +152,7 @@ CLK_OF_DECLARE(a370_core_clk, "marvell,armada-370-core-clock", * Clock Gating Control */ -static const struct clk_gating_soc_desc __initconst a370_gating_desc[] = { +static const struct clk_gating_soc_desc a370_gating_desc[] __initconst = { { "audio", NULL, 0, 0 }, { "pex0_en", NULL, 1, 0 }, { "pex1_en", NULL, 2, 0 }, From 4e280d741af5399bc04673b8e49bf6d44455fdce Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 12 Aug 2013 14:44:03 +0530 Subject: [PATCH 070/102] clk: armada-xp: Fix incorrect placement of __initconst __initconst should be placed between the variable name and equal sign for the variable to be placed in the intended section. Signed-off-by: Sachin Kamat Acked-by: Gregory Clement Signed-off-by: Mike Turquette --- drivers/clk/mvebu/armada-xp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/mvebu/armada-xp.c b/drivers/clk/mvebu/armada-xp.c index 13b62ceb3407..9922c4475aa8 100644 --- a/drivers/clk/mvebu/armada-xp.c +++ b/drivers/clk/mvebu/armada-xp.c @@ -40,7 +40,7 @@ enum { AXP_CPU_TO_NBCLK, AXP_CPU_TO_HCLK, AXP_CPU_TO_DRAMCLK }; -static const struct coreclk_ratio __initconst axp_coreclk_ratios[] = { +static const struct coreclk_ratio axp_coreclk_ratios[] __initconst = { { .id = AXP_CPU_TO_NBCLK, .name = "nbclk" }, { .id = AXP_CPU_TO_HCLK, .name = "hclk" }, { .id = AXP_CPU_TO_DRAMCLK, .name = "dramclk" }, @@ -52,7 +52,7 @@ static u32 __init axp_get_tclk_freq(void __iomem *sar) return 250000000; } -static const u32 __initconst axp_cpu_freqs[] = { +static const u32 axp_cpu_freqs[] __initconst = { 1000000000, 1066000000, 1200000000, @@ -89,7 +89,7 @@ static u32 __init axp_get_cpu_freq(void __iomem *sar) return cpu_freq; } -static const int __initconst axp_nbclk_ratios[32][2] = { +static const int axp_nbclk_ratios[32][2] __initconst = { {0, 1}, {1, 2}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {1, 1}, {2, 3}, {0, 1}, {1, 2}, {2, 4}, {0, 1}, @@ -100,7 +100,7 @@ static const int __initconst axp_nbclk_ratios[32][2] = { {0, 1}, {0, 1}, {0, 1}, {0, 1}, }; -static const int __initconst axp_hclk_ratios[32][2] = { +static const int axp_hclk_ratios[32][2] __initconst = { {0, 1}, {1, 2}, {2, 6}, {2, 3}, {1, 3}, {1, 4}, {1, 2}, {2, 6}, {0, 1}, {1, 6}, {2, 10}, {0, 1}, @@ -111,7 +111,7 @@ static const int __initconst axp_hclk_ratios[32][2] = { {0, 1}, {0, 1}, {0, 1}, {0, 1}, }; -static const int __initconst axp_dramclk_ratios[32][2] = { +static const int axp_dramclk_ratios[32][2] __initconst = { {0, 1}, {1, 2}, {2, 3}, {2, 3}, {1, 3}, {1, 2}, {1, 2}, {2, 6}, {0, 1}, {1, 3}, {2, 5}, {0, 1}, @@ -169,7 +169,7 @@ CLK_OF_DECLARE(axp_core_clk, "marvell,armada-xp-core-clock", * Clock Gating Control */ -static const struct clk_gating_soc_desc __initconst axp_gating_desc[] = { +static const struct clk_gating_soc_desc axp_gating_desc[] __initconst = { { "audio", NULL, 0, 0 }, { "ge3", NULL, 1, 0 }, { "ge2", NULL, 2, 0 }, From 114c4747a701f0a630b2ccebd269caf5808f2df7 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 12 Aug 2013 14:44:04 +0530 Subject: [PATCH 071/102] clk: dove: Fix incorrect placement of __initconst __initconst should be placed between the variable name and equal sign for the variable to be placed in the intended section. Signed-off-by: Sachin Kamat Acked-by: Gregory Clement Signed-off-by: Mike Turquette --- drivers/clk/mvebu/dove.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/mvebu/dove.c b/drivers/clk/mvebu/dove.c index 79d7aedf03fb..38aee1e3f242 100644 --- a/drivers/clk/mvebu/dove.c +++ b/drivers/clk/mvebu/dove.c @@ -74,12 +74,12 @@ enum { DOVE_CPU_TO_L2, DOVE_CPU_TO_DDR }; -static const struct coreclk_ratio __initconst dove_coreclk_ratios[] = { +static const struct coreclk_ratio dove_coreclk_ratios[] __initconst = { { .id = DOVE_CPU_TO_L2, .name = "l2clk", }, { .id = DOVE_CPU_TO_DDR, .name = "ddrclk", } }; -static const u32 __initconst dove_tclk_freqs[] = { +static const u32 dove_tclk_freqs[] __initconst = { 166666667, 125000000, 0, 0 @@ -92,7 +92,7 @@ static u32 __init dove_get_tclk_freq(void __iomem *sar) return dove_tclk_freqs[opt]; } -static const u32 __initconst dove_cpu_freqs[] = { +static const u32 dove_cpu_freqs[] __initconst = { 0, 0, 0, 0, 0, 1000000000, 933333333, 933333333, @@ -111,12 +111,12 @@ static u32 __init dove_get_cpu_freq(void __iomem *sar) return dove_cpu_freqs[opt]; } -static const int __initconst dove_cpu_l2_ratios[8][2] = { +static const int dove_cpu_l2_ratios[8][2] __initconst = { { 1, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 }, { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 } }; -static const int __initconst dove_cpu_ddr_ratios[16][2] = { +static const int dove_cpu_ddr_ratios[16][2] __initconst = { { 1, 1 }, { 0, 1 }, { 1, 2 }, { 2, 5 }, { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 }, { 1, 5 }, { 0, 1 }, { 1, 6 }, { 0, 1 }, @@ -164,7 +164,7 @@ CLK_OF_DECLARE(dove_core_clk, "marvell,dove-core-clock", dove_coreclk_init); * Clock Gating Control */ -static const struct clk_gating_soc_desc __initconst dove_gating_desc[] = { +static const struct clk_gating_soc_desc dove_gating_desc[] __initconst = { { "usb0", NULL, 0, 0 }, { "usb1", NULL, 1, 0 }, { "ge", "gephy", 2, 0 }, From 847b1c000ee02fa69043bc88b110f948bed2e136 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 12 Aug 2013 14:44:05 +0530 Subject: [PATCH 072/102] clk: kirkwood: Fix incorrect placement of __initconst __initconst should be placed between the variable name and equal sign for the variable to be placed in the intended section. Signed-off-by: Sachin Kamat Acked-by: Gregory Clement Signed-off-by: Mike Turquette --- drivers/clk/mvebu/kirkwood.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/clk/mvebu/kirkwood.c b/drivers/clk/mvebu/kirkwood.c index 71d24619ccdb..2636a55f29f9 100644 --- a/drivers/clk/mvebu/kirkwood.c +++ b/drivers/clk/mvebu/kirkwood.c @@ -78,7 +78,7 @@ enum { KIRKWOOD_CPU_TO_L2, KIRKWOOD_CPU_TO_DDR }; -static const struct coreclk_ratio __initconst kirkwood_coreclk_ratios[] = { +static const struct coreclk_ratio kirkwood_coreclk_ratios[] __initconst = { { .id = KIRKWOOD_CPU_TO_L2, .name = "l2clk", }, { .id = KIRKWOOD_CPU_TO_DDR, .name = "ddrclk", } }; @@ -90,7 +90,7 @@ static u32 __init kirkwood_get_tclk_freq(void __iomem *sar) return (opt) ? 166666667 : 200000000; } -static const u32 __initconst kirkwood_cpu_freqs[] = { +static const u32 kirkwood_cpu_freqs[] __initconst = { 0, 0, 0, 0, 600000000, 0, @@ -111,12 +111,12 @@ static u32 __init kirkwood_get_cpu_freq(void __iomem *sar) return kirkwood_cpu_freqs[opt]; } -static const int __initconst kirkwood_cpu_l2_ratios[8][2] = { +static const int kirkwood_cpu_l2_ratios[8][2] __initconst = { { 0, 1 }, { 1, 2 }, { 0, 1 }, { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 }, { 0, 1 } }; -static const int __initconst kirkwood_cpu_ddr_ratios[16][2] = { +static const int kirkwood_cpu_ddr_ratios[16][2] __initconst = { { 0, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 }, { 1, 3 }, { 0, 1 }, { 1, 4 }, { 2, 9 }, { 1, 5 }, { 1, 6 }, { 0, 1 }, { 0, 1 }, @@ -145,7 +145,7 @@ static void __init kirkwood_get_clk_ratio( } } -static const u32 __initconst mv88f6180_cpu_freqs[] = { +static const u32 mv88f6180_cpu_freqs[] __initconst = { 0, 0, 0, 0, 0, 600000000, 800000000, @@ -158,7 +158,7 @@ static u32 __init mv88f6180_get_cpu_freq(void __iomem *sar) return mv88f6180_cpu_freqs[opt]; } -static const int __initconst mv88f6180_cpu_ddr_ratios[8][2] = { +static const int mv88f6180_cpu_ddr_ratios[8][2] __initconst = { { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, { 1, 3 }, { 1, 4 }, { 1, 5 } }; @@ -219,7 +219,7 @@ CLK_OF_DECLARE(mv88f6180_core_clk, "marvell,mv88f6180-core-clock", * Clock Gating Control */ -static const struct clk_gating_soc_desc __initconst kirkwood_gating_desc[] = { +static const struct clk_gating_soc_desc kirkwood_gating_desc[] __initconst = { { "ge0", NULL, 0, 0 }, { "pex0", NULL, 2, 0 }, { "usb0", NULL, 3, 0 }, From 52be7cc862942ea0a53031b3b1ca84dc95422b5b Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 12 Aug 2013 14:44:06 +0530 Subject: [PATCH 073/102] clk: sunxi: Fix incorrect placement of __initconst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit __initconst should be placed between the variable name and equal sign for the variable to be placed in the intended section. Signed-off-by: Sachin Kamat Cc: Emilio López Signed-off-by: Mike Turquette [mturquette@linaro.org: refreshed patch based on sunxi changes] --- drivers/clk/sunxi/clk-sunxi.c | 60 +++++++++++++++++------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index d39f213f0fbe..34ee69f4d50c 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -288,17 +288,17 @@ static struct clk_factors_config sun4i_apb1_config = { .pwidth = 2, }; -static const __initconst struct factors_data sun4i_pll1_data = { +static const struct factors_data sun4i_pll1_data __initconst = { .table = &sun4i_pll1_config, .getter = sun4i_get_pll1_factors, }; -static const __initconst struct factors_data sun6i_a31_pll1_data = { +static const struct factors_data sun6i_a31_pll1_data __initconst = { .table = &sun6i_a31_pll1_config, .getter = sun6i_a31_get_pll1_factors, }; -static const __initconst struct factors_data sun4i_apb1_data = { +static const struct factors_data sun4i_apb1_data __initconst = { .table = &sun4i_apb1_config, .getter = sun4i_get_apb1_factors, }; @@ -336,15 +336,15 @@ struct mux_data { u8 shift; }; -static const __initconst struct mux_data sun4i_cpu_mux_data = { +static const struct mux_data sun4i_cpu_mux_data __initconst = { .shift = 16, }; -static const __initconst struct mux_data sun6i_a31_ahb1_mux_data = { +static const struct mux_data sun6i_a31_ahb1_mux_data __initconst = { .shift = 12, }; -static const __initconst struct mux_data sun4i_apb1_mux_data = { +static const struct mux_data sun4i_apb1_mux_data __initconst = { .shift = 24, }; @@ -385,25 +385,25 @@ struct div_data { u8 width; }; -static const __initconst struct div_data sun4i_axi_data = { +static const struct div_data sun4i_axi_data __initconst = { .shift = 0, .pow = 0, .width = 2, }; -static const __initconst struct div_data sun4i_ahb_data = { +static const struct div_data sun4i_ahb_data __initconst = { .shift = 4, .pow = 1, .width = 2, }; -static const __initconst struct div_data sun4i_apb0_data = { +static const struct div_data sun4i_apb0_data __initconst = { .shift = 8, .pow = 1, .width = 2, }; -static const __initconst struct div_data sun6i_a31_apb2_div_data = { +static const struct div_data sun6i_a31_apb2_div_data __initconst = { .shift = 0, .pow = 0, .width = 4, @@ -443,67 +443,67 @@ struct gates_data { DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE); }; -static const __initconst struct gates_data sun4i_axi_gates_data = { +static const struct gates_data sun4i_axi_gates_data __initconst = { .mask = {1}, }; -static const __initconst struct gates_data sun4i_ahb_gates_data = { +static const struct gates_data sun4i_ahb_gates_data __initconst = { .mask = {0x7F77FFF, 0x14FB3F}, }; -static const __initconst struct gates_data sun5i_a10s_ahb_gates_data = { +static const struct gates_data sun5i_a10s_ahb_gates_data __initconst = { .mask = {0x147667e7, 0x185915}, }; -static const __initconst struct gates_data sun5i_a13_ahb_gates_data = { +static const struct gates_data sun5i_a13_ahb_gates_data __initconst = { .mask = {0x107067e7, 0x185111}, }; -static const __initconst struct gates_data sun6i_a31_ahb1_gates_data = { +static const struct gates_data sun6i_a31_ahb1_gates_data __initconst = { .mask = {0xEDFE7F62, 0x794F931}, }; -static const __initconst struct gates_data sun7i_a20_ahb_gates_data = { +static const struct gates_data sun7i_a20_ahb_gates_data __initconst = { .mask = { 0x12f77fff, 0x16ff3f }, }; -static const __initconst struct gates_data sun4i_apb0_gates_data = { +static const struct gates_data sun4i_apb0_gates_data __initconst = { .mask = {0x4EF}, }; -static const __initconst struct gates_data sun5i_a10s_apb0_gates_data = { +static const struct gates_data sun5i_a10s_apb0_gates_data __initconst = { .mask = {0x469}, }; -static const __initconst struct gates_data sun5i_a13_apb0_gates_data = { +static const struct gates_data sun5i_a13_apb0_gates_data __initconst = { .mask = {0x61}, }; -static const __initconst struct gates_data sun7i_a20_apb0_gates_data = { +static const struct gates_data sun7i_a20_apb0_gates_data __initconst = { .mask = { 0x4ff }, }; -static const __initconst struct gates_data sun4i_apb1_gates_data = { +static const struct gates_data sun4i_apb1_gates_data __initconst = { .mask = {0xFF00F7}, }; -static const __initconst struct gates_data sun5i_a10s_apb1_gates_data = { +static const struct gates_data sun5i_a10s_apb1_gates_data __initconst = { .mask = {0xf0007}, }; -static const __initconst struct gates_data sun5i_a13_apb1_gates_data = { +static const struct gates_data sun5i_a13_apb1_gates_data __initconst = { .mask = {0xa0007}, }; -static const __initconst struct gates_data sun6i_a31_apb1_gates_data = { +static const struct gates_data sun6i_a31_apb1_gates_data __initconst = { .mask = {0x3031}, }; -static const __initconst struct gates_data sun6i_a31_apb2_gates_data = { +static const struct gates_data sun6i_a31_apb2_gates_data __initconst = { .mask = {0x3F000F}, }; -static const __initconst struct gates_data sun7i_a20_apb1_gates_data = { +static const struct gates_data sun7i_a20_apb1_gates_data __initconst = { .mask = { 0xff80ff }, }; @@ -557,7 +557,7 @@ static void __init sunxi_gates_clk_setup(struct device_node *node, } /* Matches for factors clocks */ -static const __initconst struct of_device_id clk_factors_match[] = { +static const struct of_device_id clk_factors_match[] __initconst = { {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,}, {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,}, @@ -565,7 +565,7 @@ static const __initconst struct of_device_id clk_factors_match[] = { }; /* Matches for divider clocks */ -static const __initconst struct of_device_id clk_div_match[] = { +static const struct of_device_id clk_div_match[] __initconst = { {.compatible = "allwinner,sun4i-axi-clk", .data = &sun4i_axi_data,}, {.compatible = "allwinner,sun4i-ahb-clk", .data = &sun4i_ahb_data,}, {.compatible = "allwinner,sun4i-apb0-clk", .data = &sun4i_apb0_data,}, @@ -574,7 +574,7 @@ static const __initconst struct of_device_id clk_div_match[] = { }; /* Matches for mux clocks */ -static const __initconst struct of_device_id clk_mux_match[] = { +static const struct of_device_id clk_mux_match[] __initconst = { {.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,}, {.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &sun4i_apb1_mux_data,}, {.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,}, @@ -582,7 +582,7 @@ static const __initconst struct of_device_id clk_mux_match[] = { }; /* Matches for gate clocks */ -static const __initconst struct of_device_id clk_gates_match[] = { +static const struct of_device_id clk_gates_match[] __initconst = { {.compatible = "allwinner,sun4i-axi-gates-clk", .data = &sun4i_axi_gates_data,}, {.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &sun4i_ahb_gates_data,}, {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,}, From 5b0dde99e8a9971030b36096ee1dc85a1a12ff57 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 12 Aug 2013 14:44:07 +0530 Subject: [PATCH 074/102] clk: s3c64xx: Fix incorrect placement of __initdata __initdata should be placed between the variable name and equal sign for the variable to be placed in the intended section. Signed-off-by: Sachin Kamat Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-s3c64xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c index eeda5675bd17..7d2c84265947 100644 --- a/drivers/clk/samsung/clk-s3c64xx.c +++ b/drivers/clk/samsung/clk-s3c64xx.c @@ -65,7 +65,7 @@ enum s3c64xx_plls { * List of controller registers to be saved and restored during * a suspend/resume cycle. */ -static __initdata unsigned long s3c64xx_clk_regs[] = { +static unsigned long s3c64xx_clk_regs[] __initdata = { APLL_LOCK, MPLL_LOCK, EPLL_LOCK, @@ -82,7 +82,7 @@ static __initdata unsigned long s3c64xx_clk_regs[] = { SCLK_GATE, }; -static __initdata unsigned long s3c6410_clk_regs[] = { +static unsigned long s3c6410_clk_regs[] __initdata = { CLK_SRC2, MEM0_GATE, }; From 89ac8567b97fea558238c4bb73637471f9197813 Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Wed, 28 Aug 2013 18:18:47 +0300 Subject: [PATCH 075/102] clk: tegra30: Don't wait for PLL_U lock bit The lock bit on PLL_U does not seem to be working correctly and sometimes never gets set when waiting for the PLL to come up. Remove the TEGRA_PLL_USE_LOCK flag to use a constant delay. Signed-off-by: Tuomas Tynkkynen Tested-by: Stephen Warren Acked-by: Stephen Warren Signed-off-by: Mike Turquette --- drivers/clk/tegra/clk-tegra30.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index b09ebf64cdc8..dbe7c8003c5c 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -971,7 +971,7 @@ static void __init tegra30_pll_init(void) /* PLLU */ clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc_base, 0, 0, &pll_u_params, TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | - TEGRA_PLL_SET_LFCON | TEGRA_PLL_USE_LOCK, + TEGRA_PLL_SET_LFCON, pll_u_freq_table, NULL); clk_register_clkdev(clk, "pll_u", NULL); From e2815b048aa05bc2e1c0a49ffd23ebed47e9c813 Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Fri, 23 Aug 2013 12:46:59 +0530 Subject: [PATCH 076/102] clk/exynos5250: change parent to aclk200_disp1 for hdmi subsystem parent of hdmi and mixer block is mentioned as aclk200 which is not correct. It is clocked by the ouput of aclk200_disp1. Hence parent for mixer and hdmi clocks is changed to aclk200_disp1. Signed-off-by: Rahul Sharma Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos5250.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index a9916a46e7a7..d90e59326252 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -489,8 +489,8 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { GATE(mie1, "mie1", "aclk200", GATE_IP_DISP1, 1, 0, 0), GATE(dsim0, "dsim0", "aclk200", GATE_IP_DISP1, 3, 0, 0), GATE(dp, "dp", "aclk200", GATE_IP_DISP1, 4, 0, 0), - GATE(mixer, "mixer", "aclk200", GATE_IP_DISP1, 5, 0, 0), - GATE(hdmi, "hdmi", "aclk200", GATE_IP_DISP1, 6, 0, 0), + GATE(mixer, "mixer", "mout_aclk200_disp1", GATE_IP_DISP1, 5, 0, 0), + GATE(hdmi, "hdmi", "mout_aclk200_disp1", GATE_IP_DISP1, 6, 0, 0), GATE(g2d, "g2d", "aclk200", GATE_IP_ACP, 3, 0, 0), }; From a5828a6c5f51a909c3c4dbbf22c76c75a033b2e9 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 29 Aug 2013 15:13:28 +0100 Subject: [PATCH 077/102] clk: wm831x: Provide is_prepared() rather than is_enabled() Since the driver was written an is_prepared() operation has been made possible. Since the driver uses I2C I/O only prepare operations are provided so move the is_enabled() operation over to is_prepared(). Signed-off-by: Mark Brown Signed-off-by: Mike Turquette --- drivers/clk/clk-wm831x.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c index 1b3f8c9b98cc..c370ecb6b685 100644 --- a/drivers/clk/clk-wm831x.c +++ b/drivers/clk/clk-wm831x.c @@ -31,7 +31,7 @@ struct wm831x_clk { bool xtal_ena; }; -static int wm831x_xtal_is_enabled(struct clk_hw *hw) +static int wm831x_xtal_is_prepared(struct clk_hw *hw) { struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk, xtal_hw); @@ -52,7 +52,7 @@ static unsigned long wm831x_xtal_recalc_rate(struct clk_hw *hw, } static const struct clk_ops wm831x_xtal_ops = { - .is_enabled = wm831x_xtal_is_enabled, + .is_prepared = wm831x_xtal_is_prepared, .recalc_rate = wm831x_xtal_recalc_rate, }; @@ -73,7 +73,7 @@ static const unsigned long wm831x_fll_auto_rates[] = { 24576000, }; -static int wm831x_fll_is_enabled(struct clk_hw *hw) +static int wm831x_fll_is_prepared(struct clk_hw *hw) { struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk, fll_hw); @@ -170,7 +170,7 @@ static int wm831x_fll_set_rate(struct clk_hw *hw, unsigned long rate, if (i == ARRAY_SIZE(wm831x_fll_auto_rates)) return -EINVAL; - if (wm831x_fll_is_enabled(hw)) + if (wm831x_fll_is_prepared(hw)) return -EPERM; return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_2, @@ -220,7 +220,7 @@ static u8 wm831x_fll_get_parent(struct clk_hw *hw) } static const struct clk_ops wm831x_fll_ops = { - .is_enabled = wm831x_fll_is_enabled, + .is_prepared = wm831x_fll_is_prepared, .prepare = wm831x_fll_prepare, .unprepare = wm831x_fll_unprepare, .round_rate = wm831x_fll_round_rate, @@ -237,7 +237,7 @@ static struct clk_init_data wm831x_fll_init = { .flags = CLK_SET_RATE_GATE, }; -static int wm831x_clkout_is_enabled(struct clk_hw *hw) +static int wm831x_clkout_is_prepared(struct clk_hw *hw) { struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk, clkout_hw); @@ -335,7 +335,7 @@ static int wm831x_clkout_set_parent(struct clk_hw *hw, u8 parent) } static const struct clk_ops wm831x_clkout_ops = { - .is_enabled = wm831x_clkout_is_enabled, + .is_prepared = wm831x_clkout_is_prepared, .prepare = wm831x_clkout_prepare, .unprepare = wm831x_clkout_unprepare, .get_parent = wm831x_clkout_get_parent, From c9f3f0815909386c2dba1cdb803af5cef34ec796 Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Thu, 29 Aug 2013 11:07:05 +0530 Subject: [PATCH 078/102] clk/exynos5420: add sclk_hdmiphy to the list of special clocks Add sclk_hdmiphy to the list of exposed clocks. This is required by hdmi driver to change the parent of hdmi clock. Signed-off-by: Rahul Sharma Acked-by: Tomasz Figa Signed-off-by: Mike Turquette --- Documentation/devicetree/bindings/clock/exynos5420-clock.txt | 1 + drivers/clk/samsung/clk-exynos5420.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/exynos5420-clock.txt b/Documentation/devicetree/bindings/clock/exynos5420-clock.txt index 9bcc4b1bff51..596a36868a56 100644 --- a/Documentation/devicetree/bindings/clock/exynos5420-clock.txt +++ b/Documentation/devicetree/bindings/clock/exynos5420-clock.txt @@ -59,6 +59,7 @@ clock which they consume. sclk_pwm 155 sclk_gscl_wa 156 sclk_gscl_wb 157 + sclk_hdmiphy 158 [Peripheral Clock Gates] diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index e035fd0afbc7..a86cadc76650 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -120,7 +120,7 @@ enum exynos5420_clks { sclk_i2s2, sclk_pcm1, sclk_pcm2, sclk_spdif, sclk_hdmi, sclk_pixel, sclk_dp1, sclk_mipi1, sclk_fimd1, sclk_maudio0, sclk_maupcm0, sclk_usbd300, sclk_usbd301, sclk_usbphy300, sclk_usbphy301, sclk_unipro, - sclk_pwm, sclk_gscl_wa, sclk_gscl_wb, + sclk_pwm, sclk_gscl_wa, sclk_gscl_wb, sclk_hdmiphy, /* gate clocks */ aclk66_peric = 256, uart0, uart1, uart2, uart3, i2c0, i2c1, i2c2, i2c3, @@ -297,7 +297,7 @@ static struct samsung_fixed_rate_clock exynos5420_fixed_rate_ext_clks[] __initda /* fixed rate clocks generated inside the soc */ static struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = { - FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000), + FRATE(sclk_hdmiphy, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000), FRATE(none, "sclk_pwi", NULL, CLK_IS_ROOT, 24000000), FRATE(none, "sclk_usbh20", NULL, CLK_IS_ROOT, 48000000), FRATE(none, "mphy_refclk_ixtal24", NULL, CLK_IS_ROOT, 48000000), From 9b229d8b04b4050938257e1f2a12860670e52e80 Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Thu, 29 Aug 2013 11:07:06 +0530 Subject: [PATCH 079/102] clk/exynos5420: add gate clock for mixer sysmmu Adding sysmmu clock for mixer for exynos5420. Signed-off-by: Rahul Sharma Acked-by: Tomasz Figa Signed-off-by: Mike Turquette --- Documentation/devicetree/bindings/clock/exynos5420-clock.txt | 1 + drivers/clk/samsung/clk-exynos5420.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/exynos5420-clock.txt b/Documentation/devicetree/bindings/clock/exynos5420-clock.txt index 596a36868a56..5758a690d789 100644 --- a/Documentation/devicetree/bindings/clock/exynos5420-clock.txt +++ b/Documentation/devicetree/bindings/clock/exynos5420-clock.txt @@ -180,6 +180,7 @@ clock which they consume. fimc_lite3 495 aclk_g3d 500 g3d 501 + smmu_mixer 502 Example 1: An example of a clock controller node is listed below. diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index a86cadc76650..4e0c13e88569 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -138,7 +138,7 @@ enum exynos5420_clks { aclk300_gscl = 460, smmu_gscl0, smmu_gscl1, gscl_wa, gscl_wb, gscl0, gscl1, clk_3aa, aclk266_g2d = 470, sss, slim_sss, mdma0, aclk333_g2d = 480, g2d, aclk333_432_gscl = 490, smmu_3aa, smmu_fimcl0, - smmu_fimcl1, smmu_fimcl3, fimc_lite3, aclk_g3d = 500, g3d, + smmu_fimcl1, smmu_fimcl3, fimc_lite3, aclk_g3d = 500, g3d, smmu_mixer, nr_clks, }; @@ -725,6 +725,7 @@ static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { GATE(smmu_mscl0, "smmu_mscl0", "aclk400_mscl", GATE_IP_MSCL, 8, 0, 0), GATE(smmu_mscl1, "smmu_mscl1", "aclk400_mscl", GATE_IP_MSCL, 9, 0, 0), GATE(smmu_mscl2, "smmu_mscl2", "aclk400_mscl", GATE_IP_MSCL, 10, 0, 0), + GATE(smmu_mixer, "smmu_mixer", "aclk200_disp1", GATE_IP_DISP1, 9, 0, 0), }; static struct samsung_pll_clock exynos5420_plls[nr_plls] __initdata = { From 14d87cda8dc6d35b2a6cbbc1e1a5f6df4d9645ae Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Thu, 29 Aug 2013 11:07:07 +0530 Subject: [PATCH 080/102] clk/exynos5420: fix the order of parents of hdmi mux Listing sclk_hdmiphy at 0th position in the list of parents is causing wrong configuration in reg SRC_DISP10. Signed-off-by: Rahul Sharma Acked-by: Tomasz Figa Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos5420.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 4e0c13e88569..522c033f5257 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -286,7 +286,7 @@ PNAME(audio2_p) = { "fin_pll", "cdclk2", "sclk_dpll", "sclk_mpll", "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; PNAME(spdif_p) = { "fin_pll", "dout_audio0", "dout_audio1", "dout_audio2", "spdif_extclk", "sclk_ipll", "sclk_epll", "sclk_rpll" }; -PNAME(hdmi_p) = { "sclk_hdmiphy", "dout_hdmi_pixel" }; +PNAME(hdmi_p) = { "dout_hdmi_pixel", "sclk_hdmiphy" }; PNAME(maudio0_p) = { "fin_pll", "maudio_clk", "sclk_dpll", "sclk_mpll", "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; From 4625f1b5d44c7f38801c0553fa90b33577307843 Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Thu, 29 Aug 2013 11:07:08 +0530 Subject: [PATCH 081/102] clk/exynos5420: add hdmi mux to change parents in hdmi driver hdmi driver needs to change the parent of hdmi clock to pixel clock or hdmiphy clock, based on the stability of hdmiphy. This patch is exposing the mux for changing the parent. Signed-off-by: Rahul Sharma Acked-by: Tomasz Figa Signed-off-by: Mike Turquette --- Documentation/devicetree/bindings/clock/exynos5420-clock.txt | 5 +++++ drivers/clk/samsung/clk-exynos5420.c | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/exynos5420-clock.txt b/Documentation/devicetree/bindings/clock/exynos5420-clock.txt index 5758a690d789..343430bd5573 100644 --- a/Documentation/devicetree/bindings/clock/exynos5420-clock.txt +++ b/Documentation/devicetree/bindings/clock/exynos5420-clock.txt @@ -182,6 +182,11 @@ clock which they consume. g3d 501 smmu_mixer 502 + Mux ID + ---------------------------- + + mout_hdmi 640 + Example 1: An example of a clock controller node is listed below. clock: clock-controller@0x10010000 { diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 522c033f5257..78465a5aa8e9 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -140,6 +140,9 @@ enum exynos5420_clks { aclk333_g2d = 480, g2d, aclk333_432_gscl = 490, smmu_3aa, smmu_fimcl0, smmu_fimcl1, smmu_fimcl3, fimc_lite3, aclk_g3d = 500, g3d, smmu_mixer, + /* mux clocks */ + mout_hdmi = 640, + nr_clks, }; @@ -400,7 +403,7 @@ static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = { MUX(none, "mout_mipi1", group2_p, SRC_DISP10, 16, 3), MUX(none, "mout_dp1", group2_p, SRC_DISP10, 20, 3), MUX(none, "mout_pixel", group2_p, SRC_DISP10, 24, 3), - MUX(none, "mout_hdmi", hdmi_p, SRC_DISP10, 28, 1), + MUX(mout_hdmi, "mout_hdmi", hdmi_p, SRC_DISP10, 28, 1), /* MAU Block */ MUX(none, "mout_maudio0", maudio0_p, SRC_MAU, 28, 3), From 0044cbcd667520fedbd96d07c20cfe5b7473f71a Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Thu, 29 Aug 2013 11:07:09 +0530 Subject: [PATCH 082/102] clk/exynos5420: assign dout_pixel id to pixel clock divider dout_pixel is a new ID allocated for pixel clock divider. It is queried in the driver to pass as the parent to hdmi clock while switching between parents. Signed-off-by: Rahul Sharma Acked-by: Tomasz Figa Signed-off-by: Mike Turquette --- Documentation/devicetree/bindings/clock/exynos5420-clock.txt | 5 +++++ drivers/clk/samsung/clk-exynos5420.c | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/exynos5420-clock.txt b/Documentation/devicetree/bindings/clock/exynos5420-clock.txt index 343430bd5573..32aa34ecad36 100644 --- a/Documentation/devicetree/bindings/clock/exynos5420-clock.txt +++ b/Documentation/devicetree/bindings/clock/exynos5420-clock.txt @@ -187,6 +187,11 @@ clock which they consume. mout_hdmi 640 + Divider ID + ---------------------------- + + dout_pixel 768 + Example 1: An example of a clock controller node is listed below. clock: clock-controller@0x10010000 { diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 78465a5aa8e9..48c4a9350b91 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -143,6 +143,9 @@ enum exynos5420_clks { /* mux clocks */ mout_hdmi = 640, + /* divider clocks */ + dout_pixel = 768, + nr_clks, }; @@ -463,7 +466,7 @@ static struct samsung_div_clock exynos5420_div_clks[] __initdata = { DIV(none, "dout_fimd1", "mout_fimd1", DIV_DISP10, 0, 4), DIV(none, "dout_mipi1", "mout_mipi1", DIV_DISP10, 16, 8), DIV(none, "dout_dp1", "mout_dp1", DIV_DISP10, 24, 4), - DIV(none, "dout_hdmi_pixel", "mout_pixel", DIV_DISP10, 28, 4), + DIV(dout_pixel, "dout_hdmi_pixel", "mout_pixel", DIV_DISP10, 28, 4), /* Audio Block */ DIV(none, "dout_maudio0", "mout_maudio0", DIV_MAU, 20, 4), From 08442ce993deeb15a070c14cc3f3459e87d111e0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 29 Aug 2013 12:21:01 +0100 Subject: [PATCH 083/102] clk: wm831x: Initialise wm831x pointer on init Otherwise any attempt to interact with the hardware will crash. This is what happens when drivers get written blind. Signed-off-by: Mark Brown Cc: stable@vger.kernel.org Signed-off-by: Mike Turquette --- drivers/clk/clk-wm831x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c index c370ecb6b685..805b4c344006 100644 --- a/drivers/clk/clk-wm831x.c +++ b/drivers/clk/clk-wm831x.c @@ -360,6 +360,8 @@ static int wm831x_clk_probe(struct platform_device *pdev) if (!clkdata) return -ENOMEM; + clkdata->wm831x = wm831x; + /* XTAL_ENA can only be set via OTP/InstantConfig so just read once */ ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2); if (ret < 0) { From 903efc553f738030a4ffa23fa03e7f329655c1c2 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Thu, 29 Aug 2013 12:10:51 +0100 Subject: [PATCH 084/102] clk: fix new_parent dereference before null check Commit 71472c0 (clk: add support for clock reparent on set_rate) added a dereference of the new_parent pointer in clk_reparent(), but as detected by smatch clk_reparent() later checks whether new_parent is NULL. The dereference was in order to clear the new parent's new_child pointer to avoid duplicate POST_RATE_CHANGE notifications, so clearly isn't necessary if the new parent is NULL, so move it inside the "if (new_parent)" block. Reported-by: Dan Carpenter Signed-off-by: James Hogan Signed-off-by: Mike Turquette --- drivers/clk/clk.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 2db08c01ef51..02e75d4e0a77 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1108,16 +1108,17 @@ static u8 clk_fetch_parent_index(struct clk *clk, struct clk *parent) static void clk_reparent(struct clk *clk, struct clk *new_parent) { - /* avoid duplicate POST_RATE_CHANGE notifications */ - if (new_parent->new_child == clk) - new_parent->new_child = NULL; - hlist_del(&clk->child_node); - if (new_parent) + if (new_parent) { + /* avoid duplicate POST_RATE_CHANGE notifications */ + if (new_parent->new_child == clk) + new_parent->new_child = NULL; + hlist_add_head(&clk->child_node, &new_parent->children); - else + } else { hlist_add_head(&clk->child_node, &clk_orphan_list); + } clk->parent = new_parent; } From b05c683637fd538686030ec46c6717439d5571ab Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 3 Sep 2013 09:43:51 +0200 Subject: [PATCH 085/102] clk: Move symbol export to proper location The __clk_get_flags() symbol is exported immediately following the clk_unprepare_unused_subtree() function. This is unusual, since a symbol export typically follows body of the function that it exports. Signed-off-by: Thierry Reding Signed-off-by: Mike Turquette --- drivers/clk/clk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 02e75d4e0a77..cc4cb6fd7d83 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -458,7 +458,6 @@ static void clk_unprepare_unused_subtree(struct clk *clk) clk->ops->unprepare(clk->hw); } } -EXPORT_SYMBOL_GPL(__clk_get_flags); /* caller must hold prepare_lock */ static void clk_disable_unused_subtree(struct clk *clk) @@ -607,6 +606,7 @@ unsigned long __clk_get_flags(struct clk *clk) { return !clk ? 0 : clk->flags; } +EXPORT_SYMBOL_GPL(__clk_get_flags); bool __clk_is_prepared(struct clk *clk) { From f51a87a9fbd00d4081874dd24271071a1b491daa Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 26 Aug 2013 19:08:56 +0200 Subject: [PATCH 086/102] pwm: samsung: Update DT bindings documentation to cover clocks PWM driver consumes at least one and up to three clocks, which need to be specified in device tree when used. This patch updates bindings documentation to add information about clocks. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Acked-by: Stephen Warren Reviewed-by: Sylwester Nawrocki Signed-off-by: Mike Turquette --- .../devicetree/bindings/pwm/pwm-samsung.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/devicetree/bindings/pwm/pwm-samsung.txt b/Documentation/devicetree/bindings/pwm/pwm-samsung.txt index ac67c687a327..39f0ca7008ba 100644 --- a/Documentation/devicetree/bindings/pwm/pwm-samsung.txt +++ b/Documentation/devicetree/bindings/pwm/pwm-samsung.txt @@ -19,6 +19,16 @@ Required properties: - reg: base address and size of register area - interrupts: list of timer interrupts (one interrupt per timer, starting at timer 0) +- clock-names: should contain all following required clock names: + - "timers" - PWM base clock used to generate PWM signals, + and any subset of following optional clock names: + - "pwm-tclk0" - first external PWM clock source, + - "pwm-tclk1" - second external PWM clock source. + Note that not all IP variants allow using all external clock sources. + Refer to SoC documentation to learn which clock source configurations + are available. +- clocks: should contain clock specifiers of all clocks, which input names + have been specified in clock-names property, in same order. - #pwm-cells: number of cells used for PWM specifier - must be 3 the specifier format is as follows: - phandle to PWM controller node @@ -38,6 +48,8 @@ Example: reg = <0x7f006000 0x1000>; interrupt-parent = <&vic0>; interrupts = <23>, <24>, <25>, <27>, <28>; + clocks = <&clock 67>; + clock-names = "timers"; samsung,pwm-outputs = <0>, <1>; #pwm-cells = <3>; } From ec06dbe773084f9dfadd38d46d7b783d575c2306 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 26 Aug 2013 19:08:57 +0200 Subject: [PATCH 087/102] ARM: dts: exynos4: Specify PWM clocks in PWM node Since pwm-samsung bindings require at least one clock to be specified, this patch adds the missing clocks and clock-names properties to specify clocks used by PWM block on Exynos4 SoCs. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mike Turquette --- arch/arm/boot/dts/exynos4.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index 3f94fe8e3706..b8c6e90dcc5c 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi @@ -342,6 +342,8 @@ compatible = "samsung,exynos4210-pwm"; reg = <0x139D0000 0x1000>; interrupts = <0 37 0>, <0 38 0>, <0 39 0>, <0 40 0>, <0 41 0>; + clocks = <&clock 336>; + clock-names = "timers"; #pwm-cells = <2>; status = "disabled"; }; From a1fa6f503aad8da91c4cc8dd0e71d2789d78d3f6 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 26 Aug 2013 19:08:58 +0200 Subject: [PATCH 088/102] clocksource: samsung_pwm_timer: Get clock from device tree When booting with device tree static clkdev aliases should not be used. This patch modifies the samsung_pwm_timer driver to use DT-based clock lookup when booting with device tree. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mike Turquette --- drivers/clocksource/samsung_pwm_timer.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c index 584b5472eea3..32950c3ed374 100644 --- a/drivers/clocksource/samsung_pwm_timer.c +++ b/drivers/clocksource/samsung_pwm_timer.c @@ -349,10 +349,6 @@ static void __init samsung_clocksource_init(void) static void __init samsung_timer_resources(void) { - pwm.timerclk = clk_get(NULL, "timers"); - if (IS_ERR(pwm.timerclk)) - panic("failed to get timers clock for timer"); - clk_prepare_enable(pwm.timerclk); pwm.tcnt_max = (1UL << pwm.variant.bits) - 1; @@ -397,6 +393,10 @@ void __init samsung_pwm_clocksource_init(void __iomem *base, memcpy(&pwm.variant, variant, sizeof(pwm.variant)); memcpy(pwm.irq, irqs, SAMSUNG_PWM_NUM * sizeof(*irqs)); + pwm.timerclk = clk_get(NULL, "timers"); + if (IS_ERR(pwm.timerclk)) + panic("failed to get timers clock for timer"); + _samsung_pwm_clocksource_init(); } @@ -437,6 +437,10 @@ static void __init samsung_pwm_alloc(struct device_node *np, return; } + pwm.timerclk = of_clk_get_by_name(np, "timers"); + if (IS_ERR(pwm.timerclk)) + panic("failed to get timers clock for timer"); + _samsung_pwm_clocksource_init(); } From e6c3e730a75faee17ebbf3220c00e3039ab49f53 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 26 Aug 2013 19:08:59 +0200 Subject: [PATCH 089/102] clk: samsung: exynos4: Use separate aliases for cpufreq related clocks Exynos cpufreq driver is the only remaining piece of code that needs static clkdev aliases for operation, because it can not do device tree based clock lookups yet. This patch moves clock alias definitions for those clocks to separate arrays that can be used with samsung_clk_register_alias() helper. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos4.c | 35 ++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 742b4c58ced9..d70d3cbaacfe 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -392,9 +392,8 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = { MUX(none, "mout_g2d", mout_g2d_p, E4210_SRC_IMAGE, 8, 1), MUX(none, "mout_fimd1", group1_p4210, E4210_SRC_LCD1, 0, 4), MUX(none, "mout_mipi1", group1_p4210, E4210_SRC_LCD1, 12, 4), - MUX_A(sclk_mpll, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1, "mout_mpll"), - MUX_A(mout_core, "mout_core", mout_core_p4210, - SRC_CPU, 16, 1, "moutcore"), + MUX(sclk_mpll, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1), + MUX(mout_core, "mout_core", mout_core_p4210, SRC_CPU, 16, 1), MUX_A(sclk_vpll, "sclk_vpll", sclk_vpll_p4210, SRC_TOP0, 8, 1, "sclk_vpll"), MUX(mout_fimc0, "mout_fimc0", group1_p4210, SRC_CAM, 0, 4), @@ -431,8 +430,8 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = { /* list of mux clocks supported in exynos4x12 soc */ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = { - MUX_A(mout_mpll_user_c, "mout_mpll_user_c", mout_mpll_user_p4x12, - SRC_CPU, 24, 1, "mout_mpll"), + MUX(mout_mpll_user_c, "mout_mpll_user_c", mout_mpll_user_p4x12, + SRC_CPU, 24, 1), MUX(none, "mout_aclk266_gps", aclk_p4412, SRC_TOP1, 4, 1), MUX(none, "mout_aclk400_mcuisp", aclk_p4412, SRC_TOP1, 8, 1), MUX(mout_mpll_user_t, "mout_mpll_user_t", mout_mpll_user_p4x12, @@ -456,8 +455,7 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = { SRC_DMC, 12, 1, "sclk_mpll"), MUX_A(sclk_vpll, "sclk_vpll", mout_vpll_p, SRC_TOP0, 8, 1, "sclk_vpll"), - MUX_A(mout_core, "mout_core", mout_core_p4x12, - SRC_CPU, 16, 1, "moutcore"), + MUX(mout_core, "mout_core", mout_core_p4x12, SRC_CPU, 16, 1), MUX(mout_fimc0, "mout_fimc0", group1_p4x12, SRC_CAM, 0, 4), MUX(mout_fimc1, "mout_fimc1", group1_p4x12, SRC_CAM, 4, 4), MUX(mout_fimc2, "mout_fimc2", group1_p4x12, SRC_CAM, 8, 4), @@ -545,7 +543,7 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = { DIV(none, "div_spi_pre2", "div_spi2", DIV_PERIL2, 8, 8), DIV(none, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4), DIV(none, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4), - DIV_A(arm_clk, "arm_clk", "div_core2", DIV_CPU0, 28, 3, "armclk"), + DIV(arm_clk, "arm_clk", "div_core2", DIV_CPU0, 28, 3), DIV_A(sclk_apll, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3, "sclk_apll"), DIV_F(none, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4, @@ -926,6 +924,20 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = { GATE(tmu_apbif, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0, 0), }; +static struct samsung_clock_alias exynos4_aliases[] __initdata = { + ALIAS(mout_core, NULL, "moutcore"), + ALIAS(arm_clk, NULL, "armclk"), + ALIAS(sclk_apll, NULL, "mout_apll"), +}; + +static struct samsung_clock_alias exynos4210_aliases[] __initdata = { + ALIAS(sclk_mpll, NULL, "mout_mpll"), +}; + +static struct samsung_clock_alias exynos4x12_aliases[] __initdata = { + ALIAS(mout_mpll_user_c, NULL, "mout_mpll"), +}; + /* * The parent of the fin_pll clock is selected by the XOM[0] bit. This bit * resides in chipid register space, outside of the clock controller memory @@ -1061,6 +1073,8 @@ static void __init exynos4_clk_init(struct device_node *np, ARRAY_SIZE(exynos4210_div_clks)); samsung_clk_register_gate(exynos4210_gate_clks, ARRAY_SIZE(exynos4210_gate_clks)); + samsung_clk_register_alias(exynos4210_aliases, + ARRAY_SIZE(exynos4210_aliases)); } else { samsung_clk_register_mux(exynos4x12_mux_clks, ARRAY_SIZE(exynos4x12_mux_clks)); @@ -1068,8 +1082,13 @@ static void __init exynos4_clk_init(struct device_node *np, ARRAY_SIZE(exynos4x12_div_clks)); samsung_clk_register_gate(exynos4x12_gate_clks, ARRAY_SIZE(exynos4x12_gate_clks)); + samsung_clk_register_alias(exynos4x12_aliases, + ARRAY_SIZE(exynos4x12_aliases)); } + samsung_clk_register_alias(exynos4_aliases, + ARRAY_SIZE(exynos4_aliases)); + pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n" "\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n", exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12", From 3a64789568f5f8afdc09fb33764f2ecbb72fb817 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 26 Aug 2013 19:09:00 +0200 Subject: [PATCH 090/102] clk: samsung: Modify _get_rate() helper to use __clk_lookup() There is no need to use clkdev inside the clock driver to retrieve the clocks for internal use. Instead __clk_lookup() helper can be used to look up clocks by their platform name. This patch modifies the behavior of _get_rate() helper to look up clocks by platform name and adjusts all users of it to pass platform names instead of clkdev aliases. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos4.c | 4 ++-- drivers/clk/samsung/clk-exynos5440.c | 2 +- drivers/clk/samsung/clk.c | 10 ++++------ 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index d70d3cbaacfe..cf7afde6e758 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1092,9 +1092,9 @@ static void __init exynos4_clk_init(struct device_node *np, pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n" "\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n", exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12", - _get_rate("sclk_apll"), _get_rate("mout_mpll"), + _get_rate("sclk_apll"), _get_rate("sclk_mpll"), _get_rate("sclk_epll"), _get_rate("sclk_vpll"), - _get_rate("armclk")); + _get_rate("arm_clk")); } diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c index 4ef38e045e39..f8658945bfd2 100644 --- a/drivers/clk/samsung/clk-exynos5440.c +++ b/drivers/clk/samsung/clk-exynos5440.c @@ -132,7 +132,7 @@ static void __init exynos5440_clk_init(struct device_node *np) samsung_clk_register_gate(exynos5440_gate_clks, ARRAY_SIZE(exynos5440_gate_clks)); - pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("armclk")); + pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk")); pr_info("exynos5440 clock initialization complete\n"); } CLK_OF_DECLARE(exynos5440_clk, "samsung,exynos5440-clock", exynos5440_clk_init); diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index cd3c40ab50f3..f503f32e2f80 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -307,14 +307,12 @@ void __init samsung_clk_of_register_fixed_ext( unsigned long _get_rate(const char *clk_name) { struct clk *clk; - unsigned long rate; - clk = clk_get(NULL, clk_name); - if (IS_ERR(clk)) { + clk = __clk_lookup(clk_name); + if (!clk) { pr_err("%s: could not find clock %s\n", __func__, clk_name); return 0; } - rate = clk_get_rate(clk); - clk_put(clk); - return rate; + + return clk_get_rate(clk); } From a11a2f8f254f0716b750f806547acb8bb6ce5e3f Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 26 Aug 2013 19:09:01 +0200 Subject: [PATCH 091/102] clk: samsung: exynos4: Remove unused static clkdev aliases Since Exynos does not support legacy non-DT boot anymore, most of clock lookups happen using device tree, so most of static clkdev aliases are no longer necessary. This patch removes them. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos4.c | 356 +++++++++++++++--------------- 1 file changed, 172 insertions(+), 184 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index cf7afde6e758..be5f6e4b9624 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -374,7 +374,7 @@ static struct samsung_mux_clock exynos4_mux_clks[] __initdata = { CLK_SET_RATE_PARENT, 0), MUX(none, "mout_spdif", mout_spdif_p, SRC_PERIL1, 8, 2), MUX(none, "mout_onenand1", mout_onenand1_p, SRC_TOP0, 0, 1), - MUX_A(sclk_epll, "sclk_epll", mout_epll_p, SRC_TOP0, 4, 1, "sclk_epll"), + MUX(sclk_epll, "sclk_epll", mout_epll_p, SRC_TOP0, 4, 1), MUX(none, "mout_onenand", mout_onenand_p, SRC_TOP0, 28, 1), }; @@ -394,8 +394,7 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = { MUX(none, "mout_mipi1", group1_p4210, E4210_SRC_LCD1, 12, 4), MUX(sclk_mpll, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1), MUX(mout_core, "mout_core", mout_core_p4210, SRC_CPU, 16, 1), - MUX_A(sclk_vpll, "sclk_vpll", sclk_vpll_p4210, - SRC_TOP0, 8, 1, "sclk_vpll"), + MUX(sclk_vpll, "sclk_vpll", sclk_vpll_p4210, SRC_TOP0, 8, 1), MUX(mout_fimc0, "mout_fimc0", group1_p4210, SRC_CAM, 0, 4), MUX(mout_fimc1, "mout_fimc1", group1_p4210, SRC_CAM, 4, 4), MUX(mout_fimc2, "mout_fimc2", group1_p4210, SRC_CAM, 8, 4), @@ -451,10 +450,8 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = { MUX(none, "mout_jpeg0", sclk_ampll_p4x12, E4X12_SRC_CAM1, 0, 1), MUX(none, "mout_jpeg1", sclk_evpll_p, E4X12_SRC_CAM1, 4, 1), MUX(none, "mout_jpeg", mout_jpeg_p, E4X12_SRC_CAM1, 8, 1), - MUX_A(sclk_mpll, "sclk_mpll", mout_mpll_p, - SRC_DMC, 12, 1, "sclk_mpll"), - MUX_A(sclk_vpll, "sclk_vpll", mout_vpll_p, - SRC_TOP0, 8, 1, "sclk_vpll"), + MUX(sclk_mpll, "sclk_mpll", mout_mpll_p, SRC_DMC, 12, 1), + MUX(sclk_vpll, "sclk_vpll", mout_vpll_p, SRC_TOP0, 8, 1), MUX(mout_core, "mout_core", mout_core_p4x12, SRC_CPU, 16, 1), MUX(mout_fimc0, "mout_fimc0", group1_p4x12, SRC_CAM, 0, 4), MUX(mout_fimc1, "mout_fimc1", group1_p4x12, SRC_CAM, 4, 4), @@ -544,8 +541,7 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = { DIV(none, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4), DIV(none, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4), DIV(arm_clk, "arm_clk", "div_core2", DIV_CPU0, 28, 3), - DIV_A(sclk_apll, "sclk_apll", "mout_apll", - DIV_CPU0, 24, 3, "sclk_apll"), + DIV(sclk_apll, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3), DIV_F(none, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4, CLK_SET_RATE_PARENT, 0), DIV_F(none, "div_mmc_pre0", "div_mmc0", DIV_FSYS1, 8, 8, @@ -630,160 +626,147 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = { CLK_SET_RATE_PARENT, 0), GATE(sclk_audio1, "sclk_audio1", "div_audio1", SRC_MASK_PERIL1, 0, CLK_SET_RATE_PARENT, 0), - GATE_D(vp, "s5p-mixer", "vp", "aclk160", GATE_IP_TV, 0, 0, 0), - GATE_D(mixer, "s5p-mixer", "mixer", "aclk160", GATE_IP_TV, 1, 0, 0), - GATE_D(hdmi, "exynos4-hdmi", "hdmi", "aclk160", GATE_IP_TV, 3, 0, 0), - GATE_A(pwm, "pwm", "aclk100", GATE_IP_PERIL, 24, 0, 0, "timers"), - GATE_A(sdmmc4, "sdmmc4", "aclk133", GATE_IP_FSYS, 9, 0, 0, "biu"), - GATE_A(usb_host, "usb_host", "aclk133", - GATE_IP_FSYS, 12, 0, 0, "usbhost"), - GATE_DA(sclk_fimc0, "exynos4-fimc.0", "sclk_fimc0", "div_fimc0", - SRC_MASK_CAM, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimc"), - GATE_DA(sclk_fimc1, "exynos4-fimc.1", "sclk_fimc1", "div_fimc1", - SRC_MASK_CAM, 4, CLK_SET_RATE_PARENT, 0, "sclk_fimc"), - GATE_DA(sclk_fimc2, "exynos4-fimc.2", "sclk_fimc2", "div_fimc2", - SRC_MASK_CAM, 8, CLK_SET_RATE_PARENT, 0, "sclk_fimc"), - GATE_DA(sclk_fimc3, "exynos4-fimc.3", "sclk_fimc3", "div_fimc3", - SRC_MASK_CAM, 12, CLK_SET_RATE_PARENT, 0, "sclk_fimc"), - GATE_DA(sclk_csis0, "s5p-mipi-csis.0", "sclk_csis0", "div_csis0", - SRC_MASK_CAM, 24, CLK_SET_RATE_PARENT, 0, "sclk_csis"), - GATE_DA(sclk_csis1, "s5p-mipi-csis.1", "sclk_csis1", "div_csis1", - SRC_MASK_CAM, 28, CLK_SET_RATE_PARENT, 0, "sclk_csis"), - GATE_DA(sclk_fimd0, "exynos4-fb.0", "sclk_fimd0", "div_fimd0", - SRC_MASK_LCD0, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimd"), - GATE_DA(sclk_mmc0, "exynos4-sdhci.0", "sclk_mmc0", "div_mmc_pre0", - SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0, - "mmc_busclk.2"), - GATE_DA(sclk_mmc1, "exynos4-sdhci.1", "sclk_mmc1", "div_mmc_pre1", - SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0, - "mmc_busclk.2"), - GATE_DA(sclk_mmc2, "exynos4-sdhci.2", "sclk_mmc2", "div_mmc_pre2", - SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0, - "mmc_busclk.2"), - GATE_DA(sclk_mmc3, "exynos4-sdhci.3", "sclk_mmc3", "div_mmc_pre3", - SRC_MASK_FSYS, 12, CLK_SET_RATE_PARENT, 0, - "mmc_busclk.2"), - GATE_DA(sclk_mmc4, NULL, "sclk_mmc4", "div_mmc_pre4", - SRC_MASK_FSYS, 16, CLK_SET_RATE_PARENT, 0, "ciu"), - GATE_DA(sclk_uart0, "exynos4210-uart.0", "uclk0", "div_uart0", - SRC_MASK_PERIL0, 0, CLK_SET_RATE_PARENT, - 0, "clk_uart_baud0"), - GATE_DA(sclk_uart1, "exynos4210-uart.1", "uclk1", "div_uart1", - SRC_MASK_PERIL0, 4, CLK_SET_RATE_PARENT, - 0, "clk_uart_baud0"), - GATE_DA(sclk_uart2, "exynos4210-uart.2", "uclk2", "div_uart2", - SRC_MASK_PERIL0, 8, CLK_SET_RATE_PARENT, - 0, "clk_uart_baud0"), - GATE_DA(sclk_uart3, "exynos4210-uart.3", "uclk3", "div_uart3", - SRC_MASK_PERIL0, 12, CLK_SET_RATE_PARENT, - 0, "clk_uart_baud0"), - GATE_DA(sclk_uart4, "exynos4210-uart.4", "uclk4", "div_uart4", - SRC_MASK_PERIL0, 16, CLK_SET_RATE_PARENT, - 0, "clk_uart_baud0"), + GATE(vp, "vp", "aclk160", GATE_IP_TV, 0, 0, 0), + GATE(mixer, "mixer", "aclk160", GATE_IP_TV, 1, 0, 0), + GATE(hdmi, "hdmi", "aclk160", GATE_IP_TV, 3, 0, 0), + GATE(pwm, "pwm", "aclk100", GATE_IP_PERIL, 24, 0, 0), + GATE(sdmmc4, "sdmmc4", "aclk133", GATE_IP_FSYS, 9, 0, 0), + GATE(usb_host, "usb_host", "aclk133", GATE_IP_FSYS, 12, 0, 0), + GATE(sclk_fimc0, "sclk_fimc0", "div_fimc0", SRC_MASK_CAM, 0, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_fimc1, "sclk_fimc1", "div_fimc1", SRC_MASK_CAM, 4, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_fimc2, "sclk_fimc2", "div_fimc2", SRC_MASK_CAM, 8, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_fimc3, "sclk_fimc3", "div_fimc3", SRC_MASK_CAM, 12, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_csis0, "sclk_csis0", "div_csis0", SRC_MASK_CAM, 24, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_csis1, "sclk_csis1", "div_csis1", SRC_MASK_CAM, 28, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_fimd0, "sclk_fimd0", "div_fimd0", SRC_MASK_LCD0, 0, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_mmc0, "sclk_mmc0", "div_mmc_pre0", SRC_MASK_FSYS, 0, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_mmc1, "sclk_mmc1", "div_mmc_pre1", SRC_MASK_FSYS, 4, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_mmc2, "sclk_mmc2", "div_mmc_pre2", SRC_MASK_FSYS, 8, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_mmc3, "sclk_mmc3", "div_mmc_pre3", SRC_MASK_FSYS, 12, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_mmc4, "sclk_mmc4", "div_mmc_pre4", SRC_MASK_FSYS, 16, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_uart0, "uclk0", "div_uart0", SRC_MASK_PERIL0, 0, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_uart1, "uclk1", "div_uart1", SRC_MASK_PERIL0, 4, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_uart2, "uclk2", "div_uart2", SRC_MASK_PERIL0, 8, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_uart3, "uclk3", "div_uart3", SRC_MASK_PERIL0, 12, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_uart4, "uclk4", "div_uart4", SRC_MASK_PERIL0, 16, + CLK_SET_RATE_PARENT, 0), GATE(sclk_audio2, "sclk_audio2", "div_audio2", SRC_MASK_PERIL1, 4, CLK_SET_RATE_PARENT, 0), - GATE_DA(sclk_spi0, "exynos4210-spi.0", "sclk_spi0", "div_spi_pre0", - SRC_MASK_PERIL1, 16, CLK_SET_RATE_PARENT, - 0, "spi_busclk0"), - GATE_DA(sclk_spi1, "exynos4210-spi.1", "sclk_spi1", "div_spi_pre1", - SRC_MASK_PERIL1, 20, CLK_SET_RATE_PARENT, - 0, "spi_busclk0"), - GATE_DA(sclk_spi2, "exynos4210-spi.2", "sclk_spi2", "div_spi_pre2", - SRC_MASK_PERIL1, 24, CLK_SET_RATE_PARENT, - 0, "spi_busclk0"), - GATE_DA(fimc0, "exynos4-fimc.0", "fimc0", "aclk160", - GATE_IP_CAM, 0, 0, 0, "fimc"), - GATE_DA(fimc1, "exynos4-fimc.1", "fimc1", "aclk160", - GATE_IP_CAM, 1, 0, 0, "fimc"), - GATE_DA(fimc2, "exynos4-fimc.2", "fimc2", "aclk160", - GATE_IP_CAM, 2, 0, 0, "fimc"), - GATE_DA(fimc3, "exynos4-fimc.3", "fimc3", "aclk160", - GATE_IP_CAM, 3, 0, 0, "fimc"), - GATE_DA(csis0, "s5p-mipi-csis.0", "csis0", "aclk160", - GATE_IP_CAM, 4, 0, 0, "fimc"), - GATE_DA(csis1, "s5p-mipi-csis.1", "csis1", "aclk160", - GATE_IP_CAM, 5, 0, 0, "fimc"), - GATE_DA(smmu_fimc0, "exynos-sysmmu.5", "smmu_fimc0", "aclk160", - GATE_IP_CAM, 7, 0, 0, "sysmmu"), - GATE_DA(smmu_fimc1, "exynos-sysmmu.6", "smmu_fimc1", "aclk160", - GATE_IP_CAM, 8, 0, 0, "sysmmu"), - GATE_DA(smmu_fimc2, "exynos-sysmmu.7", "smmu_fimc2", "aclk160", - GATE_IP_CAM, 9, 0, 0, "sysmmu"), - GATE_DA(smmu_fimc3, "exynos-sysmmu.8", "smmu_fimc3", "aclk160", - GATE_IP_CAM, 10, 0, 0, "sysmmu"), - GATE_DA(smmu_jpeg, "exynos-sysmmu.3", "smmu_jpeg", "aclk160", - GATE_IP_CAM, 11, 0, 0, "sysmmu"), + GATE(sclk_spi0, "sclk_spi0", "div_spi_pre0", SRC_MASK_PERIL1, 16, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_spi1, "sclk_spi1", "div_spi_pre1", SRC_MASK_PERIL1, 20, + CLK_SET_RATE_PARENT, 0), + GATE(sclk_spi2, "sclk_spi2", "div_spi_pre2", SRC_MASK_PERIL1, 24, + CLK_SET_RATE_PARENT, 0), + GATE(fimc0, "fimc0", "aclk160", GATE_IP_CAM, 0, + 0, 0), + GATE(fimc1, "fimc1", "aclk160", GATE_IP_CAM, 1, + 0, 0), + GATE(fimc2, "fimc2", "aclk160", GATE_IP_CAM, 2, + 0, 0), + GATE(fimc3, "fimc3", "aclk160", GATE_IP_CAM, 3, + 0, 0), + GATE(csis0, "csis0", "aclk160", GATE_IP_CAM, 4, + 0, 0), + GATE(csis1, "csis1", "aclk160", GATE_IP_CAM, 5, + 0, 0), + GATE(smmu_fimc0, "smmu_fimc0", "aclk160", GATE_IP_CAM, 7, + 0, 0), + GATE(smmu_fimc1, "smmu_fimc1", "aclk160", GATE_IP_CAM, 8, + 0, 0), + GATE(smmu_fimc2, "smmu_fimc2", "aclk160", GATE_IP_CAM, 9, + 0, 0), + GATE(smmu_fimc3, "smmu_fimc3", "aclk160", GATE_IP_CAM, 10, + 0, 0), + GATE(smmu_jpeg, "smmu_jpeg", "aclk160", GATE_IP_CAM, 11, + 0, 0), GATE(pixelasyncm0, "pxl_async0", "aclk160", GATE_IP_CAM, 17, 0, 0), GATE(pixelasyncm1, "pxl_async1", "aclk160", GATE_IP_CAM, 18, 0, 0), - GATE_DA(smmu_tv, "exynos-sysmmu.2", "smmu_tv", "aclk160", - GATE_IP_TV, 4, 0, 0, "sysmmu"), - GATE_DA(mfc, "s5p-mfc", "mfc", "aclk100", GATE_IP_MFC, 0, 0, 0, "mfc"), - GATE_DA(smmu_mfcl, "exynos-sysmmu.0", "smmu_mfcl", "aclk100", - GATE_IP_MFC, 1, 0, 0, "sysmmu"), - GATE_DA(smmu_mfcr, "exynos-sysmmu.1", "smmu_mfcr", "aclk100", - GATE_IP_MFC, 2, 0, 0, "sysmmu"), - GATE_DA(fimd0, "exynos4-fb.0", "fimd0", "aclk160", - GATE_IP_LCD0, 0, 0, 0, "fimd"), - GATE_DA(smmu_fimd0, "exynos-sysmmu.10", "smmu_fimd0", "aclk160", - GATE_IP_LCD0, 4, 0, 0, "sysmmu"), - GATE_DA(pdma0, "dma-pl330.0", "pdma0", "aclk133", - GATE_IP_FSYS, 0, 0, 0, "dma"), - GATE_DA(pdma1, "dma-pl330.1", "pdma1", "aclk133", - GATE_IP_FSYS, 1, 0, 0, "dma"), - GATE_DA(sdmmc0, "exynos4-sdhci.0", "sdmmc0", "aclk133", - GATE_IP_FSYS, 5, 0, 0, "hsmmc"), - GATE_DA(sdmmc1, "exynos4-sdhci.1", "sdmmc1", "aclk133", - GATE_IP_FSYS, 6, 0, 0, "hsmmc"), - GATE_DA(sdmmc2, "exynos4-sdhci.2", "sdmmc2", "aclk133", - GATE_IP_FSYS, 7, 0, 0, "hsmmc"), - GATE_DA(sdmmc3, "exynos4-sdhci.3", "sdmmc3", "aclk133", - GATE_IP_FSYS, 8, 0, 0, "hsmmc"), - GATE_DA(uart0, "exynos4210-uart.0", "uart0", "aclk100", - GATE_IP_PERIL, 0, 0, 0, "uart"), - GATE_DA(uart1, "exynos4210-uart.1", "uart1", "aclk100", - GATE_IP_PERIL, 1, 0, 0, "uart"), - GATE_DA(uart2, "exynos4210-uart.2", "uart2", "aclk100", - GATE_IP_PERIL, 2, 0, 0, "uart"), - GATE_DA(uart3, "exynos4210-uart.3", "uart3", "aclk100", - GATE_IP_PERIL, 3, 0, 0, "uart"), - GATE_DA(uart4, "exynos4210-uart.4", "uart4", "aclk100", - GATE_IP_PERIL, 4, 0, 0, "uart"), - GATE_DA(i2c0, "s3c2440-i2c.0", "i2c0", "aclk100", - GATE_IP_PERIL, 6, 0, 0, "i2c"), - GATE_DA(i2c1, "s3c2440-i2c.1", "i2c1", "aclk100", - GATE_IP_PERIL, 7, 0, 0, "i2c"), - GATE_DA(i2c2, "s3c2440-i2c.2", "i2c2", "aclk100", - GATE_IP_PERIL, 8, 0, 0, "i2c"), - GATE_DA(i2c3, "s3c2440-i2c.3", "i2c3", "aclk100", - GATE_IP_PERIL, 9, 0, 0, "i2c"), - GATE_DA(i2c4, "s3c2440-i2c.4", "i2c4", "aclk100", - GATE_IP_PERIL, 10, 0, 0, "i2c"), - GATE_DA(i2c5, "s3c2440-i2c.5", "i2c5", "aclk100", - GATE_IP_PERIL, 11, 0, 0, "i2c"), - GATE_DA(i2c6, "s3c2440-i2c.6", "i2c6", "aclk100", - GATE_IP_PERIL, 12, 0, 0, "i2c"), - GATE_DA(i2c7, "s3c2440-i2c.7", "i2c7", "aclk100", - GATE_IP_PERIL, 13, 0, 0, "i2c"), - GATE_DA(i2c_hdmi, "s3c2440-hdmiphy-i2c", "i2c-hdmi", "aclk100", - GATE_IP_PERIL, 14, 0, 0, "i2c"), - GATE_DA(spi0, "exynos4210-spi.0", "spi0", "aclk100", - GATE_IP_PERIL, 16, 0, 0, "spi"), - GATE_DA(spi1, "exynos4210-spi.1", "spi1", "aclk100", - GATE_IP_PERIL, 17, 0, 0, "spi"), - GATE_DA(spi2, "exynos4210-spi.2", "spi2", "aclk100", - GATE_IP_PERIL, 18, 0, 0, "spi"), - GATE_DA(i2s1, "samsung-i2s.1", "i2s1", "aclk100", - GATE_IP_PERIL, 20, 0, 0, "iis"), - GATE_DA(i2s2, "samsung-i2s.2", "i2s2", "aclk100", - GATE_IP_PERIL, 21, 0, 0, "iis"), - GATE_DA(pcm1, "samsung-pcm.1", "pcm1", "aclk100", - GATE_IP_PERIL, 22, 0, 0, "pcm"), - GATE_DA(pcm2, "samsung-pcm.2", "pcm2", "aclk100", - GATE_IP_PERIL, 23, 0, 0, "pcm"), - GATE_DA(spdif, "samsung-spdif", "spdif", "aclk100", - GATE_IP_PERIL, 26, 0, 0, "spdif"), - GATE_DA(ac97, "samsung-ac97", "ac97", "aclk100", - GATE_IP_PERIL, 27, 0, 0, "ac97"), + GATE(smmu_tv, "smmu_tv", "aclk160", GATE_IP_TV, 4, + 0, 0), + GATE(mfc, "mfc", "aclk100", GATE_IP_MFC, 0, 0, 0), + GATE(smmu_mfcl, "smmu_mfcl", "aclk100", GATE_IP_MFC, 1, + 0, 0), + GATE(smmu_mfcr, "smmu_mfcr", "aclk100", GATE_IP_MFC, 2, + 0, 0), + GATE(fimd0, "fimd0", "aclk160", GATE_IP_LCD0, 0, + 0, 0), + GATE(smmu_fimd0, "smmu_fimd0", "aclk160", GATE_IP_LCD0, 4, + 0, 0), + GATE(pdma0, "pdma0", "aclk133", GATE_IP_FSYS, 0, + 0, 0), + GATE(pdma1, "pdma1", "aclk133", GATE_IP_FSYS, 1, + 0, 0), + GATE(sdmmc0, "sdmmc0", "aclk133", GATE_IP_FSYS, 5, + 0, 0), + GATE(sdmmc1, "sdmmc1", "aclk133", GATE_IP_FSYS, 6, + 0, 0), + GATE(sdmmc2, "sdmmc2", "aclk133", GATE_IP_FSYS, 7, + 0, 0), + GATE(sdmmc3, "sdmmc3", "aclk133", GATE_IP_FSYS, 8, + 0, 0), + GATE(uart0, "uart0", "aclk100", GATE_IP_PERIL, 0, + 0, 0), + GATE(uart1, "uart1", "aclk100", GATE_IP_PERIL, 1, + 0, 0), + GATE(uart2, "uart2", "aclk100", GATE_IP_PERIL, 2, + 0, 0), + GATE(uart3, "uart3", "aclk100", GATE_IP_PERIL, 3, + 0, 0), + GATE(uart4, "uart4", "aclk100", GATE_IP_PERIL, 4, + 0, 0), + GATE(i2c0, "i2c0", "aclk100", GATE_IP_PERIL, 6, + 0, 0), + GATE(i2c1, "i2c1", "aclk100", GATE_IP_PERIL, 7, + 0, 0), + GATE(i2c2, "i2c2", "aclk100", GATE_IP_PERIL, 8, + 0, 0), + GATE(i2c3, "i2c3", "aclk100", GATE_IP_PERIL, 9, + 0, 0), + GATE(i2c4, "i2c4", "aclk100", GATE_IP_PERIL, 10, + 0, 0), + GATE(i2c5, "i2c5", "aclk100", GATE_IP_PERIL, 11, + 0, 0), + GATE(i2c6, "i2c6", "aclk100", GATE_IP_PERIL, 12, + 0, 0), + GATE(i2c7, "i2c7", "aclk100", GATE_IP_PERIL, 13, + 0, 0), + GATE(i2c_hdmi, "i2c-hdmi", "aclk100", GATE_IP_PERIL, 14, + 0, 0), + GATE(spi0, "spi0", "aclk100", GATE_IP_PERIL, 16, + 0, 0), + GATE(spi1, "spi1", "aclk100", GATE_IP_PERIL, 17, + 0, 0), + GATE(spi2, "spi2", "aclk100", GATE_IP_PERIL, 18, + 0, 0), + GATE(i2s1, "i2s1", "aclk100", GATE_IP_PERIL, 20, + 0, 0), + GATE(i2s2, "i2s2", "aclk100", GATE_IP_PERIL, 21, + 0, 0), + GATE(pcm1, "pcm1", "aclk100", GATE_IP_PERIL, 22, + 0, 0), + GATE(pcm2, "pcm2", "aclk100", GATE_IP_PERIL, 23, + 0, 0), + GATE(spdif, "spdif", "aclk100", GATE_IP_PERIL, 26, + 0, 0), + GATE(ac97, "ac97", "aclk100", GATE_IP_PERIL, 27, + 0, 0), }; /* list of gate clocks supported in exynos4210 soc */ @@ -812,13 +795,18 @@ static struct samsung_gate_clock exynos4210_gate_clks[] __initdata = { SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0), GATE(sclk_mixer, "sclk_mixer", "mout_mixer", SRC_MASK_TV, 4, 0, 0), GATE(sclk_dac, "sclk_dac", "mout_dac", SRC_MASK_TV, 8, 0, 0), - GATE_A(tsadc, "tsadc", "aclk100", GATE_IP_PERIL, 15, 0, 0, "adc"), - GATE_A(mct, "mct", "aclk100", E4210_GATE_IP_PERIR, 13, 0, 0, "mct"), - GATE_A(wdt, "watchdog", "aclk100", E4210_GATE_IP_PERIR, 14, 0, 0, "watchdog"), - GATE_A(rtc, "rtc", "aclk100", E4210_GATE_IP_PERIR, 15, 0, 0, "rtc"), - GATE_A(keyif, "keyif", "aclk100", E4210_GATE_IP_PERIR, 16, 0, 0, "keypad"), - GATE_DA(sclk_fimd1, "exynos4-fb.1", "sclk_fimd1", "div_fimd1", - E4210_SRC_MASK_LCD1, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimd"), + GATE(tsadc, "tsadc", "aclk100", GATE_IP_PERIL, 15, + 0, 0), + GATE(mct, "mct", "aclk100", E4210_GATE_IP_PERIR, 13, + 0, 0), + GATE(wdt, "watchdog", "aclk100", E4210_GATE_IP_PERIR, 14, + 0, 0), + GATE(rtc, "rtc", "aclk100", E4210_GATE_IP_PERIR, 15, + 0, 0), + GATE(keyif, "keyif", "aclk100", E4210_GATE_IP_PERIR, 16, + 0, 0), + GATE(sclk_fimd1, "sclk_fimd1", "div_fimd1", E4210_SRC_MASK_LCD1, 0, + CLK_SET_RATE_PARENT, 0), GATE(tmu_apbif, "tmu_apbif", "aclk100", E4210_GATE_IP_PERIR, 17, 0, 0), }; @@ -842,10 +830,11 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = { SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0), GATE(smmu_rotator, "smmu_rotator", "aclk200", E4X12_GATE_IP_IMAGE, 4, 0, 0), - GATE_A(mct, "mct", "aclk100", E4X12_GATE_IP_PERIR, 13, 0, 0, "mct"), - GATE_A(rtc, "rtc", "aclk100", E4X12_GATE_IP_PERIR, 15, 0, 0, "rtc"), - GATE_A(keyif, "keyif", "aclk100", - E4X12_GATE_IP_PERIR, 16, 0, 0, "keypad"), + GATE(mct, "mct", "aclk100", E4X12_GATE_IP_PERIR, 13, + 0, 0), + GATE(rtc, "rtc", "aclk100", E4X12_GATE_IP_PERIR, 15, + 0, 0), + GATE(keyif, "keyif", "aclk100", E4X12_GATE_IP_PERIR, 16, 0, 0), GATE(sclk_pwm_isp, "sclk_pwm_isp", "div_pwm_isp", E4X12_SRC_MASK_ISP, 0, CLK_SET_RATE_PARENT, 0), GATE(sclk_spi0_isp, "sclk_spi0_isp", "div_spi0_isp_pre", @@ -862,12 +851,11 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = { E4X12_GATE_IP_ISP, 2, 0, 0), GATE(uart_isp_sclk, "uart_isp_sclk", "sclk_uart_isp", E4X12_GATE_IP_ISP, 3, 0, 0), - GATE_A(wdt, "watchdog", "aclk100", - E4X12_GATE_IP_PERIR, 14, 0, 0, "watchdog"), - GATE_DA(pcm0, "samsung-pcm.0", "pcm0", "aclk100", - E4X12_GATE_IP_MAUDIO, 2, 0, 0, "pcm"), - GATE_DA(i2s0, "samsung-i2s.0", "i2s0", "aclk100", - E4X12_GATE_IP_MAUDIO, 3, 0, 0, "iis"), + GATE(wdt, "watchdog", "aclk100", E4X12_GATE_IP_PERIR, 14, 0, 0), + GATE(pcm0, "pcm0", "aclk100", E4X12_GATE_IP_MAUDIO, 2, + 0, 0), + GATE(i2s0, "i2s0", "aclk100", E4X12_GATE_IP_MAUDIO, 3, + 0, 0), GATE(fimc_isp, "isp", "aclk200", E4X12_GATE_ISP0, 0, CLK_IGNORE_UNUSED, 0), GATE(fimc_drc, "drc", "aclk200", E4X12_GATE_ISP0, 1, @@ -997,14 +985,14 @@ static struct of_device_id ext_clk_match[] __initdata = { }; static struct samsung_pll_clock exynos4_plls[nr_plls] __initdata = { - [apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, - APLL_CON0, "fout_apll", NULL), - [mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", - E4X12_MPLL_LOCK, E4X12_MPLL_CON0, "fout_mpll", NULL), - [epll] = PLL_A(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK, - EPLL_CON0, "fout_epll", NULL), - [vpll] = PLL_A(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK, - VPLL_CON0, "fout_vpll", NULL), + [apll] = PLL(pll_35xx, fout_apll, "fout_apll", "fin_pll", + APLL_LOCK, APLL_CON0, NULL), + [mpll] = PLL(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", + E4X12_MPLL_LOCK, E4X12_MPLL_CON0, NULL), + [epll] = PLL(pll_36xx, fout_epll, "fout_epll", "fin_pll", + EPLL_LOCK, EPLL_CON0, NULL), + [vpll] = PLL(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", + VPLL_LOCK, VPLL_CON0, NULL), }; /* register exynos4 clocks */ From 336c18bd33d3b8f6061b4618ddf0f0c73d8ed541 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 26 Aug 2013 19:09:02 +0200 Subject: [PATCH 092/102] clk: samsung: exynos4: Remove checks for DT node Exynos 4 supports only DT based bootup, so non-DT cases does not need to be handled anymore. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos4.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index be5f6e4b9624..cafb6959cf69 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1002,11 +1002,9 @@ static void __init exynos4_clk_init(struct device_node *np, { struct clk *apll, *mpll, *epll, *vpll; - if (np) { - reg_base = of_iomap(np, 0); - if (!reg_base) - panic("%s: failed to map registers\n", __func__); - } + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); if (exynos4_soc == EXYNOS4210) samsung_clk_init(np, reg_base, nr_clks, @@ -1017,8 +1015,7 @@ static void __init exynos4_clk_init(struct device_node *np, exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs), exynos4x12_clk_save, ARRAY_SIZE(exynos4x12_clk_save)); - if (np) - samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks, + samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks, ARRAY_SIZE(exynos4_fixed_rate_ext_clks), ext_clk_match); From c6415963006392cd67cb2d322c56ccc1711ac732 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 26 Aug 2013 19:09:03 +0200 Subject: [PATCH 093/102] clk: samsung: exynos4: Rename exynos4_plls to exynos4x12_plls This array defines PLLs specific to Exynos 4x12 SoCs and not for all Exynos 4 SoCs, so the name should represent that. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos4.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index cafb6959cf69..41cbe6e7e182 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -984,7 +984,7 @@ static struct of_device_id ext_clk_match[] __initdata = { {}, }; -static struct samsung_pll_clock exynos4_plls[nr_plls] __initdata = { +static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = { [apll] = PLL(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, NULL), [mpll] = PLL(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", @@ -1036,8 +1036,8 @@ static void __init exynos4_clk_init(struct device_node *np, samsung_clk_add_lookup(epll, fout_epll); samsung_clk_add_lookup(vpll, fout_vpll); } else { - samsung_clk_register_pll(exynos4_plls, - ARRAY_SIZE(exynos4_plls), reg_base); + samsung_clk_register_pll(exynos4x12_plls, + ARRAY_SIZE(exynos4x12_plls), reg_base); } samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks, From 52b0601637ac41845d216c490a75e489a14c4e95 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 26 Aug 2013 19:09:04 +0200 Subject: [PATCH 094/102] clk: samsung: pll: Use new registration method for PLL45xx This patch modifies PLL45xx support code and its users to use the recently introduced common PLL registration helper. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos4.c | 18 ++++++----- drivers/clk/samsung/clk-pll.c | 52 ++++--------------------------- drivers/clk/samsung/clk-pll.h | 12 ++----- 3 files changed, 20 insertions(+), 62 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 41cbe6e7e182..fd0215d99c88 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -104,6 +104,7 @@ #define DIV_DMC1 0x10504 #define GATE_IP_DMC 0x10900 #define APLL_LOCK 0x14000 +#define E4210_MPLL_LOCK 0x14008 #define APLL_CON0 0x14100 #define E4210_MPLL_CON0 0x14108 #define SRC_CPU 0x14200 @@ -984,6 +985,13 @@ static struct of_device_id ext_clk_match[] __initdata = { {}, }; +static struct samsung_pll_clock exynos4210_plls[] __initdata = { + [apll] = PLL_A(pll_4508, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, + APLL_CON0, "fout_apll", NULL), + [mpll] = PLL_A(pll_4508, fout_mpll, "fout_mpll", "fin_pll", + E4210_MPLL_LOCK, E4210_MPLL_CON0, "fout_mpll", NULL), +}; + static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = { [apll] = PLL(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, NULL), @@ -1000,7 +1008,7 @@ static 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 clk *epll, *vpll; reg_base = of_iomap(np, 0); if (!reg_base) @@ -1022,17 +1030,13 @@ static void __init exynos4_clk_init(struct device_node *np, exynos4_clk_register_finpll(xom); if (exynos4_soc == EXYNOS4210) { - apll = samsung_clk_register_pll45xx("fout_apll", "fin_pll", - reg_base + APLL_CON0, pll_4508); - mpll = samsung_clk_register_pll45xx("fout_mpll", "fin_pll", - reg_base + E4210_MPLL_CON0, pll_4508); + samsung_clk_register_pll(exynos4210_plls, + ARRAY_SIZE(exynos4210_plls), reg_base); epll = samsung_clk_register_pll46xx("fout_epll", "fin_pll", reg_base + EPLL_CON0, pll_4600); vpll = samsung_clk_register_pll46xx("fout_vpll", "mout_vpllsrc", reg_base + VPLL_CON0, pll_4650c); - 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); } else { diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 7572d1d4fac1..f2e92e81173a 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -280,18 +280,10 @@ static const struct clk_ops samsung_pll36xx_clk_min_ops = { #define PLL45XX_PDIV_SHIFT (8) #define PLL45XX_SDIV_SHIFT (0) -struct samsung_clk_pll45xx { - struct clk_hw hw; - enum pll45xx_type type; - const void __iomem *con_reg; -}; - -#define to_clk_pll45xx(_hw) container_of(_hw, struct samsung_clk_pll45xx, hw) - static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct samsung_clk_pll45xx *pll = to_clk_pll45xx(hw); + struct samsung_clk_pll *pll = to_clk_pll(hw); u32 mdiv, pdiv, sdiv, pll_con; u64 fvco = parent_rate; @@ -313,43 +305,6 @@ static const struct clk_ops samsung_pll45xx_clk_ops = { .recalc_rate = samsung_pll45xx_recalc_rate, }; -struct clk * __init samsung_clk_register_pll45xx(const char *name, - const char *pname, const void __iomem *con_reg, - enum pll45xx_type type) -{ - struct samsung_clk_pll45xx *pll; - struct clk *clk; - struct clk_init_data init; - - pll = kzalloc(sizeof(*pll), GFP_KERNEL); - if (!pll) { - pr_err("%s: could not allocate pll clk %s\n", __func__, name); - return NULL; - } - - init.name = name; - init.ops = &samsung_pll45xx_clk_ops; - init.flags = CLK_GET_RATE_NOCACHE; - init.parent_names = &pname; - init.num_parents = 1; - - pll->hw.init = &init; - pll->con_reg = con_reg; - pll->type = type; - - clk = clk_register(NULL, &pll->hw); - if (IS_ERR(clk)) { - pr_err("%s: failed to register pll clock %s\n", __func__, - name); - kfree(pll); - } - - if (clk_register_clkdev(clk, name, NULL)) - pr_err("%s: failed to register lookup for %s", __func__, name); - - return clk; -} - /* * PLL46xx Clock Type */ @@ -635,6 +590,11 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, else init.ops = &samsung_pll35xx_clk_ops; break; + case pll_4500: + case pll_4502: + case pll_4508: + init.ops = &samsung_pll45xx_clk_ops; + break; /* clk_ops for 36xx and 2650 are similar */ case pll_36xx: case pll_2650: diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index cd1103784f71..fceb2cb00f2a 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -17,6 +17,9 @@ enum samsung_pll_type { pll_36xx, pll_2550, pll_2650, + pll_4500, + pll_4502, + pll_4508, pll_6552, pll_6553, }; @@ -48,21 +51,12 @@ struct samsung_pll_rate_table { unsigned int kdiv; }; -enum pll45xx_type { - pll_4500, - pll_4502, - pll_4508 -}; - enum pll46xx_type { pll_4600, pll_4650, pll_4650c, }; -extern struct clk * __init samsung_clk_register_pll45xx(const char *name, - const char *pname, const void __iomem *con_reg, - enum pll45xx_type type); extern struct clk * __init samsung_clk_register_pll46xx(const char *name, const char *pname, const void __iomem *con_reg, enum pll46xx_type type); From b4054ac6a26ee94a3a0f18e9ea585545d69e29c2 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 26 Aug 2013 19:09:05 +0200 Subject: [PATCH 095/102] clk: samsung: pll: Add support for rate configuration of PLL45xx This patch implements round_rate and set_rate callbacks of PLL45xx driver to allow reconfiguration of PLL at runtime. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-pll.c | 110 +++++++++++++++++++++++++++++++++- drivers/clk/samsung/clk-pll.h | 10 ++++ 2 files changed, 119 insertions(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index f2e92e81173a..4acd06169ae3 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -10,9 +10,12 @@ */ #include +#include #include "clk.h" #include "clk-pll.h" +#define PLL_TIMEOUT_MS 10 + struct samsung_clk_pll { struct clk_hw hw; void __iomem *lock_reg; @@ -272,13 +275,20 @@ static const struct clk_ops samsung_pll36xx_clk_min_ops = { /* * PLL45xx Clock Type */ +#define PLL4502_LOCK_FACTOR 400 +#define PLL4508_LOCK_FACTOR 240 #define PLL45XX_MDIV_MASK (0x3FF) #define PLL45XX_PDIV_MASK (0x3F) #define PLL45XX_SDIV_MASK (0x7) +#define PLL45XX_AFC_MASK (0x1F) #define PLL45XX_MDIV_SHIFT (16) #define PLL45XX_PDIV_SHIFT (8) #define PLL45XX_SDIV_SHIFT (0) +#define PLL45XX_AFC_SHIFT (0) + +#define PLL45XX_ENABLE BIT(31) +#define PLL45XX_LOCKED BIT(29) static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) @@ -301,8 +311,101 @@ static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw, return (unsigned long)fvco; } +static bool samsung_pll45xx_mp_change(u32 pll_con0, u32 pll_con1, + const struct samsung_pll_rate_table *rate) +{ + u32 old_mdiv, old_pdiv, old_afc; + + old_mdiv = (pll_con0 >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK; + old_pdiv = (pll_con0 >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK; + old_afc = (pll_con1 >> PLL45XX_AFC_SHIFT) & PLL45XX_AFC_MASK; + + return (old_mdiv != rate->mdiv || old_pdiv != rate->pdiv + || old_afc != rate->afc); +} + +static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long prate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + const struct samsung_pll_rate_table *rate; + u32 con0, con1; + ktime_t start; + + /* Get required rate settings from table */ + rate = samsung_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, __clk_get_name(hw->clk)); + return -EINVAL; + } + + con0 = __raw_readl(pll->con_reg); + con1 = __raw_readl(pll->con_reg + 0x4); + + if (!(samsung_pll45xx_mp_change(con0, con1, rate))) { + /* If only s change, change just s value only*/ + con0 &= ~(PLL45XX_SDIV_MASK << PLL45XX_SDIV_SHIFT); + con0 |= rate->sdiv << PLL45XX_SDIV_SHIFT; + __raw_writel(con0, pll->con_reg); + + return 0; + } + + /* Set PLL PMS values. */ + con0 &= ~((PLL45XX_MDIV_MASK << PLL45XX_MDIV_SHIFT) | + (PLL45XX_PDIV_MASK << PLL45XX_PDIV_SHIFT) | + (PLL45XX_SDIV_MASK << PLL45XX_SDIV_SHIFT)); + con0 |= (rate->mdiv << PLL45XX_MDIV_SHIFT) | + (rate->pdiv << PLL45XX_PDIV_SHIFT) | + (rate->sdiv << PLL45XX_SDIV_SHIFT); + + /* Set PLL AFC value. */ + con1 = __raw_readl(pll->con_reg + 0x4); + con1 &= ~(PLL45XX_AFC_MASK << PLL45XX_AFC_SHIFT); + con1 |= (rate->afc << PLL45XX_AFC_SHIFT); + + /* Set PLL lock time. */ + switch (pll->type) { + case pll_4502: + __raw_writel(rate->pdiv * PLL4502_LOCK_FACTOR, pll->lock_reg); + break; + case pll_4508: + __raw_writel(rate->pdiv * PLL4508_LOCK_FACTOR, pll->lock_reg); + break; + default: + break; + }; + + /* Set new configuration. */ + __raw_writel(con1, pll->con_reg + 0x4); + __raw_writel(con0, pll->con_reg); + + /* Wait for locking. */ + start = ktime_get(); + while (!(__raw_readl(pll->con_reg) & PLL45XX_LOCKED)) { + ktime_t delta = ktime_sub(ktime_get(), start); + + if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) { + pr_err("%s: could not lock PLL %s\n", + __func__, __clk_get_name(hw->clk)); + return -EFAULT; + } + + cpu_relax(); + } + + return 0; +} + static const struct clk_ops samsung_pll45xx_clk_ops = { .recalc_rate = samsung_pll45xx_recalc_rate, + .round_rate = samsung_pll_round_rate, + .set_rate = samsung_pll45xx_set_rate, +}; + +static const struct clk_ops samsung_pll45xx_clk_min_ops = { + .recalc_rate = samsung_pll45xx_recalc_rate, }; /* @@ -591,9 +694,14 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, init.ops = &samsung_pll35xx_clk_ops; break; case pll_4500: + init.ops = &samsung_pll45xx_clk_min_ops; + break; case pll_4502: case pll_4508: - init.ops = &samsung_pll45xx_clk_ops; + if (!pll->rate_table) + init.ops = &samsung_pll45xx_clk_min_ops; + else + init.ops = &samsung_pll45xx_clk_ops; break; /* clk_ops for 36xx and 2650 are similar */ case pll_36xx: diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index fceb2cb00f2a..2c331291fe40 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -41,6 +41,15 @@ enum samsung_pll_type { .kdiv = (_k), \ } +#define PLL_45XX_RATE(_rate, _m, _p, _s, _afc) \ + { \ + .rate = (_rate), \ + .mdiv = (_m), \ + .pdiv = (_p), \ + .sdiv = (_s), \ + .afc = (_afc), \ + } + /* NOTE: Rate table should be kept sorted in descending order. */ struct samsung_pll_rate_table { @@ -49,6 +58,7 @@ struct samsung_pll_rate_table { unsigned int mdiv; unsigned int sdiv; unsigned int kdiv; + unsigned int afc; }; enum pll46xx_type { From c50d11f35a021fc357922797a7638d4d6ca70b9e Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 26 Aug 2013 19:09:06 +0200 Subject: [PATCH 096/102] clk: samsung: pll: Use new registration method for PLL46xx This patch modifies PLL46xx support code and its users to use the recently introduced common PLL registration helper. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos4.c | 15 +++------ drivers/clk/samsung/clk-pll.c | 52 ++++--------------------------- drivers/clk/samsung/clk-pll.h | 12 ++----- 3 files changed, 14 insertions(+), 65 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index fd0215d99c88..779c2069e632 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -985,11 +985,15 @@ static struct of_device_id ext_clk_match[] __initdata = { {}, }; -static struct samsung_pll_clock exynos4210_plls[] __initdata = { +static struct samsung_pll_clock exynos4210_plls[nr_plls] __initdata = { [apll] = PLL_A(pll_4508, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, "fout_apll", NULL), [mpll] = PLL_A(pll_4508, fout_mpll, "fout_mpll", "fin_pll", E4210_MPLL_LOCK, E4210_MPLL_CON0, "fout_mpll", NULL), + [epll] = PLL_A(pll_4600, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK, + EPLL_CON0, "fout_epll", NULL), + [vpll] = PLL_A(pll_4650c, fout_vpll, "fout_vpll", "mout_vpllsrc", + VPLL_LOCK, VPLL_CON0, "fout_vpll", NULL), }; static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = { @@ -1008,8 +1012,6 @@ static void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_soc, void __iomem *reg_base, unsigned long xom) { - struct clk *epll, *vpll; - reg_base = of_iomap(np, 0); if (!reg_base) panic("%s: failed to map registers\n", __func__); @@ -1032,13 +1034,6 @@ static void __init exynos4_clk_init(struct device_node *np, if (exynos4_soc == EXYNOS4210) { samsung_clk_register_pll(exynos4210_plls, ARRAY_SIZE(exynos4210_plls), reg_base); - epll = samsung_clk_register_pll46xx("fout_epll", "fin_pll", - reg_base + EPLL_CON0, pll_4600); - vpll = samsung_clk_register_pll46xx("fout_vpll", "mout_vpllsrc", - reg_base + VPLL_CON0, pll_4650c); - - samsung_clk_add_lookup(epll, fout_epll); - samsung_clk_add_lookup(vpll, fout_vpll); } else { samsung_clk_register_pll(exynos4x12_plls, ARRAY_SIZE(exynos4x12_plls), reg_base); diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 4acd06169ae3..d963b3e88615 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -423,18 +423,10 @@ static const struct clk_ops samsung_pll45xx_clk_min_ops = { #define PLL4650C_KDIV_MASK (0xFFF) #define PLL46XX_KDIV_SHIFT (0) -struct samsung_clk_pll46xx { - struct clk_hw hw; - enum pll46xx_type type; - const void __iomem *con_reg; -}; - -#define to_clk_pll46xx(_hw) container_of(_hw, struct samsung_clk_pll46xx, hw) - static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct samsung_clk_pll46xx *pll = to_clk_pll46xx(hw); + struct samsung_clk_pll *pll = to_clk_pll(hw); u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1, shift; u64 fvco = parent_rate; @@ -458,43 +450,6 @@ static const struct clk_ops samsung_pll46xx_clk_ops = { .recalc_rate = samsung_pll46xx_recalc_rate, }; -struct clk * __init samsung_clk_register_pll46xx(const char *name, - const char *pname, const void __iomem *con_reg, - enum pll46xx_type type) -{ - struct samsung_clk_pll46xx *pll; - struct clk *clk; - struct clk_init_data init; - - pll = kzalloc(sizeof(*pll), GFP_KERNEL); - if (!pll) { - pr_err("%s: could not allocate pll clk %s\n", __func__, name); - return NULL; - } - - init.name = name; - init.ops = &samsung_pll46xx_clk_ops; - init.flags = CLK_GET_RATE_NOCACHE; - init.parent_names = &pname; - init.num_parents = 1; - - pll->hw.init = &init; - pll->con_reg = con_reg; - pll->type = type; - - clk = clk_register(NULL, &pll->hw); - if (IS_ERR(clk)) { - pr_err("%s: failed to register pll clock %s\n", __func__, - name); - kfree(pll); - } - - if (clk_register_clkdev(clk, name, NULL)) - pr_err("%s: failed to register lookup for %s", __func__, name); - - return clk; -} - /* * PLL6552 Clock Type */ @@ -717,6 +672,11 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, case pll_6553: init.ops = &samsung_pll6553_clk_ops; break; + case pll_4600: + case pll_4650: + case pll_4650c: + init.ops = &samsung_pll46xx_clk_ops; + break; default: pr_warn("%s: Unknown pll type for pll clk %s\n", __func__, pll_clk->name); diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index 2c331291fe40..f3c85bf9cfaf 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -20,6 +20,9 @@ enum samsung_pll_type { pll_4500, pll_4502, pll_4508, + pll_4600, + pll_4650, + pll_4650c, pll_6552, pll_6553, }; @@ -61,15 +64,6 @@ struct samsung_pll_rate_table { unsigned int afc; }; -enum pll46xx_type { - pll_4600, - pll_4650, - pll_4650c, -}; - -extern struct clk * __init samsung_clk_register_pll46xx(const char *name, - const char *pname, const void __iomem *con_reg, - enum pll46xx_type type); extern struct clk * __init samsung_clk_register_pll2550x(const char *name, const char *pname, const void __iomem *reg_base, const unsigned long offset); From 5c89658a2ef38bace96cf9d4474d59a32d06609d Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 26 Aug 2013 19:09:07 +0200 Subject: [PATCH 097/102] clk: samsung: pll: Add support for rate configuration of PLL46xx This patch implements round_rate and set_rate callbacks of PLL46xx driver to allow reconfiguration of PLL at runtime. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-pll.c | 111 +++++++++++++++++++++++++++++++++- drivers/clk/samsung/clk-pll.h | 25 ++++++++ 2 files changed, 135 insertions(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index d963b3e88615..529e11dc2c6b 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -411,10 +411,13 @@ static const struct clk_ops samsung_pll45xx_clk_min_ops = { /* * PLL46xx Clock Type */ +#define PLL46XX_LOCK_FACTOR 3000 +#define PLL46XX_VSEL_MASK (1) #define PLL46XX_MDIV_MASK (0x1FF) #define PLL46XX_PDIV_MASK (0x3F) #define PLL46XX_SDIV_MASK (0x7) +#define PLL46XX_VSEL_SHIFT (27) #define PLL46XX_MDIV_SHIFT (16) #define PLL46XX_PDIV_SHIFT (8) #define PLL46XX_SDIV_SHIFT (0) @@ -422,6 +425,15 @@ static const struct clk_ops samsung_pll45xx_clk_min_ops = { #define PLL46XX_KDIV_MASK (0xFFFF) #define PLL4650C_KDIV_MASK (0xFFF) #define PLL46XX_KDIV_SHIFT (0) +#define PLL46XX_MFR_MASK (0x3F) +#define PLL46XX_MRR_MASK (0x1F) +#define PLL46XX_KDIV_SHIFT (0) +#define PLL46XX_MFR_SHIFT (16) +#define PLL46XX_MRR_SHIFT (24) + +#define PLL46XX_ENABLE BIT(31) +#define PLL46XX_LOCKED BIT(29) +#define PLL46XX_VSEL BIT(27) static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) @@ -446,8 +458,102 @@ static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw, return (unsigned long)fvco; } +static bool samsung_pll46xx_mpk_change(u32 pll_con0, u32 pll_con1, + const struct samsung_pll_rate_table *rate) +{ + u32 old_mdiv, old_pdiv, old_kdiv; + + old_mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK; + old_pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK; + old_kdiv = (pll_con1 >> PLL46XX_KDIV_SHIFT) & PLL46XX_KDIV_MASK; + + return (old_mdiv != rate->mdiv || old_pdiv != rate->pdiv + || old_kdiv != rate->kdiv); +} + +static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long prate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + const struct samsung_pll_rate_table *rate; + u32 con0, con1, lock; + ktime_t start; + + /* Get required rate settings from table */ + rate = samsung_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, __clk_get_name(hw->clk)); + return -EINVAL; + } + + con0 = __raw_readl(pll->con_reg); + con1 = __raw_readl(pll->con_reg + 0x4); + + if (!(samsung_pll46xx_mpk_change(con0, con1, rate))) { + /* If only s change, change just s value only*/ + con0 &= ~(PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT); + con0 |= rate->sdiv << PLL46XX_SDIV_SHIFT; + __raw_writel(con0, pll->con_reg); + + return 0; + } + + /* Set PLL lock time. */ + lock = rate->pdiv * PLL46XX_LOCK_FACTOR; + if (lock > 0xffff) + /* Maximum lock time bitfield is 16-bit. */ + lock = 0xffff; + + /* Set PLL PMS and VSEL values. */ + con0 &= ~((PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT) | + (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT) | + (PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT) | + (PLL46XX_VSEL_MASK << PLL46XX_VSEL_SHIFT)); + con0 |= (rate->mdiv << PLL46XX_MDIV_SHIFT) | + (rate->pdiv << PLL46XX_PDIV_SHIFT) | + (rate->sdiv << PLL46XX_SDIV_SHIFT) | + (rate->vsel << PLL46XX_VSEL_SHIFT); + + /* Set PLL K, MFR and MRR values. */ + con1 = __raw_readl(pll->con_reg + 0x4); + con1 &= ~((PLL46XX_KDIV_MASK << PLL46XX_KDIV_SHIFT) | + (PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT) | + (PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT)); + con1 |= (rate->kdiv << PLL46XX_KDIV_SHIFT) | + (rate->mfr << PLL46XX_MFR_SHIFT) | + (rate->mrr << PLL46XX_MRR_SHIFT); + + /* Write configuration to PLL */ + __raw_writel(lock, pll->lock_reg); + __raw_writel(con0, pll->con_reg); + __raw_writel(con1, pll->con_reg + 0x4); + + /* Wait for locking. */ + start = ktime_get(); + while (!(__raw_readl(pll->con_reg) & PLL46XX_LOCKED)) { + ktime_t delta = ktime_sub(ktime_get(), start); + + if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) { + pr_err("%s: could not lock PLL %s\n", + __func__, __clk_get_name(hw->clk)); + return -EFAULT; + } + + cpu_relax(); + } + + return 0; +} + static const struct clk_ops samsung_pll46xx_clk_ops = { .recalc_rate = samsung_pll46xx_recalc_rate, + .round_rate = samsung_pll_round_rate, + .set_rate = samsung_pll46xx_set_rate, +}; + +static const struct clk_ops samsung_pll46xx_clk_min_ops = { + .recalc_rate = samsung_pll46xx_recalc_rate, }; /* @@ -675,7 +781,10 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, case pll_4600: case pll_4650: case pll_4650c: - init.ops = &samsung_pll46xx_clk_ops; + if (!pll->rate_table) + init.ops = &samsung_pll46xx_clk_min_ops; + else + init.ops = &samsung_pll46xx_clk_ops; break; default: pr_warn("%s: Unknown pll type for pll clk %s\n", diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index f3c85bf9cfaf..6c39030080fb 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -53,6 +53,28 @@ enum samsung_pll_type { .afc = (_afc), \ } +#define PLL_4600_RATE(_rate, _m, _p, _s, _k, _vsel) \ + { \ + .rate = (_rate), \ + .mdiv = (_m), \ + .pdiv = (_p), \ + .sdiv = (_s), \ + .kdiv = (_k), \ + .vsel = (_vsel), \ + } + +#define PLL_4650_RATE(_rate, _m, _p, _s, _k, _mfr, _mrr, _vsel) \ + { \ + .rate = (_rate), \ + .mdiv = (_m), \ + .pdiv = (_p), \ + .sdiv = (_s), \ + .kdiv = (_k), \ + .mfr = (_mfr), \ + .mrr = (_mrr), \ + .vsel = (_vsel), \ + } + /* NOTE: Rate table should be kept sorted in descending order. */ struct samsung_pll_rate_table { @@ -62,6 +84,9 @@ struct samsung_pll_rate_table { unsigned int sdiv; unsigned int kdiv; unsigned int afc; + unsigned int mfr; + unsigned int mrr; + unsigned int vsel; }; extern struct clk * __init samsung_clk_register_pll2550x(const char *name, From 4f7641f588dcc5f614a2dae18e614da7abd13604 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 26 Aug 2013 19:09:08 +0200 Subject: [PATCH 098/102] clk: samsung: exynos4: Reorder registration of mout_vpllsrc Since PLL input frequency must be known before PLL registration, mout_vpllsrc clock which is a reference clock of VPLL must be registered before VPLL. This patch reorders clock registration to register mout_vpllsrc before VPLL. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos4.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 779c2069e632..7b88f96739bb 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -380,12 +380,15 @@ static struct samsung_mux_clock exynos4_mux_clks[] __initdata = { }; /* list of mux clocks supported in exynos4210 soc */ +static struct samsung_mux_clock exynos4210_mux_early[] __initdata = { + MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP1, 0, 1), +}; + static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = { MUX(none, "mout_aclk200", sclk_ampll_p4210, SRC_TOP0, 12, 1), MUX(none, "mout_aclk100", sclk_ampll_p4210, SRC_TOP0, 16, 1), MUX(none, "mout_aclk160", sclk_ampll_p4210, SRC_TOP0, 20, 1), MUX(none, "mout_aclk133", sclk_ampll_p4210, SRC_TOP0, 24, 1), - MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP1, 0, 1), MUX(none, "mout_mixer", mout_mixer_p4210, SRC_TV, 4, 1), MUX(none, "mout_dac", mout_dac_p4210, SRC_TV, 8, 1), MUX(none, "mout_g2d0", sclk_ampll_p4210, E4210_SRC_IMAGE, 0, 1), @@ -1032,6 +1035,9 @@ static void __init exynos4_clk_init(struct device_node *np, exynos4_clk_register_finpll(xom); if (exynos4_soc == EXYNOS4210) { + samsung_clk_register_mux(exynos4210_mux_early, + ARRAY_SIZE(exynos4210_mux_early)); + samsung_clk_register_pll(exynos4210_plls, ARRAY_SIZE(exynos4210_plls), reg_base); } else { From 5fadfc7ed37efe272983639f0d2f8c801303e796 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 26 Aug 2013 19:09:09 +0200 Subject: [PATCH 099/102] clk: samsung: exynos4: Register PLL rate tables for Exynos4210 This patch adds rate tables for PLLs that can be reconfigured at runtime for Exynos4210 SoCs. Provided tables contain PLL coefficients for input clock of 24 MHz and so are registered only in this case. MPLL does not need runtime reconfiguration and so table for it is not provided. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos4.c | 45 +++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 7b88f96739bb..c6796aff2421 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -988,6 +988,40 @@ static struct of_device_id ext_clk_match[] __initdata = { {}, }; +/* PLLs PMS values */ +static struct samsung_pll_rate_table exynos4210_apll_rates[] __initdata = { + PLL_45XX_RATE(1200000000, 150, 3, 1, 28), + PLL_45XX_RATE(1000000000, 250, 6, 1, 28), + PLL_45XX_RATE( 800000000, 200, 6, 1, 28), + PLL_45XX_RATE( 666857142, 389, 14, 1, 13), + PLL_45XX_RATE( 600000000, 100, 4, 1, 13), + PLL_45XX_RATE( 533000000, 533, 24, 1, 5), + PLL_45XX_RATE( 500000000, 250, 6, 2, 28), + PLL_45XX_RATE( 400000000, 200, 6, 2, 28), + PLL_45XX_RATE( 200000000, 200, 6, 3, 28), + { /* sentinel */ } +}; + +static struct samsung_pll_rate_table exynos4210_epll_rates[] __initdata = { + PLL_4600_RATE(192000000, 48, 3, 1, 0, 0), + PLL_4600_RATE(180633605, 45, 3, 1, 10381, 0), + PLL_4600_RATE(180000000, 45, 3, 1, 0, 0), + PLL_4600_RATE( 73727996, 73, 3, 3, 47710, 1), + PLL_4600_RATE( 67737602, 90, 4, 3, 20762, 1), + PLL_4600_RATE( 49151992, 49, 3, 3, 9961, 0), + PLL_4600_RATE( 45158401, 45, 3, 3, 10381, 0), + { /* sentinel */ } +}; + +static struct samsung_pll_rate_table exynos4210_vpll_rates[] __initdata = { + PLL_4650_RATE(360000000, 44, 3, 0, 1024, 0, 14, 0), + PLL_4650_RATE(324000000, 53, 2, 1, 1024, 1, 1, 1), + PLL_4650_RATE(259617187, 63, 3, 1, 1950, 0, 20, 1), + PLL_4650_RATE(110000000, 53, 3, 2, 2048, 0, 17, 0), + PLL_4650_RATE( 55360351, 53, 3, 3, 2417, 0, 17, 0), + { /* sentinel */ } +}; + static struct samsung_pll_clock exynos4210_plls[nr_plls] __initdata = { [apll] = PLL_A(pll_4508, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, "fout_apll", NULL), @@ -1038,6 +1072,17 @@ static void __init exynos4_clk_init(struct device_node *np, samsung_clk_register_mux(exynos4210_mux_early, ARRAY_SIZE(exynos4210_mux_early)); + if (_get_rate("fin_pll") == 24000000) { + exynos4210_plls[apll].rate_table = + exynos4210_apll_rates; + exynos4210_plls[epll].rate_table = + exynos4210_epll_rates; + } + + if (_get_rate("mout_vpllsrc") == 24000000) + exynos4210_plls[vpll].rate_table = + exynos4210_vpll_rates; + samsung_clk_register_pll(exynos4210_plls, ARRAY_SIZE(exynos4210_plls), reg_base); } else { From efb19a85cb0b44c06ed5ff7c397341ab852148e5 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 26 Aug 2013 19:09:10 +0200 Subject: [PATCH 100/102] clk: samsung: exynos4: Register PLL rate tables for Exynos4x12 This patch adds rate tables for PLLs that can be reconfigured at runtime for Exynos4x12 SoCs. Provided tables contain PLL coefficients for input clock of 24 MHz and so are registered only in this case. MPLL does not need runtime reconfiguration and so table for it is not provided. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos4.c | 49 +++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index c6796aff2421..bf5e5e1e99d9 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1022,6 +1022,46 @@ static struct samsung_pll_rate_table exynos4210_vpll_rates[] __initdata = { { /* sentinel */ } }; +static struct samsung_pll_rate_table exynos4x12_apll_rates[] __initdata = { + PLL_35XX_RATE(1500000000, 250, 4, 0), + PLL_35XX_RATE(1400000000, 175, 3, 0), + PLL_35XX_RATE(1300000000, 325, 6, 0), + PLL_35XX_RATE(1200000000, 200, 4, 0), + PLL_35XX_RATE(1100000000, 275, 6, 0), + PLL_35XX_RATE(1000000000, 125, 3, 0), + PLL_35XX_RATE( 900000000, 150, 4, 0), + PLL_35XX_RATE( 800000000, 100, 3, 0), + PLL_35XX_RATE( 700000000, 175, 3, 1), + PLL_35XX_RATE( 600000000, 200, 4, 1), + PLL_35XX_RATE( 500000000, 125, 3, 1), + PLL_35XX_RATE( 400000000, 100, 3, 1), + PLL_35XX_RATE( 300000000, 200, 4, 2), + PLL_35XX_RATE( 200000000, 100, 3, 2), + { /* sentinel */ } +}; + +static struct samsung_pll_rate_table exynos4x12_epll_rates[] __initdata = { + PLL_36XX_RATE(192000000, 48, 3, 1, 0), + PLL_36XX_RATE(180633605, 45, 3, 1, 10381), + PLL_36XX_RATE(180000000, 45, 3, 1, 0), + PLL_36XX_RATE( 73727996, 73, 3, 3, 47710), + PLL_36XX_RATE( 67737602, 90, 4, 3, 20762), + PLL_36XX_RATE( 49151992, 49, 3, 3, 9961), + PLL_36XX_RATE( 45158401, 45, 3, 3, 10381), + { /* sentinel */ } +}; + +static struct samsung_pll_rate_table exynos4x12_vpll_rates[] __initdata = { + PLL_36XX_RATE(533000000, 133, 3, 1, 16384), + PLL_36XX_RATE(440000000, 110, 3, 1, 0), + PLL_36XX_RATE(350000000, 175, 3, 2, 0), + PLL_36XX_RATE(266000000, 133, 3, 2, 0), + PLL_36XX_RATE(160000000, 160, 3, 3, 0), + PLL_36XX_RATE(106031250, 53, 3, 2, 1024), + PLL_36XX_RATE( 53015625, 53, 3, 3, 1024), + { /* sentinel */ } +}; + static struct samsung_pll_clock exynos4210_plls[nr_plls] __initdata = { [apll] = PLL_A(pll_4508, fout_apll, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, "fout_apll", NULL), @@ -1086,6 +1126,15 @@ static void __init exynos4_clk_init(struct device_node *np, samsung_clk_register_pll(exynos4210_plls, ARRAY_SIZE(exynos4210_plls), reg_base); } else { + if (_get_rate("fin_pll") == 24000000) { + exynos4x12_plls[apll].rate_table = + exynos4x12_apll_rates; + exynos4x12_plls[epll].rate_table = + exynos4x12_epll_rates; + exynos4x12_plls[vpll].rate_table = + exynos4x12_vpll_rates; + } + samsung_clk_register_pll(exynos4x12_plls, ARRAY_SIZE(exynos4x12_plls), reg_base); } From 22e9e7589e7bc6006af983f73e4a4057dbd9da66 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 26 Aug 2013 19:09:11 +0200 Subject: [PATCH 101/102] clk: samsung: exynos5250: Simplify registration of PLL rate tables Since the _get_rate() helper has been modified to use __clk_lookup() internally, checking of PLL input rates can be done using it and so the registration code can be simplified. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Reviewed-by: Sylwester Nawrocki Signed-off-by: Mike Turquette --- drivers/clk/samsung/clk-exynos5250.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index d90e59326252..adf32343c9f9 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -543,8 +543,6 @@ static struct of_device_id ext_clk_match[] __initdata = { static void __init exynos5250_clk_init(struct device_node *np) { void __iomem *reg_base; - struct clk *vpllsrc; - unsigned long fin_pll_rate, mout_vpllsrc_rate = 0; if (np) { reg_base = of_iomap(np, 0); @@ -563,16 +561,10 @@ static void __init exynos5250_clk_init(struct device_node *np) samsung_clk_register_mux(exynos5250_pll_pmux_clks, ARRAY_SIZE(exynos5250_pll_pmux_clks)); - fin_pll_rate = _get_rate("fin_pll"); - - if (fin_pll_rate == 24 * MHZ) + if (_get_rate("fin_pll") == 24 * MHZ) exynos5250_plls[epll].rate_table = epll_24mhz_tbl; - vpllsrc = __clk_lookup("mout_vpllsrc"); - if (vpllsrc) - mout_vpllsrc_rate = clk_get_rate(vpllsrc); - - if (mout_vpllsrc_rate == 24 * MHZ) + if (_get_rate("mout_vpllsrc") == 24 * MHZ) exynos5250_plls[vpll].rate_table = vpll_24mhz_tbl; samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls), From 12d298865ec5d0f14dd570c3506c270880769ed7 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 5 Sep 2013 08:33:24 -0500 Subject: [PATCH 102/102] clk: only call get_parent if there is one In __clk_init(), after a clock is mostly initialized, a scan is done of the orphan clocks to see if the clock being registered is the parent of any of them. This code assumes that any clock that provides a get_parent method actually has at least one parent, and that's not a valid assumption. As a result, an orphan clock with no parent can return *something* as the parent index, and that value is blindly used to dereference the orphan's parent_names[] array (which will be ZERO_SIZE_PTR or NULL). Fix this by ensuring get_parent is only called for orphans with at least one parent. Signed-off-by: Alex Elder Signed-off-by: Mike Turquette --- drivers/clk/clk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index cc4cb6fd7d83..a004769528e6 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1742,7 +1742,7 @@ int __clk_init(struct device *dev, struct clk *clk) * this clock */ hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) { - if (orphan->ops->get_parent) { + if (orphan->num_parents && orphan->ops->get_parent) { i = orphan->ops->get_parent(orphan->hw); if (!strcmp(clk->name, orphan->parent_names[i])) __clk_reparent(orphan, clk);