clk-link.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-3-08 GuEe-GUI the first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #define DBG_TAG "clk.link"
  13. #define DBG_LVL DBG_INFO
  14. #include <rtdbg.h>
  15. struct rockchip_link_data
  16. {
  17. rt_size_t cells_nr;
  18. struct rt_clk_cell **cells;
  19. };
  20. struct rockchip_link_cell
  21. {
  22. struct rt_clk_cell cell;
  23. rt_uint32_t bit_idx;
  24. };
  25. #define cell_to_rockchip_link_cell(cell) rt_container_of(cell, struct rockchip_link_cell, cell)
  26. struct rockchip_link_clk
  27. {
  28. struct rt_clk_node parent;
  29. void *base;
  30. };
  31. #define raw_to_rockchip_link_clk(raw) rt_container_of(raw, struct rockchip_link_clk, parent)
  32. static void clk_gate_endisable(struct rt_clk_cell *cell, int enable)
  33. {
  34. rt_uint32_t reg;
  35. int set = 1 ^ enable;
  36. struct rockchip_link_cell *link_cell = cell_to_rockchip_link_cell(cell);
  37. struct rockchip_link_clk *link_clk = raw_to_rockchip_link_clk(cell->clk_np);
  38. reg = RT_BIT(link_cell->bit_idx + 16);
  39. if (set)
  40. {
  41. reg |= RT_BIT(link_cell->bit_idx);
  42. }
  43. HWREG32(link_clk->base) = reg;
  44. }
  45. static rt_err_t rockchip_link_clk_enable(struct rt_clk_cell *cell)
  46. {
  47. clk_gate_endisable(cell, 1);
  48. return RT_EOK;
  49. }
  50. static void rockchip_link_clk_disable(struct rt_clk_cell *cell)
  51. {
  52. clk_gate_endisable(cell, 0);
  53. }
  54. static rt_bool_t rockchip_link_clk_is_enabled(struct rt_clk_cell *cell)
  55. {
  56. rt_uint32_t reg;
  57. struct rockchip_link_cell *link_cell = cell_to_rockchip_link_cell(cell);
  58. struct rockchip_link_clk *link_clk = raw_to_rockchip_link_clk(cell->clk_np);
  59. reg = HWREG32(link_clk->base);
  60. reg ^= RT_BIT(link_cell->bit_idx);
  61. reg &= RT_BIT(link_cell->bit_idx);
  62. return !!reg;
  63. }
  64. const struct rt_clk_ops clk_gate_ops =
  65. {
  66. .enable = rockchip_link_clk_enable,
  67. .disable = rockchip_link_clk_disable,
  68. .is_enabled = rockchip_link_clk_is_enabled,
  69. };
  70. #define GATE_LINK(_name, _pname, _bit_idx) \
  71. (void *)&(struct rockchip_link_cell) \
  72. { \
  73. .cell.name = _name, \
  74. .cell.parents_nr = 1, \
  75. .cell.parent_name = _pname, \
  76. .cell.ops = &clk_gate_ops, \
  77. .cell.flags = RT_CLK_F_SET_RATE_PARENT, \
  78. .bit_idx = _bit_idx, \
  79. }
  80. static struct rt_clk_cell *rk3562_clk_cells[] =
  81. {
  82. GATE_LINK("aclk_rga_jdec", "aclk_rga_pre", 3),
  83. GATE_LINK("aclk_vdpu", "aclk_vdpu_pre", 5),
  84. GATE_LINK("aclk_vepu", "aclk_vepu_pre", 3),
  85. GATE_LINK("aclk_vi_isp", "aclk_vi", 3),
  86. GATE_LINK("aclk_vo", "aclk_vo_pre", 3),
  87. GATE_LINK("hclk_vepu", "hclk_vepu_pre", 4),
  88. };
  89. static const struct rockchip_link_data rk3562_clk_data =
  90. {
  91. .cells = rk3562_clk_cells,
  92. .cells_nr = RT_ARRAY_SIZE(rk3562_clk_cells),
  93. };
  94. static struct rt_clk_cell *rk3588_clk_cells[] =
  95. {
  96. GATE_LINK("aclk_isp1_pre", "aclk_isp1_root", 6),
  97. GATE_LINK("hclk_isp1_pre", "hclk_isp1_root", 8),
  98. GATE_LINK("hclk_nvm", "hclk_nvm_root", 2),
  99. GATE_LINK("aclk_usb", "aclk_usb_root", 2),
  100. GATE_LINK("hclk_usb", "hclk_usb_root", 3),
  101. GATE_LINK("aclk_jpeg_decoder_pre", "aclk_jpeg_decoder_root", 7),
  102. GATE_LINK("aclk_vdpu_low_pre", "aclk_vdpu_low_root", 5),
  103. GATE_LINK("aclk_rkvenc1_pre", "aclk_rkvenc1_root", 3),
  104. GATE_LINK("hclk_rkvenc1_pre", "hclk_rkvenc1_root", 2),
  105. GATE_LINK("hclk_rkvdec0_pre", "hclk_rkvdec0_root", 5),
  106. GATE_LINK("aclk_rkvdec0_pre", "aclk_rkvdec0_root", 6),
  107. GATE_LINK("hclk_rkvdec1_pre", "hclk_rkvdec1_root", 4),
  108. GATE_LINK("aclk_rkvdec1_pre", "aclk_rkvdec1_root", 5),
  109. GATE_LINK("aclk_hdcp0_pre", "aclk_vo0_root", 9),
  110. GATE_LINK("hclk_vo0", "hclk_vo0_root", 5),
  111. GATE_LINK("aclk_hdcp1_pre", "aclk_hdcp1_root", 6),
  112. GATE_LINK("hclk_vo1", "hclk_vo1_root", 9),
  113. GATE_LINK("aclk_av1_pre", "aclk_av1_root", 1),
  114. GATE_LINK("pclk_av1_pre", "pclk_av1_root", 4),
  115. GATE_LINK("hclk_sdio_pre", "hclk_sdio_root", 1),
  116. GATE_LINK("pclk_vo0_grf", "pclk_vo0_root", 10),
  117. GATE_LINK("pclk_vo1_grf", "pclk_vo1_root", 12),
  118. };
  119. static const struct rockchip_link_data rk3588_clk_data =
  120. {
  121. .cells = rk3588_clk_cells,
  122. .cells_nr = RT_ARRAY_SIZE(rk3588_clk_cells),
  123. };
  124. static rt_err_t rockchip_clk_link_probe(struct rt_platform_device *pdev)
  125. {
  126. rt_err_t err;
  127. struct rt_device *dev = &pdev->parent;
  128. const struct rockchip_link_data *clk_data = pdev->id->data;
  129. struct rockchip_link_clk *link_clk = rt_calloc(1, sizeof(*link_clk));
  130. if (!link_clk)
  131. {
  132. return -RT_ENOMEM;
  133. }
  134. if (!(link_clk->base = rt_dm_dev_iomap(dev, 0)))
  135. {
  136. err = -RT_EIO;
  137. goto _fail;
  138. }
  139. link_clk->parent.dev = dev;
  140. link_clk->parent.cells = clk_data->cells;
  141. link_clk->parent.cells_nr = clk_data->cells_nr;
  142. if ((err = rt_clk_register(&link_clk->parent)))
  143. {
  144. goto _fail;
  145. }
  146. return RT_EOK;
  147. _fail:
  148. if (link_clk->base)
  149. {
  150. rt_iounmap(link_clk->base);
  151. }
  152. rt_free(link_clk);
  153. return err;
  154. }
  155. static const struct rt_ofw_node_id rockchip_clk_link_ofw_ids[] =
  156. {
  157. { .compatible = "rockchip,rk3562-clock-gate-link", .data = &rk3562_clk_data },
  158. { .compatible = "rockchip,rk3588-clock-gate-link", .data = &rk3588_clk_data },
  159. { /* sentinel */ }
  160. };
  161. static struct rt_platform_driver rockchip_clk_link_driver =
  162. {
  163. .name = "clk-link",
  164. .ids = rockchip_clk_link_ofw_ids,
  165. .probe = rockchip_clk_link_probe,
  166. };
  167. static int rockchip_clk_link_register(void)
  168. {
  169. rt_platform_driver_register(&rockchip_clk_link_driver);
  170. return 0;
  171. }
  172. INIT_SUBSYS_EXPORT(rockchip_clk_link_register);