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

staging: comedi: drivers: use comedi_dio_insn_config() for simple cases

Convert the drivers with simple, per channel programmable i/o, to use the
comedi_dio_insn_config() helper function.

All of these pass a 'mask' of '0' to comedi_dio_insn_config() this causes
the per channel mask to be used to configure the i/o direction.
Signed-off-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: default avatarIan Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f3508b22
......@@ -3510,31 +3510,20 @@ static int do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
static int dio_60xx_config_insn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
struct comedi_insn *insn,
unsigned int *data)
{
struct pcidas64_private *devpriv = dev->private;
unsigned int mask;
mask = 1 << CR_CHAN(insn->chanspec);
int ret;
switch (data[0]) {
case INSN_CONFIG_DIO_INPUT:
s->io_bits &= ~mask;
break;
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= mask;
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
return 2;
default:
return -EINVAL;
}
ret = comedi_dio_insn_config(dev, s, insn, data, 0);
if (ret)
return ret;
writeb(s->io_bits,
devpriv->dio_counter_iobase + DIO_DIRECTION_60XX_REG);
return 1;
return insn->n;
}
static int dio_60xx_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
......
......@@ -158,27 +158,16 @@ static int ni_670x_dio_insn_bits(struct comedi_device *dev,
static int ni_670x_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
struct comedi_insn *insn,
unsigned int *data)
{
struct ni_670x_private *devpriv = dev->private;
int chan = CR_CHAN(insn->chanspec);
int ret;
ret = comedi_dio_insn_config(dev, s, insn, data, 0);
if (ret)
return ret;
switch (data[0]) {
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= 1 << chan;
break;
case INSN_CONFIG_DIO_INPUT:
s->io_bits &= ~(1 << chan);
break;
case INSN_CONFIG_DIO_QUERY:
data[1] =
(s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
break;
default:
return -EINVAL;
break;
}
writel(s->io_bits, devpriv->mite->daq_io_addr + DIO_PORT0_DIR_OFFSET);
return insn->n;
......
......@@ -90,21 +90,17 @@ static int daq700_dio_insn_bits(struct comedi_device *dev,
static int daq700_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
struct comedi_insn *insn,
unsigned int *data)
{
unsigned int chan = 1 << CR_CHAN(insn->chanspec);
switch (data[0]) {
case INSN_CONFIG_DIO_INPUT:
break;
case INSN_CONFIG_DIO_OUTPUT:
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (s->io_bits & chan) ? COMEDI_OUTPUT : COMEDI_INPUT;
break;
default:
return -EINVAL;
}
int ret;
ret = comedi_dio_insn_config(dev, s, insn, data, 0);
if (ret)
return ret;
/* The DIO channels are not configurable, fix the io_bits */
s->io_bits = 0x00ff;
return insn->n;
}
......
......@@ -3528,37 +3528,21 @@ static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s)
static int ni_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
struct comedi_insn *insn,
unsigned int *data)
{
struct ni_private *devpriv = dev->private;
int ret;
#ifdef DEBUG_DIO
printk("ni_dio_insn_config() chan=%d io=%d\n",
CR_CHAN(insn->chanspec), data[0]);
#endif
switch (data[0]) {
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= 1 << CR_CHAN(insn->chanspec);
break;
case INSN_CONFIG_DIO_INPUT:
s->io_bits &= ~(1 << CR_CHAN(insn->chanspec));
break;
case INSN_CONFIG_DIO_QUERY:
data[1] =
(s->
io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
COMEDI_INPUT;
return insn->n;
break;
default:
return -EINVAL;
}
ret = comedi_dio_insn_config(dev, s, insn, data, 0);
if (ret)
return ret;
devpriv->dio_control &= ~DIO_Pins_Dir_Mask;
devpriv->dio_control |= DIO_Pins_Dir(s->io_bits);
devpriv->stc_writew(dev, devpriv->dio_control, DIO_Control_Register);
return 1;
return insn->n;
}
static int ni_dio_insn_bits(struct comedi_device *dev,
......@@ -3596,32 +3580,15 @@ static int ni_m_series_dio_insn_config(struct comedi_device *dev,
unsigned int *data)
{
struct ni_private *devpriv __maybe_unused = dev->private;
int ret;
#ifdef DEBUG_DIO
printk("ni_m_series_dio_insn_config() chan=%d io=%d\n",
CR_CHAN(insn->chanspec), data[0]);
#endif
switch (data[0]) {
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= 1 << CR_CHAN(insn->chanspec);
break;
case INSN_CONFIG_DIO_INPUT:
s->io_bits &= ~(1 << CR_CHAN(insn->chanspec));
break;
case INSN_CONFIG_DIO_QUERY:
data[1] =
(s->
io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
COMEDI_INPUT;
return insn->n;
break;
default:
return -EINVAL;
}
ret = comedi_dio_insn_config(dev, s, insn, data, 0);
if (ret)
return ret;
ni_writel(s->io_bits, M_Offset_DIO_Direction);
return 1;
return insn->n;
}
static int ni_m_series_dio_insn_bits(struct comedi_device *dev,
......
......@@ -640,32 +640,19 @@ static void debug_int(struct comedi_device *dev)
static int ni_pcidio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
struct comedi_insn *insn,
unsigned int *data)
{
struct nidio96_private *devpriv = dev->private;
int ret;
ret = comedi_dio_insn_config(dev, s, insn, data, 0);
if (ret)
return ret;
if (insn->n != 1)
return -EINVAL;
switch (data[0]) {
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= 1 << CR_CHAN(insn->chanspec);
break;
case INSN_CONFIG_DIO_INPUT:
s->io_bits &= ~(1 << CR_CHAN(insn->chanspec));
break;
case INSN_CONFIG_DIO_QUERY:
data[1] =
(s->
io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
COMEDI_INPUT;
return insn->n;
break;
default:
return -EINVAL;
}
writel(s->io_bits, devpriv->mite->daq_io_addr + Port_Pin_Directions(0));
return 1;
return insn->n;
}
static int ni_pcidio_insn_bits(struct comedi_device *dev,
......
......@@ -310,68 +310,27 @@ static int pcmmio_dio_insn_bits(struct comedi_device *dev,
return insn->n;
}
/* The input or output configuration of each digital line is
* configured by a special insn_config instruction. chanspec
* contains the channel to be changed, and data[0] contains the
* value COMEDI_INPUT or COMEDI_OUTPUT. */
static int pcmmio_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
struct comedi_insn *insn,
unsigned int *data)
{
int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no =
chan % 8;
unsigned long ioaddr;
unsigned char byte;
/* Compute ioaddr for this channel */
ioaddr = subpriv->iobases[byte_no];
/* NOTE:
writing a 0 an IO channel's bit sets the channel to INPUT
and pulls the line high as well
writing a 1 to an IO channel's bit pulls the line low
All channels are implicitly always in OUTPUT mode -- but when
they are high they can be considered to be in INPUT mode..
Thus, we only force channels low if the config request was INPUT,
otherwise we do nothing to the hardware. */
switch (data[0]) {
case INSN_CONFIG_DIO_OUTPUT:
/* save to io_bits -- don't actually do anything since
all input channels are also output channels... */
s->io_bits |= 1 << chan;
break;
case INSN_CONFIG_DIO_INPUT:
/* write a 0 to the actual register representing the channel
to set it to 'input'. 0 means "float high". */
byte = inb(ioaddr);
byte &= ~(1 << bit_no);
/**< set input channel to '0' */
/*
* write out byte -- this is the only time we actually affect
* the hardware as all channels are implicitly output
* -- but input channels are set to float-high
*/
outb(byte, ioaddr);
unsigned int chan = CR_CHAN(insn->chanspec);
int byte_no = chan / 8;
int bit_no = chan % 8;
int ret;
/* save to io_bits */
s->io_bits &= ~(1 << chan);
break;
ret = comedi_dio_insn_config(dev, s, insn, data, 0);
if (ret)
return ret;
case INSN_CONFIG_DIO_QUERY:
/* retrieve from shadow register */
data[1] =
(s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
break;
if (data[0] == INSN_CONFIG_DIO_INPUT) {
unsigned long ioaddr = subpriv->iobases[byte_no];
unsigned char val;
default:
return -EINVAL;
break;
val = inb(ioaddr);
val &= ~(1 << bit_no);
outb(val, ioaddr);
}
return insn->n;
......
......@@ -233,27 +233,19 @@ static int pcmuio_dio_insn_bits(struct comedi_device *dev,
static int pcmuio_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
struct comedi_insn *insn,
unsigned int *data)
{
unsigned int chan_mask = 1 << CR_CHAN(insn->chanspec);
int asic = s->index / 2;
int port = (s->index % 2) ? 3 : 0;
int ret;
switch (data[0]) {
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= chan_mask;
break;
case INSN_CONFIG_DIO_INPUT:
s->io_bits &= ~chan_mask;
ret = comedi_dio_insn_config(dev, s, insn, data, 0);
if (ret)
return ret;
if (data[0] == INSN_CONFIG_DIO_INPUT)
pcmuio_write(dev, s->io_bits, asic, 0, port);
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (s->io_bits & chan_mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
break;
default:
return -EINVAL;
break;
}
return insn->n;
}
......
......@@ -1238,23 +1238,11 @@ static int rtd_dio_insn_config(struct comedi_device *dev,
unsigned int *data)
{
struct rtd_private *devpriv = dev->private;
unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int mask = 1 << chan;
int ret;
switch (data[0]) {
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= mask;
break;
case INSN_CONFIG_DIO_INPUT:
s->io_bits &= ~mask;
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
break;
default:
return -EINVAL;
}
ret = comedi_dio_insn_config(dev, s, insn, data, 0);
if (ret)
return ret;
/* TODO support digital match interrupts and strobes */
......
......@@ -1662,24 +1662,12 @@ static int s626_dio_insn_config(struct comedi_device *dev,
unsigned int *data)
{
unsigned long group = (unsigned long)s->private;
unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int mask = 1 << chan;
int ret;
ret = comedi_dio_insn_config(dev, s, insn, data, 0);
if (ret)
return ret;
switch (data[0]) {
case INSN_CONFIG_DIO_QUERY:
data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
break;
case COMEDI_INPUT:
s->io_bits &= ~mask;
break;
case COMEDI_OUTPUT:
s->io_bits |= mask;
break;
default:
return -EINVAL;
break;
}
DEBIwrite(dev, LP_WRDOUT(group), s->io_bits);
return insn->n;
......
......@@ -93,68 +93,48 @@ static int dnp_dio_insn_bits(struct comedi_device *dev,
}
/* ------------------------------------------------------------------------- */
/* Configure the direction of the bidirectional digital i/o pins. chanspec */
/* contains the channel to be changed and data[0] contains either */
/* COMEDI_INPUT or COMEDI_OUTPUT. */
/* ------------------------------------------------------------------------- */
static int dnp_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
struct comedi_insn *insn,
unsigned int *data)
{
unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int mask;
unsigned int val;
int ret;
u8 register_buffer;
/* reduces chanspec to lower 16 bits */
int chan = CR_CHAN(insn->chanspec);
switch (data[0]) {
case INSN_CONFIG_DIO_OUTPUT:
case INSN_CONFIG_DIO_INPUT:
break;
case INSN_CONFIG_DIO_QUERY:
data[1] =
(inb(CSCDR) & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
break;
default:
return -EINVAL;
break;
}
/* Test: which port does the channel belong to? */
/* We have to pay attention with port C: this is the meaning of PCMR: */
/* Bit in PCMR: 7 6 5 4 3 2 1 0 */
/* Corresponding port C pin: d 3 d 2 d 1 d 0 d= don't touch */
ret = comedi_dio_insn_config(dev, s, insn, data, 0);
if (ret)
return ret;
if ((chan >= 0) && (chan <= 7)) {
/* this is port A */
if (chan < 8) { /* Port A */
mask = 1 << chan;
outb(PAMR, CSCIR);
} else if ((chan >= 8) && (chan <= 15)) {
/* this is port B */
chan -= 8;
} else if (chan < 16) { /* Port B */
mask = 1 << (chan - 8);
outb(PBMR, CSCIR);
} else if ((chan >= 16) && (chan <= 19)) {
/* this is port C; multiplication with 2 brings bits into */
/* correct position for PCMR! */
chan -= 16;
chan *= 2;
} else { /* Port C */
/*
* We have to pay attention with port C.
* This is the meaning of PCMR:
* Bit in PCMR: 7 6 5 4 3 2 1 0
* Corresponding port C pin: d 3 d 2 d 1 d 0 d= don't touch
*
* Multiplication by 2 brings bits into correct position
* for PCMR!
*/
mask = 1 << ((chan - 16) * 2);
outb(PCMR, CSCIR);
} else {
return -EINVAL;
}
/* read 'old' direction of the port and set bits (out=1, in=0) */
register_buffer = inb(CSCDR);
val = inb(CSCDR);
if (data[0] == COMEDI_OUTPUT)
register_buffer |= (1 << chan);
val |= mask;
else
register_buffer &= ~(1 << chan);
outb(register_buffer, CSCDR);
val &= ~mask;
outb(val, CSCDR);
return 1;
return insn->n;
}
......
......@@ -1113,22 +1113,11 @@ static int usbdux_dio_insn_config(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
unsigned int mask = 1 << CR_CHAN(insn->chanspec);
int ret;
switch (data[0]) {
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= mask;
break;
case INSN_CONFIG_DIO_INPUT:
s->io_bits &= ~mask;
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
break;
default:
return -EINVAL;
break;
}
ret = comedi_dio_insn_config(dev, s, insn, data, 0);
if (ret)
return ret;
/*
* We don't tell the firmware here as it would take 8 frames
......
......@@ -1040,23 +1040,11 @@ static int usbduxsigma_dio_insn_config(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int mask = 1 << chan;
int ret;
switch (data[0]) {
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= mask;
break;
case INSN_CONFIG_DIO_INPUT:
s->io_bits &= ~mask;
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
break;
default:
return -EINVAL;
break;
}
ret = comedi_dio_insn_config(dev, s, insn, data, 0);
if (ret)
return ret;
/*
* We don't tell the firmware here as it would take 8 frames
......
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