staging: comedi: remove inline alloc_private()
[linux-2.6-block.git] / drivers / staging / comedi / drivers / rti800.c
1 /*
2    comedi/drivers/rti800.c
3    Hardware driver for Analog Devices RTI-800/815 board
4
5    COMEDI - Linux Control and Measurement Device Interface
6    Copyright (C) 1998 David A. Schleef <ds@schleef.org>
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22  */
23 /*
24 Driver: rti800
25 Description: Analog Devices RTI-800/815
26 Author: ds
27 Status: unknown
28 Updated: Fri, 05 Sep 2008 14:50:44 +0100
29 Devices: [Analog Devices] RTI-800 (rti800), RTI-815 (rti815)
30
31 Configuration options:
32   [0] - I/O port base address
33   [1] - IRQ
34   [2] - A/D reference
35         0 = differential
36         1 = pseudodifferential (common)
37         2 = single-ended
38   [3] - A/D range
39         0 = [-10,10]
40         1 = [-5,5]
41         2 = [0,10]
42   [4] - A/D encoding
43         0 = two's complement
44         1 = straight binary
45   [5] - DAC 0 range
46         0 = [-10,10]
47         1 = [0,10]
48   [6] - DAC 0 encoding
49         0 = two's complement
50         1 = straight binary
51   [7] - DAC 1 range (same as DAC 0)
52   [8] - DAC 1 encoding (same as DAC 0)
53 */
54
55 #include <linux/interrupt.h>
56 #include "../comedidev.h"
57
58 #include <linux/ioport.h>
59
60 #define RTI800_SIZE 16
61
62 #define RTI800_CSR 0
63 #define RTI800_MUXGAIN 1
64 #define RTI800_CONVERT 2
65 #define RTI800_ADCLO 3
66 #define RTI800_ADCHI 4
67 #define RTI800_DAC0LO 5
68 #define RTI800_DAC0HI 6
69 #define RTI800_DAC1LO 7
70 #define RTI800_DAC1HI 8
71 #define RTI800_CLRFLAGS 9
72 #define RTI800_DI 10
73 #define RTI800_DO 11
74 #define RTI800_9513A_DATA 12
75 #define RTI800_9513A_CNTRL 13
76 #define RTI800_9513A_STATUS 13
77
78 /*
79  * flags for CSR register
80  */
81
82 #define RTI800_BUSY             0x80
83 #define RTI800_DONE             0x40
84 #define RTI800_OVERRUN          0x20
85 #define RTI800_TCR              0x10
86 #define RTI800_DMA_ENAB         0x08
87 #define RTI800_INTR_TC          0x04
88 #define RTI800_INTR_EC          0x02
89 #define RTI800_INTR_OVRN        0x01
90
91 #define Am9513_8BITBUS
92
93 #define Am9513_output_control(a)        outb(a, dev->iobase+RTI800_9513A_CNTRL)
94 #define Am9513_output_data(a)           outb(a, dev->iobase+RTI800_9513A_DATA)
95 #define Am9513_input_data()             inb(dev->iobase+RTI800_9513A_DATA)
96 #define Am9513_input_status()           inb(dev->iobase+RTI800_9513A_STATUS)
97
98 #include "am9513.h"
99
100 static const struct comedi_lrange range_rti800_ai_10_bipolar = { 4, {
101                                                                      BIP_RANGE
102                                                                      (10),
103                                                                      BIP_RANGE
104                                                                      (1),
105                                                                      BIP_RANGE
106                                                                      (0.1),
107                                                                      BIP_RANGE
108                                                                      (0.02)
109                                                                      }
110 };
111
112 static const struct comedi_lrange range_rti800_ai_5_bipolar = { 4, {
113                                                                     BIP_RANGE
114                                                                     (5),
115                                                                     BIP_RANGE
116                                                                     (0.5),
117                                                                     BIP_RANGE
118                                                                     (0.05),
119                                                                     BIP_RANGE
120                                                                     (0.01)
121                                                                     }
122 };
123
124 static const struct comedi_lrange range_rti800_ai_unipolar = { 4, {
125                                                                    UNI_RANGE
126                                                                    (10),
127                                                                    UNI_RANGE(1),
128                                                                    UNI_RANGE
129                                                                    (0.1),
130                                                                    UNI_RANGE
131                                                                    (0.02)
132                                                                    }
133 };
134
135 struct rti800_board {
136
137         const char *name;
138         int has_ao;
139 };
140
141 static irqreturn_t rti800_interrupt(int irq, void *dev);
142
143 struct rti800_private {
144         enum {
145                 adc_diff, adc_pseudodiff, adc_singleended
146         } adc_mux;
147         enum {
148                 adc_bipolar10, adc_bipolar5, adc_unipolar10
149         } adc_range;
150         enum {
151                 adc_2comp, adc_straight
152         } adc_coding;
153         enum {
154                 dac_bipolar10, dac_unipolar10
155         } dac0_range, dac1_range;
156         enum {
157                 dac_2comp, dac_straight
158         } dac0_coding, dac1_coding;
159         const struct comedi_lrange *ao_range_type_list[2];
160         unsigned int ao_readback[2];
161         int muxgain_bits;
162 };
163
164 #define RTI800_TIMEOUT 100
165
166 static irqreturn_t rti800_interrupt(int irq, void *dev)
167 {
168         return IRQ_HANDLED;
169 }
170
171 /* settling delay times in usec for different gains */
172 static const int gaindelay[] = { 10, 20, 40, 80 };
173
174 static int rti800_ai_insn_read(struct comedi_device *dev,
175                                struct comedi_subdevice *s,
176                                struct comedi_insn *insn, unsigned int *data)
177 {
178         struct rti800_private *devpriv = dev->private;
179         int i, t;
180         int status;
181         int chan = CR_CHAN(insn->chanspec);
182         unsigned gain = CR_RANGE(insn->chanspec);
183         unsigned muxgain_bits;
184
185         inb(dev->iobase + RTI800_ADCHI);
186         outb(0, dev->iobase + RTI800_CLRFLAGS);
187
188         muxgain_bits = chan | (gain << 5);
189         if (muxgain_bits != devpriv->muxgain_bits) {
190                 devpriv->muxgain_bits = muxgain_bits;
191                 outb(devpriv->muxgain_bits, dev->iobase + RTI800_MUXGAIN);
192                 /* without a delay here, the RTI_OVERRUN bit
193                  * gets set, and you will have an error. */
194                 if (insn->n > 0) {
195                         BUG_ON(gain >= ARRAY_SIZE(gaindelay));
196                         udelay(gaindelay[gain]);
197                 }
198         }
199
200         for (i = 0; i < insn->n; i++) {
201                 outb(0, dev->iobase + RTI800_CONVERT);
202                 for (t = RTI800_TIMEOUT; t; t--) {
203                         status = inb(dev->iobase + RTI800_CSR);
204                         if (status & RTI800_OVERRUN) {
205                                 printk(KERN_WARNING "rti800: a/d overrun\n");
206                                 outb(0, dev->iobase + RTI800_CLRFLAGS);
207                                 return -EIO;
208                         }
209                         if (status & RTI800_DONE)
210                                 break;
211                         udelay(1);
212                 }
213                 if (t == 0) {
214                         printk(KERN_WARNING "rti800: timeout\n");
215                         return -ETIME;
216                 }
217                 data[i] = inb(dev->iobase + RTI800_ADCLO);
218                 data[i] |= (0xf & inb(dev->iobase + RTI800_ADCHI)) << 8;
219
220                 if (devpriv->adc_coding == adc_2comp)
221                         data[i] ^= 0x800;
222         }
223
224         return i;
225 }
226
227 static int rti800_ao_insn_read(struct comedi_device *dev,
228                                struct comedi_subdevice *s,
229                                struct comedi_insn *insn, unsigned int *data)
230 {
231         struct rti800_private *devpriv = dev->private;
232         int i;
233         int chan = CR_CHAN(insn->chanspec);
234
235         for (i = 0; i < insn->n; i++)
236                 data[i] = devpriv->ao_readback[chan];
237
238         return i;
239 }
240
241 static int rti800_ao_insn_write(struct comedi_device *dev,
242                                 struct comedi_subdevice *s,
243                                 struct comedi_insn *insn, unsigned int *data)
244 {
245         struct rti800_private *devpriv = dev->private;
246         int chan = CR_CHAN(insn->chanspec);
247         int d;
248         int i;
249
250         for (i = 0; i < insn->n; i++) {
251                 devpriv->ao_readback[chan] = d = data[i];
252                 if (devpriv->dac0_coding == dac_2comp)
253                         d ^= 0x800;
254
255                 outb(d & 0xff,
256                      dev->iobase + (chan ? RTI800_DAC1LO : RTI800_DAC0LO));
257                 outb(d >> 8,
258                      dev->iobase + (chan ? RTI800_DAC1HI : RTI800_DAC0HI));
259         }
260         return i;
261 }
262
263 static int rti800_di_insn_bits(struct comedi_device *dev,
264                                struct comedi_subdevice *s,
265                                struct comedi_insn *insn, unsigned int *data)
266 {
267         data[1] = inb(dev->iobase + RTI800_DI);
268         return insn->n;
269 }
270
271 static int rti800_do_insn_bits(struct comedi_device *dev,
272                                struct comedi_subdevice *s,
273                                struct comedi_insn *insn, unsigned int *data)
274 {
275         if (data[0]) {
276                 s->state &= ~data[0];
277                 s->state |= data[0] & data[1];
278                 /* Outputs are inverted... */
279                 outb(s->state ^ 0xff, dev->iobase + RTI800_DO);
280         }
281
282         data[1] = s->state;
283
284         return insn->n;
285 }
286
287 /*
288    options[0] - I/O port
289    options[1] - irq
290    options[2] - a/d mux
291         0=differential, 1=pseudodiff, 2=single
292    options[3] - a/d range
293         0=bipolar10, 1=bipolar5, 2=unipolar10
294    options[4] - a/d coding
295         0=2's comp, 1=straight binary
296    options[5] - dac0 range
297         0=bipolar10, 1=unipolar10
298    options[6] - dac0 coding
299         0=2's comp, 1=straight binary
300    options[7] - dac1 range
301    options[8] - dac1 coding
302  */
303
304 static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
305 {
306         const struct rti800_board *board = comedi_board(dev);
307         struct rti800_private *devpriv;
308         unsigned int irq;
309         unsigned long iobase;
310         int ret;
311         struct comedi_subdevice *s;
312
313         iobase = it->options[0];
314         printk(KERN_INFO "comedi%d: rti800: 0x%04lx\n", dev->minor, iobase);
315         if (!request_region(iobase, RTI800_SIZE, "rti800")) {
316                 printk(KERN_WARNING "I/O port conflict\n");
317                 return -EIO;
318         }
319         dev->iobase = iobase;
320
321 #ifdef DEBUG
322         printk(KERN_DEBUG "fingerprint=%x,%x,%x,%x,%x ",
323                inb(dev->iobase + 0),
324                inb(dev->iobase + 1),
325                inb(dev->iobase + 2),
326                inb(dev->iobase + 3), inb(dev->iobase + 4));
327 #endif
328
329         outb(0, dev->iobase + RTI800_CSR);
330         inb(dev->iobase + RTI800_ADCHI);
331         outb(0, dev->iobase + RTI800_CLRFLAGS);
332
333         irq = it->options[1];
334         if (irq) {
335                 printk(KERN_INFO "( irq = %u )\n", irq);
336                 ret = request_irq(irq, rti800_interrupt, 0, "rti800", dev);
337                 if (ret < 0) {
338                         printk(KERN_WARNING " Failed to allocate IRQ\n");
339                         return ret;
340                 }
341                 dev->irq = irq;
342         } else {
343                 printk(KERN_INFO "( no irq )\n");
344         }
345
346         dev->board_name = board->name;
347
348         ret = comedi_alloc_subdevices(dev, 4);
349         if (ret)
350                 return ret;
351
352         devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
353         if (!devpriv)
354                 return -ENOMEM;
355         dev->private = devpriv;
356
357         devpriv->adc_mux = it->options[2];
358         devpriv->adc_range = it->options[3];
359         devpriv->adc_coding = it->options[4];
360         devpriv->dac0_range = it->options[5];
361         devpriv->dac0_coding = it->options[6];
362         devpriv->dac1_range = it->options[7];
363         devpriv->dac1_coding = it->options[8];
364         devpriv->muxgain_bits = -1;
365
366         s = &dev->subdevices[0];
367         /* ai subdevice */
368         s->type = COMEDI_SUBD_AI;
369         s->subdev_flags = SDF_READABLE | SDF_GROUND;
370         s->n_chan = (devpriv->adc_mux ? 16 : 8);
371         s->insn_read = rti800_ai_insn_read;
372         s->maxdata = 0xfff;
373         switch (devpriv->adc_range) {
374         case adc_bipolar10:
375                 s->range_table = &range_rti800_ai_10_bipolar;
376                 break;
377         case adc_bipolar5:
378                 s->range_table = &range_rti800_ai_5_bipolar;
379                 break;
380         case adc_unipolar10:
381                 s->range_table = &range_rti800_ai_unipolar;
382                 break;
383         }
384
385         s = &dev->subdevices[1];
386         if (board->has_ao) {
387                 /* ao subdevice (only on rti815) */
388                 s->type = COMEDI_SUBD_AO;
389                 s->subdev_flags = SDF_WRITABLE;
390                 s->n_chan = 2;
391                 s->insn_read = rti800_ao_insn_read;
392                 s->insn_write = rti800_ao_insn_write;
393                 s->maxdata = 0xfff;
394                 s->range_table_list = devpriv->ao_range_type_list;
395                 switch (devpriv->dac0_range) {
396                 case dac_bipolar10:
397                         devpriv->ao_range_type_list[0] = &range_bipolar10;
398                         break;
399                 case dac_unipolar10:
400                         devpriv->ao_range_type_list[0] = &range_unipolar10;
401                         break;
402                 }
403                 switch (devpriv->dac1_range) {
404                 case dac_bipolar10:
405                         devpriv->ao_range_type_list[1] = &range_bipolar10;
406                         break;
407                 case dac_unipolar10:
408                         devpriv->ao_range_type_list[1] = &range_unipolar10;
409                         break;
410                 }
411         } else {
412                 s->type = COMEDI_SUBD_UNUSED;
413         }
414
415         s = &dev->subdevices[2];
416         /* di */
417         s->type = COMEDI_SUBD_DI;
418         s->subdev_flags = SDF_READABLE;
419         s->n_chan = 8;
420         s->insn_bits = rti800_di_insn_bits;
421         s->maxdata = 1;
422         s->range_table = &range_digital;
423
424         s = &dev->subdevices[3];
425         /* do */
426         s->type = COMEDI_SUBD_DO;
427         s->subdev_flags = SDF_WRITABLE;
428         s->n_chan = 8;
429         s->insn_bits = rti800_do_insn_bits;
430         s->maxdata = 1;
431         s->range_table = &range_digital;
432
433 /* don't yet know how to deal with counter/timers */
434 #if 0
435         s = &dev->subdevices[4];
436         /* do */
437         s->type = COMEDI_SUBD_TIMER;
438 #endif
439
440         return 0;
441 }
442
443 static void rti800_detach(struct comedi_device *dev)
444 {
445         if (dev->iobase)
446                 release_region(dev->iobase, RTI800_SIZE);
447         if (dev->irq)
448                 free_irq(dev->irq, dev);
449 }
450
451 static const struct rti800_board boardtypes[] = {
452         { "rti800", 0 },
453         { "rti815", 1 },
454 };
455
456 static struct comedi_driver rti800_driver = {
457         .driver_name    = "rti800",
458         .module         = THIS_MODULE,
459         .attach         = rti800_attach,
460         .detach         = rti800_detach,
461         .num_names      = ARRAY_SIZE(boardtypes),
462         .board_name     = &boardtypes[0].name,
463         .offset         = sizeof(struct rti800_board),
464 };
465 module_comedi_driver(rti800_driver);
466
467 MODULE_AUTHOR("Comedi http://www.comedi.org");
468 MODULE_DESCRIPTION("Comedi low-level driver");
469 MODULE_LICENSE("GPL");