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