Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  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");