diff options
author | H Hartley Sweeten <hsweeten@visionengravers.com> | 2014-11-04 10:55:15 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-11-07 09:34:04 -0800 |
commit | 6d31274053716b4cac60a6de7eb40aba8adeb9d5 (patch) | |
tree | ff865e430cb8ce9227d5e57ff67662292cf2eb01 /drivers/staging/comedi/drivers/addi_apci_3120.c | |
parent | staging: comedi: addi_apci_3120: fix timer (*insn_read) (diff) | |
download | linux-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.c | 85 |
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; |