Commit afee35c7 authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman

staging: comedi: pcl726: add support for the external interrupt signal

The ACL-6126 board supports an external interrupt signal on pin 17 of
its I/O connector (CN3). Add a new subdevice to this driver to support
asynchronous commands with this input.
Signed-off-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: default avatarIan Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent fc93af58
...@@ -67,6 +67,8 @@ Interrupts are not supported. ...@@ -67,6 +67,8 @@ Interrupts are not supported.
#include "../comedidev.h" #include "../comedidev.h"
#include "comedi_fc.h"
#define PCL726_AO_MSB_REG(x) (0x00 + ((x) * 2)) #define PCL726_AO_MSB_REG(x) (0x00 + ((x) * 2))
#define PCL726_AO_LSB_REG(x) (0x01 + ((x) * 2)) #define PCL726_AO_LSB_REG(x) (0x01 + ((x) * 2))
#define PCL726_DO_MSB_REG 0x0c #define PCL726_DO_MSB_REG 0x0c
...@@ -157,10 +159,94 @@ static const struct pcl726_board boardtypes[] = { ...@@ -157,10 +159,94 @@ static const struct pcl726_board boardtypes[] = {
struct pcl726_private { struct pcl726_private {
const struct comedi_lrange *rangelist[12]; const struct comedi_lrange *rangelist[12];
unsigned int ao_readback[12]; unsigned int ao_readback[12];
unsigned int cmd_running:1;
}; };
static int pcl818_intr_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
data[1] = 0;
return insn->n;
}
static int pcl818_intr_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
int err = 0;
/* Step 1 : check if triggers are trivially valid */
err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
if (err)
return 1;
/* Step 2a : make sure trigger sources are unique */
/* Step 2b : and mutually compatible */
if (err)
return 2;
/* Step 3: check if arguments are trivially valid */
err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, 1);
err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
if (err)
return 3;
/* step 4: ignored */
if (err)
return 4;
return 0;
}
static int pcl818_intr_cmd(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct pcl726_private *devpriv = dev->private;
devpriv->cmd_running = 1;
return 0;
}
static int pcl818_intr_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct pcl726_private *devpriv = dev->private;
devpriv->cmd_running = 0;
return 0;
}
static irqreturn_t pcl818_interrupt(int irq, void *d) static irqreturn_t pcl818_interrupt(int irq, void *d)
{ {
struct comedi_device *dev = d;
struct comedi_subdevice *s = dev->read_subdev;
struct pcl726_private *devpriv = dev->private;
if (devpriv->cmd_running) {
pcl818_intr_cancel(dev, s);
comedi_buf_put(s->async, 0);
s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
comedi_event(dev, s);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -262,6 +348,7 @@ static int pcl726_attach(struct comedi_device *dev, ...@@ -262,6 +348,7 @@ static int pcl726_attach(struct comedi_device *dev,
const struct pcl726_board *board = comedi_board(dev); const struct pcl726_board *board = comedi_board(dev);
struct pcl726_private *devpriv; struct pcl726_private *devpriv;
struct comedi_subdevice *s; struct comedi_subdevice *s;
int subdev;
int ret; int ret;
int i; int i;
...@@ -296,12 +383,17 @@ static int pcl726_attach(struct comedi_device *dev, ...@@ -296,12 +383,17 @@ static int pcl726_attach(struct comedi_device *dev,
devpriv->rangelist[i] = &range_unknown; devpriv->rangelist[i] = &range_unknown;
} }
ret = comedi_alloc_subdevices(dev, board->have_dio ? 3 : 1); subdev = board->have_dio ? 3 : 1;
if (dev->irq)
subdev++;
ret = comedi_alloc_subdevices(dev, subdev);
if (ret) if (ret)
return ret; return ret;
subdev = 0;
/* Analog Output subdevice */ /* Analog Output subdevice */
s = &dev->subdevices[0]; s = &dev->subdevices[subdev++];
s->type = COMEDI_SUBD_AO; s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND; s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
s->n_chan = board->ao_nchan; s->n_chan = board->ao_nchan;
...@@ -312,7 +404,7 @@ static int pcl726_attach(struct comedi_device *dev, ...@@ -312,7 +404,7 @@ static int pcl726_attach(struct comedi_device *dev,
if (board->have_dio) { if (board->have_dio) {
/* Digital Input subdevice */ /* Digital Input subdevice */
s = &dev->subdevices[1]; s = &dev->subdevices[subdev++];
s->type = COMEDI_SUBD_DI; s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE; s->subdev_flags = SDF_READABLE;
s->n_chan = 16; s->n_chan = 16;
...@@ -321,7 +413,7 @@ static int pcl726_attach(struct comedi_device *dev, ...@@ -321,7 +413,7 @@ static int pcl726_attach(struct comedi_device *dev,
s->range_table = &range_digital; s->range_table = &range_digital;
/* Digital Output subdevice */ /* Digital Output subdevice */
s = &dev->subdevices[2]; s = &dev->subdevices[subdev++];
s->type = COMEDI_SUBD_DO; s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE; s->subdev_flags = SDF_WRITABLE;
s->n_chan = 16; s->n_chan = 16;
...@@ -330,6 +422,21 @@ static int pcl726_attach(struct comedi_device *dev, ...@@ -330,6 +422,21 @@ static int pcl726_attach(struct comedi_device *dev,
s->range_table = &range_digital; s->range_table = &range_digital;
} }
if (dev->irq) {
/* Digial Input subdevice - Interrupt support */
s = &dev->subdevices[subdev++];
dev->read_subdev = s;
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
s->n_chan = 1;
s->maxdata = 1;
s->range_table = &range_digital;
s->insn_bits = pcl818_intr_insn_bits;
s->do_cmdtest = pcl818_intr_cmdtest;
s->do_cmd = pcl818_intr_cmd;
s->cancel = pcl818_intr_cancel;
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment