@@ -145,7 +145,7 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common,
goto out;
}
- if ((req->rate - tmp_rate) < (req->rate - best_rate)) {
+ if (abs(req->rate - tmp_rate) < abs(req->rate - best_rate)) {
best_rate = tmp_rate;
best_parent_rate = parent_rate;
best_parent = parent;
@@ -19,7 +19,7 @@ struct _ccu_nkm {
static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate,
struct _ccu_nkm *nkm)
{
- unsigned long best_rate = 0;
+ unsigned long best_rate = 0, best_diff = ULONG_MAX;
unsigned long best_n = 0, best_k = 0, best_m = 0;
unsigned long _n, _k, _m;
@@ -27,21 +27,26 @@ static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate,
for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
for (_m = nkm->min_m; _m <= nkm->max_m; _m++) {
unsigned long tmp_rate;
+ unsigned long tmp_diff;
tmp_rate = parent * _n * _k / _m;
- if (tmp_rate > rate)
- continue;
- if ((rate - tmp_rate) < (rate - best_rate)) {
+ tmp_diff = abs(rate - tmp_rate);
+
+ if (tmp_diff < best_diff) {
best_rate = tmp_rate;
+ best_diff = tmp_diff;
best_n = _n;
best_k = _k;
best_m = _m;
+ if (best_diff == 0)
+ goto out;
}
}
}
}
+out:
nkm->n = best_n;
nkm->k = best_k;
nkm->m = best_m;
Instead of selecting the first rate that is less than the requested rate, select the rate that minimizes the absolute difference with the requested rate. This ensures a more accurate rate selection, when the closest available rate is higher than the requested rate. Also stop searching once an exact match is found. Adjust mux to this change in rate selection. Signed-off-by: Frank Oltmanns <frank@oltmanns.dev> --- drivers/clk/sunxi-ng/ccu_mux.c | 2 +- drivers/clk/sunxi-ng/ccu_nkm.c | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-)