162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * OMAP2/3/4 DPLL clock functions 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2005-2008 Texas Instruments, Inc. 662306a36Sopenharmony_ci * Copyright (C) 2004-2010 Nokia Corporation 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Contacts: 962306a36Sopenharmony_ci * Richard Woodruff <r-woodruff2@ti.com> 1062306a36Sopenharmony_ci * Paul Walmsley 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci#undef DEBUG 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <linux/kernel.h> 1562306a36Sopenharmony_ci#include <linux/errno.h> 1662306a36Sopenharmony_ci#include <linux/clk.h> 1762306a36Sopenharmony_ci#include <linux/clk-provider.h> 1862306a36Sopenharmony_ci#include <linux/io.h> 1962306a36Sopenharmony_ci#include <linux/clk/ti.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include <asm/div64.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include "clock.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* DPLL rate rounding: minimum DPLL multiplier, divider values */ 2662306a36Sopenharmony_ci#define DPLL_MIN_MULTIPLIER 2 2762306a36Sopenharmony_ci#define DPLL_MIN_DIVIDER 1 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/* Possible error results from _dpll_test_mult */ 3062306a36Sopenharmony_ci#define DPLL_MULT_UNDERFLOW -1 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* 3362306a36Sopenharmony_ci * Scale factor to mitigate roundoff errors in DPLL rate rounding. 3462306a36Sopenharmony_ci * The higher the scale factor, the greater the risk of arithmetic overflow, 3562306a36Sopenharmony_ci * but the closer the rounded rate to the target rate. DPLL_SCALE_FACTOR 3662306a36Sopenharmony_ci * must be a power of DPLL_SCALE_BASE. 3762306a36Sopenharmony_ci */ 3862306a36Sopenharmony_ci#define DPLL_SCALE_FACTOR 64 3962306a36Sopenharmony_ci#define DPLL_SCALE_BASE 2 4062306a36Sopenharmony_ci#define DPLL_ROUNDING_VAL ((DPLL_SCALE_BASE / 2) * \ 4162306a36Sopenharmony_ci (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE)) 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* 4462306a36Sopenharmony_ci * DPLL valid Fint frequency range for OMAP36xx and OMAP4xxx. 4562306a36Sopenharmony_ci * From device data manual section 4.3 "DPLL and DLL Specifications". 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_ci#define OMAP3PLUS_DPLL_FINT_JTYPE_MIN 500000 4862306a36Sopenharmony_ci#define OMAP3PLUS_DPLL_FINT_JTYPE_MAX 2500000 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/* _dpll_test_fint() return codes */ 5162306a36Sopenharmony_ci#define DPLL_FINT_UNDERFLOW -1 5262306a36Sopenharmony_ci#define DPLL_FINT_INVALID -2 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* Private functions */ 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* 5762306a36Sopenharmony_ci * _dpll_test_fint - test whether an Fint value is valid for the DPLL 5862306a36Sopenharmony_ci * @clk: DPLL struct clk to test 5962306a36Sopenharmony_ci * @n: divider value (N) to test 6062306a36Sopenharmony_ci * 6162306a36Sopenharmony_ci * Tests whether a particular divider @n will result in a valid DPLL 6262306a36Sopenharmony_ci * internal clock frequency Fint. See the 34xx TRM 4.7.6.2 "DPLL Jitter 6362306a36Sopenharmony_ci * Correction". Returns 0 if OK, -1 if the enclosing loop can terminate 6462306a36Sopenharmony_ci * (assuming that it is counting N upwards), or -2 if the enclosing loop 6562306a36Sopenharmony_ci * should skip to the next iteration (again assuming N is increasing). 6662306a36Sopenharmony_ci */ 6762306a36Sopenharmony_cistatic int _dpll_test_fint(struct clk_hw_omap *clk, unsigned int n) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci struct dpll_data *dd; 7062306a36Sopenharmony_ci long fint, fint_min, fint_max; 7162306a36Sopenharmony_ci int ret = 0; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci dd = clk->dpll_data; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci /* DPLL divider must result in a valid jitter correction val */ 7662306a36Sopenharmony_ci fint = clk_hw_get_rate(clk_hw_get_parent(&clk->hw)) / n; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci if (dd->flags & DPLL_J_TYPE) { 7962306a36Sopenharmony_ci fint_min = OMAP3PLUS_DPLL_FINT_JTYPE_MIN; 8062306a36Sopenharmony_ci fint_max = OMAP3PLUS_DPLL_FINT_JTYPE_MAX; 8162306a36Sopenharmony_ci } else { 8262306a36Sopenharmony_ci fint_min = ti_clk_get_features()->fint_min; 8362306a36Sopenharmony_ci fint_max = ti_clk_get_features()->fint_max; 8462306a36Sopenharmony_ci } 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci if (!fint_min || !fint_max) { 8762306a36Sopenharmony_ci WARN(1, "No fint limits available!\n"); 8862306a36Sopenharmony_ci return DPLL_FINT_INVALID; 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci if (fint < ti_clk_get_features()->fint_min) { 9262306a36Sopenharmony_ci pr_debug("rejecting n=%d due to Fint failure, lowering max_divider\n", 9362306a36Sopenharmony_ci n); 9462306a36Sopenharmony_ci dd->max_divider = n; 9562306a36Sopenharmony_ci ret = DPLL_FINT_UNDERFLOW; 9662306a36Sopenharmony_ci } else if (fint > ti_clk_get_features()->fint_max) { 9762306a36Sopenharmony_ci pr_debug("rejecting n=%d due to Fint failure, boosting min_divider\n", 9862306a36Sopenharmony_ci n); 9962306a36Sopenharmony_ci dd->min_divider = n; 10062306a36Sopenharmony_ci ret = DPLL_FINT_INVALID; 10162306a36Sopenharmony_ci } else if (fint > ti_clk_get_features()->fint_band1_max && 10262306a36Sopenharmony_ci fint < ti_clk_get_features()->fint_band2_min) { 10362306a36Sopenharmony_ci pr_debug("rejecting n=%d due to Fint failure\n", n); 10462306a36Sopenharmony_ci ret = DPLL_FINT_INVALID; 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci return ret; 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic unsigned long _dpll_compute_new_rate(unsigned long parent_rate, 11162306a36Sopenharmony_ci unsigned int m, unsigned int n) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci unsigned long long num; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci num = (unsigned long long)parent_rate * m; 11662306a36Sopenharmony_ci do_div(num, n); 11762306a36Sopenharmony_ci return num; 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci/* 12162306a36Sopenharmony_ci * _dpll_test_mult - test a DPLL multiplier value 12262306a36Sopenharmony_ci * @m: pointer to the DPLL m (multiplier) value under test 12362306a36Sopenharmony_ci * @n: current DPLL n (divider) value under test 12462306a36Sopenharmony_ci * @new_rate: pointer to storage for the resulting rounded rate 12562306a36Sopenharmony_ci * @target_rate: the desired DPLL rate 12662306a36Sopenharmony_ci * @parent_rate: the DPLL's parent clock rate 12762306a36Sopenharmony_ci * 12862306a36Sopenharmony_ci * This code tests a DPLL multiplier value, ensuring that the 12962306a36Sopenharmony_ci * resulting rate will not be higher than the target_rate, and that 13062306a36Sopenharmony_ci * the multiplier value itself is valid for the DPLL. Initially, the 13162306a36Sopenharmony_ci * integer pointed to by the m argument should be prescaled by 13262306a36Sopenharmony_ci * multiplying by DPLL_SCALE_FACTOR. The code will replace this with 13362306a36Sopenharmony_ci * a non-scaled m upon return. This non-scaled m will result in a 13462306a36Sopenharmony_ci * new_rate as close as possible to target_rate (but not greater than 13562306a36Sopenharmony_ci * target_rate) given the current (parent_rate, n, prescaled m) 13662306a36Sopenharmony_ci * triple. Returns DPLL_MULT_UNDERFLOW in the event that the 13762306a36Sopenharmony_ci * non-scaled m attempted to underflow, which can allow the calling 13862306a36Sopenharmony_ci * function to bail out early; or 0 upon success. 13962306a36Sopenharmony_ci */ 14062306a36Sopenharmony_cistatic int _dpll_test_mult(int *m, int n, unsigned long *new_rate, 14162306a36Sopenharmony_ci unsigned long target_rate, 14262306a36Sopenharmony_ci unsigned long parent_rate) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci int r = 0, carry = 0; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci /* Unscale m and round if necessary */ 14762306a36Sopenharmony_ci if (*m % DPLL_SCALE_FACTOR >= DPLL_ROUNDING_VAL) 14862306a36Sopenharmony_ci carry = 1; 14962306a36Sopenharmony_ci *m = (*m / DPLL_SCALE_FACTOR) + carry; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* 15262306a36Sopenharmony_ci * The new rate must be <= the target rate to avoid programming 15362306a36Sopenharmony_ci * a rate that is impossible for the hardware to handle 15462306a36Sopenharmony_ci */ 15562306a36Sopenharmony_ci *new_rate = _dpll_compute_new_rate(parent_rate, *m, n); 15662306a36Sopenharmony_ci if (*new_rate > target_rate) { 15762306a36Sopenharmony_ci (*m)--; 15862306a36Sopenharmony_ci *new_rate = 0; 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci /* Guard against m underflow */ 16262306a36Sopenharmony_ci if (*m < DPLL_MIN_MULTIPLIER) { 16362306a36Sopenharmony_ci *m = DPLL_MIN_MULTIPLIER; 16462306a36Sopenharmony_ci *new_rate = 0; 16562306a36Sopenharmony_ci r = DPLL_MULT_UNDERFLOW; 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci if (*new_rate == 0) 16962306a36Sopenharmony_ci *new_rate = _dpll_compute_new_rate(parent_rate, *m, n); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci return r; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci/** 17562306a36Sopenharmony_ci * _omap2_dpll_is_in_bypass - check if DPLL is in bypass mode or not 17662306a36Sopenharmony_ci * @v: bitfield value of the DPLL enable 17762306a36Sopenharmony_ci * 17862306a36Sopenharmony_ci * Checks given DPLL enable bitfield to see whether the DPLL is in bypass 17962306a36Sopenharmony_ci * mode or not. Returns 1 if the DPLL is in bypass, 0 otherwise. 18062306a36Sopenharmony_ci */ 18162306a36Sopenharmony_cistatic int _omap2_dpll_is_in_bypass(u32 v) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci u8 mask, val; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci mask = ti_clk_get_features()->dpll_bypass_vals; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci /* 18862306a36Sopenharmony_ci * Each set bit in the mask corresponds to a bypass value equal 18962306a36Sopenharmony_ci * to the bitshift. Go through each set-bit in the mask and 19062306a36Sopenharmony_ci * compare against the given register value. 19162306a36Sopenharmony_ci */ 19262306a36Sopenharmony_ci while (mask) { 19362306a36Sopenharmony_ci val = __ffs(mask); 19462306a36Sopenharmony_ci mask ^= (1 << val); 19562306a36Sopenharmony_ci if (v == val) 19662306a36Sopenharmony_ci return 1; 19762306a36Sopenharmony_ci } 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci return 0; 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci/* Public functions */ 20362306a36Sopenharmony_ciu8 omap2_init_dpll_parent(struct clk_hw *hw) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci struct clk_hw_omap *clk = to_clk_hw_omap(hw); 20662306a36Sopenharmony_ci u32 v; 20762306a36Sopenharmony_ci struct dpll_data *dd; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci dd = clk->dpll_data; 21062306a36Sopenharmony_ci if (!dd) 21162306a36Sopenharmony_ci return -EINVAL; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci v = ti_clk_ll_ops->clk_readl(&dd->control_reg); 21462306a36Sopenharmony_ci v &= dd->enable_mask; 21562306a36Sopenharmony_ci v >>= __ffs(dd->enable_mask); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* Reparent the struct clk in case the dpll is in bypass */ 21862306a36Sopenharmony_ci if (_omap2_dpll_is_in_bypass(v)) 21962306a36Sopenharmony_ci return 1; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci return 0; 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci/** 22562306a36Sopenharmony_ci * omap2_get_dpll_rate - returns the current DPLL CLKOUT rate 22662306a36Sopenharmony_ci * @clk: struct clk * of a DPLL 22762306a36Sopenharmony_ci * 22862306a36Sopenharmony_ci * DPLLs can be locked or bypassed - basically, enabled or disabled. 22962306a36Sopenharmony_ci * When locked, the DPLL output depends on the M and N values. When 23062306a36Sopenharmony_ci * bypassed, on OMAP2xxx, the output rate is either the 32KiHz clock 23162306a36Sopenharmony_ci * or sys_clk. Bypass rates on OMAP3 depend on the DPLL: DPLLs 1 and 23262306a36Sopenharmony_ci * 2 are bypassed with dpll1_fclk and dpll2_fclk respectively 23362306a36Sopenharmony_ci * (generated by DPLL3), while DPLL 3, 4, and 5 bypass rates are sys_clk. 23462306a36Sopenharmony_ci * Returns the current DPLL CLKOUT rate (*not* CLKOUTX2) if the DPLL is 23562306a36Sopenharmony_ci * locked, or the appropriate bypass rate if the DPLL is bypassed, or 0 23662306a36Sopenharmony_ci * if the clock @clk is not a DPLL. 23762306a36Sopenharmony_ci */ 23862306a36Sopenharmony_ciunsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci u64 dpll_clk; 24162306a36Sopenharmony_ci u32 dpll_mult, dpll_div, v; 24262306a36Sopenharmony_ci struct dpll_data *dd; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci dd = clk->dpll_data; 24562306a36Sopenharmony_ci if (!dd) 24662306a36Sopenharmony_ci return 0; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci /* Return bypass rate if DPLL is bypassed */ 24962306a36Sopenharmony_ci v = ti_clk_ll_ops->clk_readl(&dd->control_reg); 25062306a36Sopenharmony_ci v &= dd->enable_mask; 25162306a36Sopenharmony_ci v >>= __ffs(dd->enable_mask); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci if (_omap2_dpll_is_in_bypass(v)) 25462306a36Sopenharmony_ci return clk_hw_get_rate(dd->clk_bypass); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg); 25762306a36Sopenharmony_ci dpll_mult = v & dd->mult_mask; 25862306a36Sopenharmony_ci dpll_mult >>= __ffs(dd->mult_mask); 25962306a36Sopenharmony_ci dpll_div = v & dd->div1_mask; 26062306a36Sopenharmony_ci dpll_div >>= __ffs(dd->div1_mask); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci dpll_clk = (u64)clk_hw_get_rate(dd->clk_ref) * dpll_mult; 26362306a36Sopenharmony_ci do_div(dpll_clk, dpll_div + 1); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci return dpll_clk; 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci/* DPLL rate rounding code */ 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci/** 27162306a36Sopenharmony_ci * omap2_dpll_round_rate - round a target rate for an OMAP DPLL 27262306a36Sopenharmony_ci * @hw: struct clk_hw containing the struct clk * for a DPLL 27362306a36Sopenharmony_ci * @target_rate: desired DPLL clock rate 27462306a36Sopenharmony_ci * @parent_rate: parent's DPLL clock rate 27562306a36Sopenharmony_ci * 27662306a36Sopenharmony_ci * Given a DPLL and a desired target rate, round the target rate to a 27762306a36Sopenharmony_ci * possible, programmable rate for this DPLL. Attempts to select the 27862306a36Sopenharmony_ci * minimum possible n. Stores the computed (m, n) in the DPLL's 27962306a36Sopenharmony_ci * dpll_data structure so set_rate() will not need to call this 28062306a36Sopenharmony_ci * (expensive) function again. Returns ~0 if the target rate cannot 28162306a36Sopenharmony_ci * be rounded, or the rounded rate upon success. 28262306a36Sopenharmony_ci */ 28362306a36Sopenharmony_cilong omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, 28462306a36Sopenharmony_ci unsigned long *parent_rate) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci struct clk_hw_omap *clk = to_clk_hw_omap(hw); 28762306a36Sopenharmony_ci int m, n, r, scaled_max_m; 28862306a36Sopenharmony_ci int min_delta_m = INT_MAX, min_delta_n = INT_MAX; 28962306a36Sopenharmony_ci unsigned long scaled_rt_rp; 29062306a36Sopenharmony_ci unsigned long new_rate = 0; 29162306a36Sopenharmony_ci struct dpll_data *dd; 29262306a36Sopenharmony_ci unsigned long ref_rate; 29362306a36Sopenharmony_ci long delta; 29462306a36Sopenharmony_ci long prev_min_delta = LONG_MAX; 29562306a36Sopenharmony_ci const char *clk_name; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci if (!clk || !clk->dpll_data) 29862306a36Sopenharmony_ci return ~0; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci dd = clk->dpll_data; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci if (dd->max_rate && target_rate > dd->max_rate) 30362306a36Sopenharmony_ci target_rate = dd->max_rate; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci ref_rate = clk_hw_get_rate(dd->clk_ref); 30662306a36Sopenharmony_ci clk_name = clk_hw_get_name(hw); 30762306a36Sopenharmony_ci pr_debug("clock: %s: starting DPLL round_rate, target rate %lu\n", 30862306a36Sopenharmony_ci clk_name, target_rate); 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci scaled_rt_rp = target_rate / (ref_rate / DPLL_SCALE_FACTOR); 31162306a36Sopenharmony_ci scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci dd->last_rounded_rate = 0; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci for (n = dd->min_divider; n <= dd->max_divider; n++) { 31662306a36Sopenharmony_ci /* Is the (input clk, divider) pair valid for the DPLL? */ 31762306a36Sopenharmony_ci r = _dpll_test_fint(clk, n); 31862306a36Sopenharmony_ci if (r == DPLL_FINT_UNDERFLOW) 31962306a36Sopenharmony_ci break; 32062306a36Sopenharmony_ci else if (r == DPLL_FINT_INVALID) 32162306a36Sopenharmony_ci continue; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci /* Compute the scaled DPLL multiplier, based on the divider */ 32462306a36Sopenharmony_ci m = scaled_rt_rp * n; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci /* 32762306a36Sopenharmony_ci * Since we're counting n up, a m overflow means we 32862306a36Sopenharmony_ci * can bail out completely (since as n increases in 32962306a36Sopenharmony_ci * the next iteration, there's no way that m can 33062306a36Sopenharmony_ci * increase beyond the current m) 33162306a36Sopenharmony_ci */ 33262306a36Sopenharmony_ci if (m > scaled_max_m) 33362306a36Sopenharmony_ci break; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci r = _dpll_test_mult(&m, n, &new_rate, target_rate, 33662306a36Sopenharmony_ci ref_rate); 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci /* m can't be set low enough for this n - try with a larger n */ 33962306a36Sopenharmony_ci if (r == DPLL_MULT_UNDERFLOW) 34062306a36Sopenharmony_ci continue; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci /* skip rates above our target rate */ 34362306a36Sopenharmony_ci delta = target_rate - new_rate; 34462306a36Sopenharmony_ci if (delta < 0) 34562306a36Sopenharmony_ci continue; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci if (delta < prev_min_delta) { 34862306a36Sopenharmony_ci prev_min_delta = delta; 34962306a36Sopenharmony_ci min_delta_m = m; 35062306a36Sopenharmony_ci min_delta_n = n; 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci pr_debug("clock: %s: m = %d: n = %d: new_rate = %lu\n", 35462306a36Sopenharmony_ci clk_name, m, n, new_rate); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci if (delta == 0) 35762306a36Sopenharmony_ci break; 35862306a36Sopenharmony_ci } 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci if (prev_min_delta == LONG_MAX) { 36162306a36Sopenharmony_ci pr_debug("clock: %s: cannot round to rate %lu\n", 36262306a36Sopenharmony_ci clk_name, target_rate); 36362306a36Sopenharmony_ci return ~0; 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci dd->last_rounded_m = min_delta_m; 36762306a36Sopenharmony_ci dd->last_rounded_n = min_delta_n; 36862306a36Sopenharmony_ci dd->last_rounded_rate = target_rate - prev_min_delta; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci return dd->last_rounded_rate; 37162306a36Sopenharmony_ci} 372