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