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	.determine_rate = clk_hw_determine_rate_no_reparent,
159	.set_parent = cdce706_clkin_set_parent,
160	.get_parent = cdce706_clkin_get_parent,
161};
162
163static unsigned long cdce706_pll_recalc_rate(struct clk_hw *hw,
164					     unsigned long parent_rate)
165{
166	struct cdce706_hw_data *hwd = to_hw_data(hw);
167
168	dev_dbg(&hwd->dev_data->client->dev,
169		"%s, pll: %d, mux: %d, mul: %u, div: %u\n",
170		__func__, hwd->idx, hwd->mux, hwd->mul, hwd->div);
171
172	if (!hwd->mux) {
173		if (hwd->div && hwd->mul) {
174			u64 res = (u64)parent_rate * hwd->mul;
175
176			do_div(res, hwd->div);
177			return res;
178		}
179	} else {
180		if (hwd->div)
181			return parent_rate / hwd->div;
182	}
183	return 0;
184}
185
186static long cdce706_pll_round_rate(struct clk_hw *hw, unsigned long rate,
187				   unsigned long *parent_rate)
188{
189	struct cdce706_hw_data *hwd = to_hw_data(hw);
190	unsigned long mul, div;
191	u64 res;
192
193	dev_dbg(&hwd->dev_data->client->dev,
194		"%s, rate: %lu, parent_rate: %lu\n",
195		__func__, rate, *parent_rate);
196
197	rational_best_approximation(rate, *parent_rate,
198				    CDCE706_PLL_N_MAX, CDCE706_PLL_M_MAX,
199				    &mul, &div);
200	hwd->mul = mul;
201	hwd->div = div;
202
203	dev_dbg(&hwd->dev_data->client->dev,
204		"%s, pll: %d, mul: %lu, div: %lu\n",
205		__func__, hwd->idx, mul, div);
206
207	res = (u64)*parent_rate * hwd->mul;
208	do_div(res, hwd->div);
209	return res;
210}
211
212static int cdce706_pll_set_rate(struct clk_hw *hw, unsigned long rate,
213				unsigned long parent_rate)
214{
215	struct cdce706_hw_data *hwd = to_hw_data(hw);
216	unsigned long mul = hwd->mul, div = hwd->div;
217	int err;
218
219	dev_dbg(&hwd->dev_data->client->dev,
220		"%s, pll: %d, mul: %lu, div: %lu\n",
221		__func__, hwd->idx, mul, div);
222
223	err = cdce706_reg_update(hwd->dev_data,
224				 CDCE706_PLL_HI(hwd->idx),
225				 CDCE706_PLL_HI_M_MASK | CDCE706_PLL_HI_N_MASK,
226				 ((div >> 8) & CDCE706_PLL_HI_M_MASK) |
227				 ((mul >> (8 - CDCE706_PLL_HI_N_SHIFT)) &
228				  CDCE706_PLL_HI_N_MASK));
229	if (err < 0)
230		return err;
231
232	err = cdce706_reg_write(hwd->dev_data,
233				CDCE706_PLL_M_LOW(hwd->idx),
234				div & CDCE706_PLL_LOW_M_MASK);
235	if (err < 0)
236		return err;
237
238	err = cdce706_reg_write(hwd->dev_data,
239				CDCE706_PLL_N_LOW(hwd->idx),
240				mul & CDCE706_PLL_LOW_N_MASK);
241	if (err < 0)
242		return err;
243
244	err = cdce706_reg_update(hwd->dev_data,
245				 CDCE706_PLL_FVCO,
246				 CDCE706_PLL_FVCO_MASK(hwd->idx),
247				 rate > CDCE706_PLL_FREQ_HI ?
248				 CDCE706_PLL_FVCO_MASK(hwd->idx) : 0);
249	return err;
250}
251
252static const struct clk_ops cdce706_pll_ops = {
253	.recalc_rate = cdce706_pll_recalc_rate,
254	.round_rate = cdce706_pll_round_rate,
255	.set_rate = cdce706_pll_set_rate,
256};
257
258static int cdce706_divider_set_parent(struct clk_hw *hw, u8 index)
259{
260	struct cdce706_hw_data *hwd = to_hw_data(hw);
261
262	if (hwd->parent == index)
263		return 0;
264	hwd->parent = index;
265	return cdce706_reg_update(hwd->dev_data,
266				  CDCE706_DIVIDER_PLL(hwd->idx),
267				  CDCE706_DIVIDER_PLL_MASK(hwd->idx),
268				  index << CDCE706_DIVIDER_PLL_SHIFT(hwd->idx));
269}
270
271static u8 cdce706_divider_get_parent(struct clk_hw *hw)
272{
273	struct cdce706_hw_data *hwd = to_hw_data(hw);
274
275	return hwd->parent;
276}
277
278static unsigned long cdce706_divider_recalc_rate(struct clk_hw *hw,
279						 unsigned long parent_rate)
280{
281	struct cdce706_hw_data *hwd = to_hw_data(hw);
282
283	dev_dbg(&hwd->dev_data->client->dev,
284		"%s, divider: %d, div: %u\n",
285		__func__, hwd->idx, hwd->div);
286	if (hwd->div)
287		return parent_rate / hwd->div;
288	return 0;
289}
290
291static int cdce706_divider_determine_rate(struct clk_hw *hw,
292					  struct clk_rate_request *req)
293{
294	struct cdce706_hw_data *hwd = to_hw_data(hw);
295	struct cdce706_dev_data *cdce = hwd->dev_data;
296	unsigned long rate = req->rate;
297	unsigned long mul, div;
298
299	dev_dbg(&hwd->dev_data->client->dev,
300		"%s, rate: %lu, parent_rate: %lu\n",
301		__func__, rate, req->best_parent_rate);
302
303	rational_best_approximation(rate, req->best_parent_rate,
304				    1, CDCE706_DIVIDER_DIVIDER_MAX,
305				    &mul, &div);
306	if (!mul)
307		div = CDCE706_DIVIDER_DIVIDER_MAX;
308
309	if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
310		unsigned long best_diff = rate;
311		unsigned long best_div = 0;
312		struct clk *gp_clk = cdce->clkin_clk[cdce->clkin[0].parent];
313		unsigned long gp_rate = gp_clk ? clk_get_rate(gp_clk) : 0;
314
315		for (div = CDCE706_PLL_FREQ_MIN / rate; best_diff &&
316		     div <= CDCE706_PLL_FREQ_MAX / rate; ++div) {
317			unsigned long n, m;
318			unsigned long diff;
319			unsigned long div_rate;
320			u64 div_rate64;
321
322			if (rate * div < CDCE706_PLL_FREQ_MIN)
323				continue;
324
325			rational_best_approximation(rate * div, gp_rate,
326						    CDCE706_PLL_N_MAX,
327						    CDCE706_PLL_M_MAX,
328						    &n, &m);
329			div_rate64 = (u64)gp_rate * n;
330			do_div(div_rate64, m);
331			do_div(div_rate64, div);
332			div_rate = div_rate64;
333			diff = max(div_rate, rate) - min(div_rate, rate);
334
335			if (diff < best_diff) {
336				best_diff = diff;
337				best_div = div;
338				dev_dbg(&hwd->dev_data->client->dev,
339					"%s, %lu * %lu / %lu / %lu = %lu\n",
340					__func__, gp_rate, n, m, div, div_rate);
341			}
342		}
343
344		div = best_div;
345
346		dev_dbg(&hwd->dev_data->client->dev,
347			"%s, altering parent rate: %lu -> %lu\n",
348			__func__, req->best_parent_rate, rate * div);
349		req->best_parent_rate = rate * div;
350	}
351	hwd->div = div;
352
353	dev_dbg(&hwd->dev_data->client->dev,
354		"%s, divider: %d, div: %lu\n",
355		__func__, hwd->idx, div);
356
357	req->rate = req->best_parent_rate / div;
358	return 0;
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	.determine_rate = cdce706_divider_determine_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 int cdce706_clkout_determine_rate(struct clk_hw *hw,
427					 struct clk_rate_request *req)
428{
429	req->best_parent_rate = req->rate;
430
431	return 0;
432}
433
434static int cdce706_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
435				   unsigned long parent_rate)
436{
437	return 0;
438}
439
440static const struct clk_ops cdce706_clkout_ops = {
441	.prepare = cdce706_clkout_prepare,
442	.unprepare = cdce706_clkout_unprepare,
443	.set_parent = cdce706_clkout_set_parent,
444	.get_parent = cdce706_clkout_get_parent,
445	.recalc_rate = cdce706_clkout_recalc_rate,
446	.determine_rate = cdce706_clkout_determine_rate,
447	.set_rate = cdce706_clkout_set_rate,
448};
449
450static int cdce706_register_hw(struct cdce706_dev_data *cdce,
451			       struct cdce706_hw_data *hw, unsigned num_hw,
452			       const char * const *clk_names,
453			       struct clk_init_data *init)
454{
455	unsigned i;
456	int ret;
457
458	for (i = 0; i < num_hw; ++i, ++hw) {
459		init->name = clk_names[i];
460		hw->dev_data = cdce;
461		hw->idx = i;
462		hw->hw.init = init;
463		ret = devm_clk_hw_register(&cdce->client->dev,
464					    &hw->hw);
465		if (ret) {
466			dev_err(&cdce->client->dev, "Failed to register %s\n",
467				clk_names[i]);
468			return ret;
469		}
470	}
471	return 0;
472}
473
474static int cdce706_register_clkin(struct cdce706_dev_data *cdce)
475{
476	struct clk_init_data init = {
477		.ops = &cdce706_clkin_ops,
478		.parent_names = cdce->clkin_name,
479		.num_parents = ARRAY_SIZE(cdce->clkin_name),
480	};
481	unsigned i;
482	int ret;
483	unsigned clock, source;
484
485	for (i = 0; i < ARRAY_SIZE(cdce->clkin_name); ++i) {
486		struct clk *parent = devm_clk_get(&cdce->client->dev,
487						  cdce706_source_name[i]);
488
489		if (IS_ERR(parent)) {
490			cdce->clkin_name[i] = cdce706_source_name[i];
491		} else {
492			cdce->clkin_name[i] = __clk_get_name(parent);
493			cdce->clkin_clk[i] = parent;
494		}
495	}
496
497	ret = cdce706_reg_read(cdce, CDCE706_CLKIN_SOURCE, &source);
498	if (ret < 0)
499		return ret;
500	if ((source & CDCE706_CLKIN_SOURCE_MASK) ==
501	    CDCE706_CLKIN_SOURCE_LVCMOS) {
502		ret = cdce706_reg_read(cdce, CDCE706_CLKIN_CLOCK, &clock);
503		if (ret < 0)
504			return ret;
505		cdce->clkin[0].parent = !!(clock & CDCE706_CLKIN_CLOCK_MASK);
506	}
507
508	ret = cdce706_register_hw(cdce, cdce->clkin,
509				  ARRAY_SIZE(cdce->clkin),
510				  cdce706_clkin_name, &init);
511	return ret;
512}
513
514static int cdce706_register_plls(struct cdce706_dev_data *cdce)
515{
516	struct clk_init_data init = {
517		.ops = &cdce706_pll_ops,
518		.parent_names = cdce706_clkin_name,
519		.num_parents = ARRAY_SIZE(cdce706_clkin_name),
520	};
521	unsigned i;
522	int ret;
523	unsigned mux;
524
525	ret = cdce706_reg_read(cdce, CDCE706_PLL_MUX, &mux);
526	if (ret < 0)
527		return ret;
528
529	for (i = 0; i < ARRAY_SIZE(cdce->pll); ++i) {
530		unsigned m, n, v;
531
532		ret = cdce706_reg_read(cdce, CDCE706_PLL_M_LOW(i), &m);
533		if (ret < 0)
534			return ret;
535		ret = cdce706_reg_read(cdce, CDCE706_PLL_N_LOW(i), &n);
536		if (ret < 0)
537			return ret;
538		ret = cdce706_reg_read(cdce, CDCE706_PLL_HI(i), &v);
539		if (ret < 0)
540			return ret;
541		cdce->pll[i].div = m | ((v & CDCE706_PLL_HI_M_MASK) << 8);
542		cdce->pll[i].mul = n | ((v & CDCE706_PLL_HI_N_MASK) <<
543					(8 - CDCE706_PLL_HI_N_SHIFT));
544		cdce->pll[i].mux = mux & CDCE706_PLL_MUX_MASK(i);
545		dev_dbg(&cdce->client->dev,
546			"%s: i: %u, div: %u, mul: %u, mux: %d\n", __func__, i,
547			cdce->pll[i].div, cdce->pll[i].mul, cdce->pll[i].mux);
548	}
549
550	ret = cdce706_register_hw(cdce, cdce->pll,
551				  ARRAY_SIZE(cdce->pll),
552				  cdce706_pll_name, &init);
553	return ret;
554}
555
556static int cdce706_register_dividers(struct cdce706_dev_data *cdce)
557{
558	struct clk_init_data init = {
559		.ops = &cdce706_divider_ops,
560		.parent_names = cdce706_divider_parent_name,
561		.num_parents = ARRAY_SIZE(cdce706_divider_parent_name),
562		.flags = CLK_SET_RATE_PARENT,
563	};
564	unsigned i;
565	int ret;
566
567	for (i = 0; i < ARRAY_SIZE(cdce->divider); ++i) {
568		unsigned val;
569
570		ret = cdce706_reg_read(cdce, CDCE706_DIVIDER_PLL(i), &val);
571		if (ret < 0)
572			return ret;
573		cdce->divider[i].parent =
574			(val & CDCE706_DIVIDER_PLL_MASK(i)) >>
575			CDCE706_DIVIDER_PLL_SHIFT(i);
576
577		ret = cdce706_reg_read(cdce, CDCE706_DIVIDER(i), &val);
578		if (ret < 0)
579			return ret;
580		cdce->divider[i].div = val & CDCE706_DIVIDER_DIVIDER_MASK;
581		dev_dbg(&cdce->client->dev,
582			"%s: i: %u, parent: %u, div: %u\n", __func__, i,
583			cdce->divider[i].parent, cdce->divider[i].div);
584	}
585
586	ret = cdce706_register_hw(cdce, cdce->divider,
587				  ARRAY_SIZE(cdce->divider),
588				  cdce706_divider_name, &init);
589	return ret;
590}
591
592static int cdce706_register_clkouts(struct cdce706_dev_data *cdce)
593{
594	struct clk_init_data init = {
595		.ops = &cdce706_clkout_ops,
596		.parent_names = cdce706_divider_name,
597		.num_parents = ARRAY_SIZE(cdce706_divider_name),
598		.flags = CLK_SET_RATE_PARENT,
599	};
600	unsigned i;
601	int ret;
602
603	for (i = 0; i < ARRAY_SIZE(cdce->clkout); ++i) {
604		unsigned val;
605
606		ret = cdce706_reg_read(cdce, CDCE706_CLKOUT(i), &val);
607		if (ret < 0)
608			return ret;
609		cdce->clkout[i].parent = val & CDCE706_CLKOUT_DIVIDER_MASK;
610		dev_dbg(&cdce->client->dev,
611			"%s: i: %u, parent: %u\n", __func__, i,
612			cdce->clkout[i].parent);
613	}
614
615	return cdce706_register_hw(cdce, cdce->clkout,
616				   ARRAY_SIZE(cdce->clkout),
617				   cdce706_clkout_name, &init);
618}
619
620static struct clk_hw *
621of_clk_cdce_get(struct of_phandle_args *clkspec, void *data)
622{
623	struct cdce706_dev_data *cdce = data;
624	unsigned int idx = clkspec->args[0];
625
626	if (idx >= ARRAY_SIZE(cdce->clkout)) {
627		pr_err("%s: invalid index %u\n", __func__, idx);
628		return ERR_PTR(-EINVAL);
629	}
630
631	return &cdce->clkout[idx].hw;
632}
633
634static int cdce706_probe(struct i2c_client *client)
635{
636	struct i2c_adapter *adapter = client->adapter;
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 devm_of_clk_add_hw_provider(&client->dev, of_clk_cdce_get,
669					   cdce);
670}
671
672#ifdef CONFIG_OF
673static const struct of_device_id cdce706_dt_match[] = {
674	{ .compatible = "ti,cdce706" },
675	{ },
676};
677MODULE_DEVICE_TABLE(of, cdce706_dt_match);
678#endif
679
680static const struct i2c_device_id cdce706_id[] = {
681	{ "cdce706", 0 },
682	{ }
683};
684MODULE_DEVICE_TABLE(i2c, cdce706_id);
685
686static struct i2c_driver cdce706_i2c_driver = {
687	.driver	= {
688		.name	= "cdce706",
689		.of_match_table = of_match_ptr(cdce706_dt_match),
690	},
691	.probe		= cdce706_probe,
692	.id_table	= cdce706_id,
693};
694module_i2c_driver(cdce706_i2c_driver);
695
696MODULE_AUTHOR("Max Filippov <jcmvbkbc@gmail.com>");
697MODULE_DESCRIPTION("TI CDCE 706 clock synthesizer driver");
698MODULE_LICENSE("GPL");