2 * comedi/drivers/adv_pci_dio.c
4 * Author: Michal Dobes <dobes@tesnet.cz>
6 * Hardware driver for Advantech PCI DIO cards.
11 * Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1735U,
12 * PCI-1736UP, PCI-1739U, PCI-1750, PCI-1751, PCI-1752,
13 * PCI-1753/E, PCI-1754, PCI-1756, PCI-1762
14 * Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733,
15 * PCI-1734, PCI-1735U, PCI-1736UP, PCI-1739U, PCI-1750,
16 * PCI-1751, PCI-1752, PCI-1753,
17 * PCI-1753+PCI-1753E, PCI-1754, PCI-1756,
19 * Author: Michal Dobes <dobes@tesnet.cz>
20 * Updated: Mon, 09 Jan 2012 12:40:46 +0000
23 * Configuration Options: not applicable, uses PCI auto config
26 #include <linux/module.h>
27 #include <linux/delay.h>
29 #include "../comedi_pci.h"
32 #include "comedi_8254.h"
34 /* hardware types of the cards */
36 TYPE_PCI1730
, TYPE_PCI1733
, TYPE_PCI1734
, TYPE_PCI1735
, TYPE_PCI1736
,
41 TYPE_PCI1753
, TYPE_PCI1753E
,
42 TYPE_PCI1754
, TYPE_PCI1756
,
46 #define MAX_DI_SUBDEVS 2 /* max number of DI subdevices per card */
47 #define MAX_DO_SUBDEVS 2 /* max number of DO subdevices per card */
48 #define MAX_DIO_SUBDEVG 2 /* max number of DIO subdevices group per
51 /* Register offset definitions */
52 /* Advantech PCI-1730/3/4 */
53 #define PCI1730_IDI 0 /* R: Isolated digital input 0-15 */
54 #define PCI1730_IDO 0 /* W: Isolated digital output 0-15 */
55 #define PCI1730_DI 2 /* R: Digital input 0-15 */
56 #define PCI1730_DO 2 /* W: Digital output 0-15 */
57 #define PCI1733_IDI 0 /* R: Isolated digital input 0-31 */
58 #define PCI1730_3_INT_EN 0x08 /* R/W: enable/disable interrupts */
59 #define PCI1730_3_INT_RF 0x0c /* R/W: set falling/raising edge for
61 #define PCI1730_3_INT_CLR 0x10 /* R/W: clear interrupts */
62 #define PCI1734_IDO 0 /* W: Isolated digital output 0-31 */
64 /* Advantech PCI-1735U */
65 #define PCI1735_DI 0 /* R: Digital input 0-31 */
66 #define PCI1735_DO 0 /* W: Digital output 0-31 */
68 /* Advantech PCI-1736UP */
69 #define PCI1736_IDI 0 /* R: Isolated digital input 0-15 */
70 #define PCI1736_IDO 0 /* W: Isolated digital output 0-15 */
71 #define PCI1736_3_INT_EN 0x08 /* R/W: enable/disable interrupts */
72 #define PCI1736_3_INT_RF 0x0c /* R/W: set falling/raising edge for
74 #define PCI1736_3_INT_CLR 0x10 /* R/W: clear interrupts */
76 /* Advantech PCI-1739U */
77 #define PCI1739_DIO 0 /* R/W: begin of 8255 registers block */
78 #define PCI1739_ICR 32 /* W: Interrupt control register */
79 #define PCI1739_ISR 32 /* R: Interrupt status register */
81 /* Advantech PCI-1750 */
82 #define PCI1750_IDI 0 /* R: Isolated digital input 0-15 */
83 #define PCI1750_IDO 0 /* W: Isolated digital output 0-15 */
84 #define PCI1750_ICR 32 /* W: Interrupt control register */
85 #define PCI1750_ISR 32 /* R: Interrupt status register */
87 /* Advantech PCI-1751/3/3E */
88 #define PCI1751_DIO 0 /* R/W: begin of 8255 registers block */
89 #define PCI1751_ICR 32 /* W: Interrupt control register */
90 #define PCI1751_ISR 32 /* R: Interrupt status register */
91 #define PCI1753_DIO 0 /* R/W: begin of 8255 registers block */
92 #define PCI1753_ICR0 16 /* R/W: Interrupt control register group 0 */
93 #define PCI1753_ICR1 17 /* R/W: Interrupt control register group 1 */
94 #define PCI1753_ICR2 18 /* R/W: Interrupt control register group 2 */
95 #define PCI1753_ICR3 19 /* R/W: Interrupt control register group 3 */
96 #define PCI1753E_DIO 32 /* R/W: begin of 8255 registers block */
97 #define PCI1753E_ICR0 48 /* R/W: Interrupt control register group 0 */
98 #define PCI1753E_ICR1 49 /* R/W: Interrupt control register group 1 */
99 #define PCI1753E_ICR2 50 /* R/W: Interrupt control register group 2 */
100 #define PCI1753E_ICR3 51 /* R/W: Interrupt control register group 3 */
102 /* Advantech PCI-1752/4/6 */
103 #define PCI1752_IDO 0 /* R/W: Digital output 0-31 */
104 #define PCI1752_IDO2 4 /* R/W: Digital output 32-63 */
105 #define PCI1754_IDI 0 /* R: Digital input 0-31 */
106 #define PCI1754_IDI2 4 /* R: Digital input 32-64 */
107 #define PCI1756_IDI 0 /* R: Digital input 0-31 */
108 #define PCI1756_IDO 4 /* R/W: Digital output 0-31 */
109 #define PCI1754_6_ICR0 0x08 /* R/W: Interrupt control register group 0 */
110 #define PCI1754_6_ICR1 0x0a /* R/W: Interrupt control register group 1 */
111 #define PCI1754_ICR2 0x0c /* R/W: Interrupt control register group 2 */
112 #define PCI1754_ICR3 0x0e /* R/W: Interrupt control register group 3 */
113 #define PCI1752_6_CFC 0x12 /* R/W: set/read channel freeze function */
115 /* Advantech PCI-1762 registers */
116 #define PCI1762_RO 0 /* R/W: Relays status/output */
117 #define PCI1762_IDI 2 /* R: Isolated input status */
118 #define PCI1762_ICR 6 /* W: Interrupt control register */
119 #define PCI1762_ISR 6 /* R: Interrupt status register */
121 struct diosubd_data
{
122 int chans
; /* num of chans or 8255 devices */
123 unsigned long addr
; /* PCI address ofset */
126 struct dio_boardtype
{
127 const char *name
; /* board name */
128 enum hw_cards_id cardtype
;
130 struct diosubd_data sdi
[MAX_DI_SUBDEVS
]; /* DI chans */
131 struct diosubd_data sdo
[MAX_DO_SUBDEVS
]; /* DO chans */
132 struct diosubd_data sdio
[MAX_DIO_SUBDEVG
]; /* DIO 8255 chans */
133 unsigned long id_reg
;
134 unsigned long timer_regbase
;
135 unsigned int is_16bit
:1;
138 static const struct dio_boardtype boardtypes
[] = {
141 .cardtype
= TYPE_PCI1730
,
143 .sdi
[0] = { 16, PCI1730_DI
, },
144 .sdi
[1] = { 16, PCI1730_IDI
, },
145 .sdo
[0] = { 16, PCI1730_DO
, },
146 .sdo
[1] = { 16, PCI1730_IDO
, },
151 .cardtype
= TYPE_PCI1733
,
153 .sdi
[1] = { 32, PCI1733_IDI
, },
158 .cardtype
= TYPE_PCI1734
,
160 .sdo
[1] = { 32, PCI1734_IDO
, },
165 .cardtype
= TYPE_PCI1735
,
167 .sdi
[0] = { 32, PCI1735_DI
, },
168 .sdo
[0] = { 32, PCI1735_DO
, },
170 .timer_regbase
= 0x04,
174 .cardtype
= TYPE_PCI1736
,
176 .sdi
[1] = { 16, PCI1736_IDI
, },
177 .sdo
[1] = { 16, PCI1736_IDO
, },
182 .cardtype
= TYPE_PCI1739
,
184 .sdio
[0] = { 2, PCI1739_DIO
, },
189 .cardtype
= TYPE_PCI1750
,
191 .sdi
[1] = { 16, PCI1750_IDI
, },
192 .sdo
[1] = { 16, PCI1750_IDO
, },
196 .cardtype
= TYPE_PCI1751
,
198 .sdio
[0] = { 2, PCI1751_DIO
, },
199 .timer_regbase
= 0x18,
203 .cardtype
= TYPE_PCI1752
,
205 .sdo
[0] = { 32, PCI1752_IDO
, },
206 .sdo
[1] = { 32, PCI1752_IDO2
, },
212 .cardtype
= TYPE_PCI1753
,
214 .sdio
[0] = { 4, PCI1753_DIO
, },
218 .cardtype
= TYPE_PCI1753E
,
220 .sdio
[0] = { 4, PCI1753_DIO
, },
221 .sdio
[1] = { 4, PCI1753E_DIO
, },
225 .cardtype
= TYPE_PCI1754
,
227 .sdi
[0] = { 32, PCI1754_IDI
, },
228 .sdi
[1] = { 32, PCI1754_IDI2
, },
234 .cardtype
= TYPE_PCI1756
,
236 .sdi
[1] = { 32, PCI1756_IDI
, },
237 .sdo
[1] = { 32, PCI1756_IDO
, },
243 .cardtype
= TYPE_PCI1762
,
245 .sdi
[1] = { 16, PCI1762_IDI
, },
246 .sdo
[1] = { 16, PCI1762_RO
, },
252 static int pci_dio_insn_bits_di_b(struct comedi_device
*dev
,
253 struct comedi_subdevice
*s
,
254 struct comedi_insn
*insn
,
257 unsigned long reg
= (unsigned long)s
->private;
258 unsigned long iobase
= dev
->iobase
+ reg
;
260 data
[1] = inb(iobase
);
262 data
[1] |= (inb(iobase
+ 1) << 8);
264 data
[1] |= (inb(iobase
+ 2) << 16);
266 data
[1] |= (inb(iobase
+ 3) << 24);
271 static int pci_dio_insn_bits_di_w(struct comedi_device
*dev
,
272 struct comedi_subdevice
*s
,
273 struct comedi_insn
*insn
,
276 unsigned long reg
= (unsigned long)s
->private;
277 unsigned long iobase
= dev
->iobase
+ reg
;
279 data
[1] = inw(iobase
);
281 data
[1] |= (inw(iobase
+ 2) << 16);
286 static int pci_dio_insn_bits_do_b(struct comedi_device
*dev
,
287 struct comedi_subdevice
*s
,
288 struct comedi_insn
*insn
,
291 unsigned long reg
= (unsigned long)s
->private;
292 unsigned long iobase
= dev
->iobase
+ reg
;
294 if (comedi_dio_update_state(s
, data
)) {
295 outb(s
->state
& 0xff, iobase
);
297 outb((s
->state
>> 8) & 0xff, iobase
+ 1);
299 outb((s
->state
>> 16) & 0xff, iobase
+ 2);
301 outb((s
->state
>> 24) & 0xff, iobase
+ 3);
309 static int pci_dio_insn_bits_do_w(struct comedi_device
*dev
,
310 struct comedi_subdevice
*s
,
311 struct comedi_insn
*insn
,
314 unsigned long reg
= (unsigned long)s
->private;
315 unsigned long iobase
= dev
->iobase
+ reg
;
317 if (comedi_dio_update_state(s
, data
)) {
318 outw(s
->state
& 0xffff, iobase
);
320 outw((s
->state
>> 16) & 0xffff, iobase
+ 2);
328 static int pci_dio_reset(struct comedi_device
*dev
)
330 const struct dio_boardtype
*board
= dev
->board_ptr
;
332 switch (board
->cardtype
) {
334 outb(0, dev
->iobase
+ PCI1730_DO
); /* clear outputs */
335 outb(0, dev
->iobase
+ PCI1730_DO
+ 1);
336 outb(0, dev
->iobase
+ PCI1730_IDO
);
337 outb(0, dev
->iobase
+ PCI1730_IDO
+ 1);
340 /* disable interrupts */
341 outb(0, dev
->iobase
+ PCI1730_3_INT_EN
);
342 /* clear interrupts */
343 outb(0x0f, dev
->iobase
+ PCI1730_3_INT_CLR
);
344 /* set rising edge trigger */
345 outb(0, dev
->iobase
+ PCI1730_3_INT_RF
);
348 outb(0, dev
->iobase
+ PCI1734_IDO
); /* clear outputs */
349 outb(0, dev
->iobase
+ PCI1734_IDO
+ 1);
350 outb(0, dev
->iobase
+ PCI1734_IDO
+ 2);
351 outb(0, dev
->iobase
+ PCI1734_IDO
+ 3);
354 outb(0, dev
->iobase
+ PCI1735_DO
); /* clear outputs */
355 outb(0, dev
->iobase
+ PCI1735_DO
+ 1);
356 outb(0, dev
->iobase
+ PCI1735_DO
+ 2);
357 outb(0, dev
->iobase
+ PCI1735_DO
+ 3);
361 outb(0, dev
->iobase
+ PCI1736_IDO
);
362 outb(0, dev
->iobase
+ PCI1736_IDO
+ 1);
363 /* disable interrupts */
364 outb(0, dev
->iobase
+ PCI1736_3_INT_EN
);
365 /* clear interrupts */
366 outb(0x0f, dev
->iobase
+ PCI1736_3_INT_CLR
);
367 /* set rising edge trigger */
368 outb(0, dev
->iobase
+ PCI1736_3_INT_RF
);
372 /* disable & clear interrupts */
373 outb(0x88, dev
->iobase
+ PCI1739_ICR
);
378 /* disable & clear interrupts */
379 outb(0x88, dev
->iobase
+ PCI1750_ICR
);
382 outw(0, dev
->iobase
+ PCI1752_6_CFC
); /* disable channel freeze
384 outw(0, dev
->iobase
+ PCI1752_IDO
); /* clear outputs */
385 outw(0, dev
->iobase
+ PCI1752_IDO
+ 2);
386 outw(0, dev
->iobase
+ PCI1752_IDO2
);
387 outw(0, dev
->iobase
+ PCI1752_IDO2
+ 2);
390 outb(0x88, dev
->iobase
+ PCI1753E_ICR0
); /* disable & clear
392 outb(0x80, dev
->iobase
+ PCI1753E_ICR1
);
393 outb(0x80, dev
->iobase
+ PCI1753E_ICR2
);
394 outb(0x80, dev
->iobase
+ PCI1753E_ICR3
);
397 outb(0x88, dev
->iobase
+ PCI1753_ICR0
); /* disable & clear
399 outb(0x80, dev
->iobase
+ PCI1753_ICR1
);
400 outb(0x80, dev
->iobase
+ PCI1753_ICR2
);
401 outb(0x80, dev
->iobase
+ PCI1753_ICR3
);
404 outw(0x08, dev
->iobase
+ PCI1754_6_ICR0
); /* disable and clear
406 outw(0x08, dev
->iobase
+ PCI1754_6_ICR1
);
407 outw(0x08, dev
->iobase
+ PCI1754_ICR2
);
408 outw(0x08, dev
->iobase
+ PCI1754_ICR3
);
411 outw(0, dev
->iobase
+ PCI1752_6_CFC
); /* disable channel freeze
413 outw(0x08, dev
->iobase
+ PCI1754_6_ICR0
); /* disable and clear
415 outw(0x08, dev
->iobase
+ PCI1754_6_ICR1
);
416 outw(0, dev
->iobase
+ PCI1756_IDO
); /* clear outputs */
417 outw(0, dev
->iobase
+ PCI1756_IDO
+ 2);
420 outw(0x0101, dev
->iobase
+ PCI1762_ICR
); /* disable & clear
428 static unsigned long pci_dio_override_cardtype(struct pci_dev
*pcidev
,
429 unsigned long cardtype
)
432 * Change cardtype from TYPE_PCI1753 to TYPE_PCI1753E if expansion
433 * board available. Need to enable PCI device and request the main
434 * registers PCI BAR temporarily to perform the test.
436 if (cardtype
!= TYPE_PCI1753
)
438 if (pci_enable_device(pcidev
) < 0)
440 if (pci_request_region(pcidev
, 2, "adv_pci_dio") == 0) {
442 * This test is based on Advantech's "advdaq" driver source
443 * (which declares its module licence as "GPL" although the
444 * driver source does not include a "COPYING" file).
446 unsigned long reg
= pci_resource_start(pcidev
, 2) + 53;
449 if ((inb(reg
) & 0x07) == 0x02) {
451 if ((inb(reg
) & 0x07) == 0x05)
452 cardtype
= TYPE_PCI1753E
;
454 pci_release_region(pcidev
, 2);
456 pci_disable_device(pcidev
);
460 static int pci_dio_auto_attach(struct comedi_device
*dev
,
461 unsigned long context
)
463 struct pci_dev
*pcidev
= comedi_to_pci_dev(dev
);
464 const struct dio_boardtype
*board
= NULL
;
465 const struct diosubd_data
*d
;
466 struct comedi_subdevice
*s
;
467 int ret
, subdev
, i
, j
;
469 if (context
< ARRAY_SIZE(boardtypes
))
470 board
= &boardtypes
[context
];
473 dev
->board_ptr
= board
;
474 dev
->board_name
= board
->name
;
476 ret
= comedi_pci_enable(dev
);
479 if (board
->cardtype
== TYPE_PCI1736
)
480 dev
->iobase
= pci_resource_start(pcidev
, 0);
482 dev
->iobase
= pci_resource_start(pcidev
, 2);
484 ret
= comedi_alloc_subdevices(dev
, board
->nsubdevs
);
489 for (i
= 0; i
< MAX_DI_SUBDEVS
; i
++) {
492 s
= &dev
->subdevices
[subdev
++];
493 s
->type
= COMEDI_SUBD_DI
;
494 s
->subdev_flags
= SDF_READABLE
;
495 s
->n_chan
= d
->chans
;
497 s
->range_table
= &range_digital
;
498 s
->insn_bits
= board
->is_16bit
499 ? pci_dio_insn_bits_di_w
500 : pci_dio_insn_bits_di_b
;
501 s
->private = (void *)d
->addr
;
505 for (i
= 0; i
< MAX_DO_SUBDEVS
; i
++) {
508 s
= &dev
->subdevices
[subdev
++];
509 s
->type
= COMEDI_SUBD_DO
;
510 s
->subdev_flags
= SDF_WRITABLE
;
511 s
->n_chan
= d
->chans
;
513 s
->range_table
= &range_digital
;
514 s
->insn_bits
= board
->is_16bit
515 ? pci_dio_insn_bits_do_w
516 : pci_dio_insn_bits_do_b
;
517 s
->private = (void *)d
->addr
;
521 for (i
= 0; i
< MAX_DIO_SUBDEVG
; i
++) {
523 for (j
= 0; j
< d
->chans
; j
++) {
524 s
= &dev
->subdevices
[subdev
++];
525 ret
= subdev_8255_init(dev
, s
, NULL
,
526 d
->addr
+ j
* I8255_SIZE
);
533 s
= &dev
->subdevices
[subdev
++];
534 s
->type
= COMEDI_SUBD_DI
;
535 s
->subdev_flags
= SDF_READABLE
| SDF_INTERNAL
;
538 s
->range_table
= &range_digital
;
539 s
->insn_bits
= board
->is_16bit
? pci_dio_insn_bits_di_w
540 : pci_dio_insn_bits_di_b
;
541 s
->private = (void *)board
->id_reg
;
544 if (board
->timer_regbase
) {
545 s
= &dev
->subdevices
[subdev
++];
547 dev
->pacer
= comedi_8254_init(dev
->iobase
+
548 board
->timer_regbase
,
553 comedi_8254_subdevice_init(s
, dev
->pacer
);
561 static void pci_dio_detach(struct comedi_device
*dev
)
565 comedi_pci_detach(dev
);
568 static struct comedi_driver adv_pci_dio_driver
= {
569 .driver_name
= "adv_pci_dio",
570 .module
= THIS_MODULE
,
571 .auto_attach
= pci_dio_auto_attach
,
572 .detach
= pci_dio_detach
,
575 static int adv_pci_dio_pci_probe(struct pci_dev
*dev
,
576 const struct pci_device_id
*id
)
578 unsigned long cardtype
;
580 cardtype
= pci_dio_override_cardtype(dev
, id
->driver_data
);
581 return comedi_pci_auto_config(dev
, &adv_pci_dio_driver
, cardtype
);
584 static const struct pci_device_id adv_pci_dio_pci_table
[] = {
585 { PCI_VDEVICE(ADVANTECH
, 0x1730), TYPE_PCI1730
},
586 { PCI_VDEVICE(ADVANTECH
, 0x1733), TYPE_PCI1733
},
587 { PCI_VDEVICE(ADVANTECH
, 0x1734), TYPE_PCI1734
},
588 { PCI_VDEVICE(ADVANTECH
, 0x1735), TYPE_PCI1735
},
589 { PCI_VDEVICE(ADVANTECH
, 0x1736), TYPE_PCI1736
},
590 { PCI_VDEVICE(ADVANTECH
, 0x1739), TYPE_PCI1739
},
591 { PCI_VDEVICE(ADVANTECH
, 0x1750), TYPE_PCI1750
},
592 { PCI_VDEVICE(ADVANTECH
, 0x1751), TYPE_PCI1751
},
593 { PCI_VDEVICE(ADVANTECH
, 0x1752), TYPE_PCI1752
},
594 { PCI_VDEVICE(ADVANTECH
, 0x1753), TYPE_PCI1753
},
595 { PCI_VDEVICE(ADVANTECH
, 0x1754), TYPE_PCI1754
},
596 { PCI_VDEVICE(ADVANTECH
, 0x1756), TYPE_PCI1756
},
597 { PCI_VDEVICE(ADVANTECH
, 0x1762), TYPE_PCI1762
},
600 MODULE_DEVICE_TABLE(pci
, adv_pci_dio_pci_table
);
602 static struct pci_driver adv_pci_dio_pci_driver
= {
603 .name
= "adv_pci_dio",
604 .id_table
= adv_pci_dio_pci_table
,
605 .probe
= adv_pci_dio_pci_probe
,
606 .remove
= comedi_pci_auto_unconfig
,
608 module_comedi_pci_driver(adv_pci_dio_driver
, adv_pci_dio_pci_driver
);
610 MODULE_AUTHOR("Comedi http://www.comedi.org");
611 MODULE_DESCRIPTION("Comedi low-level driver");
612 MODULE_LICENSE("GPL");