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 
62 static 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 
70 struct 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 
80 struct 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 
91 static const char * const cdce706_source_name[] = {
92 	"clk_in0", "clk_in1",
93 };
94 
95 static const char * const cdce706_clkin_name[] = {
96 	"clk_in",
97 };
98 
99 static const char * const cdce706_pll_name[] = {
100 	"pll1", "pll2", "pll3",
101 };
102 
103 static const char * const cdce706_divider_parent_name[] = {
104 	"clk_in", "pll1", "pll2", "pll2", "pll3",
105 };
106 
107 static const char *cdce706_divider_name[] = {
108 	"p0", "p1", "p2", "p3", "p4", "p5",
109 };
110 
111 static const char * const cdce706_clkout_name[] = {
112 	"clk_out0", "clk_out1", "clk_out2", "clk_out3", "clk_out4", "clk_out5",
113 };
114 
cdce706_reg_read(struct cdce706_dev_data * dev_data,unsigned reg,unsigned * val)115 static 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 
cdce706_reg_write(struct cdce706_dev_data * dev_data,unsigned reg,unsigned val)125 static 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 
cdce706_reg_update(struct cdce706_dev_data * dev_data,unsigned reg,unsigned mask,unsigned val)135 static 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 
cdce706_clkin_set_parent(struct clk_hw * hw,u8 index)145 static 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 
cdce706_clkin_get_parent(struct clk_hw * hw)153 static 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 
160 static const struct clk_ops cdce706_clkin_ops = {
161 	.set_parent = cdce706_clkin_set_parent,
162 	.get_parent = cdce706_clkin_get_parent,
163 };
164 
cdce706_pll_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)165 static 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 
cdce706_pll_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * parent_rate)188 static 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 
cdce706_pll_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)214 static 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 
254 static 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 
cdce706_divider_set_parent(struct clk_hw * hw,u8 index)260 static 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 
cdce706_divider_get_parent(struct clk_hw * hw)273 static 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 
cdce706_divider_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)280 static 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 
cdce706_divider_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * parent_rate)293 static 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 
cdce706_divider_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)361 static 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 
376 static 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 
cdce706_clkout_prepare(struct clk_hw * hw)384 static 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 
cdce706_clkout_unprepare(struct clk_hw * hw)393 static 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 
cdce706_clkout_set_parent(struct clk_hw * hw,u8 index)401 static 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 
cdce706_clkout_get_parent(struct clk_hw * hw)413 static 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 
cdce706_clkout_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)420 static unsigned long cdce706_clkout_recalc_rate(struct clk_hw *hw,
421 						unsigned long parent_rate)
422 {
423 	return parent_rate;
424 }
425 
cdce706_clkout_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * parent_rate)426 static 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 
cdce706_clkout_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)433 static int cdce706_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
434 				   unsigned long parent_rate)
435 {
436 	return 0;
437 }
438 
439 static 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 
cdce706_register_hw(struct cdce706_dev_data * cdce,struct cdce706_hw_data * hw,unsigned num_hw,const char * const * clk_names,struct clk_init_data * init)449 static 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 
cdce706_register_clkin(struct cdce706_dev_data * cdce)473 static 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 
cdce706_register_plls(struct cdce706_dev_data * cdce)513 static 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 
cdce706_register_dividers(struct cdce706_dev_data * cdce)555 static 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 
cdce706_register_clkouts(struct cdce706_dev_data * cdce)591 static 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 
619 static struct clk_hw *
of_clk_cdce_get(struct of_phandle_args * clkspec,void * data)620 of_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 
cdce706_probe(struct i2c_client * client,const struct i2c_device_id * id)633 static 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 
cdce706_remove(struct i2c_client * client)672 static 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
680 static const struct of_device_id cdce706_dt_match[] = {
681 	{ .compatible = "ti,cdce706" },
682 	{ },
683 };
684 MODULE_DEVICE_TABLE(of, cdce706_dt_match);
685 #endif
686 
687 static const struct i2c_device_id cdce706_id[] = {
688 	{ "cdce706", 0 },
689 	{ }
690 };
691 MODULE_DEVICE_TABLE(i2c, cdce706_id);
692 
693 static 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 };
702 module_i2c_driver(cdce706_i2c_driver);
703 
704 MODULE_AUTHOR("Max Filippov <jcmvbkbc@gmail.com>");
705 MODULE_DESCRIPTION("TI CDCE 706 clock synthesizer driver");
706 MODULE_LICENSE("GPL");
707