root/drivers/clk/clk-cdce706.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cdce706_reg_read
  2. cdce706_reg_write
  3. cdce706_reg_update
  4. cdce706_clkin_set_parent
  5. cdce706_clkin_get_parent
  6. cdce706_pll_recalc_rate
  7. cdce706_pll_round_rate
  8. cdce706_pll_set_rate
  9. cdce706_divider_set_parent
  10. cdce706_divider_get_parent
  11. cdce706_divider_recalc_rate
  12. cdce706_divider_round_rate
  13. cdce706_divider_set_rate
  14. cdce706_clkout_prepare
  15. cdce706_clkout_unprepare
  16. cdce706_clkout_set_parent
  17. cdce706_clkout_get_parent
  18. cdce706_clkout_recalc_rate
  19. cdce706_clkout_round_rate
  20. cdce706_clkout_set_rate
  21. cdce706_register_hw
  22. cdce706_register_clkin
  23. cdce706_register_plls
  24. cdce706_register_dividers
  25. cdce706_register_clkouts
  26. of_clk_cdce_get
  27. cdce706_probe
  28. cdce706_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * TI CDCE706 programmable 3-PLL clock synthesizer driver
   4  *
   5  * Copyright (c) 2014 Cadence Design Systems Inc.
   6  *
   7  * Reference: http://www.ti.com/lit/ds/symlink/cdce706.pdf
   8  */
   9 
  10 #include <linux/clk.h>
  11 #include <linux/clk-provider.h>
  12 #include <linux/delay.h>
  13 #include <linux/i2c.h>
  14 #include <linux/interrupt.h>
  15 #include <linux/mod_devicetable.h>
  16 #include <linux/module.h>
  17 #include <linux/of.h>
  18 #include <linux/rational.h>
  19 #include <linux/regmap.h>
  20 #include <linux/slab.h>
  21 
  22 #define CDCE706_CLKIN_CLOCK             10
  23 #define CDCE706_CLKIN_SOURCE            11
  24 #define CDCE706_PLL_M_LOW(pll)          (1 + 3 * (pll))
  25 #define CDCE706_PLL_N_LOW(pll)          (2 + 3 * (pll))
  26 #define CDCE706_PLL_HI(pll)             (3 + 3 * (pll))
  27 #define CDCE706_PLL_MUX                 3
  28 #define CDCE706_PLL_FVCO                6
  29 #define CDCE706_DIVIDER(div)            (13 + (div))
  30 #define CDCE706_CLKOUT(out)             (19 + (out))
  31 
  32 #define CDCE706_CLKIN_CLOCK_MASK        0x10
  33 #define CDCE706_CLKIN_SOURCE_SHIFT      6
  34 #define CDCE706_CLKIN_SOURCE_MASK       0xc0
  35 #define CDCE706_CLKIN_SOURCE_LVCMOS     0x40
  36 
  37 #define CDCE706_PLL_MUX_MASK(pll)       (0x80 >> (pll))
  38 #define CDCE706_PLL_LOW_M_MASK          0xff
  39 #define CDCE706_PLL_LOW_N_MASK          0xff
  40 #define CDCE706_PLL_HI_M_MASK           0x1
  41 #define CDCE706_PLL_HI_N_MASK           0x1e
  42 #define CDCE706_PLL_HI_N_SHIFT          1
  43 #define CDCE706_PLL_M_MAX               0x1ff
  44 #define CDCE706_PLL_N_MAX               0xfff
  45 #define CDCE706_PLL_FVCO_MASK(pll)      (0x80 >> (pll))
  46 #define CDCE706_PLL_FREQ_MIN             80000000
  47 #define CDCE706_PLL_FREQ_MAX            300000000
  48 #define CDCE706_PLL_FREQ_HI             180000000
  49 
  50 #define CDCE706_DIVIDER_PLL(div)        (9 + (div) - ((div) > 2) - ((div) > 4))
  51 #define CDCE706_DIVIDER_PLL_SHIFT(div)  ((div) < 2 ? 5 : 3 * ((div) & 1))
  52 #define CDCE706_DIVIDER_PLL_MASK(div)   (0x7 << CDCE706_DIVIDER_PLL_SHIFT(div))
  53 #define CDCE706_DIVIDER_DIVIDER_MASK    0x7f
  54 #define CDCE706_DIVIDER_DIVIDER_MAX     0x7f
  55 
  56 #define CDCE706_CLKOUT_DIVIDER_MASK     0x7
  57 #define CDCE706_CLKOUT_ENABLE_MASK      0x8
  58 
  59 static const struct regmap_config cdce706_regmap_config = {
  60         .reg_bits = 8,
  61         .val_bits = 8,
  62         .val_format_endian = REGMAP_ENDIAN_NATIVE,
  63 };
  64 
  65 #define to_hw_data(phw) (container_of((phw), struct cdce706_hw_data, hw))
  66 
  67 struct cdce706_hw_data {
  68         struct cdce706_dev_data *dev_data;
  69         unsigned idx;
  70         unsigned parent;
  71         struct clk_hw hw;
  72         unsigned div;
  73         unsigned mul;
  74         unsigned mux;
  75 };
  76 
  77 struct cdce706_dev_data {
  78         struct i2c_client *client;
  79         struct regmap *regmap;
  80         struct clk *clkin_clk[2];
  81         const char *clkin_name[2];
  82         struct cdce706_hw_data clkin[1];
  83         struct cdce706_hw_data pll[3];
  84         struct cdce706_hw_data divider[6];
  85         struct cdce706_hw_data clkout[6];
  86 };
  87 
  88 static const char * const cdce706_source_name[] = {
  89         "clk_in0", "clk_in1",
  90 };
  91 
  92 static const char * const cdce706_clkin_name[] = {
  93         "clk_in",
  94 };
  95 
  96 static const char * const cdce706_pll_name[] = {
  97         "pll1", "pll2", "pll3",
  98 };
  99 
 100 static const char * const cdce706_divider_parent_name[] = {
 101         "clk_in", "pll1", "pll2", "pll2", "pll3",
 102 };
 103 
 104 static const char *cdce706_divider_name[] = {
 105         "p0", "p1", "p2", "p3", "p4", "p5",
 106 };
 107 
 108 static const char * const cdce706_clkout_name[] = {
 109         "clk_out0", "clk_out1", "clk_out2", "clk_out3", "clk_out4", "clk_out5",
 110 };
 111 
 112 static int cdce706_reg_read(struct cdce706_dev_data *dev_data, unsigned reg,
 113                             unsigned *val)
 114 {
 115         int rc = regmap_read(dev_data->regmap, reg | 0x80, val);
 116 
 117         if (rc < 0)
 118                 dev_err(&dev_data->client->dev, "error reading reg %u", reg);
 119         return rc;
 120 }
 121 
 122 static int cdce706_reg_write(struct cdce706_dev_data *dev_data, unsigned reg,
 123                              unsigned val)
 124 {
 125         int rc = regmap_write(dev_data->regmap, reg | 0x80, val);
 126 
 127         if (rc < 0)
 128                 dev_err(&dev_data->client->dev, "error writing reg %u", reg);
 129         return rc;
 130 }
 131 
 132 static int cdce706_reg_update(struct cdce706_dev_data *dev_data, unsigned reg,
 133                               unsigned mask, unsigned val)
 134 {
 135         int rc = regmap_update_bits(dev_data->regmap, reg | 0x80, mask, val);
 136 
 137         if (rc < 0)
 138                 dev_err(&dev_data->client->dev, "error updating reg %u", reg);
 139         return rc;
 140 }
 141 
 142 static int cdce706_clkin_set_parent(struct clk_hw *hw, u8 index)
 143 {
 144         struct cdce706_hw_data *hwd = to_hw_data(hw);
 145 
 146         hwd->parent = index;
 147         return 0;
 148 }
 149 
 150 static u8 cdce706_clkin_get_parent(struct clk_hw *hw)
 151 {
 152         struct cdce706_hw_data *hwd = to_hw_data(hw);
 153 
 154         return hwd->parent;
 155 }
 156 
 157 static const struct clk_ops cdce706_clkin_ops = {
 158         .set_parent = cdce706_clkin_set_parent,
 159         .get_parent = cdce706_clkin_get_parent,
 160 };
 161 
 162 static unsigned long cdce706_pll_recalc_rate(struct clk_hw *hw,
 163                                              unsigned long parent_rate)
 164 {
 165         struct cdce706_hw_data *hwd = to_hw_data(hw);
 166 
 167         dev_dbg(&hwd->dev_data->client->dev,
 168                 "%s, pll: %d, mux: %d, mul: %u, div: %u\n",
 169                 __func__, hwd->idx, hwd->mux, hwd->mul, hwd->div);
 170 
 171         if (!hwd->mux) {
 172                 if (hwd->div && hwd->mul) {
 173                         u64 res = (u64)parent_rate * hwd->mul;
 174 
 175                         do_div(res, hwd->div);
 176                         return res;
 177                 }
 178         } else {
 179                 if (hwd->div)
 180                         return parent_rate / hwd->div;
 181         }
 182         return 0;
 183 }
 184 
 185 static long cdce706_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 186                                    unsigned long *parent_rate)
 187 {
 188         struct cdce706_hw_data *hwd = to_hw_data(hw);
 189         unsigned long mul, div;
 190         u64 res;
 191 
 192         dev_dbg(&hwd->dev_data->client->dev,
 193                 "%s, rate: %lu, parent_rate: %lu\n",
 194                 __func__, rate, *parent_rate);
 195 
 196         rational_best_approximation(rate, *parent_rate,
 197                                     CDCE706_PLL_N_MAX, CDCE706_PLL_M_MAX,
 198                                     &mul, &div);
 199         hwd->mul = mul;
 200         hwd->div = div;
 201 
 202         dev_dbg(&hwd->dev_data->client->dev,
 203                 "%s, pll: %d, mul: %lu, div: %lu\n",
 204                 __func__, hwd->idx, mul, div);
 205 
 206         res = (u64)*parent_rate * hwd->mul;
 207         do_div(res, hwd->div);
 208         return res;
 209 }
 210 
 211 static int cdce706_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 212                                 unsigned long parent_rate)
 213 {
 214         struct cdce706_hw_data *hwd = to_hw_data(hw);
 215         unsigned long mul = hwd->mul, div = hwd->div;
 216         int err;
 217 
 218         dev_dbg(&hwd->dev_data->client->dev,
 219                 "%s, pll: %d, mul: %lu, div: %lu\n",
 220                 __func__, hwd->idx, mul, div);
 221 
 222         err = cdce706_reg_update(hwd->dev_data,
 223                                  CDCE706_PLL_HI(hwd->idx),
 224                                  CDCE706_PLL_HI_M_MASK | CDCE706_PLL_HI_N_MASK,
 225                                  ((div >> 8) & CDCE706_PLL_HI_M_MASK) |
 226                                  ((mul >> (8 - CDCE706_PLL_HI_N_SHIFT)) &
 227                                   CDCE706_PLL_HI_N_MASK));
 228         if (err < 0)
 229                 return err;
 230 
 231         err = cdce706_reg_write(hwd->dev_data,
 232                                 CDCE706_PLL_M_LOW(hwd->idx),
 233                                 div & CDCE706_PLL_LOW_M_MASK);
 234         if (err < 0)
 235                 return err;
 236 
 237         err = cdce706_reg_write(hwd->dev_data,
 238                                 CDCE706_PLL_N_LOW(hwd->idx),
 239                                 mul & CDCE706_PLL_LOW_N_MASK);
 240         if (err < 0)
 241                 return err;
 242 
 243         err = cdce706_reg_update(hwd->dev_data,
 244                                  CDCE706_PLL_FVCO,
 245                                  CDCE706_PLL_FVCO_MASK(hwd->idx),
 246                                  rate > CDCE706_PLL_FREQ_HI ?
 247                                  CDCE706_PLL_FVCO_MASK(hwd->idx) : 0);
 248         return err;
 249 }
 250 
 251 static const struct clk_ops cdce706_pll_ops = {
 252         .recalc_rate = cdce706_pll_recalc_rate,
 253         .round_rate = cdce706_pll_round_rate,
 254         .set_rate = cdce706_pll_set_rate,
 255 };
 256 
 257 static int cdce706_divider_set_parent(struct clk_hw *hw, u8 index)
 258 {
 259         struct cdce706_hw_data *hwd = to_hw_data(hw);
 260 
 261         if (hwd->parent == index)
 262                 return 0;
 263         hwd->parent = index;
 264         return cdce706_reg_update(hwd->dev_data,
 265                                   CDCE706_DIVIDER_PLL(hwd->idx),
 266                                   CDCE706_DIVIDER_PLL_MASK(hwd->idx),
 267                                   index << CDCE706_DIVIDER_PLL_SHIFT(hwd->idx));
 268 }
 269 
 270 static u8 cdce706_divider_get_parent(struct clk_hw *hw)
 271 {
 272         struct cdce706_hw_data *hwd = to_hw_data(hw);
 273 
 274         return hwd->parent;
 275 }
 276 
 277 static unsigned long cdce706_divider_recalc_rate(struct clk_hw *hw,
 278                                                  unsigned long parent_rate)
 279 {
 280         struct cdce706_hw_data *hwd = to_hw_data(hw);
 281 
 282         dev_dbg(&hwd->dev_data->client->dev,
 283                 "%s, divider: %d, div: %u\n",
 284                 __func__, hwd->idx, hwd->div);
 285         if (hwd->div)
 286                 return parent_rate / hwd->div;
 287         return 0;
 288 }
 289 
 290 static long cdce706_divider_round_rate(struct clk_hw *hw, unsigned long rate,
 291                                        unsigned long *parent_rate)
 292 {
 293         struct cdce706_hw_data *hwd = to_hw_data(hw);
 294         struct cdce706_dev_data *cdce = hwd->dev_data;
 295         unsigned long mul, div;
 296 
 297         dev_dbg(&hwd->dev_data->client->dev,
 298                 "%s, rate: %lu, parent_rate: %lu\n",
 299                 __func__, rate, *parent_rate);
 300 
 301         rational_best_approximation(rate, *parent_rate,
 302                                     1, CDCE706_DIVIDER_DIVIDER_MAX,
 303                                     &mul, &div);
 304         if (!mul)
 305                 div = CDCE706_DIVIDER_DIVIDER_MAX;
 306 
 307         if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
 308                 unsigned long best_diff = rate;
 309                 unsigned long best_div = 0;
 310                 struct clk *gp_clk = cdce->clkin_clk[cdce->clkin[0].parent];
 311                 unsigned long gp_rate = gp_clk ? clk_get_rate(gp_clk) : 0;
 312 
 313                 for (div = CDCE706_PLL_FREQ_MIN / rate; best_diff &&
 314                      div <= CDCE706_PLL_FREQ_MAX / rate; ++div) {
 315                         unsigned long n, m;
 316                         unsigned long diff;
 317                         unsigned long div_rate;
 318                         u64 div_rate64;
 319 
 320                         if (rate * div < CDCE706_PLL_FREQ_MIN)
 321                                 continue;
 322 
 323                         rational_best_approximation(rate * div, gp_rate,
 324                                                     CDCE706_PLL_N_MAX,
 325                                                     CDCE706_PLL_M_MAX,
 326                                                     &n, &m);
 327                         div_rate64 = (u64)gp_rate * n;
 328                         do_div(div_rate64, m);
 329                         do_div(div_rate64, div);
 330                         div_rate = div_rate64;
 331                         diff = max(div_rate, rate) - min(div_rate, rate);
 332 
 333                         if (diff < best_diff) {
 334                                 best_diff = diff;
 335                                 best_div = div;
 336                                 dev_dbg(&hwd->dev_data->client->dev,
 337                                         "%s, %lu * %lu / %lu / %lu = %lu\n",
 338                                         __func__, gp_rate, n, m, div, div_rate);
 339                         }
 340                 }
 341 
 342                 div = best_div;
 343 
 344                 dev_dbg(&hwd->dev_data->client->dev,
 345                         "%s, altering parent rate: %lu -> %lu\n",
 346                         __func__, *parent_rate, rate * div);
 347                 *parent_rate = rate * div;
 348         }
 349         hwd->div = div;
 350 
 351         dev_dbg(&hwd->dev_data->client->dev,
 352                 "%s, divider: %d, div: %lu\n",
 353                 __func__, hwd->idx, div);
 354 
 355         return *parent_rate / div;
 356 }
 357 
 358 static int cdce706_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 359                                     unsigned long parent_rate)
 360 {
 361         struct cdce706_hw_data *hwd = to_hw_data(hw);
 362 
 363         dev_dbg(&hwd->dev_data->client->dev,
 364                 "%s, divider: %d, div: %u\n",
 365                 __func__, hwd->idx, hwd->div);
 366 
 367         return cdce706_reg_update(hwd->dev_data,
 368                                   CDCE706_DIVIDER(hwd->idx),
 369                                   CDCE706_DIVIDER_DIVIDER_MASK,
 370                                   hwd->div);
 371 }
 372 
 373 static const struct clk_ops cdce706_divider_ops = {
 374         .set_parent = cdce706_divider_set_parent,
 375         .get_parent = cdce706_divider_get_parent,
 376         .recalc_rate = cdce706_divider_recalc_rate,
 377         .round_rate = cdce706_divider_round_rate,
 378         .set_rate = cdce706_divider_set_rate,
 379 };
 380 
 381 static int cdce706_clkout_prepare(struct clk_hw *hw)
 382 {
 383         struct cdce706_hw_data *hwd = to_hw_data(hw);
 384 
 385         return cdce706_reg_update(hwd->dev_data, CDCE706_CLKOUT(hwd->idx),
 386                                   CDCE706_CLKOUT_ENABLE_MASK,
 387                                   CDCE706_CLKOUT_ENABLE_MASK);
 388 }
 389 
 390 static void cdce706_clkout_unprepare(struct clk_hw *hw)
 391 {
 392         struct cdce706_hw_data *hwd = to_hw_data(hw);
 393 
 394         cdce706_reg_update(hwd->dev_data, CDCE706_CLKOUT(hwd->idx),
 395                            CDCE706_CLKOUT_ENABLE_MASK, 0);
 396 }
 397 
 398 static int cdce706_clkout_set_parent(struct clk_hw *hw, u8 index)
 399 {
 400         struct cdce706_hw_data *hwd = to_hw_data(hw);
 401 
 402         if (hwd->parent == index)
 403                 return 0;
 404         hwd->parent = index;
 405         return cdce706_reg_update(hwd->dev_data,
 406                                   CDCE706_CLKOUT(hwd->idx),
 407                                   CDCE706_CLKOUT_ENABLE_MASK, index);
 408 }
 409 
 410 static u8 cdce706_clkout_get_parent(struct clk_hw *hw)
 411 {
 412         struct cdce706_hw_data *hwd = to_hw_data(hw);
 413 
 414         return hwd->parent;
 415 }
 416 
 417 static unsigned long cdce706_clkout_recalc_rate(struct clk_hw *hw,
 418                                                 unsigned long parent_rate)
 419 {
 420         return parent_rate;
 421 }
 422 
 423 static long cdce706_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
 424                                       unsigned long *parent_rate)
 425 {
 426         *parent_rate = rate;
 427         return rate;
 428 }
 429 
 430 static int cdce706_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
 431                                    unsigned long parent_rate)
 432 {
 433         return 0;
 434 }
 435 
 436 static const struct clk_ops cdce706_clkout_ops = {
 437         .prepare = cdce706_clkout_prepare,
 438         .unprepare = cdce706_clkout_unprepare,
 439         .set_parent = cdce706_clkout_set_parent,
 440         .get_parent = cdce706_clkout_get_parent,
 441         .recalc_rate = cdce706_clkout_recalc_rate,
 442         .round_rate = cdce706_clkout_round_rate,
 443         .set_rate = cdce706_clkout_set_rate,
 444 };
 445 
 446 static int cdce706_register_hw(struct cdce706_dev_data *cdce,
 447                                struct cdce706_hw_data *hw, unsigned num_hw,
 448                                const char * const *clk_names,
 449                                struct clk_init_data *init)
 450 {
 451         unsigned i;
 452         int ret;
 453 
 454         for (i = 0; i < num_hw; ++i, ++hw) {
 455                 init->name = clk_names[i];
 456                 hw->dev_data = cdce;
 457                 hw->idx = i;
 458                 hw->hw.init = init;
 459                 ret = devm_clk_hw_register(&cdce->client->dev,
 460                                             &hw->hw);
 461                 if (ret) {
 462                         dev_err(&cdce->client->dev, "Failed to register %s\n",
 463                                 clk_names[i]);
 464                         return ret;
 465                 }
 466         }
 467         return 0;
 468 }
 469 
 470 static int cdce706_register_clkin(struct cdce706_dev_data *cdce)
 471 {
 472         struct clk_init_data init = {
 473                 .ops = &cdce706_clkin_ops,
 474                 .parent_names = cdce->clkin_name,
 475                 .num_parents = ARRAY_SIZE(cdce->clkin_name),
 476         };
 477         unsigned i;
 478         int ret;
 479         unsigned clock, source;
 480 
 481         for (i = 0; i < ARRAY_SIZE(cdce->clkin_name); ++i) {
 482                 struct clk *parent = devm_clk_get(&cdce->client->dev,
 483                                                   cdce706_source_name[i]);
 484 
 485                 if (IS_ERR(parent)) {
 486                         cdce->clkin_name[i] = cdce706_source_name[i];
 487                 } else {
 488                         cdce->clkin_name[i] = __clk_get_name(parent);
 489                         cdce->clkin_clk[i] = parent;
 490                 }
 491         }
 492 
 493         ret = cdce706_reg_read(cdce, CDCE706_CLKIN_SOURCE, &source);
 494         if (ret < 0)
 495                 return ret;
 496         if ((source & CDCE706_CLKIN_SOURCE_MASK) ==
 497             CDCE706_CLKIN_SOURCE_LVCMOS) {
 498                 ret = cdce706_reg_read(cdce, CDCE706_CLKIN_CLOCK, &clock);
 499                 if (ret < 0)
 500                         return ret;
 501                 cdce->clkin[0].parent = !!(clock & CDCE706_CLKIN_CLOCK_MASK);
 502         }
 503 
 504         ret = cdce706_register_hw(cdce, cdce->clkin,
 505                                   ARRAY_SIZE(cdce->clkin),
 506                                   cdce706_clkin_name, &init);
 507         return ret;
 508 }
 509 
 510 static int cdce706_register_plls(struct cdce706_dev_data *cdce)
 511 {
 512         struct clk_init_data init = {
 513                 .ops = &cdce706_pll_ops,
 514                 .parent_names = cdce706_clkin_name,
 515                 .num_parents = ARRAY_SIZE(cdce706_clkin_name),
 516         };
 517         unsigned i;
 518         int ret;
 519         unsigned mux;
 520 
 521         ret = cdce706_reg_read(cdce, CDCE706_PLL_MUX, &mux);
 522         if (ret < 0)
 523                 return ret;
 524 
 525         for (i = 0; i < ARRAY_SIZE(cdce->pll); ++i) {
 526                 unsigned m, n, v;
 527 
 528                 ret = cdce706_reg_read(cdce, CDCE706_PLL_M_LOW(i), &m);
 529                 if (ret < 0)
 530                         return ret;
 531                 ret = cdce706_reg_read(cdce, CDCE706_PLL_N_LOW(i), &n);
 532                 if (ret < 0)
 533                         return ret;
 534                 ret = cdce706_reg_read(cdce, CDCE706_PLL_HI(i), &v);
 535                 if (ret < 0)
 536                         return ret;
 537                 cdce->pll[i].div = m | ((v & CDCE706_PLL_HI_M_MASK) << 8);
 538                 cdce->pll[i].mul = n | ((v & CDCE706_PLL_HI_N_MASK) <<
 539                                         (8 - CDCE706_PLL_HI_N_SHIFT));
 540                 cdce->pll[i].mux = mux & CDCE706_PLL_MUX_MASK(i);
 541                 dev_dbg(&cdce->client->dev,
 542                         "%s: i: %u, div: %u, mul: %u, mux: %d\n", __func__, i,
 543                         cdce->pll[i].div, cdce->pll[i].mul, cdce->pll[i].mux);
 544         }
 545 
 546         ret = cdce706_register_hw(cdce, cdce->pll,
 547                                   ARRAY_SIZE(cdce->pll),
 548                                   cdce706_pll_name, &init);
 549         return ret;
 550 }
 551 
 552 static int cdce706_register_dividers(struct cdce706_dev_data *cdce)
 553 {
 554         struct clk_init_data init = {
 555                 .ops = &cdce706_divider_ops,
 556                 .parent_names = cdce706_divider_parent_name,
 557                 .num_parents = ARRAY_SIZE(cdce706_divider_parent_name),
 558                 .flags = CLK_SET_RATE_PARENT,
 559         };
 560         unsigned i;
 561         int ret;
 562 
 563         for (i = 0; i < ARRAY_SIZE(cdce->divider); ++i) {
 564                 unsigned val;
 565 
 566                 ret = cdce706_reg_read(cdce, CDCE706_DIVIDER_PLL(i), &val);
 567                 if (ret < 0)
 568                         return ret;
 569                 cdce->divider[i].parent =
 570                         (val & CDCE706_DIVIDER_PLL_MASK(i)) >>
 571                         CDCE706_DIVIDER_PLL_SHIFT(i);
 572 
 573                 ret = cdce706_reg_read(cdce, CDCE706_DIVIDER(i), &val);
 574                 if (ret < 0)
 575                         return ret;
 576                 cdce->divider[i].div = val & CDCE706_DIVIDER_DIVIDER_MASK;
 577                 dev_dbg(&cdce->client->dev,
 578                         "%s: i: %u, parent: %u, div: %u\n", __func__, i,
 579                         cdce->divider[i].parent, cdce->divider[i].div);
 580         }
 581 
 582         ret = cdce706_register_hw(cdce, cdce->divider,
 583                                   ARRAY_SIZE(cdce->divider),
 584                                   cdce706_divider_name, &init);
 585         return ret;
 586 }
 587 
 588 static int cdce706_register_clkouts(struct cdce706_dev_data *cdce)
 589 {
 590         struct clk_init_data init = {
 591                 .ops = &cdce706_clkout_ops,
 592                 .parent_names = cdce706_divider_name,
 593                 .num_parents = ARRAY_SIZE(cdce706_divider_name),
 594                 .flags = CLK_SET_RATE_PARENT,
 595         };
 596         unsigned i;
 597         int ret;
 598 
 599         for (i = 0; i < ARRAY_SIZE(cdce->clkout); ++i) {
 600                 unsigned val;
 601 
 602                 ret = cdce706_reg_read(cdce, CDCE706_CLKOUT(i), &val);
 603                 if (ret < 0)
 604                         return ret;
 605                 cdce->clkout[i].parent = val & CDCE706_CLKOUT_DIVIDER_MASK;
 606                 dev_dbg(&cdce->client->dev,
 607                         "%s: i: %u, parent: %u\n", __func__, i,
 608                         cdce->clkout[i].parent);
 609         }
 610 
 611         return cdce706_register_hw(cdce, cdce->clkout,
 612                                    ARRAY_SIZE(cdce->clkout),
 613                                    cdce706_clkout_name, &init);
 614 }
 615 
 616 static struct clk_hw *
 617 of_clk_cdce_get(struct of_phandle_args *clkspec, void *data)
 618 {
 619         struct cdce706_dev_data *cdce = data;
 620         unsigned int idx = clkspec->args[0];
 621 
 622         if (idx >= ARRAY_SIZE(cdce->clkout)) {
 623                 pr_err("%s: invalid index %u\n", __func__, idx);
 624                 return ERR_PTR(-EINVAL);
 625         }
 626 
 627         return &cdce->clkout[idx].hw;
 628 }
 629 
 630 static int cdce706_probe(struct i2c_client *client,
 631                          const struct i2c_device_id *id)
 632 {
 633         struct i2c_adapter *adapter = client->adapter;
 634         struct cdce706_dev_data *cdce;
 635         int ret;
 636 
 637         if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 638                 return -EIO;
 639 
 640         cdce = devm_kzalloc(&client->dev, sizeof(*cdce), GFP_KERNEL);
 641         if (!cdce)
 642                 return -ENOMEM;
 643 
 644         cdce->client = client;
 645         cdce->regmap = devm_regmap_init_i2c(client, &cdce706_regmap_config);
 646         if (IS_ERR(cdce->regmap)) {
 647                 dev_err(&client->dev, "Failed to initialize regmap\n");
 648                 return -EINVAL;
 649         }
 650 
 651         i2c_set_clientdata(client, cdce);
 652 
 653         ret = cdce706_register_clkin(cdce);
 654         if (ret < 0)
 655                 return ret;
 656         ret = cdce706_register_plls(cdce);
 657         if (ret < 0)
 658                 return ret;
 659         ret = cdce706_register_dividers(cdce);
 660         if (ret < 0)
 661                 return ret;
 662         ret = cdce706_register_clkouts(cdce);
 663         if (ret < 0)
 664                 return ret;
 665         return of_clk_add_hw_provider(client->dev.of_node, of_clk_cdce_get,
 666                                       cdce);
 667 }
 668 
 669 static int cdce706_remove(struct i2c_client *client)
 670 {
 671         of_clk_del_provider(client->dev.of_node);
 672         return 0;
 673 }
 674 
 675 
 676 #ifdef CONFIG_OF
 677 static const struct of_device_id cdce706_dt_match[] = {
 678         { .compatible = "ti,cdce706" },
 679         { },
 680 };
 681 MODULE_DEVICE_TABLE(of, cdce706_dt_match);
 682 #endif
 683 
 684 static const struct i2c_device_id cdce706_id[] = {
 685         { "cdce706", 0 },
 686         { }
 687 };
 688 MODULE_DEVICE_TABLE(i2c, cdce706_id);
 689 
 690 static struct i2c_driver cdce706_i2c_driver = {
 691         .driver = {
 692                 .name   = "cdce706",
 693                 .of_match_table = of_match_ptr(cdce706_dt_match),
 694         },
 695         .probe          = cdce706_probe,
 696         .remove         = cdce706_remove,
 697         .id_table       = cdce706_id,
 698 };
 699 module_i2c_driver(cdce706_i2c_driver);
 700 
 701 MODULE_AUTHOR("Max Filippov <jcmvbkbc@gmail.com>");
 702 MODULE_DESCRIPTION("TI CDCE 706 clock synthesizer driver");
 703 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */