Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: fractional-divider: Improve approximation when zero based and export

Consider the CLK_FRAC_DIVIDER_ZERO_BASED flag when finding the best
approximation for m and n. By doing so, increase the range of valid
values for the numerator and denominator by 1.

Furthermore, export the approximation function so that users of this
function can be compiled as modules.

Cc: A.s. Dong <aisheng.dong@nxp.com>
Signed-off-by: Frank Oltmanns <frank@oltmanns.dev>
Link: https://lore.kernel.org/r/20230617131041.18313-2-frank@oltmanns.dev
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by

Frank Oltmanns and committed by
Stephen Boyd
2e9abc6e 0bb80ecc

+20 -7
+20 -7
drivers/clk/clk-fractional-divider.c
··· 123 123 unsigned long *m, unsigned long *n) 124 124 { 125 125 struct clk_fractional_divider *fd = to_clk_fd(hw); 126 + unsigned long max_m, max_n; 126 127 127 128 /* 128 129 * Get rate closer to *parent_rate to guarantee there is no overflow ··· 139 138 rate <<= scale - fd->nwidth; 140 139 } 141 140 142 - rational_best_approximation(rate, *parent_rate, 143 - GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0), 144 - m, n); 141 + if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) { 142 + max_m = 1 << fd->mwidth; 143 + max_n = 1 << fd->nwidth; 144 + } else { 145 + max_m = GENMASK(fd->mwidth - 1, 0); 146 + max_n = GENMASK(fd->nwidth - 1, 0); 147 + } 148 + 149 + rational_best_approximation(rate, *parent_rate, max_m, max_n, m, n); 145 150 } 151 + EXPORT_SYMBOL_GPL(clk_fractional_divider_general_approximation); 146 152 147 153 static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate, 148 154 unsigned long *parent_rate) ··· 177 169 { 178 170 struct clk_fractional_divider *fd = to_clk_fd(hw); 179 171 unsigned long flags = 0; 180 - unsigned long m, n; 172 + unsigned long m, n, max_m, max_n; 181 173 u32 mmask, nmask; 182 174 u32 val; 183 175 184 - rational_best_approximation(rate, parent_rate, 185 - GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0), 186 - &m, &n); 176 + if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) { 177 + max_m = 1 << fd->mwidth; 178 + max_n = 1 << fd->nwidth; 179 + } else { 180 + max_m = GENMASK(fd->mwidth - 1, 0); 181 + max_n = GENMASK(fd->nwidth - 1, 0); 182 + } 183 + rational_best_approximation(rate, parent_rate, max_m, max_n, &m, &n); 187 184 188 185 if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) { 189 186 m--;