2 * UIO driver fo Humusoft MF614 DAQ card.
3 * Copyright (C) 2010--2011 Rostislav Lisovy <lisovy@gmail.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <linux/init.h>
21 #include <linux/module.h>
22 #include <linux/device.h>
23 #include <linux/pci.h>
24 #include <linux/slab.h>
26 #include <linux/kernel.h>
27 #include <linux/uio_driver.h>
29 #define PCI_VENDOR_ID_HUMUSOFT 0x186c
30 #define PCI_DEVICE_ID_MF614 0x0614
31 #define PCI_SUBVENDOR_ID_HUMUSOFT 0x186c
32 #define PCI_SUBDEVICE_DEVICE 0x0000
34 #define STATUS_REG 0x10
35 #define STATUS_T5INTE (u32) (1 << 19)
36 #define STATUS_T5 (u32) (1 << 3)
37 #define STATUS_CCINTE (u32) (1 << 18)
38 #define STATUS_CC (u32) (1 << 2)
41 static irqreturn_t mf614_irq_handler(int irq, struct uio_info *info)
43 void __iomem *status_reg = info->priv;
44 status_reg = (u8 *)status_reg + STATUS_REG;
47 if ((ioread32(status_reg) & STATUS_T5INTE)
48 && (ioread32(status_reg) & STATUS_T5)) {
49 /* disable interrupt */
50 iowrite32(ioread32(status_reg) & ~STATUS_T5INTE, status_reg);
54 if ((ioread32(status_reg) & STATUS_CCINTE)
55 && (ioread32(status_reg) & STATUS_CC)) {
56 /* disable interrupt */
57 iowrite32(ioread32(status_reg) & ~STATUS_CCINTE, status_reg);
64 static int mf614_irqcontrol(struct uio_info *info, s32 irq_on)
66 void __iomem *status_reg = info->priv;
67 status_reg = (u8 *)status_reg + STATUS_REG;
70 if (irq_on == 0) { /* Disable interrupts */
71 iowrite32(ioread32(status_reg) & ~STATUS_T5INTE, status_reg);
72 iowrite32(ioread32(status_reg) & ~STATUS_CCINTE, status_reg);
73 } else if (irq_on == 1) {
74 iowrite32(ioread32(status_reg) | STATUS_T5INTE, status_reg);
75 iowrite32(ioread32(status_reg) | STATUS_CCINTE, status_reg);
81 static int __devinit mf614_pci_probe(struct pci_dev *dev,
82 const struct pci_device_id *id)
84 struct uio_info *info;
86 info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
90 if (pci_enable_device(dev))
93 if (pci_request_regions(dev, "mf614"))
97 info->version = "0.0.1";
99 info->port[0].name = "Board programming registers";
100 info->port[0].porttype = UIO_PORT_X86;
101 info->port[0].start = pci_resource_start(dev, 0);
102 if (!info->port[0].start)
104 info->port[0].size = pci_resource_len(dev, 0);
107 info->port[1].name = "OX9162 local configuration registers";
108 info->port[1].porttype = UIO_PORT_X86;
109 info->port[1].start = pci_resource_start(dev, 2);
110 if (!info->port[1].start)
112 info->port[1].size = pci_resource_len(dev, 2);
114 info->priv = pci_iomap(dev, 2, 0);
119 info->mem[0].name = "Board programming registers";
120 info->mem[0].addr = pci_resource_start(dev, 4);
121 if (!info->mem[0].addr)
123 info->mem[0].size = pci_resource_len(dev, 4);
124 info->mem[0].memtype = UIO_MEM_PHYS;
125 info->mem[0].internal_addr = pci_ioremap_bar(dev, 4);
126 if (!info->mem[0].internal_addr)
130 info->mem[1].name = "OX9162 local configuration registers";
131 info->mem[1].addr = pci_resource_start(dev, 3);
132 if (!info->mem[1].addr)
134 info->mem[1].size = pci_resource_len(dev, 3);
135 info->mem[1].memtype = UIO_MEM_PHYS;
136 info->mem[1].internal_addr = pci_ioremap_bar(dev, 3);
137 if (!info->mem[1].internal_addr)
141 info->irq = dev->irq;
142 info->irq_flags = IRQF_SHARED;
143 info->handler = mf614_irq_handler;
145 info->irqcontrol = mf614_irqcontrol;
147 if (uio_register_device(&dev->dev, info))
150 pci_set_drvdata(dev, info);
155 iounmap(info->mem[0].internal_addr);
156 iounmap(info->mem[1].internal_addr);
157 pci_iounmap(dev, info->priv);
159 pci_release_regions(dev);
161 pci_disable_device(dev);
167 static void mf614_pci_remove(struct pci_dev *dev)
169 struct uio_info *info = pci_get_drvdata(dev);
170 void __iomem *status_reg = info->priv;
171 status_reg = (u8 *)status_reg + STATUS_REG;
173 /* Disable interrupts */
174 iowrite32(ioread32(status_reg) & ~STATUS_T5INTE, status_reg);
175 iowrite32(ioread32(status_reg) & ~STATUS_CCINTE, status_reg);
177 uio_unregister_device(info);
178 pci_release_regions(dev);
179 pci_disable_device(dev);
180 pci_set_drvdata(dev, NULL);
181 pci_iounmap(dev, info->priv);
182 iounmap(info->mem[0].internal_addr);
183 iounmap(info->mem[1].internal_addr);
188 static struct pci_device_id mf614_pci_id[] __devinitdata = {
190 .vendor = PCI_VENDOR_ID_HUMUSOFT,
191 .device = PCI_DEVICE_ID_MF614,
192 .subvendor = PCI_SUBVENDOR_ID_HUMUSOFT,
193 .subdevice = PCI_SUBDEVICE_DEVICE,
197 MODULE_DEVICE_TABLE(pci, mf614_pci_id);
199 static struct pci_driver mf614_pci_driver = {
201 .id_table = mf614_pci_id,
202 .probe = mf614_pci_probe,
203 .remove = mf614_pci_remove,
206 static int __init mf614_init_module(void)
208 return pci_register_driver(&mf614_pci_driver);
211 static void __exit mf614_exit_module(void)
213 pci_unregister_driver(&mf614_pci_driver);
216 module_init(mf614_init_module);
217 module_exit(mf614_exit_module);
219 MODULE_LICENSE("GPL v2");
220 MODULE_AUTHOR("Rostislav Lisovy <lisovy@gmail.com>");