phy-qcom-ipq4019-usb.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2019 Sartura Ltd.
  4. *
  5. * Author: Robert Marko <robert.marko@sartura.hr>
  6. *
  7. * Based on Linux driver
  8. */
  9. #include <clk.h>
  10. #include <common.h>
  11. #include <dm.h>
  12. #include <generic-phy.h>
  13. #include <log.h>
  14. #include <reset.h>
  15. #include <asm/io.h>
  16. #include <linux/delay.h>
  17. struct ipq4019_usb_phy {
  18. phys_addr_t base;
  19. struct reset_ctl por_rst;
  20. struct reset_ctl srif_rst;
  21. };
  22. static int ipq4019_ss_phy_power_off(struct phy *_phy)
  23. {
  24. struct ipq4019_usb_phy *phy = dev_get_priv(_phy->dev);
  25. reset_assert(&phy->por_rst);
  26. mdelay(10);
  27. return 0;
  28. }
  29. static int ipq4019_ss_phy_power_on(struct phy *_phy)
  30. {
  31. struct ipq4019_usb_phy *phy = dev_get_priv(_phy->dev);
  32. ipq4019_ss_phy_power_off(_phy);
  33. reset_deassert(&phy->por_rst);
  34. return 0;
  35. }
  36. static struct phy_ops ipq4019_usb_ss_phy_ops = {
  37. .power_on = ipq4019_ss_phy_power_on,
  38. .power_off = ipq4019_ss_phy_power_off,
  39. };
  40. static int ipq4019_usb_ss_phy_probe(struct udevice *dev)
  41. {
  42. struct ipq4019_usb_phy *phy = dev_get_priv(dev);
  43. int ret;
  44. phy->base = dev_read_addr(dev);
  45. if (phy->base == FDT_ADDR_T_NONE)
  46. return -EINVAL;
  47. ret = reset_get_by_name(dev, "por_rst", &phy->por_rst);
  48. if (ret)
  49. return ret;
  50. return 0;
  51. }
  52. static const struct udevice_id ipq4019_usb_ss_phy_ids[] = {
  53. { .compatible = "qcom,usb-ss-ipq4019-phy" },
  54. { }
  55. };
  56. U_BOOT_DRIVER(ipq4019_usb_ss_phy) = {
  57. .name = "ipq4019-usb-ss-phy",
  58. .id = UCLASS_PHY,
  59. .of_match = ipq4019_usb_ss_phy_ids,
  60. .ops = &ipq4019_usb_ss_phy_ops,
  61. .probe = ipq4019_usb_ss_phy_probe,
  62. .priv_auto_alloc_size = sizeof(struct ipq4019_usb_phy),
  63. };
  64. static int ipq4019_hs_phy_power_off(struct phy *_phy)
  65. {
  66. struct ipq4019_usb_phy *phy = dev_get_priv(_phy->dev);
  67. reset_assert(&phy->por_rst);
  68. mdelay(10);
  69. reset_assert(&phy->srif_rst);
  70. mdelay(10);
  71. return 0;
  72. }
  73. static int ipq4019_hs_phy_power_on(struct phy *_phy)
  74. {
  75. struct ipq4019_usb_phy *phy = dev_get_priv(_phy->dev);
  76. ipq4019_hs_phy_power_off(_phy);
  77. reset_deassert(&phy->srif_rst);
  78. mdelay(10);
  79. reset_deassert(&phy->por_rst);
  80. return 0;
  81. }
  82. static struct phy_ops ipq4019_usb_hs_phy_ops = {
  83. .power_on = ipq4019_hs_phy_power_on,
  84. .power_off = ipq4019_hs_phy_power_off,
  85. };
  86. static int ipq4019_usb_hs_phy_probe(struct udevice *dev)
  87. {
  88. struct ipq4019_usb_phy *phy = dev_get_priv(dev);
  89. int ret;
  90. phy->base = dev_read_addr(dev);
  91. if (phy->base == FDT_ADDR_T_NONE)
  92. return -EINVAL;
  93. ret = reset_get_by_name(dev, "por_rst", &phy->por_rst);
  94. if (ret)
  95. return ret;
  96. ret = reset_get_by_name(dev, "srif_rst", &phy->srif_rst);
  97. if (ret)
  98. return ret;
  99. return 0;
  100. }
  101. static const struct udevice_id ipq4019_usb_hs_phy_ids[] = {
  102. { .compatible = "qcom,usb-hs-ipq4019-phy" },
  103. { }
  104. };
  105. U_BOOT_DRIVER(ipq4019_usb_hs_phy) = {
  106. .name = "ipq4019-usb-hs-phy",
  107. .id = UCLASS_PHY,
  108. .of_match = ipq4019_usb_hs_phy_ids,
  109. .ops = &ipq4019_usb_hs_phy_ops,
  110. .probe = ipq4019_usb_hs_phy_probe,
  111. .priv_auto_alloc_size = sizeof(struct ipq4019_usb_phy),
  112. };