Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / comedi / drivers / addi-data / hwdrv_apci1564.c
1 /* Digital Input IRQ Function Selection */
2 #define APCI1564_DI_INT_OR                              (0 << 1)
3 #define APCI1564_DI_INT_AND                             (1 << 1)
4
5 /* Digital Input Interrupt Enable Disable. */
6 #define APCI1564_DI_INT_ENABLE                          0x4
7 #define APCI1564_DI_INT_DISABLE                         0xfffffffb
8
9 /* Digital Output Interrupt Enable Disable. */
10 #define APCI1564_DO_VCC_INT_ENABLE                      0x1
11 #define APCI1564_DO_VCC_INT_DISABLE                     0xfffffffe
12 #define APCI1564_DO_CC_INT_ENABLE                       0x2
13 #define APCI1564_DO_CC_INT_DISABLE                      0xfffffffd
14
15 /* TIMER COUNTER WATCHDOG DEFINES */
16 #define ADDIDATA_TIMER                                  0
17 #define ADDIDATA_COUNTER                                1
18 #define ADDIDATA_WATCHDOG                               2
19
20 static int apci1564_timer_insn_config(struct comedi_device *dev,
21                                       struct comedi_subdevice *s,
22                                       struct comedi_insn *insn,
23                                       unsigned int *data)
24 {
25         struct apci1564_private *devpriv = dev->private;
26         unsigned int ctrl;
27
28         devpriv->tsk_current = current;
29
30         /* First Stop The Timer */
31         ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
32         ctrl &= 0xfffff9fe;
33         /* Stop The Timer */
34         outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
35
36         if (data[1] == 1) {
37                 /* Enable timer int & disable all the other int sources */
38                 outl(0x02, devpriv->timer + ADDI_TCW_CTRL_REG);
39                 outl(0x0, dev->iobase + APCI1564_DI_IRQ_REG);
40                 outl(0x0, dev->iobase + APCI1564_DO_IRQ_REG);
41                 outl(0x0, dev->iobase + APCI1564_WDOG_IRQ_REG);
42                 if (devpriv->counters) {
43                         unsigned long iobase;
44
45                         iobase = devpriv->counters + ADDI_TCW_IRQ_REG;
46                         outl(0x0, iobase + APCI1564_COUNTER(0));
47                         outl(0x0, iobase + APCI1564_COUNTER(1));
48                         outl(0x0, iobase + APCI1564_COUNTER(2));
49                 }
50         } else {
51                 /* disable Timer interrupt */
52                 outl(0x0, devpriv->timer + ADDI_TCW_CTRL_REG);
53         }
54
55         /* Loading Timebase */
56         outl(data[2], devpriv->timer + ADDI_TCW_TIMEBASE_REG);
57
58         /* Loading the Reload value */
59         outl(data[3], devpriv->timer + ADDI_TCW_RELOAD_REG);
60
61         ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
62         ctrl &= 0xfff719e2;
63         ctrl |= (2 << 13) | 0x10;
64         /* mode 2 */
65         outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
66
67         return insn->n;
68 }
69
70 static int apci1564_timer_insn_write(struct comedi_device *dev,
71                                      struct comedi_subdevice *s,
72                                      struct comedi_insn *insn,
73                                      unsigned int *data)
74 {
75         struct apci1564_private *devpriv = dev->private;
76         unsigned int ctrl;
77
78         ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
79         switch (data[1]) {
80         case 0: /* Stop The Timer */
81                 ctrl &= 0xfffff9fe;
82                 break;
83         case 1: /* Enable the Timer */
84                 ctrl &= 0xfffff9ff;
85                 ctrl |= 0x1;
86                 break;
87         }
88         outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
89
90         return insn->n;
91 }
92
93 static int apci1564_timer_insn_read(struct comedi_device *dev,
94                                     struct comedi_subdevice *s,
95                                     struct comedi_insn *insn,
96                                     unsigned int *data)
97 {
98         struct apci1564_private *devpriv = dev->private;
99
100         /* Stores the status of the Timer */
101         data[0] = inl(devpriv->timer + ADDI_TCW_STATUS_REG) & 0x1;
102
103         /* Stores the Actual value of the Timer */
104         data[1] = inl(devpriv->timer + ADDI_TCW_VAL_REG);
105
106         return insn->n;
107 }
108
109 static int apci1564_counter_insn_config(struct comedi_device *dev,
110                                         struct comedi_subdevice *s,
111                                         struct comedi_insn *insn,
112                                         unsigned int *data)
113 {
114         struct apci1564_private *devpriv = dev->private;
115         unsigned int chan = CR_CHAN(insn->chanspec);
116         unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
117         unsigned int ctrl;
118
119         devpriv->tsk_current = current;
120
121         /* First Stop The Counter */
122         ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
123         ctrl &= 0xfffff9fe;
124         /* Stop The Timer */
125         outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
126
127         /* Set the reload value */
128         outl(data[3], iobase + ADDI_TCW_RELOAD_REG);
129
130         /* Set the mode :             */
131         /* - Disable the hardware     */
132         /* - Disable the counter mode */
133         /* - Disable the warning      */
134         /* - Disable the reset        */
135         /* - Disable the timer mode   */
136         /* - Enable the counter mode  */
137
138         ctrl &= 0xfffc19e2;
139         ctrl |= 0x80000 | (data[4] << 16);
140         outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
141
142         /* Enable or Disable Interrupt */
143         ctrl &= 0xfffff9fd;
144         ctrl |= (data[1] << 1);
145         outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
146
147         /* Set the Up/Down selection */
148         ctrl &= 0xfffbf9ff;
149         ctrl |= (data[6] << 18);
150         outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
151
152         return insn->n;
153 }
154
155 static int apci1564_counter_insn_write(struct comedi_device *dev,
156                                        struct comedi_subdevice *s,
157                                        struct comedi_insn *insn,
158                                        unsigned int *data)
159 {
160         struct apci1564_private *devpriv = dev->private;
161         unsigned int chan = CR_CHAN(insn->chanspec);
162         unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
163         unsigned int ctrl;
164
165         ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
166         switch (data[1]) {
167         case 0: /* Stops the Counter subdevice */
168                 ctrl = 0;
169                 break;
170         case 1: /* Start the Counter subdevice */
171                 ctrl &= 0xfffff9ff;
172                 ctrl |= 0x1;
173                 break;
174         case 2: /* Clears the Counter subdevice */
175                 ctrl &= 0xfffff9ff;
176                 ctrl |= 0x400;
177                 break;
178         }
179         outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
180
181         return insn->n;
182 }
183
184 static int apci1564_counter_insn_read(struct comedi_device *dev,
185                                       struct comedi_subdevice *s,
186                                       struct comedi_insn *insn,
187                                       unsigned int *data)
188 {
189         struct apci1564_private *devpriv = dev->private;
190         unsigned int chan = CR_CHAN(insn->chanspec);
191         unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
192         unsigned int status;
193
194         /* Read the Counter Actual Value. */
195         data[0] = inl(iobase + ADDI_TCW_VAL_REG);
196
197         status = inl(iobase + ADDI_TCW_STATUS_REG);
198         data[1] = (status >> 1) & 1;    /* software trigger status */
199         data[2] = (status >> 2) & 1;    /* hardware trigger status */
200         data[3] = (status >> 3) & 1;    /* software clear status */
201         data[4] = (status >> 0) & 1;    /* overflow status */
202
203         return insn->n;
204 }