clk-wm831x.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. /*
  2. * WM831x clock control
  3. *
  4. * Copyright 2011-2 Wolfson Microelectronics PLC.
  5. *
  6. * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation; either version 2 of the License, or (at your
  11. * option) any later version.
  12. *
  13. */
  14. #include <linux/clk-provider.h>
  15. #include <linux/delay.h>
  16. #include <linux/module.h>
  17. #include <linux/slab.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/mfd/wm831x/core.h>
  20. struct wm831x_clk {
  21. struct wm831x *wm831x;
  22. struct clk_hw xtal_hw;
  23. struct clk_hw fll_hw;
  24. struct clk_hw clkout_hw;
  25. bool xtal_ena;
  26. };
  27. static int wm831x_xtal_is_prepared(struct clk_hw *hw)
  28. {
  29. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  30. xtal_hw);
  31. return clkdata->xtal_ena;
  32. }
  33. static unsigned long wm831x_xtal_recalc_rate(struct clk_hw *hw,
  34. unsigned long parent_rate)
  35. {
  36. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  37. xtal_hw);
  38. if (clkdata->xtal_ena)
  39. return 32768;
  40. else
  41. return 0;
  42. }
  43. static const struct clk_ops wm831x_xtal_ops = {
  44. .is_prepared = wm831x_xtal_is_prepared,
  45. .recalc_rate = wm831x_xtal_recalc_rate,
  46. };
  47. static const struct clk_init_data wm831x_xtal_init = {
  48. .name = "xtal",
  49. .ops = &wm831x_xtal_ops,
  50. };
  51. static const unsigned long wm831x_fll_auto_rates[] = {
  52. 2048000,
  53. 11289600,
  54. 12000000,
  55. 12288000,
  56. 19200000,
  57. 22579600,
  58. 24000000,
  59. 24576000,
  60. };
  61. static int wm831x_fll_is_prepared(struct clk_hw *hw)
  62. {
  63. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  64. fll_hw);
  65. struct wm831x *wm831x = clkdata->wm831x;
  66. int ret;
  67. ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_1);
  68. if (ret < 0) {
  69. dev_err(wm831x->dev, "Unable to read FLL_CONTROL_1: %d\n",
  70. ret);
  71. return true;
  72. }
  73. return (ret & WM831X_FLL_ENA) != 0;
  74. }
  75. static int wm831x_fll_prepare(struct clk_hw *hw)
  76. {
  77. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  78. fll_hw);
  79. struct wm831x *wm831x = clkdata->wm831x;
  80. int ret;
  81. ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_1,
  82. WM831X_FLL_ENA, WM831X_FLL_ENA);
  83. if (ret != 0)
  84. dev_crit(wm831x->dev, "Failed to enable FLL: %d\n", ret);
  85. /* wait 2-3 ms for new frequency taking effect */
  86. usleep_range(2000, 3000);
  87. return ret;
  88. }
  89. static void wm831x_fll_unprepare(struct clk_hw *hw)
  90. {
  91. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  92. fll_hw);
  93. struct wm831x *wm831x = clkdata->wm831x;
  94. int ret;
  95. ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_1, WM831X_FLL_ENA, 0);
  96. if (ret != 0)
  97. dev_crit(wm831x->dev, "Failed to disable FLL: %d\n", ret);
  98. }
  99. static unsigned long wm831x_fll_recalc_rate(struct clk_hw *hw,
  100. unsigned long parent_rate)
  101. {
  102. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  103. fll_hw);
  104. struct wm831x *wm831x = clkdata->wm831x;
  105. int ret;
  106. ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
  107. if (ret < 0) {
  108. dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
  109. ret);
  110. return 0;
  111. }
  112. if (ret & WM831X_FLL_AUTO)
  113. return wm831x_fll_auto_rates[ret & WM831X_FLL_AUTO_FREQ_MASK];
  114. dev_err(wm831x->dev, "FLL only supported in AUTO mode\n");
  115. return 0;
  116. }
  117. static long wm831x_fll_round_rate(struct clk_hw *hw, unsigned long rate,
  118. unsigned long *unused)
  119. {
  120. int best = 0;
  121. int i;
  122. for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++)
  123. if (abs(wm831x_fll_auto_rates[i] - rate) <
  124. abs(wm831x_fll_auto_rates[best] - rate))
  125. best = i;
  126. return wm831x_fll_auto_rates[best];
  127. }
  128. static int wm831x_fll_set_rate(struct clk_hw *hw, unsigned long rate,
  129. unsigned long parent_rate)
  130. {
  131. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  132. fll_hw);
  133. struct wm831x *wm831x = clkdata->wm831x;
  134. int i;
  135. for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++)
  136. if (wm831x_fll_auto_rates[i] == rate)
  137. break;
  138. if (i == ARRAY_SIZE(wm831x_fll_auto_rates))
  139. return -EINVAL;
  140. if (wm831x_fll_is_prepared(hw))
  141. return -EPERM;
  142. return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_2,
  143. WM831X_FLL_AUTO_FREQ_MASK, i);
  144. }
  145. static const char *wm831x_fll_parents[] = {
  146. "xtal",
  147. "clkin",
  148. };
  149. static u8 wm831x_fll_get_parent(struct clk_hw *hw)
  150. {
  151. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  152. fll_hw);
  153. struct wm831x *wm831x = clkdata->wm831x;
  154. int ret;
  155. /* AUTO mode is always clocked from the crystal */
  156. ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
  157. if (ret < 0) {
  158. dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
  159. ret);
  160. return 0;
  161. }
  162. if (ret & WM831X_FLL_AUTO)
  163. return 0;
  164. ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_5);
  165. if (ret < 0) {
  166. dev_err(wm831x->dev, "Unable to read FLL_CONTROL_5: %d\n",
  167. ret);
  168. return 0;
  169. }
  170. switch (ret & WM831X_FLL_CLK_SRC_MASK) {
  171. case 0:
  172. return 0;
  173. case 1:
  174. return 1;
  175. default:
  176. dev_err(wm831x->dev, "Unsupported FLL clock source %d\n",
  177. ret & WM831X_FLL_CLK_SRC_MASK);
  178. return 0;
  179. }
  180. }
  181. static const struct clk_ops wm831x_fll_ops = {
  182. .is_prepared = wm831x_fll_is_prepared,
  183. .prepare = wm831x_fll_prepare,
  184. .unprepare = wm831x_fll_unprepare,
  185. .round_rate = wm831x_fll_round_rate,
  186. .recalc_rate = wm831x_fll_recalc_rate,
  187. .set_rate = wm831x_fll_set_rate,
  188. .get_parent = wm831x_fll_get_parent,
  189. };
  190. static const struct clk_init_data wm831x_fll_init = {
  191. .name = "fll",
  192. .ops = &wm831x_fll_ops,
  193. .parent_names = wm831x_fll_parents,
  194. .num_parents = ARRAY_SIZE(wm831x_fll_parents),
  195. .flags = CLK_SET_RATE_GATE,
  196. };
  197. static int wm831x_clkout_is_prepared(struct clk_hw *hw)
  198. {
  199. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  200. clkout_hw);
  201. struct wm831x *wm831x = clkdata->wm831x;
  202. int ret;
  203. ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1);
  204. if (ret < 0) {
  205. dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
  206. ret);
  207. return false;
  208. }
  209. return (ret & WM831X_CLKOUT_ENA) != 0;
  210. }
  211. static int wm831x_clkout_prepare(struct clk_hw *hw)
  212. {
  213. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  214. clkout_hw);
  215. struct wm831x *wm831x = clkdata->wm831x;
  216. int ret;
  217. ret = wm831x_reg_unlock(wm831x);
  218. if (ret != 0) {
  219. dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);
  220. return ret;
  221. }
  222. ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
  223. WM831X_CLKOUT_ENA, WM831X_CLKOUT_ENA);
  224. if (ret != 0)
  225. dev_crit(wm831x->dev, "Failed to enable CLKOUT: %d\n", ret);
  226. wm831x_reg_lock(wm831x);
  227. return ret;
  228. }
  229. static void wm831x_clkout_unprepare(struct clk_hw *hw)
  230. {
  231. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  232. clkout_hw);
  233. struct wm831x *wm831x = clkdata->wm831x;
  234. int ret;
  235. ret = wm831x_reg_unlock(wm831x);
  236. if (ret != 0) {
  237. dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);
  238. return;
  239. }
  240. ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
  241. WM831X_CLKOUT_ENA, 0);
  242. if (ret != 0)
  243. dev_crit(wm831x->dev, "Failed to disable CLKOUT: %d\n", ret);
  244. wm831x_reg_lock(wm831x);
  245. }
  246. static const char *wm831x_clkout_parents[] = {
  247. "fll",
  248. "xtal",
  249. };
  250. static u8 wm831x_clkout_get_parent(struct clk_hw *hw)
  251. {
  252. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  253. clkout_hw);
  254. struct wm831x *wm831x = clkdata->wm831x;
  255. int ret;
  256. ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1);
  257. if (ret < 0) {
  258. dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
  259. ret);
  260. return 0;
  261. }
  262. if (ret & WM831X_CLKOUT_SRC)
  263. return 1;
  264. else
  265. return 0;
  266. }
  267. static int wm831x_clkout_set_parent(struct clk_hw *hw, u8 parent)
  268. {
  269. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  270. clkout_hw);
  271. struct wm831x *wm831x = clkdata->wm831x;
  272. return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
  273. WM831X_CLKOUT_SRC,
  274. parent << WM831X_CLKOUT_SRC_SHIFT);
  275. }
  276. static const struct clk_ops wm831x_clkout_ops = {
  277. .is_prepared = wm831x_clkout_is_prepared,
  278. .prepare = wm831x_clkout_prepare,
  279. .unprepare = wm831x_clkout_unprepare,
  280. .get_parent = wm831x_clkout_get_parent,
  281. .set_parent = wm831x_clkout_set_parent,
  282. };
  283. static const struct clk_init_data wm831x_clkout_init = {
  284. .name = "clkout",
  285. .ops = &wm831x_clkout_ops,
  286. .parent_names = wm831x_clkout_parents,
  287. .num_parents = ARRAY_SIZE(wm831x_clkout_parents),
  288. .flags = CLK_SET_RATE_PARENT,
  289. };
  290. static int wm831x_clk_probe(struct platform_device *pdev)
  291. {
  292. struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
  293. struct wm831x_clk *clkdata;
  294. int ret;
  295. clkdata = devm_kzalloc(&pdev->dev, sizeof(*clkdata), GFP_KERNEL);
  296. if (!clkdata)
  297. return -ENOMEM;
  298. clkdata->wm831x = wm831x;
  299. /* XTAL_ENA can only be set via OTP/InstantConfig so just read once */
  300. ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
  301. if (ret < 0) {
  302. dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
  303. ret);
  304. return ret;
  305. }
  306. clkdata->xtal_ena = ret & WM831X_XTAL_ENA;
  307. clkdata->xtal_hw.init = &wm831x_xtal_init;
  308. ret = devm_clk_hw_register(&pdev->dev, &clkdata->xtal_hw);
  309. if (ret)
  310. return ret;
  311. clkdata->fll_hw.init = &wm831x_fll_init;
  312. ret = devm_clk_hw_register(&pdev->dev, &clkdata->fll_hw);
  313. if (ret)
  314. return ret;
  315. clkdata->clkout_hw.init = &wm831x_clkout_init;
  316. ret = devm_clk_hw_register(&pdev->dev, &clkdata->clkout_hw);
  317. if (ret)
  318. return ret;
  319. platform_set_drvdata(pdev, clkdata);
  320. return 0;
  321. }
  322. static struct platform_driver wm831x_clk_driver = {
  323. .probe = wm831x_clk_probe,
  324. .driver = {
  325. .name = "wm831x-clk",
  326. },
  327. };
  328. module_platform_driver(wm831x_clk_driver);
  329. /* Module information */
  330. MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
  331. MODULE_DESCRIPTION("WM831x clock driver");
  332. MODULE_LICENSE("GPL");
  333. MODULE_ALIAS("platform:wm831x-clk");