From 09c5d6c83ec3bd56ee1ebef8bec42956b32ca7eb Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 17 Aug 2015 16:58:22 -0700 Subject: [PATCH] staging: comedi: s526: wait for analog output conversions to complete It's possible for the user to write more than one value to an analog output channel with the (*insn_write) operation. Use comedi_timeout() to check the interrupt status register to ensure that each data conversion is complete before writing the next value. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/s526.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index 242db7d9dfb3..152be955f8ab 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -418,16 +418,19 @@ static int s526_ai_insn_config(struct comedi_device *dev, return result; } -static int s526_ai_eoc(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned long context) +static int s526_eoc(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned long context) { unsigned int status; status = inw(dev->iobase + S526_INT_STATUS_REG); - if (status & S526_INT_AI) + if (status & context) { + /* we got our eoc event, clear it */ + outw(context, dev->iobase + S526_INT_STATUS_REG); return 0; + } return -EBUSY; } @@ -455,12 +458,10 @@ static int s526_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, outw(ctrl, dev->iobase + S526_AI_CTRL_REG); /* wait for conversion to end */ - ret = comedi_timeout(dev, s, insn, s526_ai_eoc, 0); + ret = comedi_timeout(dev, s, insn, s526_eoc, S526_INT_AI); if (ret) return ret; - outw(S526_INT_AI, dev->iobase + S526_INT_STATUS_REG); - d = inw(dev->iobase + S526_AI_REG); /* munge data */ @@ -479,6 +480,7 @@ static int s526_ao_insn_write(struct comedi_device *dev, unsigned int chan = CR_CHAN(insn->chanspec); unsigned int ctrl = S526_AO_CTRL_CHAN(chan); unsigned int val = s->readback[chan]; + int ret; int i; outw(ctrl, dev->iobase + S526_AO_CTRL_REG); @@ -488,6 +490,11 @@ static int s526_ao_insn_write(struct comedi_device *dev, val = data[i]; outw(val, dev->iobase + S526_AO_REG); outw(ctrl, dev->iobase + S526_AO_CTRL_REG); + + /* wait for conversion to end */ + ret = comedi_timeout(dev, s, insn, s526_eoc, S526_INT_AO); + if (ret) + return ret; } s->readback[chan] = val; -- 2.30.2