]> Pileus Git - ~andy/linux/blob - drivers/staging/comedi/drivers/pcl724.c
spi: atmel: add missing spi_master_{resume,suspend} calls to PM callbacks
[~andy/linux] / drivers / staging / comedi / drivers / pcl724.c
1 /*
2  * pcl724.c
3  * Comedi driver for 8255 based ISA and PC/104 DIO boards
4  *
5  * Michal Dobes <dobes@tesnet.cz>
6  */
7
8 /*
9  * Driver: pcl724
10  * Description: Comedi driver for 8255 based ISA DIO boards
11  * Devices: (Advantech) PCL-724 [pcl724]
12  *          (Advantech) PCL-722 [pcl722]
13  *          (Advantech) PCL-731 [pcl731]
14  *          (ADLink) ACL-7122 [acl7122]
15  *          (ADLink) ACL-7124 [acl7124]
16  *          (ADLink) PET-48DIO [pet48dio]
17  *          (WinSystems) PCM-IO48 [pcmio48]
18  * Author: Michal Dobes <dobes@tesnet.cz>
19  * Status: untested
20  *
21  * Configuration options:
22  *   [0] - IO Base
23  *   [1] - IRQ (not supported)
24  *   [2] - number of DIO (pcl722 and acl7122 boards)
25  *         0, 144: 144 DIO configuration
26  *         1,  96:  96 DIO configuration
27  */
28
29 #include <linux/module.h>
30 #include "../comedidev.h"
31
32 #include "8255.h"
33
34 #define SIZE_8255       4
35
36 struct pcl724_board {
37         const char *name;
38         unsigned int io_range;
39         unsigned int can_have96:1;
40         unsigned int is_pet48:1;
41         int numofports;
42 };
43
44 static const struct pcl724_board boardtypes[] = {
45         {
46                 .name           = "pcl724",
47                 .io_range       = 0x04,
48                 .numofports     = 1,    /* 24 DIO channels */
49         }, {
50                 .name           = "pcl722",
51                 .io_range       = 0x20,
52                 .can_have96     = 1,
53                 .numofports     = 6,    /* 144 (or 96) DIO channels */
54         }, {
55                 .name           = "pcl731",
56                 .io_range       = 0x08,
57                 .numofports     = 2,    /* 48 DIO channels */
58         }, {
59                 .name           = "acl7122",
60                 .io_range       = 0x20,
61                 .can_have96     = 1,
62                 .numofports     = 6,    /* 144 (or 96) DIO channels */
63         }, {
64                 .name           = "acl7124",
65                 .io_range       = 0x04,
66                 .numofports     = 1,    /* 24 DIO channels */
67         }, {
68                 .name           = "pet48dio",
69                 .io_range       = 0x02,
70                 .is_pet48       = 1,
71                 .numofports     = 2,    /* 48 DIO channels */
72         }, {
73                 .name           = "pcmio48",
74                 .io_range       = 0x08,
75                 .numofports     = 2,    /* 48 DIO channels */
76         },
77 };
78
79 static int pcl724_8255mapped_io(int dir, int port, int data,
80                                 unsigned long iobase)
81 {
82         int movport = SIZE_8255 * (iobase >> 12);
83
84         iobase &= 0x0fff;
85
86         if (dir) {
87                 outb(port + movport, iobase);
88                 outb(data, iobase + 1);
89                 return 0;
90         } else {
91                 outb(port + movport, iobase);
92                 return inb(iobase + 1);
93         }
94 }
95
96 static int pcl724_attach(struct comedi_device *dev,
97                          struct comedi_devconfig *it)
98 {
99         const struct pcl724_board *board = comedi_board(dev);
100         struct comedi_subdevice *s;
101         unsigned long iobase;
102         unsigned int iorange;
103         int n_subdevices;
104         int ret;
105         int i;
106
107         iorange = board->io_range;
108         n_subdevices = board->numofports;
109
110         /* Handle PCL-724 in 96 DIO configuration */
111         if (board->can_have96 &&
112             (it->options[2] == 1 || it->options[2] == 96)) {
113                 iorange = 0x10;
114                 n_subdevices = 4;
115         }
116
117         ret = comedi_request_region(dev, it->options[0], iorange);
118         if (ret)
119                 return ret;
120
121         ret = comedi_alloc_subdevices(dev, n_subdevices);
122         if (ret)
123                 return ret;
124
125         for (i = 0; i < dev->n_subdevices; i++) {
126                 s = &dev->subdevices[i];
127                 if (board->is_pet48) {
128                         iobase = dev->iobase + (i * 0x1000);
129                         ret = subdev_8255_init(dev, s, pcl724_8255mapped_io,
130                                                iobase);
131                 } else {
132                         iobase = dev->iobase + (i * SIZE_8255);
133                         ret = subdev_8255_init(dev, s, NULL, iobase);
134                 }
135                 if (ret)
136                         return ret;
137         }
138
139         return 0;
140 }
141
142 static struct comedi_driver pcl724_driver = {
143         .driver_name    = "pcl724",
144         .module         = THIS_MODULE,
145         .attach         = pcl724_attach,
146         .detach         = comedi_legacy_detach,
147         .board_name     = &boardtypes[0].name,
148         .num_names      = ARRAY_SIZE(boardtypes),
149         .offset         = sizeof(struct pcl724_board),
150 };
151 module_comedi_driver(pcl724_driver);
152
153 MODULE_AUTHOR("Comedi http://www.comedi.org");
154 MODULE_DESCRIPTION("Comedi driver for 8255 based ISA and PC/104 DIO boards");
155 MODULE_LICENSE("GPL");