a3e3a34d7e86aa4175a88bb9255a7f693d9470f3
[pandora-kernel.git] / drivers / staging / comedi / drivers / addi-data / hwdrv_apci1564.c
1 static int apci1564_timer_insn_config(struct comedi_device *dev,
2                                       struct comedi_subdevice *s,
3                                       struct comedi_insn *insn,
4                                       unsigned int *data)
5 {
6         struct apci1564_private *devpriv = dev->private;
7         unsigned int ctrl;
8
9         devpriv->tsk_current = current;
10
11         /* Stop the timer */
12         ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
13         ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
14                   ADDI_TCW_CTRL_ENA);
15         outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
16
17         if (data[1] == 1) {
18                 /* Enable timer int & disable all the other int sources */
19                 outl(ADDI_TCW_CTRL_IRQ_ENA,
20                      devpriv->timer + ADDI_TCW_CTRL_REG);
21                 outl(0x0, dev->iobase + APCI1564_DI_IRQ_REG);
22                 outl(0x0, dev->iobase + APCI1564_DO_IRQ_REG);
23                 outl(0x0, dev->iobase + APCI1564_WDOG_IRQ_REG);
24                 if (devpriv->counters) {
25                         unsigned long iobase;
26
27                         iobase = devpriv->counters + ADDI_TCW_IRQ_REG;
28                         outl(0x0, iobase + APCI1564_COUNTER(0));
29                         outl(0x0, iobase + APCI1564_COUNTER(1));
30                         outl(0x0, iobase + APCI1564_COUNTER(2));
31                 }
32         } else {
33                 /* disable Timer interrupt */
34                 outl(0x0, devpriv->timer + ADDI_TCW_CTRL_REG);
35         }
36
37         /* Loading Timebase */
38         outl(data[2], devpriv->timer + ADDI_TCW_TIMEBASE_REG);
39
40         /* Loading the Reload value */
41         outl(data[3], devpriv->timer + ADDI_TCW_RELOAD_REG);
42
43         ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
44         ctrl &= ~(ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE_MASK |
45                   ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
46                   ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA |
47                   ADDI_TCW_CTRL_WARN_ENA | ADDI_TCW_CTRL_ENA);
48         ctrl |= ADDI_TCW_CTRL_MODE(2) | ADDI_TCW_CTRL_TIMER_ENA;
49         outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
50
51         return insn->n;
52 }
53
54 static int apci1564_timer_insn_write(struct comedi_device *dev,
55                                      struct comedi_subdevice *s,
56                                      struct comedi_insn *insn,
57                                      unsigned int *data)
58 {
59         struct apci1564_private *devpriv = dev->private;
60         unsigned int ctrl;
61
62         ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
63         ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG);
64         switch (data[1]) {
65         case 0: /* Stop The Timer */
66                 ctrl &= ~ADDI_TCW_CTRL_ENA;
67                 break;
68         case 1: /* Enable the Timer */
69                 ctrl |= ADDI_TCW_CTRL_ENA;
70                 break;
71         }
72         outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
73
74         return insn->n;
75 }
76
77 static int apci1564_timer_insn_read(struct comedi_device *dev,
78                                     struct comedi_subdevice *s,
79                                     struct comedi_insn *insn,
80                                     unsigned int *data)
81 {
82         struct apci1564_private *devpriv = dev->private;
83
84         /* Stores the status of the Timer */
85         data[0] = inl(devpriv->timer + ADDI_TCW_STATUS_REG) &
86                   ADDI_TCW_STATUS_OVERFLOW;
87
88         /* Stores the Actual value of the Timer */
89         data[1] = inl(devpriv->timer + ADDI_TCW_VAL_REG);
90
91         return insn->n;
92 }
93
94 static int apci1564_counter_insn_config(struct comedi_device *dev,
95                                         struct comedi_subdevice *s,
96                                         struct comedi_insn *insn,
97                                         unsigned int *data)
98 {
99         struct apci1564_private *devpriv = dev->private;
100         unsigned int chan = CR_CHAN(insn->chanspec);
101         unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
102         unsigned int ctrl;
103
104         devpriv->tsk_current = current;
105
106         /* Stop The Timer */
107         ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
108         ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
109                   ADDI_TCW_CTRL_ENA);
110         outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
111
112         /* Set the reload value */
113         outl(data[3], iobase + ADDI_TCW_RELOAD_REG);
114
115         /* Set the mode */
116         ctrl &= ~(ADDI_TCW_CTRL_EXT_CLK_MASK | ADDI_TCW_CTRL_MODE_MASK |
117                   ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
118                   ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA |
119                   ADDI_TCW_CTRL_WARN_ENA | ADDI_TCW_CTRL_ENA);
120         ctrl |= ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_EXT_CLK(data[4]);
121         outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
122
123         /* Enable or Disable Interrupt */
124         ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
125                   ADDI_TCW_CTRL_IRQ_ENA);
126         if (data[1])
127                 ctrl |= ADDI_TCW_CTRL_IRQ_ENA;
128         outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
129
130         /* Set the Up/Down selection */
131         ctrl &= ~(ADDI_TCW_CTRL_CNT_UP | ADDI_TCW_CTRL_GATE |
132                   ADDI_TCW_CTRL_TRIG);
133         if (data[6])
134                 ctrl |= ADDI_TCW_CTRL_CNT_UP;
135         outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
136
137         return insn->n;
138 }
139
140 static int apci1564_counter_insn_write(struct comedi_device *dev,
141                                        struct comedi_subdevice *s,
142                                        struct comedi_insn *insn,
143                                        unsigned int *data)
144 {
145         struct apci1564_private *devpriv = dev->private;
146         unsigned int chan = CR_CHAN(insn->chanspec);
147         unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
148         unsigned int ctrl;
149
150         ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
151         switch (data[1]) {
152         case 0: /* Stops the Counter subdevice */
153                 ctrl = 0;
154                 break;
155         case 1: /* Start the Counter subdevice */
156                 ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG);
157                 ctrl |= ADDI_TCW_CTRL_ENA;
158                 break;
159         case 2: /* Clears the Counter subdevice */
160                 ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG);
161                 ctrl |= ADDI_TCW_CTRL_GATE;
162                 break;
163         }
164         outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
165
166         return insn->n;
167 }
168
169 static int apci1564_counter_insn_read(struct comedi_device *dev,
170                                       struct comedi_subdevice *s,
171                                       struct comedi_insn *insn,
172                                       unsigned int *data)
173 {
174         struct apci1564_private *devpriv = dev->private;
175         unsigned int chan = CR_CHAN(insn->chanspec);
176         unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
177         unsigned int status;
178
179         /* Read the Counter Actual Value. */
180         data[0] = inl(iobase + ADDI_TCW_VAL_REG);
181
182         status = inl(iobase + ADDI_TCW_STATUS_REG);
183         data[1] = (status >> 1) & 1;    /* software trigger status */
184         data[2] = (status >> 2) & 1;    /* hardware trigger status */
185         data[3] = (status >> 3) & 1;    /* software clear status */
186         data[4] = (status >> 0) & 1;    /* overflow status */
187
188         return insn->n;
189 }