mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 02:59:05 -04:00
clk: nuvoton: ma35d1: fix PLL_CTL1_FRAC bit field width and fractional calc
PLL_CTL1_FRAC was defined as GENMASK(31, 24), covering only 8 bits.
The hardware fractional field occupies bits [31:8] (24 bits), so the
mask must be GENMASK(31, 8).
The previous fractional-mode calculation used FIELD_MAX(PLL_CTL1_FRAC)
as the denominator to obtain 2 decimal places. With the corrected 24-bit
mask the old divisor is wrong; replace the arithmetic with a proper
24-bit fixed-point rounding to 3 decimal places using the kernel's
DIV_ROUND_CLOSEST_ULL helper:
n_frac = n * 1000 + DIV_ROUND_CLOSEST_ULL(x * 1000, 1 << 24)
Fixes: 691521a367 ("clk: nuvoton: Add clock driver for ma35d1 clock controller")
Signed-off-by: Joey Lu <a0987203069@gmail.com>
Reviewed-by: Brian Masney <bmasney@redhat.com>
Signed-off-by: Brian Masney <bmasney@redhat.com>
This commit is contained in:
@@ -48,7 +48,7 @@
|
||||
#define PLL_CTL1_PD BIT(0)
|
||||
#define PLL_CTL1_BP BIT(1)
|
||||
#define PLL_CTL1_OUTDIV GENMASK(6, 4)
|
||||
#define PLL_CTL1_FRAC GENMASK(31, 24)
|
||||
#define PLL_CTL1_FRAC GENMASK(31, 8)
|
||||
#define PLL_CTL2_SLOPE GENMASK(23, 0)
|
||||
|
||||
#define INDIV_MIN 1
|
||||
@@ -113,9 +113,9 @@ static unsigned long ma35d1_calc_pll_freq(u8 mode, u32 *reg_ctl, unsigned long p
|
||||
pll_freq = div_u64(pll_freq, m * p);
|
||||
} else {
|
||||
x = FIELD_GET(PLL_CTL1_FRAC, reg_ctl[1]);
|
||||
/* 2 decimal places floating to integer (ex. 1.23 to 123) */
|
||||
n = n * 100 + ((x * 100) / FIELD_MAX(PLL_CTL1_FRAC));
|
||||
pll_freq = div_u64(parent_rate * n, 100 * m * p);
|
||||
/* convert 24-bit fraction to 3 decimal digits, rounding to closest */
|
||||
n = n * 1000 + DIV_ROUND_CLOSEST_ULL((u64)x * 1000, 1ULL << 24);
|
||||
pll_freq = div_u64((u64)parent_rate * n, 1000 * m * p);
|
||||
}
|
||||
return pll_freq;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user