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