phy-fsl-imx8mq-usb.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /* Copyright (c) 2017 NXP. */
  3. #include <linux/bitfield.h>
  4. #include <linux/clk.h>
  5. #include <linux/delay.h>
  6. #include <linux/io.h>
  7. #include <linux/module.h>
  8. #include <linux/of_platform.h>
  9. #include <linux/phy/phy.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/regulator/consumer.h>
  12. #define PHY_CTRL0 0x0
  13. #define PHY_CTRL0_REF_SSP_EN BIT(2)
  14. #define PHY_CTRL0_FSEL_MASK GENMASK(10, 5)
  15. #define PHY_CTRL0_FSEL_24M 0x2a
  16. #define PHY_CTRL1 0x4
  17. #define PHY_CTRL1_RESET BIT(0)
  18. #define PHY_CTRL1_COMMONONN BIT(1)
  19. #define PHY_CTRL1_ATERESET BIT(3)
  20. #define PHY_CTRL1_VDATSRCENB0 BIT(19)
  21. #define PHY_CTRL1_VDATDETENB0 BIT(20)
  22. #define PHY_CTRL2 0x8
  23. #define PHY_CTRL2_TXENABLEN0 BIT(8)
  24. #define PHY_CTRL2_OTG_DISABLE BIT(9)
  25. #define PHY_CTRL6 0x18
  26. #define PHY_CTRL6_ALT_CLK_EN BIT(1)
  27. #define PHY_CTRL6_ALT_CLK_SEL BIT(0)
  28. struct imx8mq_usb_phy {
  29. struct phy *phy;
  30. struct clk *clk;
  31. void __iomem *base;
  32. struct regulator *vbus;
  33. };
  34. static int imx8mq_usb_phy_init(struct phy *phy)
  35. {
  36. struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy);
  37. u32 value;
  38. value = readl(imx_phy->base + PHY_CTRL1);
  39. value &= ~(PHY_CTRL1_VDATSRCENB0 | PHY_CTRL1_VDATDETENB0 |
  40. PHY_CTRL1_COMMONONN);
  41. value |= PHY_CTRL1_RESET | PHY_CTRL1_ATERESET;
  42. writel(value, imx_phy->base + PHY_CTRL1);
  43. value = readl(imx_phy->base + PHY_CTRL0);
  44. value |= PHY_CTRL0_REF_SSP_EN;
  45. writel(value, imx_phy->base + PHY_CTRL0);
  46. value = readl(imx_phy->base + PHY_CTRL2);
  47. value |= PHY_CTRL2_TXENABLEN0;
  48. writel(value, imx_phy->base + PHY_CTRL2);
  49. value = readl(imx_phy->base + PHY_CTRL1);
  50. value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET);
  51. writel(value, imx_phy->base + PHY_CTRL1);
  52. return 0;
  53. }
  54. static int imx8mp_usb_phy_init(struct phy *phy)
  55. {
  56. struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy);
  57. u32 value;
  58. /* USB3.0 PHY signal fsel for 24M ref */
  59. value = readl(imx_phy->base + PHY_CTRL0);
  60. value &= ~PHY_CTRL0_FSEL_MASK;
  61. value |= FIELD_PREP(PHY_CTRL0_FSEL_MASK, PHY_CTRL0_FSEL_24M);
  62. writel(value, imx_phy->base + PHY_CTRL0);
  63. /* Disable alt_clk_en and use internal MPLL clocks */
  64. value = readl(imx_phy->base + PHY_CTRL6);
  65. value &= ~(PHY_CTRL6_ALT_CLK_SEL | PHY_CTRL6_ALT_CLK_EN);
  66. writel(value, imx_phy->base + PHY_CTRL6);
  67. value = readl(imx_phy->base + PHY_CTRL1);
  68. value &= ~(PHY_CTRL1_VDATSRCENB0 | PHY_CTRL1_VDATDETENB0);
  69. value |= PHY_CTRL1_RESET | PHY_CTRL1_ATERESET;
  70. writel(value, imx_phy->base + PHY_CTRL1);
  71. value = readl(imx_phy->base + PHY_CTRL0);
  72. value |= PHY_CTRL0_REF_SSP_EN;
  73. writel(value, imx_phy->base + PHY_CTRL0);
  74. value = readl(imx_phy->base + PHY_CTRL2);
  75. value |= PHY_CTRL2_TXENABLEN0 | PHY_CTRL2_OTG_DISABLE;
  76. writel(value, imx_phy->base + PHY_CTRL2);
  77. udelay(10);
  78. value = readl(imx_phy->base + PHY_CTRL1);
  79. value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET);
  80. writel(value, imx_phy->base + PHY_CTRL1);
  81. return 0;
  82. }
  83. static int imx8mq_phy_power_on(struct phy *phy)
  84. {
  85. struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy);
  86. int ret;
  87. ret = regulator_enable(imx_phy->vbus);
  88. if (ret)
  89. return ret;
  90. return clk_prepare_enable(imx_phy->clk);
  91. }
  92. static int imx8mq_phy_power_off(struct phy *phy)
  93. {
  94. struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy);
  95. clk_disable_unprepare(imx_phy->clk);
  96. regulator_disable(imx_phy->vbus);
  97. return 0;
  98. }
  99. static const struct phy_ops imx8mq_usb_phy_ops = {
  100. .init = imx8mq_usb_phy_init,
  101. .power_on = imx8mq_phy_power_on,
  102. .power_off = imx8mq_phy_power_off,
  103. .owner = THIS_MODULE,
  104. };
  105. static struct phy_ops imx8mp_usb_phy_ops = {
  106. .init = imx8mp_usb_phy_init,
  107. .power_on = imx8mq_phy_power_on,
  108. .power_off = imx8mq_phy_power_off,
  109. .owner = THIS_MODULE,
  110. };
  111. static const struct of_device_id imx8mq_usb_phy_of_match[] = {
  112. {.compatible = "fsl,imx8mq-usb-phy",
  113. .data = &imx8mq_usb_phy_ops,},
  114. {.compatible = "fsl,imx8mp-usb-phy",
  115. .data = &imx8mp_usb_phy_ops,},
  116. { }
  117. };
  118. MODULE_DEVICE_TABLE(of, imx8mq_usb_phy_of_match);
  119. static int imx8mq_usb_phy_probe(struct platform_device *pdev)
  120. {
  121. struct phy_provider *phy_provider;
  122. struct device *dev = &pdev->dev;
  123. struct imx8mq_usb_phy *imx_phy;
  124. struct resource *res;
  125. const struct phy_ops *phy_ops;
  126. imx_phy = devm_kzalloc(dev, sizeof(*imx_phy), GFP_KERNEL);
  127. if (!imx_phy)
  128. return -ENOMEM;
  129. imx_phy->clk = devm_clk_get(dev, "phy");
  130. if (IS_ERR(imx_phy->clk)) {
  131. dev_err(dev, "failed to get imx8mq usb phy clock\n");
  132. return PTR_ERR(imx_phy->clk);
  133. }
  134. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  135. imx_phy->base = devm_ioremap_resource(dev, res);
  136. if (IS_ERR(imx_phy->base))
  137. return PTR_ERR(imx_phy->base);
  138. phy_ops = of_device_get_match_data(dev);
  139. if (!phy_ops)
  140. return -EINVAL;
  141. imx_phy->phy = devm_phy_create(dev, NULL, phy_ops);
  142. if (IS_ERR(imx_phy->phy))
  143. return PTR_ERR(imx_phy->phy);
  144. imx_phy->vbus = devm_regulator_get(dev, "vbus");
  145. if (IS_ERR(imx_phy->vbus))
  146. return PTR_ERR(imx_phy->vbus);
  147. phy_set_drvdata(imx_phy->phy, imx_phy);
  148. phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
  149. return PTR_ERR_OR_ZERO(phy_provider);
  150. }
  151. static struct platform_driver imx8mq_usb_phy_driver = {
  152. .probe = imx8mq_usb_phy_probe,
  153. .driver = {
  154. .name = "imx8mq-usb-phy",
  155. .of_match_table = imx8mq_usb_phy_of_match,
  156. }
  157. };
  158. module_platform_driver(imx8mq_usb_phy_driver);
  159. MODULE_DESCRIPTION("FSL IMX8MQ USB PHY driver");
  160. MODULE_LICENSE("GPL");