mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
clk/rockchip/regmap: divider: Make round to closest divider valid
Change-Id: I6cff98ec7573f6774700bbbd2650b6e3a01b66f0 Signed-off-by: Wyon Bi <bivvy.bi@rock-chips.com>
This commit is contained in:
@@ -47,6 +47,20 @@ clk_regmap_divider_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
CLK_DIVIDER_ROUND_CLOSEST);
|
||||
}
|
||||
|
||||
static int div_round_closest(unsigned long parent_rate, unsigned long rate)
|
||||
{
|
||||
int up, down;
|
||||
unsigned long up_rate, down_rate;
|
||||
|
||||
up = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
|
||||
down = parent_rate / rate;
|
||||
|
||||
up_rate = DIV_ROUND_UP_ULL((u64)parent_rate, up);
|
||||
down_rate = DIV_ROUND_UP_ULL((u64)parent_rate, down);
|
||||
|
||||
return (rate - up_rate) <= (down_rate - rate) ? up : down;
|
||||
}
|
||||
|
||||
static int
|
||||
clk_regmap_divider_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
@@ -54,14 +68,13 @@ clk_regmap_divider_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
struct clk_regmap_divider *divider = to_clk_regmap_divider(hw);
|
||||
u32 val, div;
|
||||
|
||||
div = divider_get_val(rate, parent_rate, NULL, divider->width,
|
||||
CLK_DIVIDER_ROUND_CLOSEST);
|
||||
div = div_round_closest(parent_rate, rate);
|
||||
|
||||
dev_dbg(divider->dev, "%s: parent_rate=%ld, div=%d, rate=%ld\n",
|
||||
clk_hw_get_name(hw), parent_rate, div, rate);
|
||||
|
||||
val = div_mask(divider->width) << (divider->shift + 16);
|
||||
val |= div << divider->shift;
|
||||
val |= (div - 1) << divider->shift;
|
||||
|
||||
return regmap_write(divider->regmap, divider->reg, val);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user