linux/drivers/clk/clk-cdce706.c
<<
>>
Prefs
   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: https://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
  59static 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
  67struct 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
  77struct 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
  88static const char * const cdce706_source_name[] = {
  89        "clk_in0", "clk_in1",
  90};
  91
  92static const char * const cdce706_clkin_name[] = {
  93        "clk_in",
  94};
  95
  96static const char * const cdce706_pll_name[] = {
  97        "pll1", "pll2", "pll3",
  98};
  99
 100static const char * const cdce706_divider_parent_name[] = {
 101        "clk_in", "pll1", "pll2", "pll2", "pll3",
 102};
 103
 104static const char *cdce706_divider_name[] = {
 105        "p0", "p1", "p2", "p3", "p4", "p5",
 106};
 107
 108static const char * const cdce706_clkout_name[] = {
 109        "clk_out0", "clk_out1", "clk_out2", "clk_out3", "clk_out4", "clk_out5",
 110};
 111
 112static 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
 122static 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
 132static 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
 142static 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
 150static 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
 157static const struct clk_ops cdce706_clkin_ops = {
 158        .set_parent = cdce706_clkin_set_parent,
 159        .get_parent = cdce706_clkin_get_parent,
 160};
 161
 162static 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
 185static 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
 211static 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
 251static 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
 257static 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
 270static 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
 277static 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
 290static 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
 358static 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
 373static 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
 381static 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
 390static 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
 398static 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
 410static 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
 417static unsigned long cdce706_clkout_recalc_rate(struct clk_hw *hw,
 418                                                unsigned long parent_rate)
 419{
 420        return parent_rate;
 421}
 422
 423static 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
 430static int cdce706_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
 431                                   unsigned long parent_rate)
 432{
 433        return 0;
 434}
 435
 436static 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
 446static 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
 470static 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
 510static 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
 552static 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
 588static 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
 616static struct clk_hw *
 617of_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
 630static 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
 669static 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
 677static const struct of_device_id cdce706_dt_match[] = {
 678        { .compatible = "ti,cdce706" },
 679        { },
 680};
 681MODULE_DEVICE_TABLE(of, cdce706_dt_match);
 682#endif
 683
 684static const struct i2c_device_id cdce706_id[] = {
 685        { "cdce706", 0 },
 686        { }
 687};
 688MODULE_DEVICE_TABLE(i2c, cdce706_id);
 689
 690static 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};
 699module_i2c_driver(cdce706_i2c_driver);
 700
 701MODULE_AUTHOR("Max Filippov <jcmvbkbc@gmail.com>");
 702MODULE_DESCRIPTION("TI CDCE 706 clock synthesizer driver");
 703MODULE_LICENSE("GPL");
 704