staging: comedi: adv_pci_dio: update the MODULE_DESCRIPTION
[linux-2.6/btrfs-unstable.git] / drivers / staging / comedi / drivers / adv_pci_dio.c
blob620cec13d74cd044dc5d99e6680c5e12b016df22
1 /*
2 * comedi/drivers/adv_pci_dio.c
4 * Author: Michal Dobes <dobes@tesnet.cz>
6 * Hardware driver for Advantech PCI DIO cards.
7 */
9 /*
10 * Driver: adv_pci_dio
11 * Description: Advantech Digital I/O Cards
12 * Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733,
13 * PCI-1734, PCI-1735U, PCI-1736UP, PCI-1739U, PCI-1750,
14 * PCI-1751, PCI-1752, PCI-1753, PCI-1753+PCI-1753E,
15 * PCI-1754, PCI-1756, PCI-1762
16 * Author: Michal Dobes <dobes@tesnet.cz>
17 * Updated: Mon, 09 Jan 2012 12:40:46 +0000
18 * Status: untested
20 * Configuration Options: not applicable, uses PCI auto config
23 #include <linux/module.h>
24 #include <linux/delay.h>
26 #include "../comedi_pci.h"
28 #include "8255.h"
29 #include "comedi_8254.h"
32 * Register offset definitions
35 /* PCI-1730, PCI-1733, PCI-1736 interrupt control registers */
36 #define PCI173X_INT_EN_REG 0x08 /* R/W: enable/disable */
37 #define PCI173X_INT_RF_REG 0x0c /* R/W: falling/rising edge */
38 #define PCI173X_INT_CLR_REG 0x10 /* R/W: clear */
40 /* PCI-1739U, PCI-1750, PCI1751 interrupt control registers */
41 #define PCI1750_INT_REG 0x20 /* R/W: status/control */
43 /* PCI-1753, PCI-1753E interrupt control registers */
44 #define PCI1753_INT_REG(x) (0x10 + (x)) /* R/W: control group 0 to 3 */
45 #define PCI1753E_INT_REG(x) (0x30 + (x)) /* R/W: control group 0 to 3 */
47 /* PCI-1754, PCI-1756 interrupt control registers */
48 #define PCI1754_INT_REG(x) (0x08 + (x) * 2) /* R/W: control group 0 to 3 */
50 /* PCI-1752, PCI-1756 special registers */
51 #define PCI1752_CFC_REG 0x12 /* R/W: channel freeze function */
53 /* PCI-1762 interrupt control registers */
54 #define PCI1762_INT_REG 0x06 /* R/W: status/control */
56 /* maximum number of subdevice descriptions in the boardinfo */
57 #define PCI_DIO_MAX_DI_SUBDEVS 2 /* 2 x 8/16/32 input channels max */
58 #define PCI_DIO_MAX_DO_SUBDEVS 2 /* 2 x 8/16/32 output channels max */
59 #define PCI_DIO_MAX_DIO_SUBDEVG 2 /* 2 x any number of 8255 devices max */
61 enum pci_dio_boardid {
62 TYPE_PCI1730,
63 TYPE_PCI1733,
64 TYPE_PCI1734,
65 TYPE_PCI1735,
66 TYPE_PCI1736,
67 TYPE_PCI1739,
68 TYPE_PCI1750,
69 TYPE_PCI1751,
70 TYPE_PCI1752,
71 TYPE_PCI1753,
72 TYPE_PCI1753E,
73 TYPE_PCI1754,
74 TYPE_PCI1756,
75 TYPE_PCI1762
78 struct diosubd_data {
79 int chans; /* num of chans or 8255 devices */
80 unsigned long addr; /* PCI address ofset */
83 struct dio_boardtype {
84 const char *name; /* board name */
85 int nsubdevs;
86 struct diosubd_data sdi[PCI_DIO_MAX_DI_SUBDEVS];
87 struct diosubd_data sdo[PCI_DIO_MAX_DO_SUBDEVS];
88 struct diosubd_data sdio[PCI_DIO_MAX_DIO_SUBDEVG];
89 unsigned long id_reg;
90 unsigned long timer_regbase;
91 unsigned int is_16bit:1;
94 static const struct dio_boardtype boardtypes[] = {
95 [TYPE_PCI1730] = {
96 .name = "pci1730",
97 .nsubdevs = 5,
98 .sdi[0] = { 16, 0x02, }, /* DI 0-15 */
99 .sdi[1] = { 16, 0x00, }, /* ISO DI 0-15 */
100 .sdo[0] = { 16, 0x02, }, /* DO 0-15 */
101 .sdo[1] = { 16, 0x00, }, /* ISO DO 0-15 */
102 .id_reg = 0x04,
104 [TYPE_PCI1733] = {
105 .name = "pci1733",
106 .nsubdevs = 2,
107 .sdi[1] = { 32, 0x00, }, /* ISO DI 0-31 */
108 .id_reg = 0x04,
110 [TYPE_PCI1734] = {
111 .name = "pci1734",
112 .nsubdevs = 2,
113 .sdo[1] = { 32, 0x00, }, /* ISO DO 0-31 */
114 .id_reg = 0x04,
116 [TYPE_PCI1735] = {
117 .name = "pci1735",
118 .nsubdevs = 4,
119 .sdi[0] = { 32, 0x00, }, /* DI 0-31 */
120 .sdo[0] = { 32, 0x00, }, /* DO 0-31 */
121 .id_reg = 0x08,
122 .timer_regbase = 0x04,
124 [TYPE_PCI1736] = {
125 .name = "pci1736",
126 .nsubdevs = 3,
127 .sdi[1] = { 16, 0x00, }, /* ISO DI 0-15 */
128 .sdo[1] = { 16, 0x00, }, /* ISO DO 0-15 */
129 .id_reg = 0x04,
131 [TYPE_PCI1739] = {
132 .name = "pci1739",
133 .nsubdevs = 3,
134 .sdio[0] = { 2, 0x00, }, /* 8255 DIO */
135 .id_reg = 0x08,
137 [TYPE_PCI1750] = {
138 .name = "pci1750",
139 .nsubdevs = 2,
140 .sdi[1] = { 16, 0x00, }, /* ISO DI 0-15 */
141 .sdo[1] = { 16, 0x00, }, /* ISO DO 0-15 */
143 [TYPE_PCI1751] = {
144 .name = "pci1751",
145 .nsubdevs = 3,
146 .sdio[0] = { 2, 0x00, }, /* 8255 DIO */
147 .timer_regbase = 0x18,
149 [TYPE_PCI1752] = {
150 .name = "pci1752",
151 .nsubdevs = 3,
152 .sdo[0] = { 32, 0x00, }, /* DO 0-31 */
153 .sdo[1] = { 32, 0x04, }, /* DO 32-63 */
154 .id_reg = 0x10,
155 .is_16bit = 1,
157 [TYPE_PCI1753] = {
158 .name = "pci1753",
159 .nsubdevs = 4,
160 .sdio[0] = { 4, 0x00, }, /* 8255 DIO */
162 [TYPE_PCI1753E] = {
163 .name = "pci1753e",
164 .nsubdevs = 8,
165 .sdio[0] = { 4, 0x00, }, /* 8255 DIO */
166 .sdio[1] = { 4, 0x20, }, /* 8255 DIO */
168 [TYPE_PCI1754] = {
169 .name = "pci1754",
170 .nsubdevs = 3,
171 .sdi[0] = { 32, 0x00, }, /* DI 0-31 */
172 .sdi[1] = { 32, 0x04, }, /* DI 32-63 */
173 .id_reg = 0x10,
174 .is_16bit = 1,
176 [TYPE_PCI1756] = {
177 .name = "pci1756",
178 .nsubdevs = 3,
179 .sdi[1] = { 32, 0x00, }, /* DI 0-31 */
180 .sdo[1] = { 32, 0x04, }, /* DO 0-31 */
181 .id_reg = 0x10,
182 .is_16bit = 1,
184 [TYPE_PCI1762] = {
185 .name = "pci1762",
186 .nsubdevs = 3,
187 .sdi[1] = { 16, 0x02, }, /* ISO DI 0-15 */
188 .sdo[1] = { 16, 0x00, }, /* ISO DO 0-15 */
189 .id_reg = 0x04,
190 .is_16bit = 1,
194 static int pci_dio_insn_bits_di_b(struct comedi_device *dev,
195 struct comedi_subdevice *s,
196 struct comedi_insn *insn,
197 unsigned int *data)
199 unsigned long reg = (unsigned long)s->private;
200 unsigned long iobase = dev->iobase + reg;
202 data[1] = inb(iobase);
203 if (s->n_chan > 8)
204 data[1] |= (inb(iobase + 1) << 8);
205 if (s->n_chan > 16)
206 data[1] |= (inb(iobase + 2) << 16);
207 if (s->n_chan > 24)
208 data[1] |= (inb(iobase + 3) << 24);
210 return insn->n;
213 static int pci_dio_insn_bits_di_w(struct comedi_device *dev,
214 struct comedi_subdevice *s,
215 struct comedi_insn *insn,
216 unsigned int *data)
218 unsigned long reg = (unsigned long)s->private;
219 unsigned long iobase = dev->iobase + reg;
221 data[1] = inw(iobase);
222 if (s->n_chan > 16)
223 data[1] |= (inw(iobase + 2) << 16);
225 return insn->n;
228 static int pci_dio_insn_bits_do_b(struct comedi_device *dev,
229 struct comedi_subdevice *s,
230 struct comedi_insn *insn,
231 unsigned int *data)
233 unsigned long reg = (unsigned long)s->private;
234 unsigned long iobase = dev->iobase + reg;
236 if (comedi_dio_update_state(s, data)) {
237 outb(s->state & 0xff, iobase);
238 if (s->n_chan > 8)
239 outb((s->state >> 8) & 0xff, iobase + 1);
240 if (s->n_chan > 16)
241 outb((s->state >> 16) & 0xff, iobase + 2);
242 if (s->n_chan > 24)
243 outb((s->state >> 24) & 0xff, iobase + 3);
246 data[1] = s->state;
248 return insn->n;
251 static int pci_dio_insn_bits_do_w(struct comedi_device *dev,
252 struct comedi_subdevice *s,
253 struct comedi_insn *insn,
254 unsigned int *data)
256 unsigned long reg = (unsigned long)s->private;
257 unsigned long iobase = dev->iobase + reg;
259 if (comedi_dio_update_state(s, data)) {
260 outw(s->state & 0xffff, iobase);
261 if (s->n_chan > 16)
262 outw((s->state >> 16) & 0xffff, iobase + 2);
265 data[1] = s->state;
267 return insn->n;
270 static int pci_dio_reset(struct comedi_device *dev, unsigned long cardtype)
272 /* disable channel freeze function on the PCI-1752/1756 boards */
273 if (cardtype == TYPE_PCI1752 || cardtype == TYPE_PCI1756)
274 outw(0, dev->iobase + PCI1752_CFC_REG);
276 /* disable and clear interrupts */
277 switch (cardtype) {
278 case TYPE_PCI1730:
279 case TYPE_PCI1733:
280 case TYPE_PCI1736:
281 outb(0, dev->iobase + PCI173X_INT_EN_REG);
282 outb(0x0f, dev->iobase + PCI173X_INT_CLR_REG);
283 outb(0, dev->iobase + PCI173X_INT_RF_REG);
284 break;
285 case TYPE_PCI1739:
286 case TYPE_PCI1750:
287 case TYPE_PCI1751:
288 outb(0x88, dev->iobase + PCI1750_INT_REG);
289 break;
290 case TYPE_PCI1753:
291 case TYPE_PCI1753E:
292 outb(0x88, dev->iobase + PCI1753_INT_REG(0));
293 outb(0x80, dev->iobase + PCI1753_INT_REG(1));
294 outb(0x80, dev->iobase + PCI1753_INT_REG(2));
295 outb(0x80, dev->iobase + PCI1753_INT_REG(3));
296 if (cardtype == TYPE_PCI1753E) {
297 outb(0x88, dev->iobase + PCI1753E_INT_REG(0));
298 outb(0x80, dev->iobase + PCI1753E_INT_REG(1));
299 outb(0x80, dev->iobase + PCI1753E_INT_REG(2));
300 outb(0x80, dev->iobase + PCI1753E_INT_REG(3));
302 break;
303 case TYPE_PCI1754:
304 case TYPE_PCI1756:
305 outw(0x08, dev->iobase + PCI1754_INT_REG(0));
306 outw(0x08, dev->iobase + PCI1754_INT_REG(1));
307 if (cardtype == TYPE_PCI1754) {
308 outw(0x08, dev->iobase + PCI1754_INT_REG(2));
309 outw(0x08, dev->iobase + PCI1754_INT_REG(3));
311 break;
312 case TYPE_PCI1762:
313 outw(0x0101, dev->iobase + PCI1762_INT_REG);
314 break;
315 default:
316 break;
319 return 0;
322 static int pci_dio_auto_attach(struct comedi_device *dev,
323 unsigned long context)
325 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
326 const struct dio_boardtype *board = NULL;
327 const struct diosubd_data *d;
328 struct comedi_subdevice *s;
329 int ret, subdev, i, j;
331 if (context < ARRAY_SIZE(boardtypes))
332 board = &boardtypes[context];
333 if (!board)
334 return -ENODEV;
335 dev->board_ptr = board;
336 dev->board_name = board->name;
338 ret = comedi_pci_enable(dev);
339 if (ret)
340 return ret;
341 if (context == TYPE_PCI1736)
342 dev->iobase = pci_resource_start(pcidev, 0);
343 else
344 dev->iobase = pci_resource_start(pcidev, 2);
346 pci_dio_reset(dev, context);
348 ret = comedi_alloc_subdevices(dev, board->nsubdevs);
349 if (ret)
350 return ret;
352 subdev = 0;
353 for (i = 0; i < PCI_DIO_MAX_DI_SUBDEVS; i++) {
354 d = &board->sdi[i];
355 if (d->chans) {
356 s = &dev->subdevices[subdev++];
357 s->type = COMEDI_SUBD_DI;
358 s->subdev_flags = SDF_READABLE;
359 s->n_chan = d->chans;
360 s->maxdata = 1;
361 s->range_table = &range_digital;
362 s->insn_bits = board->is_16bit
363 ? pci_dio_insn_bits_di_w
364 : pci_dio_insn_bits_di_b;
365 s->private = (void *)d->addr;
369 for (i = 0; i < PCI_DIO_MAX_DO_SUBDEVS; i++) {
370 d = &board->sdo[i];
371 if (d->chans) {
372 s = &dev->subdevices[subdev++];
373 s->type = COMEDI_SUBD_DO;
374 s->subdev_flags = SDF_WRITABLE;
375 s->n_chan = d->chans;
376 s->maxdata = 1;
377 s->range_table = &range_digital;
378 s->insn_bits = board->is_16bit
379 ? pci_dio_insn_bits_do_w
380 : pci_dio_insn_bits_do_b;
381 s->private = (void *)d->addr;
383 /* reset all outputs to 0 */
384 if (board->is_16bit) {
385 outw(0, dev->iobase + d->addr);
386 if (s->n_chan > 16)
387 outw(0, dev->iobase + d->addr + 2);
388 } else {
389 outb(0, dev->iobase + d->addr);
390 if (s->n_chan > 8)
391 outb(0, dev->iobase + d->addr + 1);
392 if (s->n_chan > 16)
393 outb(0, dev->iobase + d->addr + 2);
394 if (s->n_chan > 24)
395 outb(0, dev->iobase + d->addr + 3);
400 for (i = 0; i < PCI_DIO_MAX_DIO_SUBDEVG; i++) {
401 d = &board->sdio[i];
402 for (j = 0; j < d->chans; j++) {
403 s = &dev->subdevices[subdev++];
404 ret = subdev_8255_init(dev, s, NULL,
405 d->addr + j * I8255_SIZE);
406 if (ret)
407 return ret;
411 if (board->id_reg) {
412 s = &dev->subdevices[subdev++];
413 s->type = COMEDI_SUBD_DI;
414 s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
415 s->n_chan = 4;
416 s->maxdata = 1;
417 s->range_table = &range_digital;
418 s->insn_bits = board->is_16bit ? pci_dio_insn_bits_di_w
419 : pci_dio_insn_bits_di_b;
420 s->private = (void *)board->id_reg;
423 if (board->timer_regbase) {
424 s = &dev->subdevices[subdev++];
426 dev->pacer = comedi_8254_init(dev->iobase +
427 board->timer_regbase,
428 0, I8254_IO8, 0);
429 if (!dev->pacer)
430 return -ENOMEM;
432 comedi_8254_subdevice_init(s, dev->pacer);
435 return 0;
438 static struct comedi_driver adv_pci_dio_driver = {
439 .driver_name = "adv_pci_dio",
440 .module = THIS_MODULE,
441 .auto_attach = pci_dio_auto_attach,
442 .detach = comedi_pci_detach,
445 static unsigned long pci_dio_override_cardtype(struct pci_dev *pcidev,
446 unsigned long cardtype)
449 * Change cardtype from TYPE_PCI1753 to TYPE_PCI1753E if expansion
450 * board available. Need to enable PCI device and request the main
451 * registers PCI BAR temporarily to perform the test.
453 if (cardtype != TYPE_PCI1753)
454 return cardtype;
455 if (pci_enable_device(pcidev) < 0)
456 return cardtype;
457 if (pci_request_region(pcidev, 2, "adv_pci_dio") == 0) {
459 * This test is based on Advantech's "advdaq" driver source
460 * (which declares its module licence as "GPL" although the
461 * driver source does not include a "COPYING" file).
463 unsigned long reg = pci_resource_start(pcidev, 2) + 53;
465 outb(0x05, reg);
466 if ((inb(reg) & 0x07) == 0x02) {
467 outb(0x02, reg);
468 if ((inb(reg) & 0x07) == 0x05)
469 cardtype = TYPE_PCI1753E;
471 pci_release_region(pcidev, 2);
473 pci_disable_device(pcidev);
474 return cardtype;
477 static int adv_pci_dio_pci_probe(struct pci_dev *dev,
478 const struct pci_device_id *id)
480 unsigned long cardtype;
482 cardtype = pci_dio_override_cardtype(dev, id->driver_data);
483 return comedi_pci_auto_config(dev, &adv_pci_dio_driver, cardtype);
486 static const struct pci_device_id adv_pci_dio_pci_table[] = {
487 { PCI_VDEVICE(ADVANTECH, 0x1730), TYPE_PCI1730 },
488 { PCI_VDEVICE(ADVANTECH, 0x1733), TYPE_PCI1733 },
489 { PCI_VDEVICE(ADVANTECH, 0x1734), TYPE_PCI1734 },
490 { PCI_VDEVICE(ADVANTECH, 0x1735), TYPE_PCI1735 },
491 { PCI_VDEVICE(ADVANTECH, 0x1736), TYPE_PCI1736 },
492 { PCI_VDEVICE(ADVANTECH, 0x1739), TYPE_PCI1739 },
493 { PCI_VDEVICE(ADVANTECH, 0x1750), TYPE_PCI1750 },
494 { PCI_VDEVICE(ADVANTECH, 0x1751), TYPE_PCI1751 },
495 { PCI_VDEVICE(ADVANTECH, 0x1752), TYPE_PCI1752 },
496 { PCI_VDEVICE(ADVANTECH, 0x1753), TYPE_PCI1753 },
497 { PCI_VDEVICE(ADVANTECH, 0x1754), TYPE_PCI1754 },
498 { PCI_VDEVICE(ADVANTECH, 0x1756), TYPE_PCI1756 },
499 { PCI_VDEVICE(ADVANTECH, 0x1762), TYPE_PCI1762 },
500 { 0 }
502 MODULE_DEVICE_TABLE(pci, adv_pci_dio_pci_table);
504 static struct pci_driver adv_pci_dio_pci_driver = {
505 .name = "adv_pci_dio",
506 .id_table = adv_pci_dio_pci_table,
507 .probe = adv_pci_dio_pci_probe,
508 .remove = comedi_pci_auto_unconfig,
510 module_comedi_pci_driver(adv_pci_dio_driver, adv_pci_dio_pci_driver);
512 MODULE_AUTHOR("Comedi http://www.comedi.org");
513 MODULE_DESCRIPTION("Comedi driver for Advantech Digital I/O Cards");
514 MODULE_LICENSE("GPL");