Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / comedi / drivers / addi-data / hwdrv_apci3501.c
diff --git a/kernel/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/kernel/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
new file mode 100644 (file)
index 0000000..1f2f781
--- /dev/null
@@ -0,0 +1,173 @@
+/* Watchdog Related Defines */
+
+#define ADDIDATA_TIMER                 0
+#define ADDIDATA_WATCHDOG              2
+
+/*
+ * (*insn_config) for the timer subdevice
+ *
+ * Configures The Timer, Counter or Watchdog
+ * Data Pointer contains configuration parameters as below
+ *     data[0] : 0 Configure As Timer
+ *               1 Configure As Counter
+ *               2 Configure As Watchdog
+ *     data[1] : 1 Enable  Interrupt
+ *               0 Disable Interrupt
+ *     data[2] : Time Unit
+ *     data[3] : Reload Value
+ */
+static int apci3501_config_insn_timer(struct comedi_device *dev,
+                                     struct comedi_subdevice *s,
+                                     struct comedi_insn *insn,
+                                     unsigned int *data)
+{
+       struct apci3501_private *devpriv = dev->private;
+       unsigned int ul_Command1 = 0;
+
+       devpriv->tsk_Current = current;
+       if (data[0] == ADDIDATA_WATCHDOG) {
+
+               devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
+               /* Disable the watchdog */
+               outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
+
+               if (data[1] == 1) {
+                       /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
+                       outl(0x02, dev->iobase + APCI3501_TIMER_CTRL_REG);
+               } else {
+                       /* disable Timer interrupt */
+                       outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
+               }
+
+               outl(data[2], dev->iobase + APCI3501_TIMER_TIMEBASE_REG);
+               outl(data[3], dev->iobase + APCI3501_TIMER_RELOAD_REG);
+
+               /* Set the mode (e2->e0) */
+               ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG) | 0xFFF819E0UL;
+               outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+       }
+
+       else if (data[0] == ADDIDATA_TIMER) {
+               /* First Stop The Timer */
+               ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
+               ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+               outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+               devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
+               if (data[1] == 1) {
+                       /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
+                       outl(0x02, dev->iobase + APCI3501_TIMER_CTRL_REG);
+               } else {
+                       /* disable Timer interrupt */
+                       outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
+               }
+
+               outl(data[2], dev->iobase + APCI3501_TIMER_TIMEBASE_REG);
+               outl(data[3], dev->iobase + APCI3501_TIMER_RELOAD_REG);
+
+               /* mode 2 */
+               ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
+               ul_Command1 =
+                       (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
+               outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+       }
+
+       return insn->n;
+}
+
+/*
+ * (*insn_write) for the timer subdevice
+ *
+ * Start / Stop The Selected Timer , Counter or Watchdog
+ * Data Pointer contains configuration parameters as below
+ *     data[0] : 0 Timer
+ *               1 Counter
+ *               2 Watchdog
+ *     data[1] : 1 Start
+ *               0 Stop
+ *               2 Trigger
+ */
+static int apci3501_write_insn_timer(struct comedi_device *dev,
+                                    struct comedi_subdevice *s,
+                                    struct comedi_insn *insn,
+                                    unsigned int *data)
+{
+       struct apci3501_private *devpriv = dev->private;
+       unsigned int ul_Command1 = 0;
+
+       if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+
+               if (data[1] == 1) {
+                       ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
+                       ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
+                       /* Enable the Watchdog */
+                       outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+               } else if (data[1] == 0) { /* Stop The Watchdog */
+                       ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
+                       ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+                       outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
+               } else if (data[1] == 2) {
+                       ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
+                       ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
+                       outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+               }
+       }
+
+       if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+               if (data[1] == 1) {
+
+                       ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
+                       ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
+                       /* Enable the Timer */
+                       outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+               } else if (data[1] == 0) {
+                       /* Stop The Timer */
+                       ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
+                       ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
+                       outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+               }
+
+               else if (data[1] == 2) {
+                       /* Trigger the Timer */
+                       ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
+                       ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
+                       outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+               }
+       }
+
+       inl(dev->iobase + APCI3501_TIMER_STATUS_REG);
+       return insn->n;
+}
+
+/*
+ * (*insn_read) for the timer subdevice
+ *
+ * Read The Selected Timer, Counter or Watchdog
+ * Data Pointer contains configuration parameters as below
+ *     data[0] : 0 Timer
+ *               1 Counter
+ *               2 Watchdog
+ *     data[1] : Timer Counter Watchdog Number
+ */
+static int apci3501_read_insn_timer(struct comedi_device *dev,
+                                   struct comedi_subdevice *s,
+                                   struct comedi_insn *insn,
+                                   unsigned int *data)
+{
+       struct apci3501_private *devpriv = dev->private;
+
+       if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+               data[0] = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1;
+               data[1] = inl(dev->iobase + APCI3501_TIMER_SYNC_REG);
+       }
+
+       else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
+               data[0] = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1;
+               data[1] = inl(dev->iobase + APCI3501_TIMER_SYNC_REG);
+       }
+
+       else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
+               && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)) {
+               dev_err(dev->class_dev, "Invalid subdevice.\n");
+       }
+       return insn->n;
+}