[PATCH] Staging: comedi: adv_pci_dio: Support Advantech PCI-1735U

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add support for the Advantech PCI-1735U card, including support for a
counter subdevice (based on an 82C54 counter timer chip).

The counter subdevice needs more testing, as the only person I know who
tried it couldn't get it to work!

Signed-off-by: Ian Abbott <abbotti@xxxxxxxxx>
---
 drivers/staging/comedi/drivers/adv_pci_dio.c |  180 ++++++++++++++++++++++++--
 1 files changed, 169 insertions(+), 11 deletions(-)

diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
index 40eeecf..e424a0c 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -7,17 +7,17 @@
 */
 /*
 Driver: adv_pci_dio
-Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1736UP,
-             PCI-1750, PCI-1751, PCI-1752, PCI-1753/E, PCI-1754,
-             PCI-1756, PCI-1762
+Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1735U,
+             PCI-1736UP, PCI-1750, PCI-1751, PCI-1752, PCI-1753/E,
+             PCI-1754, PCI-1756, PCI-1762
 Author: Michal Dobes <dobes@xxxxxxxxx>
 Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733,
-  PCI-1734, PCI-1736UP, PCI-1750,
+  PCI-1734, PCI-1735U, PCI-1736UP, PCI-1750,
   PCI-1751, PCI-1752, PCI-1753,
   PCI-1753+PCI-1753E, PCI-1754, PCI-1756,
   PCI-1760, PCI-1762
 Status: untested
-Updated: Mon, 14 Apr 2008 10:43:08 +0100
+Updated: Tue, 04 May 2010 13:00:00 +0000
 
 This driver supports now only insn interface for DI/DO/DIO.
 
@@ -35,6 +35,7 @@ Configuration options:
 
 #include "comedi_pci.h"
 #include "8255.h"
+#include "8253.h"
 
 #undef PCI_DIO_EXTDEBUG		/* if defined, enable extensive debug logging */
 
@@ -49,7 +50,7 @@ Configuration options:
 
 /* hardware types of the cards */
 enum hw_cards_id {
-	TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1736,
+	TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1735, TYPE_PCI1736,
 	TYPE_PCI1750,
 	TYPE_PCI1751,
 	TYPE_PCI1752,
@@ -67,7 +68,10 @@ enum hw_io_access {
 #define MAX_DI_SUBDEVS	2	/* max number of DI subdevices per card */
 #define MAX_DO_SUBDEVS	2	/* max number of DO subdevices per card */
 #define MAX_DIO_SUBDEVG	2	/* max number of DIO subdevices group per card */
+#define MAX_8254_SUBDEVS   1	/* max number of 8254 counter subdevs per card */
+				/* (could be more than one 8254 per subdevice) */
 
+#define SIZE_8254	   4	/* 8254 IO space length */
 #define SIZE_8255	   4	/* 8255 IO space length */
 
 #define PCIDIO_MAINREG	   2	/* main I/O region for all Advantech cards? */
@@ -85,6 +89,12 @@ enum hw_io_access {
 #define PCI1734_IDO	   0	/* W:   Isolated digital output 0-31 */
 #define PCI173x_BOARDID	   4	/* R:   Board I/D switch for 1730/3/4 */
 
+/* Advantech PCI-1735U */
+#define PCI1735_DI	   0	/* R:   Digital input  0-31 */
+#define PCI1735_DO	   0	/* W:   Digital output 0-31 */
+#define PCI1735_C8254	   4	/* R/W: 8254 counter */
+#define PCI1735_BOARDID	   8    /* R:   Board I/D switch for 1735U */
+
 /*  Advantech PCI-1736UP */
 #define PCI1736_IDI        0	/* R:   Isolated digital input  0-15 */
 #define PCI1736_IDO        0	/* W:   Isolated digital output 0-15 */
@@ -192,7 +202,8 @@ static int pci_dio_detach(struct comedi_device *dev);
 struct diosubd_data {
 	int chans;		/*  num of chans */
 	int addr;		/*  PCI address ofset */
-	int regs;		/*  number of registers to read or 8255 subdevices */
+	int regs;		/*  number of registers to read or 8255
+				    subdevices or 8254 chips */
 	unsigned int specflags;	/*  addon subdevice flags */
 };
 
@@ -206,6 +217,7 @@ struct dio_boardtype {
 	struct diosubd_data sdo[MAX_DO_SUBDEVS];	/*  DO chans */
 	struct diosubd_data sdio[MAX_DIO_SUBDEVG];	/*  DIO 8255 chans */
 	struct diosubd_data boardid;	/*  card supports board ID switch */
+	struct diosubd_data s8254[MAX_8254_SUBDEVS];	/* 8254 subdevices */
 	enum hw_io_access io_access;
 };
 
@@ -214,6 +226,7 @@ static DEFINE_PCI_DEVICE_TABLE(pci_dio_pci_table) = {
 	PCI_VENDOR_ID_ADVANTECH, 0x1730, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 	PCI_VENDOR_ID_ADVANTECH, 0x1733, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 	PCI_VENDOR_ID_ADVANTECH, 0x1734, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
+	PCI_VENDOR_ID_ADVANTECH, 0x1735, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 	PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 	PCI_VENDOR_ID_ADVANTECH, 0x1750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 	PCI_VENDOR_ID_ADVANTECH, 0x1751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
@@ -235,14 +248,15 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
-	 IO_8b,
-	 },
+	 {{0, 0, 0, 0}},
+	 IO_8b},
 	{"pci1733", PCI_VENDOR_ID_ADVANTECH, 0x1733, PCIDIO_MAINREG,
 	 TYPE_PCI1733,
 	 {{0, 0, 0, 0}, {32, PCI1733_IDI, 4, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
+	 {{0, 0, 0, 0}},
 	 IO_8b},
 	{"pci1734", PCI_VENDOR_ID_ADVANTECH, 0x1734, PCIDIO_MAINREG,
 	 TYPE_PCI1734,
@@ -250,6 +264,15 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {32, PCI1734_IDO, 4, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
+	 {{0, 0, 0, 0}},
+	 IO_8b},
+	{"pci1735", PCI_VENDOR_ID_ADVANTECH, 0x1735, PCIDIO_MAINREG,
+	 TYPE_PCI1735,
+	 {{32, PCI1735_DI, 4, 0}, {0, 0, 0, 0}},
+	 {{32, PCI1735_DO, 4, 0}, {0, 0, 0, 0}},
+	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
+	 { 4, PCI1735_BOARDID, 1, SDF_INTERNAL},
+	 {{3, PCI1735_C8254, 1, 0}},
 	 IO_8b},
 	{"pci1736", PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI1736_MAINREG,
 	 TYPE_PCI1736,
@@ -257,14 +280,15 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {4, PCI1736_BOARDID, 1, SDF_INTERNAL},
-	 IO_8b,
-	 },
+	 {{0, 0, 0, 0}},
+	 IO_8b},
 	{"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG,
 	 TYPE_PCI1750,
 	 {{0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0}},
 	 {{0, 0, 0, 0}, {16, PCI1750_IDO, 2, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {0, 0, 0, 0},
+	 {{0, 0, 0, 0}},
 	 IO_8b},
 	{"pci1751", PCI_VENDOR_ID_ADVANTECH, 0x1751, PCIDIO_MAINREG,
 	 TYPE_PCI1751,
@@ -272,6 +296,7 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {{48, PCI1751_DIO, 2, 0}, {0, 0, 0, 0}},
 	 {0, 0, 0, 0},
+	 {{0, 0, 0, 0}},
 	 IO_8b},
 	{"pci1752", PCI_VENDOR_ID_ADVANTECH, 0x1752, PCIDIO_MAINREG,
 	 TYPE_PCI1752,
@@ -279,6 +304,7 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{32, PCI1752_IDO, 2, 0}, {32, PCI1752_IDO2, 2, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
+	 {{0, 0, 0, 0}},
 	 IO_16b},
 	{"pci1753", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
 	 TYPE_PCI1753,
@@ -286,6 +312,7 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {{96, PCI1753_DIO, 4, 0}, {0, 0, 0, 0}},
 	 {0, 0, 0, 0},
+	 {{0, 0, 0, 0}},
 	 IO_8b},
 	{"pci1753e", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
 	 TYPE_PCI1753E,
@@ -293,6 +320,7 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {{96, PCI1753_DIO, 4, 0}, {96, PCI1753E_DIO, 4, 0}},
 	 {0, 0, 0, 0},
+	 {{0, 0, 0, 0}},
 	 IO_8b},
 	{"pci1754", PCI_VENDOR_ID_ADVANTECH, 0x1754, PCIDIO_MAINREG,
 	 TYPE_PCI1754,
@@ -300,6 +328,7 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
+	 {{0, 0, 0, 0}},
 	 IO_16b},
 	{"pci1756", PCI_VENDOR_ID_ADVANTECH, 0x1756, PCIDIO_MAINREG,
 	 TYPE_PCI1756,
@@ -307,6 +336,7 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
+	 {{0, 0, 0, 0}},
 	 IO_16b},
 	{"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0,
 	 TYPE_PCI1760,
@@ -314,6 +344,7 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {0, 0, 0, 0},
+	 {{0, 0, 0, 0}},
 	 IO_8b},
 	{"pci1762", PCI_VENDOR_ID_ADVANTECH, 0x1762, PCIDIO_MAINREG,
 	 TYPE_PCI1762,
@@ -321,6 +352,7 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {16, PCI1762_RO, 1, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {4, PCI1762_BOARDID, 1, SDF_INTERNAL},
+	 {{0, 0, 0, 0}},
 	 IO_16b}
 };
 
@@ -440,6 +472,83 @@ static int pci_dio_insn_bits_do_w(struct comedi_device *dev,
 /*
 ==============================================================================
 */
+static int pci_8254_insn_read(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      struct comedi_insn *insn, unsigned int *data)
+{
+	const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+	unsigned int chan, chip, chipchan;
+	unsigned long flags;
+
+	chan = CR_CHAN(insn->chanspec);	/* channel on subdevice */
+	chip = chan / 3;		/* chip on subdevice */
+	chipchan = chan - (3 * chip);	/* channel on chip on subdevice */
+	spin_lock_irqsave(&s->spin_lock, flags);
+	data[0] = i8254_read(dev->iobase + d->addr + (SIZE_8254 * chip),
+			0, chipchan);
+	spin_unlock_irqrestore(&s->spin_lock, flags);
+	return 1;
+}
+
+/*
+==============================================================================
+*/
+static int pci_8254_insn_write(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       struct comedi_insn *insn, unsigned int *data)
+{
+	const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+	unsigned int chan, chip, chipchan;
+	unsigned long flags;
+
+	chan = CR_CHAN(insn->chanspec);	/* channel on subdevice */
+	chip = chan / 3;		/* chip on subdevice */
+	chipchan = chan - (3 * chip);	/* channel on chip on subdevice */
+	spin_lock_irqsave(&s->spin_lock, flags);
+	i8254_write(dev->iobase + d->addr + (SIZE_8254 * chip),
+			0, chipchan, data[0]);
+	spin_unlock_irqrestore(&s->spin_lock, flags);
+	return 1;
+}
+
+/*
+==============================================================================
+*/
+static int pci_8254_insn_config(struct comedi_device *dev,
+				struct comedi_subdevice *s,
+				struct comedi_insn *insn, unsigned int *data)
+{
+	const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+	unsigned int chan, chip, chipchan;
+	unsigned long iobase;
+	int ret = 0;
+	unsigned long flags;
+
+	chan = CR_CHAN(insn->chanspec);	/* channel on subdevice */
+	chip = chan / 3;		/* chip on subdevice */
+	chipchan = chan - (3 * chip);	/* channel on chip on subdevice */
+	iobase = dev->iobase + d->addr + (SIZE_8254 * chip);
+	spin_lock_irqsave(&s->spin_lock, flags);
+	switch (data[0]) {
+	case INSN_CONFIG_SET_COUNTER_MODE:
+		ret = i8254_set_mode(iobase, 0, chipchan, data[1]);
+		if (ret < 0)
+			ret = -EINVAL;
+		break;
+	case INSN_CONFIG_8254_READ_STATUS:
+		data[1] = i8254_status(iobase, 0, chipchan);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	spin_unlock_irqrestore(&s->spin_lock, flags);
+	return ret < 0 ? ret : insn->n;
+}
+
+/*
+==============================================================================
+*/
 static int pci1760_unchecked_mbxrequest(struct comedi_device *dev,
 					unsigned char *omb, unsigned char *imb,
 					int repeats)
@@ -708,6 +817,15 @@ static int pci_dio_reset(struct comedi_device *dev)
 		outb(0, dev->iobase + PCI1734_IDO + 2);
 		outb(0, dev->iobase + PCI1734_IDO + 3);
 		break;
+	case TYPE_PCI1735:
+		outb(0, dev->iobase + PCI1735_DO);	/*  clear outputs */
+		outb(0, dev->iobase + PCI1735_DO + 1);
+		outb(0, dev->iobase + PCI1735_DO + 2);
+		outb(0, dev->iobase + PCI1735_DO + 3);
+		i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 0, I8254_MODE0);
+		i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 1, I8254_MODE0);
+		i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 2, I8254_MODE0);
+		break;
 
 	case TYPE_PCI1736:
 		outb(0, dev->iobase + PCI1736_IDO);
@@ -877,6 +995,26 @@ static int pci_dio_add_do(struct comedi_device *dev, struct comedi_subdevice *s,
 /*
 ==============================================================================
 */
+static int pci_dio_add_8254(struct comedi_device *dev,
+			    struct comedi_subdevice * s,
+			    const struct diosubd_data *d, int subdev)
+{
+	s->type = COMEDI_SUBD_COUNTER;
+	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+	s->n_chan = d->chans;
+	s->maxdata = 65535;
+	s->len_chanlist = d->chans;
+	s->insn_read = pci_8254_insn_read;
+	s->insn_write = pci_8254_insn_write;
+	s->insn_config = pci_8254_insn_config;
+	s->private = (void *)d;
+
+	return 0;
+}
+
+/*
+==============================================================================
+*/
 static int CheckAndAllocCard(struct comedi_device *dev,
 			     struct comedi_devconfig *it,
 			     struct pci_dev *pcidev)
@@ -979,6 +1117,9 @@ static int pci_dio_attach(struct comedi_device *dev,
 			n_subdevices += this_board->sdio[i].regs;
 		if (this_board->boardid.chans)
 			n_subdevices++;
+		for (i = 0; i < MAX_8254_SUBDEVS; i++)
+			if (this_board->s8254[i].chans)
+				n_subdevices++;
 	}
 
 	ret = alloc_subdevices(dev, n_subdevices);
@@ -1022,6 +1163,13 @@ static int pci_dio_attach(struct comedi_device *dev,
 		subdev++;
 	}
 
+	for (i = 0; i < MAX_8254_SUBDEVS; i++)
+		if (this_board->s8254[i].chans) {
+			s = dev->subdevices + subdev;
+			pci_dio_add_8254(dev, s, &this_board->s8254[i], subdev);
+			subdev++;
+		}
+
 	if (this_board->cardtype == TYPE_PCI1760)
 		pci1760_attach(dev, it);
 
@@ -1067,6 +1215,16 @@ static int pci_dio_detach(struct comedi_device *dev)
 			}
 		}
 
+		if (this_board->boardid.chans) {
+			subdev++;
+		}
+
+		for (i = 0; i < MAX_8254_SUBDEVS; i++) {
+			if (this_board->s8254[i].chans) {
+				subdev++;
+			}
+		}
+
 		for (i = 0; i < dev->n_subdevices; i++) {
 			s = dev->subdevices + i;
 			s->private = NULL;
-- 
1.7.1

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel

[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux