static struct clk * __init meson_clk_register_fixed_factor(const struct clk_conf *clk_conf, void __iomem *clk_base) { struct clk *clk; const struct fixed_fact_conf *fixed_fact_conf; const struct parm *p; unsigned int mult, div; u32 reg; fixed_fact_conf = &clk_conf->conf.fixed_fact; mult = clk_conf->conf.fixed_fact.mult; div = clk_conf->conf.fixed_fact.div; if (!mult) { mult = 1; p = &fixed_fact_conf->mult_parm; if (MESON_PARM_APPLICABLE(p)) { reg = readl(clk_base + clk_conf->reg_off + p->reg_off); mult = PARM_GET(p->width, p->shift, reg); } } if (!div) { div = 1; p = &fixed_fact_conf->div_parm; if (MESON_PARM_APPLICABLE(p)) { reg = readl(clk_base + clk_conf->reg_off + p->reg_off); mult = PARM_GET(p->width, p->shift, reg); } } clk = clk_register_fixed_factor(NULL, clk_conf->clk_name, clk_conf->clks_parent[0], clk_conf->flags, mult, div); return clk; }
static void mpll_init(struct clk_hw *hw) { struct clk_regmap *clk = to_clk_regmap(hw); struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk); if (mpll->init_count) regmap_multi_reg_write(clk->map, mpll->init_regs, mpll->init_count); /* Enable the fractional part */ meson_parm_write(clk->map, &mpll->sdm_en, 1); /* Set spread spectrum if possible */ if (MESON_PARM_APPLICABLE(&mpll->ssen)) { unsigned int ss = mpll->flags & CLK_MESON_MPLL_SPREAD_SPECTRUM ? 1 : 0; meson_parm_write(clk->map, &mpll->ssen, ss); } /* Set the magic misc bit if required */ if (MESON_PARM_APPLICABLE(&mpll->misc)) meson_parm_write(clk->map, &mpll->misc, 1); }
static struct clk * __init meson_clk_register_composite(const struct clk_conf *clk_conf, void __iomem *clk_base) { struct clk *clk; struct clk_mux *mux = NULL; struct clk_divider *div = NULL; struct clk_gate *gate = NULL; const struct clk_ops *mux_ops = NULL; const struct composite_conf *composite_conf; composite_conf = clk_conf->conf.composite; if (clk_conf->num_parents > 1) { mux = kzalloc(sizeof(*mux), GFP_KERNEL); if (!mux) return ERR_PTR(-ENOMEM); mux->reg = clk_base + clk_conf->reg_off + composite_conf->mux_parm.reg_off; mux->shift = composite_conf->mux_parm.shift; mux->mask = BIT(composite_conf->mux_parm.width) - 1; mux->flags = composite_conf->mux_flags; mux->lock = &clk_lock; mux->table = composite_conf->mux_table; mux_ops = (composite_conf->mux_flags & CLK_MUX_READ_ONLY) ? &clk_mux_ro_ops : &clk_mux_ops; } if (MESON_PARM_APPLICABLE(&composite_conf->div_parm)) { div = kzalloc(sizeof(*div), GFP_KERNEL); if (!div) { clk = ERR_PTR(-ENOMEM); goto error; } div->reg = clk_base + clk_conf->reg_off + composite_conf->div_parm.reg_off; div->shift = composite_conf->div_parm.shift; div->width = composite_conf->div_parm.width; div->lock = &clk_lock; div->flags = composite_conf->div_flags; div->table = composite_conf->div_table; } if (MESON_PARM_APPLICABLE(&composite_conf->gate_parm)) { gate = kzalloc(sizeof(*gate), GFP_KERNEL); if (!gate) { clk = ERR_PTR(-ENOMEM); goto error; } gate->reg = clk_base + clk_conf->reg_off + composite_conf->div_parm.reg_off; gate->bit_idx = composite_conf->gate_parm.shift; gate->flags = composite_conf->gate_flags; gate->lock = &clk_lock; } clk = clk_register_composite(NULL, clk_conf->clk_name, clk_conf->clks_parent, clk_conf->num_parents, mux ? &mux->hw : NULL, mux_ops, div ? &div->hw : NULL, &clk_divider_ops, gate ? &gate->hw : NULL, &clk_gate_ops, clk_conf->flags); if (IS_ERR(clk)) goto error; return clk; error: kfree(gate); kfree(div); kfree(mux); return clk; }