Merge branch 'for-2.6.31' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
[pandora-kernel.git] / drivers / staging / comedi / drivers / adq12b.c
1 /*
2     comedi/drivers/adq12b.c
3     driver for MicroAxial ADQ12-B data acquisition and control card
4
5     COMEDI - Linux Control and Measurement Device Interface
6     Copyright (C) 2000 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: adq12b
25 Description: driver for MicroAxial ADQ12-B data acquisition and control card
26 Devices: [MicroAxial] ADQ12-B (adq12b)
27 Author: jeremy theler <thelerg@ib.cnea.gov.ar>
28 Updated: Thu, 21 Feb 2008 02:56:27 -0300
29 Status: works
30
31 Driver for the acquisition card ADQ12-B (without any add-on).
32
33  - Analog input is subdevice 0 (16 channels single-ended or 8 differential)
34  - Digital input is subdevice 1 (5 channels)
35  - Digital output is subdevice 1 (8 channels)
36  - The PACER is not supported in this version
37
38 If you do not specify any options, they will default to
39
40   # comedi_config /dev/comedi0 adq12b 0x300,0,0
41
42   option 1: I/O base address. The following table is provided as a help
43    of the hardware jumpers.
44
45          address            jumper JADR
46           0x300                 1 (factory default)
47           0x320                 2
48           0x340                 3
49           0x360                 4
50           0x380                 5
51           0x3A0                 6
52
53   option 2: unipolar/bipolar ADC selection: 0 -> bipolar, 1 -> unipolar
54
55         selection         comedi_config option            JUB
56          bipolar                0                         2-3 (factory default)
57          unipolar               1                         1-2
58
59   option 3: single-ended/differential AI selection: 0 -> SE, 1 -> differential
60
61         selection         comedi_config option     JCHA    JCHB
62        single-ended             0                  1-2     1-2 (factory default)
63        differential             1                  2-3     2-3
64
65
66    written by jeremy theler <thelerg@ib.cnea.gov.ar>
67
68    instituto balseiro
69    comision nacional de energia atomica
70    universidad nacional de cuyo
71    argentina
72
73    21-feb-2008
74      + changed supported devices string (missused the [] and ())
75
76    13-oct-2007
77      + first try
78
79
80 */
81
82 #include "../comedidev.h"
83
84 /* address scheme (page 2.17 of the manual) */
85 #define ADQ12B_SIZE     16
86
87 #define ADQ12B_CTREG    0x00
88 #define ADQ12B_STINR    0x00
89 #define ADQ12B_OUTBR    0x04
90 #define ADQ12B_ADLOW    0x08
91 #define ADQ12B_ADHIG    0x09
92 #define ADQ12B_CONT0    0x0c
93 #define ADQ12B_CONT1    0x0d
94 #define ADQ12B_CONT2    0x0e
95 #define ADQ12B_COWORD   0x0f
96
97 /* mask of the bit at STINR to check end of conversion */
98 #define ADQ12B_EOC     0x20
99
100 #define TIMEOUT        20
101
102 /* available ranges through the PGA gains */
103 static const struct comedi_lrange range_adq12b_ai_bipolar = { 4, {
104         BIP_RANGE(5),
105         BIP_RANGE(2),
106         BIP_RANGE(1),
107         BIP_RANGE(0.5)
108 }};
109
110 static const struct comedi_lrange range_adq12b_ai_unipolar = { 4, {
111         UNI_RANGE(5),
112         UNI_RANGE(2),
113         UNI_RANGE(1),
114         UNI_RANGE(0.5)
115 }};
116
117
118
119 struct adq12b_board {
120         const char *name;
121         int ai_se_chans;
122         int ai_diff_chans;
123         int ai_bits;
124         int di_chans;
125         int do_chans;
126 };
127
128 static const struct adq12b_board adq12b_boards[] = {
129         {
130         .name = "adq12b",
131         .ai_se_chans = 16,
132         .ai_diff_chans = 8,
133         .ai_bits = 12,
134         .di_chans = 5,
135         .do_chans = 8
136         }
137 /* potentially, more adq-based deviced will be added */
138 /*,
139         .name = "adq12b",
140         .ai_chans = 16,  // this is just for reference, hardcoded again later
141         .ai_bits = 12,
142         .di_chans = 8,
143         .do_chans = 5
144         }*/
145 };
146
147 #define thisboard ((const struct adq12b_board *)dev->board_ptr)
148
149 struct adq12b_private {
150         int unipolar;          /* option 2 of comedi_config (1 is iobase) */
151         int differential;      /* option 3 of comedi_config */
152         int last_channel;
153         int last_range;
154         unsigned int digital_state;
155 };
156
157 #define devpriv ((struct adq12b_private *)dev->private)
158
159 /*
160  * The struct comedi_driver structure tells the Comedi core module
161  * which functions to call to configure/deconfigure (attach/detach)
162  * the board, and also about the kernel module that contains
163  * the device code.
164  */
165 static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it);
166 static int adq12b_detach(struct comedi_device *dev);
167 static struct comedi_driver driver_adq12b={
168         driver_name:    "adq12b",
169         module:         THIS_MODULE,
170         attach:         adq12b_attach,
171         detach:         adq12b_detach,
172         board_name:     &adq12b_boards[0].name,
173         offset:         sizeof(struct adq12b_board),
174         num_names:      ARRAY_SIZE(adq12b_boards),
175 };
176
177 static int adq12b_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
178 static int adq12b_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
179 static int adq12b_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
180
181 /*
182  * Attach is called by the Comedi core to configure the driver
183  * for a particular board.  If you specified a board_name array
184  * in the driver structure, dev->board_ptr contains that
185  * address.
186  */
187 static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
188 {
189         struct comedi_subdevice *s;
190         unsigned long iobase;
191         int unipolar, differential;
192
193         iobase = it->options[0];
194         unipolar = it->options[1];
195         differential = it->options[2];
196
197         printk("comedi%d: adq12b called with options base=0x%03lx, %s and %s\n", dev->minor, iobase, (unipolar==1)?"unipolar":"bipolar", (differential==1) ? "differential" : "single-ended");
198
199         /* if no address was specified, try the default 0x300 */
200         if (iobase == 0) {
201           printk("comedi%d: adq12b warning: I/O base address not specified. Trying the default 0x300.\n", dev->minor);
202           iobase = 0x300;
203         }
204
205         printk("comedi%d: adq12b: 0x%04lx ", dev->minor, iobase);
206         if (!request_region(iobase, ADQ12B_SIZE, "adq12b")) {
207           printk("I/O port conflict\n");
208           return -EIO;
209         }
210         dev->iobase = iobase;
211
212 /*
213  * Initialize dev->board_name.  Note that we can use the "thisboard"
214  * macro now, since we just initialized it in the last line.
215  */
216         dev->board_name = thisboard->name;
217
218 /*
219  * Allocate the private structure area.  alloc_private() is a
220  * convenient macro defined in comedidev.h.
221  */
222         if (alloc_private (dev, sizeof (struct adq12b_private)) < 0)
223           return -ENOMEM;
224
225 /* fill in devpriv structure */
226         devpriv->unipolar = unipolar;
227         devpriv->differential = differential;
228         devpriv->digital_state = 0;
229 /* initialize channel and range to -1 so we make sure we always write
230    at least once to the CTREG in the instruction */
231         devpriv->last_channel = -1;
232         devpriv->last_range = -1;
233
234
235 /*
236  * Allocate the subdevice structures.  alloc_subdevice() is a
237  * convenient macro defined in comedidev.h.
238  */
239         if (alloc_subdevices (dev, 3)<0)
240            return -ENOMEM;
241
242         s = dev->subdevices+0;
243         /* analog input subdevice */
244         s->type = COMEDI_SUBD_AI;
245         if (differential) {
246           s->subdev_flags = SDF_READABLE|SDF_GROUND|SDF_DIFF;
247           s->n_chan = thisboard->ai_diff_chans;
248         } else {
249           s->subdev_flags = SDF_READABLE|SDF_GROUND;
250           s->n_chan = thisboard->ai_se_chans;
251         }
252
253         if (unipolar) {
254           s->range_table = &range_adq12b_ai_unipolar;
255         } else {
256           s->range_table = &range_adq12b_ai_bipolar;
257         }
258
259         s->maxdata = (1 << thisboard->ai_bits)-1;
260
261
262         s->len_chanlist = 4;  /* This is the maximum chanlist length that
263                                  the board can handle */
264         s->insn_read = adq12b_ai_rinsn;
265
266
267         s = dev->subdevices+1;
268         /* digital input subdevice */
269         s->type = COMEDI_SUBD_DI;
270         s->subdev_flags = SDF_READABLE;
271         s->n_chan=thisboard->di_chans;
272         s->maxdata = 1;
273         s->range_table = &range_digital;
274         s->insn_bits = adq12b_di_insn_bits;
275
276         s = dev->subdevices+2;
277         /* digital output subdevice */
278         s->type = COMEDI_SUBD_DO;
279         s->subdev_flags = SDF_WRITABLE;
280         s->n_chan = thisboard->do_chans;
281         s->maxdata = 1;
282         s->range_table = &range_digital;
283         s->insn_bits = adq12b_do_insn_bits;
284
285
286         printk("attached\n");
287
288         return 0;
289 }
290
291
292 /*
293  * _detach is called to deconfigure a device.  It should deallocate
294  * resources.
295  * This function is also called when _attach() fails, so it should be
296  * careful not to release resources that were not necessarily
297  * allocated by _attach().  dev->private and dev->subdevices are
298  * deallocated automatically by the core.
299  */
300 static int adq12b_detach(struct comedi_device *dev)
301 {
302         if (dev->iobase)
303           release_region(dev->iobase, ADQ12B_SIZE);
304
305         kfree(devpriv);
306
307         printk("comedi%d: adq12b: removed\n", dev->minor);
308
309         return 0;
310 }
311
312 /*
313  * "instructions" read/write data in "one-shot" or "software-triggered"
314  * mode.
315  */
316
317 static int adq12b_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
318 {
319         int n, i;
320         int range, channel;
321         unsigned char hi, lo, status;
322
323         /* change channel and range only if it is different from the previous */
324         range = CR_RANGE(insn->chanspec);
325         channel = CR_CHAN(insn->chanspec);
326         if (channel != devpriv->last_channel || range != devpriv->last_range) {
327           outb((range << 4) | channel, dev->iobase + ADQ12B_CTREG);
328           udelay(50);   /* wait for the mux to settle */
329         }
330
331         /* trigger conversion */
332         status = inb(dev->iobase + ADQ12B_ADLOW);
333
334         /* convert n samples */
335         for (n=0; n < insn->n; n++){
336
337           /* wait for end of convertion */
338           i = 0;
339           do {
340 /* udelay(1); */
341             status = inb(dev->iobase + ADQ12B_STINR);
342             status = status & ADQ12B_EOC;
343           } while (status == 0 && ++i < TIMEOUT);
344 /* } while (++i < 10); */
345
346           /* read data */
347           hi = inb(dev->iobase + ADQ12B_ADHIG);
348           lo = inb(dev->iobase + ADQ12B_ADLOW);
349
350           /* printk("debug: chan=%d range=%d status=%d hi=%d lo=%d\n", channel, range, status,  hi, lo); */
351           data[n] = (hi << 8) | lo;
352
353         }
354
355         /* return the number of samples read/written */
356         return n;
357 }
358
359
360 static int adq12b_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,   struct comedi_insn *insn, unsigned int *data)
361 {
362
363         /* only bits 0-4 have information about digital inputs */
364         data[1] = (inb(dev->iobase+ADQ12B_STINR) & (0x1f));
365
366         return 2;
367 }
368
369
370 static int adq12b_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,   struct comedi_insn *insn, unsigned int *data)
371 {
372         int channel;
373
374         for (channel = 0; channel < 8; channel++)
375           if (((data[0]>>channel) & 0x01) != 0)
376             outb((((data[1]>>channel)&0x01)<<3) | channel, dev->iobase + ADQ12B_OUTBR);
377
378         /* store information to retrieve when asked for reading */
379         if (data[0]) {
380           devpriv->digital_state &= ~data[0];
381           devpriv->digital_state |= (data[0]&data[1]);
382         }
383
384         data[1] = devpriv->digital_state;
385
386         return 2;
387 }
388
389
390 /*
391  * A convenient macro that defines init_module() and cleanup_module(),
392  * as necessary.
393  */
394 COMEDI_INITCLEANUP(driver_adq12b);