[PATCH v3 4/5] staging: comedi: addi_apci_1564: add Change-of-State interrupt subdevice and required functions
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
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