1 | // SPDX-License-Identifier: (GPL-2.0 OR MIT) |
2 | /* |
3 | * Copyright 2018 NXP. |
4 | * |
5 | * This driver supports the SCCG plls found in the imx8m SOCs |
6 | * |
7 | * Documentation for this SCCG pll can be found at: |
8 | * https://www.nxp.com/docs/en/reference-manual/IMX8MDQLQRM.pdf#page=834 |
9 | */ |
10 | |
11 | #include <linux/clk-provider.h> |
12 | #include <linux/err.h> |
13 | #include <linux/export.h> |
14 | #include <linux/io.h> |
15 | #include <linux/iopoll.h> |
16 | #include <linux/slab.h> |
17 | #include <linux/bitfield.h> |
18 | |
19 | #include "clk.h" |
20 | |
21 | /* PLL CFGs */ |
22 | #define PLL_CFG0 0x0 |
23 | #define PLL_CFG1 0x4 |
24 | #define PLL_CFG2 0x8 |
25 | |
26 | #define PLL_DIVF1_MASK GENMASK(18, 13) |
27 | #define PLL_DIVF2_MASK GENMASK(12, 7) |
28 | #define PLL_DIVR1_MASK GENMASK(27, 25) |
29 | #define PLL_DIVR2_MASK GENMASK(24, 19) |
30 | #define PLL_DIVQ_MASK GENMASK(6, 1) |
31 | #define PLL_REF_MASK GENMASK(2, 0) |
32 | |
33 | #define PLL_LOCK_MASK BIT(31) |
34 | #define PLL_PD_MASK BIT(7) |
35 | |
36 | /* These are the specification limits for the SSCG PLL */ |
37 | #define PLL_REF_MIN_FREQ 25000000UL |
38 | #define PLL_REF_MAX_FREQ 235000000UL |
39 | |
40 | #define PLL_STAGE1_MIN_FREQ 1600000000UL |
41 | #define PLL_STAGE1_MAX_FREQ 2400000000UL |
42 | |
43 | #define PLL_STAGE1_REF_MIN_FREQ 25000000UL |
44 | #define PLL_STAGE1_REF_MAX_FREQ 54000000UL |
45 | |
46 | #define PLL_STAGE2_MIN_FREQ 1200000000UL |
47 | #define PLL_STAGE2_MAX_FREQ 2400000000UL |
48 | |
49 | #define PLL_STAGE2_REF_MIN_FREQ 54000000UL |
50 | #define PLL_STAGE2_REF_MAX_FREQ 75000000UL |
51 | |
52 | #define PLL_OUT_MIN_FREQ 20000000UL |
53 | #define PLL_OUT_MAX_FREQ 1200000000UL |
54 | |
55 | #define PLL_DIVR1_MAX 7 |
56 | #define PLL_DIVR2_MAX 63 |
57 | #define PLL_DIVF1_MAX 63 |
58 | #define PLL_DIVF2_MAX 63 |
59 | #define PLL_DIVQ_MAX 63 |
60 | |
61 | #define PLL_BYPASS_NONE 0x0 |
62 | #define PLL_BYPASS1 0x2 |
63 | #define PLL_BYPASS2 0x1 |
64 | |
65 | #define SSCG_PLL_BYPASS1_MASK BIT(5) |
66 | #define SSCG_PLL_BYPASS2_MASK BIT(4) |
67 | #define SSCG_PLL_BYPASS_MASK GENMASK(5, 4) |
68 | |
69 | #define PLL_SCCG_LOCK_TIMEOUT 70 |
70 | |
71 | struct clk_sscg_pll_setup { |
72 | int divr1, divf1; |
73 | int divr2, divf2; |
74 | int divq; |
75 | int bypass; |
76 | uint64_t vco1; |
77 | uint64_t vco2; |
78 | uint64_t fout; |
79 | uint64_t ref; |
80 | uint64_t ref_div1; |
81 | uint64_t ref_div2; |
82 | uint64_t fout_request; |
83 | int fout_error; |
84 | }; |
85 | |
86 | struct clk_sscg_pll { |
87 | struct clk_hw hw; |
88 | const struct clk_ops ops; |
89 | void __iomem *base; |
90 | struct clk_sscg_pll_setup setup; |
91 | u8 parent; |
92 | u8 bypass1; |
93 | u8 bypass2; |
94 | }; |
95 | |
96 | #define to_clk_sscg_pll(_hw) container_of(_hw, struct clk_sscg_pll, hw) |
97 | |
98 | static int clk_sscg_pll_wait_lock(struct clk_sscg_pll *pll) |
99 | { |
100 | u32 val; |
101 | |
102 | val = readl_relaxed(pll->base + PLL_CFG0); |
103 | |
104 | /* don't wait for lock if all plls are bypassed */ |
105 | if (!(val & SSCG_PLL_BYPASS2_MASK)) |
106 | return readl_poll_timeout(pll->base, val, val & PLL_LOCK_MASK, |
107 | 0, PLL_SCCG_LOCK_TIMEOUT); |
108 | |
109 | return 0; |
110 | } |
111 | |
112 | static int clk_sscg_pll2_check_match(struct clk_sscg_pll_setup *setup, |
113 | struct clk_sscg_pll_setup *temp_setup) |
114 | { |
115 | int new_diff = temp_setup->fout - temp_setup->fout_request; |
116 | int diff = temp_setup->fout_error; |
117 | |
118 | if (abs(diff) > abs(new_diff)) { |
119 | temp_setup->fout_error = new_diff; |
120 | memcpy(setup, temp_setup, sizeof(struct clk_sscg_pll_setup)); |
121 | |
122 | if (temp_setup->fout_request == temp_setup->fout) |
123 | return 0; |
124 | } |
125 | return -1; |
126 | } |
127 | |
128 | static int clk_sscg_divq_lookup(struct clk_sscg_pll_setup *setup, |
129 | struct clk_sscg_pll_setup *temp_setup) |
130 | { |
131 | int ret = -EINVAL; |
132 | |
133 | for (temp_setup->divq = 0; temp_setup->divq <= PLL_DIVQ_MAX; |
134 | temp_setup->divq++) { |
135 | temp_setup->vco2 = temp_setup->vco1; |
136 | do_div(temp_setup->vco2, temp_setup->divr2 + 1); |
137 | temp_setup->vco2 *= 2; |
138 | temp_setup->vco2 *= temp_setup->divf2 + 1; |
139 | if (temp_setup->vco2 >= PLL_STAGE2_MIN_FREQ && |
140 | temp_setup->vco2 <= PLL_STAGE2_MAX_FREQ) { |
141 | temp_setup->fout = temp_setup->vco2; |
142 | do_div(temp_setup->fout, 2 * (temp_setup->divq + 1)); |
143 | |
144 | ret = clk_sscg_pll2_check_match(setup, temp_setup); |
145 | if (!ret) { |
146 | temp_setup->bypass = PLL_BYPASS1; |
147 | return ret; |
148 | } |
149 | } |
150 | } |
151 | |
152 | return ret; |
153 | } |
154 | |
155 | static int clk_sscg_divf2_lookup(struct clk_sscg_pll_setup *setup, |
156 | struct clk_sscg_pll_setup *temp_setup) |
157 | { |
158 | int ret = -EINVAL; |
159 | |
160 | for (temp_setup->divf2 = 0; temp_setup->divf2 <= PLL_DIVF2_MAX; |
161 | temp_setup->divf2++) { |
162 | ret = clk_sscg_divq_lookup(setup, temp_setup); |
163 | if (!ret) |
164 | return ret; |
165 | } |
166 | |
167 | return ret; |
168 | } |
169 | |
170 | static int clk_sscg_divr2_lookup(struct clk_sscg_pll_setup *setup, |
171 | struct clk_sscg_pll_setup *temp_setup) |
172 | { |
173 | int ret = -EINVAL; |
174 | |
175 | for (temp_setup->divr2 = 0; temp_setup->divr2 <= PLL_DIVR2_MAX; |
176 | temp_setup->divr2++) { |
177 | temp_setup->ref_div2 = temp_setup->vco1; |
178 | do_div(temp_setup->ref_div2, temp_setup->divr2 + 1); |
179 | if (temp_setup->ref_div2 >= PLL_STAGE2_REF_MIN_FREQ && |
180 | temp_setup->ref_div2 <= PLL_STAGE2_REF_MAX_FREQ) { |
181 | ret = clk_sscg_divf2_lookup(setup, temp_setup); |
182 | if (!ret) |
183 | return ret; |
184 | } |
185 | } |
186 | |
187 | return ret; |
188 | } |
189 | |
190 | static int clk_sscg_pll2_find_setup(struct clk_sscg_pll_setup *setup, |
191 | struct clk_sscg_pll_setup *temp_setup, |
192 | uint64_t ref) |
193 | { |
194 | int ret; |
195 | |
196 | if (ref < PLL_STAGE1_MIN_FREQ || ref > PLL_STAGE1_MAX_FREQ) |
197 | return -EINVAL; |
198 | |
199 | temp_setup->vco1 = ref; |
200 | |
201 | ret = clk_sscg_divr2_lookup(setup, temp_setup); |
202 | return ret; |
203 | } |
204 | |
205 | static int clk_sscg_divf1_lookup(struct clk_sscg_pll_setup *setup, |
206 | struct clk_sscg_pll_setup *temp_setup) |
207 | { |
208 | int ret = -EINVAL; |
209 | |
210 | for (temp_setup->divf1 = 0; temp_setup->divf1 <= PLL_DIVF1_MAX; |
211 | temp_setup->divf1++) { |
212 | uint64_t vco1 = temp_setup->ref; |
213 | |
214 | do_div(vco1, temp_setup->divr1 + 1); |
215 | vco1 *= 2; |
216 | vco1 *= temp_setup->divf1 + 1; |
217 | |
218 | ret = clk_sscg_pll2_find_setup(setup, temp_setup, ref: vco1); |
219 | if (!ret) { |
220 | temp_setup->bypass = PLL_BYPASS_NONE; |
221 | return ret; |
222 | } |
223 | } |
224 | |
225 | return ret; |
226 | } |
227 | |
228 | static int clk_sscg_divr1_lookup(struct clk_sscg_pll_setup *setup, |
229 | struct clk_sscg_pll_setup *temp_setup) |
230 | { |
231 | int ret = -EINVAL; |
232 | |
233 | for (temp_setup->divr1 = 0; temp_setup->divr1 <= PLL_DIVR1_MAX; |
234 | temp_setup->divr1++) { |
235 | temp_setup->ref_div1 = temp_setup->ref; |
236 | do_div(temp_setup->ref_div1, temp_setup->divr1 + 1); |
237 | if (temp_setup->ref_div1 >= PLL_STAGE1_REF_MIN_FREQ && |
238 | temp_setup->ref_div1 <= PLL_STAGE1_REF_MAX_FREQ) { |
239 | ret = clk_sscg_divf1_lookup(setup, temp_setup); |
240 | if (!ret) |
241 | return ret; |
242 | } |
243 | } |
244 | |
245 | return ret; |
246 | } |
247 | |
248 | static int clk_sscg_pll1_find_setup(struct clk_sscg_pll_setup *setup, |
249 | struct clk_sscg_pll_setup *temp_setup, |
250 | uint64_t ref) |
251 | { |
252 | int ret; |
253 | |
254 | if (ref < PLL_REF_MIN_FREQ || ref > PLL_REF_MAX_FREQ) |
255 | return -EINVAL; |
256 | |
257 | temp_setup->ref = ref; |
258 | |
259 | ret = clk_sscg_divr1_lookup(setup, temp_setup); |
260 | |
261 | return ret; |
262 | } |
263 | |
264 | static int clk_sscg_pll_find_setup(struct clk_sscg_pll_setup *setup, |
265 | uint64_t prate, |
266 | uint64_t rate, int try_bypass) |
267 | { |
268 | struct clk_sscg_pll_setup temp_setup; |
269 | int ret = -EINVAL; |
270 | |
271 | memset(&temp_setup, 0, sizeof(struct clk_sscg_pll_setup)); |
272 | memset(setup, 0, sizeof(struct clk_sscg_pll_setup)); |
273 | |
274 | temp_setup.fout_error = PLL_OUT_MAX_FREQ; |
275 | temp_setup.fout_request = rate; |
276 | |
277 | switch (try_bypass) { |
278 | case PLL_BYPASS2: |
279 | if (prate == rate) { |
280 | setup->bypass = PLL_BYPASS2; |
281 | setup->fout = rate; |
282 | ret = 0; |
283 | } |
284 | break; |
285 | case PLL_BYPASS1: |
286 | ret = clk_sscg_pll2_find_setup(setup, temp_setup: &temp_setup, ref: prate); |
287 | break; |
288 | case PLL_BYPASS_NONE: |
289 | ret = clk_sscg_pll1_find_setup(setup, temp_setup: &temp_setup, ref: prate); |
290 | break; |
291 | } |
292 | |
293 | return ret; |
294 | } |
295 | |
296 | static int clk_sscg_pll_is_prepared(struct clk_hw *hw) |
297 | { |
298 | struct clk_sscg_pll *pll = to_clk_sscg_pll(hw); |
299 | |
300 | u32 val = readl_relaxed(pll->base + PLL_CFG0); |
301 | |
302 | return (val & PLL_PD_MASK) ? 0 : 1; |
303 | } |
304 | |
305 | static int clk_sscg_pll_prepare(struct clk_hw *hw) |
306 | { |
307 | struct clk_sscg_pll *pll = to_clk_sscg_pll(hw); |
308 | u32 val; |
309 | |
310 | val = readl_relaxed(pll->base + PLL_CFG0); |
311 | val &= ~PLL_PD_MASK; |
312 | writel_relaxed(val, pll->base + PLL_CFG0); |
313 | |
314 | return clk_sscg_pll_wait_lock(pll); |
315 | } |
316 | |
317 | static void clk_sscg_pll_unprepare(struct clk_hw *hw) |
318 | { |
319 | struct clk_sscg_pll *pll = to_clk_sscg_pll(hw); |
320 | u32 val; |
321 | |
322 | val = readl_relaxed(pll->base + PLL_CFG0); |
323 | val |= PLL_PD_MASK; |
324 | writel_relaxed(val, pll->base + PLL_CFG0); |
325 | } |
326 | |
327 | static unsigned long clk_sscg_pll_recalc_rate(struct clk_hw *hw, |
328 | unsigned long parent_rate) |
329 | { |
330 | struct clk_sscg_pll *pll = to_clk_sscg_pll(hw); |
331 | u32 val, divr1, divf1, divr2, divf2, divq; |
332 | u64 temp64; |
333 | |
334 | val = readl_relaxed(pll->base + PLL_CFG2); |
335 | divr1 = FIELD_GET(PLL_DIVR1_MASK, val); |
336 | divr2 = FIELD_GET(PLL_DIVR2_MASK, val); |
337 | divf1 = FIELD_GET(PLL_DIVF1_MASK, val); |
338 | divf2 = FIELD_GET(PLL_DIVF2_MASK, val); |
339 | divq = FIELD_GET(PLL_DIVQ_MASK, val); |
340 | |
341 | temp64 = parent_rate; |
342 | |
343 | val = readl(addr: pll->base + PLL_CFG0); |
344 | if (val & SSCG_PLL_BYPASS2_MASK) { |
345 | temp64 = parent_rate; |
346 | } else if (val & SSCG_PLL_BYPASS1_MASK) { |
347 | temp64 *= divf2; |
348 | do_div(temp64, (divr2 + 1) * (divq + 1)); |
349 | } else { |
350 | temp64 *= 2; |
351 | temp64 *= (divf1 + 1) * (divf2 + 1); |
352 | do_div(temp64, (divr1 + 1) * (divr2 + 1) * (divq + 1)); |
353 | } |
354 | |
355 | return temp64; |
356 | } |
357 | |
358 | static int clk_sscg_pll_set_rate(struct clk_hw *hw, unsigned long rate, |
359 | unsigned long parent_rate) |
360 | { |
361 | struct clk_sscg_pll *pll = to_clk_sscg_pll(hw); |
362 | struct clk_sscg_pll_setup *setup = &pll->setup; |
363 | u32 val; |
364 | |
365 | /* set bypass here too since the parent might be the same */ |
366 | val = readl(addr: pll->base + PLL_CFG0); |
367 | val &= ~SSCG_PLL_BYPASS_MASK; |
368 | val |= FIELD_PREP(SSCG_PLL_BYPASS_MASK, setup->bypass); |
369 | writel(val, addr: pll->base + PLL_CFG0); |
370 | |
371 | val = readl_relaxed(pll->base + PLL_CFG2); |
372 | val &= ~(PLL_DIVF1_MASK | PLL_DIVF2_MASK); |
373 | val &= ~(PLL_DIVR1_MASK | PLL_DIVR2_MASK | PLL_DIVQ_MASK); |
374 | val |= FIELD_PREP(PLL_DIVF1_MASK, setup->divf1); |
375 | val |= FIELD_PREP(PLL_DIVF2_MASK, setup->divf2); |
376 | val |= FIELD_PREP(PLL_DIVR1_MASK, setup->divr1); |
377 | val |= FIELD_PREP(PLL_DIVR2_MASK, setup->divr2); |
378 | val |= FIELD_PREP(PLL_DIVQ_MASK, setup->divq); |
379 | writel_relaxed(val, pll->base + PLL_CFG2); |
380 | |
381 | return clk_sscg_pll_wait_lock(pll); |
382 | } |
383 | |
384 | static u8 clk_sscg_pll_get_parent(struct clk_hw *hw) |
385 | { |
386 | struct clk_sscg_pll *pll = to_clk_sscg_pll(hw); |
387 | u32 val; |
388 | u8 ret = pll->parent; |
389 | |
390 | val = readl(addr: pll->base + PLL_CFG0); |
391 | if (val & SSCG_PLL_BYPASS2_MASK) |
392 | ret = pll->bypass2; |
393 | else if (val & SSCG_PLL_BYPASS1_MASK) |
394 | ret = pll->bypass1; |
395 | return ret; |
396 | } |
397 | |
398 | static int clk_sscg_pll_set_parent(struct clk_hw *hw, u8 index) |
399 | { |
400 | struct clk_sscg_pll *pll = to_clk_sscg_pll(hw); |
401 | u32 val; |
402 | |
403 | val = readl(addr: pll->base + PLL_CFG0); |
404 | val &= ~SSCG_PLL_BYPASS_MASK; |
405 | val |= FIELD_PREP(SSCG_PLL_BYPASS_MASK, pll->setup.bypass); |
406 | writel(val, addr: pll->base + PLL_CFG0); |
407 | |
408 | return clk_sscg_pll_wait_lock(pll); |
409 | } |
410 | |
411 | static int __clk_sscg_pll_determine_rate(struct clk_hw *hw, |
412 | struct clk_rate_request *req, |
413 | uint64_t min, |
414 | uint64_t max, |
415 | uint64_t rate, |
416 | int bypass) |
417 | { |
418 | struct clk_sscg_pll *pll = to_clk_sscg_pll(hw); |
419 | struct clk_sscg_pll_setup *setup = &pll->setup; |
420 | struct clk_hw *parent_hw = NULL; |
421 | int bypass_parent_index; |
422 | int ret; |
423 | |
424 | req->max_rate = max; |
425 | req->min_rate = min; |
426 | |
427 | switch (bypass) { |
428 | case PLL_BYPASS2: |
429 | bypass_parent_index = pll->bypass2; |
430 | break; |
431 | case PLL_BYPASS1: |
432 | bypass_parent_index = pll->bypass1; |
433 | break; |
434 | default: |
435 | bypass_parent_index = pll->parent; |
436 | break; |
437 | } |
438 | |
439 | parent_hw = clk_hw_get_parent_by_index(hw, index: bypass_parent_index); |
440 | ret = __clk_determine_rate(core: parent_hw, req); |
441 | if (!ret) { |
442 | ret = clk_sscg_pll_find_setup(setup, prate: req->rate, |
443 | rate, try_bypass: bypass); |
444 | } |
445 | |
446 | req->best_parent_hw = parent_hw; |
447 | req->best_parent_rate = req->rate; |
448 | req->rate = setup->fout; |
449 | |
450 | return ret; |
451 | } |
452 | |
453 | static int clk_sscg_pll_determine_rate(struct clk_hw *hw, |
454 | struct clk_rate_request *req) |
455 | { |
456 | struct clk_sscg_pll *pll = to_clk_sscg_pll(hw); |
457 | struct clk_sscg_pll_setup *setup = &pll->setup; |
458 | uint64_t rate = req->rate; |
459 | uint64_t min = req->min_rate; |
460 | uint64_t max = req->max_rate; |
461 | int ret; |
462 | |
463 | if (rate < PLL_OUT_MIN_FREQ || rate > PLL_OUT_MAX_FREQ) |
464 | return -EINVAL; |
465 | |
466 | ret = __clk_sscg_pll_determine_rate(hw, req, min: req->rate, max: req->rate, |
467 | rate, PLL_BYPASS2); |
468 | if (!ret) |
469 | return ret; |
470 | |
471 | ret = __clk_sscg_pll_determine_rate(hw, req, PLL_STAGE1_REF_MIN_FREQ, |
472 | PLL_STAGE1_REF_MAX_FREQ, rate, |
473 | PLL_BYPASS1); |
474 | if (!ret) |
475 | return ret; |
476 | |
477 | ret = __clk_sscg_pll_determine_rate(hw, req, PLL_REF_MIN_FREQ, |
478 | PLL_REF_MAX_FREQ, rate, |
479 | PLL_BYPASS_NONE); |
480 | if (!ret) |
481 | return ret; |
482 | |
483 | if (setup->fout >= min && setup->fout <= max) |
484 | ret = 0; |
485 | |
486 | return ret; |
487 | } |
488 | |
489 | static const struct clk_ops clk_sscg_pll_ops = { |
490 | .prepare = clk_sscg_pll_prepare, |
491 | .unprepare = clk_sscg_pll_unprepare, |
492 | .is_prepared = clk_sscg_pll_is_prepared, |
493 | .recalc_rate = clk_sscg_pll_recalc_rate, |
494 | .set_rate = clk_sscg_pll_set_rate, |
495 | .set_parent = clk_sscg_pll_set_parent, |
496 | .get_parent = clk_sscg_pll_get_parent, |
497 | .determine_rate = clk_sscg_pll_determine_rate, |
498 | }; |
499 | |
500 | struct clk_hw *imx_clk_hw_sscg_pll(const char *name, |
501 | const char * const *parent_names, |
502 | u8 num_parents, |
503 | u8 parent, u8 bypass1, u8 bypass2, |
504 | void __iomem *base, |
505 | unsigned long flags) |
506 | { |
507 | struct clk_sscg_pll *pll; |
508 | struct clk_init_data init; |
509 | struct clk_hw *hw; |
510 | int ret; |
511 | |
512 | pll = kzalloc(size: sizeof(*pll), GFP_KERNEL); |
513 | if (!pll) |
514 | return ERR_PTR(error: -ENOMEM); |
515 | |
516 | pll->parent = parent; |
517 | pll->bypass1 = bypass1; |
518 | pll->bypass2 = bypass2; |
519 | |
520 | pll->base = base; |
521 | init.name = name; |
522 | init.ops = &clk_sscg_pll_ops; |
523 | |
524 | init.flags = flags; |
525 | init.parent_names = parent_names; |
526 | init.num_parents = num_parents; |
527 | |
528 | pll->hw.init = &init; |
529 | |
530 | hw = &pll->hw; |
531 | |
532 | ret = clk_hw_register(NULL, hw); |
533 | if (ret) { |
534 | kfree(objp: pll); |
535 | return ERR_PTR(error: ret); |
536 | } |
537 | |
538 | return hw; |
539 | } |
540 | EXPORT_SYMBOL_GPL(imx_clk_hw_sscg_pll); |
541 | |