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