Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4da77a7 authored by Ian Abbott's avatar Ian Abbott Committed by Greg Kroah-Hartman
Browse files

Staging: comedi: adv_pci_dio: Support Advantech PCI-1735U



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: default avatarIan Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent b2e68b00
Loading
Loading
Loading
Loading
+169 −11
Original line number Diff line number Diff line
@@ -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@tesnet.cz>
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}
};

@@ -437,6 +469,83 @@ static int pci_dio_insn_bits_do_w(struct comedi_device *dev,
	return 2;
}

/*
==============================================================================
*/
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;
}

/*
==============================================================================
*/
@@ -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);
@@ -874,6 +992,26 @@ static int pci_dio_add_do(struct comedi_device *dev, struct comedi_subdevice *s,
	return 0;
}

/*
==============================================================================
*/
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;
}

/*
==============================================================================
*/
@@ -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;