diff options
author | Stephen Boyd <sboyd@codeaurora.org> | 2018-01-02 19:50:27 -0500 |
---|---|---|
committer | Stephen Boyd <sboyd@codeaurora.org> | 2018-01-04 18:13:24 -0500 |
commit | 9919d44ff2977d4da709282fa0ebedddaa3b8d85 (patch) | |
tree | d6f6bce4621942794d1c7fdbc368f8e6cd3ba5ca | |
parent | e0af0c161000fa5914198d4cd1183bced68378f5 (diff) |
clk: sunxi: Use CLK_IS_CRITICAL flag for critical clks
We'd like to privatize __clk_get(), but the sunxi clk driver is
calling this function to keep a reference held on the clk and
call clk_prepare_enable() on it. We support this design in the
clk core now with the CLK_IS_CRITICAL flag, so let's just use
that instead.
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-rw-r--r-- | drivers/clk/sunxi/clk-factors.c | 26 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk-factors.h | 4 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk-mod0.c | 9 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk-sun8i-mbus.c | 7 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk-sun9i-core.c | 9 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk-sunxi.c | 36 |
6 files changed, 44 insertions, 47 deletions
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index 856fef65433b..661a73284e9f 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c | |||
@@ -176,10 +176,10 @@ static const struct clk_ops clk_factors_ops = { | |||
176 | .set_rate = clk_factors_set_rate, | 176 | .set_rate = clk_factors_set_rate, |
177 | }; | 177 | }; |
178 | 178 | ||
179 | struct clk *sunxi_factors_register(struct device_node *node, | 179 | static struct clk *__sunxi_factors_register(struct device_node *node, |
180 | const struct factors_data *data, | 180 | const struct factors_data *data, |
181 | spinlock_t *lock, | 181 | spinlock_t *lock, void __iomem *reg, |
182 | void __iomem *reg) | 182 | unsigned long flags) |
183 | { | 183 | { |
184 | struct clk *clk; | 184 | struct clk *clk; |
185 | struct clk_factors *factors; | 185 | struct clk_factors *factors; |
@@ -249,7 +249,7 @@ struct clk *sunxi_factors_register(struct device_node *node, | |||
249 | parents, i, | 249 | parents, i, |
250 | mux_hw, &clk_mux_ops, | 250 | mux_hw, &clk_mux_ops, |
251 | &factors->hw, &clk_factors_ops, | 251 | &factors->hw, &clk_factors_ops, |
252 | gate_hw, &clk_gate_ops, 0); | 252 | gate_hw, &clk_gate_ops, CLK_IS_CRITICAL); |
253 | if (IS_ERR(clk)) | 253 | if (IS_ERR(clk)) |
254 | goto err_register; | 254 | goto err_register; |
255 | 255 | ||
@@ -272,6 +272,22 @@ err_factors: | |||
272 | return NULL; | 272 | return NULL; |
273 | } | 273 | } |
274 | 274 | ||
275 | struct clk *sunxi_factors_register(struct device_node *node, | ||
276 | const struct factors_data *data, | ||
277 | spinlock_t *lock, | ||
278 | void __iomem *reg) | ||
279 | { | ||
280 | return __sunxi_factors_register(node, data, lock, reg, 0); | ||
281 | } | ||
282 | |||
283 | struct clk *sunxi_factors_register_critical(struct device_node *node, | ||
284 | const struct factors_data *data, | ||
285 | spinlock_t *lock, | ||
286 | void __iomem *reg) | ||
287 | { | ||
288 | return __sunxi_factors_register(node, data, lock, reg, CLK_IS_CRITICAL); | ||
289 | } | ||
290 | |||
275 | void sunxi_factors_unregister(struct device_node *node, struct clk *clk) | 291 | void sunxi_factors_unregister(struct device_node *node, struct clk *clk) |
276 | { | 292 | { |
277 | struct clk_hw *hw = __clk_get_hw(clk); | 293 | struct clk_hw *hw = __clk_get_hw(clk); |
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h index 824f746b2567..7ad2ca924d0d 100644 --- a/drivers/clk/sunxi/clk-factors.h +++ b/drivers/clk/sunxi/clk-factors.h | |||
@@ -55,6 +55,10 @@ struct clk *sunxi_factors_register(struct device_node *node, | |||
55 | const struct factors_data *data, | 55 | const struct factors_data *data, |
56 | spinlock_t *lock, | 56 | spinlock_t *lock, |
57 | void __iomem *reg); | 57 | void __iomem *reg); |
58 | struct clk *sunxi_factors_register_critical(struct device_node *node, | ||
59 | const struct factors_data *data, | ||
60 | spinlock_t *lock, | ||
61 | void __iomem *reg); | ||
58 | 62 | ||
59 | void sunxi_factors_unregister(struct device_node *node, struct clk *clk); | 63 | void sunxi_factors_unregister(struct device_node *node, struct clk *clk); |
60 | 64 | ||
diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c index 4417ae129ac7..a27c264cc9b4 100644 --- a/drivers/clk/sunxi/clk-mod0.c +++ b/drivers/clk/sunxi/clk-mod0.c | |||
@@ -15,7 +15,6 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/clkdev.h> | ||
19 | #include <linux/clk-provider.h> | 18 | #include <linux/clk-provider.h> |
20 | #include <linux/of_address.h> | 19 | #include <linux/of_address.h> |
21 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
@@ -155,7 +154,6 @@ static DEFINE_SPINLOCK(sun5i_a13_mbus_lock); | |||
155 | 154 | ||
156 | static void __init sun5i_a13_mbus_setup(struct device_node *node) | 155 | static void __init sun5i_a13_mbus_setup(struct device_node *node) |
157 | { | 156 | { |
158 | struct clk *mbus; | ||
159 | void __iomem *reg; | 157 | void __iomem *reg; |
160 | 158 | ||
161 | reg = of_iomap(node, 0); | 159 | reg = of_iomap(node, 0); |
@@ -164,12 +162,9 @@ static void __init sun5i_a13_mbus_setup(struct device_node *node) | |||
164 | return; | 162 | return; |
165 | } | 163 | } |
166 | 164 | ||
167 | mbus = sunxi_factors_register(node, &sun4i_a10_mod0_data, | ||
168 | &sun5i_a13_mbus_lock, reg); | ||
169 | |||
170 | /* The MBUS clocks needs to be always enabled */ | 165 | /* The MBUS clocks needs to be always enabled */ |
171 | __clk_get(mbus); | 166 | sunxi_factors_register_critical(node, &sun4i_a10_mod0_data, |
172 | clk_prepare_enable(mbus); | 167 | &sun5i_a13_mbus_lock, reg); |
173 | } | 168 | } |
174 | CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup); | 169 | CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup); |
175 | 170 | ||
diff --git a/drivers/clk/sunxi/clk-sun8i-mbus.c b/drivers/clk/sunxi/clk-sun8i-mbus.c index b200ebf159ee..56db89b6979f 100644 --- a/drivers/clk/sunxi/clk-sun8i-mbus.c +++ b/drivers/clk/sunxi/clk-sun8i-mbus.c | |||
@@ -15,7 +15,6 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/clkdev.h> | ||
19 | #include <linux/clk-provider.h> | 18 | #include <linux/clk-provider.h> |
20 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
21 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
@@ -82,11 +81,12 @@ static void __init sun8i_a23_mbus_setup(struct device_node *node) | |||
82 | mux->mask = SUN8I_MBUS_MUX_MASK; | 81 | mux->mask = SUN8I_MBUS_MUX_MASK; |
83 | mux->lock = &sun8i_a23_mbus_lock; | 82 | mux->lock = &sun8i_a23_mbus_lock; |
84 | 83 | ||
84 | /* The MBUS clocks needs to be always enabled */ | ||
85 | clk = clk_register_composite(NULL, clk_name, parents, num_parents, | 85 | clk = clk_register_composite(NULL, clk_name, parents, num_parents, |
86 | &mux->hw, &clk_mux_ops, | 86 | &mux->hw, &clk_mux_ops, |
87 | &div->hw, &clk_divider_ops, | 87 | &div->hw, &clk_divider_ops, |
88 | &gate->hw, &clk_gate_ops, | 88 | &gate->hw, &clk_gate_ops, |
89 | 0); | 89 | CLK_IS_CRITICAL); |
90 | if (IS_ERR(clk)) | 90 | if (IS_ERR(clk)) |
91 | goto err_free_gate; | 91 | goto err_free_gate; |
92 | 92 | ||
@@ -95,9 +95,6 @@ static void __init sun8i_a23_mbus_setup(struct device_node *node) | |||
95 | goto err_unregister_clk; | 95 | goto err_unregister_clk; |
96 | 96 | ||
97 | kfree(parents); /* parents is deep copied */ | 97 | kfree(parents); /* parents is deep copied */ |
98 | /* The MBUS clocks needs to be always enabled */ | ||
99 | __clk_get(clk); | ||
100 | clk_prepare_enable(clk); | ||
101 | 98 | ||
102 | return; | 99 | return; |
103 | 100 | ||
diff --git a/drivers/clk/sunxi/clk-sun9i-core.c b/drivers/clk/sunxi/clk-sun9i-core.c index 43f014f85803..e9295c286d5d 100644 --- a/drivers/clk/sunxi/clk-sun9i-core.c +++ b/drivers/clk/sunxi/clk-sun9i-core.c | |||
@@ -15,7 +15,6 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/clkdev.h> | ||
19 | #include <linux/clk-provider.h> | 18 | #include <linux/clk-provider.h> |
20 | #include <linux/of.h> | 19 | #include <linux/of.h> |
21 | #include <linux/of_address.h> | 20 | #include <linux/of_address.h> |
@@ -140,7 +139,6 @@ static DEFINE_SPINLOCK(sun9i_a80_gt_lock); | |||
140 | static void __init sun9i_a80_gt_setup(struct device_node *node) | 139 | static void __init sun9i_a80_gt_setup(struct device_node *node) |
141 | { | 140 | { |
142 | void __iomem *reg; | 141 | void __iomem *reg; |
143 | struct clk *gt; | ||
144 | 142 | ||
145 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | 143 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); |
146 | if (IS_ERR(reg)) { | 144 | if (IS_ERR(reg)) { |
@@ -149,12 +147,9 @@ static void __init sun9i_a80_gt_setup(struct device_node *node) | |||
149 | return; | 147 | return; |
150 | } | 148 | } |
151 | 149 | ||
152 | gt = sunxi_factors_register(node, &sun9i_a80_gt_data, | ||
153 | &sun9i_a80_gt_lock, reg); | ||
154 | |||
155 | /* The GT bus clock needs to be always enabled */ | 150 | /* The GT bus clock needs to be always enabled */ |
156 | __clk_get(gt); | 151 | sunxi_factors_register_critical(node, &sun9i_a80_gt_data, |
157 | clk_prepare_enable(gt); | 152 | &sun9i_a80_gt_lock, reg); |
158 | } | 153 | } |
159 | CLK_OF_DECLARE(sun9i_a80_gt, "allwinner,sun9i-a80-gt-clk", sun9i_a80_gt_setup); | 154 | CLK_OF_DECLARE(sun9i_a80_gt, "allwinner,sun9i-a80-gt-clk", sun9i_a80_gt_setup); |
160 | 155 | ||
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index aa4add580516..012714d94b42 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c | |||
@@ -656,7 +656,8 @@ static const struct mux_data sun8i_h3_ahb2_mux_data __initconst = { | |||
656 | }; | 656 | }; |
657 | 657 | ||
658 | static struct clk * __init sunxi_mux_clk_setup(struct device_node *node, | 658 | static struct clk * __init sunxi_mux_clk_setup(struct device_node *node, |
659 | const struct mux_data *data) | 659 | const struct mux_data *data, |
660 | unsigned long flags) | ||
660 | { | 661 | { |
661 | struct clk *clk; | 662 | struct clk *clk; |
662 | const char *clk_name = node->name; | 663 | const char *clk_name = node->name; |
@@ -678,7 +679,7 @@ static struct clk * __init sunxi_mux_clk_setup(struct device_node *node, | |||
678 | } | 679 | } |
679 | 680 | ||
680 | clk = clk_register_mux(NULL, clk_name, parents, i, | 681 | clk = clk_register_mux(NULL, clk_name, parents, i, |
681 | CLK_SET_RATE_PARENT, reg, | 682 | CLK_SET_RATE_PARENT | flags, reg, |
682 | data->shift, SUNXI_MUX_GATE_WIDTH, | 683 | data->shift, SUNXI_MUX_GATE_WIDTH, |
683 | 0, &clk_lock); | 684 | 0, &clk_lock); |
684 | 685 | ||
@@ -703,29 +704,22 @@ out_unmap: | |||
703 | 704 | ||
704 | static void __init sun4i_cpu_clk_setup(struct device_node *node) | 705 | static void __init sun4i_cpu_clk_setup(struct device_node *node) |
705 | { | 706 | { |
706 | struct clk *clk; | ||
707 | |||
708 | clk = sunxi_mux_clk_setup(node, &sun4i_cpu_mux_data); | ||
709 | if (!clk) | ||
710 | return; | ||
711 | |||
712 | /* Protect CPU clock */ | 707 | /* Protect CPU clock */ |
713 | __clk_get(clk); | 708 | sunxi_mux_clk_setup(node, &sun4i_cpu_mux_data, CLK_IS_CRITICAL); |
714 | clk_prepare_enable(clk); | ||
715 | } | 709 | } |
716 | CLK_OF_DECLARE(sun4i_cpu, "allwinner,sun4i-a10-cpu-clk", | 710 | CLK_OF_DECLARE(sun4i_cpu, "allwinner,sun4i-a10-cpu-clk", |
717 | sun4i_cpu_clk_setup); | 711 | sun4i_cpu_clk_setup); |
718 | 712 | ||
719 | static void __init sun6i_ahb1_mux_clk_setup(struct device_node *node) | 713 | static void __init sun6i_ahb1_mux_clk_setup(struct device_node *node) |
720 | { | 714 | { |
721 | sunxi_mux_clk_setup(node, &sun6i_a31_ahb1_mux_data); | 715 | sunxi_mux_clk_setup(node, &sun6i_a31_ahb1_mux_data, 0); |
722 | } | 716 | } |
723 | CLK_OF_DECLARE(sun6i_ahb1_mux, "allwinner,sun6i-a31-ahb1-mux-clk", | 717 | CLK_OF_DECLARE(sun6i_ahb1_mux, "allwinner,sun6i-a31-ahb1-mux-clk", |
724 | sun6i_ahb1_mux_clk_setup); | 718 | sun6i_ahb1_mux_clk_setup); |
725 | 719 | ||
726 | static void __init sun8i_ahb2_clk_setup(struct device_node *node) | 720 | static void __init sun8i_ahb2_clk_setup(struct device_node *node) |
727 | { | 721 | { |
728 | sunxi_mux_clk_setup(node, &sun8i_h3_ahb2_mux_data); | 722 | sunxi_mux_clk_setup(node, &sun8i_h3_ahb2_mux_data, 0); |
729 | } | 723 | } |
730 | CLK_OF_DECLARE(sun8i_ahb2, "allwinner,sun8i-h3-ahb2-clk", | 724 | CLK_OF_DECLARE(sun8i_ahb2, "allwinner,sun8i-h3-ahb2-clk", |
731 | sun8i_ahb2_clk_setup); | 725 | sun8i_ahb2_clk_setup); |
@@ -900,6 +894,7 @@ struct divs_data { | |||
900 | u8 shift; /* otherwise it's a normal divisor with this shift */ | 894 | u8 shift; /* otherwise it's a normal divisor with this shift */ |
901 | u8 pow; /* is it power-of-two based? */ | 895 | u8 pow; /* is it power-of-two based? */ |
902 | u8 gate; /* is it independently gateable? */ | 896 | u8 gate; /* is it independently gateable? */ |
897 | bool critical; | ||
903 | } div[SUNXI_DIVS_MAX_QTY]; | 898 | } div[SUNXI_DIVS_MAX_QTY]; |
904 | }; | 899 | }; |
905 | 900 | ||
@@ -915,7 +910,8 @@ static const struct divs_data pll5_divs_data __initconst = { | |||
915 | .factors = &sun4i_pll5_data, | 910 | .factors = &sun4i_pll5_data, |
916 | .ndivs = 2, | 911 | .ndivs = 2, |
917 | .div = { | 912 | .div = { |
918 | { .shift = 0, .pow = 0, }, /* M, DDR */ | 913 | /* Protect PLL5_DDR */ |
914 | { .shift = 0, .pow = 0, .critical = true }, /* M, DDR */ | ||
919 | { .shift = 16, .pow = 1, }, /* P, other */ | 915 | { .shift = 16, .pow = 1, }, /* P, other */ |
920 | /* No output for the base factor clock */ | 916 | /* No output for the base factor clock */ |
921 | } | 917 | } |
@@ -1089,7 +1085,9 @@ static struct clk ** __init sunxi_divs_clk_setup(struct device_node *node, | |||
1089 | NULL, NULL, | 1085 | NULL, NULL, |
1090 | rate_hw, rate_ops, | 1086 | rate_hw, rate_ops, |
1091 | gate_hw, &clk_gate_ops, | 1087 | gate_hw, &clk_gate_ops, |
1092 | clkflags); | 1088 | clkflags | |
1089 | data->div[i].critical ? | ||
1090 | CLK_IS_CRITICAL : 0); | ||
1093 | 1091 | ||
1094 | WARN_ON(IS_ERR(clk_data->clks[i])); | 1092 | WARN_ON(IS_ERR(clk_data->clks[i])); |
1095 | } | 1093 | } |
@@ -1117,15 +1115,7 @@ out_unmap: | |||
1117 | 1115 | ||
1118 | static void __init sun4i_pll5_clk_setup(struct device_node *node) | 1116 | static void __init sun4i_pll5_clk_setup(struct device_node *node) |
1119 | { | 1117 | { |
1120 | struct clk **clks; | 1118 | sunxi_divs_clk_setup(node, &pll5_divs_data); |
1121 | |||
1122 | clks = sunxi_divs_clk_setup(node, &pll5_divs_data); | ||
1123 | if (!clks) | ||
1124 | return; | ||
1125 | |||
1126 | /* Protect PLL5_DDR */ | ||
1127 | __clk_get(clks[0]); | ||
1128 | clk_prepare_enable(clks[0]); | ||
1129 | } | 1119 | } |
1130 | CLK_OF_DECLARE(sun4i_pll5, "allwinner,sun4i-a10-pll5-clk", | 1120 | CLK_OF_DECLARE(sun4i_pll5, "allwinner,sun4i-a10-pll5-clk", |
1131 | sun4i_pll5_clk_setup); | 1121 | sun4i_pll5_clk_setup); |