clk-wm831x.c 9.4 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 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. usleep_range(2000, 2000);
  86. return ret;
  87. }
  88. static void wm831x_fll_unprepare(struct clk_hw *hw)
  89. {
  90. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  91. fll_hw);
  92. struct wm831x *wm831x = clkdata->wm831x;
  93. int ret;
  94. ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_1, WM831X_FLL_ENA, 0);
  95. if (ret != 0)
  96. dev_crit(wm831x->dev, "Failed to disable FLL: %d\n", ret);
  97. }
  98. static unsigned long wm831x_fll_recalc_rate(struct clk_hw *hw,
  99. unsigned long parent_rate)
  100. {
  101. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  102. fll_hw);
  103. struct wm831x *wm831x = clkdata->wm831x;
  104. int ret;
  105. ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
  106. if (ret < 0) {
  107. dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
  108. ret);
  109. return 0;
  110. }
  111. if (ret & WM831X_FLL_AUTO)
  112. return wm831x_fll_auto_rates[ret & WM831X_FLL_AUTO_FREQ_MASK];
  113. dev_err(wm831x->dev, "FLL only supported in AUTO mode\n");
  114. return 0;
  115. }
  116. static long wm831x_fll_round_rate(struct clk_hw *hw, unsigned long rate,
  117. unsigned long *unused)
  118. {
  119. int best = 0;
  120. int i;
  121. for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++)
  122. if (abs(wm831x_fll_auto_rates[i] - rate) <
  123. abs(wm831x_fll_auto_rates[best] - rate))
  124. best = i;
  125. return wm831x_fll_auto_rates[best];
  126. }
  127. static int wm831x_fll_set_rate(struct clk_hw *hw, unsigned long rate,
  128. unsigned long parent_rate)
  129. {
  130. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  131. fll_hw);
  132. struct wm831x *wm831x = clkdata->wm831x;
  133. int i;
  134. for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++)
  135. if (wm831x_fll_auto_rates[i] == rate)
  136. break;
  137. if (i == ARRAY_SIZE(wm831x_fll_auto_rates))
  138. return -EINVAL;
  139. if (wm831x_fll_is_prepared(hw))
  140. return -EPERM;
  141. return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_2,
  142. WM831X_FLL_AUTO_FREQ_MASK, i);
  143. }
  144. static const char *wm831x_fll_parents[] = {
  145. "xtal",
  146. "clkin",
  147. };
  148. static u8 wm831x_fll_get_parent(struct clk_hw *hw)
  149. {
  150. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  151. fll_hw);
  152. struct wm831x *wm831x = clkdata->wm831x;
  153. int ret;
  154. /* AUTO mode is always clocked from the crystal */
  155. ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
  156. if (ret < 0) {
  157. dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
  158. ret);
  159. return 0;
  160. }
  161. if (ret & WM831X_FLL_AUTO)
  162. return 0;
  163. ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_5);
  164. if (ret < 0) {
  165. dev_err(wm831x->dev, "Unable to read FLL_CONTROL_5: %d\n",
  166. ret);
  167. return 0;
  168. }
  169. switch (ret & WM831X_FLL_CLK_SRC_MASK) {
  170. case 0:
  171. return 0;
  172. case 1:
  173. return 1;
  174. default:
  175. dev_err(wm831x->dev, "Unsupported FLL clock source %d\n",
  176. ret & WM831X_FLL_CLK_SRC_MASK);
  177. return 0;
  178. }
  179. }
  180. static const struct clk_ops wm831x_fll_ops = {
  181. .is_prepared = wm831x_fll_is_prepared,
  182. .prepare = wm831x_fll_prepare,
  183. .unprepare = wm831x_fll_unprepare,
  184. .round_rate = wm831x_fll_round_rate,
  185. .recalc_rate = wm831x_fll_recalc_rate,
  186. .set_rate = wm831x_fll_set_rate,
  187. .get_parent = wm831x_fll_get_parent,
  188. };
  189. static struct clk_init_data wm831x_fll_init = {
  190. .name = "fll",
  191. .ops = &wm831x_fll_ops,
  192. .parent_names = wm831x_fll_parents,
  193. .num_parents = ARRAY_SIZE(wm831x_fll_parents),
  194. .flags = CLK_SET_RATE_GATE,
  195. };
  196. static int wm831x_clkout_is_prepared(struct clk_hw *hw)
  197. {
  198. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  199. clkout_hw);
  200. struct wm831x *wm831x = clkdata->wm831x;
  201. int ret;
  202. ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1);
  203. if (ret < 0) {
  204. dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
  205. ret);
  206. return false;
  207. }
  208. return (ret & WM831X_CLKOUT_ENA) != 0;
  209. }
  210. static int wm831x_clkout_prepare(struct clk_hw *hw)
  211. {
  212. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  213. clkout_hw);
  214. struct wm831x *wm831x = clkdata->wm831x;
  215. int ret;
  216. ret = wm831x_reg_unlock(wm831x);
  217. if (ret != 0) {
  218. dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);
  219. return ret;
  220. }
  221. ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
  222. WM831X_CLKOUT_ENA, WM831X_CLKOUT_ENA);
  223. if (ret != 0)
  224. dev_crit(wm831x->dev, "Failed to enable CLKOUT: %d\n", ret);
  225. wm831x_reg_lock(wm831x);
  226. return ret;
  227. }
  228. static void wm831x_clkout_unprepare(struct clk_hw *hw)
  229. {
  230. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  231. clkout_hw);
  232. struct wm831x *wm831x = clkdata->wm831x;
  233. int ret;
  234. ret = wm831x_reg_unlock(wm831x);
  235. if (ret != 0) {
  236. dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);
  237. return;
  238. }
  239. ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
  240. WM831X_CLKOUT_ENA, 0);
  241. if (ret != 0)
  242. dev_crit(wm831x->dev, "Failed to disable CLKOUT: %d\n", ret);
  243. wm831x_reg_lock(wm831x);
  244. }
  245. static const char *wm831x_clkout_parents[] = {
  246. "fll",
  247. "xtal",
  248. };
  249. static u8 wm831x_clkout_get_parent(struct clk_hw *hw)
  250. {
  251. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  252. clkout_hw);
  253. struct wm831x *wm831x = clkdata->wm831x;
  254. int ret;
  255. ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1);
  256. if (ret < 0) {
  257. dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
  258. ret);
  259. return 0;
  260. }
  261. if (ret & WM831X_CLKOUT_SRC)
  262. return 1;
  263. else
  264. return 0;
  265. }
  266. static int wm831x_clkout_set_parent(struct clk_hw *hw, u8 parent)
  267. {
  268. struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  269. clkout_hw);
  270. struct wm831x *wm831x = clkdata->wm831x;
  271. return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
  272. WM831X_CLKOUT_SRC,
  273. parent << WM831X_CLKOUT_SRC_SHIFT);
  274. }
  275. static const struct clk_ops wm831x_clkout_ops = {
  276. .is_prepared = wm831x_clkout_is_prepared,
  277. .prepare = wm831x_clkout_prepare,
  278. .unprepare = wm831x_clkout_unprepare,
  279. .get_parent = wm831x_clkout_get_parent,
  280. .set_parent = wm831x_clkout_set_parent,
  281. };
  282. static struct clk_init_data wm831x_clkout_init = {
  283. .name = "clkout",
  284. .ops = &wm831x_clkout_ops,
  285. .parent_names = wm831x_clkout_parents,
  286. .num_parents = ARRAY_SIZE(wm831x_clkout_parents),
  287. .flags = CLK_SET_RATE_PARENT,
  288. };
  289. static int wm831x_clk_probe(struct platform_device *pdev)
  290. {
  291. struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
  292. struct wm831x_clk *clkdata;
  293. int ret;
  294. clkdata = devm_kzalloc(&pdev->dev, sizeof(*clkdata), GFP_KERNEL);
  295. if (!clkdata)
  296. return -ENOMEM;
  297. clkdata->wm831x = wm831x;
  298. /* XTAL_ENA can only be set via OTP/InstantConfig so just read once */
  299. ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
  300. if (ret < 0) {
  301. dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
  302. ret);
  303. return ret;
  304. }
  305. clkdata->xtal_ena = ret & WM831X_XTAL_ENA;
  306. clkdata->xtal_hw.init = &wm831x_xtal_init;
  307. ret = devm_clk_hw_register(&pdev->dev, &clkdata->xtal_hw);
  308. if (ret)
  309. return ret;
  310. clkdata->fll_hw.init = &wm831x_fll_init;
  311. ret = devm_clk_hw_register(&pdev->dev, &clkdata->fll_hw);
  312. if (ret)
  313. return ret;
  314. clkdata->clkout_hw.init = &wm831x_clkout_init;
  315. ret = devm_clk_hw_register(&pdev->dev, &clkdata->clkout_hw);
  316. if (ret)
  317. return ret;
  318. platform_set_drvdata(pdev, clkdata);
  319. return 0;
  320. }
  321. static struct platform_driver wm831x_clk_driver = {
  322. .probe = wm831x_clk_probe,
  323. .driver = {
  324. .name = "wm831x-clk",
  325. },
  326. };
  327. module_platform_driver(wm831x_clk_driver);
  328. /* Module information */
  329. MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
  330. MODULE_DESCRIPTION("WM831x clock driver");
  331. MODULE_LICENSE("GPL");
  332. MODULE_ALIAS("platform:wm831x-clk");