aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Stuebner <heiko@sntech.de>2015-06-20 07:08:57 -0400
committerHeiko Stuebner <heiko@sntech.de>2016-02-04 09:49:09 -0500
commit29a30c269aba4223e2a8b443f443d7def1e43fea (patch)
tree6e378316dcebd11f449c771455091c0c0bacfa7d
parentaebe3ad801ebbcd90b3649c24ae0e90d2db8bde8 (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.c55
-rw-r--r--drivers/clk/rockchip/clk.h28
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
268static 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
268static DEFINE_SPINLOCK(clk_lock); 315static DEFINE_SPINLOCK(clk_lock);
269static struct clk **clk_table; 316static struct clk **clk_table;
270static void __iomem *reg_base; 317static 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
259struct rockchip_clk_branch { 260struct 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
511void rockchip_clk_init(struct device_node *np, void __iomem *base, 539void rockchip_clk_init(struct device_node *np, void __iomem *base,
512 unsigned long nr_clks); 540 unsigned long nr_clks);
513struct regmap *rockchip_clk_get_grf(void); 541struct regmap *rockchip_clk_get_grf(void);