Commit d8644e41 authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman

staging: comedi: dt282x: use comedi_timeout()

The wait_for() macro in this driver is a bit nasty. It effects control flow
which according to the CodingStyle is a _very_ bad idea.

The mux_busy() and ad_done() macros are also bad since they rely on a local
variable having a specific name.

Remove these macros and use comedi_timeout() to wait for the analog input
mux busy completion and end-of-conversion. Both of these are detected by
reading the same register and testing different bits. Pass the bits to test
as the 'context' to the callback function.

The dt282x_ai_cmd() function also checks for the mux busy completion. The
'insn' is not available here but passing NULL is safe because nothing
uses it.
Signed-off-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 45b281e4
...@@ -63,7 +63,6 @@ Configuration options: ...@@ -63,7 +63,6 @@ Configuration options:
#include "comedi_fc.h" #include "comedi_fc.h"
#define DT2821_TIMEOUT 100 /* 500 us */
#define DT2821_SIZE 0x10 #define DT2821_SIZE 0x10
/* /*
...@@ -248,27 +247,6 @@ struct dt282x_private { ...@@ -248,27 +247,6 @@ struct dt282x_private {
* Some useless abstractions * Some useless abstractions
*/ */
#define chan_to_DAC(a) ((a)&1) #define chan_to_DAC(a) ((a)&1)
#define mux_busy() (inw(dev->iobase+DT2821_ADCSR)&DT2821_MUXBUSY)
#define ad_done() (inw(dev->iobase+DT2821_ADCSR)&DT2821_ADDONE)
/*
* danger! macro abuse... a is the expression to wait on, and b is
* the statement(s) to execute if it doesn't happen.
*/
#define wait_for(a, b) \
do { \
int _i; \
for (_i = 0; _i < DT2821_TIMEOUT; _i++) { \
if (a) { \
_i = 0; \
break; \
} \
udelay(5); \
} \
if (_i) { \
b \
} \
} while (0)
static int prep_ai_dma(struct comedi_device *dev, int chan, int size); static int prep_ai_dma(struct comedi_device *dev, int chan, int size);
static int prep_ao_dma(struct comedi_device *dev, int chan, int size); static int prep_ao_dma(struct comedi_device *dev, int chan, int size);
...@@ -530,6 +508,29 @@ static void dt282x_load_changain(struct comedi_device *dev, int n, ...@@ -530,6 +508,29 @@ static void dt282x_load_changain(struct comedi_device *dev, int n,
outw(n - 1, dev->iobase + DT2821_CHANCSR); outw(n - 1, dev->iobase + DT2821_CHANCSR);
} }
static int dt282x_ai_timeout(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned long context)
{
unsigned int status;
status = inw(dev->iobase + DT2821_ADCSR);
switch (context) {
case DT2821_MUXBUSY:
if ((status & DT2821_MUXBUSY) == 0)
return 0;
break;
case DT2821_ADDONE:
if (status & DT2821_ADDONE)
return 0;
break;
default:
return -EINVAL;
}
return -EBUSY;
}
/* /*
* Performs a single A/D conversion. * Performs a single A/D conversion.
* - Put channel/gain into channel-gain list * - Put channel/gain into channel-gain list
...@@ -542,6 +543,7 @@ static int dt282x_ai_insn_read(struct comedi_device *dev, ...@@ -542,6 +543,7 @@ static int dt282x_ai_insn_read(struct comedi_device *dev,
{ {
const struct dt282x_board *board = comedi_board(dev); const struct dt282x_board *board = comedi_board(dev);
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
int ret;
int i; int i;
/* XXX should we really be enabling the ad clock here? */ /* XXX should we really be enabling the ad clock here? */
...@@ -551,13 +553,22 @@ static int dt282x_ai_insn_read(struct comedi_device *dev, ...@@ -551,13 +553,22 @@ static int dt282x_ai_insn_read(struct comedi_device *dev,
dt282x_load_changain(dev, 1, &insn->chanspec); dt282x_load_changain(dev, 1, &insn->chanspec);
outw(devpriv->supcsr | DT2821_PRLD, dev->iobase + DT2821_SUPCSR); outw(devpriv->supcsr | DT2821_PRLD, dev->iobase + DT2821_SUPCSR);
wait_for(!mux_busy(), comedi_error(dev, "timeout\n"); return -ETIME;); ret = comedi_timeout(dev, s, insn, dt282x_ai_timeout, DT2821_MUXBUSY);
if (ret) {
comedi_error(dev, "timeout\n");
return ret;
}
for (i = 0; i < insn->n; i++) { for (i = 0; i < insn->n; i++) {
outw(devpriv->supcsr | DT2821_STRIG, outw(devpriv->supcsr | DT2821_STRIG,
dev->iobase + DT2821_SUPCSR); dev->iobase + DT2821_SUPCSR);
wait_for(ad_done(), comedi_error(dev, "timeout\n");
return -ETIME;); ret = comedi_timeout(dev, s, insn, dt282x_ai_timeout,
DT2821_ADDONE);
if (ret) {
comedi_error(dev, "timeout\n");
return ret;
}
data[i] = data[i] =
inw(dev->iobase + inw(dev->iobase +
...@@ -646,6 +657,7 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ...@@ -646,6 +657,7 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd; struct comedi_cmd *cmd = &s->async->cmd;
int timer; int timer;
int ret;
if (devpriv->usedma == 0) { if (devpriv->usedma == 0) {
comedi_error(dev, comedi_error(dev,
...@@ -691,7 +703,11 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ...@@ -691,7 +703,11 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR); outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR);
outw(devpriv->supcsr | DT2821_PRLD, dev->iobase + DT2821_SUPCSR); outw(devpriv->supcsr | DT2821_PRLD, dev->iobase + DT2821_SUPCSR);
wait_for(!mux_busy(), comedi_error(dev, "timeout\n"); return -ETIME;); ret = comedi_timeout(dev, s, NULL, dt282x_ai_timeout, DT2821_MUXBUSY);
if (ret) {
comedi_error(dev, "timeout\n");
return ret;
}
if (cmd->scan_begin_src == TRIG_FOLLOW) { if (cmd->scan_begin_src == TRIG_FOLLOW) {
outw(devpriv->supcsr | DT2821_STRIG, outw(devpriv->supcsr | DT2821_STRIG,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment