Merge tag 'arc-v3.9-rc1-late' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc
[firefly-linux-kernel-4.4.55.git] / drivers / staging / comedi / drivers / pcl725.c
1 /*
2  * comedi/drivers/pcl725.c
3  * Driver for PCL725 and clones
4  * David A. Schleef
5  */
6 /*
7 Driver: pcl725
8 Description: Advantech PCL-725 (& compatibles)
9 Author: ds
10 Status: unknown
11 Devices: [Advantech] PCL-725 (pcl725)
12 */
13
14 #include "../comedidev.h"
15
16 #include <linux/ioport.h>
17
18 #define PCL725_SIZE 2
19
20 #define PCL725_DO 0
21 #define PCL725_DI 1
22
23 static int pcl725_do_insn(struct comedi_device *dev, struct comedi_subdevice *s,
24                           struct comedi_insn *insn, unsigned int *data)
25 {
26         if (data[0]) {
27                 s->state &= ~data[0];
28                 s->state |= (data[0] & data[1]);
29                 outb(s->state, dev->iobase + PCL725_DO);
30         }
31
32         data[1] = s->state;
33
34         return insn->n;
35 }
36
37 static int pcl725_di_insn(struct comedi_device *dev, struct comedi_subdevice *s,
38                           struct comedi_insn *insn, unsigned int *data)
39 {
40         data[1] = inb(dev->iobase + PCL725_DI);
41
42         return insn->n;
43 }
44
45 static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it)
46 {
47         struct comedi_subdevice *s;
48         unsigned long iobase;
49         int ret;
50
51         iobase = it->options[0];
52         printk(KERN_INFO "comedi%d: pcl725: 0x%04lx ", dev->minor, iobase);
53         if (!request_region(iobase, PCL725_SIZE, "pcl725")) {
54                 printk("I/O port conflict\n");
55                 return -EIO;
56         }
57         dev->board_name = "pcl725";
58         dev->iobase = iobase;
59         dev->irq = 0;
60
61         ret = comedi_alloc_subdevices(dev, 2);
62         if (ret)
63                 return ret;
64
65         s = &dev->subdevices[0];
66         /* do */
67         s->type = COMEDI_SUBD_DO;
68         s->subdev_flags = SDF_WRITABLE;
69         s->maxdata = 1;
70         s->n_chan = 8;
71         s->insn_bits = pcl725_do_insn;
72         s->range_table = &range_digital;
73
74         s = &dev->subdevices[1];
75         /* di */
76         s->type = COMEDI_SUBD_DI;
77         s->subdev_flags = SDF_READABLE;
78         s->maxdata = 1;
79         s->n_chan = 8;
80         s->insn_bits = pcl725_di_insn;
81         s->range_table = &range_digital;
82
83         printk(KERN_INFO "\n");
84
85         return 0;
86 }
87
88 static void pcl725_detach(struct comedi_device *dev)
89 {
90         if (dev->iobase)
91                 release_region(dev->iobase, PCL725_SIZE);
92 }
93
94 static struct comedi_driver pcl725_driver = {
95         .driver_name    = "pcl725",
96         .module         = THIS_MODULE,
97         .attach         = pcl725_attach,
98         .detach         = pcl725_detach,
99 };
100 module_comedi_driver(pcl725_driver);
101
102 MODULE_AUTHOR("Comedi http://www.comedi.org");
103 MODULE_DESCRIPTION("Comedi low-level driver");
104 MODULE_LICENSE("GPL");