The interrupt support for Advantech PCI-1730 currrently supports only
rising edge inputs for the trigger sources.  Each of four interrupt
sources (each with its own Comedi subdevice) can be set to trigger on
either a rising edge or a falling edge.  Add support for choosing the
edge during set-up of the asynchronous command for the subdevice, using
the `CR_INVERT` bit of `scan_begin_arg` to indicate falling edge when
set, or rising edge when clear.  Also allow the `CR_EDGE` bit to be set,
but ignore it.  All other bits of `scan_begin_arg` must be zero.

Signed-off-by: Ian Abbott <abbo...@mev.co.uk>
---
 drivers/staging/comedi/drivers/adv_pci_dio.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c 
b/drivers/staging/comedi/drivers/adv_pci_dio.c
index a894d0844a81..8e222b6ff2b4 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -227,6 +227,7 @@ struct pci_dio_dev_private_data {
        int boardtype;
        int irq_subd;
        unsigned short int_ctrl;
+       unsigned short int_rf;
 };
 
 struct pci_dio_sd_private_data {
@@ -313,7 +314,15 @@ static int pci_dio_asy_cmdtest(struct comedi_device *dev,
        /* Step 3: check if arguments are trivially valid */
 
        err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
-       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       /*
+        * For scan_begin_arg, the trigger number must be 0 and the only
+        * allowed flags are CR_EDGE and CR_INVERT.  CR_EDGE is ignored,
+        * CR_INVERT sets the trigger to falling edge.
+        */
+       if (cmd->scan_begin_arg & ~(CR_EDGE | CR_INVERT)) {
+               cmd->scan_begin_arg &= (CR_EDGE | CR_INVERT);
+               err |= -EINVAL;
+       }
        err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
        err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
                                           cmd->chanlist_len);
@@ -335,12 +344,18 @@ static int pci_dio_asy_cmd(struct comedi_device *dev,
        struct pci_dio_dev_private_data *dev_private = dev->private;
        struct pci_dio_sd_private_data *sd_priv = s->private;
        const struct dio_boardtype *board = dev->board_ptr;
+       struct comedi_cmd *cmd = &s->async->cmd;
        unsigned long cpu_flags;
        unsigned short int_en;
 
        int_en = board->sdirq[s->index - dev_private->irq_subd].int_en;
 
        spin_lock_irqsave(&dev->spinlock, cpu_flags);
+       if (cmd->scan_begin_arg & CR_INVERT)
+               dev_private->int_rf |= int_en;  /* falling edge */
+       else
+               dev_private->int_rf &= ~int_en; /* rising edge */
+       outb(dev_private->int_rf, dev->iobase + PCI173X_INT_RF_REG);
        dev_private->int_ctrl |= int_en;        /* enable interrupt source */
        outb(dev_private->int_ctrl, dev->iobase + PCI173X_INT_EN_REG);
        spin_unlock_irqrestore(&dev->spinlock, cpu_flags);
@@ -483,7 +498,8 @@ static int pci_dio_reset(struct comedi_device *dev, 
unsigned long cardtype)
                /* Reset all 4 Int Flags */
                outb(0x0f, dev->iobase + PCI173X_INT_CLR_REG);
                /* Rising Edge => IRQ . On all 4 Pins */
-               outb(0x00, dev->iobase + PCI173X_INT_RF_REG);
+               dev_private->int_rf = 0x00;
+               outb(dev_private->int_rf, dev->iobase + PCI173X_INT_RF_REG);
                break;
        case TYPE_PCI1739:
        case TYPE_PCI1750:
-- 
2.29.2

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

Reply via email to