phy-uniphier-usb2.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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 <[email protected]>
  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. 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, *child;
  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(dev->of_node, child) {
  108. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  109. if (!priv) {
  110. ret = -ENOMEM;
  111. goto out_put_child;
  112. }
  113. priv->regmap = regmap;
  114. priv->vbus = devm_regulator_get_optional(dev, "vbus");
  115. if (IS_ERR(priv->vbus)) {
  116. if (PTR_ERR(priv->vbus) == -EPROBE_DEFER) {
  117. ret = PTR_ERR(priv->vbus);
  118. goto out_put_child;
  119. }
  120. priv->vbus = NULL;
  121. }
  122. priv->phy = devm_phy_create(dev, child, &uniphier_u2phy_ops);
  123. if (IS_ERR(priv->phy)) {
  124. dev_err(dev, "Failed to create phy\n");
  125. ret = PTR_ERR(priv->phy);
  126. goto out_put_child;
  127. }
  128. ret = of_property_read_u32(child, "reg", &data_idx);
  129. if (ret) {
  130. dev_err(dev, "Failed to get reg property\n");
  131. goto out_put_child;
  132. }
  133. if (data_idx < ndatas)
  134. priv->data = &data[data_idx];
  135. else
  136. dev_warn(dev, "No phy configuration: %s\n",
  137. child->full_name);
  138. phy_set_drvdata(priv->phy, priv);
  139. priv->next = next;
  140. next = priv;
  141. }
  142. dev_set_drvdata(dev, priv);
  143. phy_provider = devm_of_phy_provider_register(dev,
  144. uniphier_u2phy_xlate);
  145. return PTR_ERR_OR_ZERO(phy_provider);
  146. out_put_child:
  147. of_node_put(child);
  148. return ret;
  149. }
  150. static const struct uniphier_u2phy_soc_data uniphier_pro4_data[] = {
  151. {
  152. .config0 = { SG_USBPHY1CTRL, 0x05142400 },
  153. .config1 = { SG_USBPHY12PLL, 0x00010010 },
  154. },
  155. {
  156. .config0 = { SG_USBPHY2CTRL, 0x05142400 },
  157. .config1 = { SG_USBPHY12PLL, 0x00010010 },
  158. },
  159. {
  160. .config0 = { SG_USBPHY3CTRL, 0x05142400 },
  161. .config1 = { SG_USBPHY34PLL, 0x00010010 },
  162. },
  163. {
  164. .config0 = { SG_USBPHY4CTRL, 0x05142400 },
  165. .config1 = { SG_USBPHY34PLL, 0x00010010 },
  166. },
  167. { /* sentinel */ }
  168. };
  169. static const struct uniphier_u2phy_soc_data uniphier_ld11_data[] = {
  170. {
  171. .config0 = { SG_USBPHY1CTRL, 0x82280000 },
  172. .config1 = { SG_USBPHY1CTRL2, 0x00000106 },
  173. },
  174. {
  175. .config0 = { SG_USBPHY2CTRL, 0x82280000 },
  176. .config1 = { SG_USBPHY2CTRL2, 0x00000106 },
  177. },
  178. {
  179. .config0 = { SG_USBPHY3CTRL, 0x82280000 },
  180. .config1 = { SG_USBPHY3CTRL2, 0x00000106 },
  181. },
  182. { /* sentinel */ }
  183. };
  184. static const struct of_device_id uniphier_u2phy_match[] = {
  185. {
  186. .compatible = "socionext,uniphier-pro4-usb2-phy",
  187. .data = &uniphier_pro4_data,
  188. },
  189. {
  190. .compatible = "socionext,uniphier-ld11-usb2-phy",
  191. .data = &uniphier_ld11_data,
  192. },
  193. { /* sentinel */ }
  194. };
  195. MODULE_DEVICE_TABLE(of, uniphier_u2phy_match);
  196. static struct platform_driver uniphier_u2phy_driver = {
  197. .probe = uniphier_u2phy_probe,
  198. .driver = {
  199. .name = "uniphier-usb2-phy",
  200. .of_match_table = uniphier_u2phy_match,
  201. },
  202. };
  203. module_platform_driver(uniphier_u2phy_driver);
  204. MODULE_AUTHOR("Kunihiko Hayashi <[email protected]>");
  205. MODULE_DESCRIPTION("UniPhier PHY driver for USB2 controller");
  206. MODULE_LICENSE("GPL v2");