Lines Matching +full:m +full:- +full:num
1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2005-2008 Texas Instruments, Inc.
6 * Copyright (C) 2004-2010 Nokia Corporation
9 * Richard Woodruff <r-woodruff2@ti.com>
17 #include <linux/clk-provider.h>
30 #define DPLL_MULT_UNDERFLOW -1
51 #define DPLL_FINT_UNDERFLOW -1
52 #define DPLL_FINT_INVALID -2
57 * _dpll_test_fint - test whether an Fint value is valid for the DPLL
63 * Correction". Returns 0 if OK, -1 if the enclosing loop can terminate
64 * (assuming that it is counting N upwards), or -2 if the enclosing loop
73 dd = clk->dpll_data; in _dpll_test_fint()
76 fint = clk_hw_get_rate(clk_hw_get_parent(&clk->hw)) / n; in _dpll_test_fint()
78 if (dd->flags & DPLL_J_TYPE) { in _dpll_test_fint()
82 fint_min = ti_clk_get_features()->fint_min; in _dpll_test_fint()
83 fint_max = ti_clk_get_features()->fint_max; in _dpll_test_fint()
91 if (fint < ti_clk_get_features()->fint_min) { in _dpll_test_fint()
94 dd->max_divider = n; in _dpll_test_fint()
96 } else if (fint > ti_clk_get_features()->fint_max) { in _dpll_test_fint()
99 dd->min_divider = n; in _dpll_test_fint()
101 } else if (fint > ti_clk_get_features()->fint_band1_max && in _dpll_test_fint()
102 fint < ti_clk_get_features()->fint_band2_min) { in _dpll_test_fint()
111 unsigned int m, unsigned int n) in _dpll_compute_new_rate() argument
113 unsigned long long num; in _dpll_compute_new_rate() local
115 num = (unsigned long long)parent_rate * m; in _dpll_compute_new_rate()
116 do_div(num, n); in _dpll_compute_new_rate()
117 return num; in _dpll_compute_new_rate()
121 * _dpll_test_mult - test a DPLL multiplier value
122 * @m: pointer to the DPLL m (multiplier) value under test
131 * integer pointed to by the m argument should be prescaled by
133 * a non-scaled m upon return. This non-scaled m will result in a
135 * target_rate) given the current (parent_rate, n, prescaled m)
137 * non-scaled m attempted to underflow, which can allow the calling
140 static int _dpll_test_mult(int *m, int n, unsigned long *new_rate, in _dpll_test_mult() argument
146 /* Unscale m and round if necessary */ in _dpll_test_mult()
147 if (*m % DPLL_SCALE_FACTOR >= DPLL_ROUNDING_VAL) in _dpll_test_mult()
149 *m = (*m / DPLL_SCALE_FACTOR) + carry; in _dpll_test_mult()
155 *new_rate = _dpll_compute_new_rate(parent_rate, *m, n); in _dpll_test_mult()
157 (*m)--; in _dpll_test_mult()
161 /* Guard against m underflow */ in _dpll_test_mult()
162 if (*m < DPLL_MIN_MULTIPLIER) { in _dpll_test_mult()
163 *m = DPLL_MIN_MULTIPLIER; in _dpll_test_mult()
169 *new_rate = _dpll_compute_new_rate(parent_rate, *m, n); in _dpll_test_mult()
175 * _omap2_dpll_is_in_bypass - check if DPLL is in bypass mode or not
185 mask = ti_clk_get_features()->dpll_bypass_vals; in _omap2_dpll_is_in_bypass()
189 * to the bitshift. Go through each set-bit in the mask and in _omap2_dpll_is_in_bypass()
209 dd = clk->dpll_data; in omap2_init_dpll_parent()
211 return -EINVAL; in omap2_init_dpll_parent()
213 v = ti_clk_ll_ops->clk_readl(&dd->control_reg); in omap2_init_dpll_parent()
214 v &= dd->enable_mask; in omap2_init_dpll_parent()
215 v >>= __ffs(dd->enable_mask); in omap2_init_dpll_parent()
225 * omap2_get_dpll_rate - returns the current DPLL CLKOUT rate
228 * DPLLs can be locked or bypassed - basically, enabled or disabled.
229 * When locked, the DPLL output depends on the M and N values. When
244 dd = clk->dpll_data; in omap2_get_dpll_rate()
249 v = ti_clk_ll_ops->clk_readl(&dd->control_reg); in omap2_get_dpll_rate()
250 v &= dd->enable_mask; in omap2_get_dpll_rate()
251 v >>= __ffs(dd->enable_mask); in omap2_get_dpll_rate()
254 return clk_hw_get_rate(dd->clk_bypass); in omap2_get_dpll_rate()
256 v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg); in omap2_get_dpll_rate()
257 dpll_mult = v & dd->mult_mask; in omap2_get_dpll_rate()
258 dpll_mult >>= __ffs(dd->mult_mask); in omap2_get_dpll_rate()
259 dpll_div = v & dd->div1_mask; in omap2_get_dpll_rate()
260 dpll_div >>= __ffs(dd->div1_mask); in omap2_get_dpll_rate()
262 dpll_clk = (u64)clk_hw_get_rate(dd->clk_ref) * dpll_mult; in omap2_get_dpll_rate()
271 * omap2_dpll_determine_rate - round a target rate for an OMAP DPLL
277 * minimum possible n. Stores the computed (m, n) in the DPLL's
279 * (expensive) function again. Returns -EINVAL if the target rate
285 int m, n, r, scaled_max_m; in omap2_dpll_determine_rate() local
295 if (!clk || !clk->dpll_data) in omap2_dpll_determine_rate()
296 return -EINVAL; in omap2_dpll_determine_rate()
298 dd = clk->dpll_data; in omap2_dpll_determine_rate()
300 if (dd->max_rate && req->rate > dd->max_rate) in omap2_dpll_determine_rate()
301 req->rate = dd->max_rate; in omap2_dpll_determine_rate()
303 ref_rate = clk_hw_get_rate(dd->clk_ref); in omap2_dpll_determine_rate()
306 clk_name, req->rate); in omap2_dpll_determine_rate()
308 scaled_rt_rp = req->rate / (ref_rate / DPLL_SCALE_FACTOR); in omap2_dpll_determine_rate()
309 scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR; in omap2_dpll_determine_rate()
311 dd->last_rounded_rate = 0; in omap2_dpll_determine_rate()
313 for (n = dd->min_divider; n <= dd->max_divider; n++) { in omap2_dpll_determine_rate()
322 m = scaled_rt_rp * n; in omap2_dpll_determine_rate()
325 * Since we're counting n up, a m overflow means we in omap2_dpll_determine_rate()
327 * the next iteration, there's no way that m can in omap2_dpll_determine_rate()
328 * increase beyond the current m) in omap2_dpll_determine_rate()
330 if (m > scaled_max_m) in omap2_dpll_determine_rate()
333 r = _dpll_test_mult(&m, n, &new_rate, req->rate, in omap2_dpll_determine_rate()
336 /* m can't be set low enough for this n - try with a larger n */ in omap2_dpll_determine_rate()
341 delta = req->rate - new_rate; in omap2_dpll_determine_rate()
347 min_delta_m = m; in omap2_dpll_determine_rate()
351 pr_debug("clock: %s: m = %d: n = %d: new_rate = %lu\n", in omap2_dpll_determine_rate()
352 clk_name, m, n, new_rate); in omap2_dpll_determine_rate()
360 clk_name, req->rate); in omap2_dpll_determine_rate()
361 return -EINVAL; in omap2_dpll_determine_rate()
364 dd->last_rounded_m = min_delta_m; in omap2_dpll_determine_rate()
365 dd->last_rounded_n = min_delta_n; in omap2_dpll_determine_rate()
366 dd->last_rounded_rate = req->rate - prev_min_delta; in omap2_dpll_determine_rate()
368 req->rate = dd->last_rounded_rate; in omap2_dpll_determine_rate()