diff options
author | Heiko Stuebner <heiko@sntech.de> | 2015-06-20 07:08:57 -0400 |
---|---|---|
committer | Heiko Stuebner <heiko@sntech.de> | 2016-02-04 09:49:09 -0500 |
commit | 29a30c269aba4223e2a8b443f443d7def1e43fea (patch) | |
tree | 6e378316dcebd11f449c771455091c0c0bacfa7d | |
parent | aebe3ad801ebbcd90b3649c24ae0e90d2db8bde8 (diff) |
clk: rockchip: add a factor clock type
Add a clock type for fixed factor clocks. This allows us to define fixed
factor clocks where they appear in the clock hierarchy instead of in the
init function.
The additional factor_gate type, finally allows us to model some last
parts of the clock tree correctly.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
-rw-r--r-- | drivers/clk/rockchip/clk.c | 55 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk.h | 28 |
2 files changed, 83 insertions, 0 deletions
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 62fbe2c6eaaf..ab5052478870 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c | |||
@@ -265,6 +265,53 @@ static struct clk *rockchip_clk_register_frac_branch(const char *name, | |||
265 | return clk; | 265 | return clk; |
266 | } | 266 | } |
267 | 267 | ||
268 | static struct clk *rockchip_clk_register_factor_branch(const char *name, | ||
269 | const char *const *parent_names, u8 num_parents, | ||
270 | void __iomem *base, unsigned int mult, unsigned int div, | ||
271 | int gate_offset, u8 gate_shift, u8 gate_flags, | ||
272 | unsigned long flags, spinlock_t *lock) | ||
273 | { | ||
274 | struct clk *clk; | ||
275 | struct clk_gate *gate = NULL; | ||
276 | struct clk_fixed_factor *fix = NULL; | ||
277 | |||
278 | /* without gate, register a simple factor clock */ | ||
279 | if (gate_offset == 0) { | ||
280 | return clk_register_fixed_factor(NULL, name, | ||
281 | parent_names[0], flags, mult, | ||
282 | div); | ||
283 | } | ||
284 | |||
285 | gate = kzalloc(sizeof(*gate), GFP_KERNEL); | ||
286 | if (!gate) | ||
287 | return ERR_PTR(-ENOMEM); | ||
288 | |||
289 | gate->flags = gate_flags; | ||
290 | gate->reg = base + gate_offset; | ||
291 | gate->bit_idx = gate_shift; | ||
292 | gate->lock = lock; | ||
293 | |||
294 | fix = kzalloc(sizeof(*fix), GFP_KERNEL); | ||
295 | if (!fix) { | ||
296 | kfree(gate); | ||
297 | return ERR_PTR(-ENOMEM); | ||
298 | } | ||
299 | |||
300 | fix->mult = mult; | ||
301 | fix->div = div; | ||
302 | |||
303 | clk = clk_register_composite(NULL, name, parent_names, num_parents, | ||
304 | NULL, NULL, | ||
305 | &fix->hw, &clk_fixed_factor_ops, | ||
306 | &gate->hw, &clk_gate_ops, flags); | ||
307 | if (IS_ERR(clk)) { | ||
308 | kfree(fix); | ||
309 | kfree(gate); | ||
310 | } | ||
311 | |||
312 | return clk; | ||
313 | } | ||
314 | |||
268 | static DEFINE_SPINLOCK(clk_lock); | 315 | static DEFINE_SPINLOCK(clk_lock); |
269 | static struct clk **clk_table; | 316 | static struct clk **clk_table; |
270 | static void __iomem *reg_base; | 317 | static void __iomem *reg_base; |
@@ -400,6 +447,14 @@ void __init rockchip_clk_register_branches( | |||
400 | reg_base + list->muxdiv_offset, | 447 | reg_base + list->muxdiv_offset, |
401 | list->div_shift, list->div_flags, &clk_lock); | 448 | list->div_shift, list->div_flags, &clk_lock); |
402 | break; | 449 | break; |
450 | case branch_factor: | ||
451 | clk = rockchip_clk_register_factor_branch( | ||
452 | list->name, list->parent_names, | ||
453 | list->num_parents, reg_base, | ||
454 | list->div_shift, list->div_width, | ||
455 | list->gate_offset, list->gate_shift, | ||
456 | list->gate_flags, flags, &clk_lock); | ||
457 | break; | ||
403 | } | 458 | } |
404 | 459 | ||
405 | /* none of the cases above matched */ | 460 | /* none of the cases above matched */ |
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index ff8bd23a93ec..39c198bbcbee 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h | |||
@@ -254,6 +254,7 @@ enum rockchip_clk_branch_type { | |||
254 | branch_gate, | 254 | branch_gate, |
255 | branch_mmc, | 255 | branch_mmc, |
256 | branch_inverter, | 256 | branch_inverter, |
257 | branch_factor, | ||
257 | }; | 258 | }; |
258 | 259 | ||
259 | struct rockchip_clk_branch { | 260 | struct rockchip_clk_branch { |
@@ -508,6 +509,33 @@ struct rockchip_clk_branch { | |||
508 | .div_flags = if, \ | 509 | .div_flags = if, \ |
509 | } | 510 | } |
510 | 511 | ||
512 | #define FACTOR(_id, cname, pname, f, fm, fd) \ | ||
513 | { \ | ||
514 | .id = _id, \ | ||
515 | .branch_type = branch_factor, \ | ||
516 | .name = cname, \ | ||
517 | .parent_names = (const char *[]){ pname }, \ | ||
518 | .num_parents = 1, \ | ||
519 | .flags = f, \ | ||
520 | .div_shift = fm, \ | ||
521 | .div_width = fd, \ | ||
522 | } | ||
523 | |||
524 | #define FACTOR_GATE(_id, cname, pname, f, fm, fd, go, gb, gf) \ | ||
525 | { \ | ||
526 | .id = _id, \ | ||
527 | .branch_type = branch_factor, \ | ||
528 | .name = cname, \ | ||
529 | .parent_names = (const char *[]){ pname }, \ | ||
530 | .num_parents = 1, \ | ||
531 | .flags = f, \ | ||
532 | .div_shift = fm, \ | ||
533 | .div_width = fd, \ | ||
534 | .gate_offset = go, \ | ||
535 | .gate_shift = gb, \ | ||
536 | .gate_flags = gf, \ | ||
537 | } | ||
538 | |||
511 | void rockchip_clk_init(struct device_node *np, void __iomem *base, | 539 | void rockchip_clk_init(struct device_node *np, void __iomem *base, |
512 | unsigned long nr_clks); | 540 | unsigned long nr_clks); |
513 | struct regmap *rockchip_clk_get_grf(void); | 541 | struct regmap *rockchip_clk_get_grf(void); |