Lines Matching +full:clk +full:- +full:div
6 * Tero Kristo <t-kristo@ti.com>
18 #include <linux/clk-provider.h>
23 #include <linux/clk/ti.h>
29 #define div_mask(d) ((1 << ((d)->width)) - 1)
36 for (clkt = table; clkt->div; clkt++) in _get_table_maxdiv()
37 if (clkt->div > maxdiv) in _get_table_maxdiv()
38 maxdiv = clkt->div; in _get_table_maxdiv()
44 if (divider->flags & CLK_DIVIDER_ONE_BASED) in _get_maxdiv()
46 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) in _get_maxdiv()
48 if (divider->table) in _get_maxdiv()
49 return _get_table_maxdiv(divider->table); in _get_maxdiv()
58 for (clkt = table; clkt->div; clkt++) in _get_table_div()
59 if (clkt->val == val) in _get_table_div()
60 return clkt->div; in _get_table_div()
66 if (divider->flags & CLK_DIVIDER_ONE_BASED) in _get_div()
68 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) in _get_div()
70 if (divider->table) in _get_div()
71 return _get_table_div(divider->table, val); in _get_div()
76 unsigned int div) in _get_table_val() argument
80 for (clkt = table; clkt->div; clkt++) in _get_table_val()
81 if (clkt->div == div) in _get_table_val()
82 return clkt->val; in _get_table_val()
86 static unsigned int _get_val(struct clk_omap_divider *divider, u8 div) in _get_val() argument
88 if (divider->flags & CLK_DIVIDER_ONE_BASED) in _get_val()
89 return div; in _get_val()
90 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) in _get_val()
91 return __ffs(div); in _get_val()
92 if (divider->table) in _get_val()
93 return _get_table_val(divider->table, div); in _get_val()
94 return div - 1; in _get_val()
101 unsigned int div, val; in ti_clk_divider_recalc_rate() local
103 val = ti_clk_ll_ops->clk_readl(÷r->reg) >> divider->shift; in ti_clk_divider_recalc_rate()
106 div = _get_div(divider, val); in ti_clk_divider_recalc_rate()
107 if (!div) { in ti_clk_divider_recalc_rate()
108 WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO), in ti_clk_divider_recalc_rate()
114 return DIV_ROUND_UP(parent_rate, div); in ti_clk_divider_recalc_rate()
121 #define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
124 unsigned int div) in _is_valid_table_div() argument
128 for (clkt = table; clkt->div; clkt++) in _is_valid_table_div()
129 if (clkt->div == div) in _is_valid_table_div()
134 static bool _is_valid_div(struct clk_omap_divider *divider, unsigned int div) in _is_valid_div() argument
136 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) in _is_valid_div()
137 return is_power_of_2(div); in _is_valid_div()
138 if (divider->table) in _is_valid_div()
139 return _is_valid_table_div(divider->table, div); in _is_valid_div()
148 int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate); in _div_round_up() local
150 for (clkt = table; clkt->div; clkt++) { in _div_round_up()
151 if (clkt->div == div) in _div_round_up()
152 return clkt->div; in _div_round_up()
153 else if (clkt->div < div) in _div_round_up()
156 if ((clkt->div - div) < (up - div)) in _div_round_up()
157 up = clkt->div; in _div_round_up()
187 bestdiv = _div_round(divider->table, parent_rate, rate); in ti_clk_divider_bestdiv()
233 int div; in ti_clk_divider_round_rate() local
234 div = ti_clk_divider_bestdiv(hw, rate, prate); in ti_clk_divider_round_rate()
236 return DIV_ROUND_UP(*prate, div); in ti_clk_divider_round_rate()
243 unsigned int div, value; in ti_clk_divider_set_rate() local
247 return -EINVAL; in ti_clk_divider_set_rate()
251 div = DIV_ROUND_UP(parent_rate, rate); in ti_clk_divider_set_rate()
252 value = _get_val(divider, div); in ti_clk_divider_set_rate()
257 if (divider->flags & CLK_DIVIDER_HIWORD_MASK) { in ti_clk_divider_set_rate()
258 val = div_mask(divider) << (divider->shift + 16); in ti_clk_divider_set_rate()
260 val = ti_clk_ll_ops->clk_readl(÷r->reg); in ti_clk_divider_set_rate()
261 val &= ~(div_mask(divider) << divider->shift); in ti_clk_divider_set_rate()
263 val |= value << divider->shift; in ti_clk_divider_set_rate()
264 ti_clk_ll_ops->clk_writel(val, ÷r->reg); in ti_clk_divider_set_rate()
266 ti_clk_latch(÷r->reg, divider->latch); in ti_clk_divider_set_rate()
277 static struct clk *_register_divider(struct device *dev, const char *name, in _register_divider()
285 struct clk_omap_divider *div; in _register_divider() local
286 struct clk *clk; in _register_divider() local
292 return ERR_PTR(-EINVAL); in _register_divider()
297 div = kzalloc(sizeof(*div), GFP_KERNEL); in _register_divider()
298 if (!div) in _register_divider()
299 return ERR_PTR(-ENOMEM); in _register_divider()
308 memcpy(&div->reg, reg, sizeof(*reg)); in _register_divider()
309 div->shift = shift; in _register_divider()
310 div->width = width; in _register_divider()
311 div->latch = latch; in _register_divider()
312 div->flags = clk_divider_flags; in _register_divider()
313 div->hw.init = &init; in _register_divider()
314 div->table = table; in _register_divider()
317 clk = ti_clk_register(dev, &div->hw, name); in _register_divider()
319 if (IS_ERR(clk)) in _register_divider()
320 kfree(div); in _register_divider()
322 return clk; in _register_divider()
331 int div; in ti_clk_parse_divider_data() local
341 div = 1; in ti_clk_parse_divider_data()
343 while (div < max_div) { in ti_clk_parse_divider_data()
345 div <<= 1; in ti_clk_parse_divider_data()
347 div++; in ti_clk_parse_divider_data()
360 if (div_table[i] == -1) in ti_clk_parse_divider_data()
371 *table = ERR_PTR(-ENOMEM); in ti_clk_parse_divider_data()
372 return -ENOMEM; in ti_clk_parse_divider_data()
380 tmp[valid_div].div = div_table[i]; in ti_clk_parse_divider_data()
397 ti_clk_parse_divider_data(setup->dividers, setup->num_dividers, in _get_div_table_from_setup()
398 setup->max_div, setup->flags, width, in _get_div_table_from_setup()
406 struct clk_omap_divider *div; in ti_clk_build_component_div() local
413 div = kzalloc(sizeof(*div), GFP_KERNEL); in ti_clk_build_component_div()
414 if (!div) in ti_clk_build_component_div()
415 return ERR_PTR(-ENOMEM); in ti_clk_build_component_div()
417 reg = (struct clk_omap_reg *)&div->reg; in ti_clk_build_component_div()
418 reg->index = setup->module; in ti_clk_build_component_div()
419 reg->offset = setup->reg; in ti_clk_build_component_div()
421 if (setup->flags & CLKF_INDEX_STARTS_AT_ONE) in ti_clk_build_component_div()
422 div->flags |= CLK_DIVIDER_ONE_BASED; in ti_clk_build_component_div()
424 if (setup->flags & CLKF_INDEX_POWER_OF_TWO) in ti_clk_build_component_div()
425 div->flags |= CLK_DIVIDER_POWER_OF_TWO; in ti_clk_build_component_div()
427 div->table = _get_div_table_from_setup(setup, &div->width); in ti_clk_build_component_div()
428 if (IS_ERR(div->table)) { in ti_clk_build_component_div()
429 ret = PTR_ERR(div->table); in ti_clk_build_component_div()
430 kfree(div); in ti_clk_build_component_div()
435 div->shift = setup->bit_shift; in ti_clk_build_component_div()
436 div->latch = -EINVAL; in ti_clk_build_component_div()
438 return &div->hw; in ti_clk_build_component_div()
441 struct clk *ti_clk_register_divider(struct ti_clk *setup) in ti_clk_register_divider()
443 struct ti_clk_divider *div = setup->data; in ti_clk_register_divider() local
445 .index = div->module, in ti_clk_register_divider()
446 .offset = div->reg, in ti_clk_register_divider()
452 struct clk *clk; in ti_clk_register_divider() local
454 if (div->flags & CLKF_INDEX_STARTS_AT_ONE) in ti_clk_register_divider()
457 if (div->flags & CLKF_INDEX_POWER_OF_TWO) in ti_clk_register_divider()
460 if (div->flags & CLKF_SET_RATE_PARENT) in ti_clk_register_divider()
463 table = _get_div_table_from_setup(div, &width); in ti_clk_register_divider()
465 return (struct clk *)table; in ti_clk_register_divider()
467 clk = _register_divider(NULL, setup->name, div->parent, in ti_clk_register_divider()
468 flags, ®, div->bit_shift, in ti_clk_register_divider()
469 width, -EINVAL, div_flags, table); in ti_clk_register_divider()
471 if (IS_ERR(clk)) in ti_clk_register_divider()
474 return clk; in ti_clk_register_divider()
504 pr_err("no valid dividers for %s table\n", node->name); in ti_clk_get_div_table()
505 return ERR_PTR(-EINVAL); in ti_clk_get_div_table()
511 return ERR_PTR(-ENOMEM); in ti_clk_get_div_table()
518 table[valid_div].div = val; in ti_clk_get_div_table()
534 u32 div; in _get_divider_width() local
537 /* Clk divider table not provided, determine min/max divs */ in _get_divider_width()
538 if (of_property_read_u32(node, "ti,min-div", &min_div)) in _get_divider_width()
541 if (of_property_read_u32(node, "ti,max-div", &max_div)) { in _get_divider_width()
542 pr_err("no max-div for %s!\n", node->name); in _get_divider_width()
543 return -EINVAL; in _get_divider_width()
550 div = min_div; in _get_divider_width()
552 while (div < max_div) { in _get_divider_width()
554 div <<= 1; in _get_divider_width()
556 div++; in _get_divider_width()
560 div = 0; in _get_divider_width()
562 while (table[div].div) { in _get_divider_width()
563 val = table[div].val; in _get_divider_width()
564 div++; in _get_divider_width()
582 if (!of_property_read_u32(node, "ti,bit-shift", &val)) in ti_clk_divider_populate()
588 if (!of_property_read_u32(node, "ti,latch-bit", &val)) in ti_clk_divider_populate()
591 *latch = -EINVAL; in ti_clk_divider_populate()
597 if (of_property_read_bool(node, "ti,index-starts-at-one")) in ti_clk_divider_populate()
600 if (of_property_read_bool(node, "ti,index-power-of-two")) in ti_clk_divider_populate()
603 if (of_property_read_bool(node, "ti,set-rate-parent")) in ti_clk_divider_populate()
617 * of_ti_divider_clk_setup - Setup function for simple div rate clock
624 struct clk *clk; in of_ti_divider_clk_setup() local
630 s8 latch = -EINVAL; in of_ti_divider_clk_setup()
640 clk = _register_divider(NULL, node->name, parent_name, flags, ®, in of_ti_divider_clk_setup()
643 if (!IS_ERR(clk)) { in of_ti_divider_clk_setup()
644 of_clk_add_provider(node, of_clk_src_simple_get, clk); in of_ti_divider_clk_setup()
652 CLK_OF_DECLARE(divider_clk, "ti,divider-clock", of_ti_divider_clk_setup);
656 struct clk_omap_divider *div; in of_ti_composite_divider_clk_setup() local
659 div = kzalloc(sizeof(*div), GFP_KERNEL); in of_ti_composite_divider_clk_setup()
660 if (!div) in of_ti_composite_divider_clk_setup()
663 if (ti_clk_divider_populate(node, &div->reg, &div->table, &val, in of_ti_composite_divider_clk_setup()
664 &div->flags, &div->width, &div->shift, in of_ti_composite_divider_clk_setup()
668 if (!ti_clk_add_component(node, &div->hw, CLK_COMPONENT_TYPE_DIVIDER)) in of_ti_composite_divider_clk_setup()
672 kfree(div->table); in of_ti_composite_divider_clk_setup()
673 kfree(div); in of_ti_composite_divider_clk_setup()
675 CLK_OF_DECLARE(ti_composite_divider_clk, "ti,composite-divider-clock",