xref: /openbmc/linux/drivers/clk/clk-axi-clkgen.c (revision a2cce7a9)
1 /*
2  * AXI clkgen driver
3  *
4  * Copyright 2012-2013 Analog Devices Inc.
5  *  Author: Lars-Peter Clausen <lars@metafoo.de>
6  *
7  * Licensed under the GPL-2.
8  *
9  */
10 
11 #include <linux/platform_device.h>
12 #include <linux/clk-provider.h>
13 #include <linux/slab.h>
14 #include <linux/io.h>
15 #include <linux/of.h>
16 #include <linux/module.h>
17 #include <linux/err.h>
18 
19 #define AXI_CLKGEN_V1_REG_UPDATE_ENABLE	0x04
20 #define AXI_CLKGEN_V1_REG_CLK_OUT1	0x08
21 #define AXI_CLKGEN_V1_REG_CLK_OUT2	0x0c
22 #define AXI_CLKGEN_V1_REG_CLK_DIV	0x10
23 #define AXI_CLKGEN_V1_REG_CLK_FB1	0x14
24 #define AXI_CLKGEN_V1_REG_CLK_FB2	0x18
25 #define AXI_CLKGEN_V1_REG_LOCK1		0x1c
26 #define AXI_CLKGEN_V1_REG_LOCK2		0x20
27 #define AXI_CLKGEN_V1_REG_LOCK3		0x24
28 #define AXI_CLKGEN_V1_REG_FILTER1	0x28
29 #define AXI_CLKGEN_V1_REG_FILTER2	0x2c
30 
31 #define AXI_CLKGEN_V2_REG_RESET		0x40
32 #define AXI_CLKGEN_V2_REG_DRP_CNTRL	0x70
33 #define AXI_CLKGEN_V2_REG_DRP_STATUS	0x74
34 
35 #define AXI_CLKGEN_V2_RESET_MMCM_ENABLE	BIT(1)
36 #define AXI_CLKGEN_V2_RESET_ENABLE	BIT(0)
37 
38 #define AXI_CLKGEN_V2_DRP_CNTRL_SEL	BIT(29)
39 #define AXI_CLKGEN_V2_DRP_CNTRL_READ	BIT(28)
40 
41 #define AXI_CLKGEN_V2_DRP_STATUS_BUSY	BIT(16)
42 
43 #define MMCM_REG_CLKOUT0_1	0x08
44 #define MMCM_REG_CLKOUT0_2	0x09
45 #define MMCM_REG_CLK_FB1	0x14
46 #define MMCM_REG_CLK_FB2	0x15
47 #define MMCM_REG_CLK_DIV	0x16
48 #define MMCM_REG_LOCK1		0x18
49 #define MMCM_REG_LOCK2		0x19
50 #define MMCM_REG_LOCK3		0x1a
51 #define MMCM_REG_FILTER1	0x4e
52 #define MMCM_REG_FILTER2	0x4f
53 
54 struct axi_clkgen;
55 
56 struct axi_clkgen_mmcm_ops {
57 	void (*enable)(struct axi_clkgen *axi_clkgen, bool enable);
58 	int (*write)(struct axi_clkgen *axi_clkgen, unsigned int reg,
59 		     unsigned int val, unsigned int mask);
60 	int (*read)(struct axi_clkgen *axi_clkgen, unsigned int reg,
61 		    unsigned int *val);
62 };
63 
64 struct axi_clkgen {
65 	void __iomem *base;
66 	const struct axi_clkgen_mmcm_ops *mmcm_ops;
67 	struct clk_hw clk_hw;
68 };
69 
70 static void axi_clkgen_mmcm_enable(struct axi_clkgen *axi_clkgen,
71 	bool enable)
72 {
73 	axi_clkgen->mmcm_ops->enable(axi_clkgen, enable);
74 }
75 
76 static int axi_clkgen_mmcm_write(struct axi_clkgen *axi_clkgen,
77 	unsigned int reg, unsigned int val, unsigned int mask)
78 {
79 	return axi_clkgen->mmcm_ops->write(axi_clkgen, reg, val, mask);
80 }
81 
82 static int axi_clkgen_mmcm_read(struct axi_clkgen *axi_clkgen,
83 	unsigned int reg, unsigned int *val)
84 {
85 	return axi_clkgen->mmcm_ops->read(axi_clkgen, reg, val);
86 }
87 
88 static uint32_t axi_clkgen_lookup_filter(unsigned int m)
89 {
90 	switch (m) {
91 	case 0:
92 		return 0x01001990;
93 	case 1:
94 		return 0x01001190;
95 	case 2:
96 		return 0x01009890;
97 	case 3:
98 		return 0x01001890;
99 	case 4:
100 		return 0x01008890;
101 	case 5 ... 8:
102 		return 0x01009090;
103 	case 9 ... 11:
104 		return 0x01000890;
105 	case 12:
106 		return 0x08009090;
107 	case 13 ... 22:
108 		return 0x01001090;
109 	case 23 ... 36:
110 		return 0x01008090;
111 	case 37 ... 46:
112 		return 0x08001090;
113 	default:
114 		return 0x08008090;
115 	}
116 }
117 
118 static const uint32_t axi_clkgen_lock_table[] = {
119 	0x060603e8, 0x060603e8, 0x080803e8, 0x0b0b03e8,
120 	0x0e0e03e8, 0x111103e8, 0x131303e8, 0x161603e8,
121 	0x191903e8, 0x1c1c03e8, 0x1f1f0384, 0x1f1f0339,
122 	0x1f1f02ee, 0x1f1f02bc, 0x1f1f028a, 0x1f1f0271,
123 	0x1f1f023f, 0x1f1f0226, 0x1f1f020d, 0x1f1f01f4,
124 	0x1f1f01db, 0x1f1f01c2, 0x1f1f01a9, 0x1f1f0190,
125 	0x1f1f0190, 0x1f1f0177, 0x1f1f015e, 0x1f1f015e,
126 	0x1f1f0145, 0x1f1f0145, 0x1f1f012c, 0x1f1f012c,
127 	0x1f1f012c, 0x1f1f0113, 0x1f1f0113, 0x1f1f0113,
128 };
129 
130 static uint32_t axi_clkgen_lookup_lock(unsigned int m)
131 {
132 	if (m < ARRAY_SIZE(axi_clkgen_lock_table))
133 		return axi_clkgen_lock_table[m];
134 	return 0x1f1f00fa;
135 }
136 
137 static const unsigned int fpfd_min = 10000;
138 static const unsigned int fpfd_max = 300000;
139 static const unsigned int fvco_min = 600000;
140 static const unsigned int fvco_max = 1200000;
141 
142 static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout,
143 	unsigned int *best_d, unsigned int *best_m, unsigned int *best_dout)
144 {
145 	unsigned long d, d_min, d_max, _d_min, _d_max;
146 	unsigned long m, m_min, m_max;
147 	unsigned long f, dout, best_f, fvco;
148 
149 	fin /= 1000;
150 	fout /= 1000;
151 
152 	best_f = ULONG_MAX;
153 	*best_d = 0;
154 	*best_m = 0;
155 	*best_dout = 0;
156 
157 	d_min = max_t(unsigned long, DIV_ROUND_UP(fin, fpfd_max), 1);
158 	d_max = min_t(unsigned long, fin / fpfd_min, 80);
159 
160 	m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min, fin) * d_min, 1);
161 	m_max = min_t(unsigned long, fvco_max * d_max / fin, 64);
162 
163 	for (m = m_min; m <= m_max; m++) {
164 		_d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max));
165 		_d_max = min(d_max, fin * m / fvco_min);
166 
167 		for (d = _d_min; d <= _d_max; d++) {
168 			fvco = fin * m / d;
169 
170 			dout = DIV_ROUND_CLOSEST(fvco, fout);
171 			dout = clamp_t(unsigned long, dout, 1, 128);
172 			f = fvco / dout;
173 			if (abs(f - fout) < abs(best_f - fout)) {
174 				best_f = f;
175 				*best_d = d;
176 				*best_m = m;
177 				*best_dout = dout;
178 				if (best_f == fout)
179 					return;
180 			}
181 		}
182 	}
183 }
184 
185 static void axi_clkgen_calc_clk_params(unsigned int divider, unsigned int *low,
186 	unsigned int *high, unsigned int *edge, unsigned int *nocount)
187 {
188 	if (divider == 1)
189 		*nocount = 1;
190 	else
191 		*nocount = 0;
192 
193 	*high = divider / 2;
194 	*edge = divider % 2;
195 	*low = divider - *high;
196 }
197 
198 static void axi_clkgen_write(struct axi_clkgen *axi_clkgen,
199 	unsigned int reg, unsigned int val)
200 {
201 	writel(val, axi_clkgen->base + reg);
202 }
203 
204 static void axi_clkgen_read(struct axi_clkgen *axi_clkgen,
205 	unsigned int reg, unsigned int *val)
206 {
207 	*val = readl(axi_clkgen->base + reg);
208 }
209 
210 static unsigned int axi_clkgen_v1_map_mmcm_reg(unsigned int reg)
211 {
212 	switch (reg) {
213 	case MMCM_REG_CLKOUT0_1:
214 		return AXI_CLKGEN_V1_REG_CLK_OUT1;
215 	case MMCM_REG_CLKOUT0_2:
216 		return AXI_CLKGEN_V1_REG_CLK_OUT2;
217 	case MMCM_REG_CLK_FB1:
218 		return AXI_CLKGEN_V1_REG_CLK_FB1;
219 	case MMCM_REG_CLK_FB2:
220 		return AXI_CLKGEN_V1_REG_CLK_FB2;
221 	case MMCM_REG_CLK_DIV:
222 		return AXI_CLKGEN_V1_REG_CLK_DIV;
223 	case MMCM_REG_LOCK1:
224 		return AXI_CLKGEN_V1_REG_LOCK1;
225 	case MMCM_REG_LOCK2:
226 		return AXI_CLKGEN_V1_REG_LOCK2;
227 	case MMCM_REG_LOCK3:
228 		return AXI_CLKGEN_V1_REG_LOCK3;
229 	case MMCM_REG_FILTER1:
230 		return AXI_CLKGEN_V1_REG_FILTER1;
231 	case MMCM_REG_FILTER2:
232 		return AXI_CLKGEN_V1_REG_FILTER2;
233 	default:
234 		return 0;
235 	}
236 }
237 
238 static int axi_clkgen_v1_mmcm_write(struct axi_clkgen *axi_clkgen,
239 	unsigned int reg, unsigned int val, unsigned int mask)
240 {
241 	reg = axi_clkgen_v1_map_mmcm_reg(reg);
242 	if (reg == 0)
243 		return -EINVAL;
244 
245 	axi_clkgen_write(axi_clkgen, reg, val);
246 
247 	return 0;
248 }
249 
250 static int axi_clkgen_v1_mmcm_read(struct axi_clkgen *axi_clkgen,
251 	unsigned int reg, unsigned int *val)
252 {
253 	reg = axi_clkgen_v1_map_mmcm_reg(reg);
254 	if (reg == 0)
255 		return -EINVAL;
256 
257 	axi_clkgen_read(axi_clkgen, reg, val);
258 
259 	return 0;
260 }
261 
262 static void axi_clkgen_v1_mmcm_enable(struct axi_clkgen *axi_clkgen,
263 	bool enable)
264 {
265 	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V1_REG_UPDATE_ENABLE, enable);
266 }
267 
268 static const struct axi_clkgen_mmcm_ops axi_clkgen_v1_mmcm_ops = {
269 	.write = axi_clkgen_v1_mmcm_write,
270 	.read = axi_clkgen_v1_mmcm_read,
271 	.enable = axi_clkgen_v1_mmcm_enable,
272 };
273 
274 static int axi_clkgen_wait_non_busy(struct axi_clkgen *axi_clkgen)
275 {
276 	unsigned int timeout = 10000;
277 	unsigned int val;
278 
279 	do {
280 		axi_clkgen_read(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_STATUS, &val);
281 	} while ((val & AXI_CLKGEN_V2_DRP_STATUS_BUSY) && --timeout);
282 
283 	if (val & AXI_CLKGEN_V2_DRP_STATUS_BUSY)
284 		return -EIO;
285 
286 	return val & 0xffff;
287 }
288 
289 static int axi_clkgen_v2_mmcm_read(struct axi_clkgen *axi_clkgen,
290 	unsigned int reg, unsigned int *val)
291 {
292 	unsigned int reg_val;
293 	int ret;
294 
295 	ret = axi_clkgen_wait_non_busy(axi_clkgen);
296 	if (ret < 0)
297 		return ret;
298 
299 	reg_val = AXI_CLKGEN_V2_DRP_CNTRL_SEL | AXI_CLKGEN_V2_DRP_CNTRL_READ;
300 	reg_val |= (reg << 16);
301 
302 	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_CNTRL, reg_val);
303 
304 	ret = axi_clkgen_wait_non_busy(axi_clkgen);
305 	if (ret < 0)
306 		return ret;
307 
308 	*val = ret;
309 
310 	return 0;
311 }
312 
313 static int axi_clkgen_v2_mmcm_write(struct axi_clkgen *axi_clkgen,
314 	unsigned int reg, unsigned int val, unsigned int mask)
315 {
316 	unsigned int reg_val = 0;
317 	int ret;
318 
319 	ret = axi_clkgen_wait_non_busy(axi_clkgen);
320 	if (ret < 0)
321 		return ret;
322 
323 	if (mask != 0xffff) {
324 		axi_clkgen_v2_mmcm_read(axi_clkgen, reg, &reg_val);
325 		reg_val &= ~mask;
326 	}
327 
328 	reg_val |= AXI_CLKGEN_V2_DRP_CNTRL_SEL | (reg << 16) | (val & mask);
329 
330 	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_CNTRL, reg_val);
331 
332 	return 0;
333 }
334 
335 static void axi_clkgen_v2_mmcm_enable(struct axi_clkgen *axi_clkgen,
336 	bool enable)
337 {
338 	unsigned int val = AXI_CLKGEN_V2_RESET_ENABLE;
339 
340 	if (enable)
341 		val |= AXI_CLKGEN_V2_RESET_MMCM_ENABLE;
342 
343 	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_RESET, val);
344 }
345 
346 static const struct axi_clkgen_mmcm_ops axi_clkgen_v2_mmcm_ops = {
347 	.write = axi_clkgen_v2_mmcm_write,
348 	.read = axi_clkgen_v2_mmcm_read,
349 	.enable = axi_clkgen_v2_mmcm_enable,
350 };
351 
352 static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw)
353 {
354 	return container_of(clk_hw, struct axi_clkgen, clk_hw);
355 }
356 
357 static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
358 	unsigned long rate, unsigned long parent_rate)
359 {
360 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
361 	unsigned int d, m, dout;
362 	unsigned int nocount;
363 	unsigned int high;
364 	unsigned int edge;
365 	unsigned int low;
366 	uint32_t filter;
367 	uint32_t lock;
368 
369 	if (parent_rate == 0 || rate == 0)
370 		return -EINVAL;
371 
372 	axi_clkgen_calc_params(parent_rate, rate, &d, &m, &dout);
373 
374 	if (d == 0 || dout == 0 || m == 0)
375 		return -EINVAL;
376 
377 	filter = axi_clkgen_lookup_filter(m - 1);
378 	lock = axi_clkgen_lookup_lock(m - 1);
379 
380 	axi_clkgen_calc_clk_params(dout, &low, &high, &edge, &nocount);
381 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_1,
382 		(high << 6) | low, 0xefff);
383 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_2,
384 		(edge << 7) | (nocount << 6), 0x03ff);
385 
386 	axi_clkgen_calc_clk_params(d, &low, &high, &edge, &nocount);
387 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_DIV,
388 		(edge << 13) | (nocount << 12) | (high << 6) | low, 0x3fff);
389 
390 	axi_clkgen_calc_clk_params(m, &low, &high, &edge, &nocount);
391 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB1,
392 		(high << 6) | low, 0xefff);
393 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB2,
394 		(edge << 7) | (nocount << 6), 0x03ff);
395 
396 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK1, lock & 0x3ff, 0x3ff);
397 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK2,
398 		(((lock >> 16) & 0x1f) << 10) | 0x1, 0x7fff);
399 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK3,
400 		(((lock >> 24) & 0x1f) << 10) | 0x3e9, 0x7fff);
401 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER1, filter >> 16, 0x9900);
402 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER2, filter, 0x9900);
403 
404 	return 0;
405 }
406 
407 static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate,
408 	unsigned long *parent_rate)
409 {
410 	unsigned int d, m, dout;
411 
412 	axi_clkgen_calc_params(*parent_rate, rate, &d, &m, &dout);
413 
414 	if (d == 0 || dout == 0 || m == 0)
415 		return -EINVAL;
416 
417 	return *parent_rate / d * m / dout;
418 }
419 
420 static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
421 	unsigned long parent_rate)
422 {
423 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
424 	unsigned int d, m, dout;
425 	unsigned int reg;
426 	unsigned long long tmp;
427 
428 	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_1, &reg);
429 	dout = (reg & 0x3f) + ((reg >> 6) & 0x3f);
430 	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, &reg);
431 	d = (reg & 0x3f) + ((reg >> 6) & 0x3f);
432 	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB1, &reg);
433 	m = (reg & 0x3f) + ((reg >> 6) & 0x3f);
434 
435 	if (d == 0 || dout == 0)
436 		return 0;
437 
438 	tmp = (unsigned long long)(parent_rate / d) * m;
439 	do_div(tmp, dout);
440 
441 	if (tmp > ULONG_MAX)
442 		return ULONG_MAX;
443 
444 	return tmp;
445 }
446 
447 static int axi_clkgen_enable(struct clk_hw *clk_hw)
448 {
449 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
450 
451 	axi_clkgen_mmcm_enable(axi_clkgen, true);
452 
453 	return 0;
454 }
455 
456 static void axi_clkgen_disable(struct clk_hw *clk_hw)
457 {
458 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
459 
460 	axi_clkgen_mmcm_enable(axi_clkgen, false);
461 }
462 
463 static const struct clk_ops axi_clkgen_ops = {
464 	.recalc_rate = axi_clkgen_recalc_rate,
465 	.round_rate = axi_clkgen_round_rate,
466 	.set_rate = axi_clkgen_set_rate,
467 	.enable = axi_clkgen_enable,
468 	.disable = axi_clkgen_disable,
469 };
470 
471 static const struct of_device_id axi_clkgen_ids[] = {
472 	{
473 		.compatible = "adi,axi-clkgen-1.00.a",
474 		.data = &axi_clkgen_v1_mmcm_ops
475 	}, {
476 		.compatible = "adi,axi-clkgen-2.00.a",
477 		.data = &axi_clkgen_v2_mmcm_ops,
478 	},
479 	{ },
480 };
481 MODULE_DEVICE_TABLE(of, axi_clkgen_ids);
482 
483 static int axi_clkgen_probe(struct platform_device *pdev)
484 {
485 	const struct of_device_id *id;
486 	struct axi_clkgen *axi_clkgen;
487 	struct clk_init_data init;
488 	const char *parent_name;
489 	const char *clk_name;
490 	struct resource *mem;
491 	struct clk *clk;
492 
493 	if (!pdev->dev.of_node)
494 		return -ENODEV;
495 
496 	id = of_match_node(axi_clkgen_ids, pdev->dev.of_node);
497 	if (!id)
498 		return -ENODEV;
499 
500 	axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL);
501 	if (!axi_clkgen)
502 		return -ENOMEM;
503 
504 	axi_clkgen->mmcm_ops = id->data;
505 
506 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
507 	axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem);
508 	if (IS_ERR(axi_clkgen->base))
509 		return PTR_ERR(axi_clkgen->base);
510 
511 	parent_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
512 	if (!parent_name)
513 		return -EINVAL;
514 
515 	clk_name = pdev->dev.of_node->name;
516 	of_property_read_string(pdev->dev.of_node, "clock-output-names",
517 		&clk_name);
518 
519 	init.name = clk_name;
520 	init.ops = &axi_clkgen_ops;
521 	init.flags = CLK_SET_RATE_GATE;
522 	init.parent_names = &parent_name;
523 	init.num_parents = 1;
524 
525 	axi_clkgen_mmcm_enable(axi_clkgen, false);
526 
527 	axi_clkgen->clk_hw.init = &init;
528 	clk = devm_clk_register(&pdev->dev, &axi_clkgen->clk_hw);
529 	if (IS_ERR(clk))
530 		return PTR_ERR(clk);
531 
532 	return of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get,
533 				    clk);
534 }
535 
536 static int axi_clkgen_remove(struct platform_device *pdev)
537 {
538 	of_clk_del_provider(pdev->dev.of_node);
539 
540 	return 0;
541 }
542 
543 static struct platform_driver axi_clkgen_driver = {
544 	.driver = {
545 		.name = "adi-axi-clkgen",
546 		.of_match_table = axi_clkgen_ids,
547 	},
548 	.probe = axi_clkgen_probe,
549 	.remove = axi_clkgen_remove,
550 };
551 module_platform_driver(axi_clkgen_driver);
552 
553 MODULE_LICENSE("GPL v2");
554 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
555 MODULE_DESCRIPTION("Driver for the Analog Devices' AXI clkgen pcore clock generator");
556