Use comedi_timeout() to wait for the analog input end-of-conversion. Combine the logic for the pcl812 and acl812 end-of-conversion in the helper function to simplify the driver. Signed-off-by: H Hartley Sweeten <hsweeten@xxxxxxxxxxxxxxxxxxx> Cc: Ian Abbott <abbotti@xxxxxxxxx> Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/staging/comedi/drivers/pcl812.c | 68 +++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 53613b38..2ad6c73 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -394,16 +394,35 @@ static void setup_range_channel(struct comedi_device *dev, unsigned int rangechan, char wait); static int pcl812_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s); -/* -============================================================================== -*/ + +static int pcl812_ai_eoc(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned long context) +{ + struct pcl812_private *devpriv = dev->private; + unsigned int status; + + if (devpriv->ai_is16b) { + status = inb(dev->iobase + ACL8216_STATUS); + if ((status & ACL8216_DRDY) == 0) + return 0; + } else { + status = inb(dev->iobase + PCL812_AD_HI); + if ((status & PCL812_DRDY) == 0) + return 0; + } + return -EBUSY; +} + static int pcl812_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct pcl812_private *devpriv = dev->private; + int ret = 0; int n; - int timeout, hi; + int hi; /* select software trigger */ outb(devpriv->mode_reg_int | 1, dev->iobase + PCL812_MODE); @@ -413,33 +432,27 @@ static int pcl812_ai_insn_read(struct comedi_device *dev, /* start conversion */ outb(255, dev->iobase + PCL812_SOFTTRIG); udelay(5); - timeout = 50; /* wait max 50us, it must finish under 33us */ - while (timeout--) { - hi = inb(dev->iobase + PCL812_AD_HI); - if (!(hi & PCL812_DRDY)) - goto conv_finish; - udelay(1); + + ret = comedi_timeout(dev, s, insn, pcl812_ai_eoc, 0); + if (ret) { + dev_dbg(dev->class_dev, "A/D insn read timeout\n"); + break; } - dev_dbg(dev->class_dev, "A/D insn read timeout\n"); - outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE); - return -ETIME; -conv_finish: + hi = inb(dev->iobase + PCL812_AD_HI); data[n] = ((hi & 0xf) << 8) | inb(dev->iobase + PCL812_AD_LO); } outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE); - return n; + + return ret ? ret : n; } -/* -============================================================================== -*/ static int acl8216_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + int ret = 0; int n; - int timeout; /* select software trigger */ outb(1, dev->iobase + PCL812_MODE); @@ -449,23 +462,20 @@ static int acl8216_ai_insn_read(struct comedi_device *dev, /* start conversion */ outb(255, dev->iobase + PCL812_SOFTTRIG); udelay(5); - timeout = 50; /* wait max 50us, it must finish under 33us */ - while (timeout--) { - if (!(inb(dev->iobase + ACL8216_STATUS) & ACL8216_DRDY)) - goto conv_finish; - udelay(1); + + ret = comedi_timeout(dev, s, insn, pcl812_ai_eoc, 0); + if (ret) { + dev_dbg(dev->class_dev, "A/D insn read timeout\n"); + break; } - dev_dbg(dev->class_dev, "A/D insn read timeout\n"); - outb(0, dev->iobase + PCL812_MODE); - return -ETIME; -conv_finish: data[n] = (inb(dev->iobase + PCL812_AD_HI) << 8) | inb(dev->iobase + PCL812_AD_LO); } outb(0, dev->iobase + PCL812_MODE); - return n; + + return ret ? ret : n; } /* -- 1.8.5.2 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel