Lines Matching +full:div +full:- +full:clk
1 // SPDX-License-Identifier: GPL-2.0-only
7 * Tero Kristo <t-kristo@ti.com>
10 #include <linux/clk-provider.h>
15 #include <linux/clk/ti.h>
26 for (clkt = table; clkt->div; clkt++) in _get_table_div()
27 if (clkt->val == val) in _get_table_div()
28 return clkt->div; in _get_table_div()
38 if (divider->table) { in _setup_mask()
41 for (clkt = divider->table; clkt->div; clkt++) in _setup_mask()
42 if (clkt->val > max_val) in _setup_mask()
43 max_val = clkt->val; in _setup_mask()
45 max_val = divider->max; in _setup_mask()
47 if (!(divider->flags & CLK_DIVIDER_ONE_BASED) && in _setup_mask()
48 !(divider->flags & CLK_DIVIDER_POWER_OF_TWO)) in _setup_mask()
49 max_val--; in _setup_mask()
52 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) in _setup_mask()
53 mask = fls(max_val) - 1; in _setup_mask()
57 divider->mask = (1 << fls(mask)) - 1; in _setup_mask()
62 if (divider->flags & CLK_DIVIDER_ONE_BASED) in _get_div()
64 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) in _get_div()
66 if (divider->table) in _get_div()
67 return _get_table_div(divider->table, val); in _get_div()
72 unsigned int div) in _get_table_val() argument
76 for (clkt = table; clkt->div; clkt++) in _get_table_val()
77 if (clkt->div == div) in _get_table_val()
78 return clkt->val; in _get_table_val()
82 static unsigned int _get_val(struct clk_omap_divider *divider, u8 div) in _get_val() argument
84 if (divider->flags & CLK_DIVIDER_ONE_BASED) in _get_val()
85 return div; in _get_val()
86 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) in _get_val()
87 return __ffs(div); in _get_val()
88 if (divider->table) in _get_val()
89 return _get_table_val(divider->table, div); in _get_val()
90 return div - 1; in _get_val()
97 unsigned int div, val; in ti_clk_divider_recalc_rate() local
99 val = ti_clk_ll_ops->clk_readl(÷r->reg) >> divider->shift; in ti_clk_divider_recalc_rate()
100 val &= divider->mask; in ti_clk_divider_recalc_rate()
102 div = _get_div(divider, val); in ti_clk_divider_recalc_rate()
103 if (!div) { in ti_clk_divider_recalc_rate()
104 WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO), in ti_clk_divider_recalc_rate()
110 return DIV_ROUND_UP(parent_rate, div); in ti_clk_divider_recalc_rate()
117 #define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
120 unsigned int div) in _is_valid_table_div() argument
124 for (clkt = table; clkt->div; clkt++) in _is_valid_table_div()
125 if (clkt->div == div) in _is_valid_table_div()
130 static bool _is_valid_div(struct clk_omap_divider *divider, unsigned int div) in _is_valid_div() argument
132 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) in _is_valid_div()
133 return is_power_of_2(div); in _is_valid_div()
134 if (divider->table) in _is_valid_div()
135 return _is_valid_table_div(divider->table, div); in _is_valid_div()
144 int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate); in _div_round_up() local
146 for (clkt = table; clkt->div; clkt++) { in _div_round_up()
147 if (clkt->div == div) in _div_round_up()
148 return clkt->div; in _div_round_up()
149 else if (clkt->div < div) in _div_round_up()
152 if ((clkt->div - div) < (up - div)) in _div_round_up()
153 up = clkt->div; in _div_round_up()
179 maxdiv = divider->max; in ti_clk_divider_bestdiv()
183 bestdiv = _div_round(divider->table, parent_rate, rate); in ti_clk_divider_bestdiv()
218 bestdiv = divider->max; in ti_clk_divider_bestdiv()
229 int div; in ti_clk_divider_determine_rate() local
230 div = ti_clk_divider_bestdiv(hw, req->rate, &req->best_parent_rate); in ti_clk_divider_determine_rate()
232 req->rate = DIV_ROUND_UP(req->best_parent_rate, div); in ti_clk_divider_determine_rate()
241 unsigned int div, value; in ti_clk_divider_set_rate() local
245 return -EINVAL; in ti_clk_divider_set_rate()
249 div = DIV_ROUND_UP(parent_rate, rate); in ti_clk_divider_set_rate()
251 if (div > divider->max) in ti_clk_divider_set_rate()
252 div = divider->max; in ti_clk_divider_set_rate()
253 if (div < divider->min) in ti_clk_divider_set_rate()
254 div = divider->min; in ti_clk_divider_set_rate()
256 value = _get_val(divider, div); in ti_clk_divider_set_rate()
258 val = ti_clk_ll_ops->clk_readl(÷r->reg); in ti_clk_divider_set_rate()
259 val &= ~(divider->mask << divider->shift); in ti_clk_divider_set_rate()
260 val |= value << divider->shift; in ti_clk_divider_set_rate()
261 ti_clk_ll_ops->clk_writel(val, ÷r->reg); in ti_clk_divider_set_rate()
263 ti_clk_latch(÷r->reg, divider->latch); in ti_clk_divider_set_rate()
269 * clk_divider_save_context - Save the divider value
279 val = ti_clk_ll_ops->clk_readl(÷r->reg) >> divider->shift; in clk_divider_save_context()
280 divider->context = val & divider->mask; in clk_divider_save_context()
286 * clk_divider_restore_context - restore the saved the divider value
296 val = ti_clk_ll_ops->clk_readl(÷r->reg); in clk_divider_restore_context()
297 val &= ~(divider->mask << divider->shift); in clk_divider_restore_context()
298 val |= divider->context << divider->shift; in clk_divider_restore_context()
299 ti_clk_ll_ops->clk_writel(val, ÷r->reg); in clk_divider_restore_context()
310 static struct clk *_register_divider(struct device_node *node, in _register_divider()
312 struct clk_omap_divider *div) in _register_divider() argument
327 div->hw.init = &init; in _register_divider()
330 return of_ti_clk_register(node, &div->hw, name); in _register_divider()
342 divider->min = 1; in ti_clk_parse_divider_data()
343 divider->max = max_div; in ti_clk_parse_divider_data()
351 if (div_table[i] == -1) in ti_clk_parse_divider_data()
362 return -ENOMEM; in ti_clk_parse_divider_data()
368 tmp[valid_div].div = div_table[i]; in ti_clk_parse_divider_data()
377 divider->min = min_div; in ti_clk_parse_divider_data()
378 divider->max = max_div; in ti_clk_parse_divider_data()
379 divider->table = tmp; in ti_clk_parse_divider_data()
386 struct clk_omap_divider *div) in ti_clk_get_div_table() argument
413 return -EINVAL; in ti_clk_get_div_table()
418 return -ENOMEM; in ti_clk_get_div_table()
425 table[valid_div].div = val; in ti_clk_get_div_table()
431 div->table = table; in ti_clk_get_div_table()
444 if (!divider->table) { in _populate_divider_min_max()
445 /* Clk divider table not provided, determine min/max divs */ in _populate_divider_min_max()
446 if (of_property_read_u32(node, "ti,min-div", &min_div)) in _populate_divider_min_max()
449 if (of_property_read_u32(node, "ti,max-div", &max_div)) { in _populate_divider_min_max()
450 pr_err("no max-div for %pOFn!\n", node); in _populate_divider_min_max()
451 return -EINVAL; in _populate_divider_min_max()
455 for (clkt = divider->table; clkt->div; clkt++) { in _populate_divider_min_max()
456 val = clkt->div; in _populate_divider_min_max()
464 divider->min = min_div; in _populate_divider_min_max()
465 divider->max = max_div; in _populate_divider_min_max()
472 struct clk_omap_divider *div, in ti_clk_divider_populate() argument
478 ret = ti_clk_get_reg_addr(node, 0, &div->reg); in ti_clk_divider_populate()
482 div->shift = div->reg.bit; in ti_clk_divider_populate()
484 if (!of_property_read_u32(node, "ti,latch-bit", &val)) in ti_clk_divider_populate()
485 div->latch = val; in ti_clk_divider_populate()
487 div->latch = -EINVAL; in ti_clk_divider_populate()
490 div->flags = 0; in ti_clk_divider_populate()
492 if (of_property_read_bool(node, "ti,index-starts-at-one")) in ti_clk_divider_populate()
493 div->flags |= CLK_DIVIDER_ONE_BASED; in ti_clk_divider_populate()
495 if (of_property_read_bool(node, "ti,index-power-of-two")) in ti_clk_divider_populate()
496 div->flags |= CLK_DIVIDER_POWER_OF_TWO; in ti_clk_divider_populate()
498 if (of_property_read_bool(node, "ti,set-rate-parent")) in ti_clk_divider_populate()
501 ret = ti_clk_get_div_table(node, div); in ti_clk_divider_populate()
505 return _populate_divider_min_max(node, div); in ti_clk_divider_populate()
509 * of_ti_divider_clk_setup - Setup function for simple div rate clock
516 struct clk *clk; in of_ti_divider_clk_setup() local
518 struct clk_omap_divider *div; in of_ti_divider_clk_setup() local
520 div = kzalloc(sizeof(*div), GFP_KERNEL); in of_ti_divider_clk_setup()
521 if (!div) in of_ti_divider_clk_setup()
524 if (ti_clk_divider_populate(node, div, &flags)) in of_ti_divider_clk_setup()
527 clk = _register_divider(node, flags, div); in of_ti_divider_clk_setup()
528 if (!IS_ERR(clk)) { in of_ti_divider_clk_setup()
529 of_clk_add_provider(node, of_clk_src_simple_get, clk); in of_ti_divider_clk_setup()
535 kfree(div->table); in of_ti_divider_clk_setup()
536 kfree(div); in of_ti_divider_clk_setup()
538 CLK_OF_DECLARE(divider_clk, "ti,divider-clock", of_ti_divider_clk_setup);
542 struct clk_omap_divider *div; in of_ti_composite_divider_clk_setup() local
545 div = kzalloc(sizeof(*div), GFP_KERNEL); in of_ti_composite_divider_clk_setup()
546 if (!div) in of_ti_composite_divider_clk_setup()
549 if (ti_clk_divider_populate(node, div, &tmp)) in of_ti_composite_divider_clk_setup()
552 if (!ti_clk_add_component(node, &div->hw, CLK_COMPONENT_TYPE_DIVIDER)) in of_ti_composite_divider_clk_setup()
556 kfree(div->table); in of_ti_composite_divider_clk_setup()
557 kfree(div); in of_ti_composite_divider_clk_setup()
559 CLK_OF_DECLARE(ti_composite_divider_clk, "ti,composite-divider-clock",