3 * Comedi driver for Data Translation DT2821 series
5 * COMEDI - Linux Control and Measurement Device Interface
6 * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
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.
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.
21 * Description: Data Translation DT2821 series (including DT-EZ)
23 * Devices: [Data Translation] DT2821 (dt2821), DT2821-F-16SE (dt2821-f),
24 * DT2821-F-8DI (dt2821-f), DT2821-G-16SE (dt2821-g),
25 * DT2821-G-8DI (dt2821-g), DT2823 (dt2823), DT2824-PGH (dt2824-pgh),
26 * DT2824-PGL (dt2824-pgl), DT2825 (dt2825), DT2827 (dt2827),
27 * DT2828 (dt2828), DT2928 (dt2829), DT21-EZ (dt21-ez), DT23-EZ (dt23-ez),
28 * DT24-EZ (dt24-ez), DT24-EZ-PGL (dt24-ez-pgl)
30 * Updated: Wed, 22 Aug 2001 17:11:34 -0700
32 * Configuration options:
33 * [0] - I/O port base address
34 * [1] - IRQ (optional, required for async command support)
35 * [2] - DMA 1 (optional, required for async command support)
36 * [3] - DMA 2 (optional, required for async command support)
37 * [4] - AI jumpered for 0=single ended, 1=differential
38 * [5] - AI jumpered for 0=straight binary, 1=2's complement
39 * [6] - AO 0 data format (deprecated, see below)
40 * [7] - AO 1 data format (deprecated, see below)
41 * [8] - AI jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5]
42 * [9] - AO channel 0 range (deprecated, see below)
43 * [10]- AO channel 1 range (deprecated, see below)
46 * - AO commands might be broken.
47 * - If you try to run a command on both the AI and AO subdevices
48 * simultaneously, bad things will happen. The driver needs to
49 * be fixed to check for this situation and return an error.
50 * - AO range is not programmable. The AO subdevice has a range_table
51 * containing all the possible analog output ranges. Use the range
52 * that matches your board configuration to convert between data
53 * values and physical units. The format of the data written to the
54 * board is handled automatically based on the unipolar/bipolar
55 * range that is selected.
58 #include <linux/module.h>
59 #include "../comedidev.h"
61 #include <linux/delay.h>
62 #include <linux/gfp.h>
63 #include <linux/interrupt.h>
68 #include "comedi_fc.h"
73 #define DT2821_ADCSR_REG 0x00
74 #define DT2821_ADCSR_ADERR (1 << 15)
75 #define DT2821_ADCSR_ADCLK (1 << 9)
76 #define DT2821_ADCSR_MUXBUSY (1 << 8)
77 #define DT2821_ADCSR_ADDONE (1 << 7)
78 #define DT2821_ADCSR_IADDONE (1 << 6)
79 #define DT2821_ADCSR_GS(x) (((x) & 0x3) << 4)
80 #define DT2821_ADCSR_CHAN(x) (((x) & 0xf) << 0)
81 #define DT2821_CHANCSR_REG 0x02
82 #define DT2821_CHANCSR_LLE (1 << 15)
83 #define DT2821_CHANCSR_PRESLA(x) (((x) & 0xf) >> 8)
84 #define DT2821_CHANCSR_NUMB(x) ((((x) - 1) & 0xf) << 0)
85 #define DT2821_ADDAT_REG 0x04
86 #define DT2821_DACSR_REG 0x06
87 #define DT2821_DACSR_DAERR (1 << 15)
88 #define DT2821_DACSR_YSEL(x) ((x) << 9)
89 #define DT2821_DACSR_SSEL (1 << 8)
90 #define DT2821_DACSR_DACRDY (1 << 7)
91 #define DT2821_DACSR_IDARDY (1 << 6)
92 #define DT2821_DACSR_DACLK (1 << 5)
93 #define DT2821_DACSR_HBOE (1 << 1)
94 #define DT2821_DACSR_LBOE (1 << 0)
95 #define DT2821_DADAT_REG 0x08
96 #define DT2821_DIODAT_REG 0x0a
97 #define DT2821_SUPCSR_REG 0x0c
98 #define DT2821_SUPCSR_DMAD (1 << 15)
99 #define DT2821_SUPCSR_ERRINTEN (1 << 14)
100 #define DT2821_SUPCSR_CLRDMADNE (1 << 13)
101 #define DT2821_SUPCSR_DDMA (1 << 12)
102 #define DT2821_SUPCSR_DS_PIO (0 << 10)
103 #define DT2821_SUPCSR_DS_AD_CLK (1 << 10)
104 #define DT2821_SUPCSR_DS_DA_CLK (2 << 10)
105 #define DT2821_SUPCSR_DS_AD_TRIG (3 << 10)
106 #define DT2821_SUPCSR_BUFFB (1 << 9)
107 #define DT2821_SUPCSR_SCDN (1 << 8)
108 #define DT2821_SUPCSR_DACON (1 << 7)
109 #define DT2821_SUPCSR_ADCINIT (1 << 6)
110 #define DT2821_SUPCSR_DACINIT (1 << 5)
111 #define DT2821_SUPCSR_PRLD (1 << 4)
112 #define DT2821_SUPCSR_STRIG (1 << 3)
113 #define DT2821_SUPCSR_XTRIG (1 << 2)
114 #define DT2821_SUPCSR_XCLK (1 << 1)
115 #define DT2821_SUPCSR_BDINIT (1 << 0)
116 #define DT2821_TMRCTR_REG 0x0e
118 static const struct comedi_lrange range_dt282x_ai_lo_bipolar = {
127 static const struct comedi_lrange range_dt282x_ai_lo_unipolar = {
136 static const struct comedi_lrange range_dt282x_ai_5_bipolar = {
145 static const struct comedi_lrange range_dt282x_ai_5_unipolar = {
154 static const struct comedi_lrange range_dt282x_ai_hi_bipolar = {
163 static const struct comedi_lrange range_dt282x_ai_hi_unipolar = {
173 * The Analog Output range is set per-channel using jumpers on the board.
174 * All of these ranges may not be available on some DT2821 series boards.
175 * The default jumper setting has both channels set for +/-10V output.
177 static const struct comedi_lrange dt282x_ao_range = {
187 struct dt282x_board {
189 unsigned int ai_maxdata;
195 unsigned int ao_maxdata;
198 static const struct dt282x_board boardtypes[] = {
201 .ai_maxdata = 0x0fff,
206 .ao_maxdata = 0x0fff,
209 .ai_maxdata = 0x0fff,
214 .ao_maxdata = 0x0fff,
217 .ai_maxdata = 0x0fff,
222 .ao_maxdata = 0x0fff,
225 .ai_maxdata = 0xffff,
229 .ao_maxdata = 0xffff,
231 .name = "dt2824-pgh",
232 .ai_maxdata = 0x0fff,
237 .name = "dt2824-pgl",
238 .ai_maxdata = 0x0fff,
245 .ai_maxdata = 0x0fff,
251 .ao_maxdata = 0x0fff,
254 .ai_maxdata = 0xffff,
258 .ao_maxdata = 0x0fff,
261 .ai_maxdata = 0x0fff,
265 .ao_maxdata = 0x0fff,
268 .ai_maxdata = 0xffff,
272 .ao_maxdata = 0xffff,
275 .ai_maxdata = 0x0fff,
280 .ao_maxdata = 0x0fff,
283 .ai_maxdata = 0xffff,
289 .ai_maxdata = 0x0fff,
294 .name = "dt24-ez-pgl",
295 .ai_maxdata = 0x0fff,
303 struct dt282x_dma_desc {
304 unsigned int chan; /* DMA channel */
305 void *virt_addr; /* virtual address of DMA buffer */
306 dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */
307 unsigned int size; /* transfer size (in bytes) */
308 char mode; /* DMA_MODE_* */
311 struct dt282x_private {
312 unsigned int ad_2scomp:1;
314 unsigned int divisor;
316 int dacsr; /* software copies of registers */
323 struct dt282x_dma_desc dma_desc[2];
324 int dma_maxsize; /* max size of DMA transfer (in bytes) */
329 static void dt282x_isadma_program(struct dt282x_dma_desc *dma)
333 flags = claim_dma_lock();
334 clear_dma_ff(dma->chan);
335 set_dma_mode(dma->chan, dma->mode);
336 set_dma_addr(dma->chan, dma->hw_addr);
337 set_dma_count(dma->chan, dma->size);
338 enable_dma(dma->chan);
339 release_dma_lock(flags);
342 static void dt282x_isadma_disable(struct dt282x_dma_desc *dma)
346 flags = claim_dma_lock();
347 disable_dma(dma->chan);
348 release_dma_lock(flags);
351 static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n)
353 struct dt282x_private *devpriv = dev->private;
354 struct dt282x_dma_desc *dma = &devpriv->dma_desc[dma_index];
360 n = devpriv->dma_maxsize;
361 if (n > devpriv->ntrig * 2)
362 n = devpriv->ntrig * 2;
363 devpriv->ntrig -= n / 2;
366 dma->mode = DMA_MODE_READ;
368 dt282x_isadma_program(dma);
373 static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n)
375 struct dt282x_private *devpriv = dev->private;
376 struct dt282x_dma_desc *dma = &devpriv->dma_desc[dma_index];
379 dma->mode = DMA_MODE_WRITE;
381 dt282x_isadma_program(dma);
386 static void dt282x_disable_dma(struct comedi_device *dev)
388 struct dt282x_private *devpriv = dev->private;
391 for (i = 0; i < 2; i++)
392 dt282x_isadma_disable(&devpriv->dma_desc[i]);
395 static unsigned int dt282x_ns_to_timer(unsigned int *ns, unsigned int flags)
397 unsigned int prescale, base, divider;
399 for (prescale = 0; prescale < 16; prescale++) {
402 base = 250 * (1 << prescale);
403 switch (flags & CMDF_ROUND_MASK) {
404 case CMDF_ROUND_NEAREST:
406 divider = (*ns + base / 2) / base;
408 case CMDF_ROUND_DOWN:
409 divider = (*ns) / base;
412 divider = (*ns + base - 1) / base;
416 *ns = divider * base;
417 return (prescale << 8) | (255 - divider);
420 base = 250 * (1 << 15);
422 *ns = divider * base;
423 return (15 << 8) | (255 - divider);
426 static void dt282x_munge(struct comedi_device *dev,
427 struct comedi_subdevice *s,
431 struct dt282x_private *devpriv = dev->private;
436 dev_err(dev->class_dev,
437 "bug! odd number of bytes from dma xfer\n");
439 for (i = 0; i < nbytes / 2; i++) {
442 if (devpriv->ad_2scomp)
443 val = comedi_offset_munge(s, val);
449 static unsigned int dt282x_ao_setup_dma(struct comedi_device *dev,
450 struct comedi_subdevice *s,
453 struct dt282x_private *devpriv = dev->private;
454 struct dt282x_dma_desc *dma = &devpriv->dma_desc[cur_dma];
455 unsigned int nsamples = comedi_bytes_to_samples(s, devpriv->dma_maxsize);
458 nbytes = comedi_buf_read_samples(s, dma->virt_addr, nsamples);
460 dt282x_prep_ao_dma(dev, cur_dma, nbytes);
462 dev_err(dev->class_dev, "AO underrun\n");
467 static void dt282x_ao_dma_interrupt(struct comedi_device *dev,
468 struct comedi_subdevice *s)
470 struct dt282x_private *devpriv = dev->private;
471 struct dt282x_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma];
473 outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE,
474 dev->iobase + DT2821_SUPCSR_REG);
476 dt282x_isadma_disable(dma);
478 if (!dt282x_ao_setup_dma(dev, s, devpriv->cur_dma))
479 s->async->events |= COMEDI_CB_OVERFLOW;
481 devpriv->cur_dma = 1 - devpriv->cur_dma;
484 static void dt282x_ai_dma_interrupt(struct comedi_device *dev,
485 struct comedi_subdevice *s)
487 struct dt282x_private *devpriv = dev->private;
488 struct dt282x_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma];
489 unsigned int nsamples = comedi_bytes_to_samples(s, dma->size);
492 outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE,
493 dev->iobase + DT2821_SUPCSR_REG);
495 dt282x_isadma_disable(dma);
497 dt282x_munge(dev, s, dma->virt_addr, dma->size);
498 ret = comedi_buf_write_samples(s, dma->virt_addr, nsamples);
499 if (ret != dma->size)
502 devpriv->nread -= nsamples;
503 if (devpriv->nread < 0) {
504 dev_info(dev->class_dev, "nread off by one\n");
507 if (!devpriv->nread) {
508 s->async->events |= COMEDI_CB_EOA;
512 /* clear the dual dma flag, making this the last dma segment */
513 /* XXX probably wrong */
514 if (!devpriv->ntrig) {
515 devpriv->supcsr &= ~DT2821_SUPCSR_DDMA;
516 outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR_REG);
519 /* restart the channel */
520 dt282x_prep_ai_dma(dev, devpriv->cur_dma, 0);
522 devpriv->cur_dma = 1 - devpriv->cur_dma;
525 static irqreturn_t dt282x_interrupt(int irq, void *d)
527 struct comedi_device *dev = d;
528 struct dt282x_private *devpriv = dev->private;
529 struct comedi_subdevice *s = dev->read_subdev;
530 struct comedi_subdevice *s_ao = dev->write_subdev;
531 unsigned int supcsr, adcsr, dacsr;
534 if (!dev->attached) {
535 dev_err(dev->class_dev, "spurious interrupt\n");
539 adcsr = inw(dev->iobase + DT2821_ADCSR_REG);
540 dacsr = inw(dev->iobase + DT2821_DACSR_REG);
541 supcsr = inw(dev->iobase + DT2821_SUPCSR_REG);
542 if (supcsr & DT2821_SUPCSR_DMAD) {
543 if (devpriv->dma_dir == DMA_MODE_READ)
544 dt282x_ai_dma_interrupt(dev, s);
546 dt282x_ao_dma_interrupt(dev, s_ao);
549 if (adcsr & DT2821_ADCSR_ADERR) {
550 if (devpriv->nread != 0) {
551 dev_err(dev->class_dev, "A/D error\n");
552 s->async->events |= COMEDI_CB_ERROR;
556 if (dacsr & DT2821_DACSR_DAERR) {
557 dev_err(dev->class_dev, "D/A error\n");
558 s_ao->async->events |= COMEDI_CB_ERROR;
562 if (adcsr & DT2821_ADCSR_ADDONE) {
565 data = inw(dev->iobase + DT2821_ADDAT_REG);
567 if (devpriv->ad_2scomp)
568 data = comedi_offset_munge(s, data);
570 comedi_buf_write_samples(s, &data, 1);
573 if (!devpriv->nread) {
574 s->async->events |= COMEDI_CB_EOA;
576 if (supcsr & DT2821_SUPCSR_SCDN)
577 outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
578 dev->iobase + DT2821_SUPCSR_REG);
583 comedi_handle_events(dev, s);
584 comedi_handle_events(dev, s_ao);
586 return IRQ_RETVAL(handled);
589 static void dt282x_load_changain(struct comedi_device *dev, int n,
590 unsigned int *chanlist)
592 struct dt282x_private *devpriv = dev->private;
595 outw(DT2821_CHANCSR_LLE | DT2821_CHANCSR_NUMB(n),
596 dev->iobase + DT2821_CHANCSR_REG);
597 for (i = 0; i < n; i++) {
598 unsigned int chan = CR_CHAN(chanlist[i]);
599 unsigned int range = CR_RANGE(chanlist[i]);
601 outw(devpriv->adcsr |
602 DT2821_ADCSR_GS(range) |
603 DT2821_ADCSR_CHAN(chan),
604 dev->iobase + DT2821_ADCSR_REG);
606 outw(DT2821_CHANCSR_NUMB(n), dev->iobase + DT2821_CHANCSR_REG);
609 static int dt282x_ai_timeout(struct comedi_device *dev,
610 struct comedi_subdevice *s,
611 struct comedi_insn *insn,
612 unsigned long context)
616 status = inw(dev->iobase + DT2821_ADCSR_REG);
618 case DT2821_ADCSR_MUXBUSY:
619 if ((status & DT2821_ADCSR_MUXBUSY) == 0)
622 case DT2821_ADCSR_ADDONE:
623 if (status & DT2821_ADCSR_ADDONE)
633 * Performs a single A/D conversion.
634 * - Put channel/gain into channel-gain list
635 * - preload multiplexer
636 * - trigger conversion and wait for it to finish
638 static int dt282x_ai_insn_read(struct comedi_device *dev,
639 struct comedi_subdevice *s,
640 struct comedi_insn *insn,
643 struct dt282x_private *devpriv = dev->private;
648 /* XXX should we really be enabling the ad clock here? */
649 devpriv->adcsr = DT2821_ADCSR_ADCLK;
650 outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR_REG);
652 dt282x_load_changain(dev, 1, &insn->chanspec);
654 outw(devpriv->supcsr | DT2821_SUPCSR_PRLD,
655 dev->iobase + DT2821_SUPCSR_REG);
656 ret = comedi_timeout(dev, s, insn,
657 dt282x_ai_timeout, DT2821_ADCSR_MUXBUSY);
661 for (i = 0; i < insn->n; i++) {
662 outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
663 dev->iobase + DT2821_SUPCSR_REG);
665 ret = comedi_timeout(dev, s, insn,
666 dt282x_ai_timeout, DT2821_ADCSR_ADDONE);
670 val = inw(dev->iobase + DT2821_ADDAT_REG);
672 if (devpriv->ad_2scomp)
673 val = comedi_offset_munge(s, val);
681 static int dt282x_ai_cmdtest(struct comedi_device *dev,
682 struct comedi_subdevice *s,
683 struct comedi_cmd *cmd)
685 const struct dt282x_board *board = dev->board_ptr;
686 struct dt282x_private *devpriv = dev->private;
690 /* Step 1 : check if triggers are trivially valid */
692 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
693 err |= cfc_check_trigger_src(&cmd->scan_begin_src,
694 TRIG_FOLLOW | TRIG_EXT);
695 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
696 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
697 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
702 /* Step 2a : make sure trigger sources are unique */
704 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
705 err |= cfc_check_trigger_is_unique(cmd->stop_src);
707 /* Step 2b : and mutually compatible */
712 /* Step 3: check if arguments are trivially valid */
714 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
716 if (cmd->scan_begin_src == TRIG_FOLLOW) {
717 /* internal trigger */
718 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
720 /* external trigger */
721 /* should be level/edge, hi/lo specification here */
722 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
725 err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 4000);
727 #define SLOWEST_TIMER (250*(1<<15)*255)
728 err |= cfc_check_trigger_arg_max(&cmd->convert_arg, SLOWEST_TIMER);
729 err |= cfc_check_trigger_arg_min(&cmd->convert_arg, board->ai_speed);
730 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
732 if (cmd->stop_src == TRIG_COUNT)
733 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
734 else /* TRIG_EXT | TRIG_NONE */
735 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
740 /* step 4: fix up any arguments */
742 arg = cmd->convert_arg;
743 devpriv->divisor = dt282x_ns_to_timer(&arg, cmd->flags);
744 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
752 static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
754 struct dt282x_private *devpriv = dev->private;
755 struct comedi_cmd *cmd = &s->async->cmd;
758 dt282x_disable_dma(dev);
760 outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR_REG);
762 devpriv->supcsr = DT2821_SUPCSR_ERRINTEN;
763 if (cmd->scan_begin_src == TRIG_FOLLOW)
764 devpriv->supcsr = DT2821_SUPCSR_DS_AD_CLK;
766 devpriv->supcsr = DT2821_SUPCSR_DS_AD_TRIG;
767 outw(devpriv->supcsr |
768 DT2821_SUPCSR_CLRDMADNE |
769 DT2821_SUPCSR_BUFFB |
770 DT2821_SUPCSR_ADCINIT,
771 dev->iobase + DT2821_SUPCSR_REG);
773 devpriv->ntrig = cmd->stop_arg * cmd->scan_end_arg;
774 devpriv->nread = devpriv->ntrig;
776 devpriv->dma_dir = DMA_MODE_READ;
777 devpriv->cur_dma = 0;
778 dt282x_prep_ai_dma(dev, 0, 0);
779 if (devpriv->ntrig) {
780 dt282x_prep_ai_dma(dev, 1, 0);
781 devpriv->supcsr |= DT2821_SUPCSR_DDMA;
782 outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR_REG);
787 dt282x_load_changain(dev, cmd->chanlist_len, cmd->chanlist);
789 devpriv->adcsr = DT2821_ADCSR_ADCLK | DT2821_ADCSR_IADDONE;
790 outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR_REG);
792 outw(devpriv->supcsr | DT2821_SUPCSR_PRLD,
793 dev->iobase + DT2821_SUPCSR_REG);
794 ret = comedi_timeout(dev, s, NULL,
795 dt282x_ai_timeout, DT2821_ADCSR_MUXBUSY);
799 if (cmd->scan_begin_src == TRIG_FOLLOW) {
800 outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
801 dev->iobase + DT2821_SUPCSR_REG);
803 devpriv->supcsr |= DT2821_SUPCSR_XTRIG;
804 outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR_REG);
810 static int dt282x_ai_cancel(struct comedi_device *dev,
811 struct comedi_subdevice *s)
813 struct dt282x_private *devpriv = dev->private;
815 dt282x_disable_dma(dev);
818 outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR_REG);
821 outw(devpriv->supcsr | DT2821_SUPCSR_ADCINIT,
822 dev->iobase + DT2821_SUPCSR_REG);
827 static int dt282x_ao_insn_write(struct comedi_device *dev,
828 struct comedi_subdevice *s,
829 struct comedi_insn *insn,
832 struct dt282x_private *devpriv = dev->private;
833 unsigned int chan = CR_CHAN(insn->chanspec);
834 unsigned int range = CR_RANGE(insn->chanspec);
837 devpriv->dacsr |= DT2821_DACSR_SSEL | DT2821_DACSR_YSEL(chan);
839 for (i = 0; i < insn->n; i++) {
840 unsigned int val = data[i];
842 s->readback[chan] = val;
844 if (comedi_range_is_bipolar(s, range))
845 val = comedi_offset_munge(s, val);
847 outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG);
849 outw(val, dev->iobase + DT2821_DADAT_REG);
851 outw(devpriv->supcsr | DT2821_SUPCSR_DACON,
852 dev->iobase + DT2821_SUPCSR_REG);
858 static int dt282x_ao_cmdtest(struct comedi_device *dev,
859 struct comedi_subdevice *s,
860 struct comedi_cmd *cmd)
862 struct dt282x_private *devpriv = dev->private;
866 /* Step 1 : check if triggers are trivially valid */
868 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT);
869 err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
870 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
871 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
872 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
877 /* Step 2a : make sure trigger sources are unique */
879 err |= cfc_check_trigger_is_unique(cmd->stop_src);
881 /* Step 2b : and mutually compatible */
886 /* Step 3: check if arguments are trivially valid */
888 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
889 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, 5000);
890 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
891 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
893 if (cmd->stop_src == TRIG_COUNT)
894 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
895 else /* TRIG_EXT | TRIG_NONE */
896 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
901 /* step 4: fix up any arguments */
903 arg = cmd->scan_begin_arg;
904 devpriv->divisor = dt282x_ns_to_timer(&arg, cmd->flags);
905 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
914 static int dt282x_ao_inttrig(struct comedi_device *dev,
915 struct comedi_subdevice *s,
916 unsigned int trig_num)
918 struct dt282x_private *devpriv = dev->private;
919 struct comedi_cmd *cmd = &s->async->cmd;
921 if (trig_num != cmd->start_src)
924 if (!dt282x_ao_setup_dma(dev, s, 0))
927 if (!dt282x_ao_setup_dma(dev, s, 1))
930 outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
931 dev->iobase + DT2821_SUPCSR_REG);
932 s->async->inttrig = NULL;
937 static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
939 struct dt282x_private *devpriv = dev->private;
940 struct comedi_cmd *cmd = &s->async->cmd;
942 dt282x_disable_dma(dev);
944 devpriv->supcsr = DT2821_SUPCSR_ERRINTEN |
945 DT2821_SUPCSR_DS_DA_CLK |
947 outw(devpriv->supcsr |
948 DT2821_SUPCSR_CLRDMADNE |
949 DT2821_SUPCSR_BUFFB |
950 DT2821_SUPCSR_DACINIT,
951 dev->iobase + DT2821_SUPCSR_REG);
953 devpriv->ntrig = cmd->stop_arg * cmd->chanlist_len;
954 devpriv->nread = devpriv->ntrig;
956 devpriv->dma_dir = DMA_MODE_WRITE;
957 devpriv->cur_dma = 0;
959 outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR_REG);
961 /* clear all bits but the DIO direction bits */
962 devpriv->dacsr &= (DT2821_DACSR_LBOE | DT2821_DACSR_HBOE);
964 devpriv->dacsr |= (DT2821_DACSR_SSEL |
966 DT2821_DACSR_IDARDY);
967 outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG);
969 s->async->inttrig = dt282x_ao_inttrig;
974 static int dt282x_ao_cancel(struct comedi_device *dev,
975 struct comedi_subdevice *s)
977 struct dt282x_private *devpriv = dev->private;
979 dt282x_disable_dma(dev);
981 /* clear all bits but the DIO direction bits */
982 devpriv->dacsr &= (DT2821_DACSR_LBOE | DT2821_DACSR_HBOE);
984 outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG);
987 outw(devpriv->supcsr | DT2821_SUPCSR_DACINIT,
988 dev->iobase + DT2821_SUPCSR_REG);
993 static int dt282x_dio_insn_bits(struct comedi_device *dev,
994 struct comedi_subdevice *s,
995 struct comedi_insn *insn,
998 if (comedi_dio_update_state(s, data))
999 outw(s->state, dev->iobase + DT2821_DIODAT_REG);
1001 data[1] = inw(dev->iobase + DT2821_DIODAT_REG);
1006 static int dt282x_dio_insn_config(struct comedi_device *dev,
1007 struct comedi_subdevice *s,
1008 struct comedi_insn *insn,
1011 struct dt282x_private *devpriv = dev->private;
1012 unsigned int chan = CR_CHAN(insn->chanspec);
1021 ret = comedi_dio_insn_config(dev, s, insn, data, mask);
1025 devpriv->dacsr &= ~(DT2821_DACSR_LBOE | DT2821_DACSR_HBOE);
1026 if (s->io_bits & 0x00ff)
1027 devpriv->dacsr |= DT2821_DACSR_LBOE;
1028 if (s->io_bits & 0xff00)
1029 devpriv->dacsr |= DT2821_DACSR_HBOE;
1031 outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG);
1036 static const struct comedi_lrange *const ai_range_table[] = {
1037 &range_dt282x_ai_lo_bipolar,
1038 &range_dt282x_ai_lo_unipolar,
1039 &range_dt282x_ai_5_bipolar,
1040 &range_dt282x_ai_5_unipolar
1043 static const struct comedi_lrange *const ai_range_pgl_table[] = {
1044 &range_dt282x_ai_hi_bipolar,
1045 &range_dt282x_ai_hi_unipolar
1048 static const struct comedi_lrange *opt_ai_range_lkup(int ispgl, int x)
1051 if (x < 0 || x >= 2)
1053 return ai_range_pgl_table[x];
1056 if (x < 0 || x >= 4)
1058 return ai_range_table[x];
1061 static int dt282x_alloc_dma(struct comedi_device *dev,
1062 struct comedi_devconfig *it)
1064 struct dt282x_private *devpriv = dev->private;
1065 unsigned int irq_num = it->options[1];
1066 unsigned int dma_chan[2];
1069 if (it->options[2] < it->options[3]) {
1070 dma_chan[0] = it->options[2];
1071 dma_chan[1] = it->options[3];
1073 dma_chan[0] = it->options[3];
1074 dma_chan[1] = it->options[2];
1077 if (!irq_num || dma_chan[0] == dma_chan[1] ||
1078 dma_chan[0] < 5 || dma_chan[0] > 7 ||
1079 dma_chan[1] < 5 || dma_chan[1] > 7)
1082 if (request_irq(irq_num, dt282x_interrupt, 0, dev->board_name, dev))
1084 if (request_dma(dma_chan[0], dev->board_name)) {
1085 free_irq(irq_num, dev);
1088 if (request_dma(dma_chan[1], dev->board_name)) {
1089 free_dma(dma_chan[0]);
1090 free_irq(irq_num, dev);
1096 devpriv->dma_maxsize = PAGE_SIZE;
1097 for (i = 0; i < 2; i++) {
1098 struct dt282x_dma_desc *dma = &devpriv->dma_desc[i];
1100 dma->chan = dma_chan[i];
1101 dma->virt_addr = dma_alloc_coherent(NULL, devpriv->dma_maxsize,
1102 &dma->hw_addr, GFP_KERNEL);
1103 if (!dma->virt_addr)
1110 static void dt282x_free_dma(struct comedi_device *dev)
1112 struct dt282x_private *devpriv = dev->private;
1113 struct dt282x_dma_desc *dma;
1119 for (i = 0; i < 2; i++) {
1120 dma = &devpriv->dma_desc[i];
1122 free_dma(dma->chan);
1124 dma_free_coherent(NULL, devpriv->dma_maxsize,
1125 dma->virt_addr, dma->hw_addr);
1129 static int dt282x_initialize(struct comedi_device *dev)
1131 /* Initialize board */
1132 outw(DT2821_SUPCSR_BDINIT, dev->iobase + DT2821_SUPCSR_REG);
1133 inw(dev->iobase + DT2821_ADCSR_REG);
1136 * At power up, some registers are in a well-known state.
1137 * Check them to see if a DT2821 series board is present.
1139 if (((inw(dev->iobase + DT2821_ADCSR_REG) & 0xfff0) != 0x7c00) ||
1140 ((inw(dev->iobase + DT2821_CHANCSR_REG) & 0xf0f0) != 0x70f0) ||
1141 ((inw(dev->iobase + DT2821_DACSR_REG) & 0x7c93) != 0x7c90) ||
1142 ((inw(dev->iobase + DT2821_SUPCSR_REG) & 0xf8ff) != 0x0000) ||
1143 ((inw(dev->iobase + DT2821_TMRCTR_REG) & 0xff00) != 0xf000)) {
1144 dev_err(dev->class_dev, "board not found\n");
1156 4 0=single ended, 1=differential
1157 5 ai 0=straight binary, 1=2's comp
1158 6 ao0 0=straight binary, 1=2's comp
1159 7 ao1 0=straight binary, 1=2's comp
1160 8 ai 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V
1161 9 ao0 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V, 4=±2.5 V
1162 10 ao1 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V, 4=±2.5 V
1164 static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1166 const struct dt282x_board *board = dev->board_ptr;
1167 struct dt282x_private *devpriv;
1168 struct comedi_subdevice *s;
1171 ret = comedi_request_region(dev, it->options[0], 0x10);
1175 ret = dt282x_initialize(dev);
1179 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1183 /* an IRQ and 2 DMA channels are required for async command support */
1184 ret = dt282x_alloc_dma(dev, it);
1188 ret = comedi_alloc_subdevices(dev, 3);
1192 /* Analog Input subdevice */
1193 s = &dev->subdevices[0];
1194 s->type = COMEDI_SUBD_AI;
1195 s->subdev_flags = SDF_READABLE;
1196 if ((it->options[4] && board->adchan_di) || board->adchan_se == 0) {
1197 s->subdev_flags |= SDF_DIFF;
1198 s->n_chan = board->adchan_di;
1200 s->subdev_flags |= SDF_COMMON;
1201 s->n_chan = board->adchan_se;
1203 s->maxdata = board->ai_maxdata;
1205 s->range_table = opt_ai_range_lkup(board->ispgl, it->options[8]);
1206 devpriv->ad_2scomp = it->options[5] ? 1 : 0;
1208 s->insn_read = dt282x_ai_insn_read;
1210 dev->read_subdev = s;
1211 s->subdev_flags |= SDF_CMD_READ;
1212 s->len_chanlist = s->n_chan;
1213 s->do_cmdtest = dt282x_ai_cmdtest;
1214 s->do_cmd = dt282x_ai_cmd;
1215 s->cancel = dt282x_ai_cancel;
1218 /* Analog Output subdevice */
1219 s = &dev->subdevices[1];
1220 if (board->dachan) {
1221 s->type = COMEDI_SUBD_AO;
1222 s->subdev_flags = SDF_WRITABLE;
1223 s->n_chan = board->dachan;
1224 s->maxdata = board->ao_maxdata;
1225 /* ranges are per-channel, set by jumpers on the board */
1226 s->range_table = &dt282x_ao_range;
1227 s->insn_write = dt282x_ao_insn_write;
1229 dev->write_subdev = s;
1230 s->subdev_flags |= SDF_CMD_WRITE;
1231 s->len_chanlist = s->n_chan;
1232 s->do_cmdtest = dt282x_ao_cmdtest;
1233 s->do_cmd = dt282x_ao_cmd;
1234 s->cancel = dt282x_ao_cancel;
1237 ret = comedi_alloc_subdev_readback(s);
1241 s->type = COMEDI_SUBD_UNUSED;
1244 /* Digital I/O subdevice */
1245 s = &dev->subdevices[2];
1246 s->type = COMEDI_SUBD_DIO;
1247 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1250 s->range_table = &range_digital;
1251 s->insn_bits = dt282x_dio_insn_bits;
1252 s->insn_config = dt282x_dio_insn_config;
1257 static void dt282x_detach(struct comedi_device *dev)
1259 dt282x_free_dma(dev);
1260 comedi_legacy_detach(dev);
1263 static struct comedi_driver dt282x_driver = {
1264 .driver_name = "dt282x",
1265 .module = THIS_MODULE,
1266 .attach = dt282x_attach,
1267 .detach = dt282x_detach,
1268 .board_name = &boardtypes[0].name,
1269 .num_names = ARRAY_SIZE(boardtypes),
1270 .offset = sizeof(struct dt282x_board),
1272 module_comedi_driver(dt282x_driver);
1274 MODULE_AUTHOR("Comedi http://www.comedi.org");
1275 MODULE_DESCRIPTION("Comedi driver for Data Translation DT2821 series");
1276 MODULE_LICENSE("GPL");