ohci-generic.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2015 Alexey Brodkin <abrodkin@synopsys.com>
  4. */
  5. #include <common.h>
  6. #include <clk.h>
  7. #include <dm.h>
  8. #include <dm/ofnode.h>
  9. #include <generic-phy.h>
  10. #include <reset.h>
  11. #include "ohci.h"
  12. #if !defined(CONFIG_USB_OHCI_NEW)
  13. # error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW"
  14. #endif
  15. struct generic_ohci {
  16. ohci_t ohci;
  17. struct clk *clocks; /* clock list */
  18. struct reset_ctl *resets; /* reset list */
  19. struct phy phy;
  20. int clock_count; /* number of clock in clock list */
  21. int reset_count; /* number of reset in reset list */
  22. };
  23. static int ohci_setup_phy(struct udevice *dev, int index)
  24. {
  25. struct generic_ohci *priv = dev_get_priv(dev);
  26. int ret;
  27. ret = generic_phy_get_by_index(dev, index, &priv->phy);
  28. if (ret) {
  29. if (ret != -ENOENT) {
  30. dev_err(dev, "failed to get usb phy\n");
  31. return ret;
  32. }
  33. } else {
  34. ret = generic_phy_init(&priv->phy);
  35. if (ret) {
  36. dev_err(dev, "failed to init usb phy\n");
  37. return ret;
  38. }
  39. ret = generic_phy_power_on(&priv->phy);
  40. if (ret) {
  41. dev_err(dev, "failed to power on usb phy\n");
  42. return generic_phy_exit(&priv->phy);
  43. }
  44. }
  45. return 0;
  46. }
  47. static int ohci_shutdown_phy(struct udevice *dev)
  48. {
  49. struct generic_ohci *priv = dev_get_priv(dev);
  50. int ret = 0;
  51. if (generic_phy_valid(&priv->phy)) {
  52. ret = generic_phy_power_off(&priv->phy);
  53. if (ret) {
  54. dev_err(dev, "failed to power off usb phy\n");
  55. return ret;
  56. }
  57. ret = generic_phy_exit(&priv->phy);
  58. if (ret) {
  59. dev_err(dev, "failed to power off usb phy\n");
  60. return ret;
  61. }
  62. }
  63. return 0;
  64. }
  65. static int ohci_usb_probe(struct udevice *dev)
  66. {
  67. struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
  68. struct generic_ohci *priv = dev_get_priv(dev);
  69. int i, err, ret, clock_nb, reset_nb;
  70. err = 0;
  71. priv->clock_count = 0;
  72. clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells");
  73. if (clock_nb > 0) {
  74. priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
  75. GFP_KERNEL);
  76. if (!priv->clocks)
  77. return -ENOMEM;
  78. for (i = 0; i < clock_nb; i++) {
  79. err = clk_get_by_index(dev, i, &priv->clocks[i]);
  80. if (err < 0)
  81. break;
  82. err = clk_enable(&priv->clocks[i]);
  83. if (err) {
  84. dev_err(dev, "failed to enable clock %d\n", i);
  85. clk_free(&priv->clocks[i]);
  86. goto clk_err;
  87. }
  88. priv->clock_count++;
  89. }
  90. } else if (clock_nb != -ENOENT) {
  91. dev_err(dev, "failed to get clock phandle(%d)\n", clock_nb);
  92. return clock_nb;
  93. }
  94. priv->reset_count = 0;
  95. reset_nb = dev_count_phandle_with_args(dev, "resets", "#reset-cells");
  96. if (reset_nb > 0) {
  97. priv->resets = devm_kcalloc(dev, reset_nb,
  98. sizeof(struct reset_ctl),
  99. GFP_KERNEL);
  100. if (!priv->resets)
  101. return -ENOMEM;
  102. for (i = 0; i < reset_nb; i++) {
  103. err = reset_get_by_index(dev, i, &priv->resets[i]);
  104. if (err < 0)
  105. break;
  106. err = reset_deassert(&priv->resets[i]);
  107. if (err) {
  108. dev_err(dev, "failed to deassert reset %d\n", i);
  109. reset_free(&priv->resets[i]);
  110. goto reset_err;
  111. }
  112. priv->reset_count++;
  113. }
  114. } else if (reset_nb != -ENOENT) {
  115. dev_err(dev, "failed to get reset phandle(%d)\n", reset_nb);
  116. goto clk_err;
  117. }
  118. err = ohci_setup_phy(dev, 0);
  119. if (err)
  120. goto reset_err;
  121. err = ohci_register(dev, regs);
  122. if (err)
  123. goto phy_err;
  124. return 0;
  125. phy_err:
  126. ret = ohci_shutdown_phy(dev);
  127. if (ret)
  128. dev_err(dev, "failed to shutdown usb phy\n");
  129. reset_err:
  130. ret = reset_release_all(priv->resets, priv->reset_count);
  131. if (ret)
  132. dev_err(dev, "failed to assert all resets\n");
  133. clk_err:
  134. ret = clk_release_all(priv->clocks, priv->clock_count);
  135. if (ret)
  136. dev_err(dev, "failed to disable all clocks\n");
  137. return err;
  138. }
  139. static int ohci_usb_remove(struct udevice *dev)
  140. {
  141. struct generic_ohci *priv = dev_get_priv(dev);
  142. int ret;
  143. ret = ohci_deregister(dev);
  144. if (ret)
  145. return ret;
  146. ret = ohci_shutdown_phy(dev);
  147. if (ret)
  148. return ret;
  149. ret = reset_release_all(priv->resets, priv->reset_count);
  150. if (ret)
  151. return ret;
  152. return clk_release_all(priv->clocks, priv->clock_count);
  153. }
  154. static const struct udevice_id ohci_usb_ids[] = {
  155. { .compatible = "generic-ohci" },
  156. { }
  157. };
  158. U_BOOT_DRIVER(ohci_generic) = {
  159. .name = "ohci_generic",
  160. .id = UCLASS_USB,
  161. .of_match = ohci_usb_ids,
  162. .probe = ohci_usb_probe,
  163. .remove = ohci_usb_remove,
  164. .ops = &ohci_usb_ops,
  165. .priv_auto_alloc_size = sizeof(struct generic_ohci),
  166. .flags = DM_FLAG_ALLOC_PRIV_DMA,
  167. };