cdnsp-pci.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Cadence PCI Glue driver.
  4. *
  5. * Copyright (C) 2019 Cadence.
  6. *
  7. * Author: Pawel Laszczak <[email protected]>
  8. *
  9. */
  10. #include <linux/platform_device.h>
  11. #include <linux/dma-mapping.h>
  12. #include <linux/kernel.h>
  13. #include <linux/module.h>
  14. #include <linux/slab.h>
  15. #include <linux/pci.h>
  16. #include "core.h"
  17. #include "gadget-export.h"
  18. #define PCI_BAR_HOST 0
  19. #define PCI_BAR_OTG 0
  20. #define PCI_BAR_DEV 2
  21. #define PCI_DEV_FN_HOST_DEVICE 0
  22. #define PCI_DEV_FN_OTG 1
  23. #define PCI_DRIVER_NAME "cdns-pci-usbssp"
  24. #define PLAT_DRIVER_NAME "cdns-usbssp"
  25. #define CDNS_VENDOR_ID 0x17cd
  26. #define CDNS_DEVICE_ID 0x0200
  27. #define CDNS_DRD_ID 0x0100
  28. #define CDNS_DRD_IF (PCI_CLASS_SERIAL_USB << 8 | 0x80)
  29. static struct pci_dev *cdnsp_get_second_fun(struct pci_dev *pdev)
  30. {
  31. /*
  32. * Gets the second function.
  33. * Platform has two function. The fist keeps resources for
  34. * Host/Device while the secon keeps resources for DRD/OTG.
  35. */
  36. if (pdev->device == CDNS_DEVICE_ID)
  37. return pci_get_device(pdev->vendor, CDNS_DRD_ID, NULL);
  38. else if (pdev->device == CDNS_DRD_ID)
  39. return pci_get_device(pdev->vendor, CDNS_DEVICE_ID, NULL);
  40. return NULL;
  41. }
  42. static int cdnsp_pci_probe(struct pci_dev *pdev,
  43. const struct pci_device_id *id)
  44. {
  45. struct device *dev = &pdev->dev;
  46. struct pci_dev *func;
  47. struct resource *res;
  48. struct cdns *cdnsp;
  49. int ret;
  50. /*
  51. * For GADGET/HOST PCI (devfn) function number is 0,
  52. * for OTG PCI (devfn) function number is 1.
  53. */
  54. if (!id || (pdev->devfn != PCI_DEV_FN_HOST_DEVICE &&
  55. pdev->devfn != PCI_DEV_FN_OTG))
  56. return -EINVAL;
  57. func = cdnsp_get_second_fun(pdev);
  58. if (!func)
  59. return -EINVAL;
  60. if (func->class == PCI_CLASS_SERIAL_USB_XHCI ||
  61. pdev->class == PCI_CLASS_SERIAL_USB_XHCI) {
  62. ret = -EINVAL;
  63. goto put_pci;
  64. }
  65. ret = pcim_enable_device(pdev);
  66. if (ret) {
  67. dev_err(&pdev->dev, "Enabling PCI device has failed %d\n", ret);
  68. goto put_pci;
  69. }
  70. pci_set_master(pdev);
  71. if (pci_is_enabled(func)) {
  72. cdnsp = pci_get_drvdata(func);
  73. } else {
  74. cdnsp = kzalloc(sizeof(*cdnsp), GFP_KERNEL);
  75. if (!cdnsp) {
  76. ret = -ENOMEM;
  77. goto disable_pci;
  78. }
  79. }
  80. /* For GADGET device function number is 0. */
  81. if (pdev->devfn == 0) {
  82. resource_size_t rsrc_start, rsrc_len;
  83. /* Function 0: host(BAR_0) + device(BAR_1).*/
  84. dev_dbg(dev, "Initialize resources\n");
  85. rsrc_start = pci_resource_start(pdev, PCI_BAR_DEV);
  86. rsrc_len = pci_resource_len(pdev, PCI_BAR_DEV);
  87. res = devm_request_mem_region(dev, rsrc_start, rsrc_len, "dev");
  88. if (!res) {
  89. dev_dbg(dev, "controller already in use\n");
  90. ret = -EBUSY;
  91. goto free_cdnsp;
  92. }
  93. cdnsp->dev_regs = devm_ioremap(dev, rsrc_start, rsrc_len);
  94. if (!cdnsp->dev_regs) {
  95. dev_dbg(dev, "error mapping memory\n");
  96. ret = -EFAULT;
  97. goto free_cdnsp;
  98. }
  99. cdnsp->dev_irq = pdev->irq;
  100. dev_dbg(dev, "USBSS-DEV physical base addr: %pa\n",
  101. &rsrc_start);
  102. res = &cdnsp->xhci_res[0];
  103. res->start = pci_resource_start(pdev, PCI_BAR_HOST);
  104. res->end = pci_resource_end(pdev, PCI_BAR_HOST);
  105. res->name = "xhci";
  106. res->flags = IORESOURCE_MEM;
  107. dev_dbg(dev, "USBSS-XHCI physical base addr: %pa\n",
  108. &res->start);
  109. /* Interrupt for XHCI, */
  110. res = &cdnsp->xhci_res[1];
  111. res->start = pdev->irq;
  112. res->name = "host";
  113. res->flags = IORESOURCE_IRQ;
  114. } else {
  115. res = &cdnsp->otg_res;
  116. res->start = pci_resource_start(pdev, PCI_BAR_OTG);
  117. res->end = pci_resource_end(pdev, PCI_BAR_OTG);
  118. res->name = "otg";
  119. res->flags = IORESOURCE_MEM;
  120. dev_dbg(dev, "CDNSP-DRD physical base addr: %pa\n",
  121. &res->start);
  122. /* Interrupt for OTG/DRD. */
  123. cdnsp->otg_irq = pdev->irq;
  124. }
  125. if (pci_is_enabled(func)) {
  126. cdnsp->dev = dev;
  127. cdnsp->gadget_init = cdnsp_gadget_init;
  128. ret = cdns_init(cdnsp);
  129. if (ret)
  130. goto free_cdnsp;
  131. }
  132. pci_set_drvdata(pdev, cdnsp);
  133. device_wakeup_enable(&pdev->dev);
  134. if (pci_dev_run_wake(pdev))
  135. pm_runtime_put_noidle(&pdev->dev);
  136. return 0;
  137. free_cdnsp:
  138. if (!pci_is_enabled(func))
  139. kfree(cdnsp);
  140. disable_pci:
  141. pci_disable_device(pdev);
  142. put_pci:
  143. pci_dev_put(func);
  144. return ret;
  145. }
  146. static void cdnsp_pci_remove(struct pci_dev *pdev)
  147. {
  148. struct cdns *cdnsp;
  149. struct pci_dev *func;
  150. func = cdnsp_get_second_fun(pdev);
  151. cdnsp = (struct cdns *)pci_get_drvdata(pdev);
  152. if (pci_dev_run_wake(pdev))
  153. pm_runtime_get_noresume(&pdev->dev);
  154. if (!pci_is_enabled(func)) {
  155. kfree(cdnsp);
  156. goto pci_put;
  157. }
  158. cdns_remove(cdnsp);
  159. pci_put:
  160. pci_dev_put(func);
  161. }
  162. static int __maybe_unused cdnsp_pci_suspend(struct device *dev)
  163. {
  164. struct cdns *cdns = dev_get_drvdata(dev);
  165. return cdns_suspend(cdns);
  166. }
  167. static int __maybe_unused cdnsp_pci_resume(struct device *dev)
  168. {
  169. struct cdns *cdns = dev_get_drvdata(dev);
  170. unsigned long flags;
  171. int ret;
  172. spin_lock_irqsave(&cdns->lock, flags);
  173. ret = cdns_resume(cdns);
  174. spin_unlock_irqrestore(&cdns->lock, flags);
  175. cdns_set_active(cdns, 1);
  176. return ret;
  177. }
  178. static const struct dev_pm_ops cdnsp_pci_pm_ops = {
  179. SET_SYSTEM_SLEEP_PM_OPS(cdnsp_pci_suspend, cdnsp_pci_resume)
  180. };
  181. static const struct pci_device_id cdnsp_pci_ids[] = {
  182. { PCI_VENDOR_ID_CDNS, CDNS_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
  183. PCI_CLASS_SERIAL_USB_DEVICE, PCI_ANY_ID },
  184. { PCI_VENDOR_ID_CDNS, CDNS_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
  185. CDNS_DRD_IF, PCI_ANY_ID },
  186. { PCI_VENDOR_ID_CDNS, CDNS_DRD_ID, PCI_ANY_ID, PCI_ANY_ID,
  187. CDNS_DRD_IF, PCI_ANY_ID },
  188. { 0, }
  189. };
  190. static struct pci_driver cdnsp_pci_driver = {
  191. .name = "cdnsp-pci",
  192. .id_table = &cdnsp_pci_ids[0],
  193. .probe = cdnsp_pci_probe,
  194. .remove = cdnsp_pci_remove,
  195. .driver = {
  196. .pm = &cdnsp_pci_pm_ops,
  197. }
  198. };
  199. module_pci_driver(cdnsp_pci_driver);
  200. MODULE_DEVICE_TABLE(pci, cdnsp_pci_ids);
  201. MODULE_ALIAS("pci:cdnsp");
  202. MODULE_AUTHOR("Pawel Laszczak <[email protected]>");
  203. MODULE_LICENSE("GPL v2");
  204. MODULE_DESCRIPTION("Cadence CDNSP PCI driver");