Commit 860ba36c authored by Chase Southwood's avatar Chase Southwood Committed by Greg Kroah-Hartman
Browse files

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: default avatarChase Southwood <chase.southwood@gmail.com>
Reviewed-by: default avatarIan Abbott <abbotti@mev.co.uk>
Cc: H Hartley Sweeten <hsweeten@visionengravers.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 1e15687e
Loading
Loading
Loading
Loading
+0 −146
Original line number Diff line number Diff line
@@ -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;
}
+153 −4
Original line number Diff line number Diff line
@@ -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;