Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
uio_cif.c
Go to the documentation of this file.
1 /*
2  * UIO Hilscher CIF card driver
3  *
4  * (C) 2007 Hans J. Koch <[email protected]>
5  * Original code (C) 2005 Benedikt Spranger <[email protected]>
6  *
7  * Licensed under GPL version 2 only.
8  *
9  */
10 
11 #include <linux/device.h>
12 #include <linux/module.h>
13 #include <linux/pci.h>
14 #include <linux/slab.h>
15 #include <linux/uio_driver.h>
16 
17 #include <asm/io.h>
18 
19 #define PLX9030_INTCSR 0x4C
20 #define INTSCR_INT1_ENABLE 0x01
21 #define INTSCR_INT1_STATUS 0x04
22 #define INT1_ENABLED_AND_ACTIVE (INTSCR_INT1_ENABLE | INTSCR_INT1_STATUS)
23 
24 #define PCI_SUBVENDOR_ID_PEP 0x1518
25 #define CIF_SUBDEVICE_PROFIBUS 0x430
26 #define CIF_SUBDEVICE_DEVICENET 0x432
27 
28 
29 static irqreturn_t hilscher_handler(int irq, struct uio_info *dev_info)
30 {
31  void __iomem *plx_intscr = dev_info->mem[0].internal_addr
33 
34  if ((ioread8(plx_intscr) & INT1_ENABLED_AND_ACTIVE)
35  != INT1_ENABLED_AND_ACTIVE)
36  return IRQ_NONE;
37 
38  /* Disable interrupt */
39  iowrite8(ioread8(plx_intscr) & ~INTSCR_INT1_ENABLE, plx_intscr);
40  return IRQ_HANDLED;
41 }
42 
43 static int __devinit hilscher_pci_probe(struct pci_dev *dev,
44  const struct pci_device_id *id)
45 {
46  struct uio_info *info;
47 
48  info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
49  if (!info)
50  return -ENOMEM;
51 
52  if (pci_enable_device(dev))
53  goto out_free;
54 
55  if (pci_request_regions(dev, "hilscher"))
56  goto out_disable;
57 
58  info->mem[0].addr = pci_resource_start(dev, 0);
59  if (!info->mem[0].addr)
60  goto out_release;
61  info->mem[0].internal_addr = pci_ioremap_bar(dev, 0);
62  if (!info->mem[0].internal_addr)
63  goto out_release;
64 
65  info->mem[0].size = pci_resource_len(dev, 0);
66  info->mem[0].memtype = UIO_MEM_PHYS;
67  info->mem[1].addr = pci_resource_start(dev, 2);
68  info->mem[1].size = pci_resource_len(dev, 2);
69  info->mem[1].memtype = UIO_MEM_PHYS;
70  switch (id->subdevice) {
72  info->name = "CIF_Profibus";
73  break;
75  info->name = "CIF_Devicenet";
76  break;
77  default:
78  info->name = "CIF_???";
79  }
80  info->version = "0.0.1";
81  info->irq = dev->irq;
82  info->irq_flags = IRQF_SHARED;
83  info->handler = hilscher_handler;
84 
85  if (uio_register_device(&dev->dev, info))
86  goto out_unmap;
87 
88  pci_set_drvdata(dev, info);
89 
90  return 0;
91 out_unmap:
92  iounmap(info->mem[0].internal_addr);
93 out_release:
95 out_disable:
96  pci_disable_device(dev);
97 out_free:
98  kfree (info);
99  return -ENODEV;
100 }
101 
102 static void hilscher_pci_remove(struct pci_dev *dev)
103 {
104  struct uio_info *info = pci_get_drvdata(dev);
105 
106  uio_unregister_device(info);
107  pci_release_regions(dev);
108  pci_disable_device(dev);
109  pci_set_drvdata(dev, NULL);
110  iounmap(info->mem[0].internal_addr);
111 
112  kfree (info);
113 }
114 
115 static struct pci_device_id hilscher_pci_ids[] __devinitdata = {
116  {
117  .vendor = PCI_VENDOR_ID_PLX,
118  .device = PCI_DEVICE_ID_PLX_9030,
119  .subvendor = PCI_SUBVENDOR_ID_PEP,
120  .subdevice = CIF_SUBDEVICE_PROFIBUS,
121  },
122  {
123  .vendor = PCI_VENDOR_ID_PLX,
124  .device = PCI_DEVICE_ID_PLX_9030,
125  .subvendor = PCI_SUBVENDOR_ID_PEP,
126  .subdevice = CIF_SUBDEVICE_DEVICENET,
127  },
128  { 0, }
129 };
130 
131 static struct pci_driver hilscher_pci_driver = {
132  .name = "hilscher",
133  .id_table = hilscher_pci_ids,
134  .probe = hilscher_pci_probe,
135  .remove = hilscher_pci_remove,
136 };
137 
138 static int __init hilscher_init_module(void)
139 {
140  return pci_register_driver(&hilscher_pci_driver);
141 }
142 
143 static void __exit hilscher_exit_module(void)
144 {
145  pci_unregister_driver(&hilscher_pci_driver);
146 }
147 
148 module_init(hilscher_init_module);
149 module_exit(hilscher_exit_module);
150 
151 MODULE_DEVICE_TABLE(pci, hilscher_pci_ids);
152 MODULE_LICENSE("GPL v2");
153 MODULE_AUTHOR("Hans J. Koch, Benedikt Spranger");