Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / comedi / drivers / addi-data / hwdrv_apci3501.c
1 /* Watchdog Related Defines */
2
3 #define ADDIDATA_TIMER                  0
4 #define ADDIDATA_WATCHDOG               2
5
6 /*
7  * (*insn_config) for the timer subdevice
8  *
9  * Configures The Timer, Counter or Watchdog
10  * Data Pointer contains configuration parameters as below
11  *      data[0] : 0 Configure As Timer
12  *                1 Configure As Counter
13  *                2 Configure As Watchdog
14  *      data[1] : 1 Enable  Interrupt
15  *                0 Disable Interrupt
16  *      data[2] : Time Unit
17  *      data[3] : Reload Value
18  */
19 static int apci3501_config_insn_timer(struct comedi_device *dev,
20                                       struct comedi_subdevice *s,
21                                       struct comedi_insn *insn,
22                                       unsigned int *data)
23 {
24         struct apci3501_private *devpriv = dev->private;
25         unsigned int ul_Command1 = 0;
26
27         devpriv->tsk_Current = current;
28         if (data[0] == ADDIDATA_WATCHDOG) {
29
30                 devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
31                 /* Disable the watchdog */
32                 outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
33
34                 if (data[1] == 1) {
35                         /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
36                         outl(0x02, dev->iobase + APCI3501_TIMER_CTRL_REG);
37                 } else {
38                         /* disable Timer interrupt */
39                         outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
40                 }
41
42                 outl(data[2], dev->iobase + APCI3501_TIMER_TIMEBASE_REG);
43                 outl(data[3], dev->iobase + APCI3501_TIMER_RELOAD_REG);
44
45                 /* Set the mode (e2->e0) */
46                 ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG) | 0xFFF819E0UL;
47                 outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
48         }
49
50         else if (data[0] == ADDIDATA_TIMER) {
51                 /* First Stop The Timer */
52                 ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
53                 ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
54                 outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
55                 devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
56                 if (data[1] == 1) {
57                         /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
58                         outl(0x02, dev->iobase + APCI3501_TIMER_CTRL_REG);
59                 } else {
60                         /* disable Timer interrupt */
61                         outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
62                 }
63
64                 outl(data[2], dev->iobase + APCI3501_TIMER_TIMEBASE_REG);
65                 outl(data[3], dev->iobase + APCI3501_TIMER_RELOAD_REG);
66
67                 /* mode 2 */
68                 ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
69                 ul_Command1 =
70                         (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
71                 outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
72         }
73
74         return insn->n;
75 }
76
77 /*
78  * (*insn_write) for the timer subdevice
79  *
80  * Start / Stop The Selected Timer , Counter or Watchdog
81  * Data Pointer contains configuration parameters as below
82  *      data[0] : 0 Timer
83  *                1 Counter
84  *                2 Watchdog
85  *      data[1] : 1 Start
86  *                0 Stop
87  *                2 Trigger
88  */
89 static int apci3501_write_insn_timer(struct comedi_device *dev,
90                                      struct comedi_subdevice *s,
91                                      struct comedi_insn *insn,
92                                      unsigned int *data)
93 {
94         struct apci3501_private *devpriv = dev->private;
95         unsigned int ul_Command1 = 0;
96
97         if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
98
99                 if (data[1] == 1) {
100                         ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
101                         ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
102                         /* Enable the Watchdog */
103                         outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
104                 } else if (data[1] == 0) { /* Stop The Watchdog */
105                         ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
106                         ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
107                         outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
108                 } else if (data[1] == 2) {
109                         ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
110                         ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
111                         outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
112                 }
113         }
114
115         if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
116                 if (data[1] == 1) {
117
118                         ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
119                         ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
120                         /* Enable the Timer */
121                         outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
122                 } else if (data[1] == 0) {
123                         /* Stop The Timer */
124                         ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
125                         ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
126                         outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
127                 }
128
129                 else if (data[1] == 2) {
130                         /* Trigger the Timer */
131                         ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
132                         ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
133                         outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
134                 }
135         }
136
137         inl(dev->iobase + APCI3501_TIMER_STATUS_REG);
138         return insn->n;
139 }
140
141 /*
142  * (*insn_read) for the timer subdevice
143  *
144  * Read The Selected Timer, Counter or Watchdog
145  * Data Pointer contains configuration parameters as below
146  *      data[0] : 0 Timer
147  *                1 Counter
148  *                2 Watchdog
149  *      data[1] : Timer Counter Watchdog Number
150  */
151 static int apci3501_read_insn_timer(struct comedi_device *dev,
152                                     struct comedi_subdevice *s,
153                                     struct comedi_insn *insn,
154                                     unsigned int *data)
155 {
156         struct apci3501_private *devpriv = dev->private;
157
158         if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
159                 data[0] = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1;
160                 data[1] = inl(dev->iobase + APCI3501_TIMER_SYNC_REG);
161         }
162
163         else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
164                 data[0] = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1;
165                 data[1] = inl(dev->iobase + APCI3501_TIMER_SYNC_REG);
166         }
167
168         else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
169                 && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)) {
170                 dev_err(dev->class_dev, "Invalid subdevice.\n");
171         }
172         return insn->n;
173 }