[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1401849307-22255-1-git-send-email-chase.southwood@gmail.com>
Date: Tue, 3 Jun 2014 21:35:07 -0500
From: Chase Southwood <chase.southwood@...il.com>
To: gregkh@...uxfoundation.org
Cc: abbotti@....co.uk, hsweeten@...ionengravers.com,
devel@...verdev.osuosl.org, linux-kernel@...r.kernel.org,
Chase Southwood <chase.southwood@...il.com>
Subject: [PATCH v2 5/5] staging: comedi: addi_apci_1564: move apci1564_interrupt() into addi_apci_1564.c
On moving the function into the driver proper, also check the device is
asserting the shared interrupt line.
This patch also fixes the interrupt handling for the digital input
change-of-state interrupts.
Signed-off-by: Chase Southwood <chase.southwood@...il.com>
Cc: Ian Abbott <abbotti@....co.uk>
Cc: H Hartley Sweeten <hsweeten@...ionengravers.com>
---
Hartley,
I know that this interrupt handler still needs major tidying up, but I would like to do that in a follow-on patch once I know that I have fixed DI interrupt handling properly. The cleanup itself will be a large task, hah. At any rate, I am not sure if the below is correct, but I think overall this version is a big step in a better direction. As usual, review is appreciated!!
Chase
.../comedi/drivers/addi-data/hwdrv_apci1564.c | 146 -------------------
drivers/staging/comedi/drivers/addi_apci_1564.c | 157 ++++++++++++++++++++-
2 files changed, 153 insertions(+), 150 deletions(-)
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
index 697ee76..ef419b4 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
@@ -357,149 +357,3 @@ static int apci1564_do_read(struct comedi_device *dev,
*data = devpriv->do_int_type;
return insn->n;
}
-
-/*
- * Interrupt handler for the interruptible digital inputs
- */
-static void apci1564_interrupt(int irq, void *d)
-{
- struct comedi_device *dev = d;
- struct apci1564_private *devpriv = dev->private;
- unsigned int ui_DO, ui_DI;
- unsigned int ui_Timer;
- unsigned int ui_C1, ui_C2, ui_C3, ui_C4;
- unsigned int ul_Command2 = 0;
-
- ui_DI = inl(devpriv->amcc_iobase + APCI1564_DI_IRQ_REG) & 0x01;
- ui_DO = inl(devpriv->amcc_iobase + APCI1564_DO_IRQ_REG) & 0x01;
- ui_Timer = inl(devpriv->amcc_iobase + APCI1564_TIMER_IRQ_REG) & 0x01;
- ui_C1 =
- inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER1)) & 0x1;
- ui_C2 =
- inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER2)) & 0x1;
- ui_C3 =
- inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER3)) & 0x1;
- ui_C4 =
- inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER4)) & 0x1;
- if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0
- && ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) {
- dev_err(dev->class_dev, "Interrupt from unknown source.\n");
- }
-
- if (ui_DI == 1) {
- ui_DI = inl(devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
- outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
- /* send signal to the sample */
- send_sig(SIGIO, devpriv->tsk_current, 0);
- /* enable the interrupt */
- outl(ui_DI, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
- return;
- }
-
- if (ui_DO == 1) {
- /* Check for Digital Output interrupt Type */
- /* 1: VCC interrupt */
- /* 2: CC interrupt */
- devpriv->do_int_type = inl(devpriv->amcc_iobase +
- APCI1564_DO_INT_STATUS_REG) & 0x3;
- /* Disable the Interrupt */
- outl(0x0, devpriv->amcc_iobase + APCI1564_DO_INT_CTRL_REG);
-
- /* Sends signal to user space */
- send_sig(SIGIO, devpriv->tsk_current, 0);
- }
-
- if (ui_Timer == 1) {
- devpriv->timer_select_mode = ADDIDATA_TIMER;
- if (devpriv->timer_select_mode) {
-
- /* Disable Timer Interrupt */
- ul_Command2 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
-
- /* Send a signal to from kernel to user space */
- send_sig(SIGIO, devpriv->tsk_current, 0);
-
- /* Enable Timer Interrupt */
-
- outl(ul_Command2, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- }
- }
-
- if (ui_C1 == 1) {
- devpriv->timer_select_mode = ADDIDATA_COUNTER;
- if (devpriv->timer_select_mode) {
-
- /* Disable Counter Interrupt */
- ul_Command2 =
- inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1));
- outl(0x0,
- dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1));
-
- /* Send a signal to from kernel to user space */
- send_sig(SIGIO, devpriv->tsk_current, 0);
-
- /* Enable Counter Interrupt */
- outl(ul_Command2,
- dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1));
- }
- }
-
- if (ui_C2 == 1) {
- devpriv->timer_select_mode = ADDIDATA_COUNTER;
- if (devpriv->timer_select_mode) {
-
- /* Disable Counter Interrupt */
- ul_Command2 =
- inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2));
- outl(0x0,
- dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2));
-
- /* Send a signal to from kernel to user space */
- send_sig(SIGIO, devpriv->tsk_current, 0);
-
- /* Enable Counter Interrupt */
- outl(ul_Command2,
- dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2));
- }
- }
-
- if (ui_C3 == 1) {
- devpriv->timer_select_mode = ADDIDATA_COUNTER;
- if (devpriv->timer_select_mode) {
-
- /* Disable Counter Interrupt */
- ul_Command2 =
- inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3));
- outl(0x0,
- dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3));
-
- /* Send a signal to from kernel to user space */
- send_sig(SIGIO, devpriv->tsk_current, 0);
-
- /* Enable Counter Interrupt */
- outl(ul_Command2,
- dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3));
- }
- }
-
- if (ui_C4 == 1) {
- devpriv->timer_select_mode = ADDIDATA_COUNTER;
- if (devpriv->timer_select_mode) {
-
- /* Disable Counter Interrupt */
- ul_Command2 =
- inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4));
- outl(0x0,
- dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4));
-
- /* Send a signal to from kernel to user space */
- send_sig(SIGIO, devpriv->tsk_current, 0);
-
- /* Enable Counter Interrupt */
- outl(ul_Command2,
- dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4));
- }
- }
- return;
-}
diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c
index fec478c..f71ee02 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1564.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1564.c
@@ -3,6 +3,7 @@
#include "../comedidev.h"
#include "comedi_fc.h"
+#include "amcc_s5933.h"
#include "addi-data/addi_common.h"
@@ -51,10 +52,158 @@ static int apci1564_reset(struct comedi_device *dev)
return 0;
}
-static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
+static irqreturn_t apci1564_interrupt(int irq, void *d)
{
- apci1564_interrupt(irq, d);
- return IRQ_RETVAL(1);
+ struct comedi_device *dev = d;
+ struct apci1564_private *devpriv = dev->private;
+ struct comedi_subdevice *s = dev->read_subdev;
+ unsigned int ui_DO, ui_DI;
+ unsigned int ui_Timer;
+ unsigned int ui_C1, ui_C2, ui_C3, ui_C4;
+ unsigned int ul_Command2 = 0;
+
+ /* check interrupt is from this device */
+ if ((inl(devpriv->amcc_iobase + AMCC_OP_REG_INTCSR) &
+ INTCSR_INTR_ASSERTED) == 0)
+ return IRQ_NONE;
+
+ /* check which interrupt was triggered */
+ ui_DI = inl(devpriv->amcc_iobase + APCI1564_DI_IRQ_REG) &
+ APCI1564_DI_INT_ENABLE;
+ ui_DO = inl(devpriv->amcc_iobase + APCI1564_DO_IRQ_REG) & 0x01;
+ ui_Timer = inl(devpriv->amcc_iobase + APCI1564_TIMER_IRQ_REG) & 0x01;
+ ui_C1 =
+ inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER1)) & 0x1;
+ ui_C2 =
+ inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER2)) & 0x1;
+ ui_C3 =
+ inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER3)) & 0x1;
+ ui_C4 =
+ inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER4)) & 0x1;
+ if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0
+ && ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) {
+ return IRQ_HANDLED;
+ }
+
+ if (ui_DI) {
+ /* disable the interrupt */
+ outl(ui_DI & APCI1564_DI_INT_DISABLE, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
+
+ s->state = inl(dev->iobase + APCI1564_DI_INT_STATUS_REG) & 0xffff;
+ comedi_buf_put(s, s->state);
+ s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
+ comedi_event(dev, s);
+
+ /* enable the interrupt */
+ outl(ui_DI, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
+ }
+
+ if (ui_DO == 1) {
+ /* Check for Digital Output interrupt Type */
+ /* 1: VCC interrupt */
+ /* 2: CC interrupt */
+ devpriv->do_int_type = inl(devpriv->amcc_iobase +
+ APCI1564_DO_INT_STATUS_REG) & 0x3;
+ /* Disable the Interrupt */
+ outl(0x0, devpriv->amcc_iobase + APCI1564_DO_INT_CTRL_REG);
+
+ /* Sends signal to user space */
+ send_sig(SIGIO, devpriv->tsk_current, 0);
+ }
+
+ if (ui_Timer == 1) {
+ devpriv->timer_select_mode = ADDIDATA_TIMER;
+ if (devpriv->timer_select_mode) {
+
+ /* Disable Timer Interrupt */
+ ul_Command2 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
+ outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
+
+ /* Send a signal to from kernel to user space */
+ send_sig(SIGIO, devpriv->tsk_current, 0);
+
+ /* Enable Timer Interrupt */
+
+ outl(ul_Command2, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
+ }
+ }
+
+ if (ui_C1 == 1) {
+ devpriv->timer_select_mode = ADDIDATA_COUNTER;
+ if (devpriv->timer_select_mode) {
+
+ /* Disable Counter Interrupt */
+ ul_Command2 =
+ inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1));
+ outl(0x0,
+ dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1));
+
+ /* Send a signal to from kernel to user space */
+ send_sig(SIGIO, devpriv->tsk_current, 0);
+
+ /* Enable Counter Interrupt */
+ outl(ul_Command2,
+ dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1));
+ }
+ }
+
+ if (ui_C2 == 1) {
+ devpriv->timer_select_mode = ADDIDATA_COUNTER;
+ if (devpriv->timer_select_mode) {
+
+ /* Disable Counter Interrupt */
+ ul_Command2 =
+ inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2));
+ outl(0x0,
+ dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2));
+
+ /* Send a signal to from kernel to user space */
+ send_sig(SIGIO, devpriv->tsk_current, 0);
+
+ /* Enable Counter Interrupt */
+ outl(ul_Command2,
+ dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2));
+ }
+ }
+
+ if (ui_C3 == 1) {
+ devpriv->timer_select_mode = ADDIDATA_COUNTER;
+ if (devpriv->timer_select_mode) {
+
+ /* Disable Counter Interrupt */
+ ul_Command2 =
+ inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3));
+ outl(0x0,
+ dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3));
+
+ /* Send a signal to from kernel to user space */
+ send_sig(SIGIO, devpriv->tsk_current, 0);
+
+ /* Enable Counter Interrupt */
+ outl(ul_Command2,
+ dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3));
+ }
+ }
+
+ if (ui_C4 == 1) {
+ devpriv->timer_select_mode = ADDIDATA_COUNTER;
+ if (devpriv->timer_select_mode) {
+
+ /* Disable Counter Interrupt */
+ ul_Command2 =
+ inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4));
+ outl(0x0,
+ dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4));
+
+ /* Send a signal to from kernel to user space */
+ send_sig(SIGIO, devpriv->tsk_current, 0);
+
+ /* Enable Counter Interrupt */
+ outl(ul_Command2,
+ dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4));
+ }
+ }
+ return IRQ_HANDLED;
}
static int apci1564_di_insn_bits(struct comedi_device *dev,
@@ -295,7 +444,7 @@ static int apci1564_auto_attach(struct comedi_device *dev,
apci1564_reset(dev);
if (pcidev->irq > 0) {
- ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED,
+ ret = request_irq(pcidev->irq, apci1564_interrupt, IRQF_SHARED,
dev->board_name, dev);
if (ret == 0)
dev->irq = pcidev->irq;
--
1.9.3
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists