1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
4 * Copyright (c) 2013 Linaro Ltd.
5 *
6 * This file contains the utility functions to register the pll clocks.
7 */
8
9 #include <linux/errno.h>
10 #include <linux/hrtimer.h>
11 #include <linux/delay.h>
12 #include <linux/slab.h>
13 #include <linux/clk-provider.h>
14 #include <linux/io.h>
15 #include "clk.h"
16 #include "clk-pll.h"
17
18 #define PLL_TIMEOUT_MS 10
19
20 struct samsung_clk_pll {
21 struct clk_hw hw;
22 void __iomem *lock_reg;
23 void __iomem *con_reg;
24 /* PLL enable control bit offset in @con_reg register */
25 unsigned short enable_offs;
26 /* PLL lock status bit offset in @con_reg register */
27 unsigned short lock_offs;
28 enum samsung_pll_type type;
29 unsigned int rate_count;
30 const struct samsung_pll_rate_table *rate_table;
31 };
32
33 #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
34
samsung_get_pll_settings(struct samsung_clk_pll * pll,unsigned long rate)35 static const struct samsung_pll_rate_table *samsung_get_pll_settings(
36 struct samsung_clk_pll *pll, unsigned long rate)
37 {
38 const struct samsung_pll_rate_table *rate_table = pll->rate_table;
39 int i;
40
41 for (i = 0; i < pll->rate_count; i++) {
42 if (rate == rate_table[i].rate)
43 return &rate_table[i];
44 }
45
46 return NULL;
47 }
48
samsung_pll_round_rate(struct clk_hw * hw,unsigned long drate,unsigned long * prate)49 static long samsung_pll_round_rate(struct clk_hw *hw,
50 unsigned long drate, unsigned long *prate)
51 {
52 struct samsung_clk_pll *pll = to_clk_pll(hw);
53 const struct samsung_pll_rate_table *rate_table = pll->rate_table;
54 int i;
55
56 /* Assumming rate_table is in descending order */
57 for (i = 0; i < pll->rate_count; i++) {
58 if (drate >= rate_table[i].rate)
59 return rate_table[i].rate;
60 }
61
62 /* return minimum supported value */
63 return rate_table[i - 1].rate;
64 }
65
samsung_pll3xxx_enable(struct clk_hw * hw)66 static int samsung_pll3xxx_enable(struct clk_hw *hw)
67 {
68 struct samsung_clk_pll *pll = to_clk_pll(hw);
69 u32 tmp;
70
71 tmp = readl_relaxed(pll->con_reg);
72 tmp |= BIT(pll->enable_offs);
73 writel_relaxed(tmp, pll->con_reg);
74
75 /* wait lock time */
76 do {
77 cpu_relax();
78 tmp = readl_relaxed(pll->con_reg);
79 } while (!(tmp & BIT(pll->lock_offs)));
80
81 return 0;
82 }
83
samsung_pll3xxx_disable(struct clk_hw * hw)84 static void samsung_pll3xxx_disable(struct clk_hw *hw)
85 {
86 struct samsung_clk_pll *pll = to_clk_pll(hw);
87 u32 tmp;
88
89 tmp = readl_relaxed(pll->con_reg);
90 tmp &= ~BIT(pll->enable_offs);
91 writel_relaxed(tmp, pll->con_reg);
92 }
93
94 /*
95 * PLL2126 Clock Type
96 */
97
98 #define PLL2126_MDIV_MASK (0xff)
99 #define PLL2126_PDIV_MASK (0x3f)
100 #define PLL2126_SDIV_MASK (0x3)
101 #define PLL2126_MDIV_SHIFT (16)
102 #define PLL2126_PDIV_SHIFT (8)
103 #define PLL2126_SDIV_SHIFT (0)
104
samsung_pll2126_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)105 static unsigned long samsung_pll2126_recalc_rate(struct clk_hw *hw,
106 unsigned long parent_rate)
107 {
108 struct samsung_clk_pll *pll = to_clk_pll(hw);
109 u32 pll_con, mdiv, pdiv, sdiv;
110 u64 fvco = parent_rate;
111
112 pll_con = readl_relaxed(pll->con_reg);
113 mdiv = (pll_con >> PLL2126_MDIV_SHIFT) & PLL2126_MDIV_MASK;
114 pdiv = (pll_con >> PLL2126_PDIV_SHIFT) & PLL2126_PDIV_MASK;
115 sdiv = (pll_con >> PLL2126_SDIV_SHIFT) & PLL2126_SDIV_MASK;
116
117 fvco *= (mdiv + 8);
118 do_div(fvco, (pdiv + 2) << sdiv);
119
120 return (unsigned long)fvco;
121 }
122
123 static const struct clk_ops samsung_pll2126_clk_ops = {
124 .recalc_rate = samsung_pll2126_recalc_rate,
125 };
126
127 /*
128 * PLL3000 Clock Type
129 */
130
131 #define PLL3000_MDIV_MASK (0xff)
132 #define PLL3000_PDIV_MASK (0x3)
133 #define PLL3000_SDIV_MASK (0x3)
134 #define PLL3000_MDIV_SHIFT (16)
135 #define PLL3000_PDIV_SHIFT (8)
136 #define PLL3000_SDIV_SHIFT (0)
137
samsung_pll3000_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)138 static unsigned long samsung_pll3000_recalc_rate(struct clk_hw *hw,
139 unsigned long parent_rate)
140 {
141 struct samsung_clk_pll *pll = to_clk_pll(hw);
142 u32 pll_con, mdiv, pdiv, sdiv;
143 u64 fvco = parent_rate;
144
145 pll_con = readl_relaxed(pll->con_reg);
146 mdiv = (pll_con >> PLL3000_MDIV_SHIFT) & PLL3000_MDIV_MASK;
147 pdiv = (pll_con >> PLL3000_PDIV_SHIFT) & PLL3000_PDIV_MASK;
148 sdiv = (pll_con >> PLL3000_SDIV_SHIFT) & PLL3000_SDIV_MASK;
149
150 fvco *= (2 * (mdiv + 8));
151 do_div(fvco, pdiv << sdiv);
152
153 return (unsigned long)fvco;
154 }
155
156 static const struct clk_ops samsung_pll3000_clk_ops = {
157 .recalc_rate = samsung_pll3000_recalc_rate,
158 };
159
160 /*
161 * PLL35xx Clock Type
162 */
163 /* Maximum lock time can be 270 * PDIV cycles */
164 #define PLL35XX_LOCK_FACTOR (270)
165
166 #define PLL35XX_MDIV_MASK (0x3FF)
167 #define PLL35XX_PDIV_MASK (0x3F)
168 #define PLL35XX_SDIV_MASK (0x7)
169 #define PLL35XX_MDIV_SHIFT (16)
170 #define PLL35XX_PDIV_SHIFT (8)
171 #define PLL35XX_SDIV_SHIFT (0)
172 #define PLL35XX_LOCK_STAT_SHIFT (29)
173 #define PLL35XX_ENABLE_SHIFT (31)
174
samsung_pll35xx_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)175 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
176 unsigned long parent_rate)
177 {
178 struct samsung_clk_pll *pll = to_clk_pll(hw);
179 u32 mdiv, pdiv, sdiv, pll_con;
180 u64 fvco = parent_rate;
181
182 pll_con = readl_relaxed(pll->con_reg);
183 mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
184 pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
185 sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
186
187 fvco *= mdiv;
188 do_div(fvco, (pdiv << sdiv));
189
190 return (unsigned long)fvco;
191 }
192
samsung_pll35xx_mp_change(const struct samsung_pll_rate_table * rate,u32 pll_con)193 static inline bool samsung_pll35xx_mp_change(
194 const struct samsung_pll_rate_table *rate, u32 pll_con)
195 {
196 u32 old_mdiv, old_pdiv;
197
198 old_mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
199 old_pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
200
201 return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv);
202 }
203
samsung_pll35xx_set_rate(struct clk_hw * hw,unsigned long drate,unsigned long prate)204 static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
205 unsigned long prate)
206 {
207 struct samsung_clk_pll *pll = to_clk_pll(hw);
208 const struct samsung_pll_rate_table *rate;
209 u32 tmp;
210
211 /* Get required rate settings from table */
212 rate = samsung_get_pll_settings(pll, drate);
213 if (!rate) {
214 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
215 drate, clk_hw_get_name(hw));
216 return -EINVAL;
217 }
218
219 tmp = readl_relaxed(pll->con_reg);
220
221 if (!(samsung_pll35xx_mp_change(rate, tmp))) {
222 /* If only s change, change just s value only*/
223 tmp &= ~(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT);
224 tmp |= rate->sdiv << PLL35XX_SDIV_SHIFT;
225 writel_relaxed(tmp, pll->con_reg);
226
227 return 0;
228 }
229
230 /* Set PLL lock time. */
231 writel_relaxed(rate->pdiv * PLL35XX_LOCK_FACTOR,
232 pll->lock_reg);
233
234 /* Change PLL PMS values */
235 tmp &= ~((PLL35XX_MDIV_MASK << PLL35XX_MDIV_SHIFT) |
236 (PLL35XX_PDIV_MASK << PLL35XX_PDIV_SHIFT) |
237 (PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT));
238 tmp |= (rate->mdiv << PLL35XX_MDIV_SHIFT) |
239 (rate->pdiv << PLL35XX_PDIV_SHIFT) |
240 (rate->sdiv << PLL35XX_SDIV_SHIFT);
241 writel_relaxed(tmp, pll->con_reg);
242
243 /* Wait until the PLL is locked if it is enabled. */
244 if (tmp & BIT(pll->enable_offs)) {
245 do {
246 cpu_relax();
247 tmp = readl_relaxed(pll->con_reg);
248 } while (!(tmp & BIT(pll->lock_offs)));
249 }
250 return 0;
251 }
252
253 static const struct clk_ops samsung_pll35xx_clk_ops = {
254 .recalc_rate = samsung_pll35xx_recalc_rate,
255 .round_rate = samsung_pll_round_rate,
256 .set_rate = samsung_pll35xx_set_rate,
257 .enable = samsung_pll3xxx_enable,
258 .disable = samsung_pll3xxx_disable,
259 };
260
261 static const struct clk_ops samsung_pll35xx_clk_min_ops = {
262 .recalc_rate = samsung_pll35xx_recalc_rate,
263 };
264
265 /*
266 * PLL36xx Clock Type
267 */
268 /* Maximum lock time can be 3000 * PDIV cycles */
269 #define PLL36XX_LOCK_FACTOR (3000)
270
271 #define PLL36XX_KDIV_MASK (0xFFFF)
272 #define PLL36XX_MDIV_MASK (0x1FF)
273 #define PLL36XX_PDIV_MASK (0x3F)
274 #define PLL36XX_SDIV_MASK (0x7)
275 #define PLL36XX_MDIV_SHIFT (16)
276 #define PLL36XX_PDIV_SHIFT (8)
277 #define PLL36XX_SDIV_SHIFT (0)
278 #define PLL36XX_KDIV_SHIFT (0)
279 #define PLL36XX_LOCK_STAT_SHIFT (29)
280 #define PLL36XX_ENABLE_SHIFT (31)
281
samsung_pll36xx_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)282 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
283 unsigned long parent_rate)
284 {
285 struct samsung_clk_pll *pll = to_clk_pll(hw);
286 u32 mdiv, pdiv, sdiv, pll_con0, pll_con1;
287 s16 kdiv;
288 u64 fvco = parent_rate;
289
290 pll_con0 = readl_relaxed(pll->con_reg);
291 pll_con1 = readl_relaxed(pll->con_reg + 4);
292 mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
293 pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
294 sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
295 kdiv = (s16)(pll_con1 & PLL36XX_KDIV_MASK);
296
297 fvco *= (mdiv << 16) + kdiv;
298 do_div(fvco, (pdiv << sdiv));
299 fvco >>= 16;
300
301 return (unsigned long)fvco;
302 }
303
samsung_pll36xx_mpk_change(const struct samsung_pll_rate_table * rate,u32 pll_con0,u32 pll_con1)304 static inline bool samsung_pll36xx_mpk_change(
305 const struct samsung_pll_rate_table *rate, u32 pll_con0, u32 pll_con1)
306 {
307 u32 old_mdiv, old_pdiv, old_kdiv;
308
309 old_mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
310 old_pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
311 old_kdiv = (pll_con1 >> PLL36XX_KDIV_SHIFT) & PLL36XX_KDIV_MASK;
312
313 return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
314 rate->kdiv != old_kdiv);
315 }
316
samsung_pll36xx_set_rate(struct clk_hw * hw,unsigned long drate,unsigned long parent_rate)317 static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
318 unsigned long parent_rate)
319 {
320 struct samsung_clk_pll *pll = to_clk_pll(hw);
321 u32 tmp, pll_con0, pll_con1;
322 const struct samsung_pll_rate_table *rate;
323
324 rate = samsung_get_pll_settings(pll, drate);
325 if (!rate) {
326 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
327 drate, clk_hw_get_name(hw));
328 return -EINVAL;
329 }
330
331 pll_con0 = readl_relaxed(pll->con_reg);
332 pll_con1 = readl_relaxed(pll->con_reg + 4);
333
334 if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) {
335 /* If only s change, change just s value only*/
336 pll_con0 &= ~(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT);
337 pll_con0 |= (rate->sdiv << PLL36XX_SDIV_SHIFT);
338 writel_relaxed(pll_con0, pll->con_reg);
339
340 return 0;
341 }
342
343 /* Set PLL lock time. */
344 writel_relaxed(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg);
345
346 /* Change PLL PMS values */
347 pll_con0 &= ~((PLL36XX_MDIV_MASK << PLL36XX_MDIV_SHIFT) |
348 (PLL36XX_PDIV_MASK << PLL36XX_PDIV_SHIFT) |
349 (PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT));
350 pll_con0 |= (rate->mdiv << PLL36XX_MDIV_SHIFT) |
351 (rate->pdiv << PLL36XX_PDIV_SHIFT) |
352 (rate->sdiv << PLL36XX_SDIV_SHIFT);
353 writel_relaxed(pll_con0, pll->con_reg);
354
355 pll_con1 &= ~(PLL36XX_KDIV_MASK << PLL36XX_KDIV_SHIFT);
356 pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT;
357 writel_relaxed(pll_con1, pll->con_reg + 4);
358
359 /* wait_lock_time */
360 if (pll_con0 & BIT(pll->enable_offs)) {
361 do {
362 cpu_relax();
363 tmp = readl_relaxed(pll->con_reg);
364 } while (!(tmp & BIT(pll->lock_offs)));
365 }
366
367 return 0;
368 }
369
370 static const struct clk_ops samsung_pll36xx_clk_ops = {
371 .recalc_rate = samsung_pll36xx_recalc_rate,
372 .set_rate = samsung_pll36xx_set_rate,
373 .round_rate = samsung_pll_round_rate,
374 .enable = samsung_pll3xxx_enable,
375 .disable = samsung_pll3xxx_disable,
376 };
377
378 static const struct clk_ops samsung_pll36xx_clk_min_ops = {
379 .recalc_rate = samsung_pll36xx_recalc_rate,
380 };
381
382 /*
383 * PLL45xx Clock Type
384 */
385 #define PLL4502_LOCK_FACTOR 400
386 #define PLL4508_LOCK_FACTOR 240
387
388 #define PLL45XX_MDIV_MASK (0x3FF)
389 #define PLL45XX_PDIV_MASK (0x3F)
390 #define PLL45XX_SDIV_MASK (0x7)
391 #define PLL45XX_AFC_MASK (0x1F)
392 #define PLL45XX_MDIV_SHIFT (16)
393 #define PLL45XX_PDIV_SHIFT (8)
394 #define PLL45XX_SDIV_SHIFT (0)
395 #define PLL45XX_AFC_SHIFT (0)
396
397 #define PLL45XX_ENABLE BIT(31)
398 #define PLL45XX_LOCKED BIT(29)
399
samsung_pll45xx_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)400 static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw,
401 unsigned long parent_rate)
402 {
403 struct samsung_clk_pll *pll = to_clk_pll(hw);
404 u32 mdiv, pdiv, sdiv, pll_con;
405 u64 fvco = parent_rate;
406
407 pll_con = readl_relaxed(pll->con_reg);
408 mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
409 pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
410 sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
411
412 if (pll->type == pll_4508)
413 sdiv = sdiv - 1;
414
415 fvco *= mdiv;
416 do_div(fvco, (pdiv << sdiv));
417
418 return (unsigned long)fvco;
419 }
420
samsung_pll45xx_mp_change(u32 pll_con0,u32 pll_con1,const struct samsung_pll_rate_table * rate)421 static bool samsung_pll45xx_mp_change(u32 pll_con0, u32 pll_con1,
422 const struct samsung_pll_rate_table *rate)
423 {
424 u32 old_mdiv, old_pdiv, old_afc;
425
426 old_mdiv = (pll_con0 >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
427 old_pdiv = (pll_con0 >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
428 old_afc = (pll_con1 >> PLL45XX_AFC_SHIFT) & PLL45XX_AFC_MASK;
429
430 return (old_mdiv != rate->mdiv || old_pdiv != rate->pdiv
431 || old_afc != rate->afc);
432 }
433
samsung_pll45xx_set_rate(struct clk_hw * hw,unsigned long drate,unsigned long prate)434 static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
435 unsigned long prate)
436 {
437 struct samsung_clk_pll *pll = to_clk_pll(hw);
438 const struct samsung_pll_rate_table *rate;
439 u32 con0, con1;
440 ktime_t start;
441
442 /* Get required rate settings from table */
443 rate = samsung_get_pll_settings(pll, drate);
444 if (!rate) {
445 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
446 drate, clk_hw_get_name(hw));
447 return -EINVAL;
448 }
449
450 con0 = readl_relaxed(pll->con_reg);
451 con1 = readl_relaxed(pll->con_reg + 0x4);
452
453 if (!(samsung_pll45xx_mp_change(con0, con1, rate))) {
454 /* If only s change, change just s value only*/
455 con0 &= ~(PLL45XX_SDIV_MASK << PLL45XX_SDIV_SHIFT);
456 con0 |= rate->sdiv << PLL45XX_SDIV_SHIFT;
457 writel_relaxed(con0, pll->con_reg);
458
459 return 0;
460 }
461
462 /* Set PLL PMS values. */
463 con0 &= ~((PLL45XX_MDIV_MASK << PLL45XX_MDIV_SHIFT) |
464 (PLL45XX_PDIV_MASK << PLL45XX_PDIV_SHIFT) |
465 (PLL45XX_SDIV_MASK << PLL45XX_SDIV_SHIFT));
466 con0 |= (rate->mdiv << PLL45XX_MDIV_SHIFT) |
467 (rate->pdiv << PLL45XX_PDIV_SHIFT) |
468 (rate->sdiv << PLL45XX_SDIV_SHIFT);
469
470 /* Set PLL AFC value. */
471 con1 = readl_relaxed(pll->con_reg + 0x4);
472 con1 &= ~(PLL45XX_AFC_MASK << PLL45XX_AFC_SHIFT);
473 con1 |= (rate->afc << PLL45XX_AFC_SHIFT);
474
475 /* Set PLL lock time. */
476 switch (pll->type) {
477 case pll_4502:
478 writel_relaxed(rate->pdiv * PLL4502_LOCK_FACTOR, pll->lock_reg);
479 break;
480 case pll_4508:
481 writel_relaxed(rate->pdiv * PLL4508_LOCK_FACTOR, pll->lock_reg);
482 break;
483 default:
484 break;
485 }
486
487 /* Set new configuration. */
488 writel_relaxed(con1, pll->con_reg + 0x4);
489 writel_relaxed(con0, pll->con_reg);
490
491 /* Wait for locking. */
492 start = ktime_get();
493 while (!(readl_relaxed(pll->con_reg) & PLL45XX_LOCKED)) {
494 ktime_t delta = ktime_sub(ktime_get(), start);
495
496 if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
497 pr_err("%s: could not lock PLL %s\n",
498 __func__, clk_hw_get_name(hw));
499 return -EFAULT;
500 }
501
502 cpu_relax();
503 }
504
505 return 0;
506 }
507
508 static const struct clk_ops samsung_pll45xx_clk_ops = {
509 .recalc_rate = samsung_pll45xx_recalc_rate,
510 .round_rate = samsung_pll_round_rate,
511 .set_rate = samsung_pll45xx_set_rate,
512 };
513
514 static const struct clk_ops samsung_pll45xx_clk_min_ops = {
515 .recalc_rate = samsung_pll45xx_recalc_rate,
516 };
517
518 /*
519 * PLL46xx Clock Type
520 */
521 #define PLL46XX_LOCK_FACTOR 3000
522
523 #define PLL46XX_VSEL_MASK (1)
524 #define PLL46XX_MDIV_MASK (0x1FF)
525 #define PLL1460X_MDIV_MASK (0x3FF)
526
527 #define PLL46XX_PDIV_MASK (0x3F)
528 #define PLL46XX_SDIV_MASK (0x7)
529 #define PLL46XX_VSEL_SHIFT (27)
530 #define PLL46XX_MDIV_SHIFT (16)
531 #define PLL46XX_PDIV_SHIFT (8)
532 #define PLL46XX_SDIV_SHIFT (0)
533
534 #define PLL46XX_KDIV_MASK (0xFFFF)
535 #define PLL4650C_KDIV_MASK (0xFFF)
536 #define PLL46XX_KDIV_SHIFT (0)
537 #define PLL46XX_MFR_MASK (0x3F)
538 #define PLL46XX_MRR_MASK (0x1F)
539 #define PLL46XX_KDIV_SHIFT (0)
540 #define PLL46XX_MFR_SHIFT (16)
541 #define PLL46XX_MRR_SHIFT (24)
542
543 #define PLL46XX_ENABLE BIT(31)
544 #define PLL46XX_LOCKED BIT(29)
545 #define PLL46XX_VSEL BIT(27)
546
samsung_pll46xx_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)547 static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw,
548 unsigned long parent_rate)
549 {
550 struct samsung_clk_pll *pll = to_clk_pll(hw);
551 u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1, shift;
552 u64 fvco = parent_rate;
553
554 pll_con0 = readl_relaxed(pll->con_reg);
555 pll_con1 = readl_relaxed(pll->con_reg + 4);
556 mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & ((pll->type == pll_1460x) ?
557 PLL1460X_MDIV_MASK : PLL46XX_MDIV_MASK);
558 pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
559 sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
560 kdiv = pll->type == pll_4650c ? pll_con1 & PLL4650C_KDIV_MASK :
561 pll_con1 & PLL46XX_KDIV_MASK;
562
563 shift = ((pll->type == pll_4600) || (pll->type == pll_1460x)) ? 16 : 10;
564
565 fvco *= (mdiv << shift) + kdiv;
566 do_div(fvco, (pdiv << sdiv));
567 fvco >>= shift;
568
569 return (unsigned long)fvco;
570 }
571
samsung_pll46xx_mpk_change(u32 pll_con0,u32 pll_con1,const struct samsung_pll_rate_table * rate)572 static bool samsung_pll46xx_mpk_change(u32 pll_con0, u32 pll_con1,
573 const struct samsung_pll_rate_table *rate)
574 {
575 u32 old_mdiv, old_pdiv, old_kdiv;
576
577 old_mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
578 old_pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
579 old_kdiv = (pll_con1 >> PLL46XX_KDIV_SHIFT) & PLL46XX_KDIV_MASK;
580
581 return (old_mdiv != rate->mdiv || old_pdiv != rate->pdiv
582 || old_kdiv != rate->kdiv);
583 }
584
samsung_pll46xx_set_rate(struct clk_hw * hw,unsigned long drate,unsigned long prate)585 static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
586 unsigned long prate)
587 {
588 struct samsung_clk_pll *pll = to_clk_pll(hw);
589 const struct samsung_pll_rate_table *rate;
590 u32 con0, con1, lock;
591 ktime_t start;
592
593 /* Get required rate settings from table */
594 rate = samsung_get_pll_settings(pll, drate);
595 if (!rate) {
596 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
597 drate, clk_hw_get_name(hw));
598 return -EINVAL;
599 }
600
601 con0 = readl_relaxed(pll->con_reg);
602 con1 = readl_relaxed(pll->con_reg + 0x4);
603
604 if (!(samsung_pll46xx_mpk_change(con0, con1, rate))) {
605 /* If only s change, change just s value only*/
606 con0 &= ~(PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
607 con0 |= rate->sdiv << PLL46XX_SDIV_SHIFT;
608 writel_relaxed(con0, pll->con_reg);
609
610 return 0;
611 }
612
613 /* Set PLL lock time. */
614 lock = rate->pdiv * PLL46XX_LOCK_FACTOR;
615 if (lock > 0xffff)
616 /* Maximum lock time bitfield is 16-bit. */
617 lock = 0xffff;
618
619 /* Set PLL PMS and VSEL values. */
620 if (pll->type == pll_1460x) {
621 con0 &= ~((PLL1460X_MDIV_MASK << PLL46XX_MDIV_SHIFT) |
622 (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT) |
623 (PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT));
624 } else {
625 con0 &= ~((PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT) |
626 (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT) |
627 (PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT) |
628 (PLL46XX_VSEL_MASK << PLL46XX_VSEL_SHIFT));
629 con0 |= rate->vsel << PLL46XX_VSEL_SHIFT;
630 }
631
632 con0 |= (rate->mdiv << PLL46XX_MDIV_SHIFT) |
633 (rate->pdiv << PLL46XX_PDIV_SHIFT) |
634 (rate->sdiv << PLL46XX_SDIV_SHIFT);
635
636 /* Set PLL K, MFR and MRR values. */
637 con1 = readl_relaxed(pll->con_reg + 0x4);
638 con1 &= ~((PLL46XX_KDIV_MASK << PLL46XX_KDIV_SHIFT) |
639 (PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT) |
640 (PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT));
641 con1 |= (rate->kdiv << PLL46XX_KDIV_SHIFT) |
642 (rate->mfr << PLL46XX_MFR_SHIFT) |
643 (rate->mrr << PLL46XX_MRR_SHIFT);
644
645 /* Write configuration to PLL */
646 writel_relaxed(lock, pll->lock_reg);
647 writel_relaxed(con0, pll->con_reg);
648 writel_relaxed(con1, pll->con_reg + 0x4);
649
650 /* Wait for locking. */
651 start = ktime_get();
652 while (!(readl_relaxed(pll->con_reg) & PLL46XX_LOCKED)) {
653 ktime_t delta = ktime_sub(ktime_get(), start);
654
655 if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
656 pr_err("%s: could not lock PLL %s\n",
657 __func__, clk_hw_get_name(hw));
658 return -EFAULT;
659 }
660
661 cpu_relax();
662 }
663
664 return 0;
665 }
666
667 static const struct clk_ops samsung_pll46xx_clk_ops = {
668 .recalc_rate = samsung_pll46xx_recalc_rate,
669 .round_rate = samsung_pll_round_rate,
670 .set_rate = samsung_pll46xx_set_rate,
671 };
672
673 static const struct clk_ops samsung_pll46xx_clk_min_ops = {
674 .recalc_rate = samsung_pll46xx_recalc_rate,
675 };
676
677 /*
678 * PLL6552 Clock Type
679 */
680
681 #define PLL6552_MDIV_MASK 0x3ff
682 #define PLL6552_PDIV_MASK 0x3f
683 #define PLL6552_SDIV_MASK 0x7
684 #define PLL6552_MDIV_SHIFT 16
685 #define PLL6552_MDIV_SHIFT_2416 14
686 #define PLL6552_PDIV_SHIFT 8
687 #define PLL6552_PDIV_SHIFT_2416 5
688 #define PLL6552_SDIV_SHIFT 0
689
samsung_pll6552_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)690 static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw,
691 unsigned long parent_rate)
692 {
693 struct samsung_clk_pll *pll = to_clk_pll(hw);
694 u32 mdiv, pdiv, sdiv, pll_con;
695 u64 fvco = parent_rate;
696
697 pll_con = readl_relaxed(pll->con_reg);
698 if (pll->type == pll_6552_s3c2416) {
699 mdiv = (pll_con >> PLL6552_MDIV_SHIFT_2416) & PLL6552_MDIV_MASK;
700 pdiv = (pll_con >> PLL6552_PDIV_SHIFT_2416) & PLL6552_PDIV_MASK;
701 } else {
702 mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK;
703 pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK;
704 }
705 sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK;
706
707 fvco *= mdiv;
708 do_div(fvco, (pdiv << sdiv));
709
710 return (unsigned long)fvco;
711 }
712
713 static const struct clk_ops samsung_pll6552_clk_ops = {
714 .recalc_rate = samsung_pll6552_recalc_rate,
715 };
716
717 /*
718 * PLL6553 Clock Type
719 */
720
721 #define PLL6553_MDIV_MASK 0xff
722 #define PLL6553_PDIV_MASK 0x3f
723 #define PLL6553_SDIV_MASK 0x7
724 #define PLL6553_KDIV_MASK 0xffff
725 #define PLL6553_MDIV_SHIFT 16
726 #define PLL6553_PDIV_SHIFT 8
727 #define PLL6553_SDIV_SHIFT 0
728 #define PLL6553_KDIV_SHIFT 0
729
samsung_pll6553_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)730 static unsigned long samsung_pll6553_recalc_rate(struct clk_hw *hw,
731 unsigned long parent_rate)
732 {
733 struct samsung_clk_pll *pll = to_clk_pll(hw);
734 u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
735 u64 fvco = parent_rate;
736
737 pll_con0 = readl_relaxed(pll->con_reg);
738 pll_con1 = readl_relaxed(pll->con_reg + 0x4);
739 mdiv = (pll_con0 >> PLL6553_MDIV_SHIFT) & PLL6553_MDIV_MASK;
740 pdiv = (pll_con0 >> PLL6553_PDIV_SHIFT) & PLL6553_PDIV_MASK;
741 sdiv = (pll_con0 >> PLL6553_SDIV_SHIFT) & PLL6553_SDIV_MASK;
742 kdiv = (pll_con1 >> PLL6553_KDIV_SHIFT) & PLL6553_KDIV_MASK;
743
744 fvco *= (mdiv << 16) + kdiv;
745 do_div(fvco, (pdiv << sdiv));
746 fvco >>= 16;
747
748 return (unsigned long)fvco;
749 }
750
751 static const struct clk_ops samsung_pll6553_clk_ops = {
752 .recalc_rate = samsung_pll6553_recalc_rate,
753 };
754
755 /*
756 * PLL Clock Type of S3C24XX before S3C2443
757 */
758
759 #define PLLS3C2410_MDIV_MASK (0xff)
760 #define PLLS3C2410_PDIV_MASK (0x1f)
761 #define PLLS3C2410_SDIV_MASK (0x3)
762 #define PLLS3C2410_MDIV_SHIFT (12)
763 #define PLLS3C2410_PDIV_SHIFT (4)
764 #define PLLS3C2410_SDIV_SHIFT (0)
765
766 #define PLLS3C2410_ENABLE_REG_OFFSET 0x10
767
samsung_s3c2410_pll_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)768 static unsigned long samsung_s3c2410_pll_recalc_rate(struct clk_hw *hw,
769 unsigned long parent_rate)
770 {
771 struct samsung_clk_pll *pll = to_clk_pll(hw);
772 u32 pll_con, mdiv, pdiv, sdiv;
773 u64 fvco = parent_rate;
774
775 pll_con = readl_relaxed(pll->con_reg);
776 mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
777 pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
778 sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
779
780 fvco *= (mdiv + 8);
781 do_div(fvco, (pdiv + 2) << sdiv);
782
783 return (unsigned int)fvco;
784 }
785
samsung_s3c2440_mpll_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)786 static unsigned long samsung_s3c2440_mpll_recalc_rate(struct clk_hw *hw,
787 unsigned long parent_rate)
788 {
789 struct samsung_clk_pll *pll = to_clk_pll(hw);
790 u32 pll_con, mdiv, pdiv, sdiv;
791 u64 fvco = parent_rate;
792
793 pll_con = readl_relaxed(pll->con_reg);
794 mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
795 pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
796 sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
797
798 fvco *= (2 * (mdiv + 8));
799 do_div(fvco, (pdiv + 2) << sdiv);
800
801 return (unsigned int)fvco;
802 }
803
samsung_s3c2410_pll_set_rate(struct clk_hw * hw,unsigned long drate,unsigned long prate)804 static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate,
805 unsigned long prate)
806 {
807 struct samsung_clk_pll *pll = to_clk_pll(hw);
808 const struct samsung_pll_rate_table *rate;
809 u32 tmp;
810
811 /* Get required rate settings from table */
812 rate = samsung_get_pll_settings(pll, drate);
813 if (!rate) {
814 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
815 drate, clk_hw_get_name(hw));
816 return -EINVAL;
817 }
818
819 tmp = readl_relaxed(pll->con_reg);
820
821 /* Change PLL PMS values */
822 tmp &= ~((PLLS3C2410_MDIV_MASK << PLLS3C2410_MDIV_SHIFT) |
823 (PLLS3C2410_PDIV_MASK << PLLS3C2410_PDIV_SHIFT) |
824 (PLLS3C2410_SDIV_MASK << PLLS3C2410_SDIV_SHIFT));
825 tmp |= (rate->mdiv << PLLS3C2410_MDIV_SHIFT) |
826 (rate->pdiv << PLLS3C2410_PDIV_SHIFT) |
827 (rate->sdiv << PLLS3C2410_SDIV_SHIFT);
828 writel_relaxed(tmp, pll->con_reg);
829
830 /* Time to settle according to the manual */
831 udelay(300);
832
833 return 0;
834 }
835
samsung_s3c2410_pll_enable(struct clk_hw * hw,int bit,bool enable)836 static int samsung_s3c2410_pll_enable(struct clk_hw *hw, int bit, bool enable)
837 {
838 struct samsung_clk_pll *pll = to_clk_pll(hw);
839 u32 pll_en = readl_relaxed(pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
840 u32 pll_en_orig = pll_en;
841
842 if (enable)
843 pll_en &= ~BIT(bit);
844 else
845 pll_en |= BIT(bit);
846
847 writel_relaxed(pll_en, pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
848
849 /* if we started the UPLL, then allow to settle */
850 if (enable && (pll_en_orig & BIT(bit)))
851 udelay(300);
852
853 return 0;
854 }
855
samsung_s3c2410_mpll_enable(struct clk_hw * hw)856 static int samsung_s3c2410_mpll_enable(struct clk_hw *hw)
857 {
858 return samsung_s3c2410_pll_enable(hw, 5, true);
859 }
860
samsung_s3c2410_mpll_disable(struct clk_hw * hw)861 static void samsung_s3c2410_mpll_disable(struct clk_hw *hw)
862 {
863 samsung_s3c2410_pll_enable(hw, 5, false);
864 }
865
samsung_s3c2410_upll_enable(struct clk_hw * hw)866 static int samsung_s3c2410_upll_enable(struct clk_hw *hw)
867 {
868 return samsung_s3c2410_pll_enable(hw, 7, true);
869 }
870
samsung_s3c2410_upll_disable(struct clk_hw * hw)871 static void samsung_s3c2410_upll_disable(struct clk_hw *hw)
872 {
873 samsung_s3c2410_pll_enable(hw, 7, false);
874 }
875
876 static const struct clk_ops samsung_s3c2410_mpll_clk_min_ops = {
877 .recalc_rate = samsung_s3c2410_pll_recalc_rate,
878 .enable = samsung_s3c2410_mpll_enable,
879 .disable = samsung_s3c2410_mpll_disable,
880 };
881
882 static const struct clk_ops samsung_s3c2410_upll_clk_min_ops = {
883 .recalc_rate = samsung_s3c2410_pll_recalc_rate,
884 .enable = samsung_s3c2410_upll_enable,
885 .disable = samsung_s3c2410_upll_disable,
886 };
887
888 static const struct clk_ops samsung_s3c2440_mpll_clk_min_ops = {
889 .recalc_rate = samsung_s3c2440_mpll_recalc_rate,
890 .enable = samsung_s3c2410_mpll_enable,
891 .disable = samsung_s3c2410_mpll_disable,
892 };
893
894 static const struct clk_ops samsung_s3c2410_mpll_clk_ops = {
895 .recalc_rate = samsung_s3c2410_pll_recalc_rate,
896 .enable = samsung_s3c2410_mpll_enable,
897 .disable = samsung_s3c2410_mpll_disable,
898 .round_rate = samsung_pll_round_rate,
899 .set_rate = samsung_s3c2410_pll_set_rate,
900 };
901
902 static const struct clk_ops samsung_s3c2410_upll_clk_ops = {
903 .recalc_rate = samsung_s3c2410_pll_recalc_rate,
904 .enable = samsung_s3c2410_upll_enable,
905 .disable = samsung_s3c2410_upll_disable,
906 .round_rate = samsung_pll_round_rate,
907 .set_rate = samsung_s3c2410_pll_set_rate,
908 };
909
910 static const struct clk_ops samsung_s3c2440_mpll_clk_ops = {
911 .recalc_rate = samsung_s3c2440_mpll_recalc_rate,
912 .enable = samsung_s3c2410_mpll_enable,
913 .disable = samsung_s3c2410_mpll_disable,
914 .round_rate = samsung_pll_round_rate,
915 .set_rate = samsung_s3c2410_pll_set_rate,
916 };
917
918 /*
919 * PLL2550x Clock Type
920 */
921
922 #define PLL2550X_R_MASK (0x1)
923 #define PLL2550X_P_MASK (0x3F)
924 #define PLL2550X_M_MASK (0x3FF)
925 #define PLL2550X_S_MASK (0x7)
926 #define PLL2550X_R_SHIFT (20)
927 #define PLL2550X_P_SHIFT (14)
928 #define PLL2550X_M_SHIFT (4)
929 #define PLL2550X_S_SHIFT (0)
930
samsung_pll2550x_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)931 static unsigned long samsung_pll2550x_recalc_rate(struct clk_hw *hw,
932 unsigned long parent_rate)
933 {
934 struct samsung_clk_pll *pll = to_clk_pll(hw);
935 u32 r, p, m, s, pll_stat;
936 u64 fvco = parent_rate;
937
938 pll_stat = readl_relaxed(pll->con_reg);
939 r = (pll_stat >> PLL2550X_R_SHIFT) & PLL2550X_R_MASK;
940 if (!r)
941 return 0;
942 p = (pll_stat >> PLL2550X_P_SHIFT) & PLL2550X_P_MASK;
943 m = (pll_stat >> PLL2550X_M_SHIFT) & PLL2550X_M_MASK;
944 s = (pll_stat >> PLL2550X_S_SHIFT) & PLL2550X_S_MASK;
945
946 fvco *= m;
947 do_div(fvco, (p << s));
948
949 return (unsigned long)fvco;
950 }
951
952 static const struct clk_ops samsung_pll2550x_clk_ops = {
953 .recalc_rate = samsung_pll2550x_recalc_rate,
954 };
955
956 /*
957 * PLL2550xx Clock Type
958 */
959
960 /* Maximum lock time can be 270 * PDIV cycles */
961 #define PLL2550XX_LOCK_FACTOR 270
962
963 #define PLL2550XX_M_MASK 0x3FF
964 #define PLL2550XX_P_MASK 0x3F
965 #define PLL2550XX_S_MASK 0x7
966 #define PLL2550XX_LOCK_STAT_MASK 0x1
967 #define PLL2550XX_M_SHIFT 9
968 #define PLL2550XX_P_SHIFT 3
969 #define PLL2550XX_S_SHIFT 0
970 #define PLL2550XX_LOCK_STAT_SHIFT 21
971
samsung_pll2550xx_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)972 static unsigned long samsung_pll2550xx_recalc_rate(struct clk_hw *hw,
973 unsigned long parent_rate)
974 {
975 struct samsung_clk_pll *pll = to_clk_pll(hw);
976 u32 mdiv, pdiv, sdiv, pll_con;
977 u64 fvco = parent_rate;
978
979 pll_con = readl_relaxed(pll->con_reg);
980 mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK;
981 pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK;
982 sdiv = (pll_con >> PLL2550XX_S_SHIFT) & PLL2550XX_S_MASK;
983
984 fvco *= mdiv;
985 do_div(fvco, (pdiv << sdiv));
986
987 return (unsigned long)fvco;
988 }
989
samsung_pll2550xx_mp_change(u32 mdiv,u32 pdiv,u32 pll_con)990 static inline bool samsung_pll2550xx_mp_change(u32 mdiv, u32 pdiv, u32 pll_con)
991 {
992 u32 old_mdiv, old_pdiv;
993
994 old_mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK;
995 old_pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK;
996
997 return mdiv != old_mdiv || pdiv != old_pdiv;
998 }
999
samsung_pll2550xx_set_rate(struct clk_hw * hw,unsigned long drate,unsigned long prate)1000 static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate,
1001 unsigned long prate)
1002 {
1003 struct samsung_clk_pll *pll = to_clk_pll(hw);
1004 const struct samsung_pll_rate_table *rate;
1005 u32 tmp;
1006
1007 /* Get required rate settings from table */
1008 rate = samsung_get_pll_settings(pll, drate);
1009 if (!rate) {
1010 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
1011 drate, clk_hw_get_name(hw));
1012 return -EINVAL;
1013 }
1014
1015 tmp = readl_relaxed(pll->con_reg);
1016
1017 if (!(samsung_pll2550xx_mp_change(rate->mdiv, rate->pdiv, tmp))) {
1018 /* If only s change, change just s value only*/
1019 tmp &= ~(PLL2550XX_S_MASK << PLL2550XX_S_SHIFT);
1020 tmp |= rate->sdiv << PLL2550XX_S_SHIFT;
1021 writel_relaxed(tmp, pll->con_reg);
1022
1023 return 0;
1024 }
1025
1026 /* Set PLL lock time. */
1027 writel_relaxed(rate->pdiv * PLL2550XX_LOCK_FACTOR, pll->lock_reg);
1028
1029 /* Change PLL PMS values */
1030 tmp &= ~((PLL2550XX_M_MASK << PLL2550XX_M_SHIFT) |
1031 (PLL2550XX_P_MASK << PLL2550XX_P_SHIFT) |
1032 (PLL2550XX_S_MASK << PLL2550XX_S_SHIFT));
1033 tmp |= (rate->mdiv << PLL2550XX_M_SHIFT) |
1034 (rate->pdiv << PLL2550XX_P_SHIFT) |
1035 (rate->sdiv << PLL2550XX_S_SHIFT);
1036 writel_relaxed(tmp, pll->con_reg);
1037
1038 /* wait_lock_time */
1039 do {
1040 cpu_relax();
1041 tmp = readl_relaxed(pll->con_reg);
1042 } while (!(tmp & (PLL2550XX_LOCK_STAT_MASK
1043 << PLL2550XX_LOCK_STAT_SHIFT)));
1044
1045 return 0;
1046 }
1047
1048 static const struct clk_ops samsung_pll2550xx_clk_ops = {
1049 .recalc_rate = samsung_pll2550xx_recalc_rate,
1050 .round_rate = samsung_pll_round_rate,
1051 .set_rate = samsung_pll2550xx_set_rate,
1052 };
1053
1054 static const struct clk_ops samsung_pll2550xx_clk_min_ops = {
1055 .recalc_rate = samsung_pll2550xx_recalc_rate,
1056 };
1057
1058 /*
1059 * PLL2650x Clock Type
1060 */
1061
1062 /* Maximum lock time can be 3000 * PDIV cycles */
1063 #define PLL2650X_LOCK_FACTOR 3000
1064
1065 #define PLL2650X_M_MASK 0x1ff
1066 #define PLL2650X_P_MASK 0x3f
1067 #define PLL2650X_S_MASK 0x7
1068 #define PLL2650X_K_MASK 0xffff
1069 #define PLL2650X_LOCK_STAT_MASK 0x1
1070 #define PLL2650X_M_SHIFT 16
1071 #define PLL2650X_P_SHIFT 8
1072 #define PLL2650X_S_SHIFT 0
1073 #define PLL2650X_K_SHIFT 0
1074 #define PLL2650X_LOCK_STAT_SHIFT 29
1075 #define PLL2650X_PLL_ENABLE_SHIFT 31
1076
samsung_pll2650x_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)1077 static unsigned long samsung_pll2650x_recalc_rate(struct clk_hw *hw,
1078 unsigned long parent_rate)
1079 {
1080 struct samsung_clk_pll *pll = to_clk_pll(hw);
1081 u64 fout = parent_rate;
1082 u32 mdiv, pdiv, sdiv, pll_con0, pll_con1;
1083 s16 kdiv;
1084
1085 pll_con0 = readl_relaxed(pll->con_reg);
1086 mdiv = (pll_con0 >> PLL2650X_M_SHIFT) & PLL2650X_M_MASK;
1087 pdiv = (pll_con0 >> PLL2650X_P_SHIFT) & PLL2650X_P_MASK;
1088 sdiv = (pll_con0 >> PLL2650X_S_SHIFT) & PLL2650X_S_MASK;
1089
1090 pll_con1 = readl_relaxed(pll->con_reg + 4);
1091 kdiv = (s16)((pll_con1 >> PLL2650X_K_SHIFT) & PLL2650X_K_MASK);
1092
1093 fout *= (mdiv << 16) + kdiv;
1094 do_div(fout, (pdiv << sdiv));
1095 fout >>= 16;
1096
1097 return (unsigned long)fout;
1098 }
1099
samsung_pll2650x_set_rate(struct clk_hw * hw,unsigned long drate,unsigned long prate)1100 static int samsung_pll2650x_set_rate(struct clk_hw *hw, unsigned long drate,
1101 unsigned long prate)
1102 {
1103 struct samsung_clk_pll *pll = to_clk_pll(hw);
1104 const struct samsung_pll_rate_table *rate;
1105 u32 con0, con1;
1106
1107 /* Get required rate settings from table */
1108 rate = samsung_get_pll_settings(pll, drate);
1109 if (!rate) {
1110 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
1111 drate, clk_hw_get_name(hw));
1112 return -EINVAL;
1113 }
1114
1115 con0 = readl_relaxed(pll->con_reg);
1116 con1 = readl_relaxed(pll->con_reg + 4);
1117
1118 /* Set PLL lock time. */
1119 writel_relaxed(rate->pdiv * PLL2650X_LOCK_FACTOR, pll->lock_reg);
1120
1121 /* Change PLL PMS values */
1122 con0 &= ~((PLL2650X_M_MASK << PLL2650X_M_SHIFT) |
1123 (PLL2650X_P_MASK << PLL2650X_P_SHIFT) |
1124 (PLL2650X_S_MASK << PLL2650X_S_SHIFT));
1125 con0 |= (rate->mdiv << PLL2650X_M_SHIFT) |
1126 (rate->pdiv << PLL2650X_P_SHIFT) |
1127 (rate->sdiv << PLL2650X_S_SHIFT);
1128 con0 |= (1 << PLL2650X_PLL_ENABLE_SHIFT);
1129 writel_relaxed(con0, pll->con_reg);
1130
1131 con1 &= ~(PLL2650X_K_MASK << PLL2650X_K_SHIFT);
1132 con1 |= ((rate->kdiv & PLL2650X_K_MASK) << PLL2650X_K_SHIFT);
1133 writel_relaxed(con1, pll->con_reg + 4);
1134
1135 do {
1136 cpu_relax();
1137 con0 = readl_relaxed(pll->con_reg);
1138 } while (!(con0 & (PLL2650X_LOCK_STAT_MASK
1139 << PLL2650X_LOCK_STAT_SHIFT)));
1140
1141 return 0;
1142 }
1143
1144 static const struct clk_ops samsung_pll2650x_clk_ops = {
1145 .recalc_rate = samsung_pll2650x_recalc_rate,
1146 .round_rate = samsung_pll_round_rate,
1147 .set_rate = samsung_pll2650x_set_rate,
1148 };
1149
1150 static const struct clk_ops samsung_pll2650x_clk_min_ops = {
1151 .recalc_rate = samsung_pll2650x_recalc_rate,
1152 };
1153
1154 /*
1155 * PLL2650XX Clock Type
1156 */
1157
1158 /* Maximum lock time can be 3000 * PDIV cycles */
1159 #define PLL2650XX_LOCK_FACTOR 3000
1160
1161 #define PLL2650XX_MDIV_SHIFT 9
1162 #define PLL2650XX_PDIV_SHIFT 3
1163 #define PLL2650XX_SDIV_SHIFT 0
1164 #define PLL2650XX_KDIV_SHIFT 0
1165 #define PLL2650XX_MDIV_MASK 0x1ff
1166 #define PLL2650XX_PDIV_MASK 0x3f
1167 #define PLL2650XX_SDIV_MASK 0x7
1168 #define PLL2650XX_KDIV_MASK 0xffff
1169 #define PLL2650XX_PLL_ENABLE_SHIFT 23
1170 #define PLL2650XX_PLL_LOCKTIME_SHIFT 21
1171 #define PLL2650XX_PLL_FOUTMASK_SHIFT 31
1172
samsung_pll2650xx_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)1173 static unsigned long samsung_pll2650xx_recalc_rate(struct clk_hw *hw,
1174 unsigned long parent_rate)
1175 {
1176 struct samsung_clk_pll *pll = to_clk_pll(hw);
1177 u32 mdiv, pdiv, sdiv, pll_con0, pll_con2;
1178 s16 kdiv;
1179 u64 fvco = parent_rate;
1180
1181 pll_con0 = readl_relaxed(pll->con_reg);
1182 pll_con2 = readl_relaxed(pll->con_reg + 8);
1183 mdiv = (pll_con0 >> PLL2650XX_MDIV_SHIFT) & PLL2650XX_MDIV_MASK;
1184 pdiv = (pll_con0 >> PLL2650XX_PDIV_SHIFT) & PLL2650XX_PDIV_MASK;
1185 sdiv = (pll_con0 >> PLL2650XX_SDIV_SHIFT) & PLL2650XX_SDIV_MASK;
1186 kdiv = (s16)(pll_con2 & PLL2650XX_KDIV_MASK);
1187
1188 fvco *= (mdiv << 16) + kdiv;
1189 do_div(fvco, (pdiv << sdiv));
1190 fvco >>= 16;
1191
1192 return (unsigned long)fvco;
1193 }
1194
samsung_pll2650xx_set_rate(struct clk_hw * hw,unsigned long drate,unsigned long parent_rate)1195 static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate,
1196 unsigned long parent_rate)
1197 {
1198 struct samsung_clk_pll *pll = to_clk_pll(hw);
1199 u32 tmp, pll_con0, pll_con2;
1200 const struct samsung_pll_rate_table *rate;
1201
1202 rate = samsung_get_pll_settings(pll, drate);
1203 if (!rate) {
1204 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
1205 drate, clk_hw_get_name(hw));
1206 return -EINVAL;
1207 }
1208
1209 pll_con0 = readl_relaxed(pll->con_reg);
1210 pll_con2 = readl_relaxed(pll->con_reg + 8);
1211
1212 /* Change PLL PMS values */
1213 pll_con0 &= ~(PLL2650XX_MDIV_MASK << PLL2650XX_MDIV_SHIFT |
1214 PLL2650XX_PDIV_MASK << PLL2650XX_PDIV_SHIFT |
1215 PLL2650XX_SDIV_MASK << PLL2650XX_SDIV_SHIFT);
1216 pll_con0 |= rate->mdiv << PLL2650XX_MDIV_SHIFT;
1217 pll_con0 |= rate->pdiv << PLL2650XX_PDIV_SHIFT;
1218 pll_con0 |= rate->sdiv << PLL2650XX_SDIV_SHIFT;
1219 pll_con0 |= 1 << PLL2650XX_PLL_ENABLE_SHIFT;
1220 pll_con0 |= 1 << PLL2650XX_PLL_FOUTMASK_SHIFT;
1221
1222 pll_con2 &= ~(PLL2650XX_KDIV_MASK << PLL2650XX_KDIV_SHIFT);
1223 pll_con2 |= ((~(rate->kdiv) + 1) & PLL2650XX_KDIV_MASK)
1224 << PLL2650XX_KDIV_SHIFT;
1225
1226 /* Set PLL lock time. */
1227 writel_relaxed(PLL2650XX_LOCK_FACTOR * rate->pdiv, pll->lock_reg);
1228
1229 writel_relaxed(pll_con0, pll->con_reg);
1230 writel_relaxed(pll_con2, pll->con_reg + 8);
1231
1232 do {
1233 tmp = readl_relaxed(pll->con_reg);
1234 } while (!(tmp & (0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT)));
1235
1236 return 0;
1237 }
1238
1239 static const struct clk_ops samsung_pll2650xx_clk_ops = {
1240 .recalc_rate = samsung_pll2650xx_recalc_rate,
1241 .set_rate = samsung_pll2650xx_set_rate,
1242 .round_rate = samsung_pll_round_rate,
1243 };
1244
1245 static const struct clk_ops samsung_pll2650xx_clk_min_ops = {
1246 .recalc_rate = samsung_pll2650xx_recalc_rate,
1247 };
1248
_samsung_clk_register_pll(struct samsung_clk_provider * ctx,const struct samsung_pll_clock * pll_clk,void __iomem * base)1249 static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
1250 const struct samsung_pll_clock *pll_clk,
1251 void __iomem *base)
1252 {
1253 struct samsung_clk_pll *pll;
1254 struct clk_init_data init;
1255 int ret, len;
1256
1257 pll = kzalloc(sizeof(*pll), GFP_KERNEL);
1258 if (!pll) {
1259 pr_err("%s: could not allocate pll clk %s\n",
1260 __func__, pll_clk->name);
1261 return;
1262 }
1263
1264 init.name = pll_clk->name;
1265 init.flags = pll_clk->flags;
1266 init.parent_names = &pll_clk->parent_name;
1267 init.num_parents = 1;
1268
1269 if (pll_clk->rate_table) {
1270 /* find count of rates in rate_table */
1271 for (len = 0; pll_clk->rate_table[len].rate != 0; )
1272 len++;
1273
1274 pll->rate_count = len;
1275 pll->rate_table = kmemdup(pll_clk->rate_table,
1276 pll->rate_count *
1277 sizeof(struct samsung_pll_rate_table),
1278 GFP_KERNEL);
1279 WARN(!pll->rate_table,
1280 "%s: could not allocate rate table for %s\n",
1281 __func__, pll_clk->name);
1282 }
1283
1284 switch (pll_clk->type) {
1285 case pll_2126:
1286 init.ops = &samsung_pll2126_clk_ops;
1287 break;
1288 case pll_3000:
1289 init.ops = &samsung_pll3000_clk_ops;
1290 break;
1291 /* clk_ops for 35xx and 2550 are similar */
1292 case pll_35xx:
1293 case pll_2550:
1294 case pll_1450x:
1295 case pll_1451x:
1296 case pll_1452x:
1297 pll->enable_offs = PLL35XX_ENABLE_SHIFT;
1298 pll->lock_offs = PLL35XX_LOCK_STAT_SHIFT;
1299 if (!pll->rate_table)
1300 init.ops = &samsung_pll35xx_clk_min_ops;
1301 else
1302 init.ops = &samsung_pll35xx_clk_ops;
1303 break;
1304 case pll_4500:
1305 init.ops = &samsung_pll45xx_clk_min_ops;
1306 break;
1307 case pll_4502:
1308 case pll_4508:
1309 if (!pll->rate_table)
1310 init.ops = &samsung_pll45xx_clk_min_ops;
1311 else
1312 init.ops = &samsung_pll45xx_clk_ops;
1313 break;
1314 /* clk_ops for 36xx and 2650 are similar */
1315 case pll_36xx:
1316 case pll_2650:
1317 pll->enable_offs = PLL36XX_ENABLE_SHIFT;
1318 pll->lock_offs = PLL36XX_LOCK_STAT_SHIFT;
1319 if (!pll->rate_table)
1320 init.ops = &samsung_pll36xx_clk_min_ops;
1321 else
1322 init.ops = &samsung_pll36xx_clk_ops;
1323 break;
1324 case pll_6552:
1325 case pll_6552_s3c2416:
1326 init.ops = &samsung_pll6552_clk_ops;
1327 break;
1328 case pll_6553:
1329 init.ops = &samsung_pll6553_clk_ops;
1330 break;
1331 case pll_4600:
1332 case pll_4650:
1333 case pll_4650c:
1334 case pll_1460x:
1335 if (!pll->rate_table)
1336 init.ops = &samsung_pll46xx_clk_min_ops;
1337 else
1338 init.ops = &samsung_pll46xx_clk_ops;
1339 break;
1340 case pll_s3c2410_mpll:
1341 if (!pll->rate_table)
1342 init.ops = &samsung_s3c2410_mpll_clk_min_ops;
1343 else
1344 init.ops = &samsung_s3c2410_mpll_clk_ops;
1345 break;
1346 case pll_s3c2410_upll:
1347 if (!pll->rate_table)
1348 init.ops = &samsung_s3c2410_upll_clk_min_ops;
1349 else
1350 init.ops = &samsung_s3c2410_upll_clk_ops;
1351 break;
1352 case pll_s3c2440_mpll:
1353 if (!pll->rate_table)
1354 init.ops = &samsung_s3c2440_mpll_clk_min_ops;
1355 else
1356 init.ops = &samsung_s3c2440_mpll_clk_ops;
1357 break;
1358 case pll_2550x:
1359 init.ops = &samsung_pll2550x_clk_ops;
1360 break;
1361 case pll_2550xx:
1362 if (!pll->rate_table)
1363 init.ops = &samsung_pll2550xx_clk_min_ops;
1364 else
1365 init.ops = &samsung_pll2550xx_clk_ops;
1366 break;
1367 case pll_2650x:
1368 if (!pll->rate_table)
1369 init.ops = &samsung_pll2650x_clk_min_ops;
1370 else
1371 init.ops = &samsung_pll2650x_clk_ops;
1372 break;
1373 case pll_2650xx:
1374 if (!pll->rate_table)
1375 init.ops = &samsung_pll2650xx_clk_min_ops;
1376 else
1377 init.ops = &samsung_pll2650xx_clk_ops;
1378 break;
1379 default:
1380 pr_warn("%s: Unknown pll type for pll clk %s\n",
1381 __func__, pll_clk->name);
1382 }
1383
1384 pll->hw.init = &init;
1385 pll->type = pll_clk->type;
1386 pll->lock_reg = base + pll_clk->lock_offset;
1387 pll->con_reg = base + pll_clk->con_offset;
1388
1389 ret = clk_hw_register(ctx->dev, &pll->hw);
1390 if (ret) {
1391 pr_err("%s: failed to register pll clock %s : %d\n",
1392 __func__, pll_clk->name, ret);
1393 kfree(pll->rate_table);
1394 kfree(pll);
1395 return;
1396 }
1397
1398 samsung_clk_add_lookup(ctx, &pll->hw, pll_clk->id);
1399 }
1400
samsung_clk_register_pll(struct samsung_clk_provider * ctx,const struct samsung_pll_clock * pll_list,unsigned int nr_pll,void __iomem * base)1401 void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
1402 const struct samsung_pll_clock *pll_list,
1403 unsigned int nr_pll, void __iomem *base)
1404 {
1405 int cnt;
1406
1407 for (cnt = 0; cnt < nr_pll; cnt++)
1408 _samsung_clk_register_pll(ctx, &pll_list[cnt], base);
1409 }
1410