Lines Matching +full:clock +full:- +full:tree
1 // SPDX-License-Identifier: GPL-2.0
3 * MediaTek common clock driver
10 #include <clk-uclass.h>
15 #include "clk-mtk.h"
28 /* scpsys clock off control */
51 return -ENODEV; in mtk_clk_find_parent_rate()
55 parent.dev = clk->dev; in mtk_clk_find_parent_rate()
66 while (mux->parent[index] != parent) in mtk_clk_mux_set_parent()
67 if (++index == mux->num_parents) in mtk_clk_mux_set_parent()
68 return -EINVAL; in mtk_clk_mux_set_parent()
71 val = readl(base + mux->mux_reg); in mtk_clk_mux_set_parent()
72 val &= ~(mux->mux_mask << mux->mux_shift); in mtk_clk_mux_set_parent()
74 val |= index << mux->mux_shift; in mtk_clk_mux_set_parent()
75 writel(val, base + mux->mux_reg); in mtk_clk_mux_set_parent()
85 int pcwbits = pll->pcwbits; in __mtk_pll_recalc_rate()
91 pcwfbits = pcwbits > INTEGER_BITS ? pcwbits - INTEGER_BITS : 0; in __mtk_pll_recalc_rate()
95 if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0))) in __mtk_pll_recalc_rate()
103 return ((unsigned long)vco + postdiv - 1) / postdiv; in __mtk_pll_recalc_rate()
110 * fractional part. Also they have a 3 bit power-of-two post divider.
114 struct mtk_clk_priv *priv = dev_get_priv(clk->dev); in mtk_pll_set_rate_regs()
115 const struct mtk_pll_data *pll = &priv->tree->plls[clk->id]; in mtk_pll_set_rate_regs()
119 val = readl(priv->base + pll->pd_reg); in mtk_pll_set_rate_regs()
120 val &= ~(POSTDIV_MASK << pll->pd_shift); in mtk_pll_set_rate_regs()
121 val |= (ffs(postdiv) - 1) << pll->pd_shift; in mtk_pll_set_rate_regs()
124 if (pll->pd_reg != pll->pcw_reg) { in mtk_pll_set_rate_regs()
125 writel(val, priv->base + pll->pd_reg); in mtk_pll_set_rate_regs()
126 val = readl(priv->base + pll->pcw_reg); in mtk_pll_set_rate_regs()
130 val &= ~GENMASK(pll->pcw_shift + pll->pcwbits - 1, pll->pcw_shift); in mtk_pll_set_rate_regs()
131 val |= pcw << pll->pcw_shift; in mtk_pll_set_rate_regs()
133 writel(val, priv->base + pll->pcw_reg); in mtk_pll_set_rate_regs()
136 writel(val, priv->base + pll->pcw_reg); in mtk_pll_set_rate_regs()
142 * mtk_pll_calc_values - calculate good values for a given input frequency.
151 struct mtk_clk_priv *priv = dev_get_priv(clk->dev); in mtk_pll_calc_values()
152 const struct mtk_pll_data *pll = &priv->tree->plls[clk->id]; in mtk_pll_calc_values()
157 if (freq > pll->fmax) in mtk_pll_calc_values()
158 freq = pll->fmax; in mtk_pll_calc_values()
167 _pcw = ((u64)freq << val) << (pll->pcwbits - INTEGER_BITS); in mtk_pll_calc_values()
168 do_div(_pcw, priv->tree->xtal2_rate); in mtk_pll_calc_values()
186 struct mtk_clk_priv *priv = dev_get_priv(clk->dev); in mtk_apmixedsys_get_rate()
187 const struct mtk_pll_data *pll = &priv->tree->plls[clk->id]; in mtk_apmixedsys_get_rate()
191 postdiv = (readl(priv->base + pll->pd_reg) >> pll->pd_shift) & in mtk_apmixedsys_get_rate()
195 pcw = readl(priv->base + pll->pcw_reg) >> pll->pcw_shift; in mtk_apmixedsys_get_rate()
196 pcw &= GENMASK(pll->pcwbits - 1, 0); in mtk_apmixedsys_get_rate()
198 return __mtk_pll_recalc_rate(pll, priv->tree->xtal2_rate, in mtk_apmixedsys_get_rate()
204 struct mtk_clk_priv *priv = dev_get_priv(clk->dev); in mtk_apmixedsys_enable()
205 const struct mtk_pll_data *pll = &priv->tree->plls[clk->id]; in mtk_apmixedsys_enable()
208 r = readl(priv->base + pll->pwr_reg) | CON0_PWR_ON; in mtk_apmixedsys_enable()
209 writel(r, priv->base + pll->pwr_reg); in mtk_apmixedsys_enable()
212 r = readl(priv->base + pll->pwr_reg) & ~CON0_ISO_EN; in mtk_apmixedsys_enable()
213 writel(r, priv->base + pll->pwr_reg); in mtk_apmixedsys_enable()
216 r = readl(priv->base + pll->reg + REG_CON0); in mtk_apmixedsys_enable()
217 r |= pll->en_mask; in mtk_apmixedsys_enable()
218 writel(r, priv->base + pll->reg + REG_CON0); in mtk_apmixedsys_enable()
222 if (pll->flags & HAVE_RST_BAR) { in mtk_apmixedsys_enable()
223 r = readl(priv->base + pll->reg + REG_CON0); in mtk_apmixedsys_enable()
224 r |= pll->rst_bar_mask; in mtk_apmixedsys_enable()
225 writel(r, priv->base + pll->reg + REG_CON0); in mtk_apmixedsys_enable()
233 struct mtk_clk_priv *priv = dev_get_priv(clk->dev); in mtk_apmixedsys_disable()
234 const struct mtk_pll_data *pll = &priv->tree->plls[clk->id]; in mtk_apmixedsys_disable()
237 if (pll->flags & HAVE_RST_BAR) { in mtk_apmixedsys_disable()
238 r = readl(priv->base + pll->reg + REG_CON0); in mtk_apmixedsys_disable()
239 r &= ~pll->rst_bar_mask; in mtk_apmixedsys_disable()
240 writel(r, priv->base + pll->reg + REG_CON0); in mtk_apmixedsys_disable()
243 r = readl(priv->base + pll->reg + REG_CON0); in mtk_apmixedsys_disable()
245 writel(r, priv->base + pll->reg + REG_CON0); in mtk_apmixedsys_disable()
247 r = readl(priv->base + pll->pwr_reg) | CON0_ISO_EN; in mtk_apmixedsys_disable()
248 writel(r, priv->base + pll->pwr_reg); in mtk_apmixedsys_disable()
250 r = readl(priv->base + pll->pwr_reg) & ~CON0_PWR_ON; in mtk_apmixedsys_disable()
251 writel(r, priv->base + pll->pwr_reg); in mtk_apmixedsys_disable()
261 u64 rate = parent_rate * fdiv->mult; in mtk_factor_recalc_rate()
263 do_div(rate, fdiv->div); in mtk_factor_recalc_rate()
270 struct mtk_clk_priv *priv = dev_get_priv(clk->dev); in mtk_topckgen_get_factor_rate()
271 const struct mtk_fixed_factor *fdiv = &priv->tree->fdivs[off]; in mtk_topckgen_get_factor_rate()
274 switch (fdiv->flags & CLK_PARENT_MASK) { in mtk_topckgen_get_factor_rate()
276 rate = mtk_clk_find_parent_rate(clk, fdiv->parent, in mtk_topckgen_get_factor_rate()
280 rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL); in mtk_topckgen_get_factor_rate()
284 rate = priv->tree->xtal_rate; in mtk_topckgen_get_factor_rate()
292 struct mtk_clk_priv *priv = dev_get_priv(clk->dev); in mtk_topckgen_get_mux_rate()
293 const struct mtk_composite *mux = &priv->tree->muxes[off]; in mtk_topckgen_get_mux_rate()
296 index = readl(priv->base + mux->mux_reg); in mtk_topckgen_get_mux_rate()
297 index &= mux->mux_mask << mux->mux_shift; in mtk_topckgen_get_mux_rate()
298 index = index >> mux->mux_shift; in mtk_topckgen_get_mux_rate()
300 if (mux->parent[index]) in mtk_topckgen_get_mux_rate()
301 return mtk_clk_find_parent_rate(clk, mux->parent[index], in mtk_topckgen_get_mux_rate()
304 return priv->tree->xtal_rate; in mtk_topckgen_get_mux_rate()
309 struct mtk_clk_priv *priv = dev_get_priv(clk->dev); in mtk_topckgen_get_rate()
311 if (clk->id < priv->tree->fdivs_offs) in mtk_topckgen_get_rate()
312 return priv->tree->fclks[clk->id].rate; in mtk_topckgen_get_rate()
313 else if (clk->id < priv->tree->muxes_offs) in mtk_topckgen_get_rate()
314 return mtk_topckgen_get_factor_rate(clk, clk->id - in mtk_topckgen_get_rate()
315 priv->tree->fdivs_offs); in mtk_topckgen_get_rate()
317 return mtk_topckgen_get_mux_rate(clk, clk->id - in mtk_topckgen_get_rate()
318 priv->tree->muxes_offs); in mtk_topckgen_get_rate()
323 struct mtk_clk_priv *priv = dev_get_priv(clk->dev); in mtk_topckgen_enable()
327 if (clk->id < priv->tree->muxes_offs) in mtk_topckgen_enable()
330 mux = &priv->tree->muxes[clk->id - priv->tree->muxes_offs]; in mtk_topckgen_enable()
331 if (mux->gate_shift < 0) in mtk_topckgen_enable()
334 /* enable clock gate */ in mtk_topckgen_enable()
335 val = readl(priv->base + mux->gate_reg); in mtk_topckgen_enable()
336 val &= ~BIT(mux->gate_shift); in mtk_topckgen_enable()
337 writel(val, priv->base + mux->gate_reg); in mtk_topckgen_enable()
339 if (mux->flags & CLK_DOMAIN_SCPSYS) { in mtk_topckgen_enable()
340 /* enable scpsys clock off control */ in mtk_topckgen_enable()
341 writel(SCP_ARMCK_OFF_EN, priv->base + CLK_SCP_CFG0); in mtk_topckgen_enable()
343 priv->base + CLK_SCP_CFG1); in mtk_topckgen_enable()
351 struct mtk_clk_priv *priv = dev_get_priv(clk->dev); in mtk_topckgen_disable()
355 if (clk->id < priv->tree->muxes_offs) in mtk_topckgen_disable()
358 mux = &priv->tree->muxes[clk->id - priv->tree->muxes_offs]; in mtk_topckgen_disable()
359 if (mux->gate_shift < 0) in mtk_topckgen_disable()
362 /* disable clock gate */ in mtk_topckgen_disable()
363 val = readl(priv->base + mux->gate_reg); in mtk_topckgen_disable()
364 val |= BIT(mux->gate_shift); in mtk_topckgen_disable()
365 writel(val, priv->base + mux->gate_reg); in mtk_topckgen_disable()
372 struct mtk_clk_priv *priv = dev_get_priv(clk->dev); in mtk_topckgen_set_parent()
374 if (clk->id < priv->tree->muxes_offs) in mtk_topckgen_set_parent()
377 return mtk_clk_mux_set_parent(priv->base, parent->id, in mtk_topckgen_set_parent()
378 &priv->tree->muxes[clk->id - priv->tree->muxes_offs]); in mtk_topckgen_set_parent()
385 struct mtk_cg_priv *priv = dev_get_priv(clk->dev); in mtk_clk_gate_enable()
386 const struct mtk_gate *gate = &priv->gates[clk->id]; in mtk_clk_gate_enable()
387 u32 bit = BIT(gate->shift); in mtk_clk_gate_enable()
389 switch (gate->flags & CLK_GATE_MASK) { in mtk_clk_gate_enable()
391 writel(bit, priv->base + gate->regs->clr_ofs); in mtk_clk_gate_enable()
394 clrsetbits_le32(priv->base + gate->regs->sta_ofs, bit, bit); in mtk_clk_gate_enable()
398 return -EINVAL; in mtk_clk_gate_enable()
406 struct mtk_cg_priv *priv = dev_get_priv(clk->dev); in mtk_clk_gate_disable()
407 const struct mtk_gate *gate = &priv->gates[clk->id]; in mtk_clk_gate_disable()
408 u32 bit = BIT(gate->shift); in mtk_clk_gate_disable()
410 switch (gate->flags & CLK_GATE_MASK) { in mtk_clk_gate_disable()
412 writel(bit, priv->base + gate->regs->set_ofs); in mtk_clk_gate_disable()
415 clrsetbits_le32(priv->base + gate->regs->sta_ofs, bit, 0); in mtk_clk_gate_disable()
419 return -EINVAL; in mtk_clk_gate_disable()
427 struct mtk_cg_priv *priv = dev_get_priv(clk->dev); in mtk_clk_gate_get_rate()
428 const struct mtk_gate *gate = &priv->gates[clk->id]; in mtk_clk_gate_get_rate()
430 switch (gate->flags & CLK_PARENT_MASK) { in mtk_clk_gate_get_rate()
432 return mtk_clk_find_parent_rate(clk, gate->parent, in mtk_clk_gate_get_rate()
436 return mtk_clk_find_parent_rate(clk, gate->parent, in mtk_clk_gate_get_rate()
441 return priv->tree->xtal_rate; in mtk_clk_gate_get_rate()
466 const struct mtk_clk_tree *tree) in mtk_common_clk_init() argument
470 priv->base = dev_read_addr_ptr(dev); in mtk_common_clk_init()
471 if (!priv->base) in mtk_common_clk_init()
472 return -ENOENT; in mtk_common_clk_init()
474 priv->tree = tree; in mtk_common_clk_init()
480 const struct mtk_clk_tree *tree, in mtk_common_clk_gate_init() argument
485 priv->base = dev_read_addr_ptr(dev); in mtk_common_clk_gate_init()
486 if (!priv->base) in mtk_common_clk_gate_init()
487 return -ENOENT; in mtk_common_clk_gate_init()
489 priv->tree = tree; in mtk_common_clk_gate_init()
490 priv->gates = gates; in mtk_common_clk_gate_init()