summaryrefslogtreecommitdiff
path: root/drivers/clk/rockchip/clk.c
diff options
context:
space:
mode:
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;