treewide: remove redundant IS_ERR() before error code check
[linux/fpc-iii.git] / drivers / clk / samsung / clk-pll.c
blobac70ad785d8edde1ac0bb381815a1ed3ed7aaa19
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
4 * Copyright (c) 2013 Linaro Ltd.
6 * This file contains the utility functions to register the pll clocks.
7 */
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"
18 #define PLL_TIMEOUT_MS 10
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;
33 #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
35 static const struct samsung_pll_rate_table *samsung_get_pll_settings(
36 struct samsung_clk_pll *pll, unsigned long rate)
38 const struct samsung_pll_rate_table *rate_table = pll->rate_table;
39 int i;
41 for (i = 0; i < pll->rate_count; i++) {
42 if (rate == rate_table[i].rate)
43 return &rate_table[i];
46 return NULL;
49 static long samsung_pll_round_rate(struct clk_hw *hw,
50 unsigned long drate, unsigned long *prate)
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;
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;
62 /* return minimum supported value */
63 return rate_table[i - 1].rate;
66 static int samsung_pll3xxx_enable(struct clk_hw *hw)
68 struct samsung_clk_pll *pll = to_clk_pll(hw);
69 u32 tmp;
71 tmp = readl_relaxed(pll->con_reg);
72 tmp |= BIT(pll->enable_offs);
73 writel_relaxed(tmp, pll->con_reg);
75 /* wait lock time */
76 do {
77 cpu_relax();
78 tmp = readl_relaxed(pll->con_reg);
79 } while (!(tmp & BIT(pll->lock_offs)));
81 return 0;
84 static void samsung_pll3xxx_disable(struct clk_hw *hw)
86 struct samsung_clk_pll *pll = to_clk_pll(hw);
87 u32 tmp;
89 tmp = readl_relaxed(pll->con_reg);
90 tmp &= ~BIT(pll->enable_offs);
91 writel_relaxed(tmp, pll->con_reg);
95 * PLL2126 Clock Type
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)
105 static unsigned long samsung_pll2126_recalc_rate(struct clk_hw *hw,
106 unsigned long parent_rate)
108 struct samsung_clk_pll *pll = to_clk_pll(hw);
109 u32 pll_con, mdiv, pdiv, sdiv;
110 u64 fvco = parent_rate;
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;
117 fvco *= (mdiv + 8);
118 do_div(fvco, (pdiv + 2) << sdiv);
120 return (unsigned long)fvco;
123 static const struct clk_ops samsung_pll2126_clk_ops = {
124 .recalc_rate = samsung_pll2126_recalc_rate,
128 * PLL3000 Clock Type
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)
138 static unsigned long samsung_pll3000_recalc_rate(struct clk_hw *hw,
139 unsigned long parent_rate)
141 struct samsung_clk_pll *pll = to_clk_pll(hw);
142 u32 pll_con, mdiv, pdiv, sdiv;
143 u64 fvco = parent_rate;
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;
150 fvco *= (2 * (mdiv + 8));
151 do_div(fvco, pdiv << sdiv);
153 return (unsigned long)fvco;
156 static const struct clk_ops samsung_pll3000_clk_ops = {
157 .recalc_rate = samsung_pll3000_recalc_rate,
161 * PLL35xx Clock Type
163 /* Maximum lock time can be 270 * PDIV cycles */
164 #define PLL35XX_LOCK_FACTOR (270)
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)
175 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
176 unsigned long parent_rate)
178 struct samsung_clk_pll *pll = to_clk_pll(hw);
179 u32 mdiv, pdiv, sdiv, pll_con;
180 u64 fvco = parent_rate;
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;
187 fvco *= mdiv;
188 do_div(fvco, (pdiv << sdiv));
190 return (unsigned long)fvco;
193 static inline bool samsung_pll35xx_mp_change(
194 const struct samsung_pll_rate_table *rate, u32 pll_con)
196 u32 old_mdiv, old_pdiv;
198 old_mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
199 old_pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
201 return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv);
204 static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
205 unsigned long prate)
207 struct samsung_clk_pll *pll = to_clk_pll(hw);
208 const struct samsung_pll_rate_table *rate;
209 u32 tmp;
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;
219 tmp = readl_relaxed(pll->con_reg);
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);
227 return 0;
230 /* Set PLL lock time. */
231 writel_relaxed(rate->pdiv * PLL35XX_LOCK_FACTOR,
232 pll->lock_reg);
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);
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)));
250 return 0;
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,
261 static const struct clk_ops samsung_pll35xx_clk_min_ops = {
262 .recalc_rate = samsung_pll35xx_recalc_rate,
266 * PLL36xx Clock Type
268 /* Maximum lock time can be 3000 * PDIV cycles */
269 #define PLL36XX_LOCK_FACTOR (3000)
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)
282 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
283 unsigned long parent_rate)
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;
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);
297 fvco *= (mdiv << 16) + kdiv;
298 do_div(fvco, (pdiv << sdiv));
299 fvco >>= 16;
301 return (unsigned long)fvco;
304 static inline bool samsung_pll36xx_mpk_change(
305 const struct samsung_pll_rate_table *rate, u32 pll_con0, u32 pll_con1)
307 u32 old_mdiv, old_pdiv, old_kdiv;
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;
313 return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
314 rate->kdiv != old_kdiv);
317 static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
318 unsigned long parent_rate)
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;
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;
331 pll_con0 = readl_relaxed(pll->con_reg);
332 pll_con1 = readl_relaxed(pll->con_reg + 4);
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);
340 return 0;
343 /* Set PLL lock time. */
344 writel_relaxed(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg);
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);
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);
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)));
367 return 0;
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,
378 static const struct clk_ops samsung_pll36xx_clk_min_ops = {
379 .recalc_rate = samsung_pll36xx_recalc_rate,
383 * PLL45xx Clock Type
385 #define PLL4502_LOCK_FACTOR 400
386 #define PLL4508_LOCK_FACTOR 240
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)
397 #define PLL45XX_ENABLE BIT(31)
398 #define PLL45XX_LOCKED BIT(29)
400 static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw,
401 unsigned long parent_rate)
403 struct samsung_clk_pll *pll = to_clk_pll(hw);
404 u32 mdiv, pdiv, sdiv, pll_con;
405 u64 fvco = parent_rate;
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;
412 if (pll->type == pll_4508)
413 sdiv = sdiv - 1;
415 fvco *= mdiv;
416 do_div(fvco, (pdiv << sdiv));
418 return (unsigned long)fvco;
421 static bool samsung_pll45xx_mp_change(u32 pll_con0, u32 pll_con1,
422 const struct samsung_pll_rate_table *rate)
424 u32 old_mdiv, old_pdiv, old_afc;
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;
430 return (old_mdiv != rate->mdiv || old_pdiv != rate->pdiv
431 || old_afc != rate->afc);
434 static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
435 unsigned long prate)
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;
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;
450 con0 = readl_relaxed(pll->con_reg);
451 con1 = readl_relaxed(pll->con_reg + 0x4);
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);
459 return 0;
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);
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);
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;
487 /* Set new configuration. */
488 writel_relaxed(con1, pll->con_reg + 0x4);
489 writel_relaxed(con0, pll->con_reg);
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);
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;
502 cpu_relax();
505 return 0;
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,
514 static const struct clk_ops samsung_pll45xx_clk_min_ops = {
515 .recalc_rate = samsung_pll45xx_recalc_rate,
519 * PLL46xx Clock Type
521 #define PLL46XX_LOCK_FACTOR 3000
523 #define PLL46XX_VSEL_MASK (1)
524 #define PLL46XX_MDIV_MASK (0x1FF)
525 #define PLL1460X_MDIV_MASK (0x3FF)
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)
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)
543 #define PLL46XX_ENABLE BIT(31)
544 #define PLL46XX_LOCKED BIT(29)
545 #define PLL46XX_VSEL BIT(27)
547 static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw,
548 unsigned long parent_rate)
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;
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;
563 shift = ((pll->type == pll_4600) || (pll->type == pll_1460x)) ? 16 : 10;
565 fvco *= (mdiv << shift) + kdiv;
566 do_div(fvco, (pdiv << sdiv));
567 fvco >>= shift;
569 return (unsigned long)fvco;
572 static bool samsung_pll46xx_mpk_change(u32 pll_con0, u32 pll_con1,
573 const struct samsung_pll_rate_table *rate)
575 u32 old_mdiv, old_pdiv, old_kdiv;
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;
581 return (old_mdiv != rate->mdiv || old_pdiv != rate->pdiv
582 || old_kdiv != rate->kdiv);
585 static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
586 unsigned long prate)
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;
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;
601 con0 = readl_relaxed(pll->con_reg);
602 con1 = readl_relaxed(pll->con_reg + 0x4);
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);
610 return 0;
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;
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;
632 con0 |= (rate->mdiv << PLL46XX_MDIV_SHIFT) |
633 (rate->pdiv << PLL46XX_PDIV_SHIFT) |
634 (rate->sdiv << PLL46XX_SDIV_SHIFT);
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);
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);
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);
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;
661 cpu_relax();
664 return 0;
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,
673 static const struct clk_ops samsung_pll46xx_clk_min_ops = {
674 .recalc_rate = samsung_pll46xx_recalc_rate,
678 * PLL6552 Clock Type
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
690 static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw,
691 unsigned long parent_rate)
693 struct samsung_clk_pll *pll = to_clk_pll(hw);
694 u32 mdiv, pdiv, sdiv, pll_con;
695 u64 fvco = parent_rate;
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;
705 sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK;
707 fvco *= mdiv;
708 do_div(fvco, (pdiv << sdiv));
710 return (unsigned long)fvco;
713 static const struct clk_ops samsung_pll6552_clk_ops = {
714 .recalc_rate = samsung_pll6552_recalc_rate,
718 * PLL6553 Clock Type
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
730 static unsigned long samsung_pll6553_recalc_rate(struct clk_hw *hw,
731 unsigned long parent_rate)
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;
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;
744 fvco *= (mdiv << 16) + kdiv;
745 do_div(fvco, (pdiv << sdiv));
746 fvco >>= 16;
748 return (unsigned long)fvco;
751 static const struct clk_ops samsung_pll6553_clk_ops = {
752 .recalc_rate = samsung_pll6553_recalc_rate,
756 * PLL Clock Type of S3C24XX before S3C2443
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)
766 #define PLLS3C2410_ENABLE_REG_OFFSET 0x10
768 static unsigned long samsung_s3c2410_pll_recalc_rate(struct clk_hw *hw,
769 unsigned long parent_rate)
771 struct samsung_clk_pll *pll = to_clk_pll(hw);
772 u32 pll_con, mdiv, pdiv, sdiv;
773 u64 fvco = parent_rate;
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;
780 fvco *= (mdiv + 8);
781 do_div(fvco, (pdiv + 2) << sdiv);
783 return (unsigned int)fvco;
786 static unsigned long samsung_s3c2440_mpll_recalc_rate(struct clk_hw *hw,
787 unsigned long parent_rate)
789 struct samsung_clk_pll *pll = to_clk_pll(hw);
790 u32 pll_con, mdiv, pdiv, sdiv;
791 u64 fvco = parent_rate;
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;
798 fvco *= (2 * (mdiv + 8));
799 do_div(fvco, (pdiv + 2) << sdiv);
801 return (unsigned int)fvco;
804 static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate,
805 unsigned long prate)
807 struct samsung_clk_pll *pll = to_clk_pll(hw);
808 const struct samsung_pll_rate_table *rate;
809 u32 tmp;
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;
819 tmp = readl_relaxed(pll->con_reg);
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);
830 /* Time to settle according to the manual */
831 udelay(300);
833 return 0;
836 static int samsung_s3c2410_pll_enable(struct clk_hw *hw, int bit, bool enable)
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;
842 if (enable)
843 pll_en &= ~BIT(bit);
844 else
845 pll_en |= BIT(bit);
847 writel_relaxed(pll_en, pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
849 /* if we started the UPLL, then allow to settle */
850 if (enable && (pll_en_orig & BIT(bit)))
851 udelay(300);
853 return 0;
856 static int samsung_s3c2410_mpll_enable(struct clk_hw *hw)
858 return samsung_s3c2410_pll_enable(hw, 5, true);
861 static void samsung_s3c2410_mpll_disable(struct clk_hw *hw)
863 samsung_s3c2410_pll_enable(hw, 5, false);
866 static int samsung_s3c2410_upll_enable(struct clk_hw *hw)
868 return samsung_s3c2410_pll_enable(hw, 7, true);
871 static void samsung_s3c2410_upll_disable(struct clk_hw *hw)
873 samsung_s3c2410_pll_enable(hw, 7, false);
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,
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,
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,
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,
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,
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,
919 * PLL2550x Clock Type
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)
931 static unsigned long samsung_pll2550x_recalc_rate(struct clk_hw *hw,
932 unsigned long parent_rate)
934 struct samsung_clk_pll *pll = to_clk_pll(hw);
935 u32 r, p, m, s, pll_stat;
936 u64 fvco = parent_rate;
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;
946 fvco *= m;
947 do_div(fvco, (p << s));
949 return (unsigned long)fvco;
952 static const struct clk_ops samsung_pll2550x_clk_ops = {
953 .recalc_rate = samsung_pll2550x_recalc_rate,
957 * PLL2550xx Clock Type
960 /* Maximum lock time can be 270 * PDIV cycles */
961 #define PLL2550XX_LOCK_FACTOR 270
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
972 static unsigned long samsung_pll2550xx_recalc_rate(struct clk_hw *hw,
973 unsigned long parent_rate)
975 struct samsung_clk_pll *pll = to_clk_pll(hw);
976 u32 mdiv, pdiv, sdiv, pll_con;
977 u64 fvco = parent_rate;
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;
984 fvco *= mdiv;
985 do_div(fvco, (pdiv << sdiv));
987 return (unsigned long)fvco;
990 static inline bool samsung_pll2550xx_mp_change(u32 mdiv, u32 pdiv, u32 pll_con)
992 u32 old_mdiv, old_pdiv;
994 old_mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK;
995 old_pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK;
997 return mdiv != old_mdiv || pdiv != old_pdiv;
1000 static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate,
1001 unsigned long prate)
1003 struct samsung_clk_pll *pll = to_clk_pll(hw);
1004 const struct samsung_pll_rate_table *rate;
1005 u32 tmp;
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;
1015 tmp = readl_relaxed(pll->con_reg);
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);
1023 return 0;
1026 /* Set PLL lock time. */
1027 writel_relaxed(rate->pdiv * PLL2550XX_LOCK_FACTOR, pll->lock_reg);
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);
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)));
1045 return 0;
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,
1054 static const struct clk_ops samsung_pll2550xx_clk_min_ops = {
1055 .recalc_rate = samsung_pll2550xx_recalc_rate,
1059 * PLL2650x Clock Type
1062 /* Maximum lock time can be 3000 * PDIV cycles */
1063 #define PLL2650X_LOCK_FACTOR 3000
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
1077 static unsigned long samsung_pll2650x_recalc_rate(struct clk_hw *hw,
1078 unsigned long parent_rate)
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;
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;
1090 pll_con1 = readl_relaxed(pll->con_reg + 4);
1091 kdiv = (s16)((pll_con1 >> PLL2650X_K_SHIFT) & PLL2650X_K_MASK);
1093 fout *= (mdiv << 16) + kdiv;
1094 do_div(fout, (pdiv << sdiv));
1095 fout >>= 16;
1097 return (unsigned long)fout;
1100 static int samsung_pll2650x_set_rate(struct clk_hw *hw, unsigned long drate,
1101 unsigned long prate)
1103 struct samsung_clk_pll *pll = to_clk_pll(hw);
1104 const struct samsung_pll_rate_table *rate;
1105 u32 con0, con1;
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;
1115 con0 = readl_relaxed(pll->con_reg);
1116 con1 = readl_relaxed(pll->con_reg + 4);
1118 /* Set PLL lock time. */
1119 writel_relaxed(rate->pdiv * PLL2650X_LOCK_FACTOR, pll->lock_reg);
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);
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);
1135 do {
1136 cpu_relax();
1137 con0 = readl_relaxed(pll->con_reg);
1138 } while (!(con0 & (PLL2650X_LOCK_STAT_MASK
1139 << PLL2650X_LOCK_STAT_SHIFT)));
1141 return 0;
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,
1150 static const struct clk_ops samsung_pll2650x_clk_min_ops = {
1151 .recalc_rate = samsung_pll2650x_recalc_rate,
1155 * PLL2650XX Clock Type
1158 /* Maximum lock time can be 3000 * PDIV cycles */
1159 #define PLL2650XX_LOCK_FACTOR 3000
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
1173 static unsigned long samsung_pll2650xx_recalc_rate(struct clk_hw *hw,
1174 unsigned long parent_rate)
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;
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);
1188 fvco *= (mdiv << 16) + kdiv;
1189 do_div(fvco, (pdiv << sdiv));
1190 fvco >>= 16;
1192 return (unsigned long)fvco;
1195 static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate,
1196 unsigned long parent_rate)
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;
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;
1209 pll_con0 = readl_relaxed(pll->con_reg);
1210 pll_con2 = readl_relaxed(pll->con_reg + 8);
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;
1222 pll_con2 &= ~(PLL2650XX_KDIV_MASK << PLL2650XX_KDIV_SHIFT);
1223 pll_con2 |= ((~(rate->kdiv) + 1) & PLL2650XX_KDIV_MASK)
1224 << PLL2650XX_KDIV_SHIFT;
1226 /* Set PLL lock time. */
1227 writel_relaxed(PLL2650XX_LOCK_FACTOR * rate->pdiv, pll->lock_reg);
1229 writel_relaxed(pll_con0, pll->con_reg);
1230 writel_relaxed(pll_con2, pll->con_reg + 8);
1232 do {
1233 tmp = readl_relaxed(pll->con_reg);
1234 } while (!(tmp & (0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT)));
1236 return 0;
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,
1245 static const struct clk_ops samsung_pll2650xx_clk_min_ops = {
1246 .recalc_rate = samsung_pll2650xx_recalc_rate,
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)
1253 struct samsung_clk_pll *pll;
1254 struct clk_init_data init;
1255 int ret, len;
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;
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;
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++;
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);
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);
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;
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);
1394 return;
1397 samsung_clk_add_lookup(ctx, &pll->hw, pll_clk->id);
1400 void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
1401 const struct samsung_pll_clock *pll_list,
1402 unsigned int nr_pll, void __iomem *base)
1404 int cnt;
1406 for (cnt = 0; cnt < nr_pll; cnt++)
1407 _samsung_clk_register_pll(ctx, &pll_list[cnt], base);