staging: comedi: pcl812: convert driver to use the comedi_8254 module

This driver uses an 8254 timer to generate the pacer clock used for analog
input data acquisition. Convert it to use the comedi_8254 module to provide
support for the 8254 timer.

Note that the pacer does not have to be stopped when starting a new async
command in pcl812_ai_cmd() or when the card is initialy reset by pcl812_reset().
The counters are all reset when the driver is initially attached and the
counters used by the pacer are stopped when a command is canceled.

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>
This commit is contained in:
H Hartley Sweeten 2015-02-23 14:57:30 -07:00 коммит произвёл Greg Kroah-Hartman
Родитель 43db062afe
Коммит fb5678aff3
2 изменённых файлов: 21 добавлений и 37 удалений

Просмотреть файл

@ -169,6 +169,7 @@ config COMEDI_PCL730
config COMEDI_PCL812
tristate "Advantech PCL-812/813 and ADlink ACL-8112/8113/8113/8216"
select COMEDI_ISADMA if ISA_DMA_API
select COMEDI_8254
---help---
Enable support for Advantech PCL-812/PG, PCL-813/B, ADLink
ACL-8112DG/HG/PG, ACL-8113, ACL-8216, ICP DAS A-821PGH/PGL/PGL-NDA,

Просмотреть файл

@ -118,7 +118,7 @@
#include "comedi_isadma.h"
#include "comedi_fc.h"
#include "8253.h"
#include "comedi_8254.h"
/* hardware types of the cards */
#define boardPCL812PG 0 /* and ACL-8112PG */
@ -513,8 +513,6 @@ struct pcl812_private {
unsigned char mode_reg_int; /* there is stored INT number for some card */
unsigned int ai_poll_ptr; /* how many sampes transfer poll */
unsigned int max_812_ai_mode0_rangewait; /* setling time for gain */
unsigned int divisor1;
unsigned int divisor2;
unsigned int use_diff:1;
unsigned int use_mpc508:1;
unsigned int use_ext_trg:1;
@ -522,21 +520,6 @@ struct pcl812_private {
unsigned int ai_eos:1;
};
static void pcl812_start_pacer(struct comedi_device *dev, bool load_timers)
{
struct pcl812_private *devpriv = dev->private;
unsigned long timer_base = dev->iobase + PCL812_TIMER_BASE;
i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
udelay(1);
if (load_timers) {
i8254_write(timer_base, 0, 2, devpriv->divisor2);
i8254_write(timer_base, 0, 1, devpriv->divisor1);
}
}
static void pcl812_ai_setup_dma(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int unread_samples)
@ -650,7 +633,6 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev,
struct pcl812_private *devpriv = dev->private;
int err = 0;
unsigned int flags;
unsigned int arg;
/* Step 1 : check if triggers are trivially valid */
@ -703,11 +685,9 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev,
/* step 4: fix up any arguments */
if (cmd->convert_src == TRIG_TIMER) {
arg = cmd->convert_arg;
i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ,
&devpriv->divisor1,
&devpriv->divisor2,
&arg, cmd->flags);
unsigned int arg = cmd->convert_arg;
comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
}
@ -725,8 +705,6 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
unsigned int ctrl = 0;
unsigned int i;
pcl812_start_pacer(dev, false);
pcl812_ai_set_chan_range(dev, cmd->chanlist[0], 1);
if (dma) { /* check if we can use DMA transfer */
@ -760,7 +738,8 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
switch (cmd->convert_src) {
case TRIG_TIMER:
pcl812_start_pacer(dev, true);
comedi_8254_update_divisors(dev->pacer);
comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
break;
}
@ -918,7 +897,7 @@ static int pcl812_ai_cancel(struct comedi_device *dev,
outb(devpriv->mode_reg_int | PCL812_CTRL_DISABLE_TRIG,
dev->iobase + PCL812_CTRL_REG);
pcl812_start_pacer(dev, false);
comedi_8254_pacer_enable(dev->pacer, 1, 2, false);
pcl812_ai_clear_eoc(dev);
return 0;
}
@ -1010,10 +989,6 @@ static void pcl812_reset(struct comedi_device *dev)
dev->iobase + PCL812_CTRL_REG);
pcl812_ai_clear_eoc(dev);
/* stop pacer */
if (board->IRQbits)
pcl812_start_pacer(dev, false);
/*
* Invalidate last_ai_chanspec then set analog input to
* known channel/range.
@ -1162,11 +1137,19 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret)
return ret;
if ((1 << it->options[1]) & board->IRQbits) {
ret = request_irq(it->options[1], pcl812_interrupt, 0,
dev->board_name, dev);
if (ret == 0)
dev->irq = it->options[1];
if (board->IRQbits) {
dev->pacer = comedi_8254_init(dev->iobase + PCL812_TIMER_BASE,
I8254_OSC_BASE_2MHZ,
I8254_IO8, 0);
if (!dev->pacer)
return -ENOMEM;
if ((1 << it->options[1]) & board->IRQbits) {
ret = request_irq(it->options[1], pcl812_interrupt, 0,
dev->board_name, dev);
if (ret == 0)
dev->irq = it->options[1];
}
}
/* we need an IRQ to do DMA on channel 3 or 1 */