1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2015 Endless Mobile, Inc.
4 * Author: Carlo Caione <carlo@endlessm.com>
6 * Copyright (c) 2018 Baylibre, SAS.
7 * Author: Jerome Brunet <jbrunet@baylibre.com>
11 * In the most basic form, a Meson PLL is composed as follows:
14 * +--------------------------------+
17 * in >>-----[ /N ]--->| | +-----+ |
18 * | | |------| DCO |---->> out
19 * | +--------->| | +--v--+ |
22 * | +--[ *(M + (F/Fmax) ]<--+ |
24 * +--------------------------------+
26 * out = in * (m + frac / frac_max) / n
29 #include <linux/clk-provider.h>
30 #include <linux/delay.h>
31 #include <linux/err.h>
33 #include <linux/math64.h>
34 #include <linux/module.h>
35 #include <linux/rational.h>
37 #include "clk-regmap.h"
40 static inline struct meson_clk_pll_data
*
41 meson_clk_pll_data(struct clk_regmap
*clk
)
43 return (struct meson_clk_pll_data
*)clk
->data
;
46 static int __pll_round_closest_mult(struct meson_clk_pll_data
*pll
)
48 if ((pll
->flags
& CLK_MESON_PLL_ROUND_CLOSEST
) &&
49 !MESON_PARM_APPLICABLE(&pll
->frac
))
55 static unsigned long __pll_params_to_rate(unsigned long parent_rate
,
56 unsigned int m
, unsigned int n
,
58 struct meson_clk_pll_data
*pll
)
60 u64 rate
= (u64
)parent_rate
* m
;
62 if (frac
&& MESON_PARM_APPLICABLE(&pll
->frac
)) {
63 u64 frac_rate
= (u64
)parent_rate
* frac
;
65 rate
+= DIV_ROUND_UP_ULL(frac_rate
,
66 (1 << pll
->frac
.width
));
69 return DIV_ROUND_UP_ULL(rate
, n
);
72 static unsigned long meson_clk_pll_recalc_rate(struct clk_hw
*hw
,
73 unsigned long parent_rate
)
75 struct clk_regmap
*clk
= to_clk_regmap(hw
);
76 struct meson_clk_pll_data
*pll
= meson_clk_pll_data(clk
);
77 unsigned int m
, n
, frac
;
79 n
= meson_parm_read(clk
->map
, &pll
->n
);
82 * On some HW, N is set to zero on init. This value is invalid as
83 * it would result in a division by zero. The rate can't be
84 * calculated in this case
89 m
= meson_parm_read(clk
->map
, &pll
->m
);
91 frac
= MESON_PARM_APPLICABLE(&pll
->frac
) ?
92 meson_parm_read(clk
->map
, &pll
->frac
) :
95 return __pll_params_to_rate(parent_rate
, m
, n
, frac
, pll
);
98 static unsigned int __pll_params_with_frac(unsigned long rate
,
99 unsigned long parent_rate
,
102 struct meson_clk_pll_data
*pll
)
104 unsigned int frac_max
= (1 << pll
->frac
.width
);
105 u64 val
= (u64
)rate
* n
;
107 /* Bail out if we are already over the requested rate */
108 if (rate
< parent_rate
* m
/ n
)
111 if (pll
->flags
& CLK_MESON_PLL_ROUND_CLOSEST
)
112 val
= DIV_ROUND_CLOSEST_ULL(val
* frac_max
, parent_rate
);
114 val
= div_u64(val
* frac_max
, parent_rate
);
118 return min((unsigned int)val
, (frac_max
- 1));
121 static bool meson_clk_pll_is_better(unsigned long rate
,
124 struct meson_clk_pll_data
*pll
)
126 if (__pll_round_closest_mult(pll
)) {
128 if (abs(now
- rate
) < abs(best
- rate
))
132 if (now
<= rate
&& best
< now
)
139 static int meson_clk_get_pll_table_index(unsigned int index
,
142 struct meson_clk_pll_data
*pll
)
144 if (!pll
->table
[index
].n
)
147 *m
= pll
->table
[index
].m
;
148 *n
= pll
->table
[index
].n
;
153 static unsigned int meson_clk_get_pll_range_m(unsigned long rate
,
154 unsigned long parent_rate
,
156 struct meson_clk_pll_data
*pll
)
158 u64 val
= (u64
)rate
* n
;
160 if (__pll_round_closest_mult(pll
))
161 return DIV_ROUND_CLOSEST_ULL(val
, parent_rate
);
163 return div_u64(val
, parent_rate
);
166 static int meson_clk_get_pll_range_index(unsigned long rate
,
167 unsigned long parent_rate
,
171 struct meson_clk_pll_data
*pll
)
175 /* Check the predivider range */
176 if (*n
>= (1 << pll
->n
.width
))
180 /* Get the boundaries out the way */
181 if (rate
<= pll
->range
->min
* parent_rate
) {
182 *m
= pll
->range
->min
;
184 } else if (rate
>= pll
->range
->max
* parent_rate
) {
185 *m
= pll
->range
->max
;
190 *m
= meson_clk_get_pll_range_m(rate
, parent_rate
, *n
, pll
);
192 /* the pre-divider gives a multiplier too big - stop */
193 if (*m
>= (1 << pll
->m
.width
))
199 static int meson_clk_get_pll_get_index(unsigned long rate
,
200 unsigned long parent_rate
,
204 struct meson_clk_pll_data
*pll
)
207 return meson_clk_get_pll_range_index(rate
, parent_rate
,
210 return meson_clk_get_pll_table_index(index
, m
, n
, pll
);
215 static int meson_clk_get_pll_settings(unsigned long rate
,
216 unsigned long parent_rate
,
217 unsigned int *best_m
,
218 unsigned int *best_n
,
219 struct meson_clk_pll_data
*pll
)
221 unsigned long best
= 0, now
= 0;
222 unsigned int i
, m
, n
;
225 for (i
= 0, ret
= 0; !ret
; i
++) {
226 ret
= meson_clk_get_pll_get_index(rate
, parent_rate
,
231 now
= __pll_params_to_rate(parent_rate
, m
, n
, 0, pll
);
232 if (meson_clk_pll_is_better(rate
, best
, now
, pll
)) {
242 return best
? 0 : -EINVAL
;
245 static long meson_clk_pll_round_rate(struct clk_hw
*hw
, unsigned long rate
,
246 unsigned long *parent_rate
)
248 struct clk_regmap
*clk
= to_clk_regmap(hw
);
249 struct meson_clk_pll_data
*pll
= meson_clk_pll_data(clk
);
250 unsigned int m
, n
, frac
;
254 ret
= meson_clk_get_pll_settings(rate
, *parent_rate
, &m
, &n
, pll
);
256 return meson_clk_pll_recalc_rate(hw
, *parent_rate
);
258 round
= __pll_params_to_rate(*parent_rate
, m
, n
, 0, pll
);
260 if (!MESON_PARM_APPLICABLE(&pll
->frac
) || rate
== round
)
264 * The rate provided by the setting is not an exact match, let's
265 * try to improve the result using the fractional parameter
267 frac
= __pll_params_with_frac(rate
, *parent_rate
, m
, n
, pll
);
269 return __pll_params_to_rate(*parent_rate
, m
, n
, frac
, pll
);
272 static int meson_clk_pll_wait_lock(struct clk_hw
*hw
)
274 struct clk_regmap
*clk
= to_clk_regmap(hw
);
275 struct meson_clk_pll_data
*pll
= meson_clk_pll_data(clk
);
276 int delay
= 24000000;
279 /* Is the clock locked now ? */
280 if (meson_parm_read(clk
->map
, &pll
->l
))
289 static int meson_clk_pll_init(struct clk_hw
*hw
)
291 struct clk_regmap
*clk
= to_clk_regmap(hw
);
292 struct meson_clk_pll_data
*pll
= meson_clk_pll_data(clk
);
294 if (pll
->init_count
) {
295 meson_parm_write(clk
->map
, &pll
->rst
, 1);
296 regmap_multi_reg_write(clk
->map
, pll
->init_regs
,
298 meson_parm_write(clk
->map
, &pll
->rst
, 0);
304 static int meson_clk_pll_is_enabled(struct clk_hw
*hw
)
306 struct clk_regmap
*clk
= to_clk_regmap(hw
);
307 struct meson_clk_pll_data
*pll
= meson_clk_pll_data(clk
);
309 if (meson_parm_read(clk
->map
, &pll
->rst
) ||
310 !meson_parm_read(clk
->map
, &pll
->en
) ||
311 !meson_parm_read(clk
->map
, &pll
->l
))
317 static int meson_clk_pcie_pll_enable(struct clk_hw
*hw
)
319 meson_clk_pll_init(hw
);
321 if (meson_clk_pll_wait_lock(hw
))
327 static int meson_clk_pll_enable(struct clk_hw
*hw
)
329 struct clk_regmap
*clk
= to_clk_regmap(hw
);
330 struct meson_clk_pll_data
*pll
= meson_clk_pll_data(clk
);
332 /* do nothing if the PLL is already enabled */
333 if (clk_hw_is_enabled(hw
))
336 /* Make sure the pll is in reset */
337 meson_parm_write(clk
->map
, &pll
->rst
, 1);
340 meson_parm_write(clk
->map
, &pll
->en
, 1);
342 /* Take the pll out reset */
343 meson_parm_write(clk
->map
, &pll
->rst
, 0);
345 if (meson_clk_pll_wait_lock(hw
))
351 static void meson_clk_pll_disable(struct clk_hw
*hw
)
353 struct clk_regmap
*clk
= to_clk_regmap(hw
);
354 struct meson_clk_pll_data
*pll
= meson_clk_pll_data(clk
);
356 /* Put the pll is in reset */
357 meson_parm_write(clk
->map
, &pll
->rst
, 1);
359 /* Disable the pll */
360 meson_parm_write(clk
->map
, &pll
->en
, 0);
363 static int meson_clk_pll_set_rate(struct clk_hw
*hw
, unsigned long rate
,
364 unsigned long parent_rate
)
366 struct clk_regmap
*clk
= to_clk_regmap(hw
);
367 struct meson_clk_pll_data
*pll
= meson_clk_pll_data(clk
);
368 unsigned int enabled
, m
, n
, frac
= 0, ret
;
369 unsigned long old_rate
;
371 if (parent_rate
== 0 || rate
== 0)
376 ret
= meson_clk_get_pll_settings(rate
, parent_rate
, &m
, &n
, pll
);
380 enabled
= meson_parm_read(clk
->map
, &pll
->en
);
382 meson_clk_pll_disable(hw
);
384 meson_parm_write(clk
->map
, &pll
->n
, n
);
385 meson_parm_write(clk
->map
, &pll
->m
, m
);
387 if (MESON_PARM_APPLICABLE(&pll
->frac
)) {
388 frac
= __pll_params_with_frac(rate
, parent_rate
, m
, n
, pll
);
389 meson_parm_write(clk
->map
, &pll
->frac
, frac
);
392 /* If the pll is stopped, bail out now */
396 if (meson_clk_pll_enable(hw
)) {
397 pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
400 * FIXME: Do we really need/want this HACK ?
401 * It looks unsafe. what happens if the clock gets into a
402 * broken state and we can't lock back on the old_rate ? Looks
403 * like an infinite recursion is possible
405 meson_clk_pll_set_rate(hw
, old_rate
, parent_rate
);
412 * The Meson G12A PCIE PLL is fined tuned to deliver a very precise
413 * 100MHz reference clock for the PCIe Analog PHY, and thus requires
414 * a strict register sequence to enable the PLL.
415 * To simplify, re-use the _init() op to enable the PLL and keep
416 * the other ops except set_rate since the rate is fixed.
418 const struct clk_ops meson_clk_pcie_pll_ops
= {
419 .recalc_rate
= meson_clk_pll_recalc_rate
,
420 .round_rate
= meson_clk_pll_round_rate
,
421 .is_enabled
= meson_clk_pll_is_enabled
,
422 .enable
= meson_clk_pcie_pll_enable
,
423 .disable
= meson_clk_pll_disable
425 EXPORT_SYMBOL_GPL(meson_clk_pcie_pll_ops
);
427 const struct clk_ops meson_clk_pll_ops
= {
428 .init
= meson_clk_pll_init
,
429 .recalc_rate
= meson_clk_pll_recalc_rate
,
430 .round_rate
= meson_clk_pll_round_rate
,
431 .set_rate
= meson_clk_pll_set_rate
,
432 .is_enabled
= meson_clk_pll_is_enabled
,
433 .enable
= meson_clk_pll_enable
,
434 .disable
= meson_clk_pll_disable
436 EXPORT_SYMBOL_GPL(meson_clk_pll_ops
);
438 const struct clk_ops meson_clk_pll_ro_ops
= {
439 .recalc_rate
= meson_clk_pll_recalc_rate
,
440 .is_enabled
= meson_clk_pll_is_enabled
,
442 EXPORT_SYMBOL_GPL(meson_clk_pll_ro_ops
);
444 MODULE_DESCRIPTION("Amlogic PLL driver");
445 MODULE_AUTHOR("Carlo Caione <carlo@endlessm.com>");
446 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
447 MODULE_LICENSE("GPL v2");