mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:05:18 +07:00
staging: comedi: ni_6527: support INSN_CONFIG_DIGITAL_TRIG
The "edge detection interrupt" subdevice supports the `INSN_CONFIG_CHANGE_NOTIFY` comedi instruction which is only supported by one other driver. The `INSN_CONFIG_DIGITAL_TRIG` comedi instruction is more flexible as it supports both edge and level detection, but is not currently supported by this driver. Add partial support for `INSN_CONFIG_DIGITAL_TRIG`, but only for edge detection. Make use of the `ni6527_set_edge_detection()` used for `INSN_CONFIG_CHANGE_NOTIFY`, but add a parameter holding a mask of the rising and falling edges to be updated and preserve the unmasked edges when updating. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d484e33728
commit
110f9e687c
@ -299,21 +299,38 @@ static int ni6527_intr_insn_bits(struct comedi_device *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void ni6527_set_edge_detection(struct comedi_device *dev,
|
static void ni6527_set_edge_detection(struct comedi_device *dev,
|
||||||
|
unsigned int mask,
|
||||||
unsigned int rising,
|
unsigned int rising,
|
||||||
unsigned int falling)
|
unsigned int falling)
|
||||||
{
|
{
|
||||||
struct ni6527_private *devpriv = dev->private;
|
struct ni6527_private *devpriv = dev->private;
|
||||||
void __iomem *mmio = devpriv->mmio_base;
|
void __iomem *mmio = devpriv->mmio_base;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
/* enable rising-edge detection channels */
|
rising &= mask;
|
||||||
writeb(rising & 0xff, mmio + NI6527_RISING_EDGE_REG(0));
|
falling &= mask;
|
||||||
writeb((rising >> 8) & 0xff, mmio + NI6527_RISING_EDGE_REG(1));
|
for (i = 0; i < 2; i++) {
|
||||||
writeb((rising >> 16) & 0xff, mmio + NI6527_RISING_EDGE_REG(2));
|
if (mask & 0xff) {
|
||||||
|
if (~mask & 0xff) {
|
||||||
/* enable falling-edge detection channels */
|
/* preserve rising-edge detection channels */
|
||||||
writeb(falling & 0xff, mmio + NI6527_FALLING_EDGE_REG(0));
|
rising |= readb(mmio +
|
||||||
writeb((falling >> 8) & 0xff, mmio + NI6527_FALLING_EDGE_REG(1));
|
NI6527_RISING_EDGE_REG(i)) &
|
||||||
writeb((falling >> 16) & 0xff, mmio + NI6527_FALLING_EDGE_REG(2));
|
(~mask & 0xff);
|
||||||
|
/* preserve falling-edge detection channels */
|
||||||
|
falling |= readb(mmio +
|
||||||
|
NI6527_FALLING_EDGE_REG(i)) &
|
||||||
|
(~mask & 0xff);
|
||||||
|
}
|
||||||
|
/* update rising-edge detection channels */
|
||||||
|
writeb(rising & 0xff, mmio + NI6527_RISING_EDGE_REG(i));
|
||||||
|
/* update falling-edge detection channels */
|
||||||
|
writeb(falling & 0xff,
|
||||||
|
mmio + NI6527_FALLING_EDGE_REG(i));
|
||||||
|
}
|
||||||
|
rising >>= 8;
|
||||||
|
falling >>= 8;
|
||||||
|
mask >>= 8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ni6527_intr_insn_config(struct comedi_device *dev,
|
static int ni6527_intr_insn_config(struct comedi_device *dev,
|
||||||
@ -321,12 +338,45 @@ static int ni6527_intr_insn_config(struct comedi_device *dev,
|
|||||||
struct comedi_insn *insn,
|
struct comedi_insn *insn,
|
||||||
unsigned int *data)
|
unsigned int *data)
|
||||||
{
|
{
|
||||||
|
unsigned int mask = 0xffffffff;
|
||||||
|
unsigned int rising, falling, shift;
|
||||||
|
|
||||||
switch (data[0]) {
|
switch (data[0]) {
|
||||||
case INSN_CONFIG_CHANGE_NOTIFY:
|
case INSN_CONFIG_CHANGE_NOTIFY:
|
||||||
/* check_insn_config_length() does not check this instruction */
|
/* check_insn_config_length() does not check this instruction */
|
||||||
if (insn->n != 3)
|
if (insn->n != 3)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
ni6527_set_edge_detection(dev, data[1], data[2]);
|
rising = data[1];
|
||||||
|
falling = data[2];
|
||||||
|
ni6527_set_edge_detection(dev, mask, rising, falling);
|
||||||
|
break;
|
||||||
|
case INSN_CONFIG_DIGITAL_TRIG:
|
||||||
|
/* check trigger number */
|
||||||
|
if (data[1] != 0)
|
||||||
|
return -EINVAL;
|
||||||
|
/* check digital trigger operation */
|
||||||
|
switch (data[2]) {
|
||||||
|
case COMEDI_DIGITAL_TRIG_DISABLE:
|
||||||
|
rising = 0;
|
||||||
|
falling = 0;
|
||||||
|
break;
|
||||||
|
case COMEDI_DIGITAL_TRIG_ENABLE_EDGES:
|
||||||
|
/* check shift amount */
|
||||||
|
shift = data[3];
|
||||||
|
if (shift >= s->n_chan) {
|
||||||
|
mask = 0;
|
||||||
|
rising = 0;
|
||||||
|
falling = 0;
|
||||||
|
} else {
|
||||||
|
mask <<= shift;
|
||||||
|
rising = data[4] << shift;
|
||||||
|
falling = data[5] << shift;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
ni6527_set_edge_detection(dev, mask, rising, falling);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
Loading…
Reference in New Issue
Block a user