Lines Matching +full:pll +full:- +full:m +full:- +full:num
1 // SPDX-License-Identifier: GPL-2.0-only
6 * VCO-PLL clock implementation
9 #define pr_fmt(fmt) "clk-vco-pll: " fmt
11 #include <linux/clk-provider.h>
18 * DOC: VCO-PLL clock
20 * VCO and PLL rate are derived from following equations:
23 * vco = (2 * M[15:8] * Fin)/N
26 * vco = (2 * M[15:0] * Fin)/(256 * N)
28 * pll_rate = pll/2^p
30 * vco and pll are very closely bound to each other, "vco needs to program:
31 * mode, m & n" and "pll needs to program p", both share common enable/disable
34 * clk_register_vco_pll() registers instances of both vco & pll.
35 * CLK_SET_RATE_PARENT flag is forced for pll, as it will always pass its
37 * configures m, n and p.
52 /* PLL FRQ register masks */
65 /* Calculates pll clk rate for specific value of mode, m, n and p */
73 rate = (((2 * rate / 10000) * rtbl[index].m) / (mode * rtbl[index].n)); in pll_calc_rate()
84 struct clk_pll *pll = to_clk_pll(hw); in clk_pll_round_rate_index() local
90 pr_err("%s: prate is must for pll clk\n", __func__); in clk_pll_round_rate_index()
91 return -EINVAL; in clk_pll_round_rate_index()
94 for (*index = 0; *index < pll->vco->rtbl_cnt; (*index)++) { in clk_pll_round_rate_index()
97 *prate = pll_calc_rate(pll->vco->rtbl, vco_parent_rate, *index, in clk_pll_round_rate_index()
104 (*index)--; in clk_pll_round_rate_index()
118 req->rate = clk_pll_round_rate_index(hw, req->rate, in clk_pll_determine_rate()
119 &req->best_parent_rate, &unused); in clk_pll_determine_rate()
127 struct clk_pll *pll = to_clk_pll(hw); in clk_pll_recalc_rate() local
131 if (pll->vco->lock) in clk_pll_recalc_rate()
132 spin_lock_irqsave(pll->vco->lock, flags); in clk_pll_recalc_rate()
134 p = readl_relaxed(pll->vco->cfg_reg); in clk_pll_recalc_rate()
136 if (pll->vco->lock) in clk_pll_recalc_rate()
137 spin_unlock_irqrestore(pll->vco->lock, flags); in clk_pll_recalc_rate()
147 struct clk_pll *pll = to_clk_pll(hw); in clk_pll_set_rate() local
148 struct pll_rate_tbl *rtbl = pll->vco->rtbl; in clk_pll_set_rate()
154 if (pll->vco->lock) in clk_pll_set_rate()
155 spin_lock_irqsave(pll->vco->lock, flags); in clk_pll_set_rate()
157 val = readl_relaxed(pll->vco->cfg_reg); in clk_pll_set_rate()
160 writel_relaxed(val, pll->vco->cfg_reg); in clk_pll_set_rate()
162 if (pll->vco->lock) in clk_pll_set_rate()
163 spin_unlock_irqrestore(pll->vco->lock, flags); in clk_pll_set_rate()
179 return pll_calc_rate(vco->rtbl, prate, index, NULL); in vco_calc_rate()
188 req->rate = clk_round_rate_index(hw, req->rate, req->best_parent_rate, in clk_vco_determine_rate()
189 vco_calc_rate, vco->rtbl_cnt, &unused); in clk_vco_determine_rate()
199 unsigned int num = 2, den = 0, val, mode = 0; in clk_vco_recalc_rate() local
201 if (vco->lock) in clk_vco_recalc_rate()
202 spin_lock_irqsave(vco->lock, flags); in clk_vco_recalc_rate()
204 mode = (readl_relaxed(vco->mode_reg) >> PLL_MODE_SHIFT) & PLL_MODE_MASK; in clk_vco_recalc_rate()
206 val = readl_relaxed(vco->cfg_reg); in clk_vco_recalc_rate()
208 if (vco->lock) in clk_vco_recalc_rate()
209 spin_unlock_irqrestore(vco->lock, flags); in clk_vco_recalc_rate()
216 num *= (val >> PLL_NORM_FDBK_M_SHIFT) & PLL_NORM_FDBK_M_MASK; in clk_vco_recalc_rate()
219 num *= (val >> PLL_DITH_FDBK_M_SHIFT) & PLL_DITH_FDBK_M_MASK; in clk_vco_recalc_rate()
228 return (((parent_rate / 10000) * num) / den) * 10000; in clk_vco_recalc_rate()
236 struct pll_rate_tbl *rtbl = vco->rtbl; in clk_vco_set_rate()
240 clk_round_rate_index(hw, drate, prate, vco_calc_rate, vco->rtbl_cnt, in clk_vco_set_rate()
243 if (vco->lock) in clk_vco_set_rate()
244 spin_lock_irqsave(vco->lock, flags); in clk_vco_set_rate()
246 val = readl_relaxed(vco->mode_reg); in clk_vco_set_rate()
249 writel_relaxed(val, vco->mode_reg); in clk_vco_set_rate()
251 val = readl_relaxed(vco->cfg_reg); in clk_vco_set_rate()
257 val |= (rtbl[i].m & PLL_DITH_FDBK_M_MASK) << in clk_vco_set_rate()
260 val |= (rtbl[i].m & PLL_NORM_FDBK_M_MASK) << in clk_vco_set_rate()
263 writel_relaxed(val, vco->cfg_reg); in clk_vco_set_rate()
265 if (vco->lock) in clk_vco_set_rate()
266 spin_unlock_irqrestore(vco->lock, flags); in clk_vco_set_rate()
285 struct clk_pll *pll; in clk_register_vco_pll() local
293 return ERR_PTR(-EINVAL); in clk_register_vco_pll()
298 return ERR_PTR(-ENOMEM); in clk_register_vco_pll()
300 pll = kzalloc(sizeof(*pll), GFP_KERNEL); in clk_register_vco_pll()
301 if (!pll) in clk_register_vco_pll()
305 vco->mode_reg = mode_reg; in clk_register_vco_pll()
306 vco->cfg_reg = cfg_reg; in clk_register_vco_pll()
307 vco->rtbl = rtbl; in clk_register_vco_pll()
308 vco->rtbl_cnt = rtbl_cnt; in clk_register_vco_pll()
309 vco->lock = lock; in clk_register_vco_pll()
310 vco->hw.init = &vco_init; in clk_register_vco_pll()
312 pll->vco = vco; in clk_register_vco_pll()
313 pll->hw.init = &pll_init; in clk_register_vco_pll()
340 vco_clk = clk_register(NULL, &vco->hw); in clk_register_vco_pll()
344 tpll_clk = clk_register(NULL, &pll->hw); in clk_register_vco_pll()
354 kfree(pll); in clk_register_vco_pll()
358 pr_err("Failed to register vco pll clock\n"); in clk_register_vco_pll()
360 return ERR_PTR(-ENOMEM); in clk_register_vco_pll()