[PATCH v2 5/6] staging: comedi: addi_apci_1564: rewrite the counter subdevice support

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

 



Like the timer, the support functions for the counter subdevice are broken.

Rewrite the code to follow the comedi API.

The new implementation is based on the (minimal) datasheet I have from
ADDI-DATA.

Signed-off-by: H Hartley Sweeten <hsweeten@xxxxxxxxxxxxxxxxxxx>
Cc: Ian Abbott <abbotti@xxxxxxxxx>
Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
 .../comedi/drivers/addi-data/hwdrv_apci1564.c      | 92 ---------------------
 drivers/staging/comedi/drivers/addi_apci_1564.c    | 94 +++++++++++++++++++++-
 2 files changed, 92 insertions(+), 94 deletions(-)
 delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c

diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
deleted file mode 100644
index a1df66d..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+++ /dev/null
@@ -1,92 +0,0 @@
-static int apci1564_counter_insn_config(struct comedi_device *dev,
-					struct comedi_subdevice *s,
-					struct comedi_insn *insn,
-					unsigned int *data)
-{
-	struct apci1564_private *devpriv = dev->private;
-	unsigned int chan = CR_CHAN(insn->chanspec);
-	unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
-	unsigned int ctrl;
-
-	/* Stop The Timer */
-	ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
-	ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
-		  ADDI_TCW_CTRL_ENA);
-	outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
-
-	/* Set the reload value */
-	outl(data[3], iobase + ADDI_TCW_RELOAD_REG);
-
-	/* Set the mode */
-	ctrl &= ~(ADDI_TCW_CTRL_EXT_CLK_MASK | ADDI_TCW_CTRL_MODE_MASK |
-		  ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA |
-		  ADDI_TCW_CTRL_WARN_ENA);
-	ctrl |= ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE(data[4]);
-	outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
-
-	/* Enable or Disable Interrupt */
-	if (data[1])
-		ctrl |= ADDI_TCW_CTRL_IRQ_ENA;
-	else
-		ctrl &= ~ADDI_TCW_CTRL_IRQ_ENA;
-	outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
-
-	/* Set the Up/Down selection */
-	if (data[6])
-		ctrl |= ADDI_TCW_CTRL_CNT_UP;
-	else
-		ctrl &= ~ADDI_TCW_CTRL_CNT_UP;
-	outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
-
-	return insn->n;
-}
-
-static int apci1564_counter_insn_write(struct comedi_device *dev,
-				       struct comedi_subdevice *s,
-				       struct comedi_insn *insn,
-				       unsigned int *data)
-{
-	struct apci1564_private *devpriv = dev->private;
-	unsigned int chan = CR_CHAN(insn->chanspec);
-	unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
-	unsigned int ctrl;
-
-	ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
-	ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG);
-	switch (data[1]) {
-	case 0:	/* Stops the Counter subdevice */
-		ctrl = 0;
-		break;
-	case 1:	/* Start the Counter subdevice */
-		ctrl |= ADDI_TCW_CTRL_ENA;
-		break;
-	case 2:	/* Clears the Counter subdevice */
-		ctrl |= ADDI_TCW_CTRL_GATE;
-		break;
-	}
-	outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
-
-	return insn->n;
-}
-
-static int apci1564_counter_insn_read(struct comedi_device *dev,
-				      struct comedi_subdevice *s,
-				      struct comedi_insn *insn,
-				      unsigned int *data)
-{
-	struct apci1564_private *devpriv = dev->private;
-	unsigned int chan = CR_CHAN(insn->chanspec);
-	unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
-	unsigned int status;
-
-	/* Read the Counter Actual Value. */
-	data[0] = inl(iobase + ADDI_TCW_VAL_REG);
-
-	status = inl(iobase + ADDI_TCW_STATUS_REG);
-	data[1] = (status & ADDI_TCW_STATUS_SOFT_TRIG) ? 1 : 0;
-	data[2] = (status & ADDI_TCW_STATUS_HARDWARE_TRIG) ? 1 : 0;
-	data[3] = (status & ADDI_TCW_STATUS_SOFT_CLR) ? 1 : 0;
-	data[4] = (status & ADDI_TCW_STATUS_OVERFLOW) ? 1 : 0;
-
-	return insn->n;
-}
diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c
index 3e8ac67..5813de5 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1564.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1564.c
@@ -67,6 +67,12 @@
  * the raw data[1] to this register along with the raw data[2] value to the
  * ADDI_TCW_RELOAD_REG. If anyone tests this and can determine the actual
  * timebase/reload operation please let me know.
+ *
+ * The counter subdevice also does not use an async command. All control is
+ * handled by the (*insn_config).
+ *
+ * FIXME: The operation of the counters is not really described in the
+ * datasheet I have. The (*insn_config) needs more work.
  */
 
 #include <linux/module.h>
@@ -177,8 +183,6 @@ struct apci1564_private {
 	unsigned int ctrl;	/* interrupt mode OR (edge) . AND (level) */
 };
 
-#include "addi-data/hwdrv_apci1564.c"
-
 static int apci1564_reset(struct comedi_device *dev)
 {
 	struct apci1564_private *devpriv = dev->private;
@@ -573,6 +577,92 @@ static int apci1564_timer_insn_read(struct comedi_device *dev,
 	return insn->n;
 }
 
+static int apci1564_counter_insn_config(struct comedi_device *dev,
+					struct comedi_subdevice *s,
+					struct comedi_insn *insn,
+					unsigned int *data)
+{
+	struct apci1564_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
+	unsigned int val;
+
+	switch (data[0]) {
+	case INSN_CONFIG_ARM:
+		val = inl(iobase + ADDI_TCW_CTRL_REG);
+		val |= ADDI_TCW_CTRL_IRQ_ENA | ADDI_TCW_CTRL_CNTR_ENA;
+		outl(data[1], iobase + ADDI_TCW_RELOAD_REG);
+		outl(val, iobase + ADDI_TCW_CTRL_REG);
+		break;
+	case INSN_CONFIG_DISARM:
+		val = inl(iobase + ADDI_TCW_CTRL_REG);
+		val &= ~(ADDI_TCW_CTRL_IRQ_ENA | ADDI_TCW_CTRL_CNTR_ENA);
+		outl(val, iobase + ADDI_TCW_CTRL_REG);
+		break;
+	case INSN_CONFIG_SET_COUNTER_MODE:
+		/*
+		 * FIXME: The counter operation is not described in the
+		 * datasheet. For now just write the raw data[1] value to
+		 * the control register.
+		 */
+		outl(data[1], iobase + ADDI_TCW_CTRL_REG);
+		break;
+	case INSN_CONFIG_GET_COUNTER_STATUS:
+		data[1] = 0;
+		val = inl(iobase + ADDI_TCW_CTRL_REG);
+		if (val & ADDI_TCW_CTRL_IRQ_ENA)
+			data[1] |= COMEDI_COUNTER_ARMED;
+		if (val & ADDI_TCW_CTRL_CNTR_ENA)
+			data[1] |= COMEDI_COUNTER_COUNTING;
+		val = inl(iobase + ADDI_TCW_STATUS_REG);
+		if (val & ADDI_TCW_STATUS_OVERFLOW)
+			data[1] |= COMEDI_COUNTER_TERMINAL_COUNT;
+		data[2] = COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING |
+			  COMEDI_COUNTER_TERMINAL_COUNT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return insn->n;
+}
+
+static int apci1564_counter_insn_write(struct comedi_device *dev,
+				       struct comedi_subdevice *s,
+				       struct comedi_insn *insn,
+				       unsigned int *data)
+{
+	struct apci1564_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
+
+	/* just write the last last to the reload register */
+	if (insn->n) {
+		unsigned int val = data[insn->n - 1];
+
+		outl(val, iobase + ADDI_TCW_RELOAD_REG);
+	}
+
+	return insn->n;
+}
+
+static int apci1564_counter_insn_read(struct comedi_device *dev,
+				      struct comedi_subdevice *s,
+				      struct comedi_insn *insn,
+				      unsigned int *data)
+{
+	struct apci1564_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
+	int i;
+
+	/* return the actual value of the counter */
+	for (i = 0; i < insn->n; i++)
+		data[i] = inl(iobase + ADDI_TCW_VAL_REG);
+
+	return insn->n;
+}
+
 static int apci1564_auto_attach(struct comedi_device *dev,
 				unsigned long context_unused)
 {
-- 
2.8.2

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-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