[PATCH 2/2] clk: meson: regmap: use the current divisor for read-only clocks

From: Carlo Caione

Date: Mon Oct 26 2026 - 09:36:46 EST


None of the Meson clocks using clk_regmap_divider_ro_ops set
CLK_DIVIDER_READ_ONLY. Without that flag, the shared rounding callback
can choose a new divisor even though these ops cannot program it. The
clock core may then adjust child clocks using the wrong parent rate.

Make the read-only ops always round using the current hardware divisor.
Parent rate changes remain allowed with CLK_SET_RATE_PARENT.

Signed-off-by: Carlo Caione <ccaione@xxxxxxxxxxxx>
---
drivers/clk/meson/clk-regmap.c | 34 +++++++++++++++++++++-------------
1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/drivers/clk/meson/clk-regmap.c b/drivers/clk/meson/clk-regmap.c
index 1ed56fe63cae..002e16865109 100644
--- a/drivers/clk/meson/clk-regmap.c
+++ b/drivers/clk/meson/clk-regmap.c
@@ -120,26 +120,34 @@ static unsigned long clk_regmap_div_recalc_rate(struct clk_hw *hw,
div->width);
}

-static int clk_regmap_div_determine_rate(struct clk_hw *hw,
- struct clk_rate_request *req)
+static int clk_regmap_div_ro_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
unsigned int val;
int ret;

- /* if read only, just return current value */
- if (div->flags & CLK_DIVIDER_READ_ONLY) {
- ret = regmap_read(clk->map, div->offset, &val);
- if (ret)
- return ret;
+ ret = regmap_read(clk->map, div->offset, &val);
+ if (ret)
+ return ret;

- val >>= div->shift;
- val &= clk_div_mask(div->width);
+ val >>= div->shift;
+ val &= clk_div_mask(div->width);

- return divider_ro_determine_rate(hw, req, div->table,
- div->width, div->flags, val);
- }
+ return divider_ro_determine_rate(hw, req, div->table, div->width,
+ div->flags, val);
+}
+
+static int clk_regmap_div_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_regmap *clk = to_clk_regmap(hw);
+ struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
+
+ /* if read only, just return current value */
+ if (div->flags & CLK_DIVIDER_READ_ONLY)
+ return clk_regmap_div_ro_determine_rate(hw, req);

return divider_determine_rate(hw, req, div->table, div->width,
div->flags);
@@ -176,7 +184,7 @@ EXPORT_SYMBOL_NS_GPL(clk_regmap_divider_ops, "CLK_MESON");
const struct clk_ops clk_regmap_divider_ro_ops = {
.init = clk_regmap_init,
.recalc_rate = clk_regmap_div_recalc_rate,
- .determine_rate = clk_regmap_div_determine_rate,
+ .determine_rate = clk_regmap_div_ro_determine_rate,
};
EXPORT_SYMBOL_NS_GPL(clk_regmap_divider_ro_ops, "CLK_MESON");


--
2.56.0