xref: /openbmc/linux/drivers/clk/samsung/clk-pll.c (revision ae213c44)
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>
13 #include <linux/hrtimer.h>
14 #include <linux/delay.h>
15 #include <linux/slab.h>
16 #include <linux/clk-provider.h>
17 #include <linux/io.h>
18 #include "clk.h"
19 #include "clk-pll.h"
20 
21 #define PLL_TIMEOUT_MS		10
22 
23 struct samsung_clk_pll {
24 	struct clk_hw		hw;
25 	void __iomem		*lock_reg;
26 	void __iomem		*con_reg;
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;
31 	enum samsung_pll_type	type;
32 	unsigned int		rate_count;
33 	const struct samsung_pll_rate_table *rate_table;
34 };
35 
36 #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
37 
38 static 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 
52 static 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 
69 static 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 
87 static 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 
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 
108 static 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 
115 	pll_con = readl_relaxed(pll->con_reg);
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 
126 static 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 
141 static 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 
148 	pll_con = readl_relaxed(pll->con_reg);
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 
159 static const struct clk_ops samsung_pll3000_clk_ops = {
160 	.recalc_rate = samsung_pll3000_recalc_rate,
161 };
162 
163 /*
164  * PLL35xx Clock Type
165  */
166 /* Maximum lock time can be 270 * PDIV cycles */
167 #define PLL35XX_LOCK_FACTOR	(270)
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)
175 #define PLL35XX_LOCK_STAT_SHIFT	(29)
176 #define PLL35XX_ENABLE_SHIFT	(31)
177 
178 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
179 				unsigned long parent_rate)
180 {
181 	struct samsung_clk_pll *pll = to_clk_pll(hw);
182 	u32 mdiv, pdiv, sdiv, pll_con;
183 	u64 fvco = parent_rate;
184 
185 	pll_con = readl_relaxed(pll->con_reg);
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 
196 static 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 
207 static 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__,
218 			drate, clk_hw_get_name(hw));
219 		return -EINVAL;
220 	}
221 
222 	tmp = readl_relaxed(pll->con_reg);
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;
228 		writel_relaxed(tmp, pll->con_reg);
229 
230 		return 0;
231 	}
232 
233 	/* Set PLL lock time. */
234 	writel_relaxed(rate->pdiv * PLL35XX_LOCK_FACTOR,
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);
244 	writel_relaxed(tmp, pll->con_reg);
245 
246 	/* Wait until the PLL is locked if it is enabled. */
247 	if (tmp & BIT(pll->enable_offs)) {
248 		do {
249 			cpu_relax();
250 			tmp = readl_relaxed(pll->con_reg);
251 		} while (!(tmp & BIT(pll->lock_offs)));
252 	}
253 	return 0;
254 }
255 
256 static const struct clk_ops samsung_pll35xx_clk_ops = {
257 	.recalc_rate = samsung_pll35xx_recalc_rate,
258 	.round_rate = samsung_pll_round_rate,
259 	.set_rate = samsung_pll35xx_set_rate,
260 	.enable = samsung_pll3xxx_enable,
261 	.disable = samsung_pll3xxx_disable,
262 };
263 
264 static const struct clk_ops samsung_pll35xx_clk_min_ops = {
265 	.recalc_rate = samsung_pll35xx_recalc_rate,
266 };
267 
268 /*
269  * PLL36xx Clock Type
270  */
271 /* Maximum lock time can be 3000 * PDIV cycles */
272 #define PLL36XX_LOCK_FACTOR    (3000)
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)
281 #define PLL36XX_KDIV_SHIFT	(0)
282 #define PLL36XX_LOCK_STAT_SHIFT	(29)
283 #define PLL36XX_ENABLE_SHIFT	(31)
284 
285 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
286 				unsigned long parent_rate)
287 {
288 	struct samsung_clk_pll *pll = to_clk_pll(hw);
289 	u32 mdiv, pdiv, sdiv, pll_con0, pll_con1;
290 	s16 kdiv;
291 	u64 fvco = parent_rate;
292 
293 	pll_con0 = readl_relaxed(pll->con_reg);
294 	pll_con1 = readl_relaxed(pll->con_reg + 4);
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;
298 	kdiv = (s16)(pll_con1 & PLL36XX_KDIV_MASK);
299 
300 	fvco *= (mdiv << 16) + kdiv;
301 	do_div(fvco, (pdiv << sdiv));
302 	fvco >>= 16;
303 
304 	return (unsigned long)fvco;
305 }
306 
307 static 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 
320 static 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__,
330 			drate, clk_hw_get_name(hw));
331 		return -EINVAL;
332 	}
333 
334 	pll_con0 = readl_relaxed(pll->con_reg);
335 	pll_con1 = readl_relaxed(pll->con_reg + 4);
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);
341 		writel_relaxed(pll_con0, pll->con_reg);
342 
343 		return 0;
344 	}
345 
346 	/* Set PLL lock time. */
347 	writel_relaxed(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg);
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);
356 	writel_relaxed(pll_con0, pll->con_reg);
357 
358 	pll_con1 &= ~(PLL36XX_KDIV_MASK << PLL36XX_KDIV_SHIFT);
359 	pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT;
360 	writel_relaxed(pll_con1, pll->con_reg + 4);
361 
362 	/* wait_lock_time */
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 	}
369 
370 	return 0;
371 }
372 
373 static const struct clk_ops samsung_pll36xx_clk_ops = {
374 	.recalc_rate = samsung_pll36xx_recalc_rate,
375 	.set_rate = samsung_pll36xx_set_rate,
376 	.round_rate = samsung_pll_round_rate,
377 	.enable = samsung_pll3xxx_enable,
378 	.disable = samsung_pll3xxx_disable,
379 };
380 
381 static const struct clk_ops samsung_pll36xx_clk_min_ops = {
382 	.recalc_rate = samsung_pll36xx_recalc_rate,
383 };
384 
385 /*
386  * PLL45xx Clock Type
387  */
388 #define PLL4502_LOCK_FACTOR	400
389 #define PLL4508_LOCK_FACTOR	240
390 
391 #define PLL45XX_MDIV_MASK	(0x3FF)
392 #define PLL45XX_PDIV_MASK	(0x3F)
393 #define PLL45XX_SDIV_MASK	(0x7)
394 #define PLL45XX_AFC_MASK	(0x1F)
395 #define PLL45XX_MDIV_SHIFT	(16)
396 #define PLL45XX_PDIV_SHIFT	(8)
397 #define PLL45XX_SDIV_SHIFT	(0)
398 #define PLL45XX_AFC_SHIFT	(0)
399 
400 #define PLL45XX_ENABLE		BIT(31)
401 #define PLL45XX_LOCKED		BIT(29)
402 
403 static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw,
404 				unsigned long parent_rate)
405 {
406 	struct samsung_clk_pll *pll = to_clk_pll(hw);
407 	u32 mdiv, pdiv, sdiv, pll_con;
408 	u64 fvco = parent_rate;
409 
410 	pll_con = readl_relaxed(pll->con_reg);
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 
424 static 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 
437 static 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__,
449 			drate, clk_hw_get_name(hw));
450 		return -EINVAL;
451 	}
452 
453 	con0 = readl_relaxed(pll->con_reg);
454 	con1 = readl_relaxed(pll->con_reg + 0x4);
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;
460 		writel_relaxed(con0, pll->con_reg);
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. */
474 	con1 = readl_relaxed(pll->con_reg + 0x4);
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:
481 		writel_relaxed(rate->pdiv * PLL4502_LOCK_FACTOR, pll->lock_reg);
482 		break;
483 	case pll_4508:
484 		writel_relaxed(rate->pdiv * PLL4508_LOCK_FACTOR, pll->lock_reg);
485 		break;
486 	default:
487 		break;
488 	}
489 
490 	/* Set new configuration. */
491 	writel_relaxed(con1, pll->con_reg + 0x4);
492 	writel_relaxed(con0, pll->con_reg);
493 
494 	/* Wait for locking. */
495 	start = ktime_get();
496 	while (!(readl_relaxed(pll->con_reg) & PLL45XX_LOCKED)) {
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",
501 					__func__, clk_hw_get_name(hw));
502 			return -EFAULT;
503 		}
504 
505 		cpu_relax();
506 	}
507 
508 	return 0;
509 }
510 
511 static const struct clk_ops samsung_pll45xx_clk_ops = {
512 	.recalc_rate = samsung_pll45xx_recalc_rate,
513 	.round_rate = samsung_pll_round_rate,
514 	.set_rate = samsung_pll45xx_set_rate,
515 };
516 
517 static const struct clk_ops samsung_pll45xx_clk_min_ops = {
518 	.recalc_rate = samsung_pll45xx_recalc_rate,
519 };
520 
521 /*
522  * PLL46xx Clock Type
523  */
524 #define PLL46XX_LOCK_FACTOR	3000
525 
526 #define PLL46XX_VSEL_MASK	(1)
527 #define PLL46XX_MDIV_MASK	(0x1FF)
528 #define PLL1460X_MDIV_MASK	(0x3FF)
529 
530 #define PLL46XX_PDIV_MASK	(0x3F)
531 #define PLL46XX_SDIV_MASK	(0x7)
532 #define PLL46XX_VSEL_SHIFT	(27)
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)
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)
549 
550 static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw,
551 				unsigned long parent_rate)
552 {
553 	struct samsung_clk_pll *pll = to_clk_pll(hw);
554 	u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1, shift;
555 	u64 fvco = parent_rate;
556 
557 	pll_con0 = readl_relaxed(pll->con_reg);
558 	pll_con1 = readl_relaxed(pll->con_reg + 4);
559 	mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & ((pll->type == pll_1460x) ?
560 				PLL1460X_MDIV_MASK : PLL46XX_MDIV_MASK);
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 
566 	shift = ((pll->type == pll_4600) || (pll->type == pll_1460x)) ? 16 : 10;
567 
568 	fvco *= (mdiv << shift) + kdiv;
569 	do_div(fvco, (pdiv << sdiv));
570 	fvco >>= shift;
571 
572 	return (unsigned long)fvco;
573 }
574 
575 static 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 
588 static 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__,
600 			drate, clk_hw_get_name(hw));
601 		return -EINVAL;
602 	}
603 
604 	con0 = readl_relaxed(pll->con_reg);
605 	con1 = readl_relaxed(pll->con_reg + 0x4);
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;
611 		writel_relaxed(con0, pll->con_reg);
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. */
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) |
629 			(PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT) |
630 			(PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT) |
631 			(PLL46XX_VSEL_MASK << PLL46XX_VSEL_SHIFT));
632 		con0 |=	rate->vsel << PLL46XX_VSEL_SHIFT;
633 	}
634 
635 	con0 |= (rate->mdiv << PLL46XX_MDIV_SHIFT) |
636 			(rate->pdiv << PLL46XX_PDIV_SHIFT) |
637 			(rate->sdiv << PLL46XX_SDIV_SHIFT);
638 
639 	/* Set PLL K, MFR and MRR values. */
640 	con1 = readl_relaxed(pll->con_reg + 0x4);
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 */
649 	writel_relaxed(lock, pll->lock_reg);
650 	writel_relaxed(con0, pll->con_reg);
651 	writel_relaxed(con1, pll->con_reg + 0x4);
652 
653 	/* Wait for locking. */
654 	start = ktime_get();
655 	while (!(readl_relaxed(pll->con_reg) & PLL46XX_LOCKED)) {
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",
660 					__func__, clk_hw_get_name(hw));
661 			return -EFAULT;
662 		}
663 
664 		cpu_relax();
665 	}
666 
667 	return 0;
668 }
669 
670 static const struct clk_ops samsung_pll46xx_clk_ops = {
671 	.recalc_rate = samsung_pll46xx_recalc_rate,
672 	.round_rate = samsung_pll_round_rate,
673 	.set_rate = samsung_pll46xx_set_rate,
674 };
675 
676 static const struct clk_ops samsung_pll46xx_clk_min_ops = {
677 	.recalc_rate = samsung_pll46xx_recalc_rate,
678 };
679 
680 /*
681  * PLL6552 Clock Type
682  */
683 
684 #define PLL6552_MDIV_MASK	0x3ff
685 #define PLL6552_PDIV_MASK	0x3f
686 #define PLL6552_SDIV_MASK	0x7
687 #define PLL6552_MDIV_SHIFT	16
688 #define PLL6552_MDIV_SHIFT_2416	14
689 #define PLL6552_PDIV_SHIFT	8
690 #define PLL6552_PDIV_SHIFT_2416	5
691 #define PLL6552_SDIV_SHIFT	0
692 
693 static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw,
694 						unsigned long parent_rate)
695 {
696 	struct samsung_clk_pll *pll = to_clk_pll(hw);
697 	u32 mdiv, pdiv, sdiv, pll_con;
698 	u64 fvco = parent_rate;
699 
700 	pll_con = readl_relaxed(pll->con_reg);
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 	}
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 
716 static const struct clk_ops samsung_pll6552_clk_ops = {
717 	.recalc_rate = samsung_pll6552_recalc_rate,
718 };
719 
720 /*
721  * PLL6553 Clock Type
722  */
723 
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 
733 static unsigned long samsung_pll6553_recalc_rate(struct clk_hw *hw,
734 						unsigned long parent_rate)
735 {
736 	struct samsung_clk_pll *pll = to_clk_pll(hw);
737 	u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
738 	u64 fvco = parent_rate;
739 
740 	pll_con0 = readl_relaxed(pll->con_reg);
741 	pll_con1 = readl_relaxed(pll->con_reg + 0x4);
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 
754 static const struct clk_ops samsung_pll6553_clk_ops = {
755 	.recalc_rate = samsung_pll6553_recalc_rate,
756 };
757 
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 
771 static 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 
778 	pll_con = readl_relaxed(pll->con_reg);
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 
789 static 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 
796 	pll_con = readl_relaxed(pll->con_reg);
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 
807 static 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__,
818 			drate, clk_hw_get_name(hw));
819 		return -EINVAL;
820 	}
821 
822 	tmp = readl_relaxed(pll->con_reg);
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);
831 	writel_relaxed(tmp, pll->con_reg);
832 
833 	/* Time to settle according to the manual */
834 	udelay(300);
835 
836 	return 0;
837 }
838 
839 static int samsung_s3c2410_pll_enable(struct clk_hw *hw, int bit, bool enable)
840 {
841 	struct samsung_clk_pll *pll = to_clk_pll(hw);
842 	u32 pll_en = readl_relaxed(pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
843 	u32 pll_en_orig = pll_en;
844 
845 	if (enable)
846 		pll_en &= ~BIT(bit);
847 	else
848 		pll_en |= BIT(bit);
849 
850 	writel_relaxed(pll_en, pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
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 
859 static int samsung_s3c2410_mpll_enable(struct clk_hw *hw)
860 {
861 	return samsung_s3c2410_pll_enable(hw, 5, true);
862 }
863 
864 static void samsung_s3c2410_mpll_disable(struct clk_hw *hw)
865 {
866 	samsung_s3c2410_pll_enable(hw, 5, false);
867 }
868 
869 static int samsung_s3c2410_upll_enable(struct clk_hw *hw)
870 {
871 	return samsung_s3c2410_pll_enable(hw, 7, true);
872 }
873 
874 static void samsung_s3c2410_upll_disable(struct clk_hw *hw)
875 {
876 	samsung_s3c2410_pll_enable(hw, 7, false);
877 }
878 
879 static 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 
885 static 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 
891 static 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 
897 static 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 
905 static 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 
913 static 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 
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 
934 static unsigned long samsung_pll2550x_recalc_rate(struct clk_hw *hw,
935 				unsigned long parent_rate)
936 {
937 	struct samsung_clk_pll *pll = to_clk_pll(hw);
938 	u32 r, p, m, s, pll_stat;
939 	u64 fvco = parent_rate;
940 
941 	pll_stat = readl_relaxed(pll->con_reg);
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 
955 static const struct clk_ops samsung_pll2550x_clk_ops = {
956 	.recalc_rate = samsung_pll2550x_recalc_rate,
957 };
958 
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 
975 static 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 
982 	pll_con = readl_relaxed(pll->con_reg);
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 
993 static 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 
1003 static 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__,
1014 			drate, clk_hw_get_name(hw));
1015 		return -EINVAL;
1016 	}
1017 
1018 	tmp = readl_relaxed(pll->con_reg);
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;
1024 		writel_relaxed(tmp, pll->con_reg);
1025 
1026 		return 0;
1027 	}
1028 
1029 	/* Set PLL lock time. */
1030 	writel_relaxed(rate->pdiv * PLL2550XX_LOCK_FACTOR, pll->lock_reg);
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);
1039 	writel_relaxed(tmp, pll->con_reg);
1040 
1041 	/* wait_lock_time */
1042 	do {
1043 		cpu_relax();
1044 		tmp = readl_relaxed(pll->con_reg);
1045 	} while (!(tmp & (PLL2550XX_LOCK_STAT_MASK
1046 			<< PLL2550XX_LOCK_STAT_SHIFT)));
1047 
1048 	return 0;
1049 }
1050 
1051 static 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 
1057 static const struct clk_ops samsung_pll2550xx_clk_min_ops = {
1058 	.recalc_rate = samsung_pll2550xx_recalc_rate,
1059 };
1060 
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 
1080 static 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 
1103 static 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 
1147 static 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 
1153 static const struct clk_ops samsung_pll2650x_clk_min_ops = {
1154 	.recalc_rate = samsung_pll2650x_recalc_rate,
1155 };
1156 
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 
1176 static 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 
1184 	pll_con0 = readl_relaxed(pll->con_reg);
1185 	pll_con2 = readl_relaxed(pll->con_reg + 8);
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 
1198 static 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__,
1208 			drate, clk_hw_get_name(hw));
1209 		return -EINVAL;
1210 	}
1211 
1212 	pll_con0 = readl_relaxed(pll->con_reg);
1213 	pll_con2 = readl_relaxed(pll->con_reg + 8);
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. */
1230 	writel_relaxed(PLL2650XX_LOCK_FACTOR * rate->pdiv, pll->lock_reg);
1231 
1232 	writel_relaxed(pll_con0, pll->con_reg);
1233 	writel_relaxed(pll_con2, pll->con_reg + 8);
1234 
1235 	do {
1236 		tmp = readl_relaxed(pll->con_reg);
1237 	} while (!(tmp & (0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT)));
1238 
1239 	return 0;
1240 }
1241 
1242 static 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 
1248 static const struct clk_ops samsung_pll2650xx_clk_min_ops = {
1249 	.recalc_rate = samsung_pll2650xx_recalc_rate,
1250 };
1251 
1252 static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
1253 				const struct samsung_pll_clock *pll_clk,
1254 				void __iomem *base)
1255 {
1256 	struct samsung_clk_pll *pll;
1257 	struct clk_init_data init;
1258 	int ret, len;
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 
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 
1287 	switch (pll_clk->type) {
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;
1294 	/* clk_ops for 35xx and 2550 are similar */
1295 	case pll_35xx:
1296 	case pll_2550:
1297 	case pll_1450x:
1298 	case pll_1451x:
1299 	case pll_1452x:
1300 		pll->enable_offs = PLL35XX_ENABLE_SHIFT;
1301 		pll->lock_offs = PLL35XX_LOCK_STAT_SHIFT;
1302 		if (!pll->rate_table)
1303 			init.ops = &samsung_pll35xx_clk_min_ops;
1304 		else
1305 			init.ops = &samsung_pll35xx_clk_ops;
1306 		break;
1307 	case pll_4500:
1308 		init.ops = &samsung_pll45xx_clk_min_ops;
1309 		break;
1310 	case pll_4502:
1311 	case pll_4508:
1312 		if (!pll->rate_table)
1313 			init.ops = &samsung_pll45xx_clk_min_ops;
1314 		else
1315 			init.ops = &samsung_pll45xx_clk_ops;
1316 		break;
1317 	/* clk_ops for 36xx and 2650 are similar */
1318 	case pll_36xx:
1319 	case pll_2650:
1320 		pll->enable_offs = PLL36XX_ENABLE_SHIFT;
1321 		pll->lock_offs = PLL36XX_LOCK_STAT_SHIFT;
1322 		if (!pll->rate_table)
1323 			init.ops = &samsung_pll36xx_clk_min_ops;
1324 		else
1325 			init.ops = &samsung_pll36xx_clk_ops;
1326 		break;
1327 	case pll_6552:
1328 	case pll_6552_s3c2416:
1329 		init.ops = &samsung_pll6552_clk_ops;
1330 		break;
1331 	case pll_6553:
1332 		init.ops = &samsung_pll6553_clk_ops;
1333 		break;
1334 	case pll_4600:
1335 	case pll_4650:
1336 	case pll_4650c:
1337 	case pll_1460x:
1338 		if (!pll->rate_table)
1339 			init.ops = &samsung_pll46xx_clk_min_ops;
1340 		else
1341 			init.ops = &samsung_pll46xx_clk_ops;
1342 		break;
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;
1361 	case pll_2550x:
1362 		init.ops = &samsung_pll2550x_clk_ops;
1363 		break;
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;
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;
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;
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 
1392 	ret = clk_hw_register(ctx->dev, &pll->hw);
1393 	if (ret) {
1394 		pr_err("%s: failed to register pll clock %s : %d\n",
1395 			__func__, pll_clk->name, ret);
1396 		kfree(pll);
1397 		return;
1398 	}
1399 
1400 	samsung_clk_add_lookup(ctx, &pll->hw, pll_clk->id);
1401 }
1402 
1403 void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
1404 			const struct samsung_pll_clock *pll_list,
1405 			unsigned int nr_pll, void __iomem *base)
1406 {
1407 	int cnt;
1408 
1409 	for (cnt = 0; cnt < nr_pll; cnt++)
1410 		_samsung_clk_register_pll(ctx, &pll_list[cnt], base);
1411 }
1412