1 // SPDX-License-Identifier: GPL-2.0-only
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.
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>
18 #define PLL_TIMEOUT_MS 10
20 struct samsung_clk_pll
{
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
;
41 for (i
= 0; i
< pll
->rate_count
; i
++) {
42 if (rate
== rate_table
[i
].rate
)
43 return &rate_table
[i
];
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
;
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
);
71 tmp
= readl_relaxed(pll
->con_reg
);
72 tmp
|= BIT(pll
->enable_offs
);
73 writel_relaxed(tmp
, pll
->con_reg
);
78 tmp
= readl_relaxed(pll
->con_reg
);
79 } while (!(tmp
& BIT(pll
->lock_offs
)));
84 static void samsung_pll3xxx_disable(struct clk_hw
*hw
)
86 struct samsung_clk_pll
*pll
= to_clk_pll(hw
);
89 tmp
= readl_relaxed(pll
->con_reg
);
90 tmp
&= ~BIT(pll
->enable_offs
);
91 writel_relaxed(tmp
, pll
->con_reg
);
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
;
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
,
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
,
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
;
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
,
207 struct samsung_clk_pll
*pll
= to_clk_pll(hw
);
208 const struct samsung_pll_rate_table
*rate
;
211 /* Get required rate settings from table */
212 rate
= samsung_get_pll_settings(pll
, drate
);
214 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__
,
215 drate
, clk_hw_get_name(hw
));
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
);
230 /* Set PLL lock time. */
231 writel_relaxed(rate
->pdiv
* PLL35XX_LOCK_FACTOR
,
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
)) {
247 tmp
= readl_relaxed(pll
->con_reg
);
248 } while (!(tmp
& BIT(pll
->lock_offs
)));
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
,
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
;
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
));
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
);
326 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__
,
327 drate
, clk_hw_get_name(hw
));
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
);
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);
360 if (pll_con0
& BIT(pll
->enable_offs
)) {
363 tmp
= readl_relaxed(pll
->con_reg
);
364 } while (!(tmp
& BIT(pll
->lock_offs
)));
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
,
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
)
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
,
437 struct samsung_clk_pll
*pll
= to_clk_pll(hw
);
438 const struct samsung_pll_rate_table
*rate
;
442 /* Get required rate settings from table */
443 rate
= samsung_get_pll_settings(pll
, drate
);
445 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__
,
446 drate
, clk_hw_get_name(hw
));
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
);
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. */
478 writel_relaxed(rate
->pdiv
* PLL4502_LOCK_FACTOR
, pll
->lock_reg
);
481 writel_relaxed(rate
->pdiv
* PLL4508_LOCK_FACTOR
, pll
->lock_reg
);
487 /* Set new configuration. */
488 writel_relaxed(con1
, pll
->con_reg
+ 0x4);
489 writel_relaxed(con0
, pll
->con_reg
);
491 /* Wait for locking. */
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
));
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
,
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
));
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
,
588 struct samsung_clk_pll
*pll
= to_clk_pll(hw
);
589 const struct samsung_pll_rate_table
*rate
;
590 u32 con0
, con1
, lock
;
593 /* Get required rate settings from table */
594 rate
= samsung_get_pll_settings(pll
, drate
);
596 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__
,
597 drate
, clk_hw_get_name(hw
));
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
);
613 /* Set PLL lock time. */
614 lock
= rate
->pdiv
* PLL46XX_LOCK_FACTOR
;
616 /* Maximum lock time bitfield is 16-bit. */
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
));
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. */
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
));
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
,
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
;
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
;
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
,
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
));
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
;
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
,
807 struct samsung_clk_pll
*pll
= to_clk_pll(hw
);
808 const struct samsung_pll_rate_table
*rate
;
811 /* Get required rate settings from table */
812 rate
= samsung_get_pll_settings(pll
, drate
);
814 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__
,
815 drate
, clk_hw_get_name(hw
));
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 */
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
;
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
)))
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
;
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
;
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
;
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
;
1007 /* Get required rate settings from table */
1008 rate
= samsung_get_pll_settings(pll
, drate
);
1010 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__
,
1011 drate
, clk_hw_get_name(hw
));
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
);
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 */
1041 tmp
= readl_relaxed(pll
->con_reg
);
1042 } while (!(tmp
& (PLL2550XX_LOCK_STAT_MASK
1043 << PLL2550XX_LOCK_STAT_SHIFT
)));
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
;
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
));
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
;
1107 /* Get required rate settings from table */
1108 rate
= samsung_get_pll_settings(pll
, drate
);
1110 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__
,
1111 drate
, clk_hw_get_name(hw
));
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);
1137 con0
= readl_relaxed(pll
->con_reg
);
1138 } while (!(con0
& (PLL2650X_LOCK_STAT_MASK
1139 << PLL2650X_LOCK_STAT_SHIFT
)));
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
;
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
));
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
);
1204 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__
,
1205 drate
, clk_hw_get_name(hw
));
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);
1233 tmp
= readl_relaxed(pll
->con_reg
);
1234 } while (!(tmp
& (0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT
)));
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
,
1253 struct samsung_clk_pll
*pll
;
1254 struct clk_init_data init
;
1257 pll
= kzalloc(sizeof(*pll
), GFP_KERNEL
);
1259 pr_err("%s: could not allocate pll clk %s\n",
1260 __func__
, pll_clk
->name
);
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; )
1274 pll
->rate_count
= len
;
1275 pll
->rate_table
= kmemdup(pll_clk
->rate_table
,
1277 sizeof(struct samsung_pll_rate_table
),
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
) {
1286 init
.ops
= &samsung_pll2126_clk_ops
;
1289 init
.ops
= &samsung_pll3000_clk_ops
;
1291 /* clk_ops for 35xx and 2550 are similar */
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
;
1302 init
.ops
= &samsung_pll35xx_clk_ops
;
1305 init
.ops
= &samsung_pll45xx_clk_min_ops
;
1309 if (!pll
->rate_table
)
1310 init
.ops
= &samsung_pll45xx_clk_min_ops
;
1312 init
.ops
= &samsung_pll45xx_clk_ops
;
1314 /* clk_ops for 36xx and 2650 are similar */
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
;
1322 init
.ops
= &samsung_pll36xx_clk_ops
;
1325 case pll_6552_s3c2416
:
1326 init
.ops
= &samsung_pll6552_clk_ops
;
1329 init
.ops
= &samsung_pll6553_clk_ops
;
1335 if (!pll
->rate_table
)
1336 init
.ops
= &samsung_pll46xx_clk_min_ops
;
1338 init
.ops
= &samsung_pll46xx_clk_ops
;
1340 case pll_s3c2410_mpll
:
1341 if (!pll
->rate_table
)
1342 init
.ops
= &samsung_s3c2410_mpll_clk_min_ops
;
1344 init
.ops
= &samsung_s3c2410_mpll_clk_ops
;
1346 case pll_s3c2410_upll
:
1347 if (!pll
->rate_table
)
1348 init
.ops
= &samsung_s3c2410_upll_clk_min_ops
;
1350 init
.ops
= &samsung_s3c2410_upll_clk_ops
;
1352 case pll_s3c2440_mpll
:
1353 if (!pll
->rate_table
)
1354 init
.ops
= &samsung_s3c2440_mpll_clk_min_ops
;
1356 init
.ops
= &samsung_s3c2440_mpll_clk_ops
;
1359 init
.ops
= &samsung_pll2550x_clk_ops
;
1362 if (!pll
->rate_table
)
1363 init
.ops
= &samsung_pll2550xx_clk_min_ops
;
1365 init
.ops
= &samsung_pll2550xx_clk_ops
;
1368 if (!pll
->rate_table
)
1369 init
.ops
= &samsung_pll2650x_clk_min_ops
;
1371 init
.ops
= &samsung_pll2650x_clk_ops
;
1374 if (!pll
->rate_table
)
1375 init
.ops
= &samsung_pll2650xx_clk_min_ops
;
1377 init
.ops
= &samsung_pll2650xx_clk_ops
;
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
);
1391 pr_err("%s: failed to register pll clock %s : %d\n",
1392 __func__
, pll_clk
->name
, ret
);
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
)
1406 for (cnt
= 0; cnt
< nr_pll
; cnt
++)
1407 _samsung_clk_register_pll(ctx
, &pll_list
[cnt
], base
);