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, ®_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, ¶ms);
371 axi_clkgen_set_div(axi_clkgen, MMCM_REG_CLKOUT0_1, MMCM_REG_CLKOUT0_2,
372 MMCM_REG_CLKOUT5_2, ¶ms);
373
374 axi_clkgen_calc_clk_params(d, 0, ¶ms);
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, ¶ms);
380 axi_clkgen_set_div(axi_clkgen, MMCM_REG_CLK_FB1, MMCM_REG_CLK_FB2,
381 MMCM_REG_CLKOUT6_2, ¶ms);
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, ®_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 ®_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