phy-uniphier-usb2.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * phy-uniphier-usb2.c - PHY driver for UniPhier USB2 controller
  4. * Copyright 2015-2018 Socionext Inc.
  5. * Author:
  6. * Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
  7. */
  8. #include <linux/mfd/syscon.h>
  9. #include <linux/module.h>
  10. #include <linux/of.h>
  11. #include <linux/of_platform.h>
  12. #include <linux/phy/phy.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/regmap.h>
  15. #include <linux/regulator/consumer.h>
  16. #define SG_USBPHY1CTRL 0x500
  17. #define SG_USBPHY1CTRL2 0x504
  18. #define SG_USBPHY2CTRL 0x508
  19. #define SG_USBPHY2CTRL2 0x50c /* LD11 */
  20. #define SG_USBPHY12PLL 0x50c /* Pro4 */
  21. #define SG_USBPHY3CTRL 0x510
  22. #define SG_USBPHY3CTRL2 0x514
  23. #define SG_USBPHY4CTRL 0x518 /* Pro4 */
  24. #define SG_USBPHY4CTRL2 0x51c /* Pro4 */
  25. #define SG_USBPHY34PLL 0x51c /* Pro4 */
  26. struct uniphier_u2phy_param {
  27. u32 offset;
  28. u32 value;
  29. };
  30. struct uniphier_u2phy_soc_data {
  31. struct uniphier_u2phy_param config0;
  32. struct uniphier_u2phy_param config1;
  33. };
  34. struct uniphier_u2phy_priv {
  35. struct regmap *regmap;
  36. struct phy *phy;
  37. struct regulator *vbus;
  38. const struct uniphier_u2phy_soc_data *data;
  39. struct uniphier_u2phy_priv *next;
  40. };
  41. static int uniphier_u2phy_power_on(struct phy *phy)
  42. {
  43. struct uniphier_u2phy_priv *priv = phy_get_drvdata(phy);
  44. int ret = 0;
  45. if (priv->vbus)
  46. ret = regulator_enable(priv->vbus);
  47. return ret;
  48. }
  49. static int uniphier_u2phy_power_off(struct phy *phy)
  50. {
  51. struct uniphier_u2phy_priv *priv = phy_get_drvdata(phy);
  52. if (priv->vbus)
  53. regulator_disable(priv->vbus);
  54. return 0;
  55. }
  56. static int uniphier_u2phy_init(struct phy *phy)
  57. {
  58. struct uniphier_u2phy_priv *priv = phy_get_drvdata(phy);
  59. if (!priv->data)
  60. return 0;
  61. regmap_write(priv->regmap, priv->data->config0.offset,
  62. priv->data->config0.value);
  63. regmap_write(priv->regmap, priv->data->config1.offset,
  64. priv->data->config1.value);
  65. return 0;
  66. }
  67. static struct phy *uniphier_u2phy_xlate(struct device *dev,
  68. const struct of_phandle_args *args)
  69. {
  70. struct uniphier_u2phy_priv *priv = dev_get_drvdata(dev);
  71. while (priv && args->np != priv->phy->dev.of_node)
  72. priv = priv->next;
  73. if (!priv) {
  74. dev_err(dev, "Failed to find appropriate phy\n");
  75. return ERR_PTR(-EINVAL);
  76. }
  77. return priv->phy;
  78. }
  79. static const struct phy_ops uniphier_u2phy_ops = {
  80. .init = uniphier_u2phy_init,
  81. .power_on = uniphier_u2phy_power_on,
  82. .power_off = uniphier_u2phy_power_off,
  83. .owner = THIS_MODULE,
  84. };
  85. static int uniphier_u2phy_probe(struct platform_device *pdev)
  86. {
  87. struct device *dev = &pdev->dev;
  88. struct device_node *parent;
  89. struct uniphier_u2phy_priv *priv = NULL, *next = NULL;
  90. struct phy_provider *phy_provider;
  91. struct regmap *regmap;
  92. const struct uniphier_u2phy_soc_data *data;
  93. int ret, data_idx, ndatas;
  94. data = of_device_get_match_data(dev);
  95. if (WARN_ON(!data))
  96. return -EINVAL;
  97. /* get number of data */
  98. for (ndatas = 0; data[ndatas].config0.offset; ndatas++)
  99. ;
  100. parent = of_get_parent(dev->of_node);
  101. regmap = syscon_node_to_regmap(parent);
  102. of_node_put(parent);
  103. if (IS_ERR(regmap)) {
  104. dev_err(dev, "Failed to get regmap\n");
  105. return PTR_ERR(regmap);
  106. }
  107. for_each_child_of_node_scoped(dev->of_node, child) {
  108. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  109. if (!priv)
  110. return -ENOMEM;
  111. priv->regmap = regmap;
  112. priv->vbus = devm_regulator_get_optional(dev, "vbus");
  113. if (IS_ERR(priv->vbus)) {
  114. if (PTR_ERR(priv->vbus) == -EPROBE_DEFER)
  115. return PTR_ERR(priv->vbus);
  116. priv->vbus = NULL;
  117. }
  118. priv->phy = devm_phy_create(dev, child, &uniphier_u2phy_ops);
  119. if (IS_ERR(priv->phy)) {
  120. dev_err(dev, "Failed to create phy\n");
  121. return PTR_ERR(priv->phy);
  122. }
  123. ret = of_property_read_u32(child, "reg", &data_idx);
  124. if (ret) {
  125. dev_err(dev, "Failed to get reg property\n");
  126. return ret;
  127. }
  128. if (data_idx < ndatas)
  129. priv->data = &data[data_idx];
  130. else
  131. dev_warn(dev, "No phy configuration: %s\n",
  132. child->full_name);
  133. phy_set_drvdata(priv->phy, priv);
  134. priv->next = next;
  135. next = priv;
  136. }
  137. dev_set_drvdata(dev, priv);
  138. phy_provider = devm_of_phy_provider_register(dev,
  139. uniphier_u2phy_xlate);
  140. return PTR_ERR_OR_ZERO(phy_provider);
  141. }
  142. static const struct uniphier_u2phy_soc_data uniphier_pro4_data[] = {
  143. {
  144. .config0 = { SG_USBPHY1CTRL, 0x05142400 },
  145. .config1 = { SG_USBPHY12PLL, 0x00010010 },
  146. },
  147. {
  148. .config0 = { SG_USBPHY2CTRL, 0x05142400 },
  149. .config1 = { SG_USBPHY12PLL, 0x00010010 },
  150. },
  151. {
  152. .config0 = { SG_USBPHY3CTRL, 0x05142400 },
  153. .config1 = { SG_USBPHY34PLL, 0x00010010 },
  154. },
  155. {
  156. .config0 = { SG_USBPHY4CTRL, 0x05142400 },
  157. .config1 = { SG_USBPHY34PLL, 0x00010010 },
  158. },
  159. { /* sentinel */ }
  160. };
  161. static const struct uniphier_u2phy_soc_data uniphier_ld11_data[] = {
  162. {
  163. .config0 = { SG_USBPHY1CTRL, 0x82280000 },
  164. .config1 = { SG_USBPHY1CTRL2, 0x00000106 },
  165. },
  166. {
  167. .config0 = { SG_USBPHY2CTRL, 0x82280000 },
  168. .config1 = { SG_USBPHY2CTRL2, 0x00000106 },
  169. },
  170. {
  171. .config0 = { SG_USBPHY3CTRL, 0x82280000 },
  172. .config1 = { SG_USBPHY3CTRL2, 0x00000106 },
  173. },
  174. { /* sentinel */ }
  175. };
  176. static const struct of_device_id uniphier_u2phy_match[] = {
  177. {
  178. .compatible = "socionext,uniphier-pro4-usb2-phy",
  179. .data = &uniphier_pro4_data,
  180. },
  181. {
  182. .compatible = "socionext,uniphier-ld11-usb2-phy",
  183. .data = &uniphier_ld11_data,
  184. },
  185. { /* sentinel */ }
  186. };
  187. MODULE_DEVICE_TABLE(of, uniphier_u2phy_match);
  188. static struct platform_driver uniphier_u2phy_driver = {
  189. .probe = uniphier_u2phy_probe,
  190. .driver = {
  191. .name = "uniphier-usb2-phy",
  192. .of_match_table = uniphier_u2phy_match,
  193. },
  194. };
  195. module_platform_driver(uniphier_u2phy_driver);
  196. MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
  197. MODULE_DESCRIPTION("UniPhier PHY driver for USB2 controller");
  198. MODULE_LICENSE("GPL v2");