Merge tag 'regulator-v3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[deliverable/linux.git] / drivers / staging / comedi / drivers / das800.c
1 /*
2 comedi/drivers/das800.c
3 Driver for Keitley das800 series boards and compatibles
4 Copyright (C) 2000 Frank Mori Hess <fmhess@users.sourceforge.net>
5
6 COMEDI - Linux Control and Measurement Device Interface
7 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 */
19 /*
20 Driver: das800
21 Description: Keithley Metrabyte DAS800 (& compatibles)
22 Author: Frank Mori Hess <fmhess@users.sourceforge.net>
23 Devices: [Keithley Metrabyte] DAS-800 (das-800), DAS-801 (das-801),
24 DAS-802 (das-802),
25 [Measurement Computing] CIO-DAS800 (cio-das800),
26 CIO-DAS801 (cio-das801), CIO-DAS802 (cio-das802),
27 CIO-DAS802/16 (cio-das802/16)
28 Status: works, cio-das802/16 untested - email me if you have tested it
29
30 Configuration options:
31 [0] - I/O port base address
32 [1] - IRQ (optional, required for timed or externally triggered conversions)
33
34 Notes:
35 IRQ can be omitted, although the cmd interface will not work without it.
36
37 All entries in the channel/gain list must use the same gain and be
38 consecutive channels counting upwards in channel number (these are
39 hardware limitations.)
40
41 I've never tested the gain setting stuff since I only have a
42 DAS-800 board with fixed gain.
43
44 The cio-das802/16 does not have a fifo-empty status bit! Therefore
45 only fifo-half-full transfers are possible with this card.
46 */
47 /*
48
49 cmd triggers supported:
50 start_src: TRIG_NOW | TRIG_EXT
51 scan_begin_src: TRIG_FOLLOW
52 scan_end_src: TRIG_COUNT
53 convert_src: TRIG_TIMER | TRIG_EXT
54 stop_src: TRIG_NONE | TRIG_COUNT
55
56
57 */
58
59 #include <linux/module.h>
60 #include <linux/interrupt.h>
61 #include "../comedidev.h"
62
63 #include <linux/delay.h>
64
65 #include "8253.h"
66 #include "comedi_fc.h"
67
68 #define DAS800_SIZE 8
69 #define N_CHAN_AI 8 /* number of analog input channels */
70
71 /* Registers for the das800 */
72
73 #define DAS800_LSB 0
74 #define FIFO_EMPTY 0x1
75 #define FIFO_OVF 0x2
76 #define DAS800_MSB 1
77 #define DAS800_CONTROL1 2
78 #define CONTROL1_INTE 0x8
79 #define DAS800_CONV_CONTROL 2
80 #define ITE 0x1
81 #define CASC 0x2
82 #define DTEN 0x4
83 #define IEOC 0x8
84 #define EACS 0x10
85 #define CONV_HCEN 0x80
86 #define DAS800_SCAN_LIMITS 2
87 #define DAS800_STATUS 2
88 #define IRQ 0x8
89 #define BUSY 0x80
90 #define DAS800_GAIN 3
91 #define CIO_FFOV 0x8 /* cio-das802/16 fifo overflow */
92 #define CIO_ENHF 0x90 /* cio-das802/16 fifo half full int ena */
93 #define CONTROL1 0x80
94 #define CONV_CONTROL 0xa0
95 #define SCAN_LIMITS 0xc0
96 #define ID 0xe0
97 #define DAS800_8254 4
98 #define DAS800_STATUS2 7
99 #define STATUS2_HCEN 0x80
100 #define STATUS2_INTE 0X20
101 #define DAS800_ID 7
102
103 #define DAS802_16_HALF_FIFO_SZ 128
104
105 struct das800_board {
106 const char *name;
107 int ai_speed;
108 const struct comedi_lrange *ai_range;
109 int resolution;
110 };
111
112 static const struct comedi_lrange range_das801_ai = {
113 9, {
114 BIP_RANGE(5),
115 BIP_RANGE(10),
116 UNI_RANGE(10),
117 BIP_RANGE(0.5),
118 UNI_RANGE(1),
119 BIP_RANGE(0.05),
120 UNI_RANGE(0.1),
121 BIP_RANGE(0.01),
122 UNI_RANGE(0.02)
123 }
124 };
125
126 static const struct comedi_lrange range_cio_das801_ai = {
127 9, {
128 BIP_RANGE(5),
129 BIP_RANGE(10),
130 UNI_RANGE(10),
131 BIP_RANGE(0.5),
132 UNI_RANGE(1),
133 BIP_RANGE(0.05),
134 UNI_RANGE(0.1),
135 BIP_RANGE(0.005),
136 UNI_RANGE(0.01)
137 }
138 };
139
140 static const struct comedi_lrange range_das802_ai = {
141 9, {
142 BIP_RANGE(5),
143 BIP_RANGE(10),
144 UNI_RANGE(10),
145 BIP_RANGE(2.5),
146 UNI_RANGE(5),
147 BIP_RANGE(1.25),
148 UNI_RANGE(2.5),
149 BIP_RANGE(0.625),
150 UNI_RANGE(1.25)
151 }
152 };
153
154 static const struct comedi_lrange range_das80216_ai = {
155 8, {
156 BIP_RANGE(10),
157 UNI_RANGE(10),
158 BIP_RANGE(5),
159 UNI_RANGE(5),
160 BIP_RANGE(2.5),
161 UNI_RANGE(2.5),
162 BIP_RANGE(1.25),
163 UNI_RANGE(1.25)
164 }
165 };
166
167 enum das800_boardinfo {
168 BOARD_DAS800,
169 BOARD_CIODAS800,
170 BOARD_DAS801,
171 BOARD_CIODAS801,
172 BOARD_DAS802,
173 BOARD_CIODAS802,
174 BOARD_CIODAS80216,
175 };
176
177 static const struct das800_board das800_boards[] = {
178 [BOARD_DAS800] = {
179 .name = "das-800",
180 .ai_speed = 25000,
181 .ai_range = &range_bipolar5,
182 .resolution = 12,
183 },
184 [BOARD_CIODAS800] = {
185 .name = "cio-das800",
186 .ai_speed = 20000,
187 .ai_range = &range_bipolar5,
188 .resolution = 12,
189 },
190 [BOARD_DAS801] = {
191 .name = "das-801",
192 .ai_speed = 25000,
193 .ai_range = &range_das801_ai,
194 .resolution = 12,
195 },
196 [BOARD_CIODAS801] = {
197 .name = "cio-das801",
198 .ai_speed = 20000,
199 .ai_range = &range_cio_das801_ai,
200 .resolution = 12,
201 },
202 [BOARD_DAS802] = {
203 .name = "das-802",
204 .ai_speed = 25000,
205 .ai_range = &range_das802_ai,
206 .resolution = 12,
207 },
208 [BOARD_CIODAS802] = {
209 .name = "cio-das802",
210 .ai_speed = 20000,
211 .ai_range = &range_das802_ai,
212 .resolution = 12,
213 },
214 [BOARD_CIODAS80216] = {
215 .name = "cio-das802/16",
216 .ai_speed = 10000,
217 .ai_range = &range_das80216_ai,
218 .resolution = 16,
219 },
220 };
221
222 struct das800_private {
223 unsigned int count; /* number of data points left to be taken */
224 unsigned int divisor1; /* counter 1 value for timed conversions */
225 unsigned int divisor2; /* counter 2 value for timed conversions */
226 unsigned int do_bits; /* digital output bits */
227 bool forever; /* flag that we should take data forever */
228 };
229
230 static void das800_ind_write(struct comedi_device *dev,
231 unsigned val, unsigned reg)
232 {
233 /*
234 * Select dev->iobase + 2 to be desired register
235 * then write to that register.
236 */
237 outb(reg, dev->iobase + DAS800_GAIN);
238 outb(val, dev->iobase + 2);
239 }
240
241 static unsigned das800_ind_read(struct comedi_device *dev, unsigned reg)
242 {
243 /*
244 * Select dev->iobase + 7 to be desired register
245 * then read from that register.
246 */
247 outb(reg, dev->iobase + DAS800_GAIN);
248 return inb(dev->iobase + 7);
249 }
250
251 static void das800_enable(struct comedi_device *dev)
252 {
253 const struct das800_board *thisboard = comedi_board(dev);
254 struct das800_private *devpriv = dev->private;
255 unsigned long irq_flags;
256
257 spin_lock_irqsave(&dev->spinlock, irq_flags);
258 /* enable fifo-half full interrupts for cio-das802/16 */
259 if (thisboard->resolution == 16)
260 outb(CIO_ENHF, dev->iobase + DAS800_GAIN);
261 /* enable hardware triggering */
262 das800_ind_write(dev, CONV_HCEN, CONV_CONTROL);
263 /* enable card's interrupt */
264 das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, CONTROL1);
265 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
266 }
267
268 static void das800_disable(struct comedi_device *dev)
269 {
270 unsigned long irq_flags;
271
272 spin_lock_irqsave(&dev->spinlock, irq_flags);
273 /* disable hardware triggering of conversions */
274 das800_ind_write(dev, 0x0, CONV_CONTROL);
275 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
276 }
277
278 static int das800_set_frequency(struct comedi_device *dev)
279 {
280 struct das800_private *devpriv = dev->private;
281 int err = 0;
282
283 if (i8254_load(dev->iobase + DAS800_8254, 0, 1, devpriv->divisor1, 2))
284 err++;
285 if (i8254_load(dev->iobase + DAS800_8254, 0, 2, devpriv->divisor2, 2))
286 err++;
287 if (err)
288 return -1;
289
290 return 0;
291 }
292
293 static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
294 {
295 struct das800_private *devpriv = dev->private;
296
297 devpriv->forever = false;
298 devpriv->count = 0;
299 das800_disable(dev);
300 return 0;
301 }
302
303 static int das800_ai_do_cmdtest(struct comedi_device *dev,
304 struct comedi_subdevice *s,
305 struct comedi_cmd *cmd)
306 {
307 const struct das800_board *thisboard = comedi_board(dev);
308 struct das800_private *devpriv = dev->private;
309 int err = 0;
310
311 /* Step 1 : check if triggers are trivially valid */
312
313 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
314 err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
315 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
316 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
317 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
318
319 if (err)
320 return 1;
321
322 /* Step 2a : make sure trigger sources are unique */
323
324 err |= cfc_check_trigger_is_unique(cmd->start_src);
325 err |= cfc_check_trigger_is_unique(cmd->convert_src);
326 err |= cfc_check_trigger_is_unique(cmd->stop_src);
327
328 /* Step 2b : and mutually compatible */
329
330 if (err)
331 return 2;
332
333 /* Step 3: check if arguments are trivially valid */
334
335 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
336
337 if (cmd->convert_src == TRIG_TIMER)
338 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
339 thisboard->ai_speed);
340
341 err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
342 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
343
344 if (cmd->stop_src == TRIG_COUNT)
345 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
346 else /* TRIG_NONE */
347 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
348
349 if (err)
350 return 3;
351
352 /* step 4: fix up any arguments */
353
354 if (cmd->convert_src == TRIG_TIMER) {
355 int tmp = cmd->convert_arg;
356
357 /* calculate counter values that give desired timing */
358 i8253_cascade_ns_to_timer(I8254_OSC_BASE_1MHZ,
359 &devpriv->divisor1,
360 &devpriv->divisor2,
361 &cmd->convert_arg, cmd->flags);
362 if (tmp != cmd->convert_arg)
363 err++;
364 }
365
366 if (err)
367 return 4;
368
369 /* check channel/gain list against card's limitations */
370 if (cmd->chanlist) {
371 unsigned int chan = CR_CHAN(cmd->chanlist[0]);
372 unsigned int range = CR_RANGE(cmd->chanlist[0]);
373 unsigned int next;
374 int i;
375
376 for (i = 1; i < cmd->chanlist_len; i++) {
377 next = cmd->chanlist[i];
378 if (CR_CHAN(next) != (chan + i) % N_CHAN_AI) {
379 dev_err(dev->class_dev,
380 "chanlist must be consecutive, counting upwards\n");
381 err++;
382 }
383 if (CR_RANGE(next) != range) {
384 dev_err(dev->class_dev,
385 "chanlist must all have the same gain\n");
386 err++;
387 }
388 }
389 }
390
391 if (err)
392 return 5;
393
394 return 0;
395 }
396
397 static int das800_ai_do_cmd(struct comedi_device *dev,
398 struct comedi_subdevice *s)
399 {
400 const struct das800_board *thisboard = comedi_board(dev);
401 struct das800_private *devpriv = dev->private;
402 struct comedi_async *async = s->async;
403 unsigned int gain = CR_RANGE(async->cmd.chanlist[0]);
404 unsigned int start_chan = CR_CHAN(async->cmd.chanlist[0]);
405 unsigned int end_chan = (start_chan + async->cmd.chanlist_len - 1) % 8;
406 unsigned int scan_chans = (end_chan << 3) | start_chan;
407 int conv_bits;
408 unsigned long irq_flags;
409
410 das800_disable(dev);
411
412 spin_lock_irqsave(&dev->spinlock, irq_flags);
413 /* set scan limits */
414 das800_ind_write(dev, scan_chans, SCAN_LIMITS);
415 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
416
417 /* set gain */
418 if (thisboard->resolution == 12 && gain > 0)
419 gain += 0x7;
420 gain &= 0xf;
421 outb(gain, dev->iobase + DAS800_GAIN);
422
423 switch (async->cmd.stop_src) {
424 case TRIG_COUNT:
425 devpriv->count = async->cmd.stop_arg * async->cmd.chanlist_len;
426 devpriv->forever = false;
427 break;
428 case TRIG_NONE:
429 devpriv->forever = true;
430 devpriv->count = 0;
431 break;
432 default:
433 break;
434 }
435
436 /* enable auto channel scan, send interrupts on end of conversion
437 * and set clock source to internal or external
438 */
439 conv_bits = 0;
440 conv_bits |= EACS | IEOC;
441 if (async->cmd.start_src == TRIG_EXT)
442 conv_bits |= DTEN;
443 switch (async->cmd.convert_src) {
444 case TRIG_TIMER:
445 conv_bits |= CASC | ITE;
446 /* set conversion frequency */
447 if (das800_set_frequency(dev) < 0) {
448 comedi_error(dev, "Error setting up counters");
449 return -1;
450 }
451 break;
452 case TRIG_EXT:
453 break;
454 default:
455 break;
456 }
457
458 spin_lock_irqsave(&dev->spinlock, irq_flags);
459 das800_ind_write(dev, conv_bits, CONV_CONTROL);
460 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
461
462 async->events = 0;
463 das800_enable(dev);
464 return 0;
465 }
466
467 static unsigned int das800_ai_get_sample(struct comedi_device *dev)
468 {
469 unsigned int lsb = inb(dev->iobase + DAS800_LSB);
470 unsigned int msb = inb(dev->iobase + DAS800_MSB);
471
472 return (msb << 8) | lsb;
473 }
474
475 static irqreturn_t das800_interrupt(int irq, void *d)
476 {
477 struct comedi_device *dev = d;
478 struct das800_private *devpriv = dev->private;
479 struct comedi_subdevice *s = dev->read_subdev;
480 struct comedi_async *async = s ? s->async : NULL;
481 unsigned long irq_flags;
482 unsigned int status;
483 unsigned int val;
484 bool fifo_empty;
485 bool fifo_overflow;
486 int i;
487
488 status = inb(dev->iobase + DAS800_STATUS);
489 if (!(status & IRQ))
490 return IRQ_NONE;
491 if (!dev->attached)
492 return IRQ_HANDLED;
493
494 spin_lock_irqsave(&dev->spinlock, irq_flags);
495 status = das800_ind_read(dev, CONTROL1) & STATUS2_HCEN;
496 /*
497 * Don't release spinlock yet since we want to make sure
498 * no one else disables hardware conversions.
499 */
500
501 /* if hardware conversions are not enabled, then quit */
502 if (status == 0) {
503 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
504 return IRQ_HANDLED;
505 }
506
507 for (i = 0; i < DAS802_16_HALF_FIFO_SZ; i++) {
508 val = das800_ai_get_sample(dev);
509 if (s->maxdata == 0x0fff) {
510 fifo_empty = !!(val & FIFO_EMPTY);
511 fifo_overflow = !!(val & FIFO_OVF);
512 } else {
513 /* cio-das802/16 has no fifo empty status bit */
514 fifo_empty = false;
515 fifo_overflow = !!(inb(dev->iobase + DAS800_GAIN) &
516 CIO_FFOV);
517 }
518 if (fifo_empty || fifo_overflow)
519 break;
520
521 if (s->maxdata == 0x0fff)
522 val >>= 4; /* 12-bit sample */
523
524 /* if there are more data points to collect */
525 if (devpriv->count > 0 || devpriv->forever) {
526 /* write data point to buffer */
527 cfc_write_to_buffer(s, val & s->maxdata);
528 devpriv->count--;
529 }
530 }
531 async->events |= COMEDI_CB_BLOCK;
532
533 if (fifo_overflow) {
534 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
535 das800_cancel(dev, s);
536 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
537 comedi_event(dev, s);
538 async->events = 0;
539 return IRQ_HANDLED;
540 }
541
542 if (devpriv->count > 0 || devpriv->forever) {
543 /* Re-enable card's interrupt.
544 * We already have spinlock, so indirect addressing is safe */
545 das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits,
546 CONTROL1);
547 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
548 } else {
549 /* otherwise, stop taking data */
550 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
551 das800_disable(dev);
552 async->events |= COMEDI_CB_EOA;
553 }
554 comedi_event(dev, s);
555 async->events = 0;
556 return IRQ_HANDLED;
557 }
558
559 static int das800_wait_for_conv(struct comedi_device *dev, int timeout)
560 {
561 int i;
562
563 for (i = 0; i < timeout; i++) {
564 if (!(inb(dev->iobase + DAS800_STATUS) & BUSY))
565 return 0;
566 }
567 return -ETIME;
568 }
569
570 static int das800_ai_insn_read(struct comedi_device *dev,
571 struct comedi_subdevice *s,
572 struct comedi_insn *insn,
573 unsigned int *data)
574 {
575 struct das800_private *devpriv = dev->private;
576 unsigned int chan = CR_CHAN(insn->chanspec);
577 unsigned int range = CR_RANGE(insn->chanspec);
578 unsigned long irq_flags;
579 unsigned int val;
580 int ret;
581 int i;
582
583 das800_disable(dev);
584
585 /* set multiplexer */
586 spin_lock_irqsave(&dev->spinlock, irq_flags);
587 das800_ind_write(dev, chan | devpriv->do_bits, CONTROL1);
588 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
589
590 /* set gain / range */
591 if (s->maxdata == 0x0fff && range)
592 range += 0x7;
593 range &= 0xf;
594 outb(range, dev->iobase + DAS800_GAIN);
595
596 udelay(5);
597
598 for (i = 0; i < insn->n; i++) {
599 /* trigger conversion */
600 outb_p(0, dev->iobase + DAS800_MSB);
601
602 ret = das800_wait_for_conv(dev, 1000);
603 if (ret)
604 return ret;
605
606 val = das800_ai_get_sample(dev);
607 if (s->maxdata == 0x0fff)
608 val >>= 4; /* 12-bit sample */
609 data[i] = val & s->maxdata;
610 }
611
612 return insn->n;
613 }
614
615 static int das800_di_insn_bits(struct comedi_device *dev,
616 struct comedi_subdevice *s,
617 struct comedi_insn *insn,
618 unsigned int *data)
619 {
620 data[1] = (inb(dev->iobase + DAS800_STATUS) >> 4) & 0x7;
621
622 return insn->n;
623 }
624
625 static int das800_do_insn_bits(struct comedi_device *dev,
626 struct comedi_subdevice *s,
627 struct comedi_insn *insn,
628 unsigned int *data)
629 {
630 struct das800_private *devpriv = dev->private;
631 unsigned long irq_flags;
632
633 if (comedi_dio_update_state(s, data)) {
634 devpriv->do_bits = s->state << 4;
635
636 spin_lock_irqsave(&dev->spinlock, irq_flags);
637 das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits,
638 CONTROL1);
639 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
640 }
641
642 data[1] = s->state;
643
644 return insn->n;
645 }
646
647 static int das800_probe(struct comedi_device *dev)
648 {
649 const struct das800_board *thisboard = comedi_board(dev);
650 int board = thisboard ? thisboard - das800_boards : -EINVAL;
651 int id_bits;
652 unsigned long irq_flags;
653
654 spin_lock_irqsave(&dev->spinlock, irq_flags);
655 id_bits = das800_ind_read(dev, ID) & 0x3;
656 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
657
658 switch (id_bits) {
659 case 0x0:
660 if (board == BOARD_DAS800 || board == BOARD_CIODAS800)
661 break;
662 dev_dbg(dev->class_dev, "Board model (probed): DAS-800\n");
663 board = BOARD_DAS800;
664 break;
665 case 0x2:
666 if (board == BOARD_DAS801 || board == BOARD_CIODAS801)
667 break;
668 dev_dbg(dev->class_dev, "Board model (probed): DAS-801\n");
669 board = BOARD_DAS801;
670 break;
671 case 0x3:
672 if (board == BOARD_DAS802 || board == BOARD_CIODAS802 ||
673 board == BOARD_CIODAS80216)
674 break;
675 dev_dbg(dev->class_dev, "Board model (probed): DAS-802\n");
676 board = BOARD_DAS802;
677 break;
678 default:
679 dev_dbg(dev->class_dev, "Board model: 0x%x (unknown)\n",
680 id_bits);
681 board = -EINVAL;
682 break;
683 }
684 return board;
685 }
686
687 static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
688 {
689 const struct das800_board *thisboard = comedi_board(dev);
690 struct das800_private *devpriv;
691 struct comedi_subdevice *s;
692 unsigned int irq = it->options[1];
693 unsigned long irq_flags;
694 int board;
695 int ret;
696
697 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
698 if (!devpriv)
699 return -ENOMEM;
700
701 ret = comedi_request_region(dev, it->options[0], DAS800_SIZE);
702 if (ret)
703 return ret;
704
705 board = das800_probe(dev);
706 if (board < 0) {
707 dev_dbg(dev->class_dev, "unable to determine board type\n");
708 return -ENODEV;
709 }
710 dev->board_ptr = das800_boards + board;
711 thisboard = comedi_board(dev);
712 dev->board_name = thisboard->name;
713
714 if (irq > 1 && irq <= 7) {
715 ret = request_irq(irq, das800_interrupt, 0, dev->board_name,
716 dev);
717 if (ret == 0)
718 dev->irq = irq;
719 }
720
721 ret = comedi_alloc_subdevices(dev, 3);
722 if (ret)
723 return ret;
724
725 /* Analog Input subdevice */
726 s = &dev->subdevices[0];
727 dev->read_subdev = s;
728 s->type = COMEDI_SUBD_AI;
729 s->subdev_flags = SDF_READABLE | SDF_GROUND;
730 s->n_chan = 8;
731 s->maxdata = (1 << thisboard->resolution) - 1;
732 s->range_table = thisboard->ai_range;
733 s->insn_read = das800_ai_insn_read;
734 if (dev->irq) {
735 s->subdev_flags |= SDF_CMD_READ;
736 s->len_chanlist = 8;
737 s->do_cmdtest = das800_ai_do_cmdtest;
738 s->do_cmd = das800_ai_do_cmd;
739 s->cancel = das800_cancel;
740 }
741
742 /* Digital Input subdevice */
743 s = &dev->subdevices[1];
744 s->type = COMEDI_SUBD_DI;
745 s->subdev_flags = SDF_READABLE;
746 s->n_chan = 3;
747 s->maxdata = 1;
748 s->range_table = &range_digital;
749 s->insn_bits = das800_di_insn_bits;
750
751 /* Digital Output subdevice */
752 s = &dev->subdevices[2];
753 s->type = COMEDI_SUBD_DO;
754 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
755 s->n_chan = 4;
756 s->maxdata = 1;
757 s->range_table = &range_digital;
758 s->insn_bits = das800_do_insn_bits;
759
760 das800_disable(dev);
761
762 /* initialize digital out channels */
763 spin_lock_irqsave(&dev->spinlock, irq_flags);
764 das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, CONTROL1);
765 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
766
767 return 0;
768 };
769
770 static struct comedi_driver driver_das800 = {
771 .driver_name = "das800",
772 .module = THIS_MODULE,
773 .attach = das800_attach,
774 .detach = comedi_legacy_detach,
775 .num_names = ARRAY_SIZE(das800_boards),
776 .board_name = &das800_boards[0].name,
777 .offset = sizeof(struct das800_board),
778 };
779 module_comedi_driver(driver_das800);
780
781 MODULE_AUTHOR("Comedi http://www.comedi.org");
782 MODULE_DESCRIPTION("Comedi low-level driver");
783 MODULE_LICENSE("GPL");
This page took 0.057199 seconds and 5 git commands to generate.