crg-hi3798cv200.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /*
  2. * Hi3798CV200 Clock and Reset Generator Driver
  3. *
  4. * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <dt-bindings/clock/histb-clock.h>
  20. #include <linux/clk-provider.h>
  21. #include <linux/module.h>
  22. #include <linux/of_device.h>
  23. #include <linux/platform_device.h>
  24. #include "clk.h"
  25. #include "crg.h"
  26. #include "reset.h"
  27. /* hi3798CV200 core CRG */
  28. #define HI3798CV200_INNER_CLK_OFFSET 64
  29. #define HI3798CV200_FIXED_24M 65
  30. #define HI3798CV200_FIXED_25M 66
  31. #define HI3798CV200_FIXED_50M 67
  32. #define HI3798CV200_FIXED_75M 68
  33. #define HI3798CV200_FIXED_100M 69
  34. #define HI3798CV200_FIXED_150M 70
  35. #define HI3798CV200_FIXED_200M 71
  36. #define HI3798CV200_FIXED_250M 72
  37. #define HI3798CV200_FIXED_300M 73
  38. #define HI3798CV200_FIXED_400M 74
  39. #define HI3798CV200_MMC_MUX 75
  40. #define HI3798CV200_ETH_PUB_CLK 76
  41. #define HI3798CV200_ETH_BUS_CLK 77
  42. #define HI3798CV200_ETH_BUS0_CLK 78
  43. #define HI3798CV200_ETH_BUS1_CLK 79
  44. #define HI3798CV200_COMBPHY1_MUX 80
  45. #define HI3798CV200_CRG_NR_CLKS 128
  46. static const struct hisi_fixed_rate_clock hi3798cv200_fixed_rate_clks[] = {
  47. { HISTB_OSC_CLK, "clk_osc", NULL, 0, 24000000, },
  48. { HISTB_APB_CLK, "clk_apb", NULL, 0, 100000000, },
  49. { HISTB_AHB_CLK, "clk_ahb", NULL, 0, 200000000, },
  50. { HI3798CV200_FIXED_24M, "24m", NULL, 0, 24000000, },
  51. { HI3798CV200_FIXED_25M, "25m", NULL, 0, 25000000, },
  52. { HI3798CV200_FIXED_50M, "50m", NULL, 0, 50000000, },
  53. { HI3798CV200_FIXED_75M, "75m", NULL, 0, 75000000, },
  54. { HI3798CV200_FIXED_100M, "100m", NULL, 0, 100000000, },
  55. { HI3798CV200_FIXED_150M, "150m", NULL, 0, 150000000, },
  56. { HI3798CV200_FIXED_200M, "200m", NULL, 0, 200000000, },
  57. { HI3798CV200_FIXED_250M, "250m", NULL, 0, 250000000, },
  58. };
  59. static const char *const mmc_mux_p[] = {
  60. "100m", "50m", "25m", "200m", "150m" };
  61. static u32 mmc_mux_table[] = {0, 1, 2, 3, 6};
  62. static const char *const comphy1_mux_p[] = {
  63. "100m", "25m"};
  64. static u32 comphy1_mux_table[] = {2, 3};
  65. static struct hisi_mux_clock hi3798cv200_mux_clks[] = {
  66. { HI3798CV200_MMC_MUX, "mmc_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
  67. CLK_SET_RATE_PARENT, 0xa0, 8, 3, 0, mmc_mux_table, },
  68. { HI3798CV200_COMBPHY1_MUX, "combphy1_mux",
  69. comphy1_mux_p, ARRAY_SIZE(comphy1_mux_p),
  70. CLK_SET_RATE_PARENT, 0x188, 10, 2, 0, comphy1_mux_table, },
  71. };
  72. static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
  73. /* UART */
  74. { HISTB_UART2_CLK, "clk_uart2", "75m",
  75. CLK_SET_RATE_PARENT, 0x68, 4, 0, },
  76. /* I2C */
  77. { HISTB_I2C0_CLK, "clk_i2c0", "clk_apb",
  78. CLK_SET_RATE_PARENT, 0x6C, 4, 0, },
  79. { HISTB_I2C1_CLK, "clk_i2c1", "clk_apb",
  80. CLK_SET_RATE_PARENT, 0x6C, 8, 0, },
  81. { HISTB_I2C2_CLK, "clk_i2c2", "clk_apb",
  82. CLK_SET_RATE_PARENT, 0x6C, 12, 0, },
  83. { HISTB_I2C3_CLK, "clk_i2c3", "clk_apb",
  84. CLK_SET_RATE_PARENT, 0x6C, 16, 0, },
  85. { HISTB_I2C4_CLK, "clk_i2c4", "clk_apb",
  86. CLK_SET_RATE_PARENT, 0x6C, 20, 0, },
  87. /* SPI */
  88. { HISTB_SPI0_CLK, "clk_spi0", "clk_apb",
  89. CLK_SET_RATE_PARENT, 0x70, 0, 0, },
  90. /* SDIO */
  91. { HISTB_SDIO0_BIU_CLK, "clk_sdio0_biu", "200m",
  92. CLK_SET_RATE_PARENT, 0x9c, 0, 0, },
  93. { HISTB_SDIO0_CIU_CLK, "clk_sdio0_ciu", "mmc_mux",
  94. CLK_SET_RATE_PARENT, 0x9c, 1, 0, },
  95. /* EMMC */
  96. { HISTB_MMC_BIU_CLK, "clk_mmc_biu", "200m",
  97. CLK_SET_RATE_PARENT, 0xa0, 0, 0, },
  98. { HISTB_MMC_CIU_CLK, "clk_mmc_ciu", "mmc_mux",
  99. CLK_SET_RATE_PARENT, 0xa0, 1, 0, },
  100. /* PCIE*/
  101. { HISTB_PCIE_BUS_CLK, "clk_pcie_bus", "200m",
  102. CLK_SET_RATE_PARENT, 0x18c, 0, 0, },
  103. { HISTB_PCIE_SYS_CLK, "clk_pcie_sys", "100m",
  104. CLK_SET_RATE_PARENT, 0x18c, 1, 0, },
  105. { HISTB_PCIE_PIPE_CLK, "clk_pcie_pipe", "250m",
  106. CLK_SET_RATE_PARENT, 0x18c, 2, 0, },
  107. { HISTB_PCIE_AUX_CLK, "clk_pcie_aux", "24m",
  108. CLK_SET_RATE_PARENT, 0x18c, 3, 0, },
  109. /* Ethernet */
  110. { HI3798CV200_ETH_PUB_CLK, "clk_pub", NULL,
  111. CLK_SET_RATE_PARENT, 0xcc, 5, 0, },
  112. { HI3798CV200_ETH_BUS_CLK, "clk_bus", "clk_pub",
  113. CLK_SET_RATE_PARENT, 0xcc, 0, 0, },
  114. { HI3798CV200_ETH_BUS0_CLK, "clk_bus_m0", "clk_bus",
  115. CLK_SET_RATE_PARENT, 0xcc, 1, 0, },
  116. { HI3798CV200_ETH_BUS1_CLK, "clk_bus_m1", "clk_bus",
  117. CLK_SET_RATE_PARENT, 0xcc, 2, 0, },
  118. { HISTB_ETH0_MAC_CLK, "clk_mac0", "clk_bus_m0",
  119. CLK_SET_RATE_PARENT, 0xcc, 3, 0, },
  120. { HISTB_ETH0_MACIF_CLK, "clk_macif0", "clk_bus_m0",
  121. CLK_SET_RATE_PARENT, 0xcc, 24, 0, },
  122. { HISTB_ETH1_MAC_CLK, "clk_mac1", "clk_bus_m1",
  123. CLK_SET_RATE_PARENT, 0xcc, 4, 0, },
  124. { HISTB_ETH1_MACIF_CLK, "clk_macif1", "clk_bus_m1",
  125. CLK_SET_RATE_PARENT, 0xcc, 25, 0, },
  126. /* COMBPHY1 */
  127. { HISTB_COMBPHY1_CLK, "clk_combphy1", "combphy1_mux",
  128. CLK_SET_RATE_PARENT, 0x188, 8, 0, },
  129. };
  130. static struct hisi_clock_data *hi3798cv200_clk_register(
  131. struct platform_device *pdev)
  132. {
  133. struct hisi_clock_data *clk_data;
  134. int ret;
  135. clk_data = hisi_clk_alloc(pdev, HI3798CV200_CRG_NR_CLKS);
  136. if (!clk_data)
  137. return ERR_PTR(-ENOMEM);
  138. ret = hisi_clk_register_fixed_rate(hi3798cv200_fixed_rate_clks,
  139. ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
  140. clk_data);
  141. if (ret)
  142. return ERR_PTR(ret);
  143. ret = hisi_clk_register_mux(hi3798cv200_mux_clks,
  144. ARRAY_SIZE(hi3798cv200_mux_clks),
  145. clk_data);
  146. if (ret)
  147. goto unregister_fixed_rate;
  148. ret = hisi_clk_register_gate(hi3798cv200_gate_clks,
  149. ARRAY_SIZE(hi3798cv200_gate_clks),
  150. clk_data);
  151. if (ret)
  152. goto unregister_mux;
  153. ret = of_clk_add_provider(pdev->dev.of_node,
  154. of_clk_src_onecell_get, &clk_data->clk_data);
  155. if (ret)
  156. goto unregister_gate;
  157. return clk_data;
  158. unregister_fixed_rate:
  159. hisi_clk_unregister_fixed_rate(hi3798cv200_fixed_rate_clks,
  160. ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
  161. clk_data);
  162. unregister_mux:
  163. hisi_clk_unregister_mux(hi3798cv200_mux_clks,
  164. ARRAY_SIZE(hi3798cv200_mux_clks),
  165. clk_data);
  166. unregister_gate:
  167. hisi_clk_unregister_gate(hi3798cv200_gate_clks,
  168. ARRAY_SIZE(hi3798cv200_gate_clks),
  169. clk_data);
  170. return ERR_PTR(ret);
  171. }
  172. static void hi3798cv200_clk_unregister(struct platform_device *pdev)
  173. {
  174. struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
  175. of_clk_del_provider(pdev->dev.of_node);
  176. hisi_clk_unregister_gate(hi3798cv200_gate_clks,
  177. ARRAY_SIZE(hi3798cv200_gate_clks),
  178. crg->clk_data);
  179. hisi_clk_unregister_mux(hi3798cv200_mux_clks,
  180. ARRAY_SIZE(hi3798cv200_mux_clks),
  181. crg->clk_data);
  182. hisi_clk_unregister_fixed_rate(hi3798cv200_fixed_rate_clks,
  183. ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
  184. crg->clk_data);
  185. }
  186. static const struct hisi_crg_funcs hi3798cv200_crg_funcs = {
  187. .register_clks = hi3798cv200_clk_register,
  188. .unregister_clks = hi3798cv200_clk_unregister,
  189. };
  190. /* hi3798CV200 sysctrl CRG */
  191. #define HI3798CV200_SYSCTRL_NR_CLKS 16
  192. static const struct hisi_gate_clock hi3798cv200_sysctrl_gate_clks[] = {
  193. { HISTB_IR_CLK, "clk_ir", "100m",
  194. CLK_SET_RATE_PARENT, 0x48, 4, 0, },
  195. { HISTB_TIMER01_CLK, "clk_timer01", "24m",
  196. CLK_SET_RATE_PARENT, 0x48, 6, 0, },
  197. { HISTB_UART0_CLK, "clk_uart0", "75m",
  198. CLK_SET_RATE_PARENT, 0x48, 10, 0, },
  199. };
  200. static struct hisi_clock_data *hi3798cv200_sysctrl_clk_register(
  201. struct platform_device *pdev)
  202. {
  203. struct hisi_clock_data *clk_data;
  204. int ret;
  205. clk_data = hisi_clk_alloc(pdev, HI3798CV200_SYSCTRL_NR_CLKS);
  206. if (!clk_data)
  207. return ERR_PTR(-ENOMEM);
  208. ret = hisi_clk_register_gate(hi3798cv200_sysctrl_gate_clks,
  209. ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
  210. clk_data);
  211. if (ret)
  212. return ERR_PTR(ret);
  213. ret = of_clk_add_provider(pdev->dev.of_node,
  214. of_clk_src_onecell_get, &clk_data->clk_data);
  215. if (ret)
  216. goto unregister_gate;
  217. return clk_data;
  218. unregister_gate:
  219. hisi_clk_unregister_gate(hi3798cv200_sysctrl_gate_clks,
  220. ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
  221. clk_data);
  222. return ERR_PTR(ret);
  223. }
  224. static void hi3798cv200_sysctrl_clk_unregister(struct platform_device *pdev)
  225. {
  226. struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
  227. of_clk_del_provider(pdev->dev.of_node);
  228. hisi_clk_unregister_gate(hi3798cv200_sysctrl_gate_clks,
  229. ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
  230. crg->clk_data);
  231. }
  232. static const struct hisi_crg_funcs hi3798cv200_sysctrl_funcs = {
  233. .register_clks = hi3798cv200_sysctrl_clk_register,
  234. .unregister_clks = hi3798cv200_sysctrl_clk_unregister,
  235. };
  236. static const struct of_device_id hi3798cv200_crg_match_table[] = {
  237. { .compatible = "hisilicon,hi3798cv200-crg",
  238. .data = &hi3798cv200_crg_funcs },
  239. { .compatible = "hisilicon,hi3798cv200-sysctrl",
  240. .data = &hi3798cv200_sysctrl_funcs },
  241. { }
  242. };
  243. MODULE_DEVICE_TABLE(of, hi3798cv200_crg_match_table);
  244. static int hi3798cv200_crg_probe(struct platform_device *pdev)
  245. {
  246. struct hisi_crg_dev *crg;
  247. crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
  248. if (!crg)
  249. return -ENOMEM;
  250. crg->funcs = of_device_get_match_data(&pdev->dev);
  251. if (!crg->funcs)
  252. return -ENOENT;
  253. crg->rstc = hisi_reset_init(pdev);
  254. if (!crg->rstc)
  255. return -ENOMEM;
  256. crg->clk_data = crg->funcs->register_clks(pdev);
  257. if (IS_ERR(crg->clk_data)) {
  258. hisi_reset_exit(crg->rstc);
  259. return PTR_ERR(crg->clk_data);
  260. }
  261. platform_set_drvdata(pdev, crg);
  262. return 0;
  263. }
  264. static int hi3798cv200_crg_remove(struct platform_device *pdev)
  265. {
  266. struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
  267. hisi_reset_exit(crg->rstc);
  268. crg->funcs->unregister_clks(pdev);
  269. return 0;
  270. }
  271. static struct platform_driver hi3798cv200_crg_driver = {
  272. .probe = hi3798cv200_crg_probe,
  273. .remove = hi3798cv200_crg_remove,
  274. .driver = {
  275. .name = "hi3798cv200-crg",
  276. .of_match_table = hi3798cv200_crg_match_table,
  277. },
  278. };
  279. static int __init hi3798cv200_crg_init(void)
  280. {
  281. return platform_driver_register(&hi3798cv200_crg_driver);
  282. }
  283. core_initcall(hi3798cv200_crg_init);
  284. static void __exit hi3798cv200_crg_exit(void)
  285. {
  286. platform_driver_unregister(&hi3798cv200_crg_driver);
  287. }
  288. module_exit(hi3798cv200_crg_exit);
  289. MODULE_LICENSE("GPL v2");
  290. MODULE_DESCRIPTION("HiSilicon Hi3798CV200 CRG Driver");