1
2
3
4
5
6
7
8
9#define pr_fmt(fmt) "%s: " fmt, __func__
10
11#include <linux/clk-provider.h>
12#include <linux/io.h>
13#include <linux/kernel.h>
14#include <linux/printk.h>
15#include <linux/slab.h>
16
17#include "clk.h"
18
19#define PLL_STATUS 0x0
20#define PLL_STATUS_LOCK BIT(0)
21
22#define PLL_CTRL1 0x4
23#define PLL_CTRL1_REFDIV_SHIFT 0
24#define PLL_CTRL1_REFDIV_MASK 0x3f
25#define PLL_CTRL1_FBDIV_SHIFT 6
26#define PLL_CTRL1_FBDIV_MASK 0xfff
27#define PLL_INT_CTRL1_POSTDIV1_SHIFT 18
28#define PLL_INT_CTRL1_POSTDIV1_MASK 0x7
29#define PLL_INT_CTRL1_POSTDIV2_SHIFT 21
30#define PLL_INT_CTRL1_POSTDIV2_MASK 0x7
31#define PLL_INT_CTRL1_PD BIT(24)
32#define PLL_INT_CTRL1_DSMPD BIT(25)
33#define PLL_INT_CTRL1_FOUTPOSTDIVPD BIT(26)
34#define PLL_INT_CTRL1_FOUTVCOPD BIT(27)
35
36#define PLL_CTRL2 0x8
37#define PLL_FRAC_CTRL2_FRAC_SHIFT 0
38#define PLL_FRAC_CTRL2_FRAC_MASK 0xffffff
39#define PLL_FRAC_CTRL2_POSTDIV1_SHIFT 24
40#define PLL_FRAC_CTRL2_POSTDIV1_MASK 0x7
41#define PLL_FRAC_CTRL2_POSTDIV2_SHIFT 27
42#define PLL_FRAC_CTRL2_POSTDIV2_MASK 0x7
43#define PLL_INT_CTRL2_BYPASS BIT(28)
44
45#define PLL_CTRL3 0xc
46#define PLL_FRAC_CTRL3_PD BIT(0)
47#define PLL_FRAC_CTRL3_DACPD BIT(1)
48#define PLL_FRAC_CTRL3_DSMPD BIT(2)
49#define PLL_FRAC_CTRL3_FOUTPOSTDIVPD BIT(3)
50#define PLL_FRAC_CTRL3_FOUT4PHASEPD BIT(4)
51#define PLL_FRAC_CTRL3_FOUTVCOPD BIT(5)
52
53#define PLL_CTRL4 0x10
54#define PLL_FRAC_CTRL4_BYPASS BIT(28)
55
56#define MIN_PFD 9600000UL
57#define MIN_VCO_LA 400000000UL
58#define MAX_VCO_LA 1600000000UL
59#define MIN_VCO_FRAC_INT 600000000UL
60#define MAX_VCO_FRAC_INT 1600000000UL
61#define MIN_VCO_FRAC_FRAC 600000000UL
62#define MAX_VCO_FRAC_FRAC 2400000000UL
63#define MIN_OUTPUT_LA 8000000UL
64#define MAX_OUTPUT_LA 1600000000UL
65#define MIN_OUTPUT_FRAC 12000000UL
66#define MAX_OUTPUT_FRAC 1600000000UL
67
68
69enum pll_mode {
70 PLL_MODE_FRAC,
71 PLL_MODE_INT,
72};
73
74struct pistachio_clk_pll {
75 struct clk_hw hw;
76 void __iomem *base;
77 struct pistachio_pll_rate_table *rates;
78 unsigned int nr_rates;
79};
80
81static inline u32 pll_readl(struct pistachio_clk_pll *pll, u32 reg)
82{
83 return readl(pll->base + reg);
84}
85
86static inline void pll_writel(struct pistachio_clk_pll *pll, u32 val, u32 reg)
87{
88 writel(val, pll->base + reg);
89}
90
91static inline void pll_lock(struct pistachio_clk_pll *pll)
92{
93 while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK))
94 cpu_relax();
95}
96
97static inline u64 do_div_round_closest(u64 dividend, u64 divisor)
98{
99 dividend += divisor / 2;
100 return div64_u64(dividend, divisor);
101}
102
103static inline struct pistachio_clk_pll *to_pistachio_pll(struct clk_hw *hw)
104{
105 return container_of(hw, struct pistachio_clk_pll, hw);
106}
107
108static inline enum pll_mode pll_frac_get_mode(struct clk_hw *hw)
109{
110 struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
111 u32 val;
112
113 val = pll_readl(pll, PLL_CTRL3) & PLL_FRAC_CTRL3_DSMPD;
114 return val ? PLL_MODE_INT : PLL_MODE_FRAC;
115}
116
117static inline void pll_frac_set_mode(struct clk_hw *hw, enum pll_mode mode)
118{
119 struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
120 u32 val;
121
122 val = pll_readl(pll, PLL_CTRL3);
123 if (mode == PLL_MODE_INT)
124 val |= PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_DACPD;
125 else
126 val &= ~(PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_DACPD);
127
128 pll_writel(pll, val, PLL_CTRL3);
129}
130
131static struct pistachio_pll_rate_table *
132pll_get_params(struct pistachio_clk_pll *pll, unsigned long fref,
133 unsigned long fout)
134{
135 unsigned int i;
136
137 for (i = 0; i < pll->nr_rates; i++) {
138 if (pll->rates[i].fref == fref && pll->rates[i].fout == fout)
139 return &pll->rates[i];
140 }
141
142 return NULL;
143}
144
145static long pll_round_rate(struct clk_hw *hw, unsigned long rate,
146 unsigned long *parent_rate)
147{
148 struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
149 unsigned int i;
150
151 for (i = 0; i < pll->nr_rates; i++) {
152 if (i > 0 && pll->rates[i].fref == *parent_rate &&
153 pll->rates[i].fout <= rate)
154 return pll->rates[i - 1].fout;
155 }
156
157 return pll->rates[0].fout;
158}
159
160static int pll_gf40lp_frac_enable(struct clk_hw *hw)
161{
162 struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
163 u32 val;
164
165 val = pll_readl(pll, PLL_CTRL3);
166 val &= ~(PLL_FRAC_CTRL3_PD | PLL_FRAC_CTRL3_FOUTPOSTDIVPD |
167 PLL_FRAC_CTRL3_FOUT4PHASEPD | PLL_FRAC_CTRL3_FOUTVCOPD);
168 pll_writel(pll, val, PLL_CTRL3);
169
170 val = pll_readl(pll, PLL_CTRL4);
171 val &= ~PLL_FRAC_CTRL4_BYPASS;
172 pll_writel(pll, val, PLL_CTRL4);
173
174 pll_lock(pll);
175
176 return 0;
177}
178
179static void pll_gf40lp_frac_disable(struct clk_hw *hw)
180{
181 struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
182 u32 val;
183
184 val = pll_readl(pll, PLL_CTRL3);
185 val |= PLL_FRAC_CTRL3_PD;
186 pll_writel(pll, val, PLL_CTRL3);
187}
188
189static int pll_gf40lp_frac_is_enabled(struct clk_hw *hw)
190{
191 struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
192
193 return !(pll_readl(pll, PLL_CTRL3) & PLL_FRAC_CTRL3_PD);
194}
195
196static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
197 unsigned long parent_rate)
198{
199 struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
200 struct pistachio_pll_rate_table *params;
201 int enabled = pll_gf40lp_frac_is_enabled(hw);
202 u64 val, vco, old_postdiv1, old_postdiv2;
203 const char *name = clk_hw_get_name(hw);
204
205 if (rate < MIN_OUTPUT_FRAC || rate > MAX_OUTPUT_FRAC)
206 return -EINVAL;
207
208 params = pll_get_params(pll, parent_rate, rate);
209 if (!params || !params->refdiv)
210 return -EINVAL;
211
212
213 vco = params->fref;
214 vco *= (params->fbdiv << 24) + params->frac;
215 vco = div64_u64(vco, params->refdiv << 24);
216
217 if (vco < MIN_VCO_FRAC_FRAC || vco > MAX_VCO_FRAC_FRAC)
218 pr_warn("%s: VCO %llu is out of range %lu..%lu\n", name, vco,
219 MIN_VCO_FRAC_FRAC, MAX_VCO_FRAC_FRAC);
220
221 val = div64_u64(params->fref, params->refdiv);
222 if (val < MIN_PFD)
223 pr_warn("%s: PFD %llu is too low (min %lu)\n",
224 name, val, MIN_PFD);
225 if (val > vco / 16)
226 pr_warn("%s: PFD %llu is too high (max %llu)\n",
227 name, val, vco / 16);
228
229 val = pll_readl(pll, PLL_CTRL1);
230 val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) |
231 (PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT));
232 val |= (params->refdiv << PLL_CTRL1_REFDIV_SHIFT) |
233 (params->fbdiv << PLL_CTRL1_FBDIV_SHIFT);
234 pll_writel(pll, val, PLL_CTRL1);
235
236 val = pll_readl(pll, PLL_CTRL2);
237
238 old_postdiv1 = (val >> PLL_FRAC_CTRL2_POSTDIV1_SHIFT) &
239 PLL_FRAC_CTRL2_POSTDIV1_MASK;
240 old_postdiv2 = (val >> PLL_FRAC_CTRL2_POSTDIV2_SHIFT) &
241 PLL_FRAC_CTRL2_POSTDIV2_MASK;
242 if (enabled &&
243 (params->postdiv1 != old_postdiv1 ||
244 params->postdiv2 != old_postdiv2))
245 pr_warn("%s: changing postdiv while PLL is enabled\n", name);
246
247 if (params->postdiv2 > params->postdiv1)
248 pr_warn("%s: postdiv2 should not exceed postdiv1\n", name);
249
250 val &= ~((PLL_FRAC_CTRL2_FRAC_MASK << PLL_FRAC_CTRL2_FRAC_SHIFT) |
251 (PLL_FRAC_CTRL2_POSTDIV1_MASK <<
252 PLL_FRAC_CTRL2_POSTDIV1_SHIFT) |
253 (PLL_FRAC_CTRL2_POSTDIV2_MASK <<
254 PLL_FRAC_CTRL2_POSTDIV2_SHIFT));
255 val |= (params->frac << PLL_FRAC_CTRL2_FRAC_SHIFT) |
256 (params->postdiv1 << PLL_FRAC_CTRL2_POSTDIV1_SHIFT) |
257 (params->postdiv2 << PLL_FRAC_CTRL2_POSTDIV2_SHIFT);
258 pll_writel(pll, val, PLL_CTRL2);
259
260
261 if (params->frac)
262 pll_frac_set_mode(hw, PLL_MODE_FRAC);
263 else
264 pll_frac_set_mode(hw, PLL_MODE_INT);
265
266 if (enabled)
267 pll_lock(pll);
268
269 return 0;
270}
271
272static unsigned long pll_gf40lp_frac_recalc_rate(struct clk_hw *hw,
273 unsigned long parent_rate)
274{
275 struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
276 u64 val, prediv, fbdiv, frac, postdiv1, postdiv2, rate;
277
278 val = pll_readl(pll, PLL_CTRL1);
279 prediv = (val >> PLL_CTRL1_REFDIV_SHIFT) & PLL_CTRL1_REFDIV_MASK;
280 fbdiv = (val >> PLL_CTRL1_FBDIV_SHIFT) & PLL_CTRL1_FBDIV_MASK;
281
282 val = pll_readl(pll, PLL_CTRL2);
283 postdiv1 = (val >> PLL_FRAC_CTRL2_POSTDIV1_SHIFT) &
284 PLL_FRAC_CTRL2_POSTDIV1_MASK;
285 postdiv2 = (val >> PLL_FRAC_CTRL2_POSTDIV2_SHIFT) &
286 PLL_FRAC_CTRL2_POSTDIV2_MASK;
287 frac = (val >> PLL_FRAC_CTRL2_FRAC_SHIFT) & PLL_FRAC_CTRL2_FRAC_MASK;
288
289
290 rate = parent_rate;
291 if (pll_frac_get_mode(hw) == PLL_MODE_FRAC)
292 rate *= (fbdiv << 24) + frac;
293 else
294 rate *= (fbdiv << 24);
295
296 rate = do_div_round_closest(rate, (prediv * postdiv1 * postdiv2) << 24);
297
298 return rate;
299}
300
301static struct clk_ops pll_gf40lp_frac_ops = {
302 .enable = pll_gf40lp_frac_enable,
303 .disable = pll_gf40lp_frac_disable,
304 .is_enabled = pll_gf40lp_frac_is_enabled,
305 .recalc_rate = pll_gf40lp_frac_recalc_rate,
306 .round_rate = pll_round_rate,
307 .set_rate = pll_gf40lp_frac_set_rate,
308};
309
310static struct clk_ops pll_gf40lp_frac_fixed_ops = {
311 .enable = pll_gf40lp_frac_enable,
312 .disable = pll_gf40lp_frac_disable,
313 .is_enabled = pll_gf40lp_frac_is_enabled,
314 .recalc_rate = pll_gf40lp_frac_recalc_rate,
315};
316
317static int pll_gf40lp_laint_enable(struct clk_hw *hw)
318{
319 struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
320 u32 val;
321
322 val = pll_readl(pll, PLL_CTRL1);
323 val &= ~(PLL_INT_CTRL1_PD |
324 PLL_INT_CTRL1_FOUTPOSTDIVPD | PLL_INT_CTRL1_FOUTVCOPD);
325 pll_writel(pll, val, PLL_CTRL1);
326
327 val = pll_readl(pll, PLL_CTRL2);
328 val &= ~PLL_INT_CTRL2_BYPASS;
329 pll_writel(pll, val, PLL_CTRL2);
330
331 pll_lock(pll);
332
333 return 0;
334}
335
336static void pll_gf40lp_laint_disable(struct clk_hw *hw)
337{
338 struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
339 u32 val;
340
341 val = pll_readl(pll, PLL_CTRL1);
342 val |= PLL_INT_CTRL1_PD;
343 pll_writel(pll, val, PLL_CTRL1);
344}
345
346static int pll_gf40lp_laint_is_enabled(struct clk_hw *hw)
347{
348 struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
349
350 return !(pll_readl(pll, PLL_CTRL1) & PLL_INT_CTRL1_PD);
351}
352
353static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate,
354 unsigned long parent_rate)
355{
356 struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
357 struct pistachio_pll_rate_table *params;
358 int enabled = pll_gf40lp_laint_is_enabled(hw);
359 u32 val, vco, old_postdiv1, old_postdiv2;
360 const char *name = clk_hw_get_name(hw);
361
362 if (rate < MIN_OUTPUT_LA || rate > MAX_OUTPUT_LA)
363 return -EINVAL;
364
365 params = pll_get_params(pll, parent_rate, rate);
366 if (!params || !params->refdiv)
367 return -EINVAL;
368
369 vco = div_u64(params->fref * params->fbdiv, params->refdiv);
370 if (vco < MIN_VCO_LA || vco > MAX_VCO_LA)
371 pr_warn("%s: VCO %u is out of range %lu..%lu\n", name, vco,
372 MIN_VCO_LA, MAX_VCO_LA);
373
374 val = div_u64(params->fref, params->refdiv);
375 if (val < MIN_PFD)
376 pr_warn("%s: PFD %u is too low (min %lu)\n",
377 name, val, MIN_PFD);
378 if (val > vco / 16)
379 pr_warn("%s: PFD %u is too high (max %u)\n",
380 name, val, vco / 16);
381
382 val = pll_readl(pll, PLL_CTRL1);
383
384 old_postdiv1 = (val >> PLL_INT_CTRL1_POSTDIV1_SHIFT) &
385 PLL_INT_CTRL1_POSTDIV1_MASK;
386 old_postdiv2 = (val >> PLL_INT_CTRL1_POSTDIV2_SHIFT) &
387 PLL_INT_CTRL1_POSTDIV2_MASK;
388 if (enabled &&
389 (params->postdiv1 != old_postdiv1 ||
390 params->postdiv2 != old_postdiv2))
391 pr_warn("%s: changing postdiv while PLL is enabled\n", name);
392
393 if (params->postdiv2 > params->postdiv1)
394 pr_warn("%s: postdiv2 should not exceed postdiv1\n", name);
395
396 val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) |
397 (PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT) |
398 (PLL_INT_CTRL1_POSTDIV1_MASK << PLL_INT_CTRL1_POSTDIV1_SHIFT) |
399 (PLL_INT_CTRL1_POSTDIV2_MASK << PLL_INT_CTRL1_POSTDIV2_SHIFT));
400 val |= (params->refdiv << PLL_CTRL1_REFDIV_SHIFT) |
401 (params->fbdiv << PLL_CTRL1_FBDIV_SHIFT) |
402 (params->postdiv1 << PLL_INT_CTRL1_POSTDIV1_SHIFT) |
403 (params->postdiv2 << PLL_INT_CTRL1_POSTDIV2_SHIFT);
404 pll_writel(pll, val, PLL_CTRL1);
405
406 if (enabled)
407 pll_lock(pll);
408
409 return 0;
410}
411
412static unsigned long pll_gf40lp_laint_recalc_rate(struct clk_hw *hw,
413 unsigned long parent_rate)
414{
415 struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
416 u32 val, prediv, fbdiv, postdiv1, postdiv2;
417 u64 rate = parent_rate;
418
419 val = pll_readl(pll, PLL_CTRL1);
420 prediv = (val >> PLL_CTRL1_REFDIV_SHIFT) & PLL_CTRL1_REFDIV_MASK;
421 fbdiv = (val >> PLL_CTRL1_FBDIV_SHIFT) & PLL_CTRL1_FBDIV_MASK;
422 postdiv1 = (val >> PLL_INT_CTRL1_POSTDIV1_SHIFT) &
423 PLL_INT_CTRL1_POSTDIV1_MASK;
424 postdiv2 = (val >> PLL_INT_CTRL1_POSTDIV2_SHIFT) &
425 PLL_INT_CTRL1_POSTDIV2_MASK;
426
427 rate *= fbdiv;
428 rate = do_div_round_closest(rate, prediv * postdiv1 * postdiv2);
429
430 return rate;
431}
432
433static struct clk_ops pll_gf40lp_laint_ops = {
434 .enable = pll_gf40lp_laint_enable,
435 .disable = pll_gf40lp_laint_disable,
436 .is_enabled = pll_gf40lp_laint_is_enabled,
437 .recalc_rate = pll_gf40lp_laint_recalc_rate,
438 .round_rate = pll_round_rate,
439 .set_rate = pll_gf40lp_laint_set_rate,
440};
441
442static struct clk_ops pll_gf40lp_laint_fixed_ops = {
443 .enable = pll_gf40lp_laint_enable,
444 .disable = pll_gf40lp_laint_disable,
445 .is_enabled = pll_gf40lp_laint_is_enabled,
446 .recalc_rate = pll_gf40lp_laint_recalc_rate,
447};
448
449static struct clk *pll_register(const char *name, const char *parent_name,
450 unsigned long flags, void __iomem *base,
451 enum pistachio_pll_type type,
452 struct pistachio_pll_rate_table *rates,
453 unsigned int nr_rates)
454{
455 struct pistachio_clk_pll *pll;
456 struct clk_init_data init;
457 struct clk *clk;
458
459 pll = kzalloc(sizeof(*pll), GFP_KERNEL);
460 if (!pll)
461 return ERR_PTR(-ENOMEM);
462
463 init.name = name;
464 init.flags = flags | CLK_GET_RATE_NOCACHE;
465 init.parent_names = &parent_name;
466 init.num_parents = 1;
467
468 switch (type) {
469 case PLL_GF40LP_FRAC:
470 if (rates)
471 init.ops = &pll_gf40lp_frac_ops;
472 else
473 init.ops = &pll_gf40lp_frac_fixed_ops;
474 break;
475 case PLL_GF40LP_LAINT:
476 if (rates)
477 init.ops = &pll_gf40lp_laint_ops;
478 else
479 init.ops = &pll_gf40lp_laint_fixed_ops;
480 break;
481 default:
482 pr_err("Unrecognized PLL type %u\n", type);
483 kfree(pll);
484 return ERR_PTR(-EINVAL);
485 }
486
487 pll->hw.init = &init;
488 pll->base = base;
489 pll->rates = rates;
490 pll->nr_rates = nr_rates;
491
492 clk = clk_register(NULL, &pll->hw);
493 if (IS_ERR(clk))
494 kfree(pll);
495
496 return clk;
497}
498
499void pistachio_clk_register_pll(struct pistachio_clk_provider *p,
500 struct pistachio_pll *pll,
501 unsigned int num)
502{
503 struct clk *clk;
504 unsigned int i;
505
506 for (i = 0; i < num; i++) {
507 clk = pll_register(pll[i].name, pll[i].parent,
508 0, p->base + pll[i].reg_base,
509 pll[i].type, pll[i].rates,
510 pll[i].nr_rates);
511 p->clk_data.clks[pll[i].id] = clk;
512 }
513}
514