[PATCH v3 4/5] staging: comedi: addi_apci_1564: add Change-of-State interrupt subdevice and required functions

2014-06-21 Thread Chase Southwood
This board supports an interrupt that can be generated by an AND/OR
combination of 16 of the input channels.

Create a separate subdevice to handle this interrupt.

The apci1564_di_config() function is used to configure which
inputs are used to generate the interrupt. Currently this function
is broken since it does not follow the comedi API for insn_config
functions. Fix this function by implementing the config instruction
INSN_CONFIG_DIGITAL_TRIG.

Add the remaining subdevice operations necessary for the interrupt
subdevice to support async commands.

Signed-off-by: Chase Southwood 
Cc: Ian Abbott 
Cc: H Hartley Sweeten 
---
 .../comedi/drivers/addi-data/hwdrv_apci1564.c  |  44 +---
 drivers/staging/comedi/drivers/addi_apci_1564.c| 250 +++--
 2 files changed, 232 insertions(+), 62 deletions(-)

diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c 
b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
index 732f43c..697ee76 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
@@ -26,12 +26,12 @@
 #define APCI1564_ADDRESS_RANGE 128
 
 /* Digital Input IRQ Function Selection */
-#define ADDIDATA_OR0
-#define ADDIDATA_AND   1
+#define APCI1564_DI_INT_OR (0 << 1)
+#define APCI1564_DI_INT_AND(1 << 1)
 
 /* Digital Input Interrupt Enable Disable. */
-#define APCI1564_DIGITAL_IP_INTERRUPT_ENABLE   0x4
-#define APCI1564_DIGITAL_IP_INTERRUPT_DISABLE  0xfffb
+#define APCI1564_DI_INT_ENABLE 0x4
+#define APCI1564_DI_INT_DISABLE0xfffb
 
 /* Digital Output Interrupt Enable Disable. */
 #define APCI1564_DIGITAL_OP_VCC_INTERRUPT_ENABLE   0x1
@@ -90,42 +90,6 @@
 #define APCI1564_TCW_WARN_TIMEBASE_REG(x)  (0x1c + ((x) * 0x20))
 
 /*
- * Configures the digital input Subdevice
- *
- * data[0] 1 = Enable interrupt, 0 = Disable interrupt
- * data[1] 0 = ADDIDATA Interrupt OR LOGIC, 1 = ADDIDATA Interrupt AND LOGIC
- * data[2] Interrupt mask for the mode 1
- * data[3] Interrupt mask for the mode 2
- */
-static int apci1564_di_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
-   struct apci1564_private *devpriv = dev->private;
-
-   devpriv->tsk_current = current;
-
-   /* Set the digital input logic */
-   if (data[0] == 1) {
-   data[2] = data[2] << 4;
-   data[3] = data[3] << 4;
-   outl(data[2], devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG);
-   outl(data[3], devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG);
-   if (data[1] == ADDIDATA_OR)
-   outl(0x4, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
-   else
-   outl(0x6, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
-   } else {
-   outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG);
-   outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG);
-   outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
-   }
-
-   return insn->n;
-}
-
-/*
  * Configures The Digital Output Subdevice.
  *
  * data[1] 0 = Disable VCC Interrupt, 1 = Enable VCC Interrupt
diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c 
b/drivers/staging/comedi/drivers/addi_apci_1564.c
index 1971da3..fec478c 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1564.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1564.c
@@ -8,6 +8,9 @@
 
 struct apci1564_private {
unsigned int amcc_iobase;   /* base of AMCC I/O registers */
+   unsigned int mode1; /* riding-edge/high level channels */
+   unsigned int mode2; /* falling-edge/low level channels */
+   unsigned int ctrl;  /* interrupt mode OR (edge) . AND 
(level) */
unsigned int do_int_type;
unsigned char timer_select_mode;
unsigned char mode_select_register;
@@ -16,6 +19,38 @@ struct apci1564_private {
 
 #include "addi-data/hwdrv_apci1564.c"
 
+static int apci1564_reset(struct comedi_device *dev)
+{
+   struct apci1564_private *devpriv = dev->private;
+
+   devpriv->do_int_type = 0;
+
+   /* Disable the input interrupts and reset status register */
+   outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
+   inl(devpriv->amcc_iobase + APCI1564_DI_INT_STATUS_REG);
+   outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE1_REG);
+   outl(0x0, devpriv->amcc_iobase + APCI1564_DI_INT_MODE2_REG);
+
+   /* Reset the output channels and disable interrupts */
+   outl(0x0, devpriv->amcc_iobase + APCI1564_DO_REG);
+   outl(0x0, 

[PATCH v3 4/5] staging: comedi: addi_apci_1564: add Change-of-State interrupt subdevice and required functions

2014-06-21 Thread Chase Southwood
This board supports an interrupt that can be generated by an AND/OR
combination of 16 of the input channels.

Create a separate subdevice to handle this interrupt.

The apci1564_di_config() function is used to configure which
inputs are used to generate the interrupt. Currently this function
is broken since it does not follow the comedi API for insn_config
functions. Fix this function by implementing the config instruction
INSN_CONFIG_DIGITAL_TRIG.

Add the remaining subdevice operations necessary for the interrupt
subdevice to support async commands.

Signed-off-by: Chase Southwood chase.southw...@gmail.com
Cc: Ian Abbott abbo...@mev.co.uk
Cc: H Hartley Sweeten hswee...@visionengravers.com
---
 .../comedi/drivers/addi-data/hwdrv_apci1564.c  |  44 +---
 drivers/staging/comedi/drivers/addi_apci_1564.c| 250 +++--
 2 files changed, 232 insertions(+), 62 deletions(-)

diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c 
b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
index 732f43c..697ee76 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
@@ -26,12 +26,12 @@
 #define APCI1564_ADDRESS_RANGE 128
 
 /* Digital Input IRQ Function Selection */
-#define ADDIDATA_OR0
-#define ADDIDATA_AND   1
+#define APCI1564_DI_INT_OR (0  1)
+#define APCI1564_DI_INT_AND(1  1)
 
 /* Digital Input Interrupt Enable Disable. */
-#define APCI1564_DIGITAL_IP_INTERRUPT_ENABLE   0x4
-#define APCI1564_DIGITAL_IP_INTERRUPT_DISABLE  0xfffb
+#define APCI1564_DI_INT_ENABLE 0x4
+#define APCI1564_DI_INT_DISABLE0xfffb
 
 /* Digital Output Interrupt Enable Disable. */
 #define APCI1564_DIGITAL_OP_VCC_INTERRUPT_ENABLE   0x1
@@ -90,42 +90,6 @@
 #define APCI1564_TCW_WARN_TIMEBASE_REG(x)  (0x1c + ((x) * 0x20))
 
 /*
- * Configures the digital input Subdevice
- *
- * data[0] 1 = Enable interrupt, 0 = Disable interrupt
- * data[1] 0 = ADDIDATA Interrupt OR LOGIC, 1 = ADDIDATA Interrupt AND LOGIC
- * data[2] Interrupt mask for the mode 1
- * data[3] Interrupt mask for the mode 2
- */
-static int apci1564_di_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
-   struct apci1564_private *devpriv = dev-private;
-
-   devpriv-tsk_current = current;
-
-   /* Set the digital input logic */
-   if (data[0] == 1) {
-   data[2] = data[2]  4;
-   data[3] = data[3]  4;
-   outl(data[2], devpriv-amcc_iobase + APCI1564_DI_INT_MODE1_REG);
-   outl(data[3], devpriv-amcc_iobase + APCI1564_DI_INT_MODE2_REG);
-   if (data[1] == ADDIDATA_OR)
-   outl(0x4, devpriv-amcc_iobase + APCI1564_DI_IRQ_REG);
-   else
-   outl(0x6, devpriv-amcc_iobase + APCI1564_DI_IRQ_REG);
-   } else {
-   outl(0x0, devpriv-amcc_iobase + APCI1564_DI_INT_MODE1_REG);
-   outl(0x0, devpriv-amcc_iobase + APCI1564_DI_INT_MODE2_REG);
-   outl(0x0, devpriv-amcc_iobase + APCI1564_DI_IRQ_REG);
-   }
-
-   return insn-n;
-}
-
-/*
  * Configures The Digital Output Subdevice.
  *
  * data[1] 0 = Disable VCC Interrupt, 1 = Enable VCC Interrupt
diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c 
b/drivers/staging/comedi/drivers/addi_apci_1564.c
index 1971da3..fec478c 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1564.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1564.c
@@ -8,6 +8,9 @@
 
 struct apci1564_private {
unsigned int amcc_iobase;   /* base of AMCC I/O registers */
+   unsigned int mode1; /* riding-edge/high level channels */
+   unsigned int mode2; /* falling-edge/low level channels */
+   unsigned int ctrl;  /* interrupt mode OR (edge) . AND 
(level) */
unsigned int do_int_type;
unsigned char timer_select_mode;
unsigned char mode_select_register;
@@ -16,6 +19,38 @@ struct apci1564_private {
 
 #include addi-data/hwdrv_apci1564.c
 
+static int apci1564_reset(struct comedi_device *dev)
+{
+   struct apci1564_private *devpriv = dev-private;
+
+   devpriv-do_int_type = 0;
+
+   /* Disable the input interrupts and reset status register */
+   outl(0x0, devpriv-amcc_iobase + APCI1564_DI_IRQ_REG);
+   inl(devpriv-amcc_iobase + APCI1564_DI_INT_STATUS_REG);
+   outl(0x0, devpriv-amcc_iobase + APCI1564_DI_INT_MODE1_REG);
+   outl(0x0, devpriv-amcc_iobase + APCI1564_DI_INT_MODE2_REG);
+
+   /* Reset the output channels and disable interrupts */
+   outl(0x0, devpriv-amcc_iobase