1
0

clk-cdce706.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  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. #include <linux/clk.h>
  10. #include <linux/clk-provider.h>
  11. #include <linux/delay.h>
  12. #include <linux/i2c.h>
  13. #include <linux/interrupt.h>
  14. #include <linux/mod_devicetable.h>
  15. #include <linux/module.h>
  16. #include <linux/of.h>
  17. #include <linux/rational.h>
  18. #include <linux/regmap.h>
  19. #include <linux/slab.h>
  20. #define CDCE706_CLKIN_CLOCK 10
  21. #define CDCE706_CLKIN_SOURCE 11
  22. #define CDCE706_PLL_M_LOW(pll) (1 + 3 * (pll))
  23. #define CDCE706_PLL_N_LOW(pll) (2 + 3 * (pll))
  24. #define CDCE706_PLL_HI(pll) (3 + 3 * (pll))
  25. #define CDCE706_PLL_MUX 3
  26. #define CDCE706_PLL_FVCO 6
  27. #define CDCE706_DIVIDER(div) (13 + (div))
  28. #define CDCE706_CLKOUT(out) (19 + (out))
  29. #define CDCE706_CLKIN_CLOCK_MASK 0x10
  30. #define CDCE706_CLKIN_SOURCE_SHIFT 6
  31. #define CDCE706_CLKIN_SOURCE_MASK 0xc0
  32. #define CDCE706_CLKIN_SOURCE_LVCMOS 0x40
  33. #define CDCE706_PLL_MUX_MASK(pll) (0x80 >> (pll))
  34. #define CDCE706_PLL_LOW_M_MASK 0xff
  35. #define CDCE706_PLL_LOW_N_MASK 0xff
  36. #define CDCE706_PLL_HI_M_MASK 0x1
  37. #define CDCE706_PLL_HI_N_MASK 0x1e
  38. #define CDCE706_PLL_HI_N_SHIFT 1
  39. #define CDCE706_PLL_M_MAX 0x1ff
  40. #define CDCE706_PLL_N_MAX 0xfff
  41. #define CDCE706_PLL_FVCO_MASK(pll) (0x80 >> (pll))
  42. #define CDCE706_PLL_FREQ_MIN 80000000
  43. #define CDCE706_PLL_FREQ_MAX 300000000
  44. #define CDCE706_PLL_FREQ_HI 180000000
  45. #define CDCE706_DIVIDER_PLL(div) (9 + (div) - ((div) > 2) - ((div) > 4))
  46. #define CDCE706_DIVIDER_PLL_SHIFT(div) ((div) < 2 ? 5 : 3 * ((div) & 1))
  47. #define CDCE706_DIVIDER_PLL_MASK(div) (0x7 << CDCE706_DIVIDER_PLL_SHIFT(div))
  48. #define CDCE706_DIVIDER_DIVIDER_MASK 0x7f
  49. #define CDCE706_DIVIDER_DIVIDER_MAX 0x7f
  50. #define CDCE706_CLKOUT_DIVIDER_MASK 0x7
  51. #define CDCE706_CLKOUT_ENABLE_MASK 0x8
  52. static const struct regmap_config cdce706_regmap_config = {
  53. .reg_bits = 8,
  54. .val_bits = 8,
  55. .val_format_endian = REGMAP_ENDIAN_NATIVE,
  56. };
  57. #define to_hw_data(phw) (container_of((phw), struct cdce706_hw_data, hw))
  58. struct cdce706_hw_data {
  59. struct cdce706_dev_data *dev_data;
  60. unsigned idx;
  61. unsigned parent;
  62. struct clk_hw hw;
  63. unsigned div;
  64. unsigned mul;
  65. unsigned mux;
  66. };
  67. struct cdce706_dev_data {
  68. struct i2c_client *client;
  69. struct regmap *regmap;
  70. struct clk *clkin_clk[2];
  71. const char *clkin_name[2];
  72. struct cdce706_hw_data clkin[1];
  73. struct cdce706_hw_data pll[3];
  74. struct cdce706_hw_data divider[6];
  75. struct cdce706_hw_data clkout[6];
  76. };
  77. static const char * const cdce706_source_name[] = {
  78. "clk_in0", "clk_in1",
  79. };
  80. static const char * const cdce706_clkin_name[] = {
  81. "clk_in",
  82. };
  83. static const char * const cdce706_pll_name[] = {
  84. "pll1", "pll2", "pll3",
  85. };
  86. static const char * const cdce706_divider_parent_name[] = {
  87. "clk_in", "pll1", "pll2", "pll2", "pll3",
  88. };
  89. static const char *cdce706_divider_name[] = {
  90. "p0", "p1", "p2", "p3", "p4", "p5",
  91. };
  92. static const char * const cdce706_clkout_name[] = {
  93. "clk_out0", "clk_out1", "clk_out2", "clk_out3", "clk_out4", "clk_out5",
  94. };
  95. static int cdce706_reg_read(struct cdce706_dev_data *dev_data, unsigned reg,
  96. unsigned *val)
  97. {
  98. int rc = regmap_read(dev_data->regmap, reg | 0x80, val);
  99. if (rc < 0)
  100. dev_err(&dev_data->client->dev, "error reading reg %u", reg);
  101. return rc;
  102. }
  103. static int cdce706_reg_write(struct cdce706_dev_data *dev_data, unsigned reg,
  104. unsigned val)
  105. {
  106. int rc = regmap_write(dev_data->regmap, reg | 0x80, val);
  107. if (rc < 0)
  108. dev_err(&dev_data->client->dev, "error writing reg %u", reg);
  109. return rc;
  110. }
  111. static int cdce706_reg_update(struct cdce706_dev_data *dev_data, unsigned reg,
  112. unsigned mask, unsigned val)
  113. {
  114. int rc = regmap_update_bits(dev_data->regmap, reg | 0x80, mask, val);
  115. if (rc < 0)
  116. dev_err(&dev_data->client->dev, "error updating reg %u", reg);
  117. return rc;
  118. }
  119. static int cdce706_clkin_set_parent(struct clk_hw *hw, u8 index)
  120. {
  121. struct cdce706_hw_data *hwd = to_hw_data(hw);
  122. hwd->parent = index;
  123. return 0;
  124. }
  125. static u8 cdce706_clkin_get_parent(struct clk_hw *hw)
  126. {
  127. struct cdce706_hw_data *hwd = to_hw_data(hw);
  128. return hwd->parent;
  129. }
  130. static const struct clk_ops cdce706_clkin_ops = {
  131. .determine_rate = clk_hw_determine_rate_no_reparent,
  132. .set_parent = cdce706_clkin_set_parent,
  133. .get_parent = cdce706_clkin_get_parent,
  134. };
  135. static unsigned long cdce706_pll_recalc_rate(struct clk_hw *hw,
  136. unsigned long parent_rate)
  137. {
  138. struct cdce706_hw_data *hwd = to_hw_data(hw);
  139. dev_dbg(&hwd->dev_data->client->dev,
  140. "%s, pll: %d, mux: %d, mul: %u, div: %u\n",
  141. __func__, hwd->idx, hwd->mux, hwd->mul, hwd->div);
  142. if (!hwd->mux) {
  143. if (hwd->div && hwd->mul) {
  144. u64 res = (u64)parent_rate * hwd->mul;
  145. do_div(res, hwd->div);
  146. return res;
  147. }
  148. } else {
  149. if (hwd->div)
  150. return parent_rate / hwd->div;
  151. }
  152. return 0;
  153. }
  154. static int cdce706_pll_determine_rate(struct clk_hw *hw,
  155. struct clk_rate_request *req)
  156. {
  157. struct cdce706_hw_data *hwd = to_hw_data(hw);
  158. unsigned long mul, div;
  159. u64 res;
  160. dev_dbg(&hwd->dev_data->client->dev,
  161. "%s, rate: %lu, parent_rate: %lu\n",
  162. __func__, req->rate, req->best_parent_rate);
  163. rational_best_approximation(req->rate, req->best_parent_rate,
  164. CDCE706_PLL_N_MAX, CDCE706_PLL_M_MAX,
  165. &mul, &div);
  166. hwd->mul = mul;
  167. hwd->div = div;
  168. dev_dbg(&hwd->dev_data->client->dev,
  169. "%s, pll: %d, mul: %lu, div: %lu\n",
  170. __func__, hwd->idx, mul, div);
  171. res = (u64)req->best_parent_rate * hwd->mul;
  172. do_div(res, hwd->div);
  173. req->rate = res;
  174. return 0;
  175. }
  176. static int cdce706_pll_set_rate(struct clk_hw *hw, unsigned long rate,
  177. unsigned long parent_rate)
  178. {
  179. struct cdce706_hw_data *hwd = to_hw_data(hw);
  180. unsigned long mul = hwd->mul, div = hwd->div;
  181. int err;
  182. dev_dbg(&hwd->dev_data->client->dev,
  183. "%s, pll: %d, mul: %lu, div: %lu\n",
  184. __func__, hwd->idx, mul, div);
  185. err = cdce706_reg_update(hwd->dev_data,
  186. CDCE706_PLL_HI(hwd->idx),
  187. CDCE706_PLL_HI_M_MASK | CDCE706_PLL_HI_N_MASK,
  188. ((div >> 8) & CDCE706_PLL_HI_M_MASK) |
  189. ((mul >> (8 - CDCE706_PLL_HI_N_SHIFT)) &
  190. CDCE706_PLL_HI_N_MASK));
  191. if (err < 0)
  192. return err;
  193. err = cdce706_reg_write(hwd->dev_data,
  194. CDCE706_PLL_M_LOW(hwd->idx),
  195. div & CDCE706_PLL_LOW_M_MASK);
  196. if (err < 0)
  197. return err;
  198. err = cdce706_reg_write(hwd->dev_data,
  199. CDCE706_PLL_N_LOW(hwd->idx),
  200. mul & CDCE706_PLL_LOW_N_MASK);
  201. if (err < 0)
  202. return err;
  203. err = cdce706_reg_update(hwd->dev_data,
  204. CDCE706_PLL_FVCO,
  205. CDCE706_PLL_FVCO_MASK(hwd->idx),
  206. rate > CDCE706_PLL_FREQ_HI ?
  207. CDCE706_PLL_FVCO_MASK(hwd->idx) : 0);
  208. return err;
  209. }
  210. static const struct clk_ops cdce706_pll_ops = {
  211. .recalc_rate = cdce706_pll_recalc_rate,
  212. .determine_rate = cdce706_pll_determine_rate,
  213. .set_rate = cdce706_pll_set_rate,
  214. };
  215. static int cdce706_divider_set_parent(struct clk_hw *hw, u8 index)
  216. {
  217. struct cdce706_hw_data *hwd = to_hw_data(hw);
  218. if (hwd->parent == index)
  219. return 0;
  220. hwd->parent = index;
  221. return cdce706_reg_update(hwd->dev_data,
  222. CDCE706_DIVIDER_PLL(hwd->idx),
  223. CDCE706_DIVIDER_PLL_MASK(hwd->idx),
  224. index << CDCE706_DIVIDER_PLL_SHIFT(hwd->idx));
  225. }
  226. static u8 cdce706_divider_get_parent(struct clk_hw *hw)
  227. {
  228. struct cdce706_hw_data *hwd = to_hw_data(hw);
  229. return hwd->parent;
  230. }
  231. static unsigned long cdce706_divider_recalc_rate(struct clk_hw *hw,
  232. unsigned long parent_rate)
  233. {
  234. struct cdce706_hw_data *hwd = to_hw_data(hw);
  235. dev_dbg(&hwd->dev_data->client->dev,
  236. "%s, divider: %d, div: %u\n",
  237. __func__, hwd->idx, hwd->div);
  238. if (hwd->div)
  239. return parent_rate / hwd->div;
  240. return 0;
  241. }
  242. static int cdce706_divider_determine_rate(struct clk_hw *hw,
  243. struct clk_rate_request *req)
  244. {
  245. struct cdce706_hw_data *hwd = to_hw_data(hw);
  246. struct cdce706_dev_data *cdce = hwd->dev_data;
  247. unsigned long rate = req->rate;
  248. unsigned long mul, div;
  249. dev_dbg(&hwd->dev_data->client->dev,
  250. "%s, rate: %lu, parent_rate: %lu\n",
  251. __func__, rate, req->best_parent_rate);
  252. rational_best_approximation(rate, req->best_parent_rate,
  253. 1, CDCE706_DIVIDER_DIVIDER_MAX,
  254. &mul, &div);
  255. if (!mul)
  256. div = CDCE706_DIVIDER_DIVIDER_MAX;
  257. if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
  258. unsigned long best_diff = rate;
  259. unsigned long best_div = 0;
  260. struct clk *gp_clk = cdce->clkin_clk[cdce->clkin[0].parent];
  261. unsigned long gp_rate = gp_clk ? clk_get_rate(gp_clk) : 0;
  262. for (div = CDCE706_PLL_FREQ_MIN / rate; best_diff &&
  263. div <= CDCE706_PLL_FREQ_MAX / rate; ++div) {
  264. unsigned long n, m;
  265. unsigned long diff;
  266. unsigned long div_rate;
  267. u64 div_rate64;
  268. if (rate * div < CDCE706_PLL_FREQ_MIN)
  269. continue;
  270. rational_best_approximation(rate * div, gp_rate,
  271. CDCE706_PLL_N_MAX,
  272. CDCE706_PLL_M_MAX,
  273. &n, &m);
  274. div_rate64 = (u64)gp_rate * n;
  275. do_div(div_rate64, m);
  276. do_div(div_rate64, div);
  277. div_rate = div_rate64;
  278. diff = max(div_rate, rate) - min(div_rate, rate);
  279. if (diff < best_diff) {
  280. best_diff = diff;
  281. best_div = div;
  282. dev_dbg(&hwd->dev_data->client->dev,
  283. "%s, %lu * %lu / %lu / %lu = %lu\n",
  284. __func__, gp_rate, n, m, div, div_rate);
  285. }
  286. }
  287. div = best_div;
  288. dev_dbg(&hwd->dev_data->client->dev,
  289. "%s, altering parent rate: %lu -> %lu\n",
  290. __func__, req->best_parent_rate, rate * div);
  291. req->best_parent_rate = rate * div;
  292. }
  293. hwd->div = div;
  294. dev_dbg(&hwd->dev_data->client->dev,
  295. "%s, divider: %d, div: %lu\n",
  296. __func__, hwd->idx, div);
  297. req->rate = req->best_parent_rate / div;
  298. return 0;
  299. }
  300. static int cdce706_divider_set_rate(struct clk_hw *hw, unsigned long rate,
  301. unsigned long parent_rate)
  302. {
  303. struct cdce706_hw_data *hwd = to_hw_data(hw);
  304. dev_dbg(&hwd->dev_data->client->dev,
  305. "%s, divider: %d, div: %u\n",
  306. __func__, hwd->idx, hwd->div);
  307. return cdce706_reg_update(hwd->dev_data,
  308. CDCE706_DIVIDER(hwd->idx),
  309. CDCE706_DIVIDER_DIVIDER_MASK,
  310. hwd->div);
  311. }
  312. static const struct clk_ops cdce706_divider_ops = {
  313. .set_parent = cdce706_divider_set_parent,
  314. .get_parent = cdce706_divider_get_parent,
  315. .recalc_rate = cdce706_divider_recalc_rate,
  316. .determine_rate = cdce706_divider_determine_rate,
  317. .set_rate = cdce706_divider_set_rate,
  318. };
  319. static int cdce706_clkout_prepare(struct clk_hw *hw)
  320. {
  321. struct cdce706_hw_data *hwd = to_hw_data(hw);
  322. return cdce706_reg_update(hwd->dev_data, CDCE706_CLKOUT(hwd->idx),
  323. CDCE706_CLKOUT_ENABLE_MASK,
  324. CDCE706_CLKOUT_ENABLE_MASK);
  325. }
  326. static void cdce706_clkout_unprepare(struct clk_hw *hw)
  327. {
  328. struct cdce706_hw_data *hwd = to_hw_data(hw);
  329. cdce706_reg_update(hwd->dev_data, CDCE706_CLKOUT(hwd->idx),
  330. CDCE706_CLKOUT_ENABLE_MASK, 0);
  331. }
  332. static int cdce706_clkout_set_parent(struct clk_hw *hw, u8 index)
  333. {
  334. struct cdce706_hw_data *hwd = to_hw_data(hw);
  335. if (hwd->parent == index)
  336. return 0;
  337. hwd->parent = index;
  338. return cdce706_reg_update(hwd->dev_data,
  339. CDCE706_CLKOUT(hwd->idx),
  340. CDCE706_CLKOUT_ENABLE_MASK, index);
  341. }
  342. static u8 cdce706_clkout_get_parent(struct clk_hw *hw)
  343. {
  344. struct cdce706_hw_data *hwd = to_hw_data(hw);
  345. return hwd->parent;
  346. }
  347. static unsigned long cdce706_clkout_recalc_rate(struct clk_hw *hw,
  348. unsigned long parent_rate)
  349. {
  350. return parent_rate;
  351. }
  352. static int cdce706_clkout_determine_rate(struct clk_hw *hw,
  353. struct clk_rate_request *req)
  354. {
  355. req->best_parent_rate = req->rate;
  356. return 0;
  357. }
  358. static int cdce706_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
  359. unsigned long parent_rate)
  360. {
  361. return 0;
  362. }
  363. static const struct clk_ops cdce706_clkout_ops = {
  364. .prepare = cdce706_clkout_prepare,
  365. .unprepare = cdce706_clkout_unprepare,
  366. .set_parent = cdce706_clkout_set_parent,
  367. .get_parent = cdce706_clkout_get_parent,
  368. .recalc_rate = cdce706_clkout_recalc_rate,
  369. .determine_rate = cdce706_clkout_determine_rate,
  370. .set_rate = cdce706_clkout_set_rate,
  371. };
  372. static int cdce706_register_hw(struct cdce706_dev_data *cdce,
  373. struct cdce706_hw_data *hw, unsigned num_hw,
  374. const char * const *clk_names,
  375. struct clk_init_data *init)
  376. {
  377. unsigned i;
  378. int ret;
  379. for (i = 0; i < num_hw; ++i, ++hw) {
  380. init->name = clk_names[i];
  381. hw->dev_data = cdce;
  382. hw->idx = i;
  383. hw->hw.init = init;
  384. ret = devm_clk_hw_register(&cdce->client->dev,
  385. &hw->hw);
  386. if (ret) {
  387. dev_err(&cdce->client->dev, "Failed to register %s\n",
  388. clk_names[i]);
  389. return ret;
  390. }
  391. }
  392. return 0;
  393. }
  394. static int cdce706_register_clkin(struct cdce706_dev_data *cdce)
  395. {
  396. struct clk_init_data init = {
  397. .ops = &cdce706_clkin_ops,
  398. .parent_names = cdce->clkin_name,
  399. .num_parents = ARRAY_SIZE(cdce->clkin_name),
  400. };
  401. unsigned i;
  402. int ret;
  403. unsigned clock, source;
  404. for (i = 0; i < ARRAY_SIZE(cdce->clkin_name); ++i) {
  405. struct clk *parent = devm_clk_get(&cdce->client->dev,
  406. cdce706_source_name[i]);
  407. if (IS_ERR(parent)) {
  408. cdce->clkin_name[i] = cdce706_source_name[i];
  409. } else {
  410. cdce->clkin_name[i] = __clk_get_name(parent);
  411. cdce->clkin_clk[i] = parent;
  412. }
  413. }
  414. ret = cdce706_reg_read(cdce, CDCE706_CLKIN_SOURCE, &source);
  415. if (ret < 0)
  416. return ret;
  417. if ((source & CDCE706_CLKIN_SOURCE_MASK) ==
  418. CDCE706_CLKIN_SOURCE_LVCMOS) {
  419. ret = cdce706_reg_read(cdce, CDCE706_CLKIN_CLOCK, &clock);
  420. if (ret < 0)
  421. return ret;
  422. cdce->clkin[0].parent = !!(clock & CDCE706_CLKIN_CLOCK_MASK);
  423. }
  424. ret = cdce706_register_hw(cdce, cdce->clkin,
  425. ARRAY_SIZE(cdce->clkin),
  426. cdce706_clkin_name, &init);
  427. return ret;
  428. }
  429. static int cdce706_register_plls(struct cdce706_dev_data *cdce)
  430. {
  431. struct clk_init_data init = {
  432. .ops = &cdce706_pll_ops,
  433. .parent_names = cdce706_clkin_name,
  434. .num_parents = ARRAY_SIZE(cdce706_clkin_name),
  435. };
  436. unsigned i;
  437. int ret;
  438. unsigned mux;
  439. ret = cdce706_reg_read(cdce, CDCE706_PLL_MUX, &mux);
  440. if (ret < 0)
  441. return ret;
  442. for (i = 0; i < ARRAY_SIZE(cdce->pll); ++i) {
  443. unsigned m, n, v;
  444. ret = cdce706_reg_read(cdce, CDCE706_PLL_M_LOW(i), &m);
  445. if (ret < 0)
  446. return ret;
  447. ret = cdce706_reg_read(cdce, CDCE706_PLL_N_LOW(i), &n);
  448. if (ret < 0)
  449. return ret;
  450. ret = cdce706_reg_read(cdce, CDCE706_PLL_HI(i), &v);
  451. if (ret < 0)
  452. return ret;
  453. cdce->pll[i].div = m | ((v & CDCE706_PLL_HI_M_MASK) << 8);
  454. cdce->pll[i].mul = n | ((v & CDCE706_PLL_HI_N_MASK) <<
  455. (8 - CDCE706_PLL_HI_N_SHIFT));
  456. cdce->pll[i].mux = mux & CDCE706_PLL_MUX_MASK(i);
  457. dev_dbg(&cdce->client->dev,
  458. "%s: i: %u, div: %u, mul: %u, mux: %d\n", __func__, i,
  459. cdce->pll[i].div, cdce->pll[i].mul, cdce->pll[i].mux);
  460. }
  461. ret = cdce706_register_hw(cdce, cdce->pll,
  462. ARRAY_SIZE(cdce->pll),
  463. cdce706_pll_name, &init);
  464. return ret;
  465. }
  466. static int cdce706_register_dividers(struct cdce706_dev_data *cdce)
  467. {
  468. struct clk_init_data init = {
  469. .ops = &cdce706_divider_ops,
  470. .parent_names = cdce706_divider_parent_name,
  471. .num_parents = ARRAY_SIZE(cdce706_divider_parent_name),
  472. .flags = CLK_SET_RATE_PARENT,
  473. };
  474. unsigned i;
  475. int ret;
  476. for (i = 0; i < ARRAY_SIZE(cdce->divider); ++i) {
  477. unsigned val;
  478. ret = cdce706_reg_read(cdce, CDCE706_DIVIDER_PLL(i), &val);
  479. if (ret < 0)
  480. return ret;
  481. cdce->divider[i].parent =
  482. (val & CDCE706_DIVIDER_PLL_MASK(i)) >>
  483. CDCE706_DIVIDER_PLL_SHIFT(i);
  484. ret = cdce706_reg_read(cdce, CDCE706_DIVIDER(i), &val);
  485. if (ret < 0)
  486. return ret;
  487. cdce->divider[i].div = val & CDCE706_DIVIDER_DIVIDER_MASK;
  488. dev_dbg(&cdce->client->dev,
  489. "%s: i: %u, parent: %u, div: %u\n", __func__, i,
  490. cdce->divider[i].parent, cdce->divider[i].div);
  491. }
  492. ret = cdce706_register_hw(cdce, cdce->divider,
  493. ARRAY_SIZE(cdce->divider),
  494. cdce706_divider_name, &init);
  495. return ret;
  496. }
  497. static int cdce706_register_clkouts(struct cdce706_dev_data *cdce)
  498. {
  499. struct clk_init_data init = {
  500. .ops = &cdce706_clkout_ops,
  501. .parent_names = cdce706_divider_name,
  502. .num_parents = ARRAY_SIZE(cdce706_divider_name),
  503. .flags = CLK_SET_RATE_PARENT,
  504. };
  505. unsigned i;
  506. int ret;
  507. for (i = 0; i < ARRAY_SIZE(cdce->clkout); ++i) {
  508. unsigned val;
  509. ret = cdce706_reg_read(cdce, CDCE706_CLKOUT(i), &val);
  510. if (ret < 0)
  511. return ret;
  512. cdce->clkout[i].parent = val & CDCE706_CLKOUT_DIVIDER_MASK;
  513. dev_dbg(&cdce->client->dev,
  514. "%s: i: %u, parent: %u\n", __func__, i,
  515. cdce->clkout[i].parent);
  516. }
  517. return cdce706_register_hw(cdce, cdce->clkout,
  518. ARRAY_SIZE(cdce->clkout),
  519. cdce706_clkout_name, &init);
  520. }
  521. static struct clk_hw *
  522. of_clk_cdce_get(struct of_phandle_args *clkspec, void *data)
  523. {
  524. struct cdce706_dev_data *cdce = data;
  525. unsigned int idx = clkspec->args[0];
  526. if (idx >= ARRAY_SIZE(cdce->clkout)) {
  527. pr_err("%s: invalid index %u\n", __func__, idx);
  528. return ERR_PTR(-EINVAL);
  529. }
  530. return &cdce->clkout[idx].hw;
  531. }
  532. static int cdce706_probe(struct i2c_client *client)
  533. {
  534. struct i2c_adapter *adapter = client->adapter;
  535. struct cdce706_dev_data *cdce;
  536. int ret;
  537. if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
  538. return -EIO;
  539. cdce = devm_kzalloc(&client->dev, sizeof(*cdce), GFP_KERNEL);
  540. if (!cdce)
  541. return -ENOMEM;
  542. cdce->client = client;
  543. cdce->regmap = devm_regmap_init_i2c(client, &cdce706_regmap_config);
  544. if (IS_ERR(cdce->regmap)) {
  545. dev_err(&client->dev, "Failed to initialize regmap\n");
  546. return -EINVAL;
  547. }
  548. i2c_set_clientdata(client, cdce);
  549. ret = cdce706_register_clkin(cdce);
  550. if (ret < 0)
  551. return ret;
  552. ret = cdce706_register_plls(cdce);
  553. if (ret < 0)
  554. return ret;
  555. ret = cdce706_register_dividers(cdce);
  556. if (ret < 0)
  557. return ret;
  558. ret = cdce706_register_clkouts(cdce);
  559. if (ret < 0)
  560. return ret;
  561. return devm_of_clk_add_hw_provider(&client->dev, of_clk_cdce_get,
  562. cdce);
  563. }
  564. #ifdef CONFIG_OF
  565. static const struct of_device_id cdce706_dt_match[] = {
  566. { .compatible = "ti,cdce706" },
  567. { },
  568. };
  569. MODULE_DEVICE_TABLE(of, cdce706_dt_match);
  570. #endif
  571. static const struct i2c_device_id cdce706_id[] = {
  572. { "cdce706" },
  573. { }
  574. };
  575. MODULE_DEVICE_TABLE(i2c, cdce706_id);
  576. static struct i2c_driver cdce706_i2c_driver = {
  577. .driver = {
  578. .name = "cdce706",
  579. .of_match_table = of_match_ptr(cdce706_dt_match),
  580. },
  581. .probe = cdce706_probe,
  582. .id_table = cdce706_id,
  583. };
  584. module_i2c_driver(cdce706_i2c_driver);
  585. MODULE_AUTHOR("Max Filippov <jcmvbkbc@gmail.com>");
  586. MODULE_DESCRIPTION("TI CDCE 706 clock synthesizer driver");
  587. MODULE_LICENSE("GPL");