0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/platform_device.h>
0010 #include <linux/clk-provider.h>
0011 #include <linux/slab.h>
0012 #include <linux/io.h>
0013 #include <linux/of.h>
0014 #include <linux/module.h>
0015 #include <linux/err.h>
0016
0017 #define AXI_CLKGEN_V2_REG_RESET 0x40
0018 #define AXI_CLKGEN_V2_REG_CLKSEL 0x44
0019 #define AXI_CLKGEN_V2_REG_DRP_CNTRL 0x70
0020 #define AXI_CLKGEN_V2_REG_DRP_STATUS 0x74
0021
0022 #define AXI_CLKGEN_V2_RESET_MMCM_ENABLE BIT(1)
0023 #define AXI_CLKGEN_V2_RESET_ENABLE BIT(0)
0024
0025 #define AXI_CLKGEN_V2_DRP_CNTRL_SEL BIT(29)
0026 #define AXI_CLKGEN_V2_DRP_CNTRL_READ BIT(28)
0027
0028 #define AXI_CLKGEN_V2_DRP_STATUS_BUSY BIT(16)
0029
0030 #define MMCM_REG_CLKOUT5_2 0x07
0031 #define MMCM_REG_CLKOUT0_1 0x08
0032 #define MMCM_REG_CLKOUT0_2 0x09
0033 #define MMCM_REG_CLKOUT6_2 0x13
0034 #define MMCM_REG_CLK_FB1 0x14
0035 #define MMCM_REG_CLK_FB2 0x15
0036 #define MMCM_REG_CLK_DIV 0x16
0037 #define MMCM_REG_LOCK1 0x18
0038 #define MMCM_REG_LOCK2 0x19
0039 #define MMCM_REG_LOCK3 0x1a
0040 #define MMCM_REG_POWER 0x28
0041 #define MMCM_REG_FILTER1 0x4e
0042 #define MMCM_REG_FILTER2 0x4f
0043
0044 #define MMCM_CLKOUT_NOCOUNT BIT(6)
0045
0046 #define MMCM_CLK_DIV_DIVIDE BIT(11)
0047 #define MMCM_CLK_DIV_NOCOUNT BIT(12)
0048
0049 struct axi_clkgen_limits {
0050 unsigned int fpfd_min;
0051 unsigned int fpfd_max;
0052 unsigned int fvco_min;
0053 unsigned int fvco_max;
0054 };
0055
0056 struct axi_clkgen {
0057 void __iomem *base;
0058 struct clk_hw clk_hw;
0059 struct axi_clkgen_limits limits;
0060 };
0061
0062 static uint32_t axi_clkgen_lookup_filter(unsigned int m)
0063 {
0064 switch (m) {
0065 case 0:
0066 return 0x01001990;
0067 case 1:
0068 return 0x01001190;
0069 case 2:
0070 return 0x01009890;
0071 case 3:
0072 return 0x01001890;
0073 case 4:
0074 return 0x01008890;
0075 case 5 ... 8:
0076 return 0x01009090;
0077 case 9 ... 11:
0078 return 0x01000890;
0079 case 12:
0080 return 0x08009090;
0081 case 13 ... 22:
0082 return 0x01001090;
0083 case 23 ... 36:
0084 return 0x01008090;
0085 case 37 ... 46:
0086 return 0x08001090;
0087 default:
0088 return 0x08008090;
0089 }
0090 }
0091
0092 static const uint32_t axi_clkgen_lock_table[] = {
0093 0x060603e8, 0x060603e8, 0x080803e8, 0x0b0b03e8,
0094 0x0e0e03e8, 0x111103e8, 0x131303e8, 0x161603e8,
0095 0x191903e8, 0x1c1c03e8, 0x1f1f0384, 0x1f1f0339,
0096 0x1f1f02ee, 0x1f1f02bc, 0x1f1f028a, 0x1f1f0271,
0097 0x1f1f023f, 0x1f1f0226, 0x1f1f020d, 0x1f1f01f4,
0098 0x1f1f01db, 0x1f1f01c2, 0x1f1f01a9, 0x1f1f0190,
0099 0x1f1f0190, 0x1f1f0177, 0x1f1f015e, 0x1f1f015e,
0100 0x1f1f0145, 0x1f1f0145, 0x1f1f012c, 0x1f1f012c,
0101 0x1f1f012c, 0x1f1f0113, 0x1f1f0113, 0x1f1f0113,
0102 };
0103
0104 static uint32_t axi_clkgen_lookup_lock(unsigned int m)
0105 {
0106 if (m < ARRAY_SIZE(axi_clkgen_lock_table))
0107 return axi_clkgen_lock_table[m];
0108 return 0x1f1f00fa;
0109 }
0110
0111 static const struct axi_clkgen_limits axi_clkgen_zynqmp_default_limits = {
0112 .fpfd_min = 10000,
0113 .fpfd_max = 450000,
0114 .fvco_min = 800000,
0115 .fvco_max = 1600000,
0116 };
0117
0118 static const struct axi_clkgen_limits axi_clkgen_zynq_default_limits = {
0119 .fpfd_min = 10000,
0120 .fpfd_max = 300000,
0121 .fvco_min = 600000,
0122 .fvco_max = 1200000,
0123 };
0124
0125 static void axi_clkgen_calc_params(const struct axi_clkgen_limits *limits,
0126 unsigned long fin, unsigned long fout,
0127 unsigned int *best_d, unsigned int *best_m, unsigned int *best_dout)
0128 {
0129 unsigned long d, d_min, d_max, _d_min, _d_max;
0130 unsigned long m, m_min, m_max;
0131 unsigned long f, dout, best_f, fvco;
0132 unsigned long fract_shift = 0;
0133 unsigned long fvco_min_fract, fvco_max_fract;
0134
0135 fin /= 1000;
0136 fout /= 1000;
0137
0138 best_f = ULONG_MAX;
0139 *best_d = 0;
0140 *best_m = 0;
0141 *best_dout = 0;
0142
0143 d_min = max_t(unsigned long, DIV_ROUND_UP(fin, limits->fpfd_max), 1);
0144 d_max = min_t(unsigned long, fin / limits->fpfd_min, 80);
0145
0146 again:
0147 fvco_min_fract = limits->fvco_min << fract_shift;
0148 fvco_max_fract = limits->fvco_max << fract_shift;
0149
0150 m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min_fract, fin) * d_min, 1);
0151 m_max = min_t(unsigned long, fvco_max_fract * d_max / fin, 64 << fract_shift);
0152
0153 for (m = m_min; m <= m_max; m++) {
0154 _d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max_fract));
0155 _d_max = min(d_max, fin * m / fvco_min_fract);
0156
0157 for (d = _d_min; d <= _d_max; d++) {
0158 fvco = fin * m / d;
0159
0160 dout = DIV_ROUND_CLOSEST(fvco, fout);
0161 dout = clamp_t(unsigned long, dout, 1, 128 << fract_shift);
0162 f = fvco / dout;
0163 if (abs(f - fout) < abs(best_f - fout)) {
0164 best_f = f;
0165 *best_d = d;
0166 *best_m = m << (3 - fract_shift);
0167 *best_dout = dout << (3 - fract_shift);
0168 if (best_f == fout)
0169 return;
0170 }
0171 }
0172 }
0173
0174
0175 if (fract_shift == 0) {
0176 fract_shift = 3;
0177 goto again;
0178 }
0179 }
0180
0181 struct axi_clkgen_div_params {
0182 unsigned int low;
0183 unsigned int high;
0184 unsigned int edge;
0185 unsigned int nocount;
0186 unsigned int frac_en;
0187 unsigned int frac;
0188 unsigned int frac_wf_f;
0189 unsigned int frac_wf_r;
0190 unsigned int frac_phase;
0191 };
0192
0193 static void axi_clkgen_calc_clk_params(unsigned int divider,
0194 unsigned int frac_divider, struct axi_clkgen_div_params *params)
0195 {
0196
0197 memset(params, 0x0, sizeof(*params));
0198
0199 if (divider == 1) {
0200 params->nocount = 1;
0201 return;
0202 }
0203
0204 if (frac_divider == 0) {
0205 params->high = divider / 2;
0206 params->edge = divider % 2;
0207 params->low = divider - params->high;
0208 } else {
0209 params->frac_en = 1;
0210 params->frac = frac_divider;
0211
0212 params->high = divider / 2;
0213 params->edge = divider % 2;
0214 params->low = params->high;
0215
0216 if (params->edge == 0) {
0217 params->high--;
0218 params->frac_wf_r = 1;
0219 }
0220
0221 if (params->edge == 0 || frac_divider == 1)
0222 params->low--;
0223 if (((params->edge == 0) ^ (frac_divider == 1)) ||
0224 (divider == 2 && frac_divider == 1))
0225 params->frac_wf_f = 1;
0226
0227 params->frac_phase = params->edge * 4 + frac_divider / 2;
0228 }
0229 }
0230
0231 static void axi_clkgen_write(struct axi_clkgen *axi_clkgen,
0232 unsigned int reg, unsigned int val)
0233 {
0234 writel(val, axi_clkgen->base + reg);
0235 }
0236
0237 static void axi_clkgen_read(struct axi_clkgen *axi_clkgen,
0238 unsigned int reg, unsigned int *val)
0239 {
0240 *val = readl(axi_clkgen->base + reg);
0241 }
0242
0243 static int axi_clkgen_wait_non_busy(struct axi_clkgen *axi_clkgen)
0244 {
0245 unsigned int timeout = 10000;
0246 unsigned int val;
0247
0248 do {
0249 axi_clkgen_read(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_STATUS, &val);
0250 } while ((val & AXI_CLKGEN_V2_DRP_STATUS_BUSY) && --timeout);
0251
0252 if (val & AXI_CLKGEN_V2_DRP_STATUS_BUSY)
0253 return -EIO;
0254
0255 return val & 0xffff;
0256 }
0257
0258 static int axi_clkgen_mmcm_read(struct axi_clkgen *axi_clkgen,
0259 unsigned int reg, unsigned int *val)
0260 {
0261 unsigned int reg_val;
0262 int ret;
0263
0264 ret = axi_clkgen_wait_non_busy(axi_clkgen);
0265 if (ret < 0)
0266 return ret;
0267
0268 reg_val = AXI_CLKGEN_V2_DRP_CNTRL_SEL | AXI_CLKGEN_V2_DRP_CNTRL_READ;
0269 reg_val |= (reg << 16);
0270
0271 axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_CNTRL, reg_val);
0272
0273 ret = axi_clkgen_wait_non_busy(axi_clkgen);
0274 if (ret < 0)
0275 return ret;
0276
0277 *val = ret;
0278
0279 return 0;
0280 }
0281
0282 static int axi_clkgen_mmcm_write(struct axi_clkgen *axi_clkgen,
0283 unsigned int reg, unsigned int val, unsigned int mask)
0284 {
0285 unsigned int reg_val = 0;
0286 int ret;
0287
0288 ret = axi_clkgen_wait_non_busy(axi_clkgen);
0289 if (ret < 0)
0290 return ret;
0291
0292 if (mask != 0xffff) {
0293 axi_clkgen_mmcm_read(axi_clkgen, reg, ®_val);
0294 reg_val &= ~mask;
0295 }
0296
0297 reg_val |= AXI_CLKGEN_V2_DRP_CNTRL_SEL | (reg << 16) | (val & mask);
0298
0299 axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_CNTRL, reg_val);
0300
0301 return 0;
0302 }
0303
0304 static void axi_clkgen_mmcm_enable(struct axi_clkgen *axi_clkgen,
0305 bool enable)
0306 {
0307 unsigned int val = AXI_CLKGEN_V2_RESET_ENABLE;
0308
0309 if (enable)
0310 val |= AXI_CLKGEN_V2_RESET_MMCM_ENABLE;
0311
0312 axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_RESET, val);
0313 }
0314
0315 static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw)
0316 {
0317 return container_of(clk_hw, struct axi_clkgen, clk_hw);
0318 }
0319
0320 static void axi_clkgen_set_div(struct axi_clkgen *axi_clkgen,
0321 unsigned int reg1, unsigned int reg2, unsigned int reg3,
0322 struct axi_clkgen_div_params *params)
0323 {
0324 axi_clkgen_mmcm_write(axi_clkgen, reg1,
0325 (params->high << 6) | params->low, 0xefff);
0326 axi_clkgen_mmcm_write(axi_clkgen, reg2,
0327 (params->frac << 12) | (params->frac_en << 11) |
0328 (params->frac_wf_r << 10) | (params->edge << 7) |
0329 (params->nocount << 6), 0x7fff);
0330 if (reg3 != 0) {
0331 axi_clkgen_mmcm_write(axi_clkgen, reg3,
0332 (params->frac_phase << 11) | (params->frac_wf_f << 10), 0x3c00);
0333 }
0334 }
0335
0336 static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
0337 unsigned long rate, unsigned long parent_rate)
0338 {
0339 struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
0340 const struct axi_clkgen_limits *limits = &axi_clkgen->limits;
0341 unsigned int d, m, dout;
0342 struct axi_clkgen_div_params params;
0343 uint32_t power = 0;
0344 uint32_t filter;
0345 uint32_t lock;
0346
0347 if (parent_rate == 0 || rate == 0)
0348 return -EINVAL;
0349
0350 axi_clkgen_calc_params(limits, parent_rate, rate, &d, &m, &dout);
0351
0352 if (d == 0 || dout == 0 || m == 0)
0353 return -EINVAL;
0354
0355 if ((dout & 0x7) != 0 || (m & 0x7) != 0)
0356 power |= 0x9800;
0357
0358 axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_POWER, power, 0x9800);
0359
0360 filter = axi_clkgen_lookup_filter(m - 1);
0361 lock = axi_clkgen_lookup_lock(m - 1);
0362
0363 axi_clkgen_calc_clk_params(dout >> 3, dout & 0x7, ¶ms);
0364 axi_clkgen_set_div(axi_clkgen, MMCM_REG_CLKOUT0_1, MMCM_REG_CLKOUT0_2,
0365 MMCM_REG_CLKOUT5_2, ¶ms);
0366
0367 axi_clkgen_calc_clk_params(d, 0, ¶ms);
0368 axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_DIV,
0369 (params.edge << 13) | (params.nocount << 12) |
0370 (params.high << 6) | params.low, 0x3fff);
0371
0372 axi_clkgen_calc_clk_params(m >> 3, m & 0x7, ¶ms);
0373 axi_clkgen_set_div(axi_clkgen, MMCM_REG_CLK_FB1, MMCM_REG_CLK_FB2,
0374 MMCM_REG_CLKOUT6_2, ¶ms);
0375
0376 axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK1, lock & 0x3ff, 0x3ff);
0377 axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK2,
0378 (((lock >> 16) & 0x1f) << 10) | 0x1, 0x7fff);
0379 axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK3,
0380 (((lock >> 24) & 0x1f) << 10) | 0x3e9, 0x7fff);
0381 axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER1, filter >> 16, 0x9900);
0382 axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER2, filter, 0x9900);
0383
0384 return 0;
0385 }
0386
0387 static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate,
0388 unsigned long *parent_rate)
0389 {
0390 struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(hw);
0391 const struct axi_clkgen_limits *limits = &axi_clkgen->limits;
0392 unsigned int d, m, dout;
0393 unsigned long long tmp;
0394
0395 axi_clkgen_calc_params(limits, *parent_rate, rate, &d, &m, &dout);
0396
0397 if (d == 0 || dout == 0 || m == 0)
0398 return -EINVAL;
0399
0400 tmp = (unsigned long long)*parent_rate * m;
0401 tmp = DIV_ROUND_CLOSEST_ULL(tmp, dout * d);
0402
0403 return min_t(unsigned long long, tmp, LONG_MAX);
0404 }
0405
0406 static unsigned int axi_clkgen_get_div(struct axi_clkgen *axi_clkgen,
0407 unsigned int reg1, unsigned int reg2)
0408 {
0409 unsigned int val1, val2;
0410 unsigned int div;
0411
0412 axi_clkgen_mmcm_read(axi_clkgen, reg2, &val2);
0413 if (val2 & MMCM_CLKOUT_NOCOUNT)
0414 return 8;
0415
0416 axi_clkgen_mmcm_read(axi_clkgen, reg1, &val1);
0417
0418 div = (val1 & 0x3f) + ((val1 >> 6) & 0x3f);
0419 div <<= 3;
0420
0421 if (val2 & MMCM_CLK_DIV_DIVIDE) {
0422 if ((val2 & BIT(7)) && (val2 & 0x7000) != 0x1000)
0423 div += 8;
0424 else
0425 div += 16;
0426
0427 div += (val2 >> 12) & 0x7;
0428 }
0429
0430 return div;
0431 }
0432
0433 static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
0434 unsigned long parent_rate)
0435 {
0436 struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
0437 unsigned int d, m, dout;
0438 unsigned long long tmp;
0439 unsigned int val;
0440
0441 dout = axi_clkgen_get_div(axi_clkgen, MMCM_REG_CLKOUT0_1,
0442 MMCM_REG_CLKOUT0_2);
0443 m = axi_clkgen_get_div(axi_clkgen, MMCM_REG_CLK_FB1,
0444 MMCM_REG_CLK_FB2);
0445
0446 axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, &val);
0447 if (val & MMCM_CLK_DIV_NOCOUNT)
0448 d = 1;
0449 else
0450 d = (val & 0x3f) + ((val >> 6) & 0x3f);
0451
0452 if (d == 0 || dout == 0)
0453 return 0;
0454
0455 tmp = (unsigned long long)parent_rate * m;
0456 tmp = DIV_ROUND_CLOSEST_ULL(tmp, dout * d);
0457
0458 return min_t(unsigned long long, tmp, ULONG_MAX);
0459 }
0460
0461 static int axi_clkgen_enable(struct clk_hw *clk_hw)
0462 {
0463 struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
0464
0465 axi_clkgen_mmcm_enable(axi_clkgen, true);
0466
0467 return 0;
0468 }
0469
0470 static void axi_clkgen_disable(struct clk_hw *clk_hw)
0471 {
0472 struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
0473
0474 axi_clkgen_mmcm_enable(axi_clkgen, false);
0475 }
0476
0477 static int axi_clkgen_set_parent(struct clk_hw *clk_hw, u8 index)
0478 {
0479 struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
0480
0481 axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_CLKSEL, index);
0482
0483 return 0;
0484 }
0485
0486 static u8 axi_clkgen_get_parent(struct clk_hw *clk_hw)
0487 {
0488 struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
0489 unsigned int parent;
0490
0491 axi_clkgen_read(axi_clkgen, AXI_CLKGEN_V2_REG_CLKSEL, &parent);
0492
0493 return parent;
0494 }
0495
0496 static const struct clk_ops axi_clkgen_ops = {
0497 .recalc_rate = axi_clkgen_recalc_rate,
0498 .round_rate = axi_clkgen_round_rate,
0499 .set_rate = axi_clkgen_set_rate,
0500 .enable = axi_clkgen_enable,
0501 .disable = axi_clkgen_disable,
0502 .set_parent = axi_clkgen_set_parent,
0503 .get_parent = axi_clkgen_get_parent,
0504 };
0505
0506 static int axi_clkgen_probe(struct platform_device *pdev)
0507 {
0508 const struct axi_clkgen_limits *dflt_limits;
0509 struct axi_clkgen *axi_clkgen;
0510 struct clk_init_data init;
0511 const char *parent_names[2];
0512 const char *clk_name;
0513 unsigned int i;
0514 int ret;
0515
0516 dflt_limits = device_get_match_data(&pdev->dev);
0517 if (!dflt_limits)
0518 return -ENODEV;
0519
0520 axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL);
0521 if (!axi_clkgen)
0522 return -ENOMEM;
0523
0524 axi_clkgen->base = devm_platform_ioremap_resource(pdev, 0);
0525 if (IS_ERR(axi_clkgen->base))
0526 return PTR_ERR(axi_clkgen->base);
0527
0528 init.num_parents = of_clk_get_parent_count(pdev->dev.of_node);
0529 if (init.num_parents < 1 || init.num_parents > 2)
0530 return -EINVAL;
0531
0532 for (i = 0; i < init.num_parents; i++) {
0533 parent_names[i] = of_clk_get_parent_name(pdev->dev.of_node, i);
0534 if (!parent_names[i])
0535 return -EINVAL;
0536 }
0537
0538 memcpy(&axi_clkgen->limits, dflt_limits, sizeof(axi_clkgen->limits));
0539
0540 clk_name = pdev->dev.of_node->name;
0541 of_property_read_string(pdev->dev.of_node, "clock-output-names",
0542 &clk_name);
0543
0544 init.name = clk_name;
0545 init.ops = &axi_clkgen_ops;
0546 init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
0547 init.parent_names = parent_names;
0548
0549 axi_clkgen_mmcm_enable(axi_clkgen, false);
0550
0551 axi_clkgen->clk_hw.init = &init;
0552 ret = devm_clk_hw_register(&pdev->dev, &axi_clkgen->clk_hw);
0553 if (ret)
0554 return ret;
0555
0556 return of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_simple_get,
0557 &axi_clkgen->clk_hw);
0558 }
0559
0560 static int axi_clkgen_remove(struct platform_device *pdev)
0561 {
0562 of_clk_del_provider(pdev->dev.of_node);
0563
0564 return 0;
0565 }
0566
0567 static const struct of_device_id axi_clkgen_ids[] = {
0568 {
0569 .compatible = "adi,zynqmp-axi-clkgen-2.00.a",
0570 .data = &axi_clkgen_zynqmp_default_limits,
0571 },
0572 {
0573 .compatible = "adi,axi-clkgen-2.00.a",
0574 .data = &axi_clkgen_zynq_default_limits,
0575 },
0576 { }
0577 };
0578 MODULE_DEVICE_TABLE(of, axi_clkgen_ids);
0579
0580 static struct platform_driver axi_clkgen_driver = {
0581 .driver = {
0582 .name = "adi-axi-clkgen",
0583 .of_match_table = axi_clkgen_ids,
0584 },
0585 .probe = axi_clkgen_probe,
0586 .remove = axi_clkgen_remove,
0587 };
0588 module_platform_driver(axi_clkgen_driver);
0589
0590 MODULE_LICENSE("GPL v2");
0591 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
0592 MODULE_DESCRIPTION("Driver for the Analog Devices' AXI clkgen pcore clock generator");