clk-mt8183-apmixedsys.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2018 MediaTek Inc.
  4. * Weiyi Lu <weiyi.lu@mediatek.com>
  5. * Copyright (c) 2023 Collabora, Ltd.
  6. * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
  7. */
  8. #include <dt-bindings/clock/mt8183-clk.h>
  9. #include <linux/clk.h>
  10. #include <linux/of.h>
  11. #include <linux/platform_device.h>
  12. #include "clk-gate.h"
  13. #include "clk-mtk.h"
  14. #include "clk-pll.h"
  15. static const struct mtk_gate_regs apmixed_cg_regs = {
  16. .set_ofs = 0x20,
  17. .clr_ofs = 0x20,
  18. .sta_ofs = 0x20,
  19. };
  20. #define GATE_APMIXED_FLAGS(_id, _name, _parent, _shift, _flags) \
  21. GATE_MTK_FLAGS(_id, _name, _parent, &apmixed_cg_regs, \
  22. _shift, &mtk_clk_gate_ops_no_setclr_inv, _flags)
  23. #define GATE_APMIXED(_id, _name, _parent, _shift) \
  24. GATE_APMIXED_FLAGS(_id, _name, _parent, _shift, 0)
  25. /*
  26. * CRITICAL CLOCK:
  27. * apmixed_appll26m is the toppest clock gate of all PLLs.
  28. */
  29. static const struct mtk_gate apmixed_clks[] = {
  30. /* AUDIO0 */
  31. GATE_APMIXED(CLK_APMIXED_SSUSB_26M, "apmixed_ssusb26m", "f_f26m_ck", 4),
  32. GATE_APMIXED_FLAGS(CLK_APMIXED_APPLL_26M, "apmixed_appll26m",
  33. "f_f26m_ck", 5, CLK_IS_CRITICAL),
  34. GATE_APMIXED(CLK_APMIXED_MIPIC0_26M, "apmixed_mipic026m", "f_f26m_ck", 6),
  35. GATE_APMIXED(CLK_APMIXED_MDPLLGP_26M, "apmixed_mdpll26m", "f_f26m_ck", 7),
  36. GATE_APMIXED(CLK_APMIXED_MMSYS_26M, "apmixed_mmsys26m", "f_f26m_ck", 8),
  37. GATE_APMIXED(CLK_APMIXED_UFS_26M, "apmixed_ufs26m", "f_f26m_ck", 9),
  38. GATE_APMIXED(CLK_APMIXED_MIPIC1_26M, "apmixed_mipic126m", "f_f26m_ck", 11),
  39. GATE_APMIXED(CLK_APMIXED_MEMPLL_26M, "apmixed_mempll26m", "f_f26m_ck", 13),
  40. GATE_APMIXED(CLK_APMIXED_CLKSQ_LVPLL_26M, "apmixed_lvpll26m", "f_f26m_ck", 14),
  41. GATE_APMIXED(CLK_APMIXED_MIPID0_26M, "apmixed_mipid026m", "f_f26m_ck", 16),
  42. GATE_APMIXED(CLK_APMIXED_MIPID1_26M, "apmixed_mipid126m", "f_f26m_ck", 17),
  43. };
  44. #define MT8183_PLL_FMAX (3800UL * MHZ)
  45. #define MT8183_PLL_FMIN (1500UL * MHZ)
  46. #define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \
  47. _rst_bar_mask, _pcwbits, _pcwibits, _pd_reg, \
  48. _pd_shift, _tuner_reg, _tuner_en_reg, \
  49. _tuner_en_bit, _pcw_reg, _pcw_shift, \
  50. _pcw_chg_reg, _div_table) { \
  51. .id = _id, \
  52. .name = _name, \
  53. .reg = _reg, \
  54. .pwr_reg = _pwr_reg, \
  55. .en_mask = _en_mask, \
  56. .flags = _flags, \
  57. .rst_bar_mask = _rst_bar_mask, \
  58. .fmax = MT8183_PLL_FMAX, \
  59. .fmin = MT8183_PLL_FMIN, \
  60. .pcwbits = _pcwbits, \
  61. .pcwibits = _pcwibits, \
  62. .pd_reg = _pd_reg, \
  63. .pd_shift = _pd_shift, \
  64. .tuner_reg = _tuner_reg, \
  65. .tuner_en_reg = _tuner_en_reg, \
  66. .tuner_en_bit = _tuner_en_bit, \
  67. .pcw_reg = _pcw_reg, \
  68. .pcw_shift = _pcw_shift, \
  69. .pcw_chg_reg = _pcw_chg_reg, \
  70. .div_table = _div_table, \
  71. }
  72. #define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \
  73. _rst_bar_mask, _pcwbits, _pcwibits, _pd_reg, \
  74. _pd_shift, _tuner_reg, _tuner_en_reg, \
  75. _tuner_en_bit, _pcw_reg, _pcw_shift, \
  76. _pcw_chg_reg) \
  77. PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \
  78. _rst_bar_mask, _pcwbits, _pcwibits, _pd_reg, \
  79. _pd_shift, _tuner_reg, _tuner_en_reg, \
  80. _tuner_en_bit, _pcw_reg, _pcw_shift, \
  81. _pcw_chg_reg, NULL)
  82. static const struct mtk_pll_div_table armpll_div_table[] = {
  83. { .div = 0, .freq = MT8183_PLL_FMAX },
  84. { .div = 1, .freq = 1500 * MHZ },
  85. { .div = 2, .freq = 750 * MHZ },
  86. { .div = 3, .freq = 375 * MHZ },
  87. { .div = 4, .freq = 187500000 },
  88. { /* sentinel */ }
  89. };
  90. static const struct mtk_pll_div_table mfgpll_div_table[] = {
  91. { .div = 0, .freq = MT8183_PLL_FMAX },
  92. { .div = 1, .freq = 1600 * MHZ },
  93. { .div = 2, .freq = 800 * MHZ },
  94. { .div = 3, .freq = 400 * MHZ },
  95. { .div = 4, .freq = 200 * MHZ },
  96. { /* sentinel */ }
  97. };
  98. static const struct mtk_pll_data plls[] = {
  99. PLL_B(CLK_APMIXED_ARMPLL_LL, "armpll_ll", 0x0200, 0x020C, 0,
  100. HAVE_RST_BAR | PLL_AO, BIT(24), 22, 8, 0x0204, 24, 0x0, 0x0, 0,
  101. 0x0204, 0, 0, armpll_div_table),
  102. PLL_B(CLK_APMIXED_ARMPLL_L, "armpll_l", 0x0210, 0x021C, 0,
  103. HAVE_RST_BAR | PLL_AO, BIT(24), 22, 8, 0x0214, 24, 0x0, 0x0, 0,
  104. 0x0214, 0, 0, armpll_div_table),
  105. PLL(CLK_APMIXED_CCIPLL, "ccipll", 0x0290, 0x029C, 0,
  106. HAVE_RST_BAR | PLL_AO, BIT(24), 22, 8, 0x0294, 24, 0x0, 0x0, 0,
  107. 0x0294, 0, 0),
  108. PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0220, 0x022C, 0,
  109. HAVE_RST_BAR, BIT(24), 22, 8, 0x0224, 24, 0x0, 0x0, 0,
  110. 0x0224, 0, 0),
  111. PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0230, 0x023C, 0,
  112. HAVE_RST_BAR, BIT(24), 22, 8, 0x0234, 24, 0x0, 0x0, 0,
  113. 0x0234, 0, 0),
  114. PLL_B(CLK_APMIXED_MFGPLL, "mfgpll", 0x0240, 0x024C, 0,
  115. 0, 0, 22, 8, 0x0244, 24, 0x0, 0x0, 0, 0x0244, 0, 0,
  116. mfgpll_div_table),
  117. PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0250, 0x025C, 0,
  118. 0, 0, 22, 8, 0x0254, 24, 0x0, 0x0, 0, 0x0254, 0, 0),
  119. PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0260, 0x026C, 0,
  120. 0, 0, 22, 8, 0x0264, 24, 0x0, 0x0, 0, 0x0264, 0, 0),
  121. PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0270, 0x027C, 0,
  122. HAVE_RST_BAR, BIT(23), 22, 8, 0x0274, 24, 0x0, 0x0, 0,
  123. 0x0274, 0, 0),
  124. PLL(CLK_APMIXED_APLL1, "apll1", 0x02A0, 0x02B0, 0,
  125. 0, 0, 32, 8, 0x02A0, 1, 0x02A8, 0x0014, 0, 0x02A4, 0, 0x02A0),
  126. PLL(CLK_APMIXED_APLL2, "apll2", 0x02b4, 0x02c4, 0,
  127. 0, 0, 32, 8, 0x02B4, 1, 0x02BC, 0x0014, 1, 0x02B8, 0, 0x02B4),
  128. };
  129. static int clk_mt8183_apmixed_probe(struct platform_device *pdev)
  130. {
  131. void __iomem *base;
  132. struct clk_hw_onecell_data *clk_data;
  133. struct device_node *node = pdev->dev.of_node;
  134. struct device *dev = &pdev->dev;
  135. int ret;
  136. base = devm_platform_ioremap_resource(pdev, 0);
  137. if (IS_ERR(base))
  138. return PTR_ERR(base);
  139. clk_data = mtk_devm_alloc_clk_data(dev, CLK_APMIXED_NR_CLK);
  140. if (!clk_data)
  141. return -ENOMEM;
  142. ret = mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
  143. if (ret)
  144. return ret;
  145. ret = mtk_clk_register_gates(&pdev->dev, node, apmixed_clks,
  146. ARRAY_SIZE(apmixed_clks), clk_data);
  147. if (ret)
  148. goto unregister_plls;
  149. ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
  150. if (ret)
  151. goto unregister_gates;
  152. return 0;
  153. unregister_gates:
  154. mtk_clk_unregister_gates(apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data);
  155. unregister_plls:
  156. mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data);
  157. return ret;
  158. }
  159. static const struct of_device_id of_match_clk_mt8183_apmixed[] = {
  160. { .compatible = "mediatek,mt8183-apmixedsys" },
  161. { /* sentinel */ }
  162. };
  163. MODULE_DEVICE_TABLE(of, of_match_clk_mt8183_apmixed);
  164. static struct platform_driver clk_mt8183_apmixed_drv = {
  165. .probe = clk_mt8183_apmixed_probe,
  166. .driver = {
  167. .name = "clk-mt8183-apmixed",
  168. .of_match_table = of_match_clk_mt8183_apmixed,
  169. },
  170. };
  171. builtin_platform_driver(clk_mt8183_apmixed_drv)
  172. MODULE_DESCRIPTION("MediaTek MT8183 apmixedsys clocks driver");
  173. MODULE_LICENSE("GPL");