Linux Audio

Check our new training course

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