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