• Home
  • Raw
  • Download

Lines Matching +full:pll +full:- +full:0

1 // SPDX-License-Identifier: GPL-2.0-or-later
6 #include <linux/clk-provider.h>
17 #define PLL_DIV_MASK 0xff
20 #define PLL_MUL(reg, layout) (((reg) >> (layout)->mul_shift) & \
21 (layout)->mul_mask)
23 #define PLL_MUL_MASK(layout) ((layout)->mul_mask)
26 #define PLL_ICPR_MASK(id) (0xffff << PLL_ICPR_SHIFT(id))
27 #define PLL_MAX_COUNT 0x3f
51 return status & PLL_STATUS_MASK(id) ? 1 : 0; in clk_pll_ready()
56 struct clk_pll *pll = to_clk_pll(hw); in clk_pll_prepare() local
57 struct regmap *regmap = pll->regmap; in clk_pll_prepare()
58 const struct clk_pll_layout *layout = pll->layout; in clk_pll_prepare()
60 pll->characteristics; in clk_pll_prepare()
61 u8 id = pll->id; in clk_pll_prepare()
64 u8 out = 0; in clk_pll_prepare()
76 (div == pll->div && mul == pll->mul)) in clk_pll_prepare()
77 return 0; in clk_pll_prepare()
79 if (characteristics->out) in clk_pll_prepare()
80 out = characteristics->out[pll->range]; in clk_pll_prepare()
82 if (characteristics->icpll) in clk_pll_prepare()
84 characteristics->icpll[pll->range] << PLL_ICPR_SHIFT(id)); in clk_pll_prepare()
86 regmap_update_bits(regmap, offset, layout->pllr_mask, in clk_pll_prepare()
87 pll->div | (PLL_MAX_COUNT << PLL_COUNT_SHIFT) | in clk_pll_prepare()
89 ((pll->mul & layout->mul_mask) << layout->mul_shift)); in clk_pll_prepare()
91 while (!clk_pll_ready(regmap, pll->id)) in clk_pll_prepare()
94 return 0; in clk_pll_prepare()
99 struct clk_pll *pll = to_clk_pll(hw); in clk_pll_is_prepared() local
101 return clk_pll_ready(pll->regmap, pll->id); in clk_pll_is_prepared()
106 struct clk_pll *pll = to_clk_pll(hw); in clk_pll_unprepare() local
107 unsigned int mask = pll->layout->pllr_mask; in clk_pll_unprepare()
109 regmap_update_bits(pll->regmap, PLL_REG(pll->id), mask, ~mask); in clk_pll_unprepare()
115 struct clk_pll *pll = to_clk_pll(hw); in clk_pll_recalc_rate() local
117 if (!pll->div || !pll->mul) in clk_pll_recalc_rate()
118 return 0; in clk_pll_recalc_rate()
120 return (parent_rate / pll->div) * (pll->mul + 1); in clk_pll_recalc_rate()
123 static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate, in clk_pll_get_best_div_mul() argument
127 const struct clk_pll_layout *layout = pll->layout; in clk_pll_get_best_div_mul()
129 pll->characteristics; in clk_pll_get_best_div_mul()
132 long bestrate = -ERANGE; in clk_pll_get_best_div_mul()
135 int i = 0; in clk_pll_get_best_div_mul()
138 if (parent_rate < characteristics->input.min) in clk_pll_get_best_div_mul()
139 return -ERANGE; in clk_pll_get_best_div_mul()
145 * of the PLL blocks. in clk_pll_get_best_div_mul()
151 if (parent_rate > characteristics->input.max) { in clk_pll_get_best_div_mul()
152 tmpdiv = DIV_ROUND_UP(parent_rate, characteristics->input.max); in clk_pll_get_best_div_mul()
154 return -ERANGE; in clk_pll_get_best_div_mul()
161 * Calculate the maximum divider which is limited by PLL register in clk_pll_get_best_div_mul()
185 remainder = tmprate - rate; in clk_pll_get_best_div_mul()
187 remainder = rate - tmprate; in clk_pll_get_best_div_mul()
209 /* We haven't found any multiplier/divider pair => return -ERANGE */ in clk_pll_get_best_div_mul()
210 if (bestrate < 0) in clk_pll_get_best_div_mul()
214 for (i = 0; i < characteristics->num_output; i++) { in clk_pll_get_best_div_mul()
215 if (bestrate >= characteristics->output[i].min && in clk_pll_get_best_div_mul()
216 bestrate <= characteristics->output[i].max) in clk_pll_get_best_div_mul()
220 if (i >= characteristics->num_output) in clk_pll_get_best_div_mul()
221 return -ERANGE; in clk_pll_get_best_div_mul()
226 *mul = bestmul - 1; in clk_pll_get_best_div_mul()
236 struct clk_pll *pll = to_clk_pll(hw); in clk_pll_round_rate() local
238 return clk_pll_get_best_div_mul(pll, rate, *parent_rate, in clk_pll_round_rate()
245 struct clk_pll *pll = to_clk_pll(hw); in clk_pll_set_rate() local
251 ret = clk_pll_get_best_div_mul(pll, rate, parent_rate, in clk_pll_set_rate()
253 if (ret < 0) in clk_pll_set_rate()
256 pll->range = index; in clk_pll_set_rate()
257 pll->div = div; in clk_pll_set_rate()
258 pll->mul = mul; in clk_pll_set_rate()
260 return 0; in clk_pll_set_rate()
278 struct clk_pll *pll; in at91_clk_register_pll() local
286 return ERR_PTR(-EINVAL); in at91_clk_register_pll()
288 pll = kzalloc(sizeof(*pll), GFP_KERNEL); in at91_clk_register_pll()
289 if (!pll) in at91_clk_register_pll()
290 return ERR_PTR(-ENOMEM); in at91_clk_register_pll()
298 pll->id = id; in at91_clk_register_pll()
299 pll->hw.init = &init; in at91_clk_register_pll()
300 pll->layout = layout; in at91_clk_register_pll()
301 pll->characteristics = characteristics; in at91_clk_register_pll()
302 pll->regmap = regmap; in at91_clk_register_pll()
304 pll->div = PLL_DIV(pllr); in at91_clk_register_pll()
305 pll->mul = PLL_MUL(pllr, layout); in at91_clk_register_pll()
307 hw = &pll->hw; in at91_clk_register_pll()
308 ret = clk_hw_register(NULL, &pll->hw); in at91_clk_register_pll()
310 kfree(pll); in at91_clk_register_pll()
319 .pllr_mask = 0x7FFFFFF,
321 .mul_mask = 0x7FF,
325 .pllr_mask = 0xFFFFFF,
327 .mul_mask = 0xFF,
331 .pllr_mask = 0x3FFFFF,
333 .mul_mask = 0x3F,
337 .pllr_mask = 0x1FFFFFF,
339 .mul_mask = 0x7F,