aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/comedi/drivers/addi_apci_3120.c
diff options
context:
space:
mode:
authorH Hartley Sweeten <hsweeten@visionengravers.com>2014-11-04 10:55:15 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-11-07 09:34:04 -0800
commit6d31274053716b4cac60a6de7eb40aba8adeb9d5 (patch)
treeff865e430cb8ce9227d5e57ff67662292cf2eb01 /drivers/staging/comedi/drivers/addi_apci_3120.c
parentstaging: comedi: addi_apci_3120: fix timer (*insn_read) (diff)
downloadlinux-dev-6d31274053716b4cac60a6de7eb40aba8adeb9d5.tar.xz
linux-dev-6d31274053716b4cac60a6de7eb40aba8adeb9d5.zip
staging: comedi: addi_apci_3120: fix timer (*insn_config)
The timer subdevice in this driver does not follow the comedi API. Fix the (*insn_config) to correctly arm, disarm, set the mode, and get the status of the timer. Remove the unnecessary, and broken, (*insn_write). The new (*insn_config) does not enable the interrupt for timer 2. Remove the interrupt support code for the timer. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/comedi/drivers/addi_apci_3120.c')
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3120.c85
1 files changed, 79 insertions, 6 deletions
diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c
index c67c10fc7d66..806f756685a8 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3120.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3120.c
@@ -139,9 +139,6 @@ struct apci3120_private {
unsigned char timer_mode;
unsigned char mode;
unsigned short ctrl;
- unsigned char b_Timer2Mode;
- unsigned char b_Timer2Interrupt;
- struct task_struct *tsk_Current;
};
/*
@@ -447,6 +444,83 @@ static int apci3120_do_insn_bits(struct comedi_device *dev,
return insn->n;
}
+static int apci3120_timer_insn_config(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct apci3120_private *devpriv = dev->private;
+ unsigned int divisor;
+ unsigned int status;
+ unsigned int mode;
+ unsigned int timer_mode;
+
+ switch (data[0]) {
+ case INSN_CONFIG_ARM:
+ apci3120_clr_timer2_interrupt(dev);
+ divisor = apci3120_ns_to_timer(dev, 2, data[1],
+ CMDF_ROUND_DOWN);
+ apci3120_timer_write(dev, 2, divisor);
+ apci3120_timer_enable(dev, 2, true);
+ break;
+
+ case INSN_CONFIG_DISARM:
+ apci3120_timer_enable(dev, 2, false);
+ apci3120_clr_timer2_interrupt(dev);
+ break;
+
+ case INSN_CONFIG_GET_COUNTER_STATUS:
+ data[1] = 0;
+ data[2] = COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING |
+ COMEDI_COUNTER_TERMINAL_COUNT;
+
+ if (devpriv->ctrl & APCI3120_CTRL_GATE(2)) {
+ data[1] |= COMEDI_COUNTER_ARMED;
+ data[1] |= COMEDI_COUNTER_COUNTING;
+ }
+ status = inw(dev->iobase + APCI3120_STATUS_REG);
+ if (status & APCI3120_STATUS_TIMER2_INT) {
+ data[1] &= ~COMEDI_COUNTER_COUNTING;
+ data[1] |= COMEDI_COUNTER_TERMINAL_COUNT;
+ }
+ break;
+
+ case INSN_CONFIG_SET_COUNTER_MODE:
+ switch (data[1]) {
+ case I8254_MODE0:
+ mode = APCI3120_MODE_TIMER2_AS_COUNTER;
+ timer_mode = APCI3120_TIMER_MODE0;
+ break;
+ case I8254_MODE2:
+ mode = APCI3120_MODE_TIMER2_AS_TIMER;
+ timer_mode = APCI3120_TIMER_MODE2;
+ break;
+ case I8254_MODE4:
+ mode = APCI3120_MODE_TIMER2_AS_TIMER;
+ timer_mode = APCI3120_TIMER_MODE4;
+ break;
+ case I8254_MODE5:
+ mode = APCI3120_MODE_TIMER2_AS_WDOG;
+ timer_mode = APCI3120_TIMER_MODE5;
+ break;
+ default:
+ return -EINVAL;
+ }
+ apci3120_timer_enable(dev, 2, false);
+ apci3120_clr_timer2_interrupt(dev);
+ apci3120_timer_set_mode(dev, 2, timer_mode);
+ devpriv->mode &= ~APCI3120_MODE_TIMER2_AS_MASK;
+ devpriv->mode |= mode;
+ outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return insn->n;
+}
+
static int apci3120_timer_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
@@ -627,11 +701,10 @@ static int apci3120_auto_attach(struct comedi_device *dev,
/* Timer subdevice */
s = &dev->subdevices[4];
s->type = COMEDI_SUBD_TIMER;
- s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+ s->subdev_flags = SDF_READABLE;
s->n_chan = 1;
s->maxdata = 0x00ffffff;
- s->insn_write = apci3120_write_insn_timer;
- s->insn_config = apci3120_config_insn_timer;
+ s->insn_config = apci3120_timer_insn_config;
s->insn_read = apci3120_timer_insn_read;
return 0;