diff options
author | Shubhrajyoti Datta <shubhrajyoti.datta@amd.com> | 2025-07-29 10:38:42 +0530 |
---|---|---|
committer | Stephen Boyd <sboyd@kernel.org> | 2025-09-21 10:56:21 -0700 |
commit | e0a94c6bb5b48c46ff4dd0533e79aacfda366b9f (patch) | |
tree | 1b0174d6020acd9ea1a1466339e70e7eb3cfa1e0 | |
parent | 8f5ae30d69d7543eee0d70083daf4de8fe15d585 (diff) |
clk: xilinx: Optimize divisor search in clk_wzrd_get_divisors_ver()
Optimise the clock wizard divisor calculation by eliminating the innermost
loop over output divider o. Earlier there was an error that is returned
if the WZRD_MIN_ERR is not achieved error is returned now it computes
the best possible frequency.
Signed-off-by: Shubhrajyoti Datta <shubhrajyoti.datta@amd.com>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
-rw-r--r-- | drivers/clk/xilinx/clk-xlnx-clock-wizard.c | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c index 0295a13a811c..6af41d207ab5 100644 --- a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c +++ b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c @@ -340,7 +340,7 @@ static int clk_wzrd_get_divisors_ver(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); - u64 vco_freq, freq, diff, vcomin, vcomax; + u64 vco_freq, freq, diff, vcomin, vcomax, best_diff = -1ULL; u32 m, d, o; u32 mmin, mmax, dmin, dmax, omin, omax; @@ -356,22 +356,26 @@ static int clk_wzrd_get_divisors_ver(struct clk_hw *hw, unsigned long rate, for (m = mmin; m <= mmax; m++) { for (d = dmin; d <= dmax; d++) { vco_freq = DIV_ROUND_CLOSEST((parent_rate * m), d); - if (vco_freq >= vcomin && vco_freq <= vcomax) { - for (o = omin; o <= omax; o++) { - freq = DIV_ROUND_CLOSEST_ULL(vco_freq, o); - diff = abs(freq - rate); - - if (diff < WZRD_MIN_ERR) { - divider->m = m; - divider->d = d; - divider->o = o; - return 0; - } - } + if (vco_freq < vcomin || vco_freq > vcomax) + continue; + + o = DIV_ROUND_CLOSEST_ULL(vco_freq, rate); + if (o < omin || o > omax) + continue; + freq = DIV_ROUND_CLOSEST_ULL(vco_freq, o); + diff = abs(freq - rate); + + if (diff < best_diff) { + best_diff = diff; + divider->m = m; + divider->d = d; + divider->o = o; + if (!diff) + return 0; } } } - return -EBUSY; + return 0; } static int clk_wzrd_get_divisors(struct clk_hw *hw, unsigned long rate, |