aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c')
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c381
1 files changed, 163 insertions, 218 deletions
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
index 98de96953a29..fa99c8ca4f95 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
@@ -16,244 +16,189 @@
#define ADDIDATA_TIMER 0
#define ADDIDATA_COUNTER 1
#define ADDIDATA_WATCHDOG 2
-#define APCI1564_COUNTER1 0
-#define APCI1564_COUNTER2 1
-#define APCI1564_COUNTER3 2
-#define APCI1564_COUNTER4 3
-
-/*
- * devpriv->amcc_iobase Register Map
- */
-#define APCI1564_DI_REG 0x04
-#define APCI1564_DI_INT_MODE1_REG 0x08
-#define APCI1564_DI_INT_MODE2_REG 0x0c
-#define APCI1564_DI_INT_STATUS_REG 0x10
-#define APCI1564_DI_IRQ_REG 0x14
-#define APCI1564_DO_REG 0x18
-#define APCI1564_DO_INT_CTRL_REG 0x1c
-#define APCI1564_DO_INT_STATUS_REG 0x20
-#define APCI1564_DO_IRQ_REG 0x24
-#define APCI1564_WDOG_REG 0x28
-#define APCI1564_WDOG_RELOAD_REG 0x2c
-#define APCI1564_WDOG_TIMEBASE_REG 0x30
-#define APCI1564_WDOG_CTRL_REG 0x34
-#define APCI1564_WDOG_STATUS_REG 0x38
-#define APCI1564_WDOG_IRQ_REG 0x3c
-#define APCI1564_WDOG_WARN_TIMEVAL_REG 0x40
-#define APCI1564_WDOG_WARN_TIMEBASE_REG 0x44
-#define APCI1564_TIMER_REG 0x48
-#define APCI1564_TIMER_RELOAD_REG 0x4c
-#define APCI1564_TIMER_TIMEBASE_REG 0x50
-#define APCI1564_TIMER_CTRL_REG 0x54
-#define APCI1564_TIMER_STATUS_REG 0x58
-#define APCI1564_TIMER_IRQ_REG 0x5c
-#define APCI1564_TIMER_WARN_TIMEVAL_REG 0x60
-#define APCI1564_TIMER_WARN_TIMEBASE_REG 0x64
-
-/*
- * dev->iobase Register Map
- */
-#define APCI1564_COUNTER_REG(x) (0x00 + ((x) * 0x20))
-#define APCI1564_COUNTER_RELOAD_REG(x) (0x04 + ((x) * 0x20))
-#define APCI1564_COUNTER_TIMEBASE_REG(x) (0x08 + ((x) * 0x20))
-#define APCI1564_COUNTER_CTRL_REG(x) (0x0c + ((x) * 0x20))
-#define APCI1564_COUNTER_STATUS_REG(x) (0x10 + ((x) * 0x20))
-#define APCI1564_COUNTER_IRQ_REG(x) (0x14 + ((x) * 0x20))
-#define APCI1564_COUNTER_WARN_TIMEVAL_REG(x) (0x18 + ((x) * 0x20))
-#define APCI1564_COUNTER_WARN_TIMEBASE_REG(x) (0x1c + ((x) * 0x20))
-
-/*
- * Configures The Timer or Counter
- *
- * data[0] Configure as: 0 = Timer, 1 = Counter
- * data[1] 1 = Enable Interrupt, 0 = Disable Interrupt
- * data[2] Time Unit
- * data[3] Reload Value
- * data[4] Timer Mode
- * data[5] Timer Counter Watchdog Number
- * data[6] Counter Direction
- */
-static int apci1564_timer_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
+
+static int apci1564_timer_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 ul_Command1 = 0;
+ unsigned int ctrl;
devpriv->tsk_current = current;
- if (data[0] == ADDIDATA_TIMER) {
- /* First Stop The Timer */
- ul_Command1 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
- /* Stop The Timer */
- outl(ul_Command1, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
-
- devpriv->timer_select_mode = ADDIDATA_TIMER;
- if (data[1] == 1) {
- /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
- outl(0x02, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG);
- outl(0x0, devpriv->amcc_iobase + APCI1564_DO_IRQ_REG);
- outl(0x0, devpriv->amcc_iobase + APCI1564_WDOG_IRQ_REG);
- outl(0x0, dev->iobase +
- APCI1564_COUNTER_IRQ_REG(APCI1564_COUNTER1));
- outl(0x0, dev->iobase +
- APCI1564_COUNTER_IRQ_REG(APCI1564_COUNTER2));
- outl(0x0, dev->iobase +
- APCI1564_COUNTER_IRQ_REG(APCI1564_COUNTER3));
- outl(0x0, dev->iobase +
- APCI1564_COUNTER_IRQ_REG(APCI1564_COUNTER4));
- } else {
- /* disable Timer interrupt */
- outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- }
- /* Loading Timebase */
- outl(data[2], devpriv->amcc_iobase + APCI1564_TIMER_TIMEBASE_REG);
-
- /* Loading the Reload value */
- outl(data[3], devpriv->amcc_iobase + APCI1564_TIMER_RELOAD_REG);
-
- ul_Command1 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- ul_Command1 = (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
- /* mode 2 */
- outl(ul_Command1, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- } else if (data[0] == ADDIDATA_COUNTER) {
- devpriv->timer_select_mode = ADDIDATA_COUNTER;
- devpriv->mode_select_register = data[5];
-
- /* First Stop The Counter */
- ul_Command1 = inl(dev->iobase +
- APCI1564_COUNTER_CTRL_REG(data[5] - 1));
- ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
- /* Stop The Timer */
- outl(ul_Command1, dev->iobase +
- APCI1564_COUNTER_CTRL_REG(data[5] - 1));
-
- /* Set the reload value */
- outl(data[3], dev->iobase +
- APCI1564_COUNTER_RELOAD_REG(data[5] - 1));
-
- /* Set the mode : */
- /* - Disable the hardware */
- /* - Disable the counter mode */
- /* - Disable the warning */
- /* - Disable the reset */
- /* - Disable the timer mode */
- /* - Enable the counter mode */
-
- ul_Command1 =
- (ul_Command1 & 0xFFFC19E2UL) | 0x80000UL |
- (unsigned int) ((unsigned int) data[4] << 16UL);
- outl(ul_Command1, dev->iobase +
- APCI1564_COUNTER_CTRL_REG(data[5] - 1));
-
- /* Enable or Disable Interrupt */
- ul_Command1 = (ul_Command1 & 0xFFFFF9FD) | (data[1] << 1);
- outl(ul_Command1, dev->iobase +
- APCI1564_COUNTER_CTRL_REG(data[5] - 1));
-
- /* Set the Up/Down selection */
- ul_Command1 = (ul_Command1 & 0xFFFBF9FFUL) | (data[6] << 18);
- outl(ul_Command1, dev->iobase +
- APCI1564_COUNTER_CTRL_REG(data[5] - 1));
+ /* First Stop The Timer */
+ ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
+ ctrl &= 0xfffff9fe;
+ /* Stop The Timer */
+ outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
+
+ if (data[1] == 1) {
+ /* Enable timer int & disable all the other int sources */
+ outl(0x02, devpriv->timer + ADDI_TCW_CTRL_REG);
+ outl(0x0, dev->iobase + APCI1564_DI_IRQ_REG);
+ outl(0x0, dev->iobase + APCI1564_DO_IRQ_REG);
+ outl(0x0, dev->iobase + APCI1564_WDOG_IRQ_REG);
+ if (devpriv->counters) {
+ unsigned long iobase;
+
+ iobase = devpriv->counters + ADDI_TCW_IRQ_REG;
+ outl(0x0, iobase + APCI1564_COUNTER(0));
+ outl(0x0, iobase + APCI1564_COUNTER(1));
+ outl(0x0, iobase + APCI1564_COUNTER(2));
+ }
} else {
- dev_err(dev->class_dev, "Invalid subdevice.\n");
+ /* disable Timer interrupt */
+ outl(0x0, devpriv->timer + ADDI_TCW_CTRL_REG);
}
+
+ /* Loading Timebase */
+ outl(data[2], devpriv->timer + ADDI_TCW_TIMEBASE_REG);
+
+ /* Loading the Reload value */
+ outl(data[3], devpriv->timer + ADDI_TCW_RELOAD_REG);
+
+ ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
+ ctrl &= 0xfff719e2;
+ ctrl |= (2 << 13) | 0x10;
+ /* mode 2 */
+ outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
+
return insn->n;
}
-/*
- * Start / Stop The Selected Timer or Counter
- *
- * data[0] Configure as: 0 = Timer, 1 = Counter
- * data[1] 0 = Stop, 1 = Start, 2 = Trigger Clear (Only Counter)
- */
-static int apci1564_timer_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
+static int apci1564_timer_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 ul_Command1 = 0;
+ unsigned int ctrl;
+
+ ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
+ switch (data[1]) {
+ case 0: /* Stop The Timer */
+ ctrl &= 0xfffff9fe;
+ break;
+ case 1: /* Enable the Timer */
+ ctrl &= 0xfffff9ff;
+ ctrl |= 0x1;
+ break;
+ }
+ outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
- if (devpriv->timer_select_mode == ADDIDATA_TIMER) {
- if (data[1] == 1) {
- ul_Command1 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
+ return insn->n;
+}
- /* Enable the Timer */
- outl(ul_Command1, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- } else if (data[1] == 0) {
- /* Stop The Timer */
+static int apci1564_timer_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct apci1564_private *devpriv = dev->private;
+
+ /* Stores the status of the Timer */
+ data[0] = inl(devpriv->timer + ADDI_TCW_STATUS_REG) & 0x1;
+
+ /* Stores the Actual value of the Timer */
+ data[1] = inl(devpriv->timer + ADDI_TCW_VAL_REG);
- ul_Command1 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
- outl(ul_Command1, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG);
- }
- } else if (devpriv->timer_select_mode == ADDIDATA_COUNTER) {
- ul_Command1 =
- inl(dev->iobase +
- APCI1564_COUNTER_CTRL_REG(devpriv->mode_select_register - 1));
- if (data[1] == 1) {
- /* Start the Counter subdevice */
- ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
- } else if (data[1] == 0) {
- /* Stops the Counter subdevice */
- ul_Command1 = 0;
-
- } else if (data[1] == 2) {
- /* Clears the Counter subdevice */
- ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x400;
- }
- outl(ul_Command1, dev->iobase +
- APCI1564_COUNTER_CTRL_REG(devpriv->mode_select_register - 1));
- } else {
- dev_err(dev->class_dev, "Invalid subdevice.\n");
- }
return insn->n;
}
-/*
- * Read The Selected Timer or Counter
- */
-static int apci1564_timer_read(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
+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 ul_Command1 = 0;
-
- if (devpriv->timer_select_mode == ADDIDATA_TIMER) {
- /* Stores the status of the Timer */
- data[0] = inl(devpriv->amcc_iobase + APCI1564_TIMER_STATUS_REG) & 0x1;
-
- /* Stores the Actual value of the Timer */
- data[1] = inl(devpriv->amcc_iobase + APCI1564_TIMER_REG);
- } else if (devpriv->timer_select_mode == ADDIDATA_COUNTER) {
- /* Read the Counter Actual Value. */
- data[0] =
- inl(dev->iobase +
- APCI1564_COUNTER_REG(devpriv->mode_select_register - 1));
- ul_Command1 =
- inl(dev->iobase +
- APCI1564_COUNTER_STATUS_REG(devpriv->mode_select_register - 1));
-
- /* Get the software trigger status */
- data[1] = (unsigned char) ((ul_Command1 >> 1) & 1);
-
- /* Get the hardware trigger status */
- data[2] = (unsigned char) ((ul_Command1 >> 2) & 1);
-
- /* Get the software clear status */
- data[3] = (unsigned char) ((ul_Command1 >> 3) & 1);
-
- /* Get the overflow status */
- data[4] = (unsigned char) ((ul_Command1 >> 0) & 1);
- } else {
- dev_err(dev->class_dev, "Invalid subdevice.\n");
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
+ unsigned int ctrl;
+
+ devpriv->tsk_current = current;
+
+ /* First Stop The Counter */
+ ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
+ ctrl &= 0xfffff9fe;
+ /* Stop The Timer */
+ outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
+
+ /* Set the reload value */
+ outl(data[3], iobase + ADDI_TCW_RELOAD_REG);
+
+ /* Set the mode : */
+ /* - Disable the hardware */
+ /* - Disable the counter mode */
+ /* - Disable the warning */
+ /* - Disable the reset */
+ /* - Disable the timer mode */
+ /* - Enable the counter mode */
+
+ ctrl &= 0xfffc19e2;
+ ctrl |= 0x80000 | (data[4] << 16);
+ outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
+
+ /* Enable or Disable Interrupt */
+ ctrl &= 0xfffff9fd;
+ ctrl |= (data[1] << 1);
+ outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
+
+ /* Set the Up/Down selection */
+ ctrl &= 0xfffbf9ff;
+ ctrl |= (data[6] << 18);
+ 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);
+ switch (data[1]) {
+ case 0: /* Stops the Counter subdevice */
+ ctrl = 0;
+ break;
+ case 1: /* Start the Counter subdevice */
+ ctrl &= 0xfffff9ff;
+ ctrl |= 0x1;
+ break;
+ case 2: /* Clears the Counter subdevice */
+ ctrl &= 0xfffff9ff;
+ ctrl |= 0x400;
+ 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 >> 1) & 1; /* software trigger status */
+ data[2] = (status >> 2) & 1; /* hardware trigger status */
+ data[3] = (status >> 3) & 1; /* software clear status */
+ data[4] = (status >> 0) & 1; /* overflow status */
+
return insn->n;
}