aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans J. Koch <hjk@linutronix.de>2010-02-09 14:13:49 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-07 20:04:50 -0500
commit8f314cfc1259d3f5039b142ce6fdc90367c22d82 (patch)
tree7c02ccbf7832c21cdffafb2573e7450953cbd591
parent57f1e87523bdb6c39659ead7c0f72eea9e520fbe (diff)
UIO: Add a driver for Hilscher netX-based fieldbus cards
This patch adds a Userspace IO driver for netX-based fieldbus cards by Hilscher (see http://www.hilscher.com). ATM, cifX and comX cards are supported. The userspace part for this driver is provided by Hilscher and should come with the card. The driver is in use for several months now and has been tested by people at Hilscher and Linutronix. Signed-off-by: Hans J. Koch <hjk@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/uio/Kconfig11
-rw-r--r--drivers/uio/Makefile1
-rw-r--r--drivers/uio/uio_netx.c172
3 files changed, 184 insertions, 0 deletions
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index 8aa1955f35ed..069b1443be6c 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -94,4 +94,15 @@ config UIO_PCI_GENERIC
94 primarily, for virtualization scenarios. 94 primarily, for virtualization scenarios.
95 If you compile this as a module, it will be called uio_pci_generic. 95 If you compile this as a module, it will be called uio_pci_generic.
96 96
97config UIO_NETX
98 tristate "Hilscher NetX Card driver"
99 depends on PCI
100 help
101 Driver for Hilscher NetX based fieldbus cards (cifX, comX).
102 This driver requires a userspace component that comes with the card
103 or is available from Hilscher (http://www.hilscher.com).
104
105 To compile this driver as a module, choose M here; the module
106 will be called uio_netx.
107
97endif 108endif
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index 73b2e7516729..aa7d0333fa78 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_UIO_SMX) += uio_smx.o
6obj-$(CONFIG_UIO_AEC) += uio_aec.o 6obj-$(CONFIG_UIO_AEC) += uio_aec.o
7obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o 7obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o
8obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o 8obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o
9obj-$(CONFIG_UIO_NETX) += uio_netx.o
diff --git a/drivers/uio/uio_netx.c b/drivers/uio/uio_netx.c
new file mode 100644
index 000000000000..afbf0bd55cc9
--- /dev/null
+++ b/drivers/uio/uio_netx.c
@@ -0,0 +1,172 @@
1/*
2 * UIO driver for Hilscher NetX based fieldbus cards (cifX, comX).
3 * See http://www.hilscher.com for details.
4 *
5 * (C) 2007 Hans J. Koch <hjk@linutronix.de>
6 * (C) 2008 Manuel Traut <manut@linutronix.de>
7 *
8 * Licensed under GPL version 2 only.
9 *
10 */
11
12#include <linux/device.h>
13#include <linux/io.h>
14#include <linux/module.h>
15#include <linux/pci.h>
16#include <linux/uio_driver.h>
17
18#define PCI_VENDOR_ID_HILSCHER 0x15CF
19#define PCI_DEVICE_ID_HILSCHER_NETX 0x0000
20#define PCI_SUBDEVICE_ID_NXSB_PCA 0x3235
21#define PCI_SUBDEVICE_ID_NXPCA 0x3335
22
23#define DPM_HOST_INT_EN0 0xfff0
24#define DPM_HOST_INT_STAT0 0xffe0
25
26#define DPM_HOST_INT_MASK 0xe600ffff
27#define DPM_HOST_INT_GLOBAL_EN 0x80000000
28
29static irqreturn_t netx_handler(int irq, struct uio_info *dev_info)
30{
31 void __iomem *int_enable_reg = dev_info->mem[0].internal_addr
32 + DPM_HOST_INT_EN0;
33 void __iomem *int_status_reg = dev_info->mem[0].internal_addr
34 + DPM_HOST_INT_STAT0;
35
36 /* Is one of our interrupts enabled and active ? */
37 if (!(ioread32(int_enable_reg) & ioread32(int_status_reg)
38 & DPM_HOST_INT_MASK))
39 return IRQ_NONE;
40
41 /* Disable interrupt */
42 iowrite32(ioread32(int_enable_reg) & ~DPM_HOST_INT_GLOBAL_EN,
43 int_enable_reg);
44 return IRQ_HANDLED;
45}
46
47static int __devinit netx_pci_probe(struct pci_dev *dev,
48 const struct pci_device_id *id)
49{
50 struct uio_info *info;
51 int bar;
52
53 info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
54 if (!info)
55 return -ENOMEM;
56
57 if (pci_enable_device(dev))
58 goto out_free;
59
60 if (pci_request_regions(dev, "netx"))
61 goto out_disable;
62
63 switch (id->device) {
64 case PCI_DEVICE_ID_HILSCHER_NETX:
65 bar = 0;
66 info->name = "netx";
67 break;
68 default:
69 bar = 2;
70 info->name = "netx_plx";
71 }
72
73 /* BAR0 or 2 points to the card's dual port memory */
74 info->mem[0].addr = pci_resource_start(dev, bar);
75 if (!info->mem[0].addr)
76 goto out_release;
77 info->mem[0].internal_addr = ioremap(pci_resource_start(dev, bar),
78 pci_resource_len(dev, bar));
79
80 if (!info->mem[0].internal_addr)
81 goto out_release;
82
83 info->mem[0].size = pci_resource_len(dev, bar);
84 info->mem[0].memtype = UIO_MEM_PHYS;
85 info->irq = dev->irq;
86 info->irq_flags = IRQF_SHARED;
87 info->handler = netx_handler;
88 info->version = "0.0.1";
89
90 /* Make sure all interrupts are disabled */
91 iowrite32(0, info->mem[0].internal_addr + DPM_HOST_INT_EN0);
92
93 if (uio_register_device(&dev->dev, info))
94 goto out_unmap;
95
96 pci_set_drvdata(dev, info);
97 dev_info(&dev->dev, "Found %s card, registered UIO device.\n",
98 info->name);
99
100 return 0;
101
102out_unmap:
103 iounmap(info->mem[0].internal_addr);
104out_release:
105 pci_release_regions(dev);
106out_disable:
107 pci_disable_device(dev);
108out_free:
109 kfree(info);
110 return -ENODEV;
111}
112
113static void netx_pci_remove(struct pci_dev *dev)
114{
115 struct uio_info *info = pci_get_drvdata(dev);
116
117 /* Disable all interrupts */
118 iowrite32(0, info->mem[0].internal_addr + DPM_HOST_INT_EN0);
119 uio_unregister_device(info);
120 pci_release_regions(dev);
121 pci_disable_device(dev);
122 pci_set_drvdata(dev, NULL);
123 iounmap(info->mem[0].internal_addr);
124
125 kfree(info);
126}
127
128static struct pci_device_id netx_pci_ids[] = {
129 {
130 .vendor = PCI_VENDOR_ID_HILSCHER,
131 .device = PCI_DEVICE_ID_HILSCHER_NETX,
132 .subvendor = 0,
133 .subdevice = 0,
134 },
135 {
136 .vendor = PCI_VENDOR_ID_PLX,
137 .device = PCI_DEVICE_ID_PLX_9030,
138 .subvendor = PCI_VENDOR_ID_PLX,
139 .subdevice = PCI_SUBDEVICE_ID_NXSB_PCA,
140 },
141 {
142 .vendor = PCI_VENDOR_ID_PLX,
143 .device = PCI_DEVICE_ID_PLX_9030,
144 .subvendor = PCI_VENDOR_ID_PLX,
145 .subdevice = PCI_SUBDEVICE_ID_NXPCA,
146 },
147 { 0, }
148};
149
150static struct pci_driver netx_pci_driver = {
151 .name = "netx",
152 .id_table = netx_pci_ids,
153 .probe = netx_pci_probe,
154 .remove = netx_pci_remove,
155};
156
157static int __init netx_init_module(void)
158{
159 return pci_register_driver(&netx_pci_driver);
160}
161
162static void __exit netx_exit_module(void)
163{
164 pci_unregister_driver(&netx_pci_driver);
165}
166
167module_init(netx_init_module);
168module_exit(netx_exit_module);
169
170MODULE_DEVICE_TABLE(pci, netx_pci_ids);
171MODULE_LICENSE("GPL v2");
172MODULE_AUTHOR("Hans J. Koch, Manuel Traut");