From 6cf215d730d5fc050603edd0d693e3520626b6a3 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 4 Mar 2014 11:30:19 -0700 Subject: [PATCH] staging: comedi: pcl816: define the mode register bits Define the bits in the register to remove the magic values. Fix pcl816_ai_cancel(). The 0x73 mask of the value read from the control register will not stop the A/D as indicated by the comment. This would just clear the DS1, POE, and EXT bits which would only disable the external trigger. Setting the control register to '0' would then stop the A/D which means the software trigger following it would not work. Just disable the trigger and clear any pending end-of-conversion. Make sure the A/D trigger is disabled at the end of the (*insn_read). Remove a couple unnecessary devpriv->dev checks. The pcl816_ai_cmd() and pcl816_ai_poll() functions are only hooked up when devpriv->dma is valid. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl816.c | 66 ++++++++++--------------- 1 file changed, 25 insertions(+), 41 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 786680f32686..f22cf8620670 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -52,6 +52,17 @@ Configuration Options: #define PCL816_RANGE_REG 0x09 #define PCL816_MUX_REG 0x0b #define PCL816_MUX_SCAN(_first, _last) (((_last) << 4) | (_first)) +#define PCL816_CTRL_REG 0x0c +#define PCL816_CTRL_DISABLE_TRIG (0 << 0) +#define PCL816_CTRL_SOFT_TRIG (1 << 0) +#define PCL816_CTRL_PACER_TRIG (1 << 1) +#define PCL816_CTRL_EXT_TRIG (1 << 2) +#define PCL816_CTRL_POE (1 << 3) +#define PCL816_CTRL_DMAEN (1 << 4) +#define PCL816_CTRL_INTEN (1 << 5) +#define PCL816_CTRL_DMASRC_SLOT0 (0 << 6) +#define PCL816_CTRL_DMASRC_SLOT1 (1 << 6) +#define PCL816_CTRL_DMASRC_SLOT2 (2 << 6) #define PCL816_STATUS_REG 0x0d #define PCL816_STATUS_NEXT_CHAN_MASK (0xf << 0) #define PCL816_STATUS_INTSRC_MASK (3 << 4) @@ -64,9 +75,6 @@ Configuration Options: /* W: clear INT request */ #define PCL816_CLRINT 10 -/* R/W: operation control register */ -#define PCL816_CONTROL 12 - #define MAGIC_DMA_WORD 0x5a5a @@ -439,7 +447,7 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl816_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; - unsigned int dmairq; + unsigned int ctrl; unsigned int seglen; if (devpriv->ai_cmd_running) @@ -459,29 +467,18 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_poll_ptr = 0; devpriv->ai_cmd_canceled = 0; - if (devpriv->dma) - pcl816_ai_setup_dma(dev, s); + pcl816_ai_setup_dma(dev, s); pcl816_start_pacer(dev, true); - dmairq = ((devpriv->dma & 0x3) << 4) | (dev->irq & 0x7); - - switch (cmd->convert_src) { - case TRIG_TIMER: - /* Pacer+IRQ+DMA */ - outb(0x32, dev->iobase + PCL816_CONTROL); - /* write irq and DMA to card */ - outb(dmairq, dev->iobase + PCL816_STATUS_REG); - break; - - default: - /* Ext trig+IRQ+DMA */ - outb(0x34, dev->iobase + PCL816_CONTROL); + ctrl = PCL816_CTRL_INTEN | PCL816_CTRL_DMAEN | PCL816_CTRL_DMASRC_SLOT0; + if (cmd->convert_src == TRIG_TIMER) + ctrl |= PCL816_CTRL_PACER_TRIG; + else /* TRIG_EXT */ + ctrl |= PCL816_CTRL_EXT_TRIG; - /* write irq to card */ - outb(dmairq, dev->iobase + PCL816_STATUS_REG); - break; - } + outb(ctrl, dev->iobase + PCL816_CTRL_REG); + outb((devpriv->dma << 4) | dev->irq, dev->iobase + PCL816_STATUS_REG); return 0; } @@ -492,9 +489,6 @@ static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) unsigned long flags; unsigned int top1, top2, i; - if (!devpriv->dma) - return 0; /* poll is valid only for DMA transfer */ - spin_lock_irqsave(&dev->spinlock, flags); for (i = 0; i < 20; i++) { @@ -538,11 +532,8 @@ static int pcl816_ai_cancel(struct comedi_device *dev, if (!devpriv->ai_cmd_running) return 0; - disable_dma(devpriv->dma); - outb(inb(dev->iobase + PCL816_CONTROL) & 0x73, - dev->iobase + PCL816_CONTROL); /* Stop A/D */ - udelay(1); - outb(0, dev->iobase + PCL816_CONTROL); /* Stop A/D */ + outb(PCL816_CTRL_DISABLE_TRIG, dev->iobase + PCL816_CTRL_REG); + pcl816_ai_clear_eoc(dev); /* Stop pacer */ i8254_set_mode(dev->iobase + PCL816_TIMER_BASE, 0, @@ -550,13 +541,6 @@ static int pcl816_ai_cancel(struct comedi_device *dev, i8254_set_mode(dev->iobase + PCL816_TIMER_BASE, 0, 1, I8254_MODE0 | I8254_BINARY); - pcl816_ai_soft_trig(dev); - pcl816_ai_get_sample(dev, s); - - pcl816_ai_clear_eoc(dev); - - /* Stop A/D */ - outb(0, dev->iobase + PCL816_CONTROL); devpriv->ai_cmd_running = 0; devpriv->ai_cmd_canceled = 1; @@ -629,8 +613,7 @@ static int pcl816_ai_insn_read(struct comedi_device *dev, int ret = 0; int i; - /* software trigger, DMA and INT off */ - outb(0, dev->iobase + PCL816_CONTROL); + outb(PCL816_CTRL_SOFT_TRIG, dev->iobase + PCL816_CTRL_REG); pcl816_ai_set_chan_range(dev, chan, range); pcl816_ai_set_chan_scan(dev, chan, chan); @@ -645,6 +628,7 @@ static int pcl816_ai_insn_read(struct comedi_device *dev, data[i] = pcl816_ai_get_sample(dev, s); } + outb(PCL816_CTRL_DISABLE_TRIG, dev->iobase + PCL816_CTRL_REG); pcl816_ai_clear_eoc(dev); return ret ? ret : insn->n; @@ -680,7 +664,7 @@ static void pcl816_reset(struct comedi_device *dev) { unsigned long timer_base = dev->iobase + PCL816_TIMER_BASE; - outb(0, dev->iobase + PCL816_CONTROL); + outb(PCL816_CTRL_DISABLE_TRIG, dev->iobase + PCL816_CTRL_REG); pcl816_ai_set_chan_range(dev, 0, 0); pcl816_ai_clear_eoc(dev); -- 2.39.5