xref: /linux/drivers/clk/imx/clk-pll14xx.c (revision 4fd18fc38757217c746aa063ba9e4729814dc737)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2017-2018 NXP.
4  */
5 
6 #include <linux/bits.h>
7 #include <linux/clk-provider.h>
8 #include <linux/err.h>
9 #include <linux/export.h>
10 #include <linux/io.h>
11 #include <linux/iopoll.h>
12 #include <linux/slab.h>
13 #include <linux/jiffies.h>
14 
15 #include "clk.h"
16 
17 #define GNRL_CTL	0x0
18 #define DIV_CTL		0x4
19 #define LOCK_STATUS	BIT(31)
20 #define LOCK_SEL_MASK	BIT(29)
21 #define CLKE_MASK	BIT(11)
22 #define RST_MASK	BIT(9)
23 #define BYPASS_MASK	BIT(4)
24 #define MDIV_SHIFT	12
25 #define MDIV_MASK	GENMASK(21, 12)
26 #define PDIV_SHIFT	4
27 #define PDIV_MASK	GENMASK(9, 4)
28 #define SDIV_SHIFT	0
29 #define SDIV_MASK	GENMASK(2, 0)
30 #define KDIV_SHIFT	0
31 #define KDIV_MASK	GENMASK(15, 0)
32 
33 #define LOCK_TIMEOUT_US		10000
34 
35 struct clk_pll14xx {
36 	struct clk_hw			hw;
37 	void __iomem			*base;
38 	enum imx_pll14xx_type		type;
39 	const struct imx_pll14xx_rate_table *rate_table;
40 	int rate_count;
41 };
42 
43 #define to_clk_pll14xx(_hw) container_of(_hw, struct clk_pll14xx, hw)
44 
45 static const struct imx_pll14xx_rate_table imx_pll1416x_tbl[] = {
46 	PLL_1416X_RATE(1800000000U, 225, 3, 0),
47 	PLL_1416X_RATE(1600000000U, 200, 3, 0),
48 	PLL_1416X_RATE(1500000000U, 375, 3, 1),
49 	PLL_1416X_RATE(1400000000U, 350, 3, 1),
50 	PLL_1416X_RATE(1200000000U, 300, 3, 1),
51 	PLL_1416X_RATE(1000000000U, 250, 3, 1),
52 	PLL_1416X_RATE(800000000U,  200, 3, 1),
53 	PLL_1416X_RATE(750000000U,  250, 2, 2),
54 	PLL_1416X_RATE(700000000U,  350, 3, 2),
55 	PLL_1416X_RATE(600000000U,  300, 3, 2),
56 };
57 
58 static const struct imx_pll14xx_rate_table imx_pll1443x_tbl[] = {
59 	PLL_1443X_RATE(1039500000U, 173, 2, 1, 16384),
60 	PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
61 	PLL_1443X_RATE(594000000U, 198, 2, 2, 0),
62 	PLL_1443X_RATE(519750000U, 173, 2, 2, 16384),
63 	PLL_1443X_RATE(393216000U, 262, 2, 3, 9437),
64 	PLL_1443X_RATE(361267200U, 361, 3, 3, 17511),
65 };
66 
67 struct imx_pll14xx_clk imx_1443x_pll = {
68 	.type = PLL_1443X,
69 	.rate_table = imx_pll1443x_tbl,
70 	.rate_count = ARRAY_SIZE(imx_pll1443x_tbl),
71 };
72 EXPORT_SYMBOL_GPL(imx_1443x_pll);
73 
74 struct imx_pll14xx_clk imx_1443x_dram_pll = {
75 	.type = PLL_1443X,
76 	.rate_table = imx_pll1443x_tbl,
77 	.rate_count = ARRAY_SIZE(imx_pll1443x_tbl),
78 	.flags = CLK_GET_RATE_NOCACHE,
79 };
80 EXPORT_SYMBOL_GPL(imx_1443x_dram_pll);
81 
82 struct imx_pll14xx_clk imx_1416x_pll = {
83 	.type = PLL_1416X,
84 	.rate_table = imx_pll1416x_tbl,
85 	.rate_count = ARRAY_SIZE(imx_pll1416x_tbl),
86 };
87 EXPORT_SYMBOL_GPL(imx_1416x_pll);
88 
89 static const struct imx_pll14xx_rate_table *imx_get_pll_settings(
90 		struct clk_pll14xx *pll, unsigned long rate)
91 {
92 	const struct imx_pll14xx_rate_table *rate_table = pll->rate_table;
93 	int i;
94 
95 	for (i = 0; i < pll->rate_count; i++)
96 		if (rate == rate_table[i].rate)
97 			return &rate_table[i];
98 
99 	return NULL;
100 }
101 
102 static long clk_pll14xx_round_rate(struct clk_hw *hw, unsigned long rate,
103 			unsigned long *prate)
104 {
105 	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
106 	const struct imx_pll14xx_rate_table *rate_table = pll->rate_table;
107 	int i;
108 
109 	/* Assumming rate_table is in descending order */
110 	for (i = 0; i < pll->rate_count; i++)
111 		if (rate >= rate_table[i].rate)
112 			return rate_table[i].rate;
113 
114 	/* return minimum supported value */
115 	return rate_table[i - 1].rate;
116 }
117 
118 static unsigned long clk_pll1416x_recalc_rate(struct clk_hw *hw,
119 						  unsigned long parent_rate)
120 {
121 	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
122 	u32 mdiv, pdiv, sdiv, pll_div;
123 	u64 fvco = parent_rate;
124 
125 	pll_div = readl_relaxed(pll->base + 4);
126 	mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT;
127 	pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT;
128 	sdiv = (pll_div & SDIV_MASK) >> SDIV_SHIFT;
129 
130 	fvco *= mdiv;
131 	do_div(fvco, pdiv << sdiv);
132 
133 	return fvco;
134 }
135 
136 static unsigned long clk_pll1443x_recalc_rate(struct clk_hw *hw,
137 						  unsigned long parent_rate)
138 {
139 	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
140 	u32 mdiv, pdiv, sdiv, pll_div_ctl0, pll_div_ctl1;
141 	short int kdiv;
142 	u64 fvco = parent_rate;
143 
144 	pll_div_ctl0 = readl_relaxed(pll->base + 4);
145 	pll_div_ctl1 = readl_relaxed(pll->base + 8);
146 	mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
147 	pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
148 	sdiv = (pll_div_ctl0 & SDIV_MASK) >> SDIV_SHIFT;
149 	kdiv = pll_div_ctl1 & KDIV_MASK;
150 
151 	/* fvco = (m * 65536 + k) * Fin / (p * 65536) */
152 	fvco *= (mdiv * 65536 + kdiv);
153 	pdiv *= 65536;
154 
155 	do_div(fvco, pdiv << sdiv);
156 
157 	return fvco;
158 }
159 
160 static inline bool clk_pll14xx_mp_change(const struct imx_pll14xx_rate_table *rate,
161 					  u32 pll_div)
162 {
163 	u32 old_mdiv, old_pdiv;
164 
165 	old_mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT;
166 	old_pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT;
167 
168 	return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv;
169 }
170 
171 static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll)
172 {
173 	u32 val;
174 
175 	return readl_poll_timeout(pll->base, val, val & LOCK_STATUS, 0,
176 			LOCK_TIMEOUT_US);
177 }
178 
179 static int clk_pll1416x_set_rate(struct clk_hw *hw, unsigned long drate,
180 				 unsigned long prate)
181 {
182 	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
183 	const struct imx_pll14xx_rate_table *rate;
184 	u32 tmp, div_val;
185 	int ret;
186 
187 	rate = imx_get_pll_settings(pll, drate);
188 	if (!rate) {
189 		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
190 		       drate, clk_hw_get_name(hw));
191 		return -EINVAL;
192 	}
193 
194 	tmp = readl_relaxed(pll->base + 4);
195 
196 	if (!clk_pll14xx_mp_change(rate, tmp)) {
197 		tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
198 		tmp |= rate->sdiv << SDIV_SHIFT;
199 		writel_relaxed(tmp, pll->base + 4);
200 
201 		return 0;
202 	}
203 
204 	/* Bypass clock and set lock to pll output lock */
205 	tmp = readl_relaxed(pll->base);
206 	tmp |= LOCK_SEL_MASK;
207 	writel_relaxed(tmp, pll->base);
208 
209 	/* Enable RST */
210 	tmp &= ~RST_MASK;
211 	writel_relaxed(tmp, pll->base);
212 
213 	/* Enable BYPASS */
214 	tmp |= BYPASS_MASK;
215 	writel(tmp, pll->base);
216 
217 	div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
218 		(rate->sdiv << SDIV_SHIFT);
219 	writel_relaxed(div_val, pll->base + 0x4);
220 
221 	/*
222 	 * According to SPEC, t3 - t2 need to be greater than
223 	 * 1us and 1/FREF, respectively.
224 	 * FREF is FIN / Prediv, the prediv is [1, 63], so choose
225 	 * 3us.
226 	 */
227 	udelay(3);
228 
229 	/* Disable RST */
230 	tmp |= RST_MASK;
231 	writel_relaxed(tmp, pll->base);
232 
233 	/* Wait Lock */
234 	ret = clk_pll14xx_wait_lock(pll);
235 	if (ret)
236 		return ret;
237 
238 	/* Bypass */
239 	tmp &= ~BYPASS_MASK;
240 	writel_relaxed(tmp, pll->base);
241 
242 	return 0;
243 }
244 
245 static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate,
246 				 unsigned long prate)
247 {
248 	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
249 	const struct imx_pll14xx_rate_table *rate;
250 	u32 tmp, div_val;
251 	int ret;
252 
253 	rate = imx_get_pll_settings(pll, drate);
254 	if (!rate) {
255 		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
256 			drate, clk_hw_get_name(hw));
257 		return -EINVAL;
258 	}
259 
260 	tmp = readl_relaxed(pll->base + 4);
261 
262 	if (!clk_pll14xx_mp_change(rate, tmp)) {
263 		tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
264 		tmp |= rate->sdiv << SDIV_SHIFT;
265 		writel_relaxed(tmp, pll->base + 4);
266 
267 		tmp = rate->kdiv << KDIV_SHIFT;
268 		writel_relaxed(tmp, pll->base + 8);
269 
270 		return 0;
271 	}
272 
273 	/* Enable RST */
274 	tmp = readl_relaxed(pll->base);
275 	tmp &= ~RST_MASK;
276 	writel_relaxed(tmp, pll->base);
277 
278 	/* Enable BYPASS */
279 	tmp |= BYPASS_MASK;
280 	writel_relaxed(tmp, pll->base);
281 
282 	div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
283 		(rate->sdiv << SDIV_SHIFT);
284 	writel_relaxed(div_val, pll->base + 0x4);
285 	writel_relaxed(rate->kdiv << KDIV_SHIFT, pll->base + 0x8);
286 
287 	/*
288 	 * According to SPEC, t3 - t2 need to be greater than
289 	 * 1us and 1/FREF, respectively.
290 	 * FREF is FIN / Prediv, the prediv is [1, 63], so choose
291 	 * 3us.
292 	 */
293 	udelay(3);
294 
295 	/* Disable RST */
296 	tmp |= RST_MASK;
297 	writel_relaxed(tmp, pll->base);
298 
299 	/* Wait Lock*/
300 	ret = clk_pll14xx_wait_lock(pll);
301 	if (ret)
302 		return ret;
303 
304 	/* Bypass */
305 	tmp &= ~BYPASS_MASK;
306 	writel_relaxed(tmp, pll->base);
307 
308 	return 0;
309 }
310 
311 static int clk_pll14xx_prepare(struct clk_hw *hw)
312 {
313 	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
314 	u32 val;
315 	int ret;
316 
317 	/*
318 	 * RESETB = 1 from 0, PLL starts its normal
319 	 * operation after lock time
320 	 */
321 	val = readl_relaxed(pll->base + GNRL_CTL);
322 	if (val & RST_MASK)
323 		return 0;
324 	val |= BYPASS_MASK;
325 	writel_relaxed(val, pll->base + GNRL_CTL);
326 	val |= RST_MASK;
327 	writel_relaxed(val, pll->base + GNRL_CTL);
328 
329 	ret = clk_pll14xx_wait_lock(pll);
330 	if (ret)
331 		return ret;
332 
333 	val &= ~BYPASS_MASK;
334 	writel_relaxed(val, pll->base + GNRL_CTL);
335 
336 	return 0;
337 }
338 
339 static int clk_pll14xx_is_prepared(struct clk_hw *hw)
340 {
341 	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
342 	u32 val;
343 
344 	val = readl_relaxed(pll->base + GNRL_CTL);
345 
346 	return (val & RST_MASK) ? 1 : 0;
347 }
348 
349 static void clk_pll14xx_unprepare(struct clk_hw *hw)
350 {
351 	struct clk_pll14xx *pll = to_clk_pll14xx(hw);
352 	u32 val;
353 
354 	/*
355 	 * Set RST to 0, power down mode is enabled and
356 	 * every digital block is reset
357 	 */
358 	val = readl_relaxed(pll->base + GNRL_CTL);
359 	val &= ~RST_MASK;
360 	writel_relaxed(val, pll->base + GNRL_CTL);
361 }
362 
363 static const struct clk_ops clk_pll1416x_ops = {
364 	.prepare	= clk_pll14xx_prepare,
365 	.unprepare	= clk_pll14xx_unprepare,
366 	.is_prepared	= clk_pll14xx_is_prepared,
367 	.recalc_rate	= clk_pll1416x_recalc_rate,
368 	.round_rate	= clk_pll14xx_round_rate,
369 	.set_rate	= clk_pll1416x_set_rate,
370 };
371 
372 static const struct clk_ops clk_pll1416x_min_ops = {
373 	.recalc_rate	= clk_pll1416x_recalc_rate,
374 };
375 
376 static const struct clk_ops clk_pll1443x_ops = {
377 	.prepare	= clk_pll14xx_prepare,
378 	.unprepare	= clk_pll14xx_unprepare,
379 	.is_prepared	= clk_pll14xx_is_prepared,
380 	.recalc_rate	= clk_pll1443x_recalc_rate,
381 	.round_rate	= clk_pll14xx_round_rate,
382 	.set_rate	= clk_pll1443x_set_rate,
383 };
384 
385 struct clk_hw *imx_dev_clk_hw_pll14xx(struct device *dev, const char *name,
386 				const char *parent_name, void __iomem *base,
387 				const struct imx_pll14xx_clk *pll_clk)
388 {
389 	struct clk_pll14xx *pll;
390 	struct clk_hw *hw;
391 	struct clk_init_data init;
392 	int ret;
393 	u32 val;
394 
395 	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
396 	if (!pll)
397 		return ERR_PTR(-ENOMEM);
398 
399 	init.name = name;
400 	init.flags = pll_clk->flags;
401 	init.parent_names = &parent_name;
402 	init.num_parents = 1;
403 
404 	switch (pll_clk->type) {
405 	case PLL_1416X:
406 		if (!pll_clk->rate_table)
407 			init.ops = &clk_pll1416x_min_ops;
408 		else
409 			init.ops = &clk_pll1416x_ops;
410 		break;
411 	case PLL_1443X:
412 		init.ops = &clk_pll1443x_ops;
413 		break;
414 	default:
415 		pr_err("%s: Unknown pll type for pll clk %s\n",
416 		       __func__, name);
417 		kfree(pll);
418 		return ERR_PTR(-EINVAL);
419 	}
420 
421 	pll->base = base;
422 	pll->hw.init = &init;
423 	pll->type = pll_clk->type;
424 	pll->rate_table = pll_clk->rate_table;
425 	pll->rate_count = pll_clk->rate_count;
426 
427 	val = readl_relaxed(pll->base + GNRL_CTL);
428 	val &= ~BYPASS_MASK;
429 	writel_relaxed(val, pll->base + GNRL_CTL);
430 
431 	hw = &pll->hw;
432 
433 	ret = clk_hw_register(dev, hw);
434 	if (ret) {
435 		pr_err("%s: failed to register pll %s %d\n",
436 			__func__, name, ret);
437 		kfree(pll);
438 		return ERR_PTR(ret);
439 	}
440 
441 	return hw;
442 }
443 EXPORT_SYMBOL_GPL(imx_dev_clk_hw_pll14xx);
444