crg-hi3798cv200.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Hi3798CV200 Clock and Reset Generator Driver
  4. *
  5. * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
  6. */
  7. #include <dt-bindings/clock/histb-clock.h>
  8. #include <linux/clk-provider.h>
  9. #include <linux/module.h>
  10. #include <linux/of_device.h>
  11. #include <linux/platform_device.h>
  12. #include "clk.h"
  13. #include "crg.h"
  14. #include "reset.h"
  15. /* hi3798CV200 core CRG */
  16. #define HI3798CV200_INNER_CLK_OFFSET 64
  17. #define HI3798CV200_FIXED_24M 65
  18. #define HI3798CV200_FIXED_25M 66
  19. #define HI3798CV200_FIXED_50M 67
  20. #define HI3798CV200_FIXED_75M 68
  21. #define HI3798CV200_FIXED_100M 69
  22. #define HI3798CV200_FIXED_150M 70
  23. #define HI3798CV200_FIXED_200M 71
  24. #define HI3798CV200_FIXED_250M 72
  25. #define HI3798CV200_FIXED_300M 73
  26. #define HI3798CV200_FIXED_400M 74
  27. #define HI3798CV200_MMC_MUX 75
  28. #define HI3798CV200_ETH_PUB_CLK 76
  29. #define HI3798CV200_ETH_BUS_CLK 77
  30. #define HI3798CV200_ETH_BUS0_CLK 78
  31. #define HI3798CV200_ETH_BUS1_CLK 79
  32. #define HI3798CV200_COMBPHY1_MUX 80
  33. #define HI3798CV200_FIXED_12M 81
  34. #define HI3798CV200_FIXED_48M 82
  35. #define HI3798CV200_FIXED_60M 83
  36. #define HI3798CV200_FIXED_166P5M 84
  37. #define HI3798CV200_SDIO0_MUX 85
  38. #define HI3798CV200_COMBPHY0_MUX 86
  39. #define HI3798CV200_CRG_NR_CLKS 128
  40. static const struct hisi_fixed_rate_clock hi3798cv200_fixed_rate_clks[] = {
  41. { HISTB_OSC_CLK, "clk_osc", NULL, 0, 24000000, },
  42. { HISTB_APB_CLK, "clk_apb", NULL, 0, 100000000, },
  43. { HISTB_AHB_CLK, "clk_ahb", NULL, 0, 200000000, },
  44. { HI3798CV200_FIXED_12M, "12m", NULL, 0, 12000000, },
  45. { HI3798CV200_FIXED_24M, "24m", NULL, 0, 24000000, },
  46. { HI3798CV200_FIXED_25M, "25m", NULL, 0, 25000000, },
  47. { HI3798CV200_FIXED_48M, "48m", NULL, 0, 48000000, },
  48. { HI3798CV200_FIXED_50M, "50m", NULL, 0, 50000000, },
  49. { HI3798CV200_FIXED_60M, "60m", NULL, 0, 60000000, },
  50. { HI3798CV200_FIXED_75M, "75m", NULL, 0, 75000000, },
  51. { HI3798CV200_FIXED_100M, "100m", NULL, 0, 100000000, },
  52. { HI3798CV200_FIXED_150M, "150m", NULL, 0, 150000000, },
  53. { HI3798CV200_FIXED_166P5M, "166p5m", NULL, 0, 165000000, },
  54. { HI3798CV200_FIXED_200M, "200m", NULL, 0, 200000000, },
  55. { HI3798CV200_FIXED_250M, "250m", NULL, 0, 250000000, },
  56. };
  57. static const char *const mmc_mux_p[] = {
  58. "100m", "50m", "25m", "200m", "150m" };
  59. static u32 mmc_mux_table[] = {0, 1, 2, 3, 6};
  60. static const char *const comphy_mux_p[] = {
  61. "100m", "25m"};
  62. static u32 comphy_mux_table[] = {2, 3};
  63. static const char *const sdio_mux_p[] = {
  64. "100m", "50m", "150m", "166p5m" };
  65. static u32 sdio_mux_table[] = {0, 1, 2, 3};
  66. static struct hisi_mux_clock hi3798cv200_mux_clks[] = {
  67. { HI3798CV200_MMC_MUX, "mmc_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
  68. CLK_SET_RATE_PARENT, 0xa0, 8, 3, 0, mmc_mux_table, },
  69. { HI3798CV200_COMBPHY0_MUX, "combphy0_mux",
  70. comphy_mux_p, ARRAY_SIZE(comphy_mux_p),
  71. CLK_SET_RATE_PARENT, 0x188, 2, 2, 0, comphy_mux_table, },
  72. { HI3798CV200_COMBPHY1_MUX, "combphy1_mux",
  73. comphy_mux_p, ARRAY_SIZE(comphy_mux_p),
  74. CLK_SET_RATE_PARENT, 0x188, 10, 2, 0, comphy_mux_table, },
  75. { HI3798CV200_SDIO0_MUX, "sdio0_mux", sdio_mux_p,
  76. ARRAY_SIZE(sdio_mux_p), CLK_SET_RATE_PARENT,
  77. 0x9c, 8, 2, 0, sdio_mux_table, },
  78. };
  79. static u32 mmc_phase_regvals[] = {0, 1, 2, 3, 4, 5, 6, 7};
  80. static u32 mmc_phase_degrees[] = {0, 45, 90, 135, 180, 225, 270, 315};
  81. static struct hisi_phase_clock hi3798cv200_phase_clks[] = {
  82. { HISTB_MMC_SAMPLE_CLK, "mmc_sample", "clk_mmc_ciu",
  83. CLK_SET_RATE_PARENT, 0xa0, 12, 3, mmc_phase_degrees,
  84. mmc_phase_regvals, ARRAY_SIZE(mmc_phase_regvals) },
  85. { HISTB_MMC_DRV_CLK, "mmc_drive", "clk_mmc_ciu",
  86. CLK_SET_RATE_PARENT, 0xa0, 16, 3, mmc_phase_degrees,
  87. mmc_phase_regvals, ARRAY_SIZE(mmc_phase_regvals) },
  88. };
  89. static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
  90. /* UART */
  91. { HISTB_UART2_CLK, "clk_uart2", "75m",
  92. CLK_SET_RATE_PARENT, 0x68, 4, 0, },
  93. /* I2C */
  94. { HISTB_I2C0_CLK, "clk_i2c0", "clk_apb",
  95. CLK_SET_RATE_PARENT, 0x6C, 4, 0, },
  96. { HISTB_I2C1_CLK, "clk_i2c1", "clk_apb",
  97. CLK_SET_RATE_PARENT, 0x6C, 8, 0, },
  98. { HISTB_I2C2_CLK, "clk_i2c2", "clk_apb",
  99. CLK_SET_RATE_PARENT, 0x6C, 12, 0, },
  100. { HISTB_I2C3_CLK, "clk_i2c3", "clk_apb",
  101. CLK_SET_RATE_PARENT, 0x6C, 16, 0, },
  102. { HISTB_I2C4_CLK, "clk_i2c4", "clk_apb",
  103. CLK_SET_RATE_PARENT, 0x6C, 20, 0, },
  104. /* SPI */
  105. { HISTB_SPI0_CLK, "clk_spi0", "clk_apb",
  106. CLK_SET_RATE_PARENT, 0x70, 0, 0, },
  107. /* SDIO */
  108. { HISTB_SDIO0_BIU_CLK, "clk_sdio0_biu", "200m",
  109. CLK_SET_RATE_PARENT, 0x9c, 0, 0, },
  110. { HISTB_SDIO0_CIU_CLK, "clk_sdio0_ciu", "sdio0_mux",
  111. CLK_SET_RATE_PARENT, 0x9c, 1, 0, },
  112. /* EMMC */
  113. { HISTB_MMC_BIU_CLK, "clk_mmc_biu", "200m",
  114. CLK_SET_RATE_PARENT, 0xa0, 0, 0, },
  115. { HISTB_MMC_CIU_CLK, "clk_mmc_ciu", "mmc_mux",
  116. CLK_SET_RATE_PARENT, 0xa0, 1, 0, },
  117. /* PCIE*/
  118. { HISTB_PCIE_BUS_CLK, "clk_pcie_bus", "200m",
  119. CLK_SET_RATE_PARENT, 0x18c, 0, 0, },
  120. { HISTB_PCIE_SYS_CLK, "clk_pcie_sys", "100m",
  121. CLK_SET_RATE_PARENT, 0x18c, 1, 0, },
  122. { HISTB_PCIE_PIPE_CLK, "clk_pcie_pipe", "250m",
  123. CLK_SET_RATE_PARENT, 0x18c, 2, 0, },
  124. { HISTB_PCIE_AUX_CLK, "clk_pcie_aux", "24m",
  125. CLK_SET_RATE_PARENT, 0x18c, 3, 0, },
  126. /* Ethernet */
  127. { HI3798CV200_ETH_PUB_CLK, "clk_pub", NULL,
  128. CLK_SET_RATE_PARENT, 0xcc, 5, 0, },
  129. { HI3798CV200_ETH_BUS_CLK, "clk_bus", "clk_pub",
  130. CLK_SET_RATE_PARENT, 0xcc, 0, 0, },
  131. { HI3798CV200_ETH_BUS0_CLK, "clk_bus_m0", "clk_bus",
  132. CLK_SET_RATE_PARENT, 0xcc, 1, 0, },
  133. { HI3798CV200_ETH_BUS1_CLK, "clk_bus_m1", "clk_bus",
  134. CLK_SET_RATE_PARENT, 0xcc, 2, 0, },
  135. { HISTB_ETH0_MAC_CLK, "clk_mac0", "clk_bus_m0",
  136. CLK_SET_RATE_PARENT, 0xcc, 3, 0, },
  137. { HISTB_ETH0_MACIF_CLK, "clk_macif0", "clk_bus_m0",
  138. CLK_SET_RATE_PARENT, 0xcc, 24, 0, },
  139. { HISTB_ETH1_MAC_CLK, "clk_mac1", "clk_bus_m1",
  140. CLK_SET_RATE_PARENT, 0xcc, 4, 0, },
  141. { HISTB_ETH1_MACIF_CLK, "clk_macif1", "clk_bus_m1",
  142. CLK_SET_RATE_PARENT, 0xcc, 25, 0, },
  143. /* COMBPHY0 */
  144. { HISTB_COMBPHY0_CLK, "clk_combphy0", "combphy0_mux",
  145. CLK_SET_RATE_PARENT, 0x188, 0, 0, },
  146. /* COMBPHY1 */
  147. { HISTB_COMBPHY1_CLK, "clk_combphy1", "combphy1_mux",
  148. CLK_SET_RATE_PARENT, 0x188, 8, 0, },
  149. /* USB2 */
  150. { HISTB_USB2_BUS_CLK, "clk_u2_bus", "clk_ahb",
  151. CLK_SET_RATE_PARENT, 0xb8, 0, 0, },
  152. { HISTB_USB2_PHY_CLK, "clk_u2_phy", "60m",
  153. CLK_SET_RATE_PARENT, 0xb8, 4, 0, },
  154. { HISTB_USB2_12M_CLK, "clk_u2_12m", "12m",
  155. CLK_SET_RATE_PARENT, 0xb8, 2, 0 },
  156. { HISTB_USB2_48M_CLK, "clk_u2_48m", "48m",
  157. CLK_SET_RATE_PARENT, 0xb8, 1, 0 },
  158. { HISTB_USB2_UTMI_CLK, "clk_u2_utmi", "60m",
  159. CLK_SET_RATE_PARENT, 0xb8, 5, 0 },
  160. { HISTB_USB2_OTG_UTMI_CLK, "clk_u2_otg_utmi", "60m",
  161. CLK_SET_RATE_PARENT, 0xb8, 3, 0 },
  162. { HISTB_USB2_PHY1_REF_CLK, "clk_u2_phy1_ref", "24m",
  163. CLK_SET_RATE_PARENT, 0xbc, 0, 0 },
  164. { HISTB_USB2_PHY2_REF_CLK, "clk_u2_phy2_ref", "24m",
  165. CLK_SET_RATE_PARENT, 0xbc, 2, 0 },
  166. /* USB3 */
  167. { HISTB_USB3_BUS_CLK, "clk_u3_bus", NULL,
  168. CLK_SET_RATE_PARENT, 0xb0, 0, 0 },
  169. { HISTB_USB3_UTMI_CLK, "clk_u3_utmi", NULL,
  170. CLK_SET_RATE_PARENT, 0xb0, 4, 0 },
  171. { HISTB_USB3_PIPE_CLK, "clk_u3_pipe", NULL,
  172. CLK_SET_RATE_PARENT, 0xb0, 3, 0 },
  173. { HISTB_USB3_SUSPEND_CLK, "clk_u3_suspend", NULL,
  174. CLK_SET_RATE_PARENT, 0xb0, 2, 0 },
  175. { HISTB_USB3_BUS_CLK1, "clk_u3_bus1", NULL,
  176. CLK_SET_RATE_PARENT, 0xb0, 16, 0 },
  177. { HISTB_USB3_UTMI_CLK1, "clk_u3_utmi1", NULL,
  178. CLK_SET_RATE_PARENT, 0xb0, 20, 0 },
  179. { HISTB_USB3_PIPE_CLK1, "clk_u3_pipe1", NULL,
  180. CLK_SET_RATE_PARENT, 0xb0, 19, 0 },
  181. { HISTB_USB3_SUSPEND_CLK1, "clk_u3_suspend1", NULL,
  182. CLK_SET_RATE_PARENT, 0xb0, 18, 0 },
  183. };
  184. static struct hisi_clock_data *hi3798cv200_clk_register(
  185. struct platform_device *pdev)
  186. {
  187. struct hisi_clock_data *clk_data;
  188. int ret;
  189. clk_data = hisi_clk_alloc(pdev, HI3798CV200_CRG_NR_CLKS);
  190. if (!clk_data)
  191. return ERR_PTR(-ENOMEM);
  192. /* hisi_phase_clock is resource managed */
  193. ret = hisi_clk_register_phase(&pdev->dev,
  194. hi3798cv200_phase_clks,
  195. ARRAY_SIZE(hi3798cv200_phase_clks),
  196. clk_data);
  197. if (ret)
  198. return ERR_PTR(ret);
  199. ret = hisi_clk_register_fixed_rate(hi3798cv200_fixed_rate_clks,
  200. ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
  201. clk_data);
  202. if (ret)
  203. return ERR_PTR(ret);
  204. ret = hisi_clk_register_mux(hi3798cv200_mux_clks,
  205. ARRAY_SIZE(hi3798cv200_mux_clks),
  206. clk_data);
  207. if (ret)
  208. goto unregister_fixed_rate;
  209. ret = hisi_clk_register_gate(hi3798cv200_gate_clks,
  210. ARRAY_SIZE(hi3798cv200_gate_clks),
  211. clk_data);
  212. if (ret)
  213. goto unregister_mux;
  214. ret = of_clk_add_provider(pdev->dev.of_node,
  215. of_clk_src_onecell_get, &clk_data->clk_data);
  216. if (ret)
  217. goto unregister_gate;
  218. return clk_data;
  219. unregister_gate:
  220. hisi_clk_unregister_gate(hi3798cv200_gate_clks,
  221. ARRAY_SIZE(hi3798cv200_gate_clks),
  222. clk_data);
  223. unregister_mux:
  224. hisi_clk_unregister_mux(hi3798cv200_mux_clks,
  225. ARRAY_SIZE(hi3798cv200_mux_clks),
  226. clk_data);
  227. unregister_fixed_rate:
  228. hisi_clk_unregister_fixed_rate(hi3798cv200_fixed_rate_clks,
  229. ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
  230. clk_data);
  231. return ERR_PTR(ret);
  232. }
  233. static void hi3798cv200_clk_unregister(struct platform_device *pdev)
  234. {
  235. struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
  236. of_clk_del_provider(pdev->dev.of_node);
  237. hisi_clk_unregister_gate(hi3798cv200_gate_clks,
  238. ARRAY_SIZE(hi3798cv200_gate_clks),
  239. crg->clk_data);
  240. hisi_clk_unregister_mux(hi3798cv200_mux_clks,
  241. ARRAY_SIZE(hi3798cv200_mux_clks),
  242. crg->clk_data);
  243. hisi_clk_unregister_fixed_rate(hi3798cv200_fixed_rate_clks,
  244. ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
  245. crg->clk_data);
  246. }
  247. static const struct hisi_crg_funcs hi3798cv200_crg_funcs = {
  248. .register_clks = hi3798cv200_clk_register,
  249. .unregister_clks = hi3798cv200_clk_unregister,
  250. };
  251. /* hi3798CV200 sysctrl CRG */
  252. #define HI3798CV200_SYSCTRL_NR_CLKS 16
  253. static const struct hisi_gate_clock hi3798cv200_sysctrl_gate_clks[] = {
  254. { HISTB_IR_CLK, "clk_ir", "24m",
  255. CLK_SET_RATE_PARENT, 0x48, 4, 0, },
  256. { HISTB_TIMER01_CLK, "clk_timer01", "24m",
  257. CLK_SET_RATE_PARENT, 0x48, 6, 0, },
  258. { HISTB_UART0_CLK, "clk_uart0", "75m",
  259. CLK_SET_RATE_PARENT, 0x48, 10, 0, },
  260. };
  261. static struct hisi_clock_data *hi3798cv200_sysctrl_clk_register(
  262. struct platform_device *pdev)
  263. {
  264. struct hisi_clock_data *clk_data;
  265. int ret;
  266. clk_data = hisi_clk_alloc(pdev, HI3798CV200_SYSCTRL_NR_CLKS);
  267. if (!clk_data)
  268. return ERR_PTR(-ENOMEM);
  269. ret = hisi_clk_register_gate(hi3798cv200_sysctrl_gate_clks,
  270. ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
  271. clk_data);
  272. if (ret)
  273. return ERR_PTR(ret);
  274. ret = of_clk_add_provider(pdev->dev.of_node,
  275. of_clk_src_onecell_get, &clk_data->clk_data);
  276. if (ret)
  277. goto unregister_gate;
  278. return clk_data;
  279. unregister_gate:
  280. hisi_clk_unregister_gate(hi3798cv200_sysctrl_gate_clks,
  281. ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
  282. clk_data);
  283. return ERR_PTR(ret);
  284. }
  285. static void hi3798cv200_sysctrl_clk_unregister(struct platform_device *pdev)
  286. {
  287. struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
  288. of_clk_del_provider(pdev->dev.of_node);
  289. hisi_clk_unregister_gate(hi3798cv200_sysctrl_gate_clks,
  290. ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
  291. crg->clk_data);
  292. }
  293. static const struct hisi_crg_funcs hi3798cv200_sysctrl_funcs = {
  294. .register_clks = hi3798cv200_sysctrl_clk_register,
  295. .unregister_clks = hi3798cv200_sysctrl_clk_unregister,
  296. };
  297. static const struct of_device_id hi3798cv200_crg_match_table[] = {
  298. { .compatible = "hisilicon,hi3798cv200-crg",
  299. .data = &hi3798cv200_crg_funcs },
  300. { .compatible = "hisilicon,hi3798cv200-sysctrl",
  301. .data = &hi3798cv200_sysctrl_funcs },
  302. { }
  303. };
  304. MODULE_DEVICE_TABLE(of, hi3798cv200_crg_match_table);
  305. static int hi3798cv200_crg_probe(struct platform_device *pdev)
  306. {
  307. struct hisi_crg_dev *crg;
  308. crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
  309. if (!crg)
  310. return -ENOMEM;
  311. crg->funcs = of_device_get_match_data(&pdev->dev);
  312. if (!crg->funcs)
  313. return -ENOENT;
  314. crg->rstc = hisi_reset_init(pdev);
  315. if (!crg->rstc)
  316. return -ENOMEM;
  317. crg->clk_data = crg->funcs->register_clks(pdev);
  318. if (IS_ERR(crg->clk_data)) {
  319. hisi_reset_exit(crg->rstc);
  320. return PTR_ERR(crg->clk_data);
  321. }
  322. platform_set_drvdata(pdev, crg);
  323. return 0;
  324. }
  325. static int hi3798cv200_crg_remove(struct platform_device *pdev)
  326. {
  327. struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
  328. hisi_reset_exit(crg->rstc);
  329. crg->funcs->unregister_clks(pdev);
  330. return 0;
  331. }
  332. static struct platform_driver hi3798cv200_crg_driver = {
  333. .probe = hi3798cv200_crg_probe,
  334. .remove = hi3798cv200_crg_remove,
  335. .driver = {
  336. .name = "hi3798cv200-crg",
  337. .of_match_table = hi3798cv200_crg_match_table,
  338. },
  339. };
  340. static int __init hi3798cv200_crg_init(void)
  341. {
  342. return platform_driver_register(&hi3798cv200_crg_driver);
  343. }
  344. core_initcall(hi3798cv200_crg_init);
  345. static void __exit hi3798cv200_crg_exit(void)
  346. {
  347. platform_driver_unregister(&hi3798cv200_crg_driver);
  348. }
  349. module_exit(hi3798cv200_crg_exit);
  350. MODULE_LICENSE("GPL v2");
  351. MODULE_DESCRIPTION("HiSilicon Hi3798CV200 CRG Driver");