uio_cif.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * UIO Hilscher CIF card driver
  3. *
  4. * (C) 2007 Hans J. Koch <hjk@linutronix.de>
  5. * Original code (C) 2005 Benedikt Spranger <b.spranger@linutronix.de>
  6. *
  7. * Licensed under GPL version 2 only.
  8. *
  9. */
  10. #include <linux/device.h>
  11. #include <linux/module.h>
  12. #include <linux/pci.h>
  13. #include <linux/uio_driver.h>
  14. #include <asm/io.h>
  15. #ifndef PCI_DEVICE_ID_PLX_9030
  16. #define PCI_DEVICE_ID_PLX_9030 0x9030
  17. #endif
  18. #define PLX9030_INTCSR 0x4C
  19. #define INTSCR_INT1_ENABLE 0x01
  20. #define INTSCR_INT1_STATUS 0x04
  21. #define INT1_ENABLED_AND_ACTIVE (INTSCR_INT1_ENABLE | INTSCR_INT1_STATUS)
  22. #define PCI_SUBVENDOR_ID_PEP 0x1518
  23. #define CIF_SUBDEVICE_PROFIBUS 0x430
  24. #define CIF_SUBDEVICE_DEVICENET 0x432
  25. static irqreturn_t hilscher_handler(int irq, struct uio_info *dev_info)
  26. {
  27. void __iomem *plx_intscr = dev_info->mem[0].internal_addr
  28. + PLX9030_INTCSR;
  29. if ((ioread8(plx_intscr) & INT1_ENABLED_AND_ACTIVE)
  30. != INT1_ENABLED_AND_ACTIVE)
  31. return IRQ_NONE;
  32. /* Disable interrupt */
  33. iowrite8(ioread8(plx_intscr) & ~INTSCR_INT1_ENABLE, plx_intscr);
  34. return IRQ_HANDLED;
  35. }
  36. static int __devinit hilscher_pci_probe(struct pci_dev *dev,
  37. const struct pci_device_id *id)
  38. {
  39. struct uio_info *info;
  40. info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
  41. if (!info)
  42. return -ENOMEM;
  43. if (pci_enable_device(dev))
  44. goto out_free;
  45. if (pci_request_regions(dev, "hilscher"))
  46. goto out_disable;
  47. info->mem[0].addr = pci_resource_start(dev, 0);
  48. if (!info->mem[0].addr)
  49. goto out_release;
  50. info->mem[0].internal_addr = ioremap(pci_resource_start(dev, 0),
  51. pci_resource_len(dev, 0));
  52. if (!info->mem[0].internal_addr)
  53. goto out_release;
  54. info->mem[0].size = pci_resource_len(dev, 0);
  55. info->mem[0].memtype = UIO_MEM_PHYS;
  56. info->mem[1].addr = pci_resource_start(dev, 2);
  57. info->mem[1].size = pci_resource_len(dev, 2);
  58. info->mem[1].memtype = UIO_MEM_PHYS;
  59. switch (id->subdevice) {
  60. case CIF_SUBDEVICE_PROFIBUS:
  61. info->name = "CIF_Profibus";
  62. break;
  63. case CIF_SUBDEVICE_DEVICENET:
  64. info->name = "CIF_Devicenet";
  65. break;
  66. default:
  67. info->name = "CIF_???";
  68. }
  69. info->version = "0.0.1";
  70. info->irq = dev->irq;
  71. info->irq_flags = IRQF_DISABLED | IRQF_SHARED;
  72. info->handler = hilscher_handler;
  73. if (uio_register_device(&dev->dev, info))
  74. goto out_unmap;
  75. pci_set_drvdata(dev, info);
  76. return 0;
  77. out_unmap:
  78. iounmap(info->mem[0].internal_addr);
  79. out_release:
  80. pci_release_regions(dev);
  81. out_disable:
  82. pci_disable_device(dev);
  83. out_free:
  84. kfree (info);
  85. return -ENODEV;
  86. }
  87. static void hilscher_pci_remove(struct pci_dev *dev)
  88. {
  89. struct uio_info *info = pci_get_drvdata(dev);
  90. uio_unregister_device(info);
  91. pci_release_regions(dev);
  92. pci_disable_device(dev);
  93. pci_set_drvdata(dev, NULL);
  94. iounmap(info->mem[0].internal_addr);
  95. kfree (info);
  96. }
  97. static struct pci_device_id hilscher_pci_ids[] = {
  98. {
  99. .vendor = PCI_VENDOR_ID_PLX,
  100. .device = PCI_DEVICE_ID_PLX_9030,
  101. .subvendor = PCI_SUBVENDOR_ID_PEP,
  102. .subdevice = CIF_SUBDEVICE_PROFIBUS,
  103. },
  104. {
  105. .vendor = PCI_VENDOR_ID_PLX,
  106. .device = PCI_DEVICE_ID_PLX_9030,
  107. .subvendor = PCI_SUBVENDOR_ID_PEP,
  108. .subdevice = CIF_SUBDEVICE_DEVICENET,
  109. },
  110. { 0, }
  111. };
  112. static struct pci_driver hilscher_pci_driver = {
  113. .name = "hilscher",
  114. .id_table = hilscher_pci_ids,
  115. .probe = hilscher_pci_probe,
  116. .remove = hilscher_pci_remove,
  117. };
  118. static int __init hilscher_init_module(void)
  119. {
  120. return pci_register_driver(&hilscher_pci_driver);
  121. }
  122. static void __exit hilscher_exit_module(void)
  123. {
  124. pci_unregister_driver(&hilscher_pci_driver);
  125. }
  126. module_init(hilscher_init_module);
  127. module_exit(hilscher_exit_module);
  128. MODULE_LICENSE("GPL v2");
  129. MODULE_AUTHOR("Hans J. Koch, Benedikt Spranger");