cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

clk-cdce706.c (18028B)


      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{
    632	struct i2c_adapter *adapter = client->adapter;
    633	struct cdce706_dev_data *cdce;
    634	int ret;
    635
    636	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
    637		return -EIO;
    638
    639	cdce = devm_kzalloc(&client->dev, sizeof(*cdce), GFP_KERNEL);
    640	if (!cdce)
    641		return -ENOMEM;
    642
    643	cdce->client = client;
    644	cdce->regmap = devm_regmap_init_i2c(client, &cdce706_regmap_config);
    645	if (IS_ERR(cdce->regmap)) {
    646		dev_err(&client->dev, "Failed to initialize regmap\n");
    647		return -EINVAL;
    648	}
    649
    650	i2c_set_clientdata(client, cdce);
    651
    652	ret = cdce706_register_clkin(cdce);
    653	if (ret < 0)
    654		return ret;
    655	ret = cdce706_register_plls(cdce);
    656	if (ret < 0)
    657		return ret;
    658	ret = cdce706_register_dividers(cdce);
    659	if (ret < 0)
    660		return ret;
    661	ret = cdce706_register_clkouts(cdce);
    662	if (ret < 0)
    663		return ret;
    664	return of_clk_add_hw_provider(client->dev.of_node, of_clk_cdce_get,
    665				      cdce);
    666}
    667
    668static int cdce706_remove(struct i2c_client *client)
    669{
    670	of_clk_del_provider(client->dev.of_node);
    671	return 0;
    672}
    673
    674
    675#ifdef CONFIG_OF
    676static const struct of_device_id cdce706_dt_match[] = {
    677	{ .compatible = "ti,cdce706" },
    678	{ },
    679};
    680MODULE_DEVICE_TABLE(of, cdce706_dt_match);
    681#endif
    682
    683static const struct i2c_device_id cdce706_id[] = {
    684	{ "cdce706", 0 },
    685	{ }
    686};
    687MODULE_DEVICE_TABLE(i2c, cdce706_id);
    688
    689static struct i2c_driver cdce706_i2c_driver = {
    690	.driver	= {
    691		.name	= "cdce706",
    692		.of_match_table = of_match_ptr(cdce706_dt_match),
    693	},
    694	.probe_new	= cdce706_probe,
    695	.remove		= cdce706_remove,
    696	.id_table	= cdce706_id,
    697};
    698module_i2c_driver(cdce706_i2c_driver);
    699
    700MODULE_AUTHOR("Max Filippov <jcmvbkbc@gmail.com>");
    701MODULE_DESCRIPTION("TI CDCE 706 clock synthesizer driver");
    702MODULE_LICENSE("GPL");