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