clk-mt8365-apmixedsys.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2022 MediaTek Inc.
  4. * Copyright (c) 2023 Collabora Ltd.
  5. */
  6. #include <dt-bindings/clock/mediatek,mt8365-clk.h>
  7. #include <linux/clk.h>
  8. #include <linux/of.h>
  9. #include <linux/platform_device.h>
  10. #include "clk-pll.h"
  11. #include "clk-mtk.h"
  12. #define MT8365_PLL_FMAX (3800UL * MHZ)
  13. #define MT8365_PLL_FMIN (1500UL * MHZ)
  14. #define CON0_MT8365_RST_BAR BIT(23)
  15. #define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
  16. _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \
  17. _tuner_en_bit, _pcw_reg, _pcw_shift, _div_table, \
  18. _rst_bar_mask, _pcw_chg_reg) { \
  19. .id = _id, \
  20. .name = _name, \
  21. .reg = _reg, \
  22. .pwr_reg = _pwr_reg, \
  23. .en_mask = _en_mask, \
  24. .flags = _flags, \
  25. .rst_bar_mask = _rst_bar_mask, \
  26. .fmax = MT8365_PLL_FMAX, \
  27. .fmin = MT8365_PLL_FMIN, \
  28. .pcwbits = _pcwbits, \
  29. .pcwibits = 8, \
  30. .pd_reg = _pd_reg, \
  31. .pd_shift = _pd_shift, \
  32. .tuner_reg = _tuner_reg, \
  33. .tuner_en_reg = _tuner_en_reg, \
  34. .tuner_en_bit = _tuner_en_bit, \
  35. .pcw_reg = _pcw_reg, \
  36. .pcw_shift = _pcw_shift, \
  37. .pcw_chg_reg = _pcw_chg_reg, \
  38. .div_table = _div_table, \
  39. }
  40. #define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
  41. _pd_reg, _pd_shift, _tuner_reg, \
  42. _tuner_en_reg, _tuner_en_bit, _pcw_reg, \
  43. _pcw_shift, _rst_bar_mask, _pcw_chg_reg) \
  44. PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \
  45. _pcwbits, _pd_reg, _pd_shift, \
  46. _tuner_reg, _tuner_en_reg, _tuner_en_bit, \
  47. _pcw_reg, _pcw_shift, NULL, _rst_bar_mask, \
  48. _pcw_chg_reg) \
  49. static const struct mtk_pll_div_table armpll_div_table[] = {
  50. { .div = 0, .freq = MT8365_PLL_FMAX },
  51. { .div = 1, .freq = 1500 * MHZ },
  52. { .div = 2, .freq = 750 * MHZ },
  53. { .div = 3, .freq = 375 * MHZ },
  54. { .div = 4, .freq = 182500000 },
  55. { } /* sentinel */
  56. };
  57. static const struct mtk_pll_div_table mfgpll_div_table[] = {
  58. { .div = 0, .freq = MT8365_PLL_FMAX },
  59. { .div = 1, .freq = 1600 * MHZ },
  60. { .div = 2, .freq = 800 * MHZ },
  61. { .div = 3, .freq = 400 * MHZ },
  62. { .div = 4, .freq = 200 * MHZ },
  63. { } /* sentinel */
  64. };
  65. static const struct mtk_pll_div_table dsppll_div_table[] = {
  66. { .div = 0, .freq = MT8365_PLL_FMAX },
  67. { .div = 1, .freq = 1600 * MHZ },
  68. { .div = 2, .freq = 600 * MHZ },
  69. { .div = 3, .freq = 400 * MHZ },
  70. { .div = 4, .freq = 200 * MHZ },
  71. { } /* sentinel */
  72. };
  73. static const struct mtk_pll_data plls[] = {
  74. PLL_B(CLK_APMIXED_ARMPLL, "armpll", 0x030C, 0x0318, 0x00000001, PLL_AO,
  75. 22, 0x0310, 24, 0, 0, 0, 0x0310, 0, armpll_div_table, 0, 0),
  76. PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0228, 0x0234, 0xFF000001,
  77. HAVE_RST_BAR, 22, 0x022C, 24, 0, 0, 0, 0x022C, 0, CON0_MT8365_RST_BAR, 0),
  78. PLL(CLK_APMIXED_UNIVPLL, "univpll2", 0x0208, 0x0214, 0xFF000001,
  79. HAVE_RST_BAR, 22, 0x020C, 24, 0, 0, 0, 0x020C, 0, CON0_MT8365_RST_BAR, 0),
  80. PLL_B(CLK_APMIXED_MFGPLL, "mfgpll", 0x0218, 0x0224, 0x00000001, 0, 22,
  81. 0x021C, 24, 0, 0, 0, 0x021C, 0, mfgpll_div_table, 0, 0),
  82. PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0350, 0x035C, 0x00000001, 0, 22,
  83. 0x0354, 24, 0, 0, 0, 0x0354, 0, 0, 0),
  84. PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0330, 0x033C, 0x00000001, 0, 22,
  85. 0x0334, 24, 0, 0, 0, 0x0334, 0, 0, 0),
  86. PLL(CLK_APMIXED_APLL1, "apll1", 0x031C, 0x032C, 0x00000001, 0, 32,
  87. 0x0320, 24, 0x0040, 0x000C, 0, 0x0324, 0, 0, 0x0320),
  88. PLL(CLK_APMIXED_APLL2, "apll2", 0x0360, 0x0370, 0x00000001, 0, 32,
  89. 0x0364, 24, 0x004C, 0x000C, 5, 0x0368, 0, 0, 0x0364),
  90. PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x0374, 0x0380, 0x00000001, 0, 22,
  91. 0x0378, 24, 0, 0, 0, 0x0378, 0, 0, 0),
  92. PLL_B(CLK_APMIXED_DSPPLL, "dsppll", 0x0390, 0x039C, 0x00000001, 0, 22,
  93. 0x0394, 24, 0, 0, 0, 0x0394, 0, dsppll_div_table, 0, 0),
  94. PLL(CLK_APMIXED_APUPLL, "apupll", 0x03A0, 0x03AC, 0x00000001, 0, 22,
  95. 0x03A4, 24, 0, 0, 0, 0x03A4, 0, 0, 0),
  96. };
  97. static int clk_mt8365_apmixed_probe(struct platform_device *pdev)
  98. {
  99. void __iomem *base;
  100. struct clk_hw_onecell_data *clk_data;
  101. struct device_node *node = pdev->dev.of_node;
  102. struct device *dev = &pdev->dev;
  103. struct clk_hw *hw;
  104. int ret;
  105. base = devm_platform_ioremap_resource(pdev, 0);
  106. if (IS_ERR(base))
  107. return PTR_ERR(base);
  108. clk_data = mtk_devm_alloc_clk_data(dev, CLK_APMIXED_NR_CLK);
  109. if (!clk_data)
  110. return -ENOMEM;
  111. hw = devm_clk_hw_register_gate(dev, "univ_en", "univpll2", 0,
  112. base + 0x204, 0, 0, NULL);
  113. if (IS_ERR(hw))
  114. return PTR_ERR(hw);
  115. clk_data->hws[CLK_APMIXED_UNIV_EN] = hw;
  116. hw = devm_clk_hw_register_gate(dev, "usb20_en", "univ_en", 0,
  117. base + 0x204, 1, 0, NULL);
  118. if (IS_ERR(hw))
  119. return PTR_ERR(hw);
  120. clk_data->hws[CLK_APMIXED_USB20_EN] = hw;
  121. ret = mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
  122. if (ret)
  123. return ret;
  124. ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
  125. if (ret)
  126. goto unregister_plls;
  127. return 0;
  128. unregister_plls:
  129. mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data);
  130. return ret;
  131. }
  132. static const struct of_device_id of_match_clk_mt8365_apmixed[] = {
  133. { .compatible = "mediatek,mt8365-apmixedsys" },
  134. { /* sentinel */ }
  135. };
  136. MODULE_DEVICE_TABLE(of, of_match_clk_mt8365_apmixed);
  137. static struct platform_driver clk_mt8365_apmixed_drv = {
  138. .probe = clk_mt8365_apmixed_probe,
  139. .driver = {
  140. .name = "clk-mt8365-apmixed",
  141. .of_match_table = of_match_clk_mt8365_apmixed,
  142. },
  143. };
  144. builtin_platform_driver(clk_mt8365_apmixed_drv)
  145. MODULE_DESCRIPTION("MediaTek MT8365 apmixedsys clocks driver");
  146. MODULE_LICENSE("GPL");