[PATCH v3 03/12] clk: qcom: clk-regmap-divider: Support CLK_DIVIDER_* flags
Luo Jie <[email protected]>
| Newsgroups | org.kernel.vger.linux-clk,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
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_ONE_BASED. 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. Signed-off-by: Luo Jie <[email protected]> --- drivers/clk/qcom/clk-regmap-divider.c | 16 ++++++++++------ drivers/clk/qcom/clk-regmap-divider.h | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/clk/qcom/clk-regmap-divider.c b/drivers/clk/qcom/clk-regmap-divider.c index 672e82caf205..6e12aebf14b6 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,14 +44,16 @@ 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, - div << divider->shift); + (u32)div << divider->shift); } static unsigned long div_recalc_rate(struct clk_hw *hw, @@ -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