Lines Matching +full:fixed +full:- +full:parent +full:- +full:rate

1 // SPDX-License-Identifier: GPL-2.0-or-later
7 * Quentin Schulz <quentin.schulz@free-electrons.com>
9 * The Sama5d2 SoC has two audio PLLs (PMC and PAD) that shares the same parent
10 * (FRAC). FRAC can output between 620 and 700MHz and only multiply the rate of
11 * its own parent. PMC and PAD can then divide the FRAC rate to best match the
12 * asked rate.
15 * enable - clk_enable writes nd, fracr parameters and enables PLL
16 * rate - rate is adjustable.
17 * clk->rate = parent->rate * ((nd + 1) + (fracr / 2^22))
18 * parent - fixed parent. No clk_set_parent support
21 * enable - clk_enable writes qdpmc, and enables PMC output
22 * rate - rate is adjustable.
23 * clk->rate = parent->rate / (qdpmc + 1)
24 * parent - fixed parent. No clk_set_parent support
27 * enable - clk_enable writes divisors and enables PAD output
28 * rate - rate is adjustable.
29 * clk->rate = parent->rate / (qdaudio * div))
30 * parent - fixed parent. No clk_set_parent support
34 #include <linux/clk-provider.h>
86 regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0, in clk_audio_pll_frac_enable()
88 regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0, in clk_audio_pll_frac_enable()
91 regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL1, in clk_audio_pll_frac_enable()
92 AT91_PMC_AUDIO_PLL_FRACR_MASK, frac->fracr); in clk_audio_pll_frac_enable()
98 regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0, in clk_audio_pll_frac_enable()
102 AT91_PMC_AUDIO_PLL_ND(frac->nd)); in clk_audio_pll_frac_enable()
111 regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL1, in clk_audio_pll_pad_enable()
113 AUDIO_PLL_QDPAD(apad_ck->qdaudio, apad_ck->div)); in clk_audio_pll_pad_enable()
114 regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL0, in clk_audio_pll_pad_enable()
124 regmap_update_bits(apmc_ck->regmap, AT91_PMC_AUDIO_PLL0, in clk_audio_pll_pmc_enable()
128 AT91_PMC_AUDIO_PLL_QDPMC(apmc_ck->qdpmc)); in clk_audio_pll_pmc_enable()
136 regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0, in clk_audio_pll_frac_disable()
139 regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0, in clk_audio_pll_frac_disable()
147 regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL0, in clk_audio_pll_pad_disable()
155 regmap_update_bits(apmc_ck->regmap, AT91_PMC_AUDIO_PLL0, in clk_audio_pll_pmc_disable()
179 fout = clk_audio_pll_fout(parent_rate, frac->nd, frac->fracr); in clk_audio_pll_frac_recalc_rate()
182 fout, frac->nd, (unsigned long)frac->fracr); in clk_audio_pll_frac_recalc_rate()
193 if (apad_ck->qdaudio && apad_ck->div) in clk_audio_pll_pad_recalc_rate()
194 apad_rate = parent_rate / (apad_ck->qdaudio * apad_ck->div); in clk_audio_pll_pad_recalc_rate()
197 __func__, apad_rate, apad_ck->div, apad_ck->qdaudio); in clk_audio_pll_pad_recalc_rate()
208 apmc_rate = parent_rate / (apmc_ck->qdpmc + 1); in clk_audio_pll_pmc_recalc_rate()
211 apmc_rate, apmc_ck->qdpmc); in clk_audio_pll_pmc_recalc_rate()
216 static int clk_audio_pll_frac_compute_frac(unsigned long rate, in clk_audio_pll_frac_compute_frac() argument
223 if (!rate) in clk_audio_pll_frac_compute_frac()
224 return -EINVAL; in clk_audio_pll_frac_compute_frac()
226 tmp = rate; in clk_audio_pll_frac_compute_frac()
229 return -EINVAL; in clk_audio_pll_frac_compute_frac()
231 *nd = tmp - 1; in clk_audio_pll_frac_compute_frac()
236 return -EINVAL; in clk_audio_pll_frac_compute_frac()
250 pr_debug("A PLL: %s, rate = %lu (parent_rate = %lu)\n", __func__, in clk_audio_pll_frac_determine_rate()
251 req->rate, req->best_parent_rate); in clk_audio_pll_frac_determine_rate()
253 req->rate = clamp(req->rate, AUDIO_PLL_FOUT_MIN, AUDIO_PLL_FOUT_MAX); in clk_audio_pll_frac_determine_rate()
255 req->min_rate = max(req->min_rate, AUDIO_PLL_FOUT_MIN); in clk_audio_pll_frac_determine_rate()
256 req->max_rate = min(req->max_rate, AUDIO_PLL_FOUT_MAX); in clk_audio_pll_frac_determine_rate()
258 ret = clk_audio_pll_frac_compute_frac(req->rate, req->best_parent_rate, in clk_audio_pll_frac_determine_rate()
263 req->rate = clk_audio_pll_fout(req->best_parent_rate, nd, fracr); in clk_audio_pll_frac_determine_rate()
265 req->best_parent_hw = clk_hw_get_parent(hw); in clk_audio_pll_frac_determine_rate()
268 __func__, req->rate, nd, fracr); in clk_audio_pll_frac_determine_rate()
273 static long clk_audio_pll_pad_round_rate(struct clk_hw *hw, unsigned long rate, in clk_audio_pll_pad_round_rate() argument
277 long best_rate = -EINVAL; in clk_audio_pll_pad_round_rate()
283 int best_diff = -1; in clk_audio_pll_pad_round_rate()
285 pr_debug("A PLL/PAD: %s, rate = %lu (parent_rate = %lu)\n", __func__, in clk_audio_pll_pad_round_rate()
286 rate, *parent_rate); in clk_audio_pll_pad_round_rate()
289 * Rate divisor is actually made of two different divisors, multiplied in clk_audio_pll_pad_round_rate()
290 * between themselves before dividing the rate. in clk_audio_pll_pad_round_rate()
292 * In order to avoid testing twice the rate divisor (e.g. divisor 12 can in clk_audio_pll_pad_round_rate()
294 * for a rate divisor when div is 2 and tmp_qd is a multiple of 3. in clk_audio_pll_pad_round_rate()
296 * would miss some rate divisor that aren't reachable with div being 2 in clk_audio_pll_pad_round_rate()
297 * (e.g. rate divisor 90 is made with div = 3 and tmp_qd = 30, thus in clk_audio_pll_pad_round_rate()
299 * rate divisor which isn't possible since tmp_qd has to be <= 31). in clk_audio_pll_pad_round_rate()
307 rate * tmp_qd * div); in clk_audio_pll_pad_round_rate()
309 tmp_diff = abs(rate - tmp_rate); in clk_audio_pll_pad_round_rate()
324 static long clk_audio_pll_pmc_round_rate(struct clk_hw *hw, unsigned long rate, in clk_audio_pll_pmc_round_rate() argument
328 long best_rate = -EINVAL; in clk_audio_pll_pmc_round_rate()
333 int best_diff = -1; in clk_audio_pll_pmc_round_rate()
335 pr_debug("A PLL/PMC: %s, rate = %lu (parent_rate = %lu)\n", __func__, in clk_audio_pll_pmc_round_rate()
336 rate, *parent_rate); in clk_audio_pll_pmc_round_rate()
338 if (!rate) in clk_audio_pll_pmc_round_rate()
341 best_parent_rate = clk_round_rate(pclk->clk, 1); in clk_audio_pll_pmc_round_rate()
342 div = max(best_parent_rate / rate, 1UL); in clk_audio_pll_pmc_round_rate()
344 best_parent_rate = clk_round_rate(pclk->clk, rate * div); in clk_audio_pll_pmc_round_rate()
346 tmp_diff = abs(rate - tmp_rate); in clk_audio_pll_pmc_round_rate()
359 __func__, best_rate, *parent_rate, tmp_qd - 1); in clk_audio_pll_pmc_round_rate()
364 static int clk_audio_pll_frac_set_rate(struct clk_hw *hw, unsigned long rate, in clk_audio_pll_frac_set_rate() argument
371 pr_debug("A PLL: %s, rate = %lu (parent_rate = %lu)\n", __func__, rate, in clk_audio_pll_frac_set_rate()
374 if (rate < AUDIO_PLL_FOUT_MIN || rate > AUDIO_PLL_FOUT_MAX) in clk_audio_pll_frac_set_rate()
375 return -EINVAL; in clk_audio_pll_frac_set_rate()
377 ret = clk_audio_pll_frac_compute_frac(rate, parent_rate, &nd, &fracr); in clk_audio_pll_frac_set_rate()
381 frac->nd = nd; in clk_audio_pll_frac_set_rate()
382 frac->fracr = fracr; in clk_audio_pll_frac_set_rate()
387 static int clk_audio_pll_pad_set_rate(struct clk_hw *hw, unsigned long rate, in clk_audio_pll_pad_set_rate() argument
393 pr_debug("A PLL/PAD: %s, rate = %lu (parent_rate = %lu)\n", __func__, in clk_audio_pll_pad_set_rate()
394 rate, parent_rate); in clk_audio_pll_pad_set_rate()
396 if (!rate) in clk_audio_pll_pad_set_rate()
397 return -EINVAL; in clk_audio_pll_pad_set_rate()
399 tmp_div = parent_rate / rate; in clk_audio_pll_pad_set_rate()
401 apad_ck->qdaudio = tmp_div / 3; in clk_audio_pll_pad_set_rate()
402 apad_ck->div = 3; in clk_audio_pll_pad_set_rate()
404 apad_ck->qdaudio = tmp_div / 2; in clk_audio_pll_pad_set_rate()
405 apad_ck->div = 2; in clk_audio_pll_pad_set_rate()
411 static int clk_audio_pll_pmc_set_rate(struct clk_hw *hw, unsigned long rate, in clk_audio_pll_pmc_set_rate() argument
416 if (!rate) in clk_audio_pll_pmc_set_rate()
417 return -EINVAL; in clk_audio_pll_pmc_set_rate()
419 pr_debug("A PLL/PMC: %s, rate = %lu (parent_rate = %lu)\n", __func__, in clk_audio_pll_pmc_set_rate()
420 rate, parent_rate); in clk_audio_pll_pmc_set_rate()
422 apmc_ck->qdpmc = parent_rate / rate - 1; in clk_audio_pll_pmc_set_rate()
461 return ERR_PTR(-ENOMEM); in at91_clk_register_audio_pll_frac()
469 frac_ck->hw.init = &init; in at91_clk_register_audio_pll_frac()
470 frac_ck->regmap = regmap; in at91_clk_register_audio_pll_frac()
472 ret = clk_hw_register(NULL, &frac_ck->hw); in at91_clk_register_audio_pll_frac()
478 return &frac_ck->hw; in at91_clk_register_audio_pll_frac()
491 return ERR_PTR(-ENOMEM); in at91_clk_register_audio_pll_pad()
500 apad_ck->hw.init = &init; in at91_clk_register_audio_pll_pad()
501 apad_ck->regmap = regmap; in at91_clk_register_audio_pll_pad()
503 ret = clk_hw_register(NULL, &apad_ck->hw); in at91_clk_register_audio_pll_pad()
509 return &apad_ck->hw; in at91_clk_register_audio_pll_pad()
522 return ERR_PTR(-ENOMEM); in at91_clk_register_audio_pll_pmc()
531 apmc_ck->hw.init = &init; in at91_clk_register_audio_pll_pmc()
532 apmc_ck->regmap = regmap; in at91_clk_register_audio_pll_pmc()
534 ret = clk_hw_register(NULL, &apmc_ck->hw); in at91_clk_register_audio_pll_pmc()
540 return &apmc_ck->hw; in at91_clk_register_audio_pll_pmc()