diff options
Diffstat (limited to 'drivers/clk/rockchip')
-rw-r--r-- | drivers/clk/rockchip/clk.c | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 278cf9dd1e23..5db1ecf95eca 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -103,6 +103,54 @@ struct clk *rockchip_clk_register_branch(const char *name, return clk; } +static struct clk *rockchip_clk_register_frac_branch(const char *name, + const char **parent_names, u8 num_parents, void __iomem *base, + int muxdiv_offset, u8 div_flags, + int gate_offset, u8 gate_shift, u8 gate_flags, + unsigned long flags, spinlock_t *lock) +{ + struct clk *clk; + struct clk_gate *gate = NULL; + struct clk_fractional_divider *div = NULL; + const struct clk_ops *div_ops = NULL, *gate_ops = NULL; + + if (gate_offset >= 0) { + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + return ERR_PTR(-ENOMEM); + + gate->flags = gate_flags; + gate->reg = base + gate_offset; + gate->bit_idx = gate_shift; + gate->lock = lock; + gate_ops = &clk_gate_ops; + } + + if (muxdiv_offset < 0) + return ERR_PTR(-EINVAL); + + div = kzalloc(sizeof(*div), GFP_KERNEL); + if (!div) + return ERR_PTR(-ENOMEM); + + div->flags = div_flags; + div->reg = base + muxdiv_offset; + div->mshift = 16; + div->mmask = 0xffff0000; + div->nshift = 0; + div->nmask = 0xffff; + div->lock = lock; + div_ops = &clk_fractional_divider_ops; + + clk = clk_register_composite(NULL, name, parent_names, num_parents, + NULL, NULL, + &div->hw, div_ops, + gate ? &gate->hw : NULL, gate_ops, + flags); + + return clk; +} + static DEFINE_SPINLOCK(clk_lock); static struct clk **clk_table; static void __iomem *reg_base; @@ -197,8 +245,14 @@ void __init rockchip_clk_register_branches( list->div_flags, &clk_lock); break; case branch_fraction_divider: - /* unimplemented */ - continue; + /* keep all gates untouched for now */ + flags |= CLK_IGNORE_UNUSED; + + clk = rockchip_clk_register_frac_branch(list->name, + list->parent_names, list->num_parents, + reg_base, list->muxdiv_offset, list->div_flags, + list->gate_offset, list->gate_shift, + list->gate_flags, flags, &clk_lock); break; case branch_gate: flags |= CLK_SET_RATE_PARENT; |