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