Messages in this thread | | | From | Frank Oltmanns <> | Subject | Re: [PATCH v5 02/11] clk: sunxi-ng: nkm: consider alternative parent rates when determining rate | Date | Sun, 06 Aug 2023 15:57:00 +0200 |
| |
On 2023-08-06 at 15:32:29 +0200, Jernej Škrabec <jernej.skrabec@gmail.com> wrote: > Dne nedelja, 06. avgust 2023 ob 15:06:47 CEST je Frank Oltmanns napisal(a): >> In case the CLK_SET_RATE_PARENT flag is set, consider using a different >> parent rate when determining a new rate. >> >> To find the best match for the requested rate, perform the following >> steps for each NKM combination: >> - calculate the optimal parent rate, >> - find the best parent rate that the parent clock actually supports >> - use that parent rate to calculate the effective rate. >> >> In case the clk does not support setting the parent rate, use the same >> algorithm as before. >> >> Acked-by: Maxime Ripard <mripard@kernel.org> >> Signed-off-by: Frank Oltmanns <frank@oltmanns.dev> >> --- >> drivers/clk/sunxi-ng/ccu_nkm.c | 45 >> +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 >> insertions(+), 1 deletion(-) >> >> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c >> index f267142e58b3..ea1b77e9b57f 100644 >> --- a/drivers/clk/sunxi-ng/ccu_nkm.c >> +++ b/drivers/clk/sunxi-ng/ccu_nkm.c >> @@ -6,6 +6,7 @@ >> >> #include <linux/clk-provider.h> >> #include <linux/io.h> >> +#include <linux/math.h> > > Why do you need above include?
It's not needed. It's a leftover from an earlier version. I'll remove it in v6.
Thank you for your review, Frank
> > Best regards, > Jernej > >> >> #include "ccu_gate.h" >> #include "ccu_nkm.h" >> @@ -16,6 +17,45 @@ struct _ccu_nkm { >> unsigned long m, min_m, max_m; >> }; >> >> +static unsigned long ccu_nkm_find_best_with_parent_adj(struct clk_hw >> *parent_hw, + > unsigned long *parent, unsigned long rate, >> + > struct _ccu_nkm *nkm) >> +{ >> + unsigned long best_rate = 0, best_parent_rate = *parent, tmp_parent > = >> *parent; + unsigned long best_n = 0, best_k = 0, best_m = 0; >> + unsigned long _n, _k, _m; >> + >> + for (_k = nkm->min_k; _k <= nkm->max_k; _k++) { >> + for (_n = nkm->min_n; _n <= nkm->max_n; _n++) { >> + for (_m = nkm->min_m; _m <= nkm->max_m; _m++) > { >> + unsigned long tmp_rate; >> + >> + tmp_parent = > clk_hw_round_rate(parent_hw, rate * _m / (_n * _k)); >> + >> + tmp_rate = tmp_parent * _n * _k / > _m; >> + if (tmp_rate > rate) >> + continue; >> + >> + if ((rate - tmp_rate) < (rate - > best_rate)) { >> + best_rate = tmp_rate; >> + best_parent_rate = > tmp_parent; >> + best_n = _n; >> + best_k = _k; >> + best_m = _m; >> + } >> + } >> + } >> + } >> + >> + nkm->n = best_n; >> + nkm->k = best_k; >> + nkm->m = best_m; >> + >> + *parent = best_parent_rate; >> + >> + return best_rate; >> +} >> + >> static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long >> rate, struct _ccu_nkm *nkm) >> { >> @@ -124,7 +164,10 @@ static unsigned long ccu_nkm_round_rate(struct >> ccu_mux_internal *mux, if (nkm->common.features & >> CCU_FEATURE_FIXED_POSTDIV) >> rate *= nkm->fixed_post_div; >> >> - rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm); >> + if (!clk_hw_can_set_rate_parent(&nkm->common.hw)) >> + rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm); >> + else >> + rate = ccu_nkm_find_best_with_parent_adj(parent_hw, > parent_rate, rate, >> &_nkm); >> >> if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV) >> rate /= nkm->fixed_post_div;
| |