ci13xxx_pci.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * ci13xxx_pci.c - MIPS USB IP core family device controller
  3. *
  4. * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
  5. *
  6. * Author: David Lopo
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. */
  12. #include <linux/module.h>
  13. #include <linux/pci.h>
  14. #include "ci13xxx_udc.c"
  15. /* driver name */
  16. #define UDC_DRIVER_NAME "ci13xxx_pci"
  17. /******************************************************************************
  18. * PCI block
  19. *****************************************************************************/
  20. /**
  21. * ci13xxx_pci_irq: interrut handler
  22. * @irq: irq number
  23. * @pdev: USB Device Controller interrupt source
  24. *
  25. * This function returns IRQ_HANDLED if the IRQ has been handled
  26. * This is an ISR don't trace, use attribute interface instead
  27. */
  28. static irqreturn_t ci13xxx_pci_irq(int irq, void *pdev)
  29. {
  30. if (irq == 0) {
  31. dev_err(&((struct pci_dev *)pdev)->dev, "Invalid IRQ0 usage!");
  32. return IRQ_HANDLED;
  33. }
  34. return udc_irq();
  35. }
  36. static struct ci13xxx_udc_driver ci13xxx_pci_udc_driver = {
  37. .name = UDC_DRIVER_NAME,
  38. };
  39. /**
  40. * ci13xxx_pci_probe: PCI probe
  41. * @pdev: USB device controller being probed
  42. * @id: PCI hotplug ID connecting controller to UDC framework
  43. *
  44. * This function returns an error code
  45. * Allocates basic PCI resources for this USB device controller, and then
  46. * invokes the udc_probe() method to start the UDC associated with it
  47. */
  48. static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
  49. const struct pci_device_id *id)
  50. {
  51. void __iomem *regs = NULL;
  52. int retval = 0;
  53. if (id == NULL)
  54. return -EINVAL;
  55. retval = pci_enable_device(pdev);
  56. if (retval)
  57. goto done;
  58. if (!pdev->irq) {
  59. dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!");
  60. retval = -ENODEV;
  61. goto disable_device;
  62. }
  63. retval = pci_request_regions(pdev, UDC_DRIVER_NAME);
  64. if (retval)
  65. goto disable_device;
  66. /* BAR 0 holds all the registers */
  67. regs = pci_iomap(pdev, 0, 0);
  68. if (!regs) {
  69. dev_err(&pdev->dev, "Error mapping memory!");
  70. retval = -EFAULT;
  71. goto release_regions;
  72. }
  73. pci_set_drvdata(pdev, (__force void *)regs);
  74. pci_set_master(pdev);
  75. pci_try_set_mwi(pdev);
  76. retval = udc_probe(&ci13xxx_pci_udc_driver, &pdev->dev, regs);
  77. if (retval)
  78. goto iounmap;
  79. /* our device does not have MSI capability */
  80. retval = request_irq(pdev->irq, ci13xxx_pci_irq, IRQF_SHARED,
  81. UDC_DRIVER_NAME, pdev);
  82. if (retval)
  83. goto gadget_remove;
  84. return 0;
  85. gadget_remove:
  86. udc_remove();
  87. iounmap:
  88. pci_iounmap(pdev, regs);
  89. release_regions:
  90. pci_release_regions(pdev);
  91. disable_device:
  92. pci_disable_device(pdev);
  93. done:
  94. return retval;
  95. }
  96. /**
  97. * ci13xxx_pci_remove: PCI remove
  98. * @pdev: USB Device Controller being removed
  99. *
  100. * Reverses the effect of ci13xxx_pci_probe(),
  101. * first invoking the udc_remove() and then releases
  102. * all PCI resources allocated for this USB device controller
  103. */
  104. static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
  105. {
  106. free_irq(pdev->irq, pdev);
  107. udc_remove();
  108. pci_iounmap(pdev, (__force void __iomem *)pci_get_drvdata(pdev));
  109. pci_release_regions(pdev);
  110. pci_disable_device(pdev);
  111. }
  112. /**
  113. * PCI device table
  114. * PCI device structure
  115. *
  116. * Check "pci.h" for details
  117. */
  118. static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = {
  119. { PCI_DEVICE(0x153F, 0x1004) },
  120. { PCI_DEVICE(0x153F, 0x1006) },
  121. { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ }
  122. };
  123. MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table);
  124. static struct pci_driver ci13xxx_pci_driver = {
  125. .name = UDC_DRIVER_NAME,
  126. .id_table = ci13xxx_pci_id_table,
  127. .probe = ci13xxx_pci_probe,
  128. .remove = __devexit_p(ci13xxx_pci_remove),
  129. };
  130. /**
  131. * ci13xxx_pci_init: module init
  132. *
  133. * Driver load
  134. */
  135. static int __init ci13xxx_pci_init(void)
  136. {
  137. return pci_register_driver(&ci13xxx_pci_driver);
  138. }
  139. module_init(ci13xxx_pci_init);
  140. /**
  141. * ci13xxx_pci_exit: module exit
  142. *
  143. * Driver unload
  144. */
  145. static void __exit ci13xxx_pci_exit(void)
  146. {
  147. pci_unregister_driver(&ci13xxx_pci_driver);
  148. }
  149. module_exit(ci13xxx_pci_exit);
  150. MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>");
  151. MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller");
  152. MODULE_LICENSE("GPL");
  153. MODULE_VERSION("June 2008");