diff options
author | Finley Xiao <finley.xiao@rock-chips.com> | 2018-03-28 15:12:24 +0800 |
---|---|---|
committer | Tao Huang <huangtao@rock-chips.com> | 2018-04-02 17:01:54 +0800 |
commit | 4186a0e4239b087c163acdbdd03e7411001966f2 (patch) | |
tree | 293123584694eedee1ea8a4e23aa1b6f95122c46 /drivers/clk/rockchip/clk.c | |
parent | ec9e751d33630b4e3c81b5f46c784bae011d1837 (diff) |
clk: rockchip: Add supprot to limit input rate for fractional divider
From Rockchips fractional divider usage, some clocks can be generated
by fractional divider, but the input clock frequency of fractional
divider should be less than a specified value.
Change-Id: Ifd6c5f6a24a64021f990506e8657cd925f9b96f9
Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
Diffstat (limited to 'drivers/clk/rockchip/clk.c')
-rw-r--r-- | drivers/clk/rockchip/clk.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 7cb2f3e09269..3379990ef637 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -175,15 +175,24 @@ void rockchip_fractional_approximation(struct clk_hw *hw, unsigned long p_rate, p_parent_rate; struct clk_hw *p_parent; unsigned long scale; + u32 div; p_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); - if ((rate * 20 > p_rate) && (p_rate % rate != 0)) { + if (((rate * 20 > p_rate) && (p_rate % rate != 0)) || + (fd->max_prate && fd->max_prate < p_rate)) { p_parent = clk_hw_get_parent(clk_hw_get_parent(hw)); p_parent_rate = clk_hw_get_rate(p_parent); *parent_rate = p_parent_rate; + if (fd->max_prate && p_parent_rate > fd->max_prate) { + div = DIV_ROUND_UP(p_parent_rate, fd->max_prate); + *parent_rate = p_parent_rate / div; + } + if (*parent_rate < rate * 20) { pr_err("%s parent_rate(%ld) is low than rate(%ld)*20, fractional div is not allowed\n", clk_hw_get_name(hw), *parent_rate, rate); + *m = 0; + *n = 1; return; } } @@ -209,7 +218,7 @@ static struct clk *rockchip_clk_register_frac_branch( void __iomem *base, int muxdiv_offset, u8 div_flags, int gate_offset, u8 gate_shift, u8 gate_flags, unsigned long flags, struct rockchip_clk_branch *child, - spinlock_t *lock) + unsigned long max_prate, spinlock_t *lock) { struct rockchip_clk_frac *frac; struct clk *clk; @@ -250,6 +259,7 @@ static struct clk *rockchip_clk_register_frac_branch( div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift; div->lock = lock; div->approximation = rockchip_fractional_approximation; + div->max_prate = max_prate; div_ops = &clk_fractional_divider_ops; clk = clk_register_composite(NULL, name, parent_names, num_parents, @@ -497,7 +507,7 @@ void __init rockchip_clk_register_branches( ctx->reg_base, list->muxdiv_offset, list->div_flags, list->gate_offset, list->gate_shift, list->gate_flags, flags, list->child, - &ctx->lock); + list->max_prate, &ctx->lock); break; case branch_gate: flags |= CLK_SET_RATE_PARENT; |