diff options
Diffstat (limited to 'drivers/clk/clk-divider.c')
-rw-r--r-- | drivers/clk/clk-divider.c | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 3c98d2650fa3..b6234a5da12d 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -342,19 +342,43 @@ long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, } EXPORT_SYMBOL_GPL(divider_round_rate_parent); +long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, + unsigned long rate, unsigned long *prate, + const struct clk_div_table *table, u8 width, + unsigned long flags, unsigned int val) +{ + int div; + + div = _get_div(table, val, flags, width); + + /* Even a read-only clock can propagate a rate change */ + if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { + if (!parent) + return -EINVAL; + + *prate = clk_hw_round_rate(parent, rate * div); + } + + return DIV_ROUND_UP_ULL((u64)*prate, div); +} +EXPORT_SYMBOL_GPL(divider_ro_round_rate_parent); + + static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { struct clk_divider *divider = to_clk_divider(hw); - int bestdiv; /* if read only, just return current value */ if (divider->flags & CLK_DIVIDER_READ_ONLY) { - bestdiv = clk_readl(divider->reg) >> divider->shift; - bestdiv &= clk_div_mask(divider->width); - bestdiv = _get_div(divider->table, bestdiv, divider->flags, - divider->width); - return DIV_ROUND_UP_ULL((u64)*prate, bestdiv); + u32 val; + + val = clk_readl(divider->reg) >> divider->shift; + val &= clk_div_mask(divider->width); + + return divider_ro_round_rate(hw, rate, prate, divider->table, + divider->width, divider->flags, + val); } return divider_round_rate(hw, rate, prate, divider->table, |