summaryrefslogtreecommitdiff
path: root/drivers/clk/rockchip/clk.c
diff options
context:
space:
mode:
authorFinley Xiao <finley.xiao@rock-chips.com>2018-03-28 15:12:24 +0800
committerTao Huang <huangtao@rock-chips.com>2018-04-02 17:01:54 +0800
commit4186a0e4239b087c163acdbdd03e7411001966f2 (patch)
tree293123584694eedee1ea8a4e23aa1b6f95122c46 /drivers/clk/rockchip/clk.c
parentec9e751d33630b4e3c81b5f46c784bae011d1837 (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.c16
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;