From: H Hartley Sweeten Date: Mon, 17 Aug 2015 23:58:22 +0000 (-0700) Subject: staging: comedi: s526: wait for analog output conversions to complete X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=09c5d6c83ec3bd56ee1ebef8bec42956b32ca7eb;p=openwrt%2Fstaging%2Fblogic.git 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 --- 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;