brintos

brintos / linux-shallow public Read only

0
0
Text · 17.6 KiB · dd3d42d Raw
699 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * TI CDCE706 programmable 3-PLL clock synthesizer driver4 *5 * Copyright (c) 2014 Cadence Design Systems Inc.6 *7 * Reference: https://www.ti.com/lit/ds/symlink/cdce706.pdf8 */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		1023#define CDCE706_CLKIN_SOURCE		1124#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			328#define CDCE706_PLL_FVCO		629#define CDCE706_DIVIDER(div)		(13 + (div))30#define CDCE706_CLKOUT(out)		(19 + (out))31 32#define CDCE706_CLKIN_CLOCK_MASK	0x1033#define CDCE706_CLKIN_SOURCE_SHIFT	634#define CDCE706_CLKIN_SOURCE_MASK	0xc035#define CDCE706_CLKIN_SOURCE_LVCMOS	0x4036 37#define CDCE706_PLL_MUX_MASK(pll)	(0x80 >> (pll))38#define CDCE706_PLL_LOW_M_MASK		0xff39#define CDCE706_PLL_LOW_N_MASK		0xff40#define CDCE706_PLL_HI_M_MASK		0x141#define CDCE706_PLL_HI_N_MASK		0x1e42#define CDCE706_PLL_HI_N_SHIFT		143#define CDCE706_PLL_M_MAX		0x1ff44#define CDCE706_PLL_N_MAX		0xfff45#define CDCE706_PLL_FVCO_MASK(pll)	(0x80 >> (pll))46#define CDCE706_PLL_FREQ_MIN		 8000000047#define CDCE706_PLL_FREQ_MAX		30000000048#define CDCE706_PLL_FREQ_HI		18000000049 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	0x7f54#define CDCE706_DIVIDER_DIVIDER_MAX	0x7f55 56#define CDCE706_CLKOUT_DIVIDER_MASK	0x757#define CDCE706_CLKOUT_ENABLE_MASK	0x858 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_OF673static const struct of_device_id cdce706_dt_match[] = {674	{ .compatible = "ti,cdce706" },675	{ },676};677MODULE_DEVICE_TABLE(of, cdce706_dt_match);678#endif679 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");699