summaryrefslogtreecommitdiffstats
path: root/drivers/clk/clk-composite.c
diff options
context:
space:
mode:
authorSebastian Reichel <sebastian.reichel@collabora.com>2023-05-26 19:10:56 +0200
committerStephen Boyd <sboyd@kernel.org>2023-06-13 02:42:10 +0200
commitd54fb4b25a0261bf2f2bb7093fdf11a36718bf25 (patch)
tree4f97ed2ca9a8a1b2c195c90d047d36aec29ee768 /drivers/clk/clk-composite.c
parentclk: mediatek: mt8365: Fix index issue (diff)
downloadlinux-d54fb4b25a0261bf2f2bb7093fdf11a36718bf25.tar.xz
linux-d54fb4b25a0261bf2f2bb7093fdf11a36718bf25.zip
clk: composite: Fix handling of high clock rates
ULONG_MAX is used by a few drivers to figure out the highest available clock rate via clk_round_rate(clk, ULONG_MAX). Since abs() takes a signed value as input, the current logic effectively calculates with ULONG_MAX = -1, which results in the worst parent clock being chosen instead of the best one. For example on Rockchip RK3588 the eMMC driver tries to figure out the highest available clock rate. There are three parent clocks available resulting in the following rate diffs with the existing logic: GPLL: abs(18446744073709551615 - 1188000000) = 1188000001 CPLL: abs(18446744073709551615 - 1500000000) = 1500000001 XIN24M: abs(18446744073709551615 - 24000000) = 24000001 As a result the clock framework will promote a maximum supported clock rate of 24 MHz, even though 1.5GHz are possible. With the updated logic any casting between signed and unsigned is avoided and the numbers look like this instead: GPLL: 18446744073709551615 - 1188000000 = 18446744072521551615 CPLL: 18446744073709551615 - 1500000000 = 18446744072209551615 XIN24M: 18446744073709551615 - 24000000 = 18446744073685551615 As a result the parent with the highest acceptable rate is chosen instead of the parent clock with the lowest one. Cc: stable@vger.kernel.org Fixes: 49502408007b ("mmc: sdhci-of-dwcmshc: properly determine max clock on Rockchip") Tested-by: Christopher Obbard <chris.obbard@collabora.com> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> Link: https://lore.kernel.org/r/20230526171057.66876-2-sebastian.reichel@collabora.com Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
Diffstat (limited to 'drivers/clk/clk-composite.c')
-rw-r--r--drivers/clk/clk-composite.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index edfa94641bbf..66759fe28fad 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -119,7 +119,10 @@ static int clk_composite_determine_rate(struct clk_hw *hw,
if (ret)
continue;
- rate_diff = abs(req->rate - tmp_req.rate);
+ if (req->rate >= tmp_req.rate)
+ rate_diff = req->rate - tmp_req.rate;
+ else
+ rate_diff = tmp_req.rate - req->rate;
if (!rate_diff || !req->best_parent_hw
|| best_rate_diff > rate_diff) {