clk-sr.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /*
  2. * Copyright 2017 Broadcom
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License, version 2, as
  6. * published by the Free Software Foundation (the "GPL").
  7. *
  8. * This program is distributed in the hope that it will be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. * General Public License version 2 (GPLv2) for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * version 2 (GPLv2) along with this source code.
  15. */
  16. #include <linux/err.h>
  17. #include <linux/clk-provider.h>
  18. #include <linux/of_device.h>
  19. #include <linux/platform_device.h>
  20. #include <dt-bindings/clock/bcm-sr.h>
  21. #include "clk-iproc.h"
  22. #define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }
  23. #define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
  24. .pwr_shift = ps, .iso_shift = is }
  25. #define SW_CTRL_VAL(o, s) { .offset = o, .shift = s, }
  26. #define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \
  27. .p_reset_shift = prs }
  28. #define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, \
  29. .ki_shift = kis, .ki_width = kiw, .kp_shift = kps, .kp_width = kpw, \
  30. .ka_shift = kas, .ka_width = kaw }
  31. #define VCO_CTRL_VAL(uo, lo) { .u_offset = uo, .l_offset = lo }
  32. #define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \
  33. .hold_shift = hs, .bypass_shift = bs }
  34. static const struct iproc_pll_ctrl sr_genpll0 = {
  35. .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
  36. IPROC_CLK_PLL_NEEDS_SW_CFG,
  37. .aon = AON_VAL(0x0, 5, 1, 0),
  38. .reset = RESET_VAL(0x0, 12, 11),
  39. .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
  40. .sw_ctrl = SW_CTRL_VAL(0x10, 31),
  41. .ndiv_int = REG_VAL(0x10, 20, 10),
  42. .ndiv_frac = REG_VAL(0x10, 0, 20),
  43. .pdiv = REG_VAL(0x14, 0, 4),
  44. .status = REG_VAL(0x30, 12, 1),
  45. };
  46. static const struct iproc_clk_ctrl sr_genpll0_clk[] = {
  47. [BCM_SR_GENPLL0_SATA_CLK] = {
  48. .channel = BCM_SR_GENPLL0_SATA_CLK,
  49. .flags = IPROC_CLK_AON,
  50. .enable = ENABLE_VAL(0x4, 6, 0, 12),
  51. .mdiv = REG_VAL(0x18, 0, 9),
  52. },
  53. [BCM_SR_GENPLL0_SCR_CLK] = {
  54. .channel = BCM_SR_GENPLL0_SCR_CLK,
  55. .flags = IPROC_CLK_AON,
  56. .enable = ENABLE_VAL(0x4, 7, 1, 13),
  57. .mdiv = REG_VAL(0x18, 10, 9),
  58. },
  59. [BCM_SR_GENPLL0_250M_CLK] = {
  60. .channel = BCM_SR_GENPLL0_250M_CLK,
  61. .flags = IPROC_CLK_AON,
  62. .enable = ENABLE_VAL(0x4, 8, 2, 14),
  63. .mdiv = REG_VAL(0x18, 20, 9),
  64. },
  65. [BCM_SR_GENPLL0_PCIE_AXI_CLK] = {
  66. .channel = BCM_SR_GENPLL0_PCIE_AXI_CLK,
  67. .flags = IPROC_CLK_AON,
  68. .enable = ENABLE_VAL(0x4, 9, 3, 15),
  69. .mdiv = REG_VAL(0x1c, 0, 9),
  70. },
  71. [BCM_SR_GENPLL0_PAXC_AXI_X2_CLK] = {
  72. .channel = BCM_SR_GENPLL0_PAXC_AXI_X2_CLK,
  73. .flags = IPROC_CLK_AON,
  74. .enable = ENABLE_VAL(0x4, 10, 4, 16),
  75. .mdiv = REG_VAL(0x1c, 10, 9),
  76. },
  77. [BCM_SR_GENPLL0_PAXC_AXI_CLK] = {
  78. .channel = BCM_SR_GENPLL0_PAXC_AXI_CLK,
  79. .flags = IPROC_CLK_AON,
  80. .enable = ENABLE_VAL(0x4, 11, 5, 17),
  81. .mdiv = REG_VAL(0x1c, 20, 9),
  82. },
  83. };
  84. static int sr_genpll0_clk_init(struct platform_device *pdev)
  85. {
  86. iproc_pll_clk_setup(pdev->dev.of_node,
  87. &sr_genpll0, NULL, 0, sr_genpll0_clk,
  88. ARRAY_SIZE(sr_genpll0_clk));
  89. return 0;
  90. }
  91. static const struct iproc_pll_ctrl sr_genpll3 = {
  92. .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
  93. IPROC_CLK_PLL_NEEDS_SW_CFG,
  94. .aon = AON_VAL(0x0, 1, 19, 18),
  95. .reset = RESET_VAL(0x0, 12, 11),
  96. .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
  97. .sw_ctrl = SW_CTRL_VAL(0x10, 31),
  98. .ndiv_int = REG_VAL(0x10, 20, 10),
  99. .ndiv_frac = REG_VAL(0x10, 0, 20),
  100. .pdiv = REG_VAL(0x14, 0, 4),
  101. .status = REG_VAL(0x30, 12, 1),
  102. };
  103. static const struct iproc_clk_ctrl sr_genpll3_clk[] = {
  104. [BCM_SR_GENPLL3_HSLS_CLK] = {
  105. .channel = BCM_SR_GENPLL3_HSLS_CLK,
  106. .flags = IPROC_CLK_AON,
  107. .enable = ENABLE_VAL(0x4, 6, 0, 12),
  108. .mdiv = REG_VAL(0x18, 0, 9),
  109. },
  110. [BCM_SR_GENPLL3_SDIO_CLK] = {
  111. .channel = BCM_SR_GENPLL3_SDIO_CLK,
  112. .flags = IPROC_CLK_AON,
  113. .enable = ENABLE_VAL(0x4, 7, 1, 13),
  114. .mdiv = REG_VAL(0x18, 10, 9),
  115. },
  116. };
  117. static void sr_genpll3_clk_init(struct device_node *node)
  118. {
  119. iproc_pll_clk_setup(node, &sr_genpll3, NULL, 0, sr_genpll3_clk,
  120. ARRAY_SIZE(sr_genpll3_clk));
  121. }
  122. CLK_OF_DECLARE(sr_genpll3_clk, "brcm,sr-genpll3", sr_genpll3_clk_init);
  123. static const struct iproc_pll_ctrl sr_genpll4 = {
  124. .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
  125. IPROC_CLK_PLL_NEEDS_SW_CFG,
  126. .aon = AON_VAL(0x0, 1, 25, 24),
  127. .reset = RESET_VAL(0x0, 12, 11),
  128. .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
  129. .sw_ctrl = SW_CTRL_VAL(0x10, 31),
  130. .ndiv_int = REG_VAL(0x10, 20, 10),
  131. .ndiv_frac = REG_VAL(0x10, 0, 20),
  132. .pdiv = REG_VAL(0x14, 0, 4),
  133. .status = REG_VAL(0x30, 12, 1),
  134. };
  135. static const struct iproc_clk_ctrl sr_genpll4_clk[] = {
  136. [BCM_SR_GENPLL4_CCN_CLK] = {
  137. .channel = BCM_SR_GENPLL4_CCN_CLK,
  138. .flags = IPROC_CLK_AON,
  139. .enable = ENABLE_VAL(0x4, 6, 0, 12),
  140. .mdiv = REG_VAL(0x18, 0, 9),
  141. },
  142. };
  143. static int sr_genpll4_clk_init(struct platform_device *pdev)
  144. {
  145. iproc_pll_clk_setup(pdev->dev.of_node,
  146. &sr_genpll4, NULL, 0, sr_genpll4_clk,
  147. ARRAY_SIZE(sr_genpll4_clk));
  148. return 0;
  149. }
  150. static const struct iproc_pll_ctrl sr_genpll5 = {
  151. .flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
  152. IPROC_CLK_PLL_NEEDS_SW_CFG,
  153. .aon = AON_VAL(0x0, 1, 1, 0),
  154. .reset = RESET_VAL(0x0, 12, 11),
  155. .dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
  156. .sw_ctrl = SW_CTRL_VAL(0x10, 31),
  157. .ndiv_int = REG_VAL(0x10, 20, 10),
  158. .ndiv_frac = REG_VAL(0x10, 0, 20),
  159. .pdiv = REG_VAL(0x14, 0, 4),
  160. .status = REG_VAL(0x30, 12, 1),
  161. };
  162. static const struct iproc_clk_ctrl sr_genpll5_clk[] = {
  163. [BCM_SR_GENPLL5_FS_CLK] = {
  164. .channel = BCM_SR_GENPLL5_FS_CLK,
  165. .flags = IPROC_CLK_AON,
  166. .enable = ENABLE_VAL(0x4, 6, 0, 12),
  167. .mdiv = REG_VAL(0x18, 0, 9),
  168. },
  169. [BCM_SR_GENPLL5_SPU_CLK] = {
  170. .channel = BCM_SR_GENPLL5_SPU_CLK,
  171. .flags = IPROC_CLK_AON,
  172. .enable = ENABLE_VAL(0x4, 6, 0, 12),
  173. .mdiv = REG_VAL(0x18, 10, 9),
  174. },
  175. };
  176. static int sr_genpll5_clk_init(struct platform_device *pdev)
  177. {
  178. iproc_pll_clk_setup(pdev->dev.of_node,
  179. &sr_genpll5, NULL, 0, sr_genpll5_clk,
  180. ARRAY_SIZE(sr_genpll5_clk));
  181. return 0;
  182. }
  183. static const struct iproc_pll_ctrl sr_lcpll0 = {
  184. .flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
  185. .aon = AON_VAL(0x0, 2, 19, 18),
  186. .reset = RESET_VAL(0x0, 31, 30),
  187. .sw_ctrl = SW_CTRL_VAL(0x4, 31),
  188. .ndiv_int = REG_VAL(0x4, 16, 10),
  189. .pdiv = REG_VAL(0x4, 26, 4),
  190. .status = REG_VAL(0x38, 12, 1),
  191. };
  192. static const struct iproc_clk_ctrl sr_lcpll0_clk[] = {
  193. [BCM_SR_LCPLL0_SATA_REF_CLK] = {
  194. .channel = BCM_SR_LCPLL0_SATA_REF_CLK,
  195. .flags = IPROC_CLK_AON,
  196. .enable = ENABLE_VAL(0x0, 7, 1, 13),
  197. .mdiv = REG_VAL(0x14, 0, 9),
  198. },
  199. [BCM_SR_LCPLL0_USB_REF_CLK] = {
  200. .channel = BCM_SR_LCPLL0_USB_REF_CLK,
  201. .flags = IPROC_CLK_AON,
  202. .enable = ENABLE_VAL(0x0, 8, 2, 14),
  203. .mdiv = REG_VAL(0x14, 10, 9),
  204. },
  205. [BCM_SR_LCPLL0_SATA_REFPN_CLK] = {
  206. .channel = BCM_SR_LCPLL0_SATA_REFPN_CLK,
  207. .flags = IPROC_CLK_AON,
  208. .enable = ENABLE_VAL(0x0, 9, 3, 15),
  209. .mdiv = REG_VAL(0x14, 20, 9),
  210. },
  211. };
  212. static int sr_lcpll0_clk_init(struct platform_device *pdev)
  213. {
  214. iproc_pll_clk_setup(pdev->dev.of_node,
  215. &sr_lcpll0, NULL, 0, sr_lcpll0_clk,
  216. ARRAY_SIZE(sr_lcpll0_clk));
  217. return 0;
  218. }
  219. static const struct iproc_pll_ctrl sr_lcpll1 = {
  220. .flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
  221. .aon = AON_VAL(0x0, 2, 22, 21),
  222. .reset = RESET_VAL(0x0, 31, 30),
  223. .sw_ctrl = SW_CTRL_VAL(0x4, 31),
  224. .ndiv_int = REG_VAL(0x4, 16, 10),
  225. .pdiv = REG_VAL(0x4, 26, 4),
  226. .status = REG_VAL(0x38, 12, 1),
  227. };
  228. static const struct iproc_clk_ctrl sr_lcpll1_clk[] = {
  229. [BCM_SR_LCPLL1_WAN_CLK] = {
  230. .channel = BCM_SR_LCPLL1_WAN_CLK,
  231. .flags = IPROC_CLK_AON,
  232. .enable = ENABLE_VAL(0x0, 7, 1, 13),
  233. .mdiv = REG_VAL(0x14, 0, 9),
  234. },
  235. };
  236. static int sr_lcpll1_clk_init(struct platform_device *pdev)
  237. {
  238. iproc_pll_clk_setup(pdev->dev.of_node,
  239. &sr_lcpll1, NULL, 0, sr_lcpll1_clk,
  240. ARRAY_SIZE(sr_lcpll1_clk));
  241. return 0;
  242. }
  243. static const struct iproc_pll_ctrl sr_lcpll_pcie = {
  244. .flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
  245. .aon = AON_VAL(0x0, 2, 25, 24),
  246. .reset = RESET_VAL(0x0, 31, 30),
  247. .sw_ctrl = SW_CTRL_VAL(0x4, 31),
  248. .ndiv_int = REG_VAL(0x4, 16, 10),
  249. .pdiv = REG_VAL(0x4, 26, 4),
  250. .status = REG_VAL(0x38, 12, 1),
  251. };
  252. static const struct iproc_clk_ctrl sr_lcpll_pcie_clk[] = {
  253. [BCM_SR_LCPLL_PCIE_PHY_REF_CLK] = {
  254. .channel = BCM_SR_LCPLL_PCIE_PHY_REF_CLK,
  255. .flags = IPROC_CLK_AON,
  256. .enable = ENABLE_VAL(0x0, 7, 1, 13),
  257. .mdiv = REG_VAL(0x14, 0, 9),
  258. },
  259. };
  260. static int sr_lcpll_pcie_clk_init(struct platform_device *pdev)
  261. {
  262. iproc_pll_clk_setup(pdev->dev.of_node,
  263. &sr_lcpll_pcie, NULL, 0, sr_lcpll_pcie_clk,
  264. ARRAY_SIZE(sr_lcpll_pcie_clk));
  265. return 0;
  266. }
  267. static const struct of_device_id sr_clk_dt_ids[] = {
  268. { .compatible = "brcm,sr-genpll0", .data = sr_genpll0_clk_init },
  269. { .compatible = "brcm,sr-genpll4", .data = sr_genpll4_clk_init },
  270. { .compatible = "brcm,sr-genpll5", .data = sr_genpll5_clk_init },
  271. { .compatible = "brcm,sr-lcpll0", .data = sr_lcpll0_clk_init },
  272. { .compatible = "brcm,sr-lcpll1", .data = sr_lcpll1_clk_init },
  273. { .compatible = "brcm,sr-lcpll-pcie", .data = sr_lcpll_pcie_clk_init },
  274. { /* sentinel */ }
  275. };
  276. static int sr_clk_probe(struct platform_device *pdev)
  277. {
  278. int (*probe_func)(struct platform_device *);
  279. probe_func = of_device_get_match_data(&pdev->dev);
  280. if (!probe_func)
  281. return -ENODEV;
  282. return probe_func(pdev);
  283. }
  284. static struct platform_driver sr_clk_driver = {
  285. .driver = {
  286. .name = "sr-clk",
  287. .of_match_table = sr_clk_dt_ids,
  288. },
  289. .probe = sr_clk_probe,
  290. };
  291. builtin_platform_driver(sr_clk_driver);