Root/
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@hansjkoch.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/slab.h> |
17 | #include <linux/uio_driver.h> |
18 | |
19 | #define PCI_VENDOR_ID_HILSCHER 0x15CF |
20 | #define PCI_DEVICE_ID_HILSCHER_NETX 0x0000 |
21 | #define PCI_DEVICE_ID_HILSCHER_NETPLC 0x0010 |
22 | #define PCI_SUBDEVICE_ID_NETPLC_RAM 0x0000 |
23 | #define PCI_SUBDEVICE_ID_NETPLC_FLASH 0x0001 |
24 | #define PCI_SUBDEVICE_ID_NXSB_PCA 0x3235 |
25 | #define PCI_SUBDEVICE_ID_NXPCA 0x3335 |
26 | |
27 | #define DPM_HOST_INT_EN0 0xfff0 |
28 | #define DPM_HOST_INT_STAT0 0xffe0 |
29 | |
30 | #define DPM_HOST_INT_MASK 0xe600ffff |
31 | #define DPM_HOST_INT_GLOBAL_EN 0x80000000 |
32 | |
33 | static irqreturn_t netx_handler(int irq, struct uio_info *dev_info) |
34 | { |
35 | void __iomem *int_enable_reg = dev_info->mem[0].internal_addr |
36 | + DPM_HOST_INT_EN0; |
37 | void __iomem *int_status_reg = dev_info->mem[0].internal_addr |
38 | + DPM_HOST_INT_STAT0; |
39 | |
40 | /* Is one of our interrupts enabled and active ? */ |
41 | if (!(ioread32(int_enable_reg) & ioread32(int_status_reg) |
42 | & DPM_HOST_INT_MASK)) |
43 | return IRQ_NONE; |
44 | |
45 | /* Disable interrupt */ |
46 | iowrite32(ioread32(int_enable_reg) & ~DPM_HOST_INT_GLOBAL_EN, |
47 | int_enable_reg); |
48 | return IRQ_HANDLED; |
49 | } |
50 | |
51 | static int __devinit netx_pci_probe(struct pci_dev *dev, |
52 | const struct pci_device_id *id) |
53 | { |
54 | struct uio_info *info; |
55 | int bar; |
56 | |
57 | info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); |
58 | if (!info) |
59 | return -ENOMEM; |
60 | |
61 | if (pci_enable_device(dev)) |
62 | goto out_free; |
63 | |
64 | if (pci_request_regions(dev, "netx")) |
65 | goto out_disable; |
66 | |
67 | switch (id->device) { |
68 | case PCI_DEVICE_ID_HILSCHER_NETX: |
69 | bar = 0; |
70 | info->name = "netx"; |
71 | break; |
72 | case PCI_DEVICE_ID_HILSCHER_NETPLC: |
73 | bar = 0; |
74 | info->name = "netplc"; |
75 | break; |
76 | default: |
77 | bar = 2; |
78 | info->name = "netx_plx"; |
79 | } |
80 | |
81 | /* BAR0 or 2 points to the card's dual port memory */ |
82 | info->mem[0].addr = pci_resource_start(dev, bar); |
83 | if (!info->mem[0].addr) |
84 | goto out_release; |
85 | info->mem[0].internal_addr = ioremap(pci_resource_start(dev, bar), |
86 | pci_resource_len(dev, bar)); |
87 | |
88 | if (!info->mem[0].internal_addr) |
89 | goto out_release; |
90 | |
91 | info->mem[0].size = pci_resource_len(dev, bar); |
92 | info->mem[0].memtype = UIO_MEM_PHYS; |
93 | info->irq = dev->irq; |
94 | info->irq_flags = IRQF_SHARED; |
95 | info->handler = netx_handler; |
96 | info->version = "0.0.1"; |
97 | |
98 | /* Make sure all interrupts are disabled */ |
99 | iowrite32(0, info->mem[0].internal_addr + DPM_HOST_INT_EN0); |
100 | |
101 | if (uio_register_device(&dev->dev, info)) |
102 | goto out_unmap; |
103 | |
104 | pci_set_drvdata(dev, info); |
105 | dev_info(&dev->dev, "Found %s card, registered UIO device.\n", |
106 | info->name); |
107 | |
108 | return 0; |
109 | |
110 | out_unmap: |
111 | iounmap(info->mem[0].internal_addr); |
112 | out_release: |
113 | pci_release_regions(dev); |
114 | out_disable: |
115 | pci_disable_device(dev); |
116 | out_free: |
117 | kfree(info); |
118 | return -ENODEV; |
119 | } |
120 | |
121 | static void netx_pci_remove(struct pci_dev *dev) |
122 | { |
123 | struct uio_info *info = pci_get_drvdata(dev); |
124 | |
125 | /* Disable all interrupts */ |
126 | iowrite32(0, info->mem[0].internal_addr + DPM_HOST_INT_EN0); |
127 | uio_unregister_device(info); |
128 | pci_release_regions(dev); |
129 | pci_disable_device(dev); |
130 | pci_set_drvdata(dev, NULL); |
131 | iounmap(info->mem[0].internal_addr); |
132 | |
133 | kfree(info); |
134 | } |
135 | |
136 | static struct pci_device_id netx_pci_ids[] = { |
137 | { |
138 | .vendor = PCI_VENDOR_ID_HILSCHER, |
139 | .device = PCI_DEVICE_ID_HILSCHER_NETX, |
140 | .subvendor = 0, |
141 | .subdevice = 0, |
142 | }, |
143 | { |
144 | .vendor = PCI_VENDOR_ID_HILSCHER, |
145 | .device = PCI_DEVICE_ID_HILSCHER_NETPLC, |
146 | .subvendor = PCI_VENDOR_ID_HILSCHER, |
147 | .subdevice = PCI_SUBDEVICE_ID_NETPLC_RAM, |
148 | }, |
149 | { |
150 | .vendor = PCI_VENDOR_ID_HILSCHER, |
151 | .device = PCI_DEVICE_ID_HILSCHER_NETPLC, |
152 | .subvendor = PCI_VENDOR_ID_HILSCHER, |
153 | .subdevice = PCI_SUBDEVICE_ID_NETPLC_FLASH, |
154 | }, |
155 | { |
156 | .vendor = PCI_VENDOR_ID_PLX, |
157 | .device = PCI_DEVICE_ID_PLX_9030, |
158 | .subvendor = PCI_VENDOR_ID_PLX, |
159 | .subdevice = PCI_SUBDEVICE_ID_NXSB_PCA, |
160 | }, |
161 | { |
162 | .vendor = PCI_VENDOR_ID_PLX, |
163 | .device = PCI_DEVICE_ID_PLX_9030, |
164 | .subvendor = PCI_VENDOR_ID_PLX, |
165 | .subdevice = PCI_SUBDEVICE_ID_NXPCA, |
166 | }, |
167 | { 0, } |
168 | }; |
169 | |
170 | static struct pci_driver netx_pci_driver = { |
171 | .name = "netx", |
172 | .id_table = netx_pci_ids, |
173 | .probe = netx_pci_probe, |
174 | .remove = netx_pci_remove, |
175 | }; |
176 | |
177 | static int __init netx_init_module(void) |
178 | { |
179 | return pci_register_driver(&netx_pci_driver); |
180 | } |
181 | |
182 | static void __exit netx_exit_module(void) |
183 | { |
184 | pci_unregister_driver(&netx_pci_driver); |
185 | } |
186 | |
187 | module_init(netx_init_module); |
188 | module_exit(netx_exit_module); |
189 | |
190 | MODULE_DEVICE_TABLE(pci, netx_pci_ids); |
191 | MODULE_LICENSE("GPL v2"); |
192 | MODULE_AUTHOR("Hans J. Koch, Manuel Traut"); |
193 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9