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