mtk_hdmi_phy.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2018 MediaTek Inc.
  4. * Author: Jie Qiu <jie.qiu@mediatek.com>
  5. */
  6. #include "mtk_hdmi_phy.h"
  7. static int mtk_hdmi_phy_power_on(struct phy *phy);
  8. static int mtk_hdmi_phy_power_off(struct phy *phy);
  9. static const struct phy_ops mtk_hdmi_phy_dev_ops = {
  10. .power_on = mtk_hdmi_phy_power_on,
  11. .power_off = mtk_hdmi_phy_power_off,
  12. .owner = THIS_MODULE,
  13. };
  14. long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
  15. unsigned long *parent_rate)
  16. {
  17. struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
  18. hdmi_phy->pll_rate = rate;
  19. if (rate <= 74250000)
  20. *parent_rate = rate;
  21. else
  22. *parent_rate = rate / 2;
  23. return rate;
  24. }
  25. unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
  26. unsigned long parent_rate)
  27. {
  28. struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
  29. return hdmi_phy->pll_rate;
  30. }
  31. void mtk_hdmi_phy_clear_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
  32. u32 bits)
  33. {
  34. void __iomem *reg = hdmi_phy->regs + offset;
  35. u32 tmp;
  36. tmp = readl(reg);
  37. tmp &= ~bits;
  38. writel(tmp, reg);
  39. }
  40. void mtk_hdmi_phy_set_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
  41. u32 bits)
  42. {
  43. void __iomem *reg = hdmi_phy->regs + offset;
  44. u32 tmp;
  45. tmp = readl(reg);
  46. tmp |= bits;
  47. writel(tmp, reg);
  48. }
  49. void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
  50. u32 val, u32 mask)
  51. {
  52. void __iomem *reg = hdmi_phy->regs + offset;
  53. u32 tmp;
  54. tmp = readl(reg);
  55. tmp = (tmp & ~mask) | (val & mask);
  56. writel(tmp, reg);
  57. }
  58. inline struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw)
  59. {
  60. return container_of(hw, struct mtk_hdmi_phy, pll_hw);
  61. }
  62. static int mtk_hdmi_phy_power_on(struct phy *phy)
  63. {
  64. struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
  65. int ret;
  66. ret = clk_prepare_enable(hdmi_phy->pll);
  67. if (ret < 0)
  68. return ret;
  69. hdmi_phy->conf->hdmi_phy_enable_tmds(hdmi_phy);
  70. return 0;
  71. }
  72. static int mtk_hdmi_phy_power_off(struct phy *phy)
  73. {
  74. struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
  75. hdmi_phy->conf->hdmi_phy_disable_tmds(hdmi_phy);
  76. clk_disable_unprepare(hdmi_phy->pll);
  77. return 0;
  78. }
  79. static const struct phy_ops *
  80. mtk_hdmi_phy_dev_get_ops(const struct mtk_hdmi_phy *hdmi_phy)
  81. {
  82. if (hdmi_phy && hdmi_phy->conf &&
  83. hdmi_phy->conf->hdmi_phy_enable_tmds &&
  84. hdmi_phy->conf->hdmi_phy_disable_tmds)
  85. return &mtk_hdmi_phy_dev_ops;
  86. dev_err(hdmi_phy->dev, "Failed to get dev ops of phy\n");
  87. return NULL;
  88. }
  89. static void mtk_hdmi_phy_clk_get_ops(struct mtk_hdmi_phy *hdmi_phy,
  90. const struct clk_ops **ops)
  91. {
  92. if (hdmi_phy && hdmi_phy->conf && hdmi_phy->conf->hdmi_phy_clk_ops)
  93. *ops = hdmi_phy->conf->hdmi_phy_clk_ops;
  94. else
  95. dev_err(hdmi_phy->dev, "Failed to get clk ops of phy\n");
  96. }
  97. static int mtk_hdmi_phy_probe(struct platform_device *pdev)
  98. {
  99. struct device *dev = &pdev->dev;
  100. struct mtk_hdmi_phy *hdmi_phy;
  101. struct resource *mem;
  102. struct clk *ref_clk;
  103. const char *ref_clk_name;
  104. struct clk_init_data clk_init = {
  105. .num_parents = 1,
  106. .parent_names = (const char * const *)&ref_clk_name,
  107. .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
  108. };
  109. struct phy *phy;
  110. struct phy_provider *phy_provider;
  111. int ret;
  112. hdmi_phy = devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL);
  113. if (!hdmi_phy)
  114. return -ENOMEM;
  115. mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  116. hdmi_phy->regs = devm_ioremap_resource(dev, mem);
  117. if (IS_ERR(hdmi_phy->regs)) {
  118. ret = PTR_ERR(hdmi_phy->regs);
  119. dev_err(dev, "Failed to get memory resource: %d\n", ret);
  120. return ret;
  121. }
  122. ref_clk = devm_clk_get(dev, "pll_ref");
  123. if (IS_ERR(ref_clk)) {
  124. ret = PTR_ERR(ref_clk);
  125. dev_err(&pdev->dev, "Failed to get PLL reference clock: %d\n",
  126. ret);
  127. return ret;
  128. }
  129. ref_clk_name = __clk_get_name(ref_clk);
  130. ret = of_property_read_string(dev->of_node, "clock-output-names",
  131. &clk_init.name);
  132. if (ret < 0) {
  133. dev_err(dev, "Failed to read clock-output-names: %d\n", ret);
  134. return ret;
  135. }
  136. hdmi_phy->dev = dev;
  137. hdmi_phy->conf =
  138. (struct mtk_hdmi_phy_conf *)of_device_get_match_data(dev);
  139. mtk_hdmi_phy_clk_get_ops(hdmi_phy, &clk_init.ops);
  140. hdmi_phy->pll_hw.init = &clk_init;
  141. hdmi_phy->pll = devm_clk_register(dev, &hdmi_phy->pll_hw);
  142. if (IS_ERR(hdmi_phy->pll)) {
  143. ret = PTR_ERR(hdmi_phy->pll);
  144. dev_err(dev, "Failed to register PLL: %d\n", ret);
  145. return ret;
  146. }
  147. ret = of_property_read_u32(dev->of_node, "mediatek,ibias",
  148. &hdmi_phy->ibias);
  149. if (ret < 0) {
  150. dev_err(&pdev->dev, "Failed to get ibias: %d\n", ret);
  151. return ret;
  152. }
  153. ret = of_property_read_u32(dev->of_node, "mediatek,ibias_up",
  154. &hdmi_phy->ibias_up);
  155. if (ret < 0) {
  156. dev_err(&pdev->dev, "Failed to get ibias up: %d\n", ret);
  157. return ret;
  158. }
  159. dev_info(dev, "Using default TX DRV impedance: 4.2k/36\n");
  160. hdmi_phy->drv_imp_clk = 0x30;
  161. hdmi_phy->drv_imp_d2 = 0x30;
  162. hdmi_phy->drv_imp_d1 = 0x30;
  163. hdmi_phy->drv_imp_d0 = 0x30;
  164. phy = devm_phy_create(dev, NULL, mtk_hdmi_phy_dev_get_ops(hdmi_phy));
  165. if (IS_ERR(phy)) {
  166. dev_err(dev, "Failed to create HDMI PHY\n");
  167. return PTR_ERR(phy);
  168. }
  169. phy_set_drvdata(phy, hdmi_phy);
  170. phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
  171. if (IS_ERR(phy_provider)) {
  172. dev_err(dev, "Failed to register HDMI PHY\n");
  173. return PTR_ERR(phy_provider);
  174. }
  175. return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
  176. hdmi_phy->pll);
  177. }
  178. static const struct of_device_id mtk_hdmi_phy_match[] = {
  179. { .compatible = "mediatek,mt2701-hdmi-phy",
  180. .data = &mtk_hdmi_phy_2701_conf,
  181. },
  182. { .compatible = "mediatek,mt8173-hdmi-phy",
  183. .data = &mtk_hdmi_phy_8173_conf,
  184. },
  185. {},
  186. };
  187. struct platform_driver mtk_hdmi_phy_driver = {
  188. .probe = mtk_hdmi_phy_probe,
  189. .driver = {
  190. .name = "mediatek-hdmi-phy",
  191. .of_match_table = mtk_hdmi_phy_match,
  192. },
  193. };
  194. MODULE_DESCRIPTION("MediaTek HDMI PHY Driver");
  195. MODULE_LICENSE("GPL v2");