GNU Linux-libre 4.9.296-gnu1
[releases.git] / drivers / staging / comedi / drivers / dt282x.c
1 /*
2  * dt282x.c
3  * Comedi driver for Data Translation DT2821 series
4  *
5  * COMEDI - Linux Control and Measurement Device Interface
6  * Copyright (C) 1997-8 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
19 /*
20  * Driver: dt282x
21  * Description: Data Translation DT2821 series (including DT-EZ)
22  * Author: ds
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)
29  * Status: complete
30  * Updated: Wed, 22 Aug 2001 17:11:34 -0700
31  *
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)
44  *
45  * Notes:
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.
56  */
57
58 #include <linux/module.h>
59 #include <linux/delay.h>
60 #include <linux/gfp.h>
61 #include <linux/interrupt.h>
62 #include <linux/io.h>
63
64 #include "../comedidev.h"
65
66 #include "comedi_isadma.h"
67
68 /*
69  * Register map
70  */
71 #define DT2821_ADCSR_REG                0x00
72 #define DT2821_ADCSR_ADERR              BIT(15)
73 #define DT2821_ADCSR_ADCLK              BIT(9)
74 #define DT2821_ADCSR_MUXBUSY            BIT(8)
75 #define DT2821_ADCSR_ADDONE             BIT(7)
76 #define DT2821_ADCSR_IADDONE            BIT(6)
77 #define DT2821_ADCSR_GS(x)              (((x) & 0x3) << 4)
78 #define DT2821_ADCSR_CHAN(x)            (((x) & 0xf) << 0)
79 #define DT2821_CHANCSR_REG              0x02
80 #define DT2821_CHANCSR_LLE              BIT(15)
81 #define DT2821_CHANCSR_TO_PRESLA(x)     (((x) >> 8) & 0xf)
82 #define DT2821_CHANCSR_NUMB(x)          ((((x) - 1) & 0xf) << 0)
83 #define DT2821_ADDAT_REG                0x04
84 #define DT2821_DACSR_REG                0x06
85 #define DT2821_DACSR_DAERR              BIT(15)
86 #define DT2821_DACSR_YSEL(x)            ((x) << 9)
87 #define DT2821_DACSR_SSEL               BIT(8)
88 #define DT2821_DACSR_DACRDY             BIT(7)
89 #define DT2821_DACSR_IDARDY             BIT(6)
90 #define DT2821_DACSR_DACLK              BIT(5)
91 #define DT2821_DACSR_HBOE               BIT(1)
92 #define DT2821_DACSR_LBOE               BIT(0)
93 #define DT2821_DADAT_REG                0x08
94 #define DT2821_DIODAT_REG               0x0a
95 #define DT2821_SUPCSR_REG               0x0c
96 #define DT2821_SUPCSR_DMAD              BIT(15)
97 #define DT2821_SUPCSR_ERRINTEN          BIT(14)
98 #define DT2821_SUPCSR_CLRDMADNE         BIT(13)
99 #define DT2821_SUPCSR_DDMA              BIT(12)
100 #define DT2821_SUPCSR_DS(x)             (((x) & 0x3) << 10)
101 #define DT2821_SUPCSR_DS_PIO            DT2821_SUPCSR_DS(0)
102 #define DT2821_SUPCSR_DS_AD_CLK         DT2821_SUPCSR_DS(1)
103 #define DT2821_SUPCSR_DS_DA_CLK         DT2821_SUPCSR_DS(2)
104 #define DT2821_SUPCSR_DS_AD_TRIG        DT2821_SUPCSR_DS(3)
105 #define DT2821_SUPCSR_BUFFB             BIT(9)
106 #define DT2821_SUPCSR_SCDN              BIT(8)
107 #define DT2821_SUPCSR_DACON             BIT(7)
108 #define DT2821_SUPCSR_ADCINIT           BIT(6)
109 #define DT2821_SUPCSR_DACINIT           BIT(5)
110 #define DT2821_SUPCSR_PRLD              BIT(4)
111 #define DT2821_SUPCSR_STRIG             BIT(3)
112 #define DT2821_SUPCSR_XTRIG             BIT(2)
113 #define DT2821_SUPCSR_XCLK              BIT(1)
114 #define DT2821_SUPCSR_BDINIT            BIT(0)
115 #define DT2821_TMRCTR_REG               0x0e
116 #define DT2821_TMRCTR_PRESCALE(x)       (((x) & 0xf) << 8)
117 #define DT2821_TMRCTR_DIVIDER(x)        ((255 - ((x) & 0xff)) << 0)
118
119 /* Pacer Clock */
120 #define DT2821_OSC_BASE         250     /* 4 MHz (in nanoseconds) */
121 #define DT2821_PRESCALE(x)      BIT(x)
122 #define DT2821_PRESCALE_MAX     15
123 #define DT2821_DIVIDER_MAX      255
124 #define DT2821_OSC_MAX          (DT2821_OSC_BASE *                      \
125                                  DT2821_PRESCALE(DT2821_PRESCALE_MAX) * \
126                                  DT2821_DIVIDER_MAX)
127
128 static const struct comedi_lrange range_dt282x_ai_lo_bipolar = {
129         4, {
130                 BIP_RANGE(10),
131                 BIP_RANGE(5),
132                 BIP_RANGE(2.5),
133                 BIP_RANGE(1.25)
134         }
135 };
136
137 static const struct comedi_lrange range_dt282x_ai_lo_unipolar = {
138         4, {
139                 UNI_RANGE(10),
140                 UNI_RANGE(5),
141                 UNI_RANGE(2.5),
142                 UNI_RANGE(1.25)
143         }
144 };
145
146 static const struct comedi_lrange range_dt282x_ai_5_bipolar = {
147         4, {
148                 BIP_RANGE(5),
149                 BIP_RANGE(2.5),
150                 BIP_RANGE(1.25),
151                 BIP_RANGE(0.625)
152         }
153 };
154
155 static const struct comedi_lrange range_dt282x_ai_5_unipolar = {
156         4, {
157                 UNI_RANGE(5),
158                 UNI_RANGE(2.5),
159                 UNI_RANGE(1.25),
160                 UNI_RANGE(0.625)
161         }
162 };
163
164 static const struct comedi_lrange range_dt282x_ai_hi_bipolar = {
165         4, {
166                 BIP_RANGE(10),
167                 BIP_RANGE(1),
168                 BIP_RANGE(0.1),
169                 BIP_RANGE(0.02)
170         }
171 };
172
173 static const struct comedi_lrange range_dt282x_ai_hi_unipolar = {
174         4, {
175                 UNI_RANGE(10),
176                 UNI_RANGE(1),
177                 UNI_RANGE(0.1),
178                 UNI_RANGE(0.02)
179         }
180 };
181
182 /*
183  * The Analog Output range is set per-channel using jumpers on the board.
184  * All of these ranges may not be available on some DT2821 series boards.
185  * The default jumper setting has both channels set for +/-10V output.
186  */
187 static const struct comedi_lrange dt282x_ao_range = {
188         5, {
189                 BIP_RANGE(10),
190                 BIP_RANGE(5),
191                 BIP_RANGE(2.5),
192                 UNI_RANGE(10),
193                 UNI_RANGE(5),
194         }
195 };
196
197 struct dt282x_board {
198         const char *name;
199         unsigned int ai_maxdata;
200         int adchan_se;
201         int adchan_di;
202         int ai_speed;
203         int ispgl;
204         int dachan;
205         unsigned int ao_maxdata;
206 };
207
208 static const struct dt282x_board boardtypes[] = {
209         {
210                 .name           = "dt2821",
211                 .ai_maxdata     = 0x0fff,
212                 .adchan_se      = 16,
213                 .adchan_di      = 8,
214                 .ai_speed       = 20000,
215                 .dachan         = 2,
216                 .ao_maxdata     = 0x0fff,
217         }, {
218                 .name           = "dt2821-f",
219                 .ai_maxdata     = 0x0fff,
220                 .adchan_se      = 16,
221                 .adchan_di      = 8,
222                 .ai_speed       = 6500,
223                 .dachan         = 2,
224                 .ao_maxdata     = 0x0fff,
225         }, {
226                 .name           = "dt2821-g",
227                 .ai_maxdata     = 0x0fff,
228                 .adchan_se      = 16,
229                 .adchan_di      = 8,
230                 .ai_speed       = 4000,
231                 .dachan         = 2,
232                 .ao_maxdata     = 0x0fff,
233         }, {
234                 .name           = "dt2823",
235                 .ai_maxdata     = 0xffff,
236                 .adchan_di      = 4,
237                 .ai_speed       = 10000,
238                 .dachan         = 2,
239                 .ao_maxdata     = 0xffff,
240         }, {
241                 .name           = "dt2824-pgh",
242                 .ai_maxdata     = 0x0fff,
243                 .adchan_se      = 16,
244                 .adchan_di      = 8,
245                 .ai_speed       = 20000,
246         }, {
247                 .name           = "dt2824-pgl",
248                 .ai_maxdata     = 0x0fff,
249                 .adchan_se      = 16,
250                 .adchan_di      = 8,
251                 .ai_speed       = 20000,
252                 .ispgl          = 1,
253         }, {
254                 .name           = "dt2825",
255                 .ai_maxdata     = 0x0fff,
256                 .adchan_se      = 16,
257                 .adchan_di      = 8,
258                 .ai_speed       = 20000,
259                 .ispgl          = 1,
260                 .dachan         = 2,
261                 .ao_maxdata     = 0x0fff,
262         }, {
263                 .name           = "dt2827",
264                 .ai_maxdata     = 0xffff,
265                 .adchan_di      = 4,
266                 .ai_speed       = 10000,
267                 .dachan         = 2,
268                 .ao_maxdata     = 0x0fff,
269         }, {
270                 .name           = "dt2828",
271                 .ai_maxdata     = 0x0fff,
272                 .adchan_se      = 4,
273                 .ai_speed       = 10000,
274                 .dachan         = 2,
275                 .ao_maxdata     = 0x0fff,
276         }, {
277                 .name           = "dt2829",
278                 .ai_maxdata     = 0xffff,
279                 .adchan_se      = 8,
280                 .ai_speed       = 33250,
281                 .dachan         = 2,
282                 .ao_maxdata     = 0xffff,
283         }, {
284                 .name           = "dt21-ez",
285                 .ai_maxdata     = 0x0fff,
286                 .adchan_se      = 16,
287                 .adchan_di      = 8,
288                 .ai_speed       = 10000,
289                 .dachan         = 2,
290                 .ao_maxdata     = 0x0fff,
291         }, {
292                 .name           = "dt23-ez",
293                 .ai_maxdata     = 0xffff,
294                 .adchan_se      = 16,
295                 .adchan_di      = 8,
296                 .ai_speed       = 10000,
297         }, {
298                 .name           = "dt24-ez",
299                 .ai_maxdata     = 0x0fff,
300                 .adchan_se      = 16,
301                 .adchan_di      = 8,
302                 .ai_speed       = 10000,
303         }, {
304                 .name           = "dt24-ez-pgl",
305                 .ai_maxdata     = 0x0fff,
306                 .adchan_se      = 16,
307                 .adchan_di      = 8,
308                 .ai_speed       = 10000,
309                 .ispgl          = 1,
310         },
311 };
312
313 struct dt282x_private {
314         struct comedi_isadma *dma;
315         unsigned int ad_2scomp:1;
316         unsigned int divisor;
317         int dacsr;      /* software copies of registers */
318         int adcsr;
319         int supcsr;
320         int ntrig;
321         int nread;
322         int dma_dir;
323 };
324
325 static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n)
326 {
327         struct dt282x_private *devpriv = dev->private;
328         struct comedi_isadma *dma = devpriv->dma;
329         struct comedi_isadma_desc *desc = &dma->desc[dma_index];
330
331         if (!devpriv->ntrig)
332                 return 0;
333
334         if (n == 0)
335                 n = desc->maxsize;
336         if (n > devpriv->ntrig * 2)
337                 n = devpriv->ntrig * 2;
338         devpriv->ntrig -= n / 2;
339
340         desc->size = n;
341         comedi_isadma_set_mode(desc, devpriv->dma_dir);
342
343         comedi_isadma_program(desc);
344
345         return n;
346 }
347
348 static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n)
349 {
350         struct dt282x_private *devpriv = dev->private;
351         struct comedi_isadma *dma = devpriv->dma;
352         struct comedi_isadma_desc *desc = &dma->desc[dma_index];
353
354         desc->size = n;
355         comedi_isadma_set_mode(desc, devpriv->dma_dir);
356
357         comedi_isadma_program(desc);
358
359         return n;
360 }
361
362 static void dt282x_disable_dma(struct comedi_device *dev)
363 {
364         struct dt282x_private *devpriv = dev->private;
365         struct comedi_isadma *dma = devpriv->dma;
366         struct comedi_isadma_desc *desc;
367         int i;
368
369         for (i = 0; i < 2; i++) {
370                 desc = &dma->desc[i];
371                 comedi_isadma_disable(desc->chan);
372         }
373 }
374
375 static unsigned int dt282x_ns_to_timer(unsigned int *ns, unsigned int flags)
376 {
377         unsigned int prescale, base, divider;
378
379         for (prescale = 0; prescale <= DT2821_PRESCALE_MAX; prescale++) {
380                 if (prescale == 1)      /* 0 and 1 are both divide by 1 */
381                         continue;
382                 base = DT2821_OSC_BASE * DT2821_PRESCALE(prescale);
383                 switch (flags & CMDF_ROUND_MASK) {
384                 case CMDF_ROUND_NEAREST:
385                 default:
386                         divider = DIV_ROUND_CLOSEST(*ns, base);
387                         break;
388                 case CMDF_ROUND_DOWN:
389                         divider = (*ns) / base;
390                         break;
391                 case CMDF_ROUND_UP:
392                         divider = DIV_ROUND_UP(*ns, base);
393                         break;
394                 }
395                 if (divider <= DT2821_DIVIDER_MAX)
396                         break;
397         }
398         if (divider > DT2821_DIVIDER_MAX) {
399                 prescale = DT2821_PRESCALE_MAX;
400                 divider = DT2821_DIVIDER_MAX;
401                 base = DT2821_OSC_BASE * DT2821_PRESCALE(prescale);
402         }
403         *ns = divider * base;
404         return DT2821_TMRCTR_PRESCALE(prescale) |
405                DT2821_TMRCTR_DIVIDER(divider);
406 }
407
408 static void dt282x_munge(struct comedi_device *dev,
409                          struct comedi_subdevice *s,
410                          unsigned short *buf,
411                          unsigned int nbytes)
412 {
413         struct dt282x_private *devpriv = dev->private;
414         unsigned int val;
415         int i;
416
417         if (nbytes % 2)
418                 dev_err(dev->class_dev,
419                         "bug! odd number of bytes from dma xfer\n");
420
421         for (i = 0; i < nbytes / 2; i++) {
422                 val = buf[i];
423                 val &= s->maxdata;
424                 if (devpriv->ad_2scomp)
425                         val = comedi_offset_munge(s, val);
426
427                 buf[i] = val;
428         }
429 }
430
431 static unsigned int dt282x_ao_setup_dma(struct comedi_device *dev,
432                                         struct comedi_subdevice *s,
433                                         int cur_dma)
434 {
435         struct dt282x_private *devpriv = dev->private;
436         struct comedi_isadma *dma = devpriv->dma;
437         struct comedi_isadma_desc *desc = &dma->desc[cur_dma];
438         unsigned int nsamples = comedi_bytes_to_samples(s, desc->maxsize);
439         unsigned int nbytes;
440
441         nbytes = comedi_buf_read_samples(s, desc->virt_addr, nsamples);
442         if (nbytes)
443                 dt282x_prep_ao_dma(dev, cur_dma, nbytes);
444         else
445                 dev_err(dev->class_dev, "AO underrun\n");
446
447         return nbytes;
448 }
449
450 static void dt282x_ao_dma_interrupt(struct comedi_device *dev,
451                                     struct comedi_subdevice *s)
452 {
453         struct dt282x_private *devpriv = dev->private;
454         struct comedi_isadma *dma = devpriv->dma;
455         struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
456
457         outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE,
458              dev->iobase + DT2821_SUPCSR_REG);
459
460         comedi_isadma_disable(desc->chan);
461
462         if (!dt282x_ao_setup_dma(dev, s, dma->cur_dma))
463                 s->async->events |= COMEDI_CB_OVERFLOW;
464
465         dma->cur_dma = 1 - dma->cur_dma;
466 }
467
468 static void dt282x_ai_dma_interrupt(struct comedi_device *dev,
469                                     struct comedi_subdevice *s)
470 {
471         struct dt282x_private *devpriv = dev->private;
472         struct comedi_isadma *dma = devpriv->dma;
473         struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
474         unsigned int nsamples = comedi_bytes_to_samples(s, desc->size);
475         int ret;
476
477         outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE,
478              dev->iobase + DT2821_SUPCSR_REG);
479
480         comedi_isadma_disable(desc->chan);
481
482         dt282x_munge(dev, s, desc->virt_addr, desc->size);
483         ret = comedi_buf_write_samples(s, desc->virt_addr, nsamples);
484         if (ret != desc->size)
485                 return;
486
487         devpriv->nread -= nsamples;
488         if (devpriv->nread < 0) {
489                 dev_info(dev->class_dev, "nread off by one\n");
490                 devpriv->nread = 0;
491         }
492         if (!devpriv->nread) {
493                 s->async->events |= COMEDI_CB_EOA;
494                 return;
495         }
496 #if 0
497         /* clear the dual dma flag, making this the last dma segment */
498         /* XXX probably wrong */
499         if (!devpriv->ntrig) {
500                 devpriv->supcsr &= ~DT2821_SUPCSR_DDMA;
501                 outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR_REG);
502         }
503 #endif
504         /* restart the channel */
505         dt282x_prep_ai_dma(dev, dma->cur_dma, 0);
506
507         dma->cur_dma = 1 - dma->cur_dma;
508 }
509
510 static irqreturn_t dt282x_interrupt(int irq, void *d)
511 {
512         struct comedi_device *dev = d;
513         struct dt282x_private *devpriv = dev->private;
514         struct comedi_subdevice *s = dev->read_subdev;
515         struct comedi_subdevice *s_ao = dev->write_subdev;
516         unsigned int supcsr, adcsr, dacsr;
517         int handled = 0;
518
519         if (!dev->attached) {
520                 dev_err(dev->class_dev, "spurious interrupt\n");
521                 return IRQ_HANDLED;
522         }
523
524         adcsr = inw(dev->iobase + DT2821_ADCSR_REG);
525         dacsr = inw(dev->iobase + DT2821_DACSR_REG);
526         supcsr = inw(dev->iobase + DT2821_SUPCSR_REG);
527         if (supcsr & DT2821_SUPCSR_DMAD) {
528                 if (devpriv->dma_dir == COMEDI_ISADMA_READ)
529                         dt282x_ai_dma_interrupt(dev, s);
530                 else
531                         dt282x_ao_dma_interrupt(dev, s_ao);
532                 handled = 1;
533         }
534         if (adcsr & DT2821_ADCSR_ADERR) {
535                 if (devpriv->nread != 0) {
536                         dev_err(dev->class_dev, "A/D error\n");
537                         s->async->events |= COMEDI_CB_ERROR;
538                 }
539                 handled = 1;
540         }
541         if (dacsr & DT2821_DACSR_DAERR) {
542                 dev_err(dev->class_dev, "D/A error\n");
543                 s_ao->async->events |= COMEDI_CB_ERROR;
544                 handled = 1;
545         }
546 #if 0
547         if (adcsr & DT2821_ADCSR_ADDONE) {
548                 unsigned short data;
549
550                 data = inw(dev->iobase + DT2821_ADDAT_REG);
551                 data &= s->maxdata;
552                 if (devpriv->ad_2scomp)
553                         data = comedi_offset_munge(s, data);
554
555                 comedi_buf_write_samples(s, &data, 1);
556
557                 devpriv->nread--;
558                 if (!devpriv->nread) {
559                         s->async->events |= COMEDI_CB_EOA;
560                 } else {
561                         if (supcsr & DT2821_SUPCSR_SCDN)
562                                 outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
563                                      dev->iobase + DT2821_SUPCSR_REG);
564                 }
565                 handled = 1;
566         }
567 #endif
568         comedi_handle_events(dev, s);
569         if (s_ao)
570                 comedi_handle_events(dev, s_ao);
571
572         return IRQ_RETVAL(handled);
573 }
574
575 static void dt282x_load_changain(struct comedi_device *dev, int n,
576                                  unsigned int *chanlist)
577 {
578         struct dt282x_private *devpriv = dev->private;
579         int i;
580
581         outw(DT2821_CHANCSR_LLE | DT2821_CHANCSR_NUMB(n),
582              dev->iobase + DT2821_CHANCSR_REG);
583         for (i = 0; i < n; i++) {
584                 unsigned int chan = CR_CHAN(chanlist[i]);
585                 unsigned int range = CR_RANGE(chanlist[i]);
586
587                 outw(devpriv->adcsr |
588                      DT2821_ADCSR_GS(range) |
589                      DT2821_ADCSR_CHAN(chan),
590                      dev->iobase + DT2821_ADCSR_REG);
591         }
592         outw(DT2821_CHANCSR_NUMB(n), dev->iobase + DT2821_CHANCSR_REG);
593 }
594
595 static int dt282x_ai_timeout(struct comedi_device *dev,
596                              struct comedi_subdevice *s,
597                              struct comedi_insn *insn,
598                              unsigned long context)
599 {
600         unsigned int status;
601
602         status = inw(dev->iobase + DT2821_ADCSR_REG);
603         switch (context) {
604         case DT2821_ADCSR_MUXBUSY:
605                 if ((status & DT2821_ADCSR_MUXBUSY) == 0)
606                         return 0;
607                 break;
608         case DT2821_ADCSR_ADDONE:
609                 if (status & DT2821_ADCSR_ADDONE)
610                         return 0;
611                 break;
612         default:
613                 return -EINVAL;
614         }
615         return -EBUSY;
616 }
617
618 /*
619  *    Performs a single A/D conversion.
620  *      - Put channel/gain into channel-gain list
621  *      - preload multiplexer
622  *      - trigger conversion and wait for it to finish
623  */
624 static int dt282x_ai_insn_read(struct comedi_device *dev,
625                                struct comedi_subdevice *s,
626                                struct comedi_insn *insn,
627                                unsigned int *data)
628 {
629         struct dt282x_private *devpriv = dev->private;
630         unsigned int val;
631         int ret;
632         int i;
633
634         /* XXX should we really be enabling the ad clock here? */
635         devpriv->adcsr = DT2821_ADCSR_ADCLK;
636         outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR_REG);
637
638         dt282x_load_changain(dev, 1, &insn->chanspec);
639
640         outw(devpriv->supcsr | DT2821_SUPCSR_PRLD,
641              dev->iobase + DT2821_SUPCSR_REG);
642         ret = comedi_timeout(dev, s, insn,
643                              dt282x_ai_timeout, DT2821_ADCSR_MUXBUSY);
644         if (ret)
645                 return ret;
646
647         for (i = 0; i < insn->n; i++) {
648                 outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
649                      dev->iobase + DT2821_SUPCSR_REG);
650
651                 ret = comedi_timeout(dev, s, insn,
652                                      dt282x_ai_timeout, DT2821_ADCSR_ADDONE);
653                 if (ret)
654                         return ret;
655
656                 val = inw(dev->iobase + DT2821_ADDAT_REG);
657                 val &= s->maxdata;
658                 if (devpriv->ad_2scomp)
659                         val = comedi_offset_munge(s, val);
660
661                 data[i] = val;
662         }
663
664         return i;
665 }
666
667 static int dt282x_ai_cmdtest(struct comedi_device *dev,
668                              struct comedi_subdevice *s,
669                              struct comedi_cmd *cmd)
670 {
671         const struct dt282x_board *board = dev->board_ptr;
672         struct dt282x_private *devpriv = dev->private;
673         int err = 0;
674         unsigned int arg;
675
676         /* Step 1 : check if triggers are trivially valid */
677
678         err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
679         err |= comedi_check_trigger_src(&cmd->scan_begin_src,
680                                         TRIG_FOLLOW | TRIG_EXT);
681         err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
682         err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
683         err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
684
685         if (err)
686                 return 1;
687
688         /* Step 2a : make sure trigger sources are unique */
689
690         err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
691         err |= comedi_check_trigger_is_unique(cmd->stop_src);
692
693         /* Step 2b : and mutually compatible */
694
695         if (err)
696                 return 2;
697
698         /* Step 3: check if arguments are trivially valid */
699
700         err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
701         err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
702         err |= comedi_check_trigger_arg_max(&cmd->convert_arg, DT2821_OSC_MAX);
703         err |= comedi_check_trigger_arg_min(&cmd->convert_arg, board->ai_speed);
704         err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
705                                            cmd->chanlist_len);
706
707         if (cmd->stop_src == TRIG_COUNT)
708                 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
709         else    /* TRIG_EXT | TRIG_NONE */
710                 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
711
712         if (err)
713                 return 3;
714
715         /* step 4: fix up any arguments */
716
717         arg = cmd->convert_arg;
718         devpriv->divisor = dt282x_ns_to_timer(&arg, cmd->flags);
719         err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
720
721         if (err)
722                 return 4;
723
724         return 0;
725 }
726
727 static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
728 {
729         struct dt282x_private *devpriv = dev->private;
730         struct comedi_isadma *dma = devpriv->dma;
731         struct comedi_cmd *cmd = &s->async->cmd;
732         int ret;
733
734         dt282x_disable_dma(dev);
735
736         outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR_REG);
737
738         devpriv->supcsr = DT2821_SUPCSR_ERRINTEN;
739         if (cmd->scan_begin_src == TRIG_FOLLOW)
740                 devpriv->supcsr = DT2821_SUPCSR_DS_AD_CLK;
741         else
742                 devpriv->supcsr = DT2821_SUPCSR_DS_AD_TRIG;
743         outw(devpriv->supcsr |
744              DT2821_SUPCSR_CLRDMADNE |
745              DT2821_SUPCSR_BUFFB |
746              DT2821_SUPCSR_ADCINIT,
747              dev->iobase + DT2821_SUPCSR_REG);
748
749         devpriv->ntrig = cmd->stop_arg * cmd->scan_end_arg;
750         devpriv->nread = devpriv->ntrig;
751
752         devpriv->dma_dir = COMEDI_ISADMA_READ;
753         dma->cur_dma = 0;
754         dt282x_prep_ai_dma(dev, 0, 0);
755         if (devpriv->ntrig) {
756                 dt282x_prep_ai_dma(dev, 1, 0);
757                 devpriv->supcsr |= DT2821_SUPCSR_DDMA;
758                 outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR_REG);
759         }
760
761         devpriv->adcsr = 0;
762
763         dt282x_load_changain(dev, cmd->chanlist_len, cmd->chanlist);
764
765         devpriv->adcsr = DT2821_ADCSR_ADCLK | DT2821_ADCSR_IADDONE;
766         outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR_REG);
767
768         outw(devpriv->supcsr | DT2821_SUPCSR_PRLD,
769              dev->iobase + DT2821_SUPCSR_REG);
770         ret = comedi_timeout(dev, s, NULL,
771                              dt282x_ai_timeout, DT2821_ADCSR_MUXBUSY);
772         if (ret)
773                 return ret;
774
775         if (cmd->scan_begin_src == TRIG_FOLLOW) {
776                 outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
777                      dev->iobase + DT2821_SUPCSR_REG);
778         } else {
779                 devpriv->supcsr |= DT2821_SUPCSR_XTRIG;
780                 outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR_REG);
781         }
782
783         return 0;
784 }
785
786 static int dt282x_ai_cancel(struct comedi_device *dev,
787                             struct comedi_subdevice *s)
788 {
789         struct dt282x_private *devpriv = dev->private;
790
791         dt282x_disable_dma(dev);
792
793         devpriv->adcsr = 0;
794         outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR_REG);
795
796         devpriv->supcsr = 0;
797         outw(devpriv->supcsr | DT2821_SUPCSR_ADCINIT,
798              dev->iobase + DT2821_SUPCSR_REG);
799
800         return 0;
801 }
802
803 static int dt282x_ao_insn_write(struct comedi_device *dev,
804                                 struct comedi_subdevice *s,
805                                 struct comedi_insn *insn,
806                                 unsigned int *data)
807 {
808         struct dt282x_private *devpriv = dev->private;
809         unsigned int chan = CR_CHAN(insn->chanspec);
810         unsigned int range = CR_RANGE(insn->chanspec);
811         int i;
812
813         devpriv->dacsr |= DT2821_DACSR_SSEL | DT2821_DACSR_YSEL(chan);
814
815         for (i = 0; i < insn->n; i++) {
816                 unsigned int val = data[i];
817
818                 s->readback[chan] = val;
819
820                 if (comedi_range_is_bipolar(s, range))
821                         val = comedi_offset_munge(s, val);
822
823                 outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG);
824
825                 outw(val, dev->iobase + DT2821_DADAT_REG);
826
827                 outw(devpriv->supcsr | DT2821_SUPCSR_DACON,
828                      dev->iobase + DT2821_SUPCSR_REG);
829         }
830
831         return insn->n;
832 }
833
834 static int dt282x_ao_cmdtest(struct comedi_device *dev,
835                              struct comedi_subdevice *s,
836                              struct comedi_cmd *cmd)
837 {
838         struct dt282x_private *devpriv = dev->private;
839         int err = 0;
840         unsigned int arg;
841
842         /* Step 1 : check if triggers are trivially valid */
843
844         err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT);
845         err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
846         err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW);
847         err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
848         err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
849
850         if (err)
851                 return 1;
852
853         /* Step 2a : make sure trigger sources are unique */
854
855         err |= comedi_check_trigger_is_unique(cmd->stop_src);
856
857         /* Step 2b : and mutually compatible */
858
859         if (err)
860                 return 2;
861
862         /* Step 3: check if arguments are trivially valid */
863
864         err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
865         err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, 5000);
866         err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
867         err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
868                                            cmd->chanlist_len);
869
870         if (cmd->stop_src == TRIG_COUNT)
871                 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
872         else    /* TRIG_EXT | TRIG_NONE */
873                 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
874
875         if (err)
876                 return 3;
877
878         /* step 4: fix up any arguments */
879
880         arg = cmd->scan_begin_arg;
881         devpriv->divisor = dt282x_ns_to_timer(&arg, cmd->flags);
882         err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
883
884         if (err)
885                 return 4;
886
887         return 0;
888 }
889
890 static int dt282x_ao_inttrig(struct comedi_device *dev,
891                              struct comedi_subdevice *s,
892                              unsigned int trig_num)
893 {
894         struct dt282x_private *devpriv = dev->private;
895         struct comedi_cmd *cmd = &s->async->cmd;
896
897         if (trig_num != cmd->start_src)
898                 return -EINVAL;
899
900         if (!dt282x_ao_setup_dma(dev, s, 0))
901                 return -EPIPE;
902
903         if (!dt282x_ao_setup_dma(dev, s, 1))
904                 return -EPIPE;
905
906         outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
907              dev->iobase + DT2821_SUPCSR_REG);
908         s->async->inttrig = NULL;
909
910         return 1;
911 }
912
913 static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
914 {
915         struct dt282x_private *devpriv = dev->private;
916         struct comedi_isadma *dma = devpriv->dma;
917         struct comedi_cmd *cmd = &s->async->cmd;
918
919         dt282x_disable_dma(dev);
920
921         devpriv->supcsr = DT2821_SUPCSR_ERRINTEN |
922                           DT2821_SUPCSR_DS_DA_CLK |
923                           DT2821_SUPCSR_DDMA;
924         outw(devpriv->supcsr |
925              DT2821_SUPCSR_CLRDMADNE |
926              DT2821_SUPCSR_BUFFB |
927              DT2821_SUPCSR_DACINIT,
928              dev->iobase + DT2821_SUPCSR_REG);
929
930         devpriv->ntrig = cmd->stop_arg * cmd->chanlist_len;
931         devpriv->nread = devpriv->ntrig;
932
933         devpriv->dma_dir = COMEDI_ISADMA_WRITE;
934         dma->cur_dma = 0;
935
936         outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR_REG);
937
938         /* clear all bits but the DIO direction bits */
939         devpriv->dacsr &= (DT2821_DACSR_LBOE | DT2821_DACSR_HBOE);
940
941         devpriv->dacsr |= (DT2821_DACSR_SSEL |
942                            DT2821_DACSR_DACLK |
943                            DT2821_DACSR_IDARDY);
944         outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG);
945
946         s->async->inttrig = dt282x_ao_inttrig;
947
948         return 0;
949 }
950
951 static int dt282x_ao_cancel(struct comedi_device *dev,
952                             struct comedi_subdevice *s)
953 {
954         struct dt282x_private *devpriv = dev->private;
955
956         dt282x_disable_dma(dev);
957
958         /* clear all bits but the DIO direction bits */
959         devpriv->dacsr &= (DT2821_DACSR_LBOE | DT2821_DACSR_HBOE);
960
961         outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG);
962
963         devpriv->supcsr = 0;
964         outw(devpriv->supcsr | DT2821_SUPCSR_DACINIT,
965              dev->iobase + DT2821_SUPCSR_REG);
966
967         return 0;
968 }
969
970 static int dt282x_dio_insn_bits(struct comedi_device *dev,
971                                 struct comedi_subdevice *s,
972                                 struct comedi_insn *insn,
973                                 unsigned int *data)
974 {
975         if (comedi_dio_update_state(s, data))
976                 outw(s->state, dev->iobase + DT2821_DIODAT_REG);
977
978         data[1] = inw(dev->iobase + DT2821_DIODAT_REG);
979
980         return insn->n;
981 }
982
983 static int dt282x_dio_insn_config(struct comedi_device *dev,
984                                   struct comedi_subdevice *s,
985                                   struct comedi_insn *insn,
986                                   unsigned int *data)
987 {
988         struct dt282x_private *devpriv = dev->private;
989         unsigned int chan = CR_CHAN(insn->chanspec);
990         unsigned int mask;
991         int ret;
992
993         if (chan < 8)
994                 mask = 0x00ff;
995         else
996                 mask = 0xff00;
997
998         ret = comedi_dio_insn_config(dev, s, insn, data, mask);
999         if (ret)
1000                 return ret;
1001
1002         devpriv->dacsr &= ~(DT2821_DACSR_LBOE | DT2821_DACSR_HBOE);
1003         if (s->io_bits & 0x00ff)
1004                 devpriv->dacsr |= DT2821_DACSR_LBOE;
1005         if (s->io_bits & 0xff00)
1006                 devpriv->dacsr |= DT2821_DACSR_HBOE;
1007
1008         outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG);
1009
1010         return insn->n;
1011 }
1012
1013 static const struct comedi_lrange *const ai_range_table[] = {
1014         &range_dt282x_ai_lo_bipolar,
1015         &range_dt282x_ai_lo_unipolar,
1016         &range_dt282x_ai_5_bipolar,
1017         &range_dt282x_ai_5_unipolar
1018 };
1019
1020 static const struct comedi_lrange *const ai_range_pgl_table[] = {
1021         &range_dt282x_ai_hi_bipolar,
1022         &range_dt282x_ai_hi_unipolar
1023 };
1024
1025 static const struct comedi_lrange *opt_ai_range_lkup(int ispgl, int x)
1026 {
1027         if (ispgl) {
1028                 if (x < 0 || x >= 2)
1029                         x = 0;
1030                 return ai_range_pgl_table[x];
1031         }
1032
1033         if (x < 0 || x >= 4)
1034                 x = 0;
1035         return ai_range_table[x];
1036 }
1037
1038 static void dt282x_alloc_dma(struct comedi_device *dev,
1039                              struct comedi_devconfig *it)
1040 {
1041         struct dt282x_private *devpriv = dev->private;
1042         unsigned int irq_num = it->options[1];
1043         unsigned int dma_chan[2];
1044
1045         if (it->options[2] < it->options[3]) {
1046                 dma_chan[0] = it->options[2];
1047                 dma_chan[1] = it->options[3];
1048         } else {
1049                 dma_chan[0] = it->options[3];
1050                 dma_chan[1] = it->options[2];
1051         }
1052
1053         if (!irq_num || dma_chan[0] == dma_chan[1] ||
1054             dma_chan[0] < 5 || dma_chan[0] > 7 ||
1055             dma_chan[1] < 5 || dma_chan[1] > 7)
1056                 return;
1057
1058         if (request_irq(irq_num, dt282x_interrupt, 0, dev->board_name, dev))
1059                 return;
1060
1061         /* DMA uses two 4K buffers with separate DMA channels */
1062         devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan[0], dma_chan[1],
1063                                            PAGE_SIZE, 0);
1064         if (!devpriv->dma)
1065                 free_irq(irq_num, dev);
1066 }
1067
1068 static void dt282x_free_dma(struct comedi_device *dev)
1069 {
1070         struct dt282x_private *devpriv = dev->private;
1071
1072         if (devpriv)
1073                 comedi_isadma_free(devpriv->dma);
1074 }
1075
1076 static int dt282x_initialize(struct comedi_device *dev)
1077 {
1078         /* Initialize board */
1079         outw(DT2821_SUPCSR_BDINIT, dev->iobase + DT2821_SUPCSR_REG);
1080         inw(dev->iobase + DT2821_ADCSR_REG);
1081
1082         /*
1083          * At power up, some registers are in a well-known state.
1084          * Check them to see if a DT2821 series board is present.
1085          */
1086         if (((inw(dev->iobase + DT2821_ADCSR_REG) & 0xfff0) != 0x7c00) ||
1087             ((inw(dev->iobase + DT2821_CHANCSR_REG) & 0xf0f0) != 0x70f0) ||
1088             ((inw(dev->iobase + DT2821_DACSR_REG) & 0x7c93) != 0x7c90) ||
1089             ((inw(dev->iobase + DT2821_SUPCSR_REG) & 0xf8ff) != 0x0000) ||
1090             ((inw(dev->iobase + DT2821_TMRCTR_REG) & 0xff00) != 0xf000)) {
1091                 dev_err(dev->class_dev, "board not found\n");
1092                 return -EIO;
1093         }
1094         return 0;
1095 }
1096
1097 static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1098 {
1099         const struct dt282x_board *board = dev->board_ptr;
1100         struct dt282x_private *devpriv;
1101         struct comedi_subdevice *s;
1102         int ret;
1103
1104         ret = comedi_request_region(dev, it->options[0], 0x10);
1105         if (ret)
1106                 return ret;
1107
1108         ret = dt282x_initialize(dev);
1109         if (ret)
1110                 return ret;
1111
1112         devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1113         if (!devpriv)
1114                 return -ENOMEM;
1115
1116         /* an IRQ and 2 DMA channels are required for async command support */
1117         dt282x_alloc_dma(dev, it);
1118
1119         ret = comedi_alloc_subdevices(dev, 3);
1120         if (ret)
1121                 return ret;
1122
1123         /* Analog Input subdevice */
1124         s = &dev->subdevices[0];
1125         s->type         = COMEDI_SUBD_AI;
1126         s->subdev_flags = SDF_READABLE;
1127         if ((it->options[4] && board->adchan_di) || board->adchan_se == 0) {
1128                 s->subdev_flags |= SDF_DIFF;
1129                 s->n_chan       = board->adchan_di;
1130         } else {
1131                 s->subdev_flags |= SDF_COMMON;
1132                 s->n_chan       = board->adchan_se;
1133         }
1134         s->maxdata      = board->ai_maxdata;
1135
1136         s->range_table = opt_ai_range_lkup(board->ispgl, it->options[8]);
1137         devpriv->ad_2scomp = it->options[5] ? 1 : 0;
1138
1139         s->insn_read    = dt282x_ai_insn_read;
1140         if (dev->irq) {
1141                 dev->read_subdev = s;
1142                 s->subdev_flags |= SDF_CMD_READ;
1143                 s->len_chanlist = s->n_chan;
1144                 s->do_cmdtest   = dt282x_ai_cmdtest;
1145                 s->do_cmd       = dt282x_ai_cmd;
1146                 s->cancel       = dt282x_ai_cancel;
1147         }
1148
1149         /* Analog Output subdevice */
1150         s = &dev->subdevices[1];
1151         if (board->dachan) {
1152                 s->type         = COMEDI_SUBD_AO;
1153                 s->subdev_flags = SDF_WRITABLE;
1154                 s->n_chan       = board->dachan;
1155                 s->maxdata      = board->ao_maxdata;
1156                 /* ranges are per-channel, set by jumpers on the board */
1157                 s->range_table  = &dt282x_ao_range;
1158                 s->insn_write   = dt282x_ao_insn_write;
1159                 if (dev->irq) {
1160                         dev->write_subdev = s;
1161                         s->subdev_flags |= SDF_CMD_WRITE;
1162                         s->len_chanlist = s->n_chan;
1163                         s->do_cmdtest   = dt282x_ao_cmdtest;
1164                         s->do_cmd       = dt282x_ao_cmd;
1165                         s->cancel       = dt282x_ao_cancel;
1166                 }
1167
1168                 ret = comedi_alloc_subdev_readback(s);
1169                 if (ret)
1170                         return ret;
1171         } else {
1172                 s->type         = COMEDI_SUBD_UNUSED;
1173         }
1174
1175         /* Digital I/O subdevice */
1176         s = &dev->subdevices[2];
1177         s->type         = COMEDI_SUBD_DIO;
1178         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1179         s->n_chan       = 16;
1180         s->maxdata      = 1;
1181         s->range_table  = &range_digital;
1182         s->insn_bits    = dt282x_dio_insn_bits;
1183         s->insn_config  = dt282x_dio_insn_config;
1184
1185         return 0;
1186 }
1187
1188 static void dt282x_detach(struct comedi_device *dev)
1189 {
1190         dt282x_free_dma(dev);
1191         comedi_legacy_detach(dev);
1192 }
1193
1194 static struct comedi_driver dt282x_driver = {
1195         .driver_name    = "dt282x",
1196         .module         = THIS_MODULE,
1197         .attach         = dt282x_attach,
1198         .detach         = dt282x_detach,
1199         .board_name     = &boardtypes[0].name,
1200         .num_names      = ARRAY_SIZE(boardtypes),
1201         .offset         = sizeof(struct dt282x_board),
1202 };
1203 module_comedi_driver(dt282x_driver);
1204
1205 MODULE_AUTHOR("Comedi http://www.comedi.org");
1206 MODULE_DESCRIPTION("Comedi driver for Data Translation DT2821 series");
1207 MODULE_LICENSE("GPL");