From a8d722f03923b1c6166d39482c6df8f017e185d9 Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Tue, 5 Aug 2025 07:03:58 +0400 Subject: [PATCH 01/29] clk: rockchip: Fix error pointer check after rockchip_clk_register_gate_link() Replace NULL check with IS_ERR_OR_NULL() check after calling rockchip_clk_register_gate_link() since this function returns error pointers (ERR_PTR). Fixes: c62fa612cfa6 ("clk: rockchip: implement linked gate clock support") Signed-off-by: Miaoqian Lin Link: https://patch.msgid.link/20250805030358.3665878-1-linmq006@gmail.com Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 2601df3b1066..9ac9d13e87de 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -693,7 +693,7 @@ void rockchip_clk_register_late_branches(struct device *dev, break; } - if (!pdev) + if (IS_ERR_OR_NULL(pdev)) dev_err(dev, "failed to register device for clock %s\n", list->name); } } From d93faac66dc04650d924f8f9584216d14f48fb14 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Fri, 5 Dec 2025 14:46:27 -0500 Subject: [PATCH 02/29] clk: microchip: core: remove duplicate determine_rate on pic32_sclk_ops pic32_sclk_ops previously had a sclk_round_rate() member, and this was recently converted over to sclk_determine_rate() with the help of a Coccinelle semantic patch. pic32_sclk_ops now has two conflicting determine_rate ops members. Prior to the conversion, pic32_sclk_ops already had a determine_rate member that points to __clk_mux_determine_rate(). When both the round_rate() and determine_rate() ops are defined, the clk core only uses the determine_rate() op. Let's go ahead and drop the recently converted sclk_determine_rate() to match the previous functionality prior to the conversion. Fixes: e9f039c08cdc ("clk: microchip: core: convert from round_rate() to determine_rate()") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202511222115.uvHrP95A-lkp@intel.com/ Signed-off-by: Brian Masney Reviewed-by: Claudiu Beznea Link: https://lore.kernel.org/r/20251205-clk-microchip-fixes-v3-1-a02190705e47@redhat.com Signed-off-by: Claudiu Beznea --- drivers/clk/microchip/clk-core.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/clk/microchip/clk-core.c b/drivers/clk/microchip/clk-core.c index b34348d491f3..a0163441dfe5 100644 --- a/drivers/clk/microchip/clk-core.c +++ b/drivers/clk/microchip/clk-core.c @@ -780,15 +780,6 @@ static unsigned long sclk_get_rate(struct clk_hw *hw, unsigned long parent_rate) return parent_rate / div; } -static int sclk_determine_rate(struct clk_hw *hw, - struct clk_rate_request *req) -{ - req->rate = calc_best_divided_rate(req->rate, req->best_parent_rate, - SLEW_SYSDIV, 1); - - return 0; -} - static int sclk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { @@ -912,7 +903,6 @@ static int sclk_init(struct clk_hw *hw) const struct clk_ops pic32_sclk_ops = { .get_parent = sclk_get_parent, .set_parent = sclk_set_parent, - .determine_rate = sclk_determine_rate, .set_rate = sclk_set_rate, .recalc_rate = sclk_get_rate, .init = sclk_init, From 5df96d141cccb37f0c3112a22fc1112ea48e9246 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Fri, 5 Dec 2025 14:46:28 -0500 Subject: [PATCH 03/29] clk: microchip: core: correct return value on *_get_parent() roclk_get_parent() and sclk_get_parent() has the possibility of returning -EINVAL, however the framework expects this call to always succeed since the return value is unsigned. If there is no parent map defined, then the current value programmed in the hardware is used. Let's use that same value in the case where -EINVAL is currently returned. This index is only used by clk_core_get_parent_by_index(), and it validates that it doesn't overflow the number of available parents. Reported-by: kernel test robot Reported-by: Dan Carpenter Closes: https://lore.kernel.org/r/202512050233.R9hAWsJN-lkp@intel.com/ Signed-off-by: Brian Masney Reviewed-by: Claudiu Beznea Link: https://lore.kernel.org/r/20251205-clk-microchip-fixes-v3-2-a02190705e47@redhat.com Signed-off-by: Claudiu Beznea --- drivers/clk/microchip/clk-core.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/clk/microchip/clk-core.c b/drivers/clk/microchip/clk-core.c index a0163441dfe5..82f62731fc0e 100644 --- a/drivers/clk/microchip/clk-core.c +++ b/drivers/clk/microchip/clk-core.c @@ -283,14 +283,13 @@ static u8 roclk_get_parent(struct clk_hw *hw) v = (readl(refo->ctrl_reg) >> REFO_SEL_SHIFT) & REFO_SEL_MASK; - if (!refo->parent_map) - return v; + if (refo->parent_map) { + for (i = 0; i < clk_hw_get_num_parents(hw); i++) + if (refo->parent_map[i] == v) + return i; + } - for (i = 0; i < clk_hw_get_num_parents(hw); i++) - if (refo->parent_map[i] == v) - return i; - - return -EINVAL; + return v; } static unsigned long roclk_calc_rate(unsigned long parent_rate, @@ -817,13 +816,13 @@ static u8 sclk_get_parent(struct clk_hw *hw) v = (readl(sclk->mux_reg) >> OSC_CUR_SHIFT) & OSC_CUR_MASK; - if (!sclk->parent_map) - return v; + if (sclk->parent_map) { + for (i = 0; i < clk_hw_get_num_parents(hw); i++) + if (sclk->parent_map[i] == v) + return i; + } - for (i = 0; i < clk_hw_get_num_parents(hw); i++) - if (sclk->parent_map[i] == v) - return i; - return -EINVAL; + return v; } static int sclk_set_parent(struct clk_hw *hw, u8 index) From 69ccb0f338ea00732d51c164ccfcfdb703bf3839 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Fri, 5 Dec 2025 14:46:29 -0500 Subject: [PATCH 04/29] clk: microchip: core: remove unused include asm/traps.h The asm/traps.h include file is not actually used, so let's go ahead and remove it. Signed-off-by: Brian Masney Link: https://lore.kernel.org/r/20251205-clk-microchip-fixes-v3-3-a02190705e47@redhat.com Signed-off-by: Claudiu Beznea --- drivers/clk/microchip/clk-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/microchip/clk-core.c b/drivers/clk/microchip/clk-core.c index 82f62731fc0e..f467d7bc28c8 100644 --- a/drivers/clk/microchip/clk-core.c +++ b/drivers/clk/microchip/clk-core.c @@ -10,7 +10,6 @@ #include #include #include -#include #include "clk-core.h" From dfb208b9aebb32dece9ceddfecf84b35a876fbd3 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Tue, 13 Jan 2026 22:11:45 +0000 Subject: [PATCH 05/29] clk: microchip: drop POLARFIRE from ARCH_MICROCHIP_POLARFIRE This driver is used by non-polarfire devices now, and the ARCH_MICROCHIP symbol has been defined for some time on RISCV so drop it without any functional change. Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/20260113-doing-surplus-dc45866f71d4@spud Signed-off-by: Claudiu Beznea --- drivers/clk/microchip/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/microchip/Kconfig b/drivers/clk/microchip/Kconfig index 1b9e43eb5497..0c03b14699bf 100644 --- a/drivers/clk/microchip/Kconfig +++ b/drivers/clk/microchip/Kconfig @@ -5,8 +5,8 @@ config COMMON_CLK_PIC32 config MCHP_CLK_MPFS bool "Clk driver for PolarFire SoC" - depends on ARCH_MICROCHIP_POLARFIRE || COMPILE_TEST - default ARCH_MICROCHIP_POLARFIRE + depends on ARCH_MICROCHIP || COMPILE_TEST + default y depends on MFD_SYSCON select AUXILIARY_BUS select REGMAP_MMIO From e6584bda8d4584a58f020b559617ae7cfde51644 Mon Sep 17 00:00:00 2001 From: Pierre-Henry Moussay Date: Tue, 13 Jan 2026 22:11:46 +0000 Subject: [PATCH 06/29] dt-bindings: clock: mpfs-ccc: Add pic64gx compatibility pic64gx SoC Clock Conditioning Circuitry is compatibles with the Polarfire SoC Signed-off-by: Pierre-Henry Moussay Acked-by: Conor Dooley Reviewed-by: Claudiu Beznea Acked-by: Rob Herring (Arm) Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/20260113-guise-conceded-88030697b831@spud Signed-off-by: Claudiu Beznea --- .../devicetree/bindings/clock/microchip,mpfs-ccc.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/microchip,mpfs-ccc.yaml b/Documentation/devicetree/bindings/clock/microchip,mpfs-ccc.yaml index f1770360798f..9a6b50527c42 100644 --- a/Documentation/devicetree/bindings/clock/microchip,mpfs-ccc.yaml +++ b/Documentation/devicetree/bindings/clock/microchip,mpfs-ccc.yaml @@ -17,7 +17,11 @@ description: | properties: compatible: - const: microchip,mpfs-ccc + oneOf: + - items: + - const: microchip,pic64gx-ccc + - const: microchip,mpfs-ccc + - const: microchip,mpfs-ccc reg: items: From ec8c1f35b5aa7aa63bd398add63a8633adad532c Mon Sep 17 00:00:00 2001 From: Pierre-Henry Moussay Date: Tue, 13 Jan 2026 22:11:47 +0000 Subject: [PATCH 07/29] dt-bindings: clock: mpfs-clkcfg: Add pic64gx compatibility pic64gx has a clock controller compatible with mpfs-clkcfg. Don't permit the deprecated configuration that was never supported for this SoC. Signed-off-by: Pierre-Henry Moussay Acked-by: Krzysztof Kozlowski Reviewed-by: Claudiu Beznea Co-developed-by: Conor Dooley Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/20260113-glue-justifier-566ffab2ffd3@spud Signed-off-by: Claudiu Beznea --- .../bindings/clock/microchip,mpfs-clkcfg.yaml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/microchip,mpfs-clkcfg.yaml b/Documentation/devicetree/bindings/clock/microchip,mpfs-clkcfg.yaml index ee4f31596d97..a23703c281d1 100644 --- a/Documentation/devicetree/bindings/clock/microchip,mpfs-clkcfg.yaml +++ b/Documentation/devicetree/bindings/clock/microchip,mpfs-clkcfg.yaml @@ -19,7 +19,11 @@ description: | properties: compatible: - const: microchip,mpfs-clkcfg + oneOf: + - items: + - const: microchip,pic64gx-clkcfg + - const: microchip,mpfs-clkcfg + - const: microchip,mpfs-clkcfg reg: oneOf: @@ -69,6 +73,16 @@ required: - clocks - '#clock-cells' +if: + properties: + compatible: + contains: + const: microchip,pic64gx-clkcfg +then: + properties: + reg: + maxItems: 1 + additionalProperties: false examples: From 9bb910b049402b7a3496250c9c6ab169aed83d15 Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Tue, 13 Jan 2026 15:52:41 +0100 Subject: [PATCH 08/29] clk: imx: fracn-gppll: Add 332.60 MHz Support Some parallel panels have a pixelclk of 33.260 MHz. Add support for 332.60 MHz so a by 10 divider can be used to derive the exact pixelclk. Reviewed-by: Primoz Fiser Signed-off-by: Marco Felsch Reviewed-by: Abel Vesa Reviewed-by: Peng Fan Acked-by: Daniel Baluta Link: https://patch.msgid.link/20260113-v6-18-topic-clk-fracn-gppll-v3-1-45da70f43c98@pengutronix.de Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-fracn-gppll.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c index 090d60867250..579f76494eb0 100644 --- a/drivers/clk/imx/clk-fracn-gppll.c +++ b/drivers/clk/imx/clk-fracn-gppll.c @@ -88,6 +88,7 @@ static const struct imx_fracn_gppll_rate_table fracn_tbl[] = { PLL_FRACN_GP(445333333U, 167, 0, 1, 0, 9), PLL_FRACN_GP(400000000U, 200, 0, 1, 0, 12), PLL_FRACN_GP(393216000U, 163, 84, 100, 0, 10), + PLL_FRACN_GP(332600000U, 138, 584, 1000, 0, 10), PLL_FRACN_GP(300000000U, 150, 0, 1, 0, 12) }; From 3e6b0227b93c708e93e33f6c3485bad077650766 Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Tue, 13 Jan 2026 15:52:42 +0100 Subject: [PATCH 09/29] clk: imx: fracn-gppll: Add 241.90 MHz Support Some parallel panels have a pixelclk of 24.19 MHz. Add support for 241.90 MHz so a by 10 divider can be used to derive the exact pixelclk. Signed-off-by: Marco Felsch Reviewed-by: Abel Vesa Reviewed-by: Peng Fan Acked-by: Daniel Baluta Link: https://patch.msgid.link/20260113-v6-18-topic-clk-fracn-gppll-v3-2-45da70f43c98@pengutronix.de Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-fracn-gppll.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c index 579f76494eb0..6de5349adf70 100644 --- a/drivers/clk/imx/clk-fracn-gppll.c +++ b/drivers/clk/imx/clk-fracn-gppll.c @@ -89,7 +89,8 @@ static const struct imx_fracn_gppll_rate_table fracn_tbl[] = { PLL_FRACN_GP(400000000U, 200, 0, 1, 0, 12), PLL_FRACN_GP(393216000U, 163, 84, 100, 0, 10), PLL_FRACN_GP(332600000U, 138, 584, 1000, 0, 10), - PLL_FRACN_GP(300000000U, 150, 0, 1, 0, 12) + PLL_FRACN_GP(300000000U, 150, 0, 1, 0, 12), + PLL_FRACN_GP(241900000U, 201, 584, 1000, 0, 20), }; struct imx_fracn_gppll_clk imx_fracn_gppll = { From a641384bb03bc2c85bd51dc60d40e9f15aeaa446 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:19 -0500 Subject: [PATCH 10/29] clk: sophgo: cv18xx-ip: convert from divider_round_rate() to divider_determine_rate() The divider_round_rate() function is now deprecated, so let's migrate to divider_determine_rate() instead so that this deprecated API can be removed. Also go ahead and convert all of the driver from round rate type to determine rate that accepts a 'struct clk_rate_request' to simplify the overall driver code. Signed-off-by: Brian Masney --- drivers/clk/sophgo/clk-cv18xx-ip.c | 154 ++++++++++++++++------------- 1 file changed, 85 insertions(+), 69 deletions(-) diff --git a/drivers/clk/sophgo/clk-cv18xx-ip.c b/drivers/clk/sophgo/clk-cv18xx-ip.c index c2b58faf0938..e936e3154003 100644 --- a/drivers/clk/sophgo/clk-cv18xx-ip.c +++ b/drivers/clk/sophgo/clk-cv18xx-ip.c @@ -152,28 +152,27 @@ static u32 div_helper_get_clockdiv(struct cv1800_clk_common *common, return clockdiv; } -static u32 div_helper_round_rate(struct cv1800_clk_regfield *div, - struct clk_hw *hw, struct clk_hw *parent, - unsigned long rate, unsigned long *prate) +static int div_helper_determine_rate(struct cv1800_clk_regfield *div, + struct clk_hw *hw, + struct clk_rate_request *req) { if (div->width == 0) { if (div->initval <= 0) - return DIV_ROUND_UP_ULL(*prate, 1); + req->rate = DIV_ROUND_UP_ULL(req->best_parent_rate, 1); else - return DIV_ROUND_UP_ULL(*prate, div->initval); + req->rate = DIV_ROUND_UP_ULL(req->best_parent_rate, div->initval); + + return 0; } - return divider_round_rate_parent(hw, parent, rate, prate, NULL, - div->width, div->flags); + return divider_determine_rate(hw, req, NULL, div->width, div->flags); } -static long div_round_rate(struct clk_hw *parent, unsigned long *parent_rate, - unsigned long rate, int id, void *data) +static int do_div_determine_rate(struct clk_rate_request *req, int id, void *data) { struct cv1800_clk_div *div = data; - return div_helper_round_rate(&div->div, &div->common.hw, parent, - rate, parent_rate); + return div_helper_determine_rate(&div->div, &div->common.hw, req); } static bool div_is_better_rate(struct cv1800_clk_common *common, @@ -188,53 +187,60 @@ static bool div_is_better_rate(struct cv1800_clk_common *common, static int mux_helper_determine_rate(struct cv1800_clk_common *common, struct clk_rate_request *req, - long (*round)(struct clk_hw *, - unsigned long *, - unsigned long, - int, - void *), + int (*round)(struct clk_rate_request *, + int, + void *), void *data) { unsigned long best_parent_rate = 0, best_rate = 0; struct clk_hw *best_parent, *hw = &common->hw; unsigned int i; + int ret; if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) { - unsigned long adj_parent_rate; + struct clk_rate_request tmp_req = *req; best_parent = clk_hw_get_parent(hw); - best_parent_rate = clk_hw_get_rate(best_parent); + tmp_req.best_parent_hw = best_parent; + tmp_req.best_parent_rate = clk_hw_get_rate(best_parent); - best_rate = round(best_parent, &adj_parent_rate, - req->rate, -1, data); + ret = round(&tmp_req, -1, data); + if (ret) + return ret; + + best_parent_rate = tmp_req.best_parent_rate; + best_rate = tmp_req.rate; goto find; } for (i = 0; i < clk_hw_get_num_parents(hw); i++) { - unsigned long tmp_rate, parent_rate; + struct clk_rate_request tmp_req = *req; struct clk_hw *parent; parent = clk_hw_get_parent_by_index(hw, i); if (!parent) continue; - parent_rate = clk_hw_get_rate(parent); + tmp_req.best_parent_hw = parent; + tmp_req.best_parent_rate = clk_hw_get_rate(parent); - tmp_rate = round(parent, &parent_rate, req->rate, i, data); + ret = round(&tmp_req, i, data); + if (ret) + continue; - if (tmp_rate == req->rate) { + if (tmp_req.rate == req->rate) { best_parent = parent; - best_parent_rate = parent_rate; - best_rate = tmp_rate; + best_parent_rate = tmp_req.best_parent_rate; + best_rate = tmp_req.rate; goto find; } if (div_is_better_rate(common, req->rate, - tmp_rate, best_rate)) { + tmp_req.rate, best_rate)) { best_parent = parent; - best_parent_rate = parent_rate; - best_rate = tmp_rate; + best_parent_rate = tmp_req.best_parent_rate; + best_rate = tmp_req.rate; } } @@ -254,7 +260,7 @@ static int div_determine_rate(struct clk_hw *hw, struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw); return mux_helper_determine_rate(&div->common, req, - div_round_rate, div); + do_div_determine_rate, div); } static unsigned long div_recalc_rate(struct clk_hw *hw, @@ -301,24 +307,28 @@ hw_to_cv1800_clk_bypass_div(struct clk_hw *hw) return container_of(div, struct cv1800_clk_bypass_div, div); } -static long bypass_div_round_rate(struct clk_hw *parent, - unsigned long *parent_rate, - unsigned long rate, int id, void *data) +static int do_bypass_div_determine_rate(struct clk_rate_request *req, int id, + void *data) { struct cv1800_clk_bypass_div *div = data; if (id == -1) { - if (cv1800_clk_checkbit(&div->div.common, &div->bypass)) - return *parent_rate; - else - return div_round_rate(parent, parent_rate, rate, - -1, &div->div); + if (cv1800_clk_checkbit(&div->div.common, &div->bypass)) { + req->rate = req->best_parent_rate; + + return 0; + } + + return do_div_determine_rate(req, -1, &div->div); } - if (id == 0) - return *parent_rate; + if (id == 0) { + req->rate = req->best_parent_rate; - return div_round_rate(parent, parent_rate, rate, id - 1, &div->div); + return 0; + } + + return do_div_determine_rate(req, id - 1, &div->div); } static int bypass_div_determine_rate(struct clk_hw *hw, @@ -327,7 +337,7 @@ static int bypass_div_determine_rate(struct clk_hw *hw, struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw); return mux_helper_determine_rate(&div->div.common, req, - bypass_div_round_rate, div); + do_bypass_div_determine_rate, div); } static unsigned long bypass_div_recalc_rate(struct clk_hw *hw, @@ -414,13 +424,11 @@ static int mux_is_enabled(struct clk_hw *hw) return cv1800_clk_checkbit(&mux->common, &mux->gate); } -static long mux_round_rate(struct clk_hw *parent, unsigned long *parent_rate, - unsigned long rate, int id, void *data) +static int do_mux_determine_rate(struct clk_rate_request *req, int id, void *data) { struct cv1800_clk_mux *mux = data; - return div_helper_round_rate(&mux->div, &mux->common.hw, parent, - rate, parent_rate); + return div_helper_determine_rate(&mux->div, &mux->common.hw, req); } static int mux_determine_rate(struct clk_hw *hw, @@ -429,7 +437,7 @@ static int mux_determine_rate(struct clk_hw *hw, struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); return mux_helper_determine_rate(&mux->common, req, - mux_round_rate, mux); + do_mux_determine_rate, mux); } static unsigned long mux_recalc_rate(struct clk_hw *hw, @@ -512,24 +520,28 @@ hw_to_cv1800_clk_bypass_mux(struct clk_hw *hw) return container_of(mux, struct cv1800_clk_bypass_mux, mux); } -static long bypass_mux_round_rate(struct clk_hw *parent, - unsigned long *parent_rate, - unsigned long rate, int id, void *data) +static int do_bypass_mux_determine_rate(struct clk_rate_request *req, int id, + void *data) { struct cv1800_clk_bypass_mux *mux = data; if (id == -1) { - if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass)) - return *parent_rate; - else - return mux_round_rate(parent, parent_rate, rate, - -1, &mux->mux); + if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass)) { + req->rate = req->best_parent_rate; + + return 0; + } + + return do_mux_determine_rate(req, -1, &mux->mux); } - if (id == 0) - return *parent_rate; + if (id == 0) { + req->rate = req->best_parent_rate; - return mux_round_rate(parent, parent_rate, rate, id - 1, &mux->mux); + return 0; + } + + return do_mux_determine_rate(req, id - 1, &mux->mux); } static int bypass_mux_determine_rate(struct clk_hw *hw, @@ -538,7 +550,7 @@ static int bypass_mux_determine_rate(struct clk_hw *hw, struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw); return mux_helper_determine_rate(&mux->mux.common, req, - bypass_mux_round_rate, mux); + do_bypass_mux_determine_rate, mux); } static unsigned long bypass_mux_recalc_rate(struct clk_hw *hw, @@ -639,27 +651,31 @@ static int mmux_is_enabled(struct clk_hw *hw) return cv1800_clk_checkbit(&mmux->common, &mmux->gate); } -static long mmux_round_rate(struct clk_hw *parent, unsigned long *parent_rate, - unsigned long rate, int id, void *data) +static int do_mmux_determine_rate(struct clk_rate_request *req, int id, void *data) { struct cv1800_clk_mmux *mmux = data; s8 div_id; if (id == -1) { - if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass)) - return *parent_rate; + if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass)) { + req->rate = req->best_parent_rate; + + return 0; + } id = mmux_get_parent_id(mmux); } div_id = mmux->parent2sel[id]; - if (div_id < 0) - return *parent_rate; + if (div_id < 0) { + req->rate = req->best_parent_rate; - return div_helper_round_rate(&mmux->div[div_id], - &mmux->common.hw, parent, - rate, parent_rate); + return 0; + } + + return div_helper_determine_rate(&mmux->div[div_id], &mmux->common.hw, + req); } static int mmux_determine_rate(struct clk_hw *hw, @@ -668,7 +684,7 @@ static int mmux_determine_rate(struct clk_hw *hw, struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw); return mux_helper_determine_rate(&mmux->common, req, - mmux_round_rate, mmux); + do_mmux_determine_rate, mmux); } static unsigned long mmux_recalc_rate(struct clk_hw *hw, From 1c8d7af61b37db526393a46224417f36420e97f8 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:20 -0500 Subject: [PATCH 11/29] clk: sunxi-ng: convert from divider_round_rate_parent() to divider_determine_rate() The divider_round_rate_parent() function is now deprecated, so let's migrate to divider_determine_rate() instead so that this deprecated API can be removed. Also go ahead and convert all of the driver from round rate type to determine rate that accepts a 'struct clk_rate_request' to simplify the overall driver code. Acked-by: Chen-Yu Tsai Signed-off-by: Brian Masney --- drivers/clk/sunxi-ng/ccu_div.c | 25 ++++++++--------- drivers/clk/sunxi-ng/ccu_mp.c | 26 ++++++++--------- drivers/clk/sunxi-ng/ccu_mult.c | 16 +++++------ drivers/clk/sunxi-ng/ccu_mux.c | 49 ++++++++++++++++++++------------- drivers/clk/sunxi-ng/ccu_mux.h | 8 ++---- drivers/clk/sunxi-ng/ccu_nkm.c | 25 +++++++++-------- 6 files changed, 79 insertions(+), 70 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu_div.c b/drivers/clk/sunxi-ng/ccu_div.c index 916d6da6d8a3..62d680ccb524 100644 --- a/drivers/clk/sunxi-ng/ccu_div.c +++ b/drivers/clk/sunxi-ng/ccu_div.c @@ -10,26 +10,25 @@ #include "ccu_gate.h" #include "ccu_div.h" -static unsigned long ccu_div_round_rate(struct ccu_mux_internal *mux, - struct clk_hw *parent, - unsigned long *parent_rate, - unsigned long rate, - void *data) +static int ccu_div_determine_rate_helper(struct ccu_mux_internal *mux, + struct clk_rate_request *req, + void *data) { struct ccu_div *cd = data; + int ret; if (cd->common.features & CCU_FEATURE_FIXED_POSTDIV) - rate *= cd->fixed_post_div; + req->rate *= cd->fixed_post_div; - rate = divider_round_rate_parent(&cd->common.hw, parent, - rate, parent_rate, - cd->div.table, cd->div.width, - cd->div.flags); + ret = divider_determine_rate(&cd->common.hw, req, cd->div.table, + cd->div.width, cd->div.flags); + if (ret) + return ret; if (cd->common.features & CCU_FEATURE_FIXED_POSTDIV) - rate /= cd->fixed_post_div; + req->rate /= cd->fixed_post_div; - return rate; + return 0; } static void ccu_div_disable(struct clk_hw *hw) @@ -82,7 +81,7 @@ static int ccu_div_determine_rate(struct clk_hw *hw, struct ccu_div *cd = hw_to_ccu_div(hw); return ccu_mux_helper_determine_rate(&cd->common, &cd->mux, - req, ccu_div_round_rate, cd); + req, ccu_div_determine_rate_helper, cd); } static int ccu_div_set_rate(struct clk_hw *hw, unsigned long rate, diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c index 4221b1888b38..7cdb0eedc69b 100644 --- a/drivers/clk/sunxi-ng/ccu_mp.c +++ b/drivers/clk/sunxi-ng/ccu_mp.c @@ -103,11 +103,9 @@ static unsigned long ccu_mp_find_best_with_parent_adj(struct clk_hw *hw, return best_rate; } -static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux, - struct clk_hw *hw, - unsigned long *parent_rate, - unsigned long rate, - void *data) +static int ccu_mp_determine_rate_helper(struct ccu_mux_internal *mux, + struct clk_rate_request *req, + void *data) { struct ccu_mp *cmp = data; unsigned int max_m, max_p; @@ -115,7 +113,7 @@ static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux, bool shift = true; if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV) - rate *= cmp->fixed_post_div; + req->rate *= cmp->fixed_post_div; if (cmp->common.features & CCU_FEATURE_DUAL_DIV) shift = false; @@ -127,17 +125,19 @@ static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux, max_p = cmp->p.max ?: 1 << cmp->p.width; if (!clk_hw_can_set_rate_parent(&cmp->common.hw)) { - rate = ccu_mp_find_best(*parent_rate, rate, max_m, max_p, shift, - &m, &p); + req->rate = ccu_mp_find_best(req->best_parent_rate, req->rate, + max_m, max_p, shift, &m, &p); } else { - rate = ccu_mp_find_best_with_parent_adj(hw, parent_rate, rate, - max_m, max_p, shift); + req->rate = ccu_mp_find_best_with_parent_adj(req->best_parent_hw, + &req->best_parent_rate, + req->rate, max_m, max_p, + shift); } if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV) - rate /= cmp->fixed_post_div; + req->rate /= cmp->fixed_post_div; - return rate; + return 0; } static void ccu_mp_disable(struct clk_hw *hw) @@ -201,7 +201,7 @@ static int ccu_mp_determine_rate(struct clk_hw *hw, struct ccu_mp *cmp = hw_to_ccu_mp(hw); return ccu_mux_helper_determine_rate(&cmp->common, &cmp->mux, - req, ccu_mp_round_rate, cmp); + req, ccu_mp_determine_rate_helper, cmp); } static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate, diff --git a/drivers/clk/sunxi-ng/ccu_mult.c b/drivers/clk/sunxi-ng/ccu_mult.c index 8d5720f3dec1..3fc81e7de6e9 100644 --- a/drivers/clk/sunxi-ng/ccu_mult.c +++ b/drivers/clk/sunxi-ng/ccu_mult.c @@ -29,11 +29,9 @@ static void ccu_mult_find_best(unsigned long parent, unsigned long rate, mult->mult = _mult; } -static unsigned long ccu_mult_round_rate(struct ccu_mux_internal *mux, - struct clk_hw *parent, - unsigned long *parent_rate, - unsigned long rate, - void *data) +static int ccu_mult_determine_rate_helper(struct ccu_mux_internal *mux, + struct clk_rate_request *req, + void *data) { struct ccu_mult *cm = data; struct _ccu_mult _cm; @@ -45,9 +43,11 @@ static unsigned long ccu_mult_round_rate(struct ccu_mux_internal *mux, else _cm.max = (1 << cm->mult.width) + cm->mult.offset - 1; - ccu_mult_find_best(*parent_rate, rate, &_cm); + ccu_mult_find_best(req->best_parent_rate, req->rate, &_cm); - return *parent_rate * _cm.mult; + req->rate = req->best_parent_rate * _cm.mult; + + return 0; } static void ccu_mult_disable(struct clk_hw *hw) @@ -97,7 +97,7 @@ static int ccu_mult_determine_rate(struct clk_hw *hw, struct ccu_mult *cm = hw_to_ccu_mult(hw); return ccu_mux_helper_determine_rate(&cm->common, &cm->mux, - req, ccu_mult_round_rate, cm); + req, ccu_mult_determine_rate_helper, cm); } static int ccu_mult_set_rate(struct clk_hw *hw, unsigned long rate, diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c index 74f9e98a5d35..766f27cff748 100644 --- a/drivers/clk/sunxi-ng/ccu_mux.c +++ b/drivers/clk/sunxi-ng/ccu_mux.c @@ -79,41 +79,46 @@ static unsigned long ccu_mux_helper_unapply_prediv(struct ccu_common *common, int ccu_mux_helper_determine_rate(struct ccu_common *common, struct ccu_mux_internal *cm, struct clk_rate_request *req, - unsigned long (*round)(struct ccu_mux_internal *, - struct clk_hw *, - unsigned long *, - unsigned long, - void *), + int (*round)(struct ccu_mux_internal *, + struct clk_rate_request *, + void *), void *data) { unsigned long best_parent_rate = 0, best_rate = 0; struct clk_hw *best_parent, *hw = &common->hw; unsigned int i; + int ret; if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) { - unsigned long adj_parent_rate; + struct clk_rate_request adj_req = *req; best_parent = clk_hw_get_parent(hw); best_parent_rate = clk_hw_get_rate(best_parent); - adj_parent_rate = ccu_mux_helper_apply_prediv(common, cm, -1, - best_parent_rate); - best_rate = round(cm, best_parent, &adj_parent_rate, - req->rate, data); + adj_req.best_parent_hw = best_parent; + adj_req.best_parent_rate = ccu_mux_helper_apply_prediv(common, cm, -1, + best_parent_rate); + + ret = round(cm, &adj_req, data); + if (ret) + return ret; + + best_rate = adj_req.rate; /* - * adj_parent_rate might have been modified by our clock. + * best_parent_rate might have been modified by our clock. * Unapply the pre-divider if there's one, and give * the actual frequency the parent needs to run at. */ best_parent_rate = ccu_mux_helper_unapply_prediv(common, cm, -1, - adj_parent_rate); + adj_req.best_parent_rate); goto out; } for (i = 0; i < clk_hw_get_num_parents(hw); i++) { - unsigned long tmp_rate, parent_rate; + struct clk_rate_request tmp_req = *req; + unsigned long parent_rate; struct clk_hw *parent; parent = clk_hw_get_parent_by_index(hw, i); @@ -123,7 +128,12 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common, parent_rate = ccu_mux_helper_apply_prediv(common, cm, i, clk_hw_get_rate(parent)); - tmp_rate = round(cm, parent, &parent_rate, req->rate, data); + tmp_req.best_parent_hw = parent; + tmp_req.best_parent_rate = parent_rate; + + ret = round(cm, &tmp_req, data); + if (ret) + continue; /* * parent_rate might have been modified by our clock. @@ -131,16 +141,17 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common, * the actual frequency the parent needs to run at. */ parent_rate = ccu_mux_helper_unapply_prediv(common, cm, i, - parent_rate); - if (tmp_rate == req->rate) { + tmp_req.best_parent_rate); + + if (tmp_req.rate == req->rate) { best_parent = parent; best_parent_rate = parent_rate; - best_rate = tmp_rate; + best_rate = tmp_req.rate; goto out; } - if (ccu_is_better_rate(common, req->rate, tmp_rate, best_rate)) { - best_rate = tmp_rate; + if (ccu_is_better_rate(common, req->rate, tmp_req.rate, best_rate)) { + best_rate = tmp_req.rate; best_parent_rate = parent_rate; best_parent = parent; } diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h index eb1172ebbd94..c94a4bde5d01 100644 --- a/drivers/clk/sunxi-ng/ccu_mux.h +++ b/drivers/clk/sunxi-ng/ccu_mux.h @@ -137,11 +137,9 @@ unsigned long ccu_mux_helper_apply_prediv(struct ccu_common *common, int ccu_mux_helper_determine_rate(struct ccu_common *common, struct ccu_mux_internal *cm, struct clk_rate_request *req, - unsigned long (*round)(struct ccu_mux_internal *, - struct clk_hw *, - unsigned long *, - unsigned long, - void *), + int (*round)(struct ccu_mux_internal *, + struct clk_rate_request *, + void *), void *data); u8 ccu_mux_helper_get_parent(struct ccu_common *common, struct ccu_mux_internal *cm); diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c index 784eec9ac997..401fbb752479 100644 --- a/drivers/clk/sunxi-ng/ccu_nkm.c +++ b/drivers/clk/sunxi-ng/ccu_nkm.c @@ -162,11 +162,9 @@ static unsigned long ccu_nkm_recalc_rate(struct clk_hw *hw, return rate; } -static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux, - struct clk_hw *parent_hw, - unsigned long *parent_rate, - unsigned long rate, - void *data) +static int ccu_nkm_determine_rate_helper(struct ccu_mux_internal *mux, + struct clk_rate_request *req, + void *data) { struct ccu_nkm *nkm = data; struct _ccu_nkm _nkm; @@ -179,18 +177,21 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux, _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV) - rate *= nkm->fixed_post_div; + req->rate *= nkm->fixed_post_div; if (!clk_hw_can_set_rate_parent(&nkm->common.hw)) - rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm, &nkm->common); + req->rate = ccu_nkm_find_best(req->best_parent_rate, req->rate, + &_nkm, &nkm->common); else - rate = ccu_nkm_find_best_with_parent_adj(&nkm->common, parent_hw, parent_rate, rate, - &_nkm); + req->rate = ccu_nkm_find_best_with_parent_adj(&nkm->common, + req->best_parent_hw, + &req->best_parent_rate, + req->rate, &_nkm); if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV) - rate /= nkm->fixed_post_div; + req->rate /= nkm->fixed_post_div; - return rate; + return 0; } static int ccu_nkm_determine_rate(struct clk_hw *hw, @@ -199,7 +200,7 @@ static int ccu_nkm_determine_rate(struct clk_hw *hw, struct ccu_nkm *nkm = hw_to_ccu_nkm(hw); return ccu_mux_helper_determine_rate(&nkm->common, &nkm->mux, - req, ccu_nkm_round_rate, nkm); + req, ccu_nkm_determine_rate_helper, nkm); } static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate, From d0b7c5bf6c5520c35fecff34da83d390405d3eaf Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:22 -0500 Subject: [PATCH 12/29] clk: actions: owl-composite: convert from owl_divider_helper_round_rate() to divider_determine_rate() owl_divider_helper_round_rate() is just a wrapper for divider_round_rate(), which is deprecated. Let's migrate to divider_determine_rate() instead so that this deprecated API can be removed. Acked-by: Manivannan Sadhasivam Signed-off-by: Brian Masney --- drivers/clk/actions/owl-composite.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/clk/actions/owl-composite.c b/drivers/clk/actions/owl-composite.c index 00b74f8bc437..9540444307d6 100644 --- a/drivers/clk/actions/owl-composite.c +++ b/drivers/clk/actions/owl-composite.c @@ -57,15 +57,10 @@ static int owl_comp_div_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { struct owl_composite *comp = hw_to_owl_comp(hw); - long rate; + struct owl_divider_hw *div = &comp->rate.div_hw; - rate = owl_divider_helper_round_rate(&comp->common, &comp->rate.div_hw, - req->rate, &req->best_parent_rate); - if (rate < 0) - return rate; - - req->rate = rate; - return 0; + return divider_determine_rate(&comp->common.hw, req, div->table, + div->width, div->div_flags); } static unsigned long owl_comp_div_recalc_rate(struct clk_hw *hw, From 3ff3360440fa8cc7ef5a4da628d3b770b46a4f73 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:23 -0500 Subject: [PATCH 13/29] clk: actions: owl-divider: convert from divider_round_rate() to divider_determine_rate() The divider_round_rate() function is now deprecated, so let's migrate to divider_determine_rate() instead so that this deprecated API can be removed. Additionally, owl_divider_helper_round_rate() is no longer used, so let's drop that from the header file as well. Note that when the main function itself was migrated to use determine_rate, this was mistakenly converted to: req->rate = divider_round_rate(...) This is invalid in the case when an error occurs since it can set the rate to a negative value. Fixes: 1b04e12a8bcc ("clk: actions: owl-divider: convert from round_rate() to determine_rate()") Acked-by: Manivannan Sadhasivam Signed-off-by: Brian Masney --- drivers/clk/actions/owl-divider.c | 17 ++--------------- drivers/clk/actions/owl-divider.h | 5 ----- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/drivers/clk/actions/owl-divider.c b/drivers/clk/actions/owl-divider.c index 118f1393c678..316ace80e87e 100644 --- a/drivers/clk/actions/owl-divider.c +++ b/drivers/clk/actions/owl-divider.c @@ -13,26 +13,13 @@ #include "owl-divider.h" -long owl_divider_helper_round_rate(struct owl_clk_common *common, - const struct owl_divider_hw *div_hw, - unsigned long rate, - unsigned long *parent_rate) -{ - return divider_round_rate(&common->hw, rate, parent_rate, - div_hw->table, div_hw->width, - div_hw->div_flags); -} - static int owl_divider_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { struct owl_divider *div = hw_to_owl_divider(hw); - req->rate = owl_divider_helper_round_rate(&div->common, &div->div_hw, - req->rate, - &req->best_parent_rate); - - return 0; + return divider_determine_rate(hw, req, div->div_hw.table, + div->div_hw.width, div->div_hw.div_flags); } unsigned long owl_divider_helper_recalc_rate(struct owl_clk_common *common, diff --git a/drivers/clk/actions/owl-divider.h b/drivers/clk/actions/owl-divider.h index d76f58782c52..1d3bb4e5898a 100644 --- a/drivers/clk/actions/owl-divider.h +++ b/drivers/clk/actions/owl-divider.h @@ -56,11 +56,6 @@ static inline struct owl_divider *hw_to_owl_divider(struct clk_hw *hw) return container_of(common, struct owl_divider, common); } -long owl_divider_helper_round_rate(struct owl_clk_common *common, - const struct owl_divider_hw *div_hw, - unsigned long rate, - unsigned long *parent_rate); - unsigned long owl_divider_helper_recalc_rate(struct owl_clk_common *common, const struct owl_divider_hw *div_hw, unsigned long parent_rate); From 7468ac0ce262640e928c71a5da6f6b42a89d453e Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:24 -0500 Subject: [PATCH 14/29] clk: bm1880: convert from divider_ro_round_rate() to divider_ro_determine_rate() The divider_ro_round_rate() function is now deprecated, so let's migrate to divider_ro_determine_rate() instead so that this deprecated API can be removed. Note that when the main function itself was migrated to use determine_rate, this was mistakenly converted to: req->rate = divider_round_rate(...) This is invalid in the case when an error occurs since it can set the rate to a negative value. Fixes: cf1d95fa0c64 ("clk: bm1880: convert from divider_round_rate() to divider_determine_rate()") Acked-by: Manivannan Sadhasivam Signed-off-by: Brian Masney --- drivers/clk/clk-bm1880.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/clk/clk-bm1880.c b/drivers/clk/clk-bm1880.c index dac190bc6e19..536df8e828ea 100644 --- a/drivers/clk/clk-bm1880.c +++ b/drivers/clk/clk-bm1880.c @@ -621,12 +621,8 @@ static int bm1880_clk_div_determine_rate(struct clk_hw *hw, val = readl(reg_addr) >> div->shift; val &= clk_div_mask(div->width); - req->rate = divider_ro_round_rate(hw, req->rate, - &req->best_parent_rate, - div->table, - div->width, div->flags, val); - - return 0; + return divider_ro_determine_rate(hw, req, div->table, + div->width, div->flags, val); } req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, From 463b97bef0c9fb02b743d6b9f0d698cae81a1d9f Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:25 -0500 Subject: [PATCH 15/29] clk: bm1880: convert from divider_round_rate() to divider_determine_rate() The divider_round_rate() function is now deprecated, so let's migrate to divider_determine_rate() instead so that this deprecated API can be removed. Note that when the main function itself was migrated to use determine_rate, this was mistakenly converted to: req->rate = divider_round_rate(...) This is invalid in the case when an error occurs since it can set the rate to a negative value. Fixes: 64613d7fb42f ("clk: bm1880: convert from round_rate() to determine_rate()") Acked-by: Manivannan Sadhasivam Signed-off-by: Brian Masney --- drivers/clk/clk-bm1880.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/clk/clk-bm1880.c b/drivers/clk/clk-bm1880.c index 536df8e828ea..1bdceb36fa87 100644 --- a/drivers/clk/clk-bm1880.c +++ b/drivers/clk/clk-bm1880.c @@ -625,10 +625,7 @@ static int bm1880_clk_div_determine_rate(struct clk_hw *hw, div->width, div->flags, val); } - req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, - div->table, div->width, div->flags); - - return 0; + return divider_determine_rate(hw, req, div->table, div->width, div->flags); } static int bm1880_clk_div_set_rate(struct clk_hw *hw, unsigned long rate, From e3a5249c140a1ded55937ba04247d530a85f0edc Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:26 -0500 Subject: [PATCH 16/29] clk: hisilicon: clkdivider-hi6220: convert from divider_round_rate() to divider_determine_rate() The divider_round_rate() function is now deprecated, so let's migrate to divider_determine_rate() instead so that this deprecated API can be removed. Note that when the main function itself was migrated to use determine_rate, this was mistakenly converted to: req->rate = divider_round_rate(...) This is invalid in the case when an error occurs since it can set the rate to a negative value. Fixes: 619a6210f398 ("clk: hisilicon: clkdivider-hi6220: convert from round_rate() to determine_rate()") Signed-off-by: Brian Masney --- drivers/clk/hisilicon/clkdivider-hi6220.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c index 6bae18a84cb6..fd7ceb92d651 100644 --- a/drivers/clk/hisilicon/clkdivider-hi6220.c +++ b/drivers/clk/hisilicon/clkdivider-hi6220.c @@ -60,10 +60,8 @@ static int hi6220_clkdiv_determine_rate(struct clk_hw *hw, { struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw); - req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, dclk->table, - dclk->width, CLK_DIVIDER_ROUND_CLOSEST); - - return 0; + return divider_determine_rate(hw, req, dclk->table, dclk->width, + CLK_DIVIDER_ROUND_CLOSEST); } static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate, From 11d3c676e7e0f00e3398199f85e47a0e22369866 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:27 -0500 Subject: [PATCH 17/29] clk: loongson1: convert from divider_round_rate() to divider_determine_rate() The divider_round_rate() function is now deprecated, so let's migrate to divider_determine_rate() instead so that this deprecated API can be removed. Note that when the main function itself was migrated to use determine_rate, this was mistakenly converted to: req->rate = divider_round_rate(...) This is invalid in the case when an error occurs since it can set the rate to a negative value. Fixes: bb40a2ef4fc9 ("clk: loongson1: convert from round_rate() to determine_rate()") Reviewed-by: Keguang Zhang Tested-by: Keguang Zhang # on LS1B & LS1C Signed-off-by: Brian Masney --- drivers/clk/clk-loongson1.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/clk/clk-loongson1.c b/drivers/clk/clk-loongson1.c index f9f060d08a5f..1674181a1107 100644 --- a/drivers/clk/clk-loongson1.c +++ b/drivers/clk/clk-loongson1.c @@ -99,10 +99,7 @@ static int ls1x_divider_determine_rate(struct clk_hw *hw, struct ls1x_clk *ls1x_clk = to_ls1x_clk(hw); const struct ls1x_clk_div_data *d = ls1x_clk->data; - req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, - d->table, d->width, d->flags); - - return 0; + return divider_determine_rate(hw, req, d->table, d->width, d->flags); } static int ls1x_divider_set_rate(struct clk_hw *hw, unsigned long rate, From fc5d7e7ee681238035466ce60a6892ee8f637e9d Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:28 -0500 Subject: [PATCH 18/29] clk: milbeaut: convert from divider_ro_round_rate() to divider_ro_determine_rate() The divider_ro_round_rate() function is now deprecated, so let's migrate to divider_ro_determine_rate() instead so that this deprecated API can be removed. Note that when the main function itself was migrated to use determine_rate, this was mistakenly converted to: req->rate = divider_round_rate(...) This is invalid in the case when an error occurs since it can set the rate to a negative value. Fixes: fe67c682f91c ("clk: milbeaut: convert from divider_round_rate() to divider_determine_rate()") Signed-off-by: Brian Masney --- drivers/clk/clk-milbeaut.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/clk/clk-milbeaut.c b/drivers/clk/clk-milbeaut.c index b4f9b7143eaa..4e3790b7fc90 100644 --- a/drivers/clk/clk-milbeaut.c +++ b/drivers/clk/clk-milbeaut.c @@ -398,13 +398,9 @@ static int m10v_clk_divider_determine_rate(struct clk_hw *hw, val = readl(divider->reg) >> divider->shift; val &= clk_div_mask(divider->width); - req->rate = divider_ro_round_rate(hw, req->rate, - &req->best_parent_rate, - divider->table, - divider->width, - divider->flags, val); - - return 0; + return divider_ro_determine_rate(hw, req, divider->table, + divider->width, divider->flags, + val); } req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, From 865e63b038c446d38593ddbcc362ebb62e6ff007 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:29 -0500 Subject: [PATCH 19/29] clk: milbeaut: convert from divider_round_rate() to divider_determine_rate() The divider_round_rate() function is now deprecated, so let's migrate to divider_determine_rate() instead so that this deprecated API can be removed. Note that when the main function itself was migrated to use determine_rate, this was mistakenly converted to: req->rate = divider_round_rate(...) This is invalid in the case when an error occurs since it can set the rate to a negative value. Fixes: 7b45988fcf78 ("clk: milbeaut: convert from round_rate() to determine_rate()") Signed-off-by: Brian Masney --- drivers/clk/clk-milbeaut.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/clk/clk-milbeaut.c b/drivers/clk/clk-milbeaut.c index 4e3790b7fc90..45389db652e0 100644 --- a/drivers/clk/clk-milbeaut.c +++ b/drivers/clk/clk-milbeaut.c @@ -403,10 +403,7 @@ static int m10v_clk_divider_determine_rate(struct clk_hw *hw, val); } - req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, - divider->table, divider->width, divider->flags); - - return 0; + return divider_determine_rate(hw, req, divider->table, divider->width, divider->flags); } static int m10v_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, From 9329d784ca9aad03b12508128797d40fd1f2e0c1 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:30 -0500 Subject: [PATCH 20/29] clk: nuvoton: ma35d1-divider: convert from divider_round_rate() to divider_determine_rate() The divider_round_rate() function is now deprecated, so let's migrate to divider_determine_rate() instead so that this deprecated API can be removed. Note that when the main function itself was migrated to use determine_rate, this was mistakenly converted to: req->rate = divider_round_rate(...) This is invalid in the case when an error occurs since it can set the rate to a negative value. Fixes: 215f8aa095a1 ("clk: nuvoton: ma35d1-divider: convert from round_rate() to determine_rate()") Signed-off-by: Brian Masney --- drivers/clk/nuvoton/clk-ma35d1-divider.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/clk/nuvoton/clk-ma35d1-divider.c b/drivers/clk/nuvoton/clk-ma35d1-divider.c index e39f53d5bf45..e992e7c30341 100644 --- a/drivers/clk/nuvoton/clk-ma35d1-divider.c +++ b/drivers/clk/nuvoton/clk-ma35d1-divider.c @@ -44,11 +44,8 @@ static int ma35d1_clkdiv_determine_rate(struct clk_hw *hw, { struct ma35d1_adc_clk_div *dclk = to_ma35d1_adc_clk_div(hw); - req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, - dclk->table, dclk->width, - CLK_DIVIDER_ROUND_CLOSEST); - - return 0; + return divider_determine_rate(hw, req, dclk->table, dclk->width, + CLK_DIVIDER_ROUND_CLOSEST); } static int ma35d1_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) From af943663ccc266e6346e5645b13c0fca71d24395 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:31 -0500 Subject: [PATCH 21/29] clk: nxp: lpc32xx: convert from divider_round_rate() to divider_determine_rate() The divider_round_rate() function is now deprecated, so let's migrate to divider_determine_rate() instead so that this deprecated API can be removed. Note that when the main function itself was migrated to use determine_rate, this was mistakenly converted to: req->rate = divider_round_rate(...) This is invalid in the case when an error occurs since it can set the rate to a negative value. Fixes: 0879768df240 ("clk: nxp: lpc32xx: convert from round_rate() to determine_rate()") Tested-by: Vladimir Zapolskiy Reviewed-by: Vladimir Zapolskiy Signed-off-by: Brian Masney --- drivers/clk/nxp/clk-lpc32xx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c index 23f980cf6a2b..ae2fa5341a2e 100644 --- a/drivers/clk/nxp/clk-lpc32xx.c +++ b/drivers/clk/nxp/clk-lpc32xx.c @@ -975,10 +975,8 @@ static int clk_divider_determine_rate(struct clk_hw *hw, return 0; } - req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, - divider->table, divider->width, divider->flags); - - return 0; + return divider_determine_rate(hw, req, divider->table, divider->width, + divider->flags); } static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, From 77b04dc19693510ce8ed1c6eda5f5b833e208816 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:35 -0500 Subject: [PATCH 22/29] clk: sophgo: sg2042-clkgen: convert from divider_round_rate() to divider_determine_rate() The divider_round_rate() function is now deprecated, so let's migrate to divider_determine_rate() instead so that this deprecated API can be removed. Note that when the main function itself was migrated to use determine_rate, this was mistakenly converted to: req->rate = divider_round_rate(...) This is invalid in the case when an error occurs since it can set the rate to a negative value. Note that this commit also removes a debugging message that's not really needed. Fixes: 9a3b6993613d ("clk: sophgo: sg2042-clkgen: convert from round_rate() to determine_rate()") Tested-by: Chen Wang Reviewed-by: Chen Wang Signed-off-by: Brian Masney --- drivers/clk/sophgo/clk-sg2042-clkgen.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/clk/sophgo/clk-sg2042-clkgen.c b/drivers/clk/sophgo/clk-sg2042-clkgen.c index 683661b71787..9725ac4e050a 100644 --- a/drivers/clk/sophgo/clk-sg2042-clkgen.c +++ b/drivers/clk/sophgo/clk-sg2042-clkgen.c @@ -180,7 +180,6 @@ static int sg2042_clk_divider_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw); - unsigned long ret_rate; u32 bestdiv; /* if read only, just return current value */ @@ -191,17 +190,13 @@ static int sg2042_clk_divider_determine_rate(struct clk_hw *hw, bestdiv = readl(divider->reg) >> divider->shift; bestdiv &= clk_div_mask(divider->width); } - ret_rate = DIV_ROUND_UP_ULL((u64)req->best_parent_rate, bestdiv); - } else { - ret_rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, NULL, - divider->width, divider->div_flags); + req->rate = DIV_ROUND_UP_ULL((u64)req->best_parent_rate, bestdiv); + + return 0; } - pr_debug("--> %s: divider_round_rate: val = %ld\n", - clk_hw_get_name(hw), ret_rate); - req->rate = ret_rate; - - return 0; + return divider_determine_rate(hw, req, NULL, divider->width, + divider->div_flags); } static int sg2042_clk_divider_set_rate(struct clk_hw *hw, From f78fb9422980ceeb340fa3a2e370ae8845798ec7 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:36 -0500 Subject: [PATCH 23/29] clk: sprd: div: convert from divider_round_rate() to divider_determine_rate() The divider_round_rate() function is now deprecated, so let's migrate to divider_determine_rate() instead so that this deprecated API can be removed. Note that when the main function itself was migrated to use determine_rate, this was mistakenly converted to: req->rate = divider_round_rate(...) This is invalid in the case when an error occurs since it can set the rate to a negative value. Fixes: deb4740a5ff8 ("clk: sprd: div: convert from round_rate() to determine_rate()") Signed-off-by: Brian Masney --- drivers/clk/sprd/div.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/clk/sprd/div.c b/drivers/clk/sprd/div.c index 013423881968..cd57163a7204 100644 --- a/drivers/clk/sprd/div.c +++ b/drivers/clk/sprd/div.c @@ -14,11 +14,7 @@ static int sprd_div_determine_rate(struct clk_hw *hw, { struct sprd_div *cd = hw_to_sprd_div(hw); - req->rate = divider_round_rate(&cd->common.hw, req->rate, - &req->best_parent_rate, - NULL, cd->div.width, 0); - - return 0; + return divider_determine_rate(&cd->common.hw, req, NULL, cd->div.width, 0); } unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common, From 6587c9dacc89ad7014bf601fe851955429f13230 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:37 -0500 Subject: [PATCH 24/29] clk: stm32: stm32-core: convert from divider_ro_round_rate() to divider_ro_determine_rate() The divider_ro_round_rate() function is now deprecated, so let's migrate to divider_ro_determine_rate() instead so that this deprecated API can be removed. Note that when the main function itself was migrated to use determine_rate, this was mistakenly converted to: req->rate = divider_round_rate(...) This is invalid in the case when an error occurs since it can set the rate to a negative value. Fixes: cd1cb38836c0 ("clk: stm32: stm32-core: convert from round_rate() to determine_rate()") Signed-off-by: Brian Masney --- drivers/clk/stm32/clk-stm32-core.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/clk/stm32/clk-stm32-core.c b/drivers/clk/stm32/clk-stm32-core.c index 72825b9c36a4..b95b9c591fda 100644 --- a/drivers/clk/stm32/clk-stm32-core.c +++ b/drivers/clk/stm32/clk-stm32-core.c @@ -369,13 +369,10 @@ static int clk_stm32_divider_determine_rate(struct clk_hw *hw, val = readl(div->base + divider->offset) >> divider->shift; val &= clk_div_mask(divider->width); - req->rate = divider_ro_round_rate(hw, req->rate, - &req->best_parent_rate, - divider->table, - divider->width, - divider->flags, val); - - return 0; + return divider_ro_determine_rate(hw, req, + divider->table, + divider->width, + divider->flags, val); } req->rate = divider_round_rate_parent(hw, clk_hw_get_parent(hw), @@ -455,14 +452,9 @@ static int clk_stm32_composite_determine_rate(struct clk_hw *hw, val = readl(composite->base + divider->offset) >> divider->shift; val &= clk_div_mask(divider->width); - rate = divider_ro_round_rate(hw, req->rate, &req->best_parent_rate, - divider->table, divider->width, divider->flags, - val); - if (rate < 0) - return rate; - - req->rate = rate; - return 0; + return divider_ro_determine_rate(hw, req, divider->table, + divider->width, divider->flags, + val); } rate = divider_round_rate_parent(hw, clk_hw_get_parent(hw), From 2532795a6d6bb9791d713ffa9d9433f293b45b14 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:38 -0500 Subject: [PATCH 25/29] clk: stm32: stm32-core: convert from divider_round_rate_parent() to divider_determine_rate() The divider_round_rate_parent() function is now deprecated, so let's migrate to divider_determine_rate() instead so that this deprecated API can be removed. Note that when the main function itself was migrated to use determine_rate, this was mistakenly converted to: req->rate = divider_round_rate(...) This is invalid in the case when an error occurs since it can set the rate to a negative value. Fixes: cd1cb38836c0 ("clk: stm32: stm32-core: convert from round_rate() to determine_rate()") Signed-off-by: Brian Masney --- drivers/clk/stm32/clk-stm32-core.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/clk/stm32/clk-stm32-core.c b/drivers/clk/stm32/clk-stm32-core.c index b95b9c591fda..e921c25a929c 100644 --- a/drivers/clk/stm32/clk-stm32-core.c +++ b/drivers/clk/stm32/clk-stm32-core.c @@ -375,13 +375,8 @@ static int clk_stm32_divider_determine_rate(struct clk_hw *hw, divider->flags, val); } - req->rate = divider_round_rate_parent(hw, clk_hw_get_parent(hw), - req->rate, - &req->best_parent_rate, - divider->table, - divider->width, divider->flags); - - return 0; + return divider_determine_rate(hw, req, divider->table, divider->width, + divider->flags); } static unsigned long clk_stm32_divider_recalc_rate(struct clk_hw *hw, @@ -438,7 +433,6 @@ static int clk_stm32_composite_determine_rate(struct clk_hw *hw, { struct clk_stm32_composite *composite = to_clk_stm32_composite(hw); const struct stm32_div_cfg *divider; - long rate; if (composite->div_id == NO_STM32_DIV) return 0; @@ -457,14 +451,8 @@ static int clk_stm32_composite_determine_rate(struct clk_hw *hw, val); } - rate = divider_round_rate_parent(hw, clk_hw_get_parent(hw), - req->rate, &req->best_parent_rate, - divider->table, divider->width, divider->flags); - if (rate < 0) - return rate; - - req->rate = rate; - return 0; + return divider_determine_rate(hw, req, divider->table, divider->width, + divider->flags); } static u8 clk_stm32_composite_get_parent(struct clk_hw *hw) From 56c1cfb488cc17944c200edad96191a70a3783ba Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:39 -0500 Subject: [PATCH 26/29] clk: versaclock3: convert from divider_round_rate() to divider_determine_rate() The divider_round_rate() function is now deprecated, so let's migrate to divider_determine_rate() instead so that this deprecated API can be removed. Note that when the main function itself was migrated to use determine_rate, this was mistakenly converted to: req->rate = divider_round_rate(...) This is invalid in the case when an error occurs since it can set the rate to a negative value. Fixes: 9e3372b2ebac ("clk: versaclock3: convert from round_rate() to determine_rate()") Signed-off-by: Brian Masney --- drivers/clk/clk-versaclock3.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/clk/clk-versaclock3.c b/drivers/clk/clk-versaclock3.c index 1849863dbd67..27b6cf70f3ae 100644 --- a/drivers/clk/clk-versaclock3.c +++ b/drivers/clk/clk-versaclock3.c @@ -523,11 +523,8 @@ static int vc3_div_determine_rate(struct clk_hw *hw, return 0; } - req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, - div_data->table, - div_data->width, div_data->flags); - - return 0; + return divider_determine_rate(hw, req, div_data->table, div_data->width, + div_data->flags); } static int vc3_div_set_rate(struct clk_hw *hw, unsigned long rate, From bb1b0e63dbbd7150324cb4d6aef7854dbe26a617 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:40 -0500 Subject: [PATCH 27/29] clk: x86: cgu: convert from divider_round_rate() to divider_determine_rate() The divider_round_rate() function is now deprecated, so let's migrate to divider_determine_rate() instead so that this deprecated API can be removed. Note that when the main function itself was migrated to use determine_rate, this was mistakenly converted to: req->rate = divider_round_rate(...) This is invalid in the case when an error occurs since it can set the rate to a negative value. Fixes: f7a6bed91a19 ("clk: x86: cgu: convert from round_rate() to determine_rate()") Signed-off-by: Brian Masney --- drivers/clk/x86/clk-cgu.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/clk/x86/clk-cgu.c b/drivers/clk/x86/clk-cgu.c index d099667355f8..92ee05d75af2 100644 --- a/drivers/clk/x86/clk-cgu.c +++ b/drivers/clk/x86/clk-cgu.c @@ -137,10 +137,8 @@ static int lgm_clk_divider_determine_rate(struct clk_hw *hw, { struct lgm_clk_divider *divider = to_lgm_clk_divider(hw); - req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, divider->table, - divider->width, divider->flags); - - return 0; + return divider_determine_rate(hw, req, divider->table, divider->width, + divider->flags); } static int From 30a807808c69a1907001ffb79289237a2ee97cfa Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Jan 2026 16:16:41 -0500 Subject: [PATCH 28/29] clk: zynqmp: divider: convert from divider_round_rate() to divider_determine_rate() The divider_round_rate() function is now deprecated, so let's migrate to divider_determine_rate() instead so that this deprecated API can be removed. Note that when the main function itself was migrated to use determine_rate, this was mistakenly converted to: req->rate = divider_round_rate(...) This is invalid in the case when an error occurs since it can set the rate to a negative value. Fixes: 0f9cf96a01fd ("clk: zynqmp: divider: convert from round_rate() to determine_rate()") Signed-off-by: Brian Masney --- drivers/clk/zynqmp/divider.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c index c824eeacd8eb..de6f478d527d 100644 --- a/drivers/clk/zynqmp/divider.c +++ b/drivers/clk/zynqmp/divider.c @@ -151,8 +151,9 @@ static int zynqmp_clk_divider_determine_rate(struct clk_hw *hw, width = fls(divider->max_div); - req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, - NULL, width, divider->flags); + ret = divider_determine_rate(hw, req, NULL, width, divider->flags); + if (ret != 0) + return ret; if (divider->is_frac && (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) && (req->rate % req->best_parent_rate)) From ed806240b8975f951c88ccb4bb75813f5fb949df Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 22 Jan 2026 07:47:16 -0500 Subject: [PATCH 29/29] rtc: ac100: convert from divider_round_rate() to divider_determine_rate() The divider_round_rate() function is now deprecated, so let's migrate to divider_determine_rate() instead so that this deprecated API can be removed. Acked-by: Alexandre Belloni Signed-off-by: Brian Masney --- drivers/rtc/rtc-ac100.c | 73 +++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/drivers/rtc/rtc-ac100.c b/drivers/rtc/rtc-ac100.c index 33626311fa78..bba7115ff3ad 100644 --- a/drivers/rtc/rtc-ac100.c +++ b/drivers/rtc/rtc-ac100.c @@ -140,42 +140,16 @@ static unsigned long ac100_clkout_recalc_rate(struct clk_hw *hw, AC100_CLKOUT_DIV_WIDTH); } -static long ac100_clkout_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long prate) -{ - unsigned long best_rate = 0, tmp_rate, tmp_prate; - int i; - - if (prate == AC100_RTC_32K_RATE) - return divider_round_rate(hw, rate, &prate, NULL, - AC100_CLKOUT_DIV_WIDTH, - CLK_DIVIDER_POWER_OF_TWO); - - for (i = 0; ac100_clkout_prediv[i].div; i++) { - tmp_prate = DIV_ROUND_UP(prate, ac100_clkout_prediv[i].val); - tmp_rate = divider_round_rate(hw, rate, &tmp_prate, NULL, - AC100_CLKOUT_DIV_WIDTH, - CLK_DIVIDER_POWER_OF_TWO); - - if (tmp_rate > rate) - continue; - if (rate - tmp_rate < best_rate - tmp_rate) - best_rate = tmp_rate; - } - - return best_rate; -} - static int ac100_clkout_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { - struct clk_hw *best_parent; + int i, ret, num_parents = clk_hw_get_num_parents(hw); + struct clk_hw *best_parent = NULL; unsigned long best = 0; - int i, num_parents = clk_hw_get_num_parents(hw); for (i = 0; i < num_parents; i++) { struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i); - unsigned long tmp, prate; + unsigned long prate; /* * The clock has two parents, one is a fixed clock which is @@ -199,13 +173,40 @@ static int ac100_clkout_determine_rate(struct clk_hw *hw, prate = clk_hw_get_rate(parent); - tmp = ac100_clkout_round_rate(hw, req->rate, prate); + if (prate == AC100_RTC_32K_RATE) { + struct clk_rate_request div_req = *req; - if (tmp > req->rate) - continue; - if (req->rate - tmp < req->rate - best) { - best = tmp; - best_parent = parent; + div_req.best_parent_rate = prate; + + ret = divider_determine_rate(hw, &div_req, NULL, + AC100_CLKOUT_DIV_WIDTH, + CLK_DIVIDER_POWER_OF_TWO); + if (ret != 0 || div_req.rate > req->rate) { + continue; + } else if (req->rate - div_req.rate < req->rate - best) { + best = div_req.rate; + best_parent = parent; + } + } else { + int j; + + for (j = 0; ac100_clkout_prediv[j].div; j++) { + struct clk_rate_request div_req = *req; + unsigned long tmp_prate; + + tmp_prate = DIV_ROUND_UP(prate, ac100_clkout_prediv[j].div); + div_req.best_parent_rate = tmp_prate; + + ret = divider_determine_rate(hw, &div_req, NULL, + AC100_CLKOUT_DIV_WIDTH, + CLK_DIVIDER_POWER_OF_TWO); + if (ret != 0 || div_req.rate > req->rate) { + continue; + } else if (req->rate - div_req.rate < req->rate - best) { + best = div_req.rate; + best_parent = parent; + } + } } } @@ -213,7 +214,7 @@ static int ac100_clkout_determine_rate(struct clk_hw *hw, return -EINVAL; req->best_parent_hw = best_parent; - req->best_parent_rate = best; + req->best_parent_rate = clk_hw_get_rate(best_parent); req->rate = best; return 0;