[PATCH 12/30] staging: comedi: amplc_dio200: add functions to access 8254 counters

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add our own functions to manipulate the '8254' counter chip instead of
the inline ones from "8253.h".  This will make the code less messy when
we add code to support new boards later.

Signed-off-by: Ian Abbott <abbotti@xxxxxxxxx>
---
 drivers/staging/comedi/drivers/amplc_dio200.c | 83 ++++++++++++++++++++++++---
 1 file changed, 75 insertions(+), 8 deletions(-)

diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
index 16ae7a3..d874bdf 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200.c
@@ -928,6 +928,73 @@ static irqreturn_t dio200_interrupt(int irq, void *d)
 }
 
 /*
+ * Read an '8254' counter subdevice channel.
+ */
+static unsigned int
+dio200_subdev_8254_read_chan(struct comedi_device *dev,
+			     struct comedi_subdevice *s, unsigned int chan)
+{
+	struct dio200_subdev_8254 *subpriv = s->private;
+	unsigned int val;
+
+	/* latch counter */
+	val = chan << 6;
+	outb(val, dev->iobase + subpriv->ofs + i8254_control_reg);
+	/* read lsb, msb */
+	val = inb(dev->iobase + subpriv->ofs + chan);
+	val += inb(dev->iobase + subpriv->ofs + chan) << 8;
+	return val;
+}
+
+/*
+ * Write an '8254' subdevice channel.
+ */
+static void
+dio200_subdev_8254_write_chan(struct comedi_device *dev,
+			      struct comedi_subdevice *s, unsigned int chan,
+			      unsigned int count)
+{
+	struct dio200_subdev_8254 *subpriv = s->private;
+
+	/* write lsb, msb */
+	outb(count & 0xff, dev->iobase + subpriv->ofs + chan);
+	outb((count >> 8) & 0xff, dev->iobase + subpriv->ofs + chan);
+}
+
+/*
+ * Set mode of an '8254' subdevice channel.
+ */
+static void
+dio200_subdev_8254_set_mode(struct comedi_device *dev,
+			    struct comedi_subdevice *s, unsigned int chan,
+			    unsigned int mode)
+{
+	struct dio200_subdev_8254 *subpriv = s->private;
+	unsigned int byte;
+
+	byte = chan << 6;
+	byte |= 0x30;		/* access order: lsb, msb */
+	byte |= (mode & 0xf);	/* counter mode and BCD|binary */
+	outb(byte, dev->iobase + subpriv->ofs + i8254_control_reg);
+}
+
+/*
+ * Read status byte of an '8254' counter subdevice channel.
+ */
+static unsigned int
+dio200_subdev_8254_status(struct comedi_device *dev,
+			  struct comedi_subdevice *s, unsigned int chan)
+{
+	struct dio200_subdev_8254 *subpriv = s->private;
+
+	/* latch status */
+	outb(0xe0 | (2 << chan),
+	     dev->iobase + subpriv->ofs + i8254_control_reg);
+	/* read status */
+	return inb(dev->iobase + subpriv->ofs + chan);
+}
+
+/*
  * Handle 'insn_read' for an '8254' counter subdevice.
  */
 static int
@@ -939,7 +1006,7 @@ dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
 	unsigned long flags;
 
 	spin_lock_irqsave(&subpriv->spinlock, flags);
-	data[0] = i8254_read(dev->iobase + subpriv->ofs, 0, chan);
+	data[0] = dio200_subdev_8254_read_chan(dev, s, chan);
 	spin_unlock_irqrestore(&subpriv->spinlock, flags);
 
 	return 1;
@@ -957,7 +1024,7 @@ dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
 	unsigned long flags;
 
 	spin_lock_irqsave(&subpriv->spinlock, flags);
-	i8254_write(dev->iobase + subpriv->ofs, 0, chan, data[0]);
+	dio200_subdev_8254_write_chan(dev, s, chan, data[0]);
 	spin_unlock_irqrestore(&subpriv->spinlock, flags);
 
 	return 1;
@@ -1074,13 +1141,13 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
 	spin_lock_irqsave(&subpriv->spinlock, flags);
 	switch (data[0]) {
 	case INSN_CONFIG_SET_COUNTER_MODE:
-		ret = i8254_set_mode(dev->iobase + subpriv->ofs, 0, chan,
-				     data[1]);
-		if (ret < 0)
+		if (data[1] > (I8254_MODE5 | I8254_BINARY))
 			ret = -EINVAL;
+		else
+			dio200_subdev_8254_set_mode(dev, s, chan, data[1]);
 		break;
 	case INSN_CONFIG_8254_READ_STATUS:
-		data[1] = i8254_status(dev->iobase + subpriv->ofs, 0, chan);
+		data[1] = dio200_subdev_8254_status(dev, s, chan);
 		break;
 	case INSN_CONFIG_SET_GATE_SRC:
 		ret = dio200_subdev_8254_set_gate_src(dev, s, chan, data[2]);
@@ -1154,8 +1221,8 @@ dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
 
 	/* Initialize channels. */
 	for (chan = 0; chan < 3; chan++) {
-		i8254_set_mode(dev->iobase + subpriv->ofs, 0, chan,
-			       I8254_MODE0 | I8254_BINARY);
+		dio200_subdev_8254_set_mode(dev, s, chan,
+					    I8254_MODE0 | I8254_BINARY);
 		if (layout->has_clk_gat_sce) {
 			/* Gate source 0 is VCC (logic 1). */
 			dio200_subdev_8254_set_gate_src(dev, s, chan, 0);
-- 
1.7.12.4

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel


[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux