ehci-ppc-of.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. // SPDX-License-Identifier: GPL-1.0+
  2. /*
  3. * EHCI HCD (Host Controller Driver) for USB.
  4. *
  5. * Bus Glue for PPC On-Chip EHCI driver on the of_platform bus
  6. * Tested on AMCC PPC 440EPx
  7. *
  8. * Valentine Barshak <vbarshak@ru.mvista.com>
  9. *
  10. * Based on "ehci-ppc-soc.c" by Stefan Roese <sr@denx.de>
  11. * and "ohci-ppc-of.c" by Sylvain Munaut <tnt@246tNt.com>
  12. *
  13. * This file is licenced under the GPL.
  14. */
  15. #include <linux/err.h>
  16. #include <linux/signal.h>
  17. #include <linux/of.h>
  18. #include <linux/of_address.h>
  19. #include <linux/of_irq.h>
  20. #include <linux/of_platform.h>
  21. static const struct hc_driver ehci_ppc_of_hc_driver = {
  22. .description = hcd_name,
  23. .product_desc = "OF EHCI",
  24. .hcd_priv_size = sizeof(struct ehci_hcd),
  25. /*
  26. * generic hardware linkage
  27. */
  28. .irq = ehci_irq,
  29. .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH,
  30. /*
  31. * basic lifecycle operations
  32. */
  33. .reset = ehci_setup,
  34. .start = ehci_run,
  35. .stop = ehci_stop,
  36. .shutdown = ehci_shutdown,
  37. /*
  38. * managing i/o requests and associated device resources
  39. */
  40. .urb_enqueue = ehci_urb_enqueue,
  41. .urb_dequeue = ehci_urb_dequeue,
  42. .endpoint_disable = ehci_endpoint_disable,
  43. .endpoint_reset = ehci_endpoint_reset,
  44. /*
  45. * scheduling support
  46. */
  47. .get_frame_number = ehci_get_frame,
  48. /*
  49. * root hub support
  50. */
  51. .hub_status_data = ehci_hub_status_data,
  52. .hub_control = ehci_hub_control,
  53. #ifdef CONFIG_PM
  54. .bus_suspend = ehci_bus_suspend,
  55. .bus_resume = ehci_bus_resume,
  56. #endif
  57. .relinquish_port = ehci_relinquish_port,
  58. .port_handed_over = ehci_port_handed_over,
  59. .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
  60. };
  61. /*
  62. * 440EPx Errata USBH_3
  63. * Fix: Enable Break Memory Transfer (BMT) in INSNREG3
  64. */
  65. #define PPC440EPX_EHCI0_INSREG_BMT (0x1 << 0)
  66. static int
  67. ppc44x_enable_bmt(struct device_node *dn)
  68. {
  69. __iomem u32 *insreg_virt;
  70. insreg_virt = of_iomap(dn, 1);
  71. if (!insreg_virt)
  72. return -EINVAL;
  73. out_be32(insreg_virt + 3, PPC440EPX_EHCI0_INSREG_BMT);
  74. iounmap(insreg_virt);
  75. return 0;
  76. }
  77. static int ehci_hcd_ppc_of_probe(struct platform_device *op)
  78. {
  79. struct device_node *dn = op->dev.of_node;
  80. struct usb_hcd *hcd;
  81. struct ehci_hcd *ehci = NULL;
  82. struct resource res;
  83. int irq;
  84. int rv;
  85. struct device_node *np;
  86. if (usb_disabled())
  87. return -ENODEV;
  88. dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n");
  89. rv = of_address_to_resource(dn, 0, &res);
  90. if (rv)
  91. return rv;
  92. hcd = usb_create_hcd(&ehci_ppc_of_hc_driver, &op->dev, "PPC-OF USB");
  93. if (!hcd)
  94. return -ENOMEM;
  95. hcd->rsrc_start = res.start;
  96. hcd->rsrc_len = resource_size(&res);
  97. irq = irq_of_parse_and_map(dn, 0);
  98. if (irq == NO_IRQ) {
  99. dev_err(&op->dev, "%s: irq_of_parse_and_map failed\n",
  100. __FILE__);
  101. rv = -EBUSY;
  102. goto err_irq;
  103. }
  104. hcd->regs = devm_ioremap_resource(&op->dev, &res);
  105. if (IS_ERR(hcd->regs)) {
  106. rv = PTR_ERR(hcd->regs);
  107. goto err_ioremap;
  108. }
  109. ehci = hcd_to_ehci(hcd);
  110. np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx");
  111. if (np != NULL) {
  112. /* claim we really affected by usb23 erratum */
  113. if (!of_address_to_resource(np, 0, &res))
  114. ehci->ohci_hcctrl_reg =
  115. devm_ioremap(&op->dev,
  116. res.start + OHCI_HCCTRL_OFFSET,
  117. OHCI_HCCTRL_LEN);
  118. else
  119. pr_debug("%s: no ohci offset in fdt\n", __FILE__);
  120. if (!ehci->ohci_hcctrl_reg) {
  121. pr_debug("%s: ioremap for ohci hcctrl failed\n", __FILE__);
  122. } else {
  123. ehci->has_amcc_usb23 = 1;
  124. }
  125. }
  126. if (of_get_property(dn, "big-endian", NULL)) {
  127. ehci->big_endian_mmio = 1;
  128. ehci->big_endian_desc = 1;
  129. }
  130. if (of_get_property(dn, "big-endian-regs", NULL))
  131. ehci->big_endian_mmio = 1;
  132. if (of_get_property(dn, "big-endian-desc", NULL))
  133. ehci->big_endian_desc = 1;
  134. ehci->caps = hcd->regs;
  135. if (of_device_is_compatible(dn, "ibm,usb-ehci-440epx")) {
  136. rv = ppc44x_enable_bmt(dn);
  137. ehci_dbg(ehci, "Break Memory Transfer (BMT) is %senabled!\n",
  138. rv ? "NOT ": "");
  139. }
  140. rv = usb_add_hcd(hcd, irq, 0);
  141. if (rv)
  142. goto err_ioremap;
  143. device_wakeup_enable(hcd->self.controller);
  144. return 0;
  145. err_ioremap:
  146. irq_dispose_mapping(irq);
  147. err_irq:
  148. usb_put_hcd(hcd);
  149. return rv;
  150. }
  151. static int ehci_hcd_ppc_of_remove(struct platform_device *op)
  152. {
  153. struct usb_hcd *hcd = platform_get_drvdata(op);
  154. struct ehci_hcd *ehci = hcd_to_ehci(hcd);
  155. struct device_node *np;
  156. struct resource res;
  157. dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n");
  158. usb_remove_hcd(hcd);
  159. irq_dispose_mapping(hcd->irq);
  160. /* use request_mem_region to test if the ohci driver is loaded. if so
  161. * ensure the ohci core is operational.
  162. */
  163. if (ehci->has_amcc_usb23) {
  164. np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx");
  165. if (np != NULL) {
  166. if (!of_address_to_resource(np, 0, &res))
  167. if (!request_mem_region(res.start,
  168. 0x4, hcd_name))
  169. set_ohci_hcfs(ehci, 1);
  170. else
  171. release_mem_region(res.start, 0x4);
  172. else
  173. pr_debug("%s: no ohci offset in fdt\n", __FILE__);
  174. of_node_put(np);
  175. }
  176. }
  177. usb_put_hcd(hcd);
  178. return 0;
  179. }
  180. static const struct of_device_id ehci_hcd_ppc_of_match[] = {
  181. {
  182. .compatible = "usb-ehci",
  183. },
  184. {},
  185. };
  186. MODULE_DEVICE_TABLE(of, ehci_hcd_ppc_of_match);
  187. static struct platform_driver ehci_hcd_ppc_of_driver = {
  188. .probe = ehci_hcd_ppc_of_probe,
  189. .remove = ehci_hcd_ppc_of_remove,
  190. .shutdown = usb_hcd_platform_shutdown,
  191. .driver = {
  192. .name = "ppc-of-ehci",
  193. .of_match_table = ehci_hcd_ppc_of_match,
  194. },
  195. };