aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Turquette <mturquette@baylibre.com>2016-04-30 15:47:36 -0400
committerMichael Turquette <mturquette@baylibre.com>2016-06-22 21:02:35 -0400
commit55d42c40dd8aa7384aa5c5295ef9037db2b00226 (patch)
treefb4da86435984c61973000b0b240c6743401ffa2
parent6282a2da098b07763ac5d8a710b759f17d63d1b3 (diff)
clk: meson8b: clean up cpu clocks
Remove the cpu clock registration function and helpers. Replace unnecessary configuration struct with static initialization of the desired clock type. Ninja rename a5_clk to cpu_clk to better align with cpufreq convention. Tested-by: Kevin Hilman <khilman@baylibre.com> Signed-off-by: Michael Turquette <mturquette@baylibre.com>
-rw-r--r--drivers/clk/meson/clk-cpu.c73
-rw-r--r--drivers/clk/meson/clkc.c4
-rw-r--r--drivers/clk/meson/clkc.h25
-rw-r--r--drivers/clk/meson/meson8b-clkc.c47
4 files changed, 59 insertions, 90 deletions
diff --git a/drivers/clk/meson/clk-cpu.c b/drivers/clk/meson/clk-cpu.c
index f7c30ea54ca8..f8b2b7efd016 100644
--- a/drivers/clk/meson/clk-cpu.c
+++ b/drivers/clk/meson/clk-cpu.c
@@ -51,13 +51,6 @@
51 51
52#include "clkc.h" 52#include "clkc.h"
53 53
54struct meson_clk_cpu {
55 struct notifier_block clk_nb;
56 const struct clk_div_table *div_table;
57 struct clk_hw hw;
58 void __iomem *base;
59 u16 reg_off;
60};
61#define to_meson_clk_cpu_hw(_hw) container_of(_hw, struct meson_clk_cpu, hw) 54#define to_meson_clk_cpu_hw(_hw) container_of(_hw, struct meson_clk_cpu, hw)
62#define to_meson_clk_cpu_nb(_nb) container_of(_nb, struct meson_clk_cpu, clk_nb) 55#define to_meson_clk_cpu_nb(_nb) container_of(_nb, struct meson_clk_cpu, clk_nb)
63 56
@@ -119,6 +112,7 @@ static unsigned long meson_clk_cpu_recalc_rate(struct clk_hw *hw,
119 return parent_rate / div; 112 return parent_rate / div;
120} 113}
121 114
115/* FIXME MUX1 & MUX2 should be struct clk_hw objects */
122static int meson_clk_cpu_pre_rate_change(struct meson_clk_cpu *clk_cpu, 116static int meson_clk_cpu_pre_rate_change(struct meson_clk_cpu *clk_cpu,
123 struct clk_notifier_data *ndata) 117 struct clk_notifier_data *ndata)
124{ 118{
@@ -140,6 +134,7 @@ static int meson_clk_cpu_pre_rate_change(struct meson_clk_cpu *clk_cpu,
140 return 0; 134 return 0;
141} 135}
142 136
137/* FIXME MUX1 & MUX2 should be struct clk_hw objects */
143static int meson_clk_cpu_post_rate_change(struct meson_clk_cpu *clk_cpu, 138static int meson_clk_cpu_post_rate_change(struct meson_clk_cpu *clk_cpu,
144 struct clk_notifier_data *ndata) 139 struct clk_notifier_data *ndata)
145{ 140{
@@ -161,7 +156,7 @@ static int meson_clk_cpu_post_rate_change(struct meson_clk_cpu *clk_cpu,
161 * PLL clock is to be changed. We use the xtal input as temporary parent 156 * PLL clock is to be changed. We use the xtal input as temporary parent
162 * while the PLL frequency is stabilized. 157 * while the PLL frequency is stabilized.
163 */ 158 */
164static int meson_clk_cpu_notifier_cb(struct notifier_block *nb, 159int meson_clk_cpu_notifier_cb(struct notifier_block *nb,
165 unsigned long event, void *data) 160 unsigned long event, void *data)
166{ 161{
167 struct clk_notifier_data *ndata = data; 162 struct clk_notifier_data *ndata = data;
@@ -176,68 +171,8 @@ static int meson_clk_cpu_notifier_cb(struct notifier_block *nb,
176 return notifier_from_errno(ret); 171 return notifier_from_errno(ret);
177} 172}
178 173
179static const struct clk_ops meson_clk_cpu_ops = { 174const struct clk_ops meson_clk_cpu_ops = {
180 .recalc_rate = meson_clk_cpu_recalc_rate, 175 .recalc_rate = meson_clk_cpu_recalc_rate,
181 .round_rate = meson_clk_cpu_round_rate, 176 .round_rate = meson_clk_cpu_round_rate,
182 .set_rate = meson_clk_cpu_set_rate, 177 .set_rate = meson_clk_cpu_set_rate,
183}; 178};
184
185struct clk *meson_clk_register_cpu(const struct clk_conf *clk_conf,
186 void __iomem *reg_base,
187 spinlock_t *lock)
188{
189 struct clk *clk;
190 struct clk *pclk;
191 struct meson_clk_cpu *clk_cpu;
192 struct clk_init_data init;
193 int ret;
194
195 clk_cpu = kzalloc(sizeof(*clk_cpu), GFP_KERNEL);
196 if (!clk_cpu)
197 return ERR_PTR(-ENOMEM);
198
199 clk_cpu->base = reg_base;
200 clk_cpu->reg_off = clk_conf->reg_off;
201 clk_cpu->div_table = clk_conf->conf.div_table;
202 clk_cpu->clk_nb.notifier_call = meson_clk_cpu_notifier_cb;
203
204 init.name = clk_conf->clk_name;
205 init.ops = &meson_clk_cpu_ops;
206 init.flags = clk_conf->flags | CLK_GET_RATE_NOCACHE;
207 init.flags |= CLK_SET_RATE_PARENT;
208 init.parent_names = clk_conf->clks_parent;
209 init.num_parents = 1;
210
211 clk_cpu->hw.init = &init;
212
213 pclk = __clk_lookup(clk_conf->clks_parent[0]);
214 if (!pclk) {
215 pr_err("%s: could not lookup parent clock %s\n",
216 __func__, clk_conf->clks_parent[0]);
217 ret = -EINVAL;
218 goto free_clk;
219 }
220
221 ret = clk_notifier_register(pclk, &clk_cpu->clk_nb);
222 if (ret) {
223 pr_err("%s: failed to register clock notifier for %s\n",
224 __func__, clk_conf->clk_name);
225 goto free_clk;
226 }
227
228 clk = clk_register(NULL, &clk_cpu->hw);
229 if (IS_ERR(clk)) {
230 ret = PTR_ERR(clk);
231 goto unregister_clk_nb;
232 }
233
234 return clk;
235
236unregister_clk_nb:
237 clk_notifier_unregister(pclk, &clk_cpu->clk_nb);
238free_clk:
239 kfree(clk_cpu);
240
241 return ERR_PTR(ret);
242}
243
diff --git a/drivers/clk/meson/clkc.c b/drivers/clk/meson/clkc.c
index 275da2790063..0f965537b37f 100644
--- a/drivers/clk/meson/clkc.c
+++ b/drivers/clk/meson/clkc.c
@@ -140,10 +140,6 @@ void __init meson_clk_register_clks(const struct clk_conf *clk_confs,
140 clk = meson_clk_register_composite(clk_conf, 140 clk = meson_clk_register_composite(clk_conf,
141 clk_base); 141 clk_base);
142 break; 142 break;
143 case CLK_CPU:
144 clk = meson_clk_register_cpu(clk_conf, clk_base,
145 &clk_lock);
146 break;
147 default: 143 default:
148 clk = NULL; 144 clk = NULL;
149 } 145 }
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
index 97dd4d719a84..bfa5ae24930a 100644
--- a/drivers/clk/meson/clkc.h
+++ b/drivers/clk/meson/clkc.h
@@ -69,6 +69,14 @@ struct meson_clk_pll {
69 69
70#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw) 70#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
71 71
72struct meson_clk_cpu {
73 struct clk_hw hw;
74 void __iomem *base;
75 u16 reg_off;
76 struct notifier_block clk_nb;
77 const struct clk_div_table *div_table;
78};
79
72struct composite_conf { 80struct composite_conf {
73 struct parm mux_parm; 81 struct parm mux_parm;
74 struct parm div_parm; 82 struct parm div_parm;
@@ -84,7 +92,6 @@ struct composite_conf {
84 92
85enum clk_type { 93enum clk_type {
86 CLK_COMPOSITE, 94 CLK_COMPOSITE,
87 CLK_CPU,
88}; 95};
89 96
90struct clk_conf { 97struct clk_conf {
@@ -101,17 +108,6 @@ struct clk_conf {
101 } conf; 108 } conf;
102}; 109};
103 110
104#define CPU(_ro, _ci, _cn, _cp, _dt) \
105 { \
106 .reg_off = (_ro), \
107 .clk_type = CLK_CPU, \
108 .clk_id = (_ci), \
109 .clk_name = (_cn), \
110 .clks_parent = (_cp), \
111 .num_parents = ARRAY_SIZE(_cp), \
112 .conf.div_table = (_dt), \
113 } \
114
115#define COMPOSITE(_ro, _ci, _cn, _cp, _f, _c) \ 111#define COMPOSITE(_ro, _ci, _cn, _cp, _f, _c) \
116 { \ 112 { \
117 .reg_off = (_ro), \ 113 .reg_off = (_ro), \
@@ -127,8 +123,8 @@ struct clk_conf {
127struct clk **meson_clk_init(struct device_node *np, unsigned long nr_clks); 123struct clk **meson_clk_init(struct device_node *np, unsigned long nr_clks);
128void meson_clk_register_clks(const struct clk_conf *clk_confs, 124void meson_clk_register_clks(const struct clk_conf *clk_confs,
129 unsigned int nr_confs, void __iomem *clk_base); 125 unsigned int nr_confs, void __iomem *clk_base);
130struct clk *meson_clk_register_cpu(const struct clk_conf *clk_conf, 126int meson_clk_cpu_notifier_cb(struct notifier_block *nb, unsigned long event,
131 void __iomem *reg_base, spinlock_t *lock); 127 void *data);
132 128
133/* shared data */ 129/* shared data */
134extern spinlock_t clk_lock; 130extern spinlock_t clk_lock;
@@ -136,5 +132,6 @@ extern spinlock_t clk_lock;
136/* clk_ops */ 132/* clk_ops */
137extern const struct clk_ops meson_clk_pll_ro_ops; 133extern const struct clk_ops meson_clk_pll_ro_ops;
138extern const struct clk_ops meson_clk_pll_ops; 134extern const struct clk_ops meson_clk_pll_ops;
135extern const struct clk_ops meson_clk_cpu_ops;
139 136
140#endif /* __CLKC_H */ 137#endif /* __CLKC_H */
diff --git a/drivers/clk/meson/meson8b-clkc.c b/drivers/clk/meson/meson8b-clkc.c
index 6571e66ecc4e..94512b6ada25 100644
--- a/drivers/clk/meson/meson8b-clkc.c
+++ b/drivers/clk/meson/meson8b-clkc.c
@@ -15,6 +15,7 @@
15 * this program. If not, see <http://www.gnu.org/licenses/>. 15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18#include <linux/clk.h>
18#include <linux/clk-provider.h> 19#include <linux/clk-provider.h>
19#include <linux/kernel.h> 20#include <linux/kernel.h>
20#include <linux/of.h> 21#include <linux/of.h>
@@ -110,7 +111,6 @@ static const struct clk_div_table cpu_div_table[] = {
110 { /* sentinel */ }, 111 { /* sentinel */ },
111}; 112};
112 113
113PNAME(p_cpu_clk) = { "sys_pll" };
114PNAME(p_clk81) = { "fclk_div3", "fclk_div4", "fclk_div5" }; 114PNAME(p_clk81) = { "fclk_div3", "fclk_div4", "fclk_div5" };
115PNAME(p_mali) = { "fclk_div3", "fclk_div4", "fclk_div5", 115PNAME(p_mali) = { "fclk_div3", "fclk_div4", "fclk_div5",
116 "fclk_div7", "zero" }; 116 "fclk_div7", "zero" };
@@ -286,9 +286,19 @@ static struct clk_fixed_factor meson8b_fclk_div7 = {
286 }, 286 },
287}; 287};
288 288
289static struct meson_clk_cpu meson8b_cpu_clk = {
290 .reg_off = MESON8B_REG_SYS_CPU_CNTL1,
291 .div_table = cpu_div_table,
292 .clk_nb.notifier_call = meson_clk_cpu_notifier_cb,
293 .hw.init = &(struct clk_init_data){
294 .name = "cpu_clk",
295 .ops = &meson_clk_cpu_ops,
296 .parent_names = (const char *[]){ "sys_pll" },
297 .num_parents = 1,
298 },
299};
300
289static const struct clk_conf meson8b_clk_confs[] __initconst = { 301static const struct clk_conf meson8b_clk_confs[] __initconst = {
290 CPU(MESON8B_REG_SYS_CPU_CNTL1, CLKID_CPUCLK, "a5_clk", p_cpu_clk,
291 cpu_div_table),
292 COMPOSITE(MESON8B_REG_HHI_MPEG, CLKID_CLK81, "clk81", p_clk81, 302 COMPOSITE(MESON8B_REG_HHI_MPEG, CLKID_CLK81, "clk81", p_clk81,
293 CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED, &clk81_conf), 303 CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED, &clk81_conf),
294 COMPOSITE(MESON8B_REG_MALI, CLKID_MALI, "mali", p_mali, 304 COMPOSITE(MESON8B_REG_MALI, CLKID_MALI, "mali", p_mali,
@@ -314,6 +324,7 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
314 [CLKID_FCLK_DIV4] = &meson8b_fclk_div4.hw, 324 [CLKID_FCLK_DIV4] = &meson8b_fclk_div4.hw,
315 [CLKID_FCLK_DIV5] = &meson8b_fclk_div5.hw, 325 [CLKID_FCLK_DIV5] = &meson8b_fclk_div5.hw,
316 [CLKID_FCLK_DIV7] = &meson8b_fclk_div7.hw, 326 [CLKID_FCLK_DIV7] = &meson8b_fclk_div7.hw,
327 [CLKID_CPUCLK] = &meson8b_cpu_clk.hw,
317 }, 328 },
318 .num = CLK_NR_CLKS, 329 .num = CLK_NR_CLKS,
319}; 330};
@@ -328,6 +339,8 @@ static void __init meson8b_clkc_init(struct device_node *np)
328{ 339{
329 void __iomem *clk_base; 340 void __iomem *clk_base;
330 int ret, clkid, i; 341 int ret, clkid, i;
342 struct clk_hw *parent_hw;
343 struct clk *parent_clk;
331 344
332 if (!meson_clk_init(np, CLK_NR_CLKS)) 345 if (!meson_clk_init(np, CLK_NR_CLKS))
333 return; 346 return;
@@ -343,6 +356,9 @@ static void __init meson8b_clkc_init(struct device_node *np)
343 for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++) 356 for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++)
344 meson8b_clk_plls[i]->base = clk_base; 357 meson8b_clk_plls[i]->base = clk_base;
345 358
359 /* Populate the base address for CPU clk */
360 meson8b_cpu_clk.base = clk_base;
361
346 /* 362 /*
347 * register all clks 363 * register all clks
348 * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1 364 * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
@@ -358,12 +374,37 @@ static void __init meson8b_clkc_init(struct device_node *np)
358 goto unregister; 374 goto unregister;
359 } 375 }
360 376
377 /*
378 * Register CPU clk notifier
379 *
380 * FIXME this is wrong for a lot of reasons. First, the muxes should be
381 * struct clk_hw objects. Second, we shouldn't program the muxes in
382 * notifier handlers. The tricky programming sequence will be handled
383 * by the forthcoming coordinated clock rates mechanism once that
384 * feature is released.
385 *
386 * Furthermore, looking up the parent this way is terrible. At some
387 * point we will stop allocating a default struct clk when registering
388 * a new clk_hw, and this hack will no longer work. Releasing the ccr
389 * feature before that time solves the problem :-)
390 */
391 parent_hw = clk_hw_get_parent(&meson8b_cpu_clk.hw);
392 parent_clk = parent_hw->clk;
393 ret = clk_notifier_register(parent_clk, &meson8b_cpu_clk.clk_nb);
394 if (ret) {
395 pr_err("%s: failed to register clock notifier for cpu_clk\n",
396 __func__);
397 goto unregister_clk_nb;
398 }
399
361 meson_clk_register_clks(meson8b_clk_confs, 400 meson_clk_register_clks(meson8b_clk_confs,
362 ARRAY_SIZE(meson8b_clk_confs), 401 ARRAY_SIZE(meson8b_clk_confs),
363 clk_base); 402 clk_base);
364 return; 403 return;
365 404
366/* FIXME remove after converting to platform_driver/devm_clk_register */ 405/* FIXME remove after converting to platform_driver/devm_clk_register */
406unregister_clk_nb:
407 clk_notifier_unregister(parent_clk, &meson8b_a5_clk.clk_nb);
367unregister: 408unregister:
368 for (clkid = CLK_NR_CLKS - 1; clkid >= 0; clkid--) 409 for (clkid = CLK_NR_CLKS - 1; clkid >= 0; clkid--)
369 clk_hw_unregister(meson8b_hw_onecell_data.hws[clkid]); 410 clk_hw_unregister(meson8b_hw_onecell_data.hws[clkid]);