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