xref: /linux/drivers/clk/clk-axi-clkgen.c (revision d2c9a99135da931377240942d44f3dea104cedb8)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * AXI clkgen driver
4  *
5  * Copyright 2012-2013 Analog Devices Inc.
6  *  Author: Lars-Peter Clausen <lars@metafoo.de>
7  */
8 
9 #include <linux/adi-axi-common.h>
10 #include <linux/bits.h>
11 #include <linux/clk.h>
12 #include <linux/clk-provider.h>
13 #include <linux/err.h>
14 #include <linux/io.h>
15 #include <linux/module.h>
16 #include <linux/of.h>
17 #include <linux/platform_device.h>
18 #include <linux/slab.h>
19 
20 #define AXI_CLKGEN_V2_REG_RESET		0x40
21 #define AXI_CLKGEN_V2_REG_CLKSEL	0x44
22 #define AXI_CLKGEN_V2_REG_DRP_CNTRL	0x70
23 #define AXI_CLKGEN_V2_REG_DRP_STATUS	0x74
24 
25 #define AXI_CLKGEN_V2_RESET_MMCM_ENABLE	BIT(1)
26 #define AXI_CLKGEN_V2_RESET_ENABLE	BIT(0)
27 
28 #define AXI_CLKGEN_V2_DRP_CNTRL_SEL	BIT(29)
29 #define AXI_CLKGEN_V2_DRP_CNTRL_READ	BIT(28)
30 
31 #define AXI_CLKGEN_V2_DRP_STATUS_BUSY	BIT(16)
32 
33 #define ADI_CLKGEN_REG_FPGA_VOLTAGE		0x0140
34 #define ADI_CLKGEN_INFO_FPGA_VOLTAGE(val)	((val) & GENMASK(15, 0))
35 
36 #define MMCM_REG_CLKOUT5_2	0x07
37 #define MMCM_REG_CLKOUT0_1	0x08
38 #define MMCM_REG_CLKOUT0_2	0x09
39 #define MMCM_REG_CLKOUT6_2	0x13
40 #define MMCM_REG_CLK_FB1	0x14
41 #define MMCM_REG_CLK_FB2	0x15
42 #define MMCM_REG_CLK_DIV	0x16
43 #define MMCM_REG_LOCK1		0x18
44 #define MMCM_REG_LOCK2		0x19
45 #define MMCM_REG_LOCK3		0x1a
46 #define MMCM_REG_POWER		0x28
47 #define MMCM_REG_FILTER1	0x4e
48 #define MMCM_REG_FILTER2	0x4f
49 
50 #define MMCM_CLKOUT_NOCOUNT	BIT(6)
51 
52 #define MMCM_CLK_DIV_DIVIDE	BIT(11)
53 #define MMCM_CLK_DIV_NOCOUNT	BIT(12)
54 
55 struct axi_clkgen_limits {
56 	unsigned int fpfd_min;
57 	unsigned int fpfd_max;
58 	unsigned int fvco_min;
59 	unsigned int fvco_max;
60 };
61 
62 struct axi_clkgen {
63 	void __iomem *base;
64 	struct clk_hw clk_hw;
65 	struct axi_clkgen_limits limits;
66 };
67 
axi_clkgen_lookup_filter(unsigned int m)68 static uint32_t axi_clkgen_lookup_filter(unsigned int m)
69 {
70 	switch (m) {
71 	case 0:
72 		return 0x01001990;
73 	case 1:
74 		return 0x01001190;
75 	case 2:
76 		return 0x01009890;
77 	case 3:
78 		return 0x01001890;
79 	case 4:
80 		return 0x01008890;
81 	case 5 ... 8:
82 		return 0x01009090;
83 	case 9 ... 11:
84 		return 0x01000890;
85 	case 12:
86 		return 0x08009090;
87 	case 13 ... 22:
88 		return 0x01001090;
89 	case 23 ... 36:
90 		return 0x01008090;
91 	case 37 ... 46:
92 		return 0x08001090;
93 	default:
94 		return 0x08008090;
95 	}
96 }
97 
98 static const u32 axi_clkgen_lock_table[] = {
99 	0x060603e8, 0x060603e8, 0x080803e8, 0x0b0b03e8,
100 	0x0e0e03e8, 0x111103e8, 0x131303e8, 0x161603e8,
101 	0x191903e8, 0x1c1c03e8, 0x1f1f0384, 0x1f1f0339,
102 	0x1f1f02ee, 0x1f1f02bc, 0x1f1f028a, 0x1f1f0271,
103 	0x1f1f023f, 0x1f1f0226, 0x1f1f020d, 0x1f1f01f4,
104 	0x1f1f01db, 0x1f1f01c2, 0x1f1f01a9, 0x1f1f0190,
105 	0x1f1f0190, 0x1f1f0177, 0x1f1f015e, 0x1f1f015e,
106 	0x1f1f0145, 0x1f1f0145, 0x1f1f012c, 0x1f1f012c,
107 	0x1f1f012c, 0x1f1f0113, 0x1f1f0113, 0x1f1f0113,
108 };
109 
axi_clkgen_lookup_lock(unsigned int m)110 static u32 axi_clkgen_lookup_lock(unsigned int m)
111 {
112 	if (m < ARRAY_SIZE(axi_clkgen_lock_table))
113 		return axi_clkgen_lock_table[m];
114 	return 0x1f1f00fa;
115 }
116 
117 static const struct axi_clkgen_limits axi_clkgen_zynqmp_default_limits = {
118 	.fpfd_min = 10000,
119 	.fpfd_max = 450000,
120 	.fvco_min = 800000,
121 	.fvco_max = 1600000,
122 };
123 
124 static const struct axi_clkgen_limits axi_clkgen_zynq_default_limits = {
125 	.fpfd_min = 10000,
126 	.fpfd_max = 450000,
127 	.fvco_min = 600000,
128 	.fvco_max = 1200000,
129 };
130 
axi_clkgen_calc_params(const struct axi_clkgen_limits * limits,unsigned long fin,unsigned long fout,unsigned int * best_d,unsigned int * best_m,unsigned int * best_dout)131 static void axi_clkgen_calc_params(const struct axi_clkgen_limits *limits,
132 				   unsigned long fin, unsigned long fout,
133 				   unsigned int *best_d, unsigned int *best_m,
134 				   unsigned int *best_dout)
135 {
136 	unsigned long d, d_min, d_max, _d_min, _d_max;
137 	unsigned long m, m_min, m_max;
138 	unsigned long f, dout, best_f, fvco;
139 	unsigned long fract_shift = 0;
140 	unsigned long fvco_min_fract, fvco_max_fract;
141 
142 	fin /= 1000;
143 	fout /= 1000;
144 
145 	best_f = ULONG_MAX;
146 	*best_d = 0;
147 	*best_m = 0;
148 	*best_dout = 0;
149 
150 	d_min = max(DIV_ROUND_UP(fin, limits->fpfd_max), 1);
151 	d_max = min(fin / limits->fpfd_min, 80);
152 
153 again:
154 	fvco_min_fract = limits->fvco_min << fract_shift;
155 	fvco_max_fract = limits->fvco_max << fract_shift;
156 
157 	m_min = max(DIV_ROUND_UP(fvco_min_fract, fin) * d_min, 1);
158 	m_max = min(fvco_max_fract * d_max / fin, 64 << fract_shift);
159 
160 	for (m = m_min; m <= m_max; m++) {
161 		_d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max_fract));
162 		_d_max = min(d_max, fin * m / fvco_min_fract);
163 
164 		for (d = _d_min; d <= _d_max; d++) {
165 			fvco = fin * m / d;
166 
167 			dout = DIV_ROUND_CLOSEST(fvco, fout);
168 			dout = clamp_t(unsigned long, dout, 1, 128 << fract_shift);
169 			f = fvco / dout;
170 			if (abs(f - fout) < abs(best_f - fout)) {
171 				best_f = f;
172 				*best_d = d;
173 				*best_m = m << (3 - fract_shift);
174 				*best_dout = dout << (3 - fract_shift);
175 				if (best_f == fout)
176 					return;
177 			}
178 		}
179 	}
180 
181 	/* Let's see if we find a better setting in fractional mode */
182 	if (fract_shift == 0) {
183 		fract_shift = 3;
184 		goto again;
185 	}
186 }
187 
188 struct axi_clkgen_div_params {
189 	unsigned int low;
190 	unsigned int high;
191 	unsigned int edge;
192 	unsigned int nocount;
193 	unsigned int frac_en;
194 	unsigned int frac;
195 	unsigned int frac_wf_f;
196 	unsigned int frac_wf_r;
197 	unsigned int frac_phase;
198 };
199 
axi_clkgen_calc_clk_params(unsigned int divider,unsigned int frac_divider,struct axi_clkgen_div_params * params)200 static void axi_clkgen_calc_clk_params(unsigned int divider,
201 				       unsigned int frac_divider,
202 				       struct axi_clkgen_div_params *params)
203 {
204 	memset(params, 0x0, sizeof(*params));
205 
206 	if (divider == 1) {
207 		params->nocount = 1;
208 		return;
209 	}
210 
211 	if (frac_divider == 0) {
212 		params->high = divider / 2;
213 		params->edge = divider % 2;
214 		params->low = divider - params->high;
215 	} else {
216 		params->frac_en = 1;
217 		params->frac = frac_divider;
218 
219 		params->high = divider / 2;
220 		params->edge = divider % 2;
221 		params->low = params->high;
222 
223 		if (params->edge == 0) {
224 			params->high--;
225 			params->frac_wf_r = 1;
226 		}
227 
228 		if (params->edge == 0 || frac_divider == 1)
229 			params->low--;
230 		if (((params->edge == 0) ^ (frac_divider == 1)) ||
231 		    (divider == 2 && frac_divider == 1))
232 			params->frac_wf_f = 1;
233 
234 		params->frac_phase = params->edge * 4 + frac_divider / 2;
235 	}
236 }
237 
axi_clkgen_write(struct axi_clkgen * axi_clkgen,unsigned int reg,unsigned int val)238 static void axi_clkgen_write(struct axi_clkgen *axi_clkgen,
239 			     unsigned int reg, unsigned int val)
240 {
241 	writel(val, axi_clkgen->base + reg);
242 }
243 
axi_clkgen_read(struct axi_clkgen * axi_clkgen,unsigned int reg,unsigned int * val)244 static void axi_clkgen_read(struct axi_clkgen *axi_clkgen,
245 			    unsigned int reg, unsigned int *val)
246 {
247 	*val = readl(axi_clkgen->base + reg);
248 }
249 
axi_clkgen_wait_non_busy(struct axi_clkgen * axi_clkgen)250 static int axi_clkgen_wait_non_busy(struct axi_clkgen *axi_clkgen)
251 {
252 	unsigned int timeout = 10000;
253 	unsigned int val;
254 
255 	do {
256 		axi_clkgen_read(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_STATUS, &val);
257 	} while ((val & AXI_CLKGEN_V2_DRP_STATUS_BUSY) && --timeout);
258 
259 	if (val & AXI_CLKGEN_V2_DRP_STATUS_BUSY)
260 		return -EIO;
261 
262 	return val & 0xffff;
263 }
264 
axi_clkgen_mmcm_read(struct axi_clkgen * axi_clkgen,unsigned int reg,unsigned int * val)265 static int axi_clkgen_mmcm_read(struct axi_clkgen *axi_clkgen,
266 				unsigned int reg, unsigned int *val)
267 {
268 	unsigned int reg_val;
269 	int ret;
270 
271 	ret = axi_clkgen_wait_non_busy(axi_clkgen);
272 	if (ret < 0)
273 		return ret;
274 
275 	reg_val = AXI_CLKGEN_V2_DRP_CNTRL_SEL | AXI_CLKGEN_V2_DRP_CNTRL_READ;
276 	reg_val |= (reg << 16);
277 
278 	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_CNTRL, reg_val);
279 
280 	ret = axi_clkgen_wait_non_busy(axi_clkgen);
281 	if (ret < 0)
282 		return ret;
283 
284 	*val = ret;
285 
286 	return 0;
287 }
288 
axi_clkgen_mmcm_write(struct axi_clkgen * axi_clkgen,unsigned int reg,unsigned int val,unsigned int mask)289 static int axi_clkgen_mmcm_write(struct axi_clkgen *axi_clkgen,
290 				 unsigned int reg, unsigned int val,
291 				 unsigned int mask)
292 {
293 	unsigned int reg_val = 0;
294 	int ret;
295 
296 	ret = axi_clkgen_wait_non_busy(axi_clkgen);
297 	if (ret < 0)
298 		return ret;
299 
300 	if (mask != 0xffff) {
301 		axi_clkgen_mmcm_read(axi_clkgen, reg, &reg_val);
302 		reg_val &= ~mask;
303 	}
304 
305 	reg_val |= AXI_CLKGEN_V2_DRP_CNTRL_SEL | (reg << 16) | (val & mask);
306 
307 	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_CNTRL, reg_val);
308 
309 	return 0;
310 }
311 
axi_clkgen_mmcm_enable(struct axi_clkgen * axi_clkgen,bool enable)312 static void axi_clkgen_mmcm_enable(struct axi_clkgen *axi_clkgen, bool enable)
313 {
314 	unsigned int val = AXI_CLKGEN_V2_RESET_ENABLE;
315 
316 	if (enable)
317 		val |= AXI_CLKGEN_V2_RESET_MMCM_ENABLE;
318 
319 	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_RESET, val);
320 }
321 
clk_hw_to_axi_clkgen(struct clk_hw * clk_hw)322 static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw)
323 {
324 	return container_of(clk_hw, struct axi_clkgen, clk_hw);
325 }
326 
axi_clkgen_set_div(struct axi_clkgen * axi_clkgen,unsigned int reg1,unsigned int reg2,unsigned int reg3,struct axi_clkgen_div_params * params)327 static void axi_clkgen_set_div(struct axi_clkgen *axi_clkgen,
328 			       unsigned int reg1, unsigned int reg2,
329 			       unsigned int reg3,
330 			       struct axi_clkgen_div_params *params)
331 {
332 	axi_clkgen_mmcm_write(axi_clkgen, reg1,
333 			      (params->high << 6) | params->low, 0xefff);
334 	axi_clkgen_mmcm_write(axi_clkgen, reg2,
335 			      (params->frac << 12) | (params->frac_en << 11) |
336 			      (params->frac_wf_r << 10) | (params->edge << 7) |
337 			      (params->nocount << 6), 0x7fff);
338 	if (reg3 != 0) {
339 		axi_clkgen_mmcm_write(axi_clkgen, reg3,
340 				      (params->frac_phase << 11) | (params->frac_wf_f << 10),
341 				      0x3c00);
342 	}
343 }
344 
axi_clkgen_set_rate(struct clk_hw * clk_hw,unsigned long rate,unsigned long parent_rate)345 static int axi_clkgen_set_rate(struct clk_hw *clk_hw, unsigned long rate,
346 			       unsigned long parent_rate)
347 {
348 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
349 	const struct axi_clkgen_limits *limits = &axi_clkgen->limits;
350 	unsigned int d, m, dout;
351 	struct axi_clkgen_div_params params;
352 	u32 power = 0, filter, lock;
353 
354 	if (parent_rate == 0 || rate == 0)
355 		return -EINVAL;
356 
357 	axi_clkgen_calc_params(limits, parent_rate, rate, &d, &m, &dout);
358 
359 	if (d == 0 || dout == 0 || m == 0)
360 		return -EINVAL;
361 
362 	if ((dout & 0x7) != 0 || (m & 0x7) != 0)
363 		power |= 0x9800;
364 
365 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_POWER, power, 0x9800);
366 
367 	filter = axi_clkgen_lookup_filter(m - 1);
368 	lock = axi_clkgen_lookup_lock(m - 1);
369 
370 	axi_clkgen_calc_clk_params(dout >> 3, dout & 0x7, &params);
371 	axi_clkgen_set_div(axi_clkgen,  MMCM_REG_CLKOUT0_1, MMCM_REG_CLKOUT0_2,
372 			   MMCM_REG_CLKOUT5_2, &params);
373 
374 	axi_clkgen_calc_clk_params(d, 0, &params);
375 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_DIV,
376 			      (params.edge << 13) | (params.nocount << 12) |
377 			      (params.high << 6) | params.low, 0x3fff);
378 
379 	axi_clkgen_calc_clk_params(m >> 3, m & 0x7, &params);
380 	axi_clkgen_set_div(axi_clkgen,  MMCM_REG_CLK_FB1, MMCM_REG_CLK_FB2,
381 			   MMCM_REG_CLKOUT6_2, &params);
382 
383 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK1, lock & 0x3ff, 0x3ff);
384 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK2,
385 			      (((lock >> 16) & 0x1f) << 10) | 0x1, 0x7fff);
386 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK3,
387 			      (((lock >> 24) & 0x1f) << 10) | 0x3e9, 0x7fff);
388 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER1, filter >> 16, 0x9900);
389 	axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER2, filter, 0x9900);
390 
391 	return 0;
392 }
393 
axi_clkgen_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)394 static int axi_clkgen_determine_rate(struct clk_hw *hw,
395 				     struct clk_rate_request *req)
396 {
397 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(hw);
398 	const struct axi_clkgen_limits *limits = &axi_clkgen->limits;
399 	unsigned int d, m, dout;
400 	unsigned long long tmp;
401 
402 	axi_clkgen_calc_params(limits, req->best_parent_rate, req->rate,
403 			       &d, &m, &dout);
404 
405 	if (d == 0 || dout == 0 || m == 0)
406 		return -EINVAL;
407 
408 	tmp = (unsigned long long)req->best_parent_rate * m;
409 	tmp = DIV_ROUND_CLOSEST_ULL(tmp, dout * d);
410 
411 	req->rate = min_t(unsigned long long, tmp, LONG_MAX);
412 	return 0;
413 }
414 
axi_clkgen_get_div(struct axi_clkgen * axi_clkgen,unsigned int reg1,unsigned int reg2)415 static unsigned int axi_clkgen_get_div(struct axi_clkgen *axi_clkgen,
416 				       unsigned int reg1, unsigned int reg2)
417 {
418 	unsigned int val1, val2;
419 	unsigned int div;
420 
421 	axi_clkgen_mmcm_read(axi_clkgen, reg2, &val2);
422 	if (val2 & MMCM_CLKOUT_NOCOUNT)
423 		return 8;
424 
425 	axi_clkgen_mmcm_read(axi_clkgen, reg1, &val1);
426 
427 	div = (val1 & 0x3f) + ((val1 >> 6) & 0x3f);
428 	div <<= 3;
429 
430 	if (val2 & MMCM_CLK_DIV_DIVIDE) {
431 		if ((val2 & BIT(7)) && (val2 & 0x7000) != 0x1000)
432 			div += 8;
433 		else
434 			div += 16;
435 
436 		div += (val2 >> 12) & 0x7;
437 	}
438 
439 	return div;
440 }
441 
axi_clkgen_recalc_rate(struct clk_hw * clk_hw,unsigned long parent_rate)442 static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
443 					    unsigned long parent_rate)
444 {
445 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
446 	unsigned int d, m, dout;
447 	unsigned long long tmp;
448 	unsigned int val;
449 
450 	dout = axi_clkgen_get_div(axi_clkgen, MMCM_REG_CLKOUT0_1,
451 				  MMCM_REG_CLKOUT0_2);
452 	m = axi_clkgen_get_div(axi_clkgen, MMCM_REG_CLK_FB1,
453 			       MMCM_REG_CLK_FB2);
454 
455 	axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, &val);
456 	if (val & MMCM_CLK_DIV_NOCOUNT)
457 		d = 1;
458 	else
459 		d = (val & 0x3f) + ((val >> 6) & 0x3f);
460 
461 	if (d == 0 || dout == 0)
462 		return 0;
463 
464 	tmp = (unsigned long long)parent_rate * m;
465 	tmp = DIV_ROUND_CLOSEST_ULL(tmp, dout * d);
466 
467 	return min_t(unsigned long long, tmp, ULONG_MAX);
468 }
469 
axi_clkgen_enable(struct clk_hw * clk_hw)470 static int axi_clkgen_enable(struct clk_hw *clk_hw)
471 {
472 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
473 
474 	axi_clkgen_mmcm_enable(axi_clkgen, true);
475 
476 	return 0;
477 }
478 
axi_clkgen_disable(struct clk_hw * clk_hw)479 static void axi_clkgen_disable(struct clk_hw *clk_hw)
480 {
481 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
482 
483 	axi_clkgen_mmcm_enable(axi_clkgen, false);
484 }
485 
axi_clkgen_set_parent(struct clk_hw * clk_hw,u8 index)486 static int axi_clkgen_set_parent(struct clk_hw *clk_hw, u8 index)
487 {
488 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
489 
490 	axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_CLKSEL, index);
491 
492 	return 0;
493 }
494 
axi_clkgen_get_parent(struct clk_hw * clk_hw)495 static u8 axi_clkgen_get_parent(struct clk_hw *clk_hw)
496 {
497 	struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
498 	unsigned int parent;
499 
500 	axi_clkgen_read(axi_clkgen, AXI_CLKGEN_V2_REG_CLKSEL, &parent);
501 
502 	return parent;
503 }
504 
axi_clkgen_setup_limits(struct axi_clkgen * axi_clkgen,struct device * dev)505 static int axi_clkgen_setup_limits(struct axi_clkgen *axi_clkgen,
506 				   struct device *dev)
507 {
508 	unsigned int tech, family, speed_grade, reg_value;
509 
510 	axi_clkgen_read(axi_clkgen, ADI_AXI_REG_FPGA_INFO, &reg_value);
511 	tech = ADI_AXI_INFO_FPGA_TECH(reg_value);
512 	family = ADI_AXI_INFO_FPGA_FAMILY(reg_value);
513 	speed_grade = ADI_AXI_INFO_FPGA_SPEED_GRADE(reg_value);
514 
515 	axi_clkgen->limits.fpfd_min = 10000;
516 	axi_clkgen->limits.fvco_min = 600000;
517 
518 	switch (speed_grade) {
519 	case ADI_AXI_FPGA_SPEED_1 ... ADI_AXI_FPGA_SPEED_1LV:
520 		axi_clkgen->limits.fvco_max = 1200000;
521 		axi_clkgen->limits.fpfd_max = 450000;
522 		break;
523 	case ADI_AXI_FPGA_SPEED_2 ... ADI_AXI_FPGA_SPEED_2MP:
524 		axi_clkgen->limits.fvco_max = 1440000;
525 		axi_clkgen->limits.fpfd_max = 500000;
526 		if (family == ADI_AXI_FPGA_FAMILY_KINTEX || family == ADI_AXI_FPGA_FAMILY_ARTIX) {
527 			axi_clkgen_read(axi_clkgen, ADI_CLKGEN_REG_FPGA_VOLTAGE,
528 					&reg_value);
529 			if (ADI_CLKGEN_INFO_FPGA_VOLTAGE(reg_value) < 950) {
530 				axi_clkgen->limits.fvco_max = 1200000;
531 				axi_clkgen->limits.fpfd_max = 450000;
532 			}
533 		}
534 		break;
535 	case ADI_AXI_FPGA_SPEED_3:
536 		axi_clkgen->limits.fvco_max = 1600000;
537 		axi_clkgen->limits.fpfd_max = 550000;
538 		break;
539 	default:
540 		return dev_err_probe(dev, -ENODEV, "Unknown speed grade %d\n",
541 				     speed_grade);
542 	}
543 
544 	/* Overwrite vco limits for ultrascale+ */
545 	if (tech == ADI_AXI_FPGA_TECH_ULTRASCALE_PLUS) {
546 		axi_clkgen->limits.fvco_max = 1600000;
547 		axi_clkgen->limits.fvco_min = 800000;
548 	} else if (tech == ADI_AXI_FPGA_TECH_VERSAL) {
549 		axi_clkgen->limits.fvco_max = 4320000;
550 		axi_clkgen->limits.fvco_min = 2160000;
551 	}
552 
553 	return 0;
554 }
555 
556 static const struct clk_ops axi_clkgen_ops = {
557 	.recalc_rate = axi_clkgen_recalc_rate,
558 	.determine_rate = axi_clkgen_determine_rate,
559 	.set_rate = axi_clkgen_set_rate,
560 	.enable = axi_clkgen_enable,
561 	.disable = axi_clkgen_disable,
562 	.set_parent = axi_clkgen_set_parent,
563 	.get_parent = axi_clkgen_get_parent,
564 };
565 
axi_clkgen_probe(struct platform_device * pdev)566 static int axi_clkgen_probe(struct platform_device *pdev)
567 {
568 	const struct axi_clkgen_limits *dflt_limits;
569 	struct axi_clkgen *axi_clkgen;
570 	unsigned int pcore_version;
571 	struct clk_init_data init;
572 	const char *parent_names[2];
573 	const char *clk_name;
574 	struct clk *axi_clk;
575 	unsigned int i;
576 	int ret;
577 
578 	dflt_limits = device_get_match_data(&pdev->dev);
579 	if (!dflt_limits)
580 		return -ENODEV;
581 
582 	axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL);
583 	if (!axi_clkgen)
584 		return -ENOMEM;
585 
586 	axi_clkgen->base = devm_platform_ioremap_resource(pdev, 0);
587 	if (IS_ERR(axi_clkgen->base))
588 		return PTR_ERR(axi_clkgen->base);
589 
590 	init.num_parents = of_clk_get_parent_count(pdev->dev.of_node);
591 
592 	axi_clk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk");
593 	if (!IS_ERR(axi_clk)) {
594 		if (init.num_parents < 2 || init.num_parents > 3)
595 			return -EINVAL;
596 
597 		init.num_parents -= 1;
598 	} else {
599 		/*
600 		 * Legacy... So that old DTs which do not have clock-names still
601 		 * work. In this case we don't explicitly enable the AXI bus
602 		 * clock.
603 		 */
604 		if (PTR_ERR(axi_clk) != -ENOENT)
605 			return PTR_ERR(axi_clk);
606 		if (init.num_parents < 1 || init.num_parents > 2)
607 			return -EINVAL;
608 	}
609 
610 	for (i = 0; i < init.num_parents; i++) {
611 		parent_names[i] = of_clk_get_parent_name(pdev->dev.of_node, i);
612 		if (!parent_names[i])
613 			return -EINVAL;
614 	}
615 
616 	axi_clkgen_read(axi_clkgen, ADI_AXI_REG_VERSION, &pcore_version);
617 
618 	if (ADI_AXI_PCORE_VER_MAJOR(pcore_version) > 0x04) {
619 		ret = axi_clkgen_setup_limits(axi_clkgen, &pdev->dev);
620 		if (ret)
621 			return ret;
622 	} else {
623 		memcpy(&axi_clkgen->limits, dflt_limits,
624 		       sizeof(axi_clkgen->limits));
625 	}
626 
627 	clk_name = pdev->dev.of_node->name;
628 	of_property_read_string(pdev->dev.of_node, "clock-output-names",
629 				&clk_name);
630 
631 	init.name = clk_name;
632 	init.ops = &axi_clkgen_ops;
633 	init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
634 	init.parent_names = parent_names;
635 
636 	axi_clkgen_mmcm_enable(axi_clkgen, false);
637 
638 	axi_clkgen->clk_hw.init = &init;
639 	ret = devm_clk_hw_register(&pdev->dev, &axi_clkgen->clk_hw);
640 	if (ret)
641 		return ret;
642 
643 	return devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_simple_get,
644 					   &axi_clkgen->clk_hw);
645 }
646 
647 static const struct of_device_id axi_clkgen_ids[] = {
648 	{
649 		.compatible = "adi,zynqmp-axi-clkgen-2.00.a",
650 		.data = &axi_clkgen_zynqmp_default_limits,
651 	},
652 	{
653 		.compatible = "adi,axi-clkgen-2.00.a",
654 		.data = &axi_clkgen_zynq_default_limits,
655 	},
656 	{ }
657 };
658 MODULE_DEVICE_TABLE(of, axi_clkgen_ids);
659 
660 static struct platform_driver axi_clkgen_driver = {
661 	.driver = {
662 		.name = "adi-axi-clkgen",
663 		.of_match_table = axi_clkgen_ids,
664 	},
665 	.probe = axi_clkgen_probe,
666 };
667 module_platform_driver(axi_clkgen_driver);
668 
669 MODULE_LICENSE("GPL v2");
670 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
671 MODULE_DESCRIPTION("Driver for the Analog Devices' AXI clkgen pcore clock generator");
672