[PATCH v2 04/12] clk: qcom: clk-regmap-divider: Support CLK_DIVIDER_* flags
From: Luo Jie
Date: Fri Aug 07 2026 - 02:56:44 EST
Add a flags field to struct clk_regmap_div and OR it into the
CLK_DIVIDER_ROUND_CLOSEST flag passed to divider_determine_rate(),
divider_ro_determine_rate(), divider_get_val(), and
divider_recalc_rate(), so that qcom drivers can opt into
CLK_DIVIDER_* behavior variants such as
CLK_DIVIDER_EVEN_INTEGERS_NO_OFFSET.
This is additive and backward compatible: existing clk_regmap_div
users don't initialize .flags, so it defaults to 0, and
CLK_DIVIDER_ROUND_CLOSEST | 0 is identical to current behavior.
divider_get_val() can now return -EINVAL once a caller sets a
divisor-constraining flag such as CLK_DIVIDER_EVEN_INTEGERS_NO_OFFSET
(previously unreachable, since no flag passed here constrained
_is_valid_div()). Check for this in div_set_rate() before using the
result, mirroring clk_divider_set_rate()'s existing handling of the
same return value.
Signed-off-by: Luo Jie <jie.luo@xxxxxxxxxxxxxxxx>
---
drivers/clk/qcom/clk-regmap-divider.c | 14 +++++++++-----
drivers/clk/qcom/clk-regmap-divider.h | 1 +
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/clk/qcom/clk-regmap-divider.c b/drivers/clk/qcom/clk-regmap-divider.c
index 672e82caf205..fe4542b5bd58 100644
--- a/drivers/clk/qcom/clk-regmap-divider.c
+++ b/drivers/clk/qcom/clk-regmap-divider.c
@@ -27,7 +27,8 @@ static int div_ro_determine_rate(struct clk_hw *hw,
val &= BIT(divider->width) - 1;
return divider_ro_determine_rate(hw, req, NULL, divider->width,
- CLK_DIVIDER_ROUND_CLOSEST, val);
+ CLK_DIVIDER_ROUND_CLOSEST | divider->flags,
+ val);
}
static int div_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
@@ -35,7 +36,7 @@ static int div_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
struct clk_regmap_div *divider = to_clk_regmap_div(hw);
return divider_determine_rate(hw, req, NULL, divider->width,
- CLK_DIVIDER_ROUND_CLOSEST);
+ CLK_DIVIDER_ROUND_CLOSEST | divider->flags);
}
static int div_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -43,10 +44,12 @@ static int div_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct clk_regmap_div *divider = to_clk_regmap_div(hw);
struct clk_regmap *clkr = ÷r->clkr;
- u32 div;
+ int div;
div = divider_get_val(rate, parent_rate, NULL, divider->width,
- CLK_DIVIDER_ROUND_CLOSEST);
+ CLK_DIVIDER_ROUND_CLOSEST | divider->flags);
+ if (div < 0)
+ return div;
return regmap_update_bits(clkr->regmap, divider->reg,
(BIT(divider->width) - 1) << divider->shift,
@@ -65,7 +68,8 @@ static unsigned long div_recalc_rate(struct clk_hw *hw,
div &= BIT(divider->width) - 1;
return divider_recalc_rate(hw, parent_rate, div, NULL,
- CLK_DIVIDER_ROUND_CLOSEST, divider->width);
+ CLK_DIVIDER_ROUND_CLOSEST | divider->flags,
+ divider->width);
}
const struct clk_ops clk_regmap_div_ops = {
diff --git a/drivers/clk/qcom/clk-regmap-divider.h b/drivers/clk/qcom/clk-regmap-divider.h
index e75a65c3839c..4fde766b2633 100644
--- a/drivers/clk/qcom/clk-regmap-divider.h
+++ b/drivers/clk/qcom/clk-regmap-divider.h
@@ -13,6 +13,7 @@ struct clk_regmap_div {
u32 reg;
u32 shift;
u32 width;
+ unsigned long flags;
struct clk_regmap clkr;
};
--
2.43.0