Lines Matching +full:max +full:- +full:bit +full:- +full:rate
6 * Tero Kristo <t-kristo@ti.com>
18 #include <linux/clk-provider.h>
34 for (clkt = table; clkt->div; clkt++) in _get_table_div()
35 if (clkt->val == val) in _get_table_div()
36 return clkt->div; in _get_table_div()
46 if (divider->table) { in _setup_mask()
49 for (clkt = divider->table; clkt->div; clkt++) in _setup_mask()
50 if (clkt->val > max_val) in _setup_mask()
51 max_val = clkt->val; in _setup_mask()
53 max_val = divider->max; in _setup_mask()
55 if (!(divider->flags & CLK_DIVIDER_ONE_BASED) && in _setup_mask()
56 !(divider->flags & CLK_DIVIDER_POWER_OF_TWO)) in _setup_mask()
57 max_val--; in _setup_mask()
60 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) in _setup_mask()
61 mask = fls(max_val) - 1; in _setup_mask()
65 divider->mask = (1 << fls(mask)) - 1; in _setup_mask()
70 if (divider->flags & CLK_DIVIDER_ONE_BASED) in _get_div()
72 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) in _get_div()
74 if (divider->table) in _get_div()
75 return _get_table_div(divider->table, val); in _get_div()
84 for (clkt = table; clkt->div; clkt++) in _get_table_val()
85 if (clkt->div == div) in _get_table_val()
86 return clkt->val; in _get_table_val()
92 if (divider->flags & CLK_DIVIDER_ONE_BASED) in _get_val()
94 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) in _get_val()
96 if (divider->table) in _get_val()
97 return _get_table_val(divider->table, div); in _get_val()
98 return div - 1; in _get_val()
107 val = ti_clk_ll_ops->clk_readl(÷r->reg) >> divider->shift; in ti_clk_divider_recalc_rate()
108 val &= divider->mask; in ti_clk_divider_recalc_rate()
112 WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO), in ti_clk_divider_recalc_rate()
125 #define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
132 for (clkt = table; clkt->div; clkt++) in _is_valid_table_div()
133 if (clkt->div == div) in _is_valid_table_div()
140 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) in _is_valid_div()
142 if (divider->table) in _is_valid_div()
143 return _is_valid_table_div(divider->table, div); in _is_valid_div()
148 unsigned long parent_rate, unsigned long rate) in _div_round_up() argument
152 int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate); in _div_round_up()
154 for (clkt = table; clkt->div; clkt++) { in _div_round_up()
155 if (clkt->div == div) in _div_round_up()
156 return clkt->div; in _div_round_up()
157 else if (clkt->div < div) in _div_round_up()
160 if ((clkt->div - div) < (up - div)) in _div_round_up()
161 up = clkt->div; in _div_round_up()
168 unsigned long parent_rate, unsigned long rate) in _div_round() argument
171 return DIV_ROUND_UP(parent_rate, rate); in _div_round()
173 return _div_round_up(table, parent_rate, rate); in _div_round()
176 static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, in ti_clk_divider_bestdiv() argument
184 if (!rate) in ti_clk_divider_bestdiv()
185 rate = 1; in ti_clk_divider_bestdiv()
187 maxdiv = divider->max; in ti_clk_divider_bestdiv()
191 bestdiv = _div_round(divider->table, parent_rate, rate); in ti_clk_divider_bestdiv()
199 * unsigned long in rate * i below in ti_clk_divider_bestdiv()
201 maxdiv = min(ULONG_MAX / rate, maxdiv); in ti_clk_divider_bestdiv()
206 if (rate * i == parent_rate_saved) { in ti_clk_divider_bestdiv()
208 * It's the most ideal case if the requested rate can be in ti_clk_divider_bestdiv()
210 * parent rate, so return the divider immediately. in ti_clk_divider_bestdiv()
216 MULT_ROUND_UP(rate, i)); in ti_clk_divider_bestdiv()
218 if (now <= rate && now > best) { in ti_clk_divider_bestdiv()
226 bestdiv = divider->max; in ti_clk_divider_bestdiv()
234 static long ti_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, in ti_clk_divider_round_rate() argument
238 div = ti_clk_divider_bestdiv(hw, rate, prate); in ti_clk_divider_round_rate()
243 static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, in ti_clk_divider_set_rate() argument
250 if (!hw || !rate) in ti_clk_divider_set_rate()
251 return -EINVAL; in ti_clk_divider_set_rate()
255 div = DIV_ROUND_UP(parent_rate, rate); in ti_clk_divider_set_rate()
257 if (div > divider->max) in ti_clk_divider_set_rate()
258 div = divider->max; in ti_clk_divider_set_rate()
259 if (div < divider->min) in ti_clk_divider_set_rate()
260 div = divider->min; in ti_clk_divider_set_rate()
264 val = ti_clk_ll_ops->clk_readl(÷r->reg); in ti_clk_divider_set_rate()
265 val &= ~(divider->mask << divider->shift); in ti_clk_divider_set_rate()
266 val |= value << divider->shift; in ti_clk_divider_set_rate()
267 ti_clk_ll_ops->clk_writel(val, ÷r->reg); in ti_clk_divider_set_rate()
269 ti_clk_latch(÷r->reg, divider->latch); in ti_clk_divider_set_rate()
275 * clk_divider_save_context - Save the divider value
285 val = ti_clk_ll_ops->clk_readl(÷r->reg) >> divider->shift; in clk_divider_save_context()
286 divider->context = val & divider->mask; in clk_divider_save_context()
292 * clk_divider_restore_context - restore the saved the divider value
302 val = ti_clk_ll_ops->clk_readl(÷r->reg); in clk_divider_restore_context()
303 val &= ~(divider->mask << divider->shift); in clk_divider_restore_context()
304 val |= divider->context << divider->shift; in clk_divider_restore_context()
305 ti_clk_ll_ops->clk_writel(val, ÷r->reg); in clk_divider_restore_context()
326 init.name = node->name; in _register_divider()
332 div->hw.init = &init; in _register_divider()
335 clk = ti_clk_register(NULL, &div->hw, node->name); in _register_divider()
352 divider->min = 1; in ti_clk_parse_divider_data()
353 divider->max = max_div; in ti_clk_parse_divider_data()
361 if (div_table[i] == -1) in ti_clk_parse_divider_data()
372 return -ENOMEM; in ti_clk_parse_divider_data()
387 divider->min = min_div; in ti_clk_parse_divider_data()
388 divider->max = max_div; in ti_clk_parse_divider_data()
389 divider->table = tmp; in ti_clk_parse_divider_data()
423 return -EINVAL; in ti_clk_get_div_table()
428 return -ENOMEM; in ti_clk_get_div_table()
441 div->table = table; in ti_clk_get_div_table()
454 if (!divider->table) { in _populate_divider_min_max()
455 /* Clk divider table not provided, determine min/max divs */ in _populate_divider_min_max()
456 if (of_property_read_u32(node, "ti,min-div", &min_div)) in _populate_divider_min_max()
459 if (of_property_read_u32(node, "ti,max-div", &max_div)) { in _populate_divider_min_max()
460 pr_err("no max-div for %pOFn!\n", node); in _populate_divider_min_max()
461 return -EINVAL; in _populate_divider_min_max()
465 for (clkt = divider->table; clkt->div; clkt++) { in _populate_divider_min_max()
466 val = clkt->div; in _populate_divider_min_max()
474 divider->min = min_div; in _populate_divider_min_max()
475 divider->max = max_div; in _populate_divider_min_max()
488 ret = ti_clk_get_reg_addr(node, 0, &div->reg); in ti_clk_divider_populate()
492 if (!of_property_read_u32(node, "ti,bit-shift", &val)) in ti_clk_divider_populate()
493 div->shift = val; in ti_clk_divider_populate()
495 div->shift = 0; in ti_clk_divider_populate()
497 if (!of_property_read_u32(node, "ti,latch-bit", &val)) in ti_clk_divider_populate()
498 div->latch = val; in ti_clk_divider_populate()
500 div->latch = -EINVAL; in ti_clk_divider_populate()
503 div->flags = 0; in ti_clk_divider_populate()
505 if (of_property_read_bool(node, "ti,index-starts-at-one")) in ti_clk_divider_populate()
506 div->flags |= CLK_DIVIDER_ONE_BASED; in ti_clk_divider_populate()
508 if (of_property_read_bool(node, "ti,index-power-of-two")) in ti_clk_divider_populate()
509 div->flags |= CLK_DIVIDER_POWER_OF_TWO; in ti_clk_divider_populate()
511 if (of_property_read_bool(node, "ti,set-rate-parent")) in ti_clk_divider_populate()
522 * of_ti_divider_clk_setup - Setup function for simple div rate clock
548 kfree(div->table); in of_ti_divider_clk_setup()
551 CLK_OF_DECLARE(divider_clk, "ti,divider-clock", of_ti_divider_clk_setup);
565 if (!ti_clk_add_component(node, &div->hw, CLK_COMPONENT_TYPE_DIVIDER)) in of_ti_composite_divider_clk_setup()
569 kfree(div->table); in of_ti_composite_divider_clk_setup()
572 CLK_OF_DECLARE(ti_composite_divider_clk, "ti,composite-divider-clock",