staging: comedi: amplc_pc236: add callback to check and clear interrupt

Add an optional callback function pointer to the board data to be called
when checking if an interrupt has occurred and to clear it if it has.

Since the callback returns `bool`, change a few other `int` values to
`bool` to match.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Ian Abbott 2014-07-28 13:09:33 +01:00 committed by Greg Kroah-Hartman
parent 7f526aad19
commit 55901d15b6

View file

@ -83,6 +83,7 @@ struct pc236_board {
const char *name; const char *name;
enum pc236_bustype bustype; enum pc236_bustype bustype;
void (*intr_update_cb)(struct comedi_device *dev, bool enable); void (*intr_update_cb)(struct comedi_device *dev, bool enable);
bool (*intr_chk_clr_cb)(struct comedi_device *dev);
}; };
struct pc236_private { struct pc236_private {
@ -120,29 +121,21 @@ static void pc236_intr_update(struct comedi_device *dev, bool enable)
* the interrupt has been marked as enabled and was generated by the * the interrupt has been marked as enabled and was generated by the
* board. If so, the function prepares the hardware for the next * board. If so, the function prepares the hardware for the next
* interrupt. * interrupt.
* Returns 0 if the interrupt should be ignored. * Returns false if the interrupt should be ignored.
*/ */
static int pc236_intr_check(struct comedi_device *dev) static bool pc236_intr_check(struct comedi_device *dev)
{ {
const struct pc236_board *thisboard = comedi_board(dev); const struct pc236_board *thisboard = comedi_board(dev);
struct pc236_private *devpriv = dev->private; struct pc236_private *devpriv = dev->private;
int retval = 0; bool retval = false;
unsigned long flags; unsigned long flags;
unsigned int intcsr;
spin_lock_irqsave(&dev->spinlock, flags); spin_lock_irqsave(&dev->spinlock, flags);
if (devpriv->enable_irq) { if (devpriv->enable_irq) {
retval = 1; if (thisboard->intr_chk_clr_cb)
if (is_pci_board(thisboard)) { retval = thisboard->intr_chk_clr_cb(dev);
intcsr = inl(devpriv->lcr_iobase + PLX9052_INTCSR); else
if (!(intcsr & PLX9052_INTCSR_LI1STAT)) { retval = true;
retval = 0;
} else {
/* Clear interrupt and keep it enabled. */
outl(PCI236_INTR_ENABLE,
devpriv->lcr_iobase + PLX9052_INTCSR);
}
}
} }
spin_unlock_irqrestore(&dev->spinlock, flags); spin_unlock_irqrestore(&dev->spinlock, flags);
@ -236,7 +229,7 @@ static irqreturn_t pc236_interrupt(int irq, void *d)
{ {
struct comedi_device *dev = d; struct comedi_device *dev = d;
struct comedi_subdevice *s = dev->read_subdev; struct comedi_subdevice *s = dev->read_subdev;
int handled; bool handled;
handled = pc236_intr_check(dev); handled = pc236_intr_check(dev);
if (dev->attached && handled) { if (dev->attached && handled) {
@ -312,13 +305,28 @@ static void pci236_intr_update_cb(struct comedi_device *dev, bool enable)
{ {
struct pc236_private *devpriv = dev->private; struct pc236_private *devpriv = dev->private;
/* this will also clear the "local interrupt 1" latch */
outl(enable ? PCI236_INTR_ENABLE : PCI236_INTR_DISABLE, outl(enable ? PCI236_INTR_ENABLE : PCI236_INTR_DISABLE,
devpriv->lcr_iobase + PLX9052_INTCSR); devpriv->lcr_iobase + PLX9052_INTCSR);
} }
static bool pci236_intr_chk_clr_cb(struct comedi_device *dev)
{
struct pc236_private *devpriv = dev->private;
/* check if interrupt occurred */
if (!(inl(devpriv->lcr_iobase + PLX9052_INTCSR) &
PLX9052_INTCSR_LI1STAT))
return false;
/* clear the interrupt */
pci236_intr_update_cb(dev, devpriv->enable_irq);
return true;
}
static const struct pc236_board pc236_pci_board = { static const struct pc236_board pc236_pci_board = {
.name = "pci236", .name = "pci236",
.intr_update_cb = pci236_intr_update_cb, .intr_update_cb = pci236_intr_update_cb,
.intr_chk_clr_cb = pci236_intr_chk_clr_cb,
.bustype = pci_bustype, .bustype = pci_bustype,
}; };