Linux-libre 3.12.19-gnu
[librecmc/linux-libre.git] / drivers / staging / comedi / drivers / amplc_dio200_common.c
1 /*
2     comedi/drivers/amplc_dio200_common.c
3
4     Common support code for "amplc_dio200" and "amplc_dio200_pci".
5
6     Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/>
7
8     COMEDI - Linux Control and Measurement Device Interface
9     Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org>
10
11     This program is free software; you can redistribute it and/or modify
12     it under the terms of the GNU General Public License as published by
13     the Free Software Foundation; either version 2 of the License, or
14     (at your option) any later version.
15
16     This program is distributed in the hope that it will be useful,
17     but WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     GNU General Public License for more details.
20 */
21
22 #include <linux/module.h>
23 #include <linux/interrupt.h>
24
25 #include "../comedidev.h"
26
27 #include "amplc_dio200.h"
28 #include "comedi_fc.h"
29 #include "8253.h"
30
31 /* 8255 control register bits */
32 #define CR_C_LO_IO      0x01
33 #define CR_B_IO         0x02
34 #define CR_B_MODE       0x04
35 #define CR_C_HI_IO      0x08
36 #define CR_A_IO         0x10
37 #define CR_A_MODE(a)    ((a)<<5)
38 #define CR_CW           0x80
39
40 /* 200 series registers */
41 #define DIO200_IO_SIZE          0x20
42 #define DIO200_PCIE_IO_SIZE     0x4000
43 #define DIO200_XCLK_SCE         0x18    /* Group X clock selection register */
44 #define DIO200_YCLK_SCE         0x19    /* Group Y clock selection register */
45 #define DIO200_ZCLK_SCE         0x1a    /* Group Z clock selection register */
46 #define DIO200_XGAT_SCE         0x1b    /* Group X gate selection register */
47 #define DIO200_YGAT_SCE         0x1c    /* Group Y gate selection register */
48 #define DIO200_ZGAT_SCE         0x1d    /* Group Z gate selection register */
49 #define DIO200_INT_SCE          0x1e    /* Interrupt enable/status register */
50 /* Extra registers for new PCIe boards */
51 #define DIO200_ENHANCE          0x20    /* 1 to enable enhanced features */
52 #define DIO200_VERSION          0x24    /* Hardware version register */
53 #define DIO200_TS_CONFIG        0x600   /* Timestamp timer config register */
54 #define DIO200_TS_COUNT         0x602   /* Timestamp timer count register */
55
56 /*
57  * Functions for constructing value for DIO_200_?CLK_SCE and
58  * DIO_200_?GAT_SCE registers:
59  *
60  * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2.
61  * 'chan' is the channel: 0, 1 or 2.
62  * 'source' is the signal source: 0 to 7, or 0 to 31 for "enhanced" boards.
63  */
64 static unsigned char clk_gat_sce(unsigned int which, unsigned int chan,
65                                  unsigned int source)
66 {
67         return (which << 5) | (chan << 3) |
68                ((source & 030) << 3) | (source & 007);
69 }
70
71 static unsigned char clk_sce(unsigned int which, unsigned int chan,
72                              unsigned int source)
73 {
74         return clk_gat_sce(which, chan, source);
75 }
76
77 static unsigned char gat_sce(unsigned int which, unsigned int chan,
78                              unsigned int source)
79 {
80         return clk_gat_sce(which, chan, source);
81 }
82
83 /*
84  * Periods of the internal clock sources in nanoseconds.
85  */
86 static const unsigned int clock_period[32] = {
87         [1] = 100,              /* 10 MHz */
88         [2] = 1000,             /* 1 MHz */
89         [3] = 10000,            /* 100 kHz */
90         [4] = 100000,           /* 10 kHz */
91         [5] = 1000000,          /* 1 kHz */
92         [11] = 50,              /* 20 MHz (enhanced boards) */
93         /* clock sources 12 and later reserved for enhanced boards */
94 };
95
96 /*
97  * Timestamp timer configuration register (for new PCIe boards).
98  */
99 #define TS_CONFIG_RESET         0x100   /* Reset counter to zero. */
100 #define TS_CONFIG_CLK_SRC_MASK  0x0FF   /* Clock source. */
101 #define TS_CONFIG_MAX_CLK_SRC   2       /* Maximum clock source value. */
102
103 /*
104  * Periods of the timestamp timer clock sources in nanoseconds.
105  */
106 static const unsigned int ts_clock_period[TS_CONFIG_MAX_CLK_SRC + 1] = {
107         1,                      /* 1 nanosecond (but with 20 ns granularity). */
108         1000,                   /* 1 microsecond. */
109         1000000,                /* 1 millisecond. */
110 };
111
112 struct dio200_subdev_8254 {
113         unsigned int ofs;               /* Counter base offset */
114         unsigned int clk_sce_ofs;       /* CLK_SCE base address */
115         unsigned int gat_sce_ofs;       /* GAT_SCE base address */
116         int which;                      /* Bit 5 of CLK_SCE or GAT_SCE */
117         unsigned int clock_src[3];      /* Current clock sources */
118         unsigned int gate_src[3];       /* Current gate sources */
119         spinlock_t spinlock;
120 };
121
122 struct dio200_subdev_8255 {
123         unsigned int ofs;               /* DIO base offset */
124 };
125
126 struct dio200_subdev_intr {
127         spinlock_t spinlock;
128         unsigned int ofs;
129         unsigned int valid_isns;
130         unsigned int enabled_isns;
131         unsigned int stopcount;
132         bool active:1;
133         bool continuous:1;
134 };
135
136 static inline const struct dio200_layout *
137 dio200_board_layout(const struct dio200_board *board)
138 {
139         return &board->layout;
140 }
141
142 static inline const struct dio200_layout *
143 dio200_dev_layout(struct comedi_device *dev)
144 {
145         return dio200_board_layout(comedi_board(dev));
146 }
147
148 /*
149  * Read 8-bit register.
150  */
151 static unsigned char dio200_read8(struct comedi_device *dev,
152                                   unsigned int offset)
153 {
154         const struct dio200_board *thisboard = comedi_board(dev);
155         struct dio200_private *devpriv = dev->private;
156
157         offset <<= thisboard->mainshift;
158         if (devpriv->io.regtype == io_regtype)
159                 return inb(devpriv->io.u.iobase + offset);
160         else
161                 return readb(devpriv->io.u.membase + offset);
162 }
163
164 /*
165  * Write 8-bit register.
166  */
167 static void dio200_write8(struct comedi_device *dev, unsigned int offset,
168                           unsigned char val)
169 {
170         const struct dio200_board *thisboard = comedi_board(dev);
171         struct dio200_private *devpriv = dev->private;
172
173         offset <<= thisboard->mainshift;
174         if (devpriv->io.regtype == io_regtype)
175                 outb(val, devpriv->io.u.iobase + offset);
176         else
177                 writeb(val, devpriv->io.u.membase + offset);
178 }
179
180 /*
181  * Read 32-bit register.
182  */
183 static unsigned int dio200_read32(struct comedi_device *dev,
184                                   unsigned int offset)
185 {
186         const struct dio200_board *thisboard = comedi_board(dev);
187         struct dio200_private *devpriv = dev->private;
188
189         offset <<= thisboard->mainshift;
190         if (devpriv->io.regtype == io_regtype)
191                 return inl(devpriv->io.u.iobase + offset);
192         else
193                 return readl(devpriv->io.u.membase + offset);
194 }
195
196 /*
197  * Write 32-bit register.
198  */
199 static void dio200_write32(struct comedi_device *dev, unsigned int offset,
200                            unsigned int val)
201 {
202         const struct dio200_board *thisboard = comedi_board(dev);
203         struct dio200_private *devpriv = dev->private;
204
205         offset <<= thisboard->mainshift;
206         if (devpriv->io.regtype == io_regtype)
207                 outl(val, devpriv->io.u.iobase + offset);
208         else
209                 writel(val, devpriv->io.u.membase + offset);
210 }
211
212 /*
213  * 'insn_bits' function for an 'INTERRUPT' subdevice.
214  */
215 static int
216 dio200_subdev_intr_insn_bits(struct comedi_device *dev,
217                              struct comedi_subdevice *s,
218                              struct comedi_insn *insn, unsigned int *data)
219 {
220         const struct dio200_layout *layout = dio200_dev_layout(dev);
221         struct dio200_subdev_intr *subpriv = s->private;
222
223         if (layout->has_int_sce) {
224                 /* Just read the interrupt status register.  */
225                 data[1] = dio200_read8(dev, subpriv->ofs) & subpriv->valid_isns;
226         } else {
227                 /* No interrupt status register. */
228                 data[0] = 0;
229         }
230
231         return insn->n;
232 }
233
234 /*
235  * Called to stop acquisition for an 'INTERRUPT' subdevice.
236  */
237 static void dio200_stop_intr(struct comedi_device *dev,
238                              struct comedi_subdevice *s)
239 {
240         const struct dio200_layout *layout = dio200_dev_layout(dev);
241         struct dio200_subdev_intr *subpriv = s->private;
242
243         subpriv->active = false;
244         subpriv->enabled_isns = 0;
245         if (layout->has_int_sce)
246                 dio200_write8(dev, subpriv->ofs, 0);
247 }
248
249 /*
250  * Called to start acquisition for an 'INTERRUPT' subdevice.
251  */
252 static int dio200_start_intr(struct comedi_device *dev,
253                              struct comedi_subdevice *s)
254 {
255         unsigned int n;
256         unsigned isn_bits;
257         const struct dio200_layout *layout = dio200_dev_layout(dev);
258         struct dio200_subdev_intr *subpriv = s->private;
259         struct comedi_cmd *cmd = &s->async->cmd;
260         int retval = 0;
261
262         if (!subpriv->continuous && subpriv->stopcount == 0) {
263                 /* An empty acquisition! */
264                 s->async->events |= COMEDI_CB_EOA;
265                 subpriv->active = false;
266                 retval = 1;
267         } else {
268                 /* Determine interrupt sources to enable. */
269                 isn_bits = 0;
270                 if (cmd->chanlist) {
271                         for (n = 0; n < cmd->chanlist_len; n++)
272                                 isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
273                 }
274                 isn_bits &= subpriv->valid_isns;
275                 /* Enable interrupt sources. */
276                 subpriv->enabled_isns = isn_bits;
277                 if (layout->has_int_sce)
278                         dio200_write8(dev, subpriv->ofs, isn_bits);
279         }
280
281         return retval;
282 }
283
284 /*
285  * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
286  */
287 static int
288 dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
289                           unsigned int trignum)
290 {
291         struct dio200_subdev_intr *subpriv;
292         unsigned long flags;
293         int event = 0;
294
295         if (trignum != 0)
296                 return -EINVAL;
297
298         subpriv = s->private;
299
300         spin_lock_irqsave(&subpriv->spinlock, flags);
301         s->async->inttrig = NULL;
302         if (subpriv->active)
303                 event = dio200_start_intr(dev, s);
304
305         spin_unlock_irqrestore(&subpriv->spinlock, flags);
306
307         if (event)
308                 comedi_event(dev, s);
309
310         return 1;
311 }
312
313 static void dio200_read_scan_intr(struct comedi_device *dev,
314                                   struct comedi_subdevice *s,
315                                   unsigned int triggered)
316 {
317         struct dio200_subdev_intr *subpriv = s->private;
318         unsigned short val;
319         unsigned int n, ch, len;
320
321         val = 0;
322         len = s->async->cmd.chanlist_len;
323         for (n = 0; n < len; n++) {
324                 ch = CR_CHAN(s->async->cmd.chanlist[n]);
325                 if (triggered & (1U << ch))
326                         val |= (1U << n);
327         }
328         /* Write the scan to the buffer. */
329         if (comedi_buf_put(s->async, val)) {
330                 s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
331         } else {
332                 /* Error!  Stop acquisition.  */
333                 dio200_stop_intr(dev, s);
334                 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
335                 comedi_error(dev, "buffer overflow");
336         }
337
338         /* Check for end of acquisition. */
339         if (!subpriv->continuous) {
340                 /* stop_src == TRIG_COUNT */
341                 if (subpriv->stopcount > 0) {
342                         subpriv->stopcount--;
343                         if (subpriv->stopcount == 0) {
344                                 s->async->events |= COMEDI_CB_EOA;
345                                 dio200_stop_intr(dev, s);
346                         }
347                 }
348         }
349 }
350
351 /*
352  * This is called from the interrupt service routine to handle a read
353  * scan on an 'INTERRUPT' subdevice.
354  */
355 static int dio200_handle_read_intr(struct comedi_device *dev,
356                                    struct comedi_subdevice *s)
357 {
358         const struct dio200_layout *layout = dio200_dev_layout(dev);
359         struct dio200_subdev_intr *subpriv = s->private;
360         unsigned triggered;
361         unsigned intstat;
362         unsigned cur_enabled;
363         unsigned int oldevents;
364         unsigned long flags;
365
366         triggered = 0;
367
368         spin_lock_irqsave(&subpriv->spinlock, flags);
369         oldevents = s->async->events;
370         if (layout->has_int_sce) {
371                 /*
372                  * Collect interrupt sources that have triggered and disable
373                  * them temporarily.  Loop around until no extra interrupt
374                  * sources have triggered, at which point, the valid part of
375                  * the interrupt status register will read zero, clearing the
376                  * cause of the interrupt.
377                  *
378                  * Mask off interrupt sources already seen to avoid infinite
379                  * loop in case of misconfiguration.
380                  */
381                 cur_enabled = subpriv->enabled_isns;
382                 while ((intstat = (dio200_read8(dev, subpriv->ofs) &
383                                    subpriv->valid_isns & ~triggered)) != 0) {
384                         triggered |= intstat;
385                         cur_enabled &= ~triggered;
386                         dio200_write8(dev, subpriv->ofs, cur_enabled);
387                 }
388         } else {
389                 /*
390                  * No interrupt status register.  Assume the single interrupt
391                  * source has triggered.
392                  */
393                 triggered = subpriv->enabled_isns;
394         }
395
396         if (triggered) {
397                 /*
398                  * Some interrupt sources have triggered and have been
399                  * temporarily disabled to clear the cause of the interrupt.
400                  *
401                  * Reenable them NOW to minimize the time they are disabled.
402                  */
403                 cur_enabled = subpriv->enabled_isns;
404                 if (layout->has_int_sce)
405                         dio200_write8(dev, subpriv->ofs, cur_enabled);
406
407                 if (subpriv->active) {
408                         /*
409                          * The command is still active.
410                          *
411                          * Ignore interrupt sources that the command isn't
412                          * interested in (just in case there's a race
413                          * condition).
414                          */
415                         if (triggered & subpriv->enabled_isns)
416                                 /* Collect scan data. */
417                                 dio200_read_scan_intr(dev, s, triggered);
418                 }
419         }
420         spin_unlock_irqrestore(&subpriv->spinlock, flags);
421
422         if (oldevents != s->async->events)
423                 comedi_event(dev, s);
424
425         return (triggered != 0);
426 }
427
428 /*
429  * 'cancel' function for an 'INTERRUPT' subdevice.
430  */
431 static int dio200_subdev_intr_cancel(struct comedi_device *dev,
432                                      struct comedi_subdevice *s)
433 {
434         struct dio200_subdev_intr *subpriv = s->private;
435         unsigned long flags;
436
437         spin_lock_irqsave(&subpriv->spinlock, flags);
438         if (subpriv->active)
439                 dio200_stop_intr(dev, s);
440
441         spin_unlock_irqrestore(&subpriv->spinlock, flags);
442
443         return 0;
444 }
445
446 /*
447  * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
448  */
449 static int
450 dio200_subdev_intr_cmdtest(struct comedi_device *dev,
451                            struct comedi_subdevice *s, struct comedi_cmd *cmd)
452 {
453         int err = 0;
454
455         /* Step 1 : check if triggers are trivially valid */
456
457         err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
458         err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
459         err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
460         err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
461         err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
462
463         if (err)
464                 return 1;
465
466         /* Step 2a : make sure trigger sources are unique */
467
468         err |= cfc_check_trigger_is_unique(cmd->start_src);
469         err |= cfc_check_trigger_is_unique(cmd->stop_src);
470
471         /* Step 2b : and mutually compatible */
472
473         if (err)
474                 return 2;
475
476         /* Step 3: check if arguments are trivially valid */
477
478         err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
479         err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
480         err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
481         err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
482
483         switch (cmd->stop_src) {
484         case TRIG_COUNT:
485                 /* any count allowed */
486                 break;
487         case TRIG_NONE:
488                 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
489                 break;
490         default:
491                 break;
492         }
493
494         if (err)
495                 return 3;
496
497         /* step 4: fix up any arguments */
498
499         /* if (err) return 4; */
500
501         return 0;
502 }
503
504 /*
505  * 'do_cmd' function for an 'INTERRUPT' subdevice.
506  */
507 static int dio200_subdev_intr_cmd(struct comedi_device *dev,
508                                   struct comedi_subdevice *s)
509 {
510         struct comedi_cmd *cmd = &s->async->cmd;
511         struct dio200_subdev_intr *subpriv = s->private;
512         unsigned long flags;
513         int event = 0;
514
515         spin_lock_irqsave(&subpriv->spinlock, flags);
516         subpriv->active = 1;
517
518         /* Set up end of acquisition. */
519         switch (cmd->stop_src) {
520         case TRIG_COUNT:
521                 subpriv->continuous = false;
522                 subpriv->stopcount = cmd->stop_arg;
523                 break;
524         default:
525                 /* TRIG_NONE */
526                 subpriv->continuous = true;
527                 subpriv->stopcount = 0;
528                 break;
529         }
530
531         /* Set up start of acquisition. */
532         switch (cmd->start_src) {
533         case TRIG_INT:
534                 s->async->inttrig = dio200_inttrig_start_intr;
535                 break;
536         default:
537                 /* TRIG_NOW */
538                 event = dio200_start_intr(dev, s);
539                 break;
540         }
541         spin_unlock_irqrestore(&subpriv->spinlock, flags);
542
543         if (event)
544                 comedi_event(dev, s);
545
546         return 0;
547 }
548
549 /*
550  * This function initializes an 'INTERRUPT' subdevice.
551  */
552 static int
553 dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
554                         unsigned int offset, unsigned valid_isns)
555 {
556         const struct dio200_layout *layout = dio200_dev_layout(dev);
557         struct dio200_subdev_intr *subpriv;
558
559         subpriv = comedi_alloc_spriv(s, sizeof(*subpriv));
560         if (!subpriv)
561                 return -ENOMEM;
562
563         subpriv->ofs = offset;
564         subpriv->valid_isns = valid_isns;
565         spin_lock_init(&subpriv->spinlock);
566
567         if (layout->has_int_sce)
568                 /* Disable interrupt sources. */
569                 dio200_write8(dev, subpriv->ofs, 0);
570
571         s->type = COMEDI_SUBD_DI;
572         s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
573         if (layout->has_int_sce) {
574                 s->n_chan = DIO200_MAX_ISNS;
575                 s->len_chanlist = DIO200_MAX_ISNS;
576         } else {
577                 /* No interrupt source register.  Support single channel. */
578                 s->n_chan = 1;
579                 s->len_chanlist = 1;
580         }
581         s->range_table = &range_digital;
582         s->maxdata = 1;
583         s->insn_bits = dio200_subdev_intr_insn_bits;
584         s->do_cmdtest = dio200_subdev_intr_cmdtest;
585         s->do_cmd = dio200_subdev_intr_cmd;
586         s->cancel = dio200_subdev_intr_cancel;
587
588         return 0;
589 }
590
591 /*
592  * Interrupt service routine.
593  */
594 static irqreturn_t dio200_interrupt(int irq, void *d)
595 {
596         struct comedi_device *dev = d;
597         struct dio200_private *devpriv = dev->private;
598         struct comedi_subdevice *s;
599         int handled;
600
601         if (!dev->attached)
602                 return IRQ_NONE;
603
604         if (devpriv->intr_sd >= 0) {
605                 s = &dev->subdevices[devpriv->intr_sd];
606                 handled = dio200_handle_read_intr(dev, s);
607         } else {
608                 handled = 0;
609         }
610
611         return IRQ_RETVAL(handled);
612 }
613
614 /*
615  * Read an '8254' counter subdevice channel.
616  */
617 static unsigned int
618 dio200_subdev_8254_read_chan(struct comedi_device *dev,
619                              struct comedi_subdevice *s, unsigned int chan)
620 {
621         struct dio200_subdev_8254 *subpriv = s->private;
622         unsigned int val;
623
624         /* latch counter */
625         val = chan << 6;
626         dio200_write8(dev, subpriv->ofs + i8254_control_reg, val);
627         /* read lsb, msb */
628         val = dio200_read8(dev, subpriv->ofs + chan);
629         val += dio200_read8(dev, subpriv->ofs + chan) << 8;
630         return val;
631 }
632
633 /*
634  * Write an '8254' subdevice channel.
635  */
636 static void
637 dio200_subdev_8254_write_chan(struct comedi_device *dev,
638                               struct comedi_subdevice *s, unsigned int chan,
639                               unsigned int count)
640 {
641         struct dio200_subdev_8254 *subpriv = s->private;
642
643         /* write lsb, msb */
644         dio200_write8(dev, subpriv->ofs + chan, count & 0xff);
645         dio200_write8(dev, subpriv->ofs + chan, (count >> 8) & 0xff);
646 }
647
648 /*
649  * Set mode of an '8254' subdevice channel.
650  */
651 static void
652 dio200_subdev_8254_set_mode(struct comedi_device *dev,
653                             struct comedi_subdevice *s, unsigned int chan,
654                             unsigned int mode)
655 {
656         struct dio200_subdev_8254 *subpriv = s->private;
657         unsigned int byte;
658
659         byte = chan << 6;
660         byte |= 0x30;           /* access order: lsb, msb */
661         byte |= (mode & 0xf);   /* counter mode and BCD|binary */
662         dio200_write8(dev, subpriv->ofs + i8254_control_reg, byte);
663 }
664
665 /*
666  * Read status byte of an '8254' counter subdevice channel.
667  */
668 static unsigned int
669 dio200_subdev_8254_status(struct comedi_device *dev,
670                           struct comedi_subdevice *s, unsigned int chan)
671 {
672         struct dio200_subdev_8254 *subpriv = s->private;
673
674         /* latch status */
675         dio200_write8(dev, subpriv->ofs + i8254_control_reg,
676                       0xe0 | (2 << chan));
677         /* read status */
678         return dio200_read8(dev, subpriv->ofs + chan);
679 }
680
681 /*
682  * Handle 'insn_read' for an '8254' counter subdevice.
683  */
684 static int
685 dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
686                         struct comedi_insn *insn, unsigned int *data)
687 {
688         struct dio200_subdev_8254 *subpriv = s->private;
689         int chan = CR_CHAN(insn->chanspec);
690         unsigned int n;
691         unsigned long flags;
692
693         for (n = 0; n < insn->n; n++) {
694                 spin_lock_irqsave(&subpriv->spinlock, flags);
695                 data[n] = dio200_subdev_8254_read_chan(dev, s, chan);
696                 spin_unlock_irqrestore(&subpriv->spinlock, flags);
697         }
698         return insn->n;
699 }
700
701 /*
702  * Handle 'insn_write' for an '8254' counter subdevice.
703  */
704 static int
705 dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
706                          struct comedi_insn *insn, unsigned int *data)
707 {
708         struct dio200_subdev_8254 *subpriv = s->private;
709         int chan = CR_CHAN(insn->chanspec);
710         unsigned int n;
711         unsigned long flags;
712
713         for (n = 0; n < insn->n; n++) {
714                 spin_lock_irqsave(&subpriv->spinlock, flags);
715                 dio200_subdev_8254_write_chan(dev, s, chan, data[n]);
716                 spin_unlock_irqrestore(&subpriv->spinlock, flags);
717         }
718         return insn->n;
719 }
720
721 /*
722  * Set gate source for an '8254' counter subdevice channel.
723  */
724 static int
725 dio200_subdev_8254_set_gate_src(struct comedi_device *dev,
726                                 struct comedi_subdevice *s,
727                                 unsigned int counter_number,
728                                 unsigned int gate_src)
729 {
730         const struct dio200_layout *layout = dio200_dev_layout(dev);
731         struct dio200_subdev_8254 *subpriv = s->private;
732         unsigned char byte;
733
734         if (!layout->has_clk_gat_sce)
735                 return -1;
736         if (counter_number > 2)
737                 return -1;
738         if (gate_src > (layout->has_enhancements ? 31 : 7))
739                 return -1;
740
741         subpriv->gate_src[counter_number] = gate_src;
742         byte = gat_sce(subpriv->which, counter_number, gate_src);
743         dio200_write8(dev, subpriv->gat_sce_ofs, byte);
744
745         return 0;
746 }
747
748 /*
749  * Get gate source for an '8254' counter subdevice channel.
750  */
751 static int
752 dio200_subdev_8254_get_gate_src(struct comedi_device *dev,
753                                 struct comedi_subdevice *s,
754                                 unsigned int counter_number)
755 {
756         const struct dio200_layout *layout = dio200_dev_layout(dev);
757         struct dio200_subdev_8254 *subpriv = s->private;
758
759         if (!layout->has_clk_gat_sce)
760                 return -1;
761         if (counter_number > 2)
762                 return -1;
763
764         return subpriv->gate_src[counter_number];
765 }
766
767 /*
768  * Set clock source for an '8254' counter subdevice channel.
769  */
770 static int
771 dio200_subdev_8254_set_clock_src(struct comedi_device *dev,
772                                  struct comedi_subdevice *s,
773                                  unsigned int counter_number,
774                                  unsigned int clock_src)
775 {
776         const struct dio200_layout *layout = dio200_dev_layout(dev);
777         struct dio200_subdev_8254 *subpriv = s->private;
778         unsigned char byte;
779
780         if (!layout->has_clk_gat_sce)
781                 return -1;
782         if (counter_number > 2)
783                 return -1;
784         if (clock_src > (layout->has_enhancements ? 31 : 7))
785                 return -1;
786
787         subpriv->clock_src[counter_number] = clock_src;
788         byte = clk_sce(subpriv->which, counter_number, clock_src);
789         dio200_write8(dev, subpriv->clk_sce_ofs, byte);
790
791         return 0;
792 }
793
794 /*
795  * Get clock source for an '8254' counter subdevice channel.
796  */
797 static int
798 dio200_subdev_8254_get_clock_src(struct comedi_device *dev,
799                                  struct comedi_subdevice *s,
800                                  unsigned int counter_number,
801                                  unsigned int *period_ns)
802 {
803         const struct dio200_layout *layout = dio200_dev_layout(dev);
804         struct dio200_subdev_8254 *subpriv = s->private;
805         unsigned clock_src;
806
807         if (!layout->has_clk_gat_sce)
808                 return -1;
809         if (counter_number > 2)
810                 return -1;
811
812         clock_src = subpriv->clock_src[counter_number];
813         *period_ns = clock_period[clock_src];
814         return clock_src;
815 }
816
817 /*
818  * Handle 'insn_config' for an '8254' counter subdevice.
819  */
820 static int
821 dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
822                           struct comedi_insn *insn, unsigned int *data)
823 {
824         struct dio200_subdev_8254 *subpriv = s->private;
825         int ret = 0;
826         int chan = CR_CHAN(insn->chanspec);
827         unsigned long flags;
828
829         spin_lock_irqsave(&subpriv->spinlock, flags);
830         switch (data[0]) {
831         case INSN_CONFIG_SET_COUNTER_MODE:
832                 if (data[1] > (I8254_MODE5 | I8254_BINARY))
833                         ret = -EINVAL;
834                 else
835                         dio200_subdev_8254_set_mode(dev, s, chan, data[1]);
836                 break;
837         case INSN_CONFIG_8254_READ_STATUS:
838                 data[1] = dio200_subdev_8254_status(dev, s, chan);
839                 break;
840         case INSN_CONFIG_SET_GATE_SRC:
841                 ret = dio200_subdev_8254_set_gate_src(dev, s, chan, data[2]);
842                 if (ret < 0)
843                         ret = -EINVAL;
844                 break;
845         case INSN_CONFIG_GET_GATE_SRC:
846                 ret = dio200_subdev_8254_get_gate_src(dev, s, chan);
847                 if (ret < 0) {
848                         ret = -EINVAL;
849                         break;
850                 }
851                 data[2] = ret;
852                 break;
853         case INSN_CONFIG_SET_CLOCK_SRC:
854                 ret = dio200_subdev_8254_set_clock_src(dev, s, chan, data[1]);
855                 if (ret < 0)
856                         ret = -EINVAL;
857                 break;
858         case INSN_CONFIG_GET_CLOCK_SRC:
859                 ret = dio200_subdev_8254_get_clock_src(dev, s, chan, &data[2]);
860                 if (ret < 0) {
861                         ret = -EINVAL;
862                         break;
863                 }
864                 data[1] = ret;
865                 break;
866         default:
867                 ret = -EINVAL;
868                 break;
869         }
870         spin_unlock_irqrestore(&subpriv->spinlock, flags);
871         return ret < 0 ? ret : insn->n;
872 }
873
874 /*
875  * This function initializes an '8254' counter subdevice.
876  */
877 static int
878 dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
879                         unsigned int offset)
880 {
881         const struct dio200_layout *layout = dio200_dev_layout(dev);
882         struct dio200_subdev_8254 *subpriv;
883         unsigned int chan;
884
885         subpriv = comedi_alloc_spriv(s, sizeof(*subpriv));
886         if (!subpriv)
887                 return -ENOMEM;
888
889         s->type = COMEDI_SUBD_COUNTER;
890         s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
891         s->n_chan = 3;
892         s->maxdata = 0xFFFF;
893         s->insn_read = dio200_subdev_8254_read;
894         s->insn_write = dio200_subdev_8254_write;
895         s->insn_config = dio200_subdev_8254_config;
896
897         spin_lock_init(&subpriv->spinlock);
898         subpriv->ofs = offset;
899         if (layout->has_clk_gat_sce) {
900                 /* Derive CLK_SCE and GAT_SCE register offsets from
901                  * 8254 offset. */
902                 subpriv->clk_sce_ofs = DIO200_XCLK_SCE + (offset >> 3);
903                 subpriv->gat_sce_ofs = DIO200_XGAT_SCE + (offset >> 3);
904                 subpriv->which = (offset >> 2) & 1;
905         }
906
907         /* Initialize channels. */
908         for (chan = 0; chan < 3; chan++) {
909                 dio200_subdev_8254_set_mode(dev, s, chan,
910                                             I8254_MODE0 | I8254_BINARY);
911                 if (layout->has_clk_gat_sce) {
912                         /* Gate source 0 is VCC (logic 1). */
913                         dio200_subdev_8254_set_gate_src(dev, s, chan, 0);
914                         /* Clock source 0 is the dedicated clock input. */
915                         dio200_subdev_8254_set_clock_src(dev, s, chan, 0);
916                 }
917         }
918
919         return 0;
920 }
921
922 /*
923  * This function sets I/O directions for an '8255' DIO subdevice.
924  */
925 static void dio200_subdev_8255_set_dir(struct comedi_device *dev,
926                                        struct comedi_subdevice *s)
927 {
928         struct dio200_subdev_8255 *subpriv = s->private;
929         int config;
930
931         config = CR_CW;
932         /* 1 in io_bits indicates output, 1 in config indicates input */
933         if (!(s->io_bits & 0x0000ff))
934                 config |= CR_A_IO;
935         if (!(s->io_bits & 0x00ff00))
936                 config |= CR_B_IO;
937         if (!(s->io_bits & 0x0f0000))
938                 config |= CR_C_LO_IO;
939         if (!(s->io_bits & 0xf00000))
940                 config |= CR_C_HI_IO;
941         dio200_write8(dev, subpriv->ofs + 3, config);
942 }
943
944 /*
945  * Handle 'insn_bits' for an '8255' DIO subdevice.
946  */
947 static int dio200_subdev_8255_bits(struct comedi_device *dev,
948                                    struct comedi_subdevice *s,
949                                    struct comedi_insn *insn, unsigned int *data)
950 {
951         struct dio200_subdev_8255 *subpriv = s->private;
952
953         if (data[0]) {
954                 s->state &= ~data[0];
955                 s->state |= (data[0] & data[1]);
956                 if (data[0] & 0xff)
957                         dio200_write8(dev, subpriv->ofs, s->state & 0xff);
958                 if (data[0] & 0xff00)
959                         dio200_write8(dev, subpriv->ofs + 1,
960                                       (s->state >> 8) & 0xff);
961                 if (data[0] & 0xff0000)
962                         dio200_write8(dev, subpriv->ofs + 2,
963                                       (s->state >> 16) & 0xff);
964         }
965         data[1] = dio200_read8(dev, subpriv->ofs);
966         data[1] |= dio200_read8(dev, subpriv->ofs + 1) << 8;
967         data[1] |= dio200_read8(dev, subpriv->ofs + 2) << 16;
968         return 2;
969 }
970
971 /*
972  * Handle 'insn_config' for an '8255' DIO subdevice.
973  */
974 static int dio200_subdev_8255_config(struct comedi_device *dev,
975                                      struct comedi_subdevice *s,
976                                      struct comedi_insn *insn,
977                                      unsigned int *data)
978 {
979         unsigned int chan = CR_CHAN(insn->chanspec);
980         unsigned int mask;
981         int ret;
982
983         if (chan < 8)
984                 mask = 0x0000ff;
985         else if (chan < 16)
986                 mask = 0x00ff00;
987         else if (chan < 20)
988                 mask = 0x0f0000;
989         else
990                 mask = 0xf00000;
991
992         ret = comedi_dio_insn_config(dev, s, insn, data, mask);
993         if (ret)
994                 return ret;
995
996         dio200_subdev_8255_set_dir(dev, s);
997
998         return insn->n;
999 }
1000
1001 /*
1002  * This function initializes an '8255' DIO subdevice.
1003  *
1004  * offset is the offset to the 8255 chip.
1005  */
1006 static int dio200_subdev_8255_init(struct comedi_device *dev,
1007                                    struct comedi_subdevice *s,
1008                                    unsigned int offset)
1009 {
1010         struct dio200_subdev_8255 *subpriv;
1011
1012         subpriv = comedi_alloc_spriv(s, sizeof(*subpriv));
1013         if (!subpriv)
1014                 return -ENOMEM;
1015
1016         subpriv->ofs = offset;
1017
1018         s->type = COMEDI_SUBD_DIO;
1019         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1020         s->n_chan = 24;
1021         s->range_table = &range_digital;
1022         s->maxdata = 1;
1023         s->insn_bits = dio200_subdev_8255_bits;
1024         s->insn_config = dio200_subdev_8255_config;
1025         s->state = 0;
1026         s->io_bits = 0;
1027         dio200_subdev_8255_set_dir(dev, s);
1028         return 0;
1029 }
1030
1031 /*
1032  * Handle 'insn_read' for a timer subdevice.
1033  */
1034 static int dio200_subdev_timer_read(struct comedi_device *dev,
1035                                     struct comedi_subdevice *s,
1036                                     struct comedi_insn *insn,
1037                                     unsigned int *data)
1038 {
1039         unsigned int n;
1040
1041         for (n = 0; n < insn->n; n++)
1042                 data[n] = dio200_read32(dev, DIO200_TS_COUNT);
1043         return n;
1044 }
1045
1046 /*
1047  * Reset timer subdevice.
1048  */
1049 static void dio200_subdev_timer_reset(struct comedi_device *dev,
1050                                       struct comedi_subdevice *s)
1051 {
1052         unsigned int clock;
1053
1054         clock = dio200_read32(dev, DIO200_TS_CONFIG) & TS_CONFIG_CLK_SRC_MASK;
1055         dio200_write32(dev, DIO200_TS_CONFIG, clock | TS_CONFIG_RESET);
1056         dio200_write32(dev, DIO200_TS_CONFIG, clock);
1057 }
1058
1059 /*
1060  * Get timer subdevice clock source and period.
1061  */
1062 static void dio200_subdev_timer_get_clock_src(struct comedi_device *dev,
1063                                               struct comedi_subdevice *s,
1064                                               unsigned int *src,
1065                                               unsigned int *period)
1066 {
1067         unsigned int clk;
1068
1069         clk = dio200_read32(dev, DIO200_TS_CONFIG) & TS_CONFIG_CLK_SRC_MASK;
1070         *src = clk;
1071         *period = (clk < ARRAY_SIZE(ts_clock_period)) ?
1072                   ts_clock_period[clk] : 0;
1073 }
1074
1075 /*
1076  * Set timer subdevice clock source.
1077  */
1078 static int dio200_subdev_timer_set_clock_src(struct comedi_device *dev,
1079                                              struct comedi_subdevice *s,
1080                                              unsigned int src)
1081 {
1082         if (src > TS_CONFIG_MAX_CLK_SRC)
1083                 return -EINVAL;
1084         dio200_write32(dev, DIO200_TS_CONFIG, src);
1085         return 0;
1086 }
1087
1088 /*
1089  * Handle 'insn_config' for a timer subdevice.
1090  */
1091 static int dio200_subdev_timer_config(struct comedi_device *dev,
1092                                       struct comedi_subdevice *s,
1093                                       struct comedi_insn *insn,
1094                                       unsigned int *data)
1095 {
1096         int ret = 0;
1097
1098         switch (data[0]) {
1099         case INSN_CONFIG_RESET:
1100                 dio200_subdev_timer_reset(dev, s);
1101                 break;
1102         case INSN_CONFIG_SET_CLOCK_SRC:
1103                 ret = dio200_subdev_timer_set_clock_src(dev, s, data[1]);
1104                 if (ret < 0)
1105                         ret = -EINVAL;
1106                 break;
1107         case INSN_CONFIG_GET_CLOCK_SRC:
1108                 dio200_subdev_timer_get_clock_src(dev, s, &data[1], &data[2]);
1109                 break;
1110         default:
1111                 ret = -EINVAL;
1112                 break;
1113         }
1114         return ret < 0 ? ret : insn->n;
1115 }
1116
1117 /*
1118  * This function initializes a timer subdevice.
1119  *
1120  * Uses the timestamp timer registers.  There is only one timestamp timer.
1121  */
1122 static int dio200_subdev_timer_init(struct comedi_device *dev,
1123                                     struct comedi_subdevice *s)
1124 {
1125         s->type = COMEDI_SUBD_TIMER;
1126         s->subdev_flags = SDF_READABLE | SDF_LSAMPL;
1127         s->n_chan = 1;
1128         s->maxdata = 0xFFFFFFFF;
1129         s->insn_read = dio200_subdev_timer_read;
1130         s->insn_config = dio200_subdev_timer_config;
1131         return 0;
1132 }
1133
1134 void amplc_dio200_set_enhance(struct comedi_device *dev, unsigned char val)
1135 {
1136         dio200_write8(dev, DIO200_ENHANCE, val);
1137 }
1138 EXPORT_SYMBOL_GPL(amplc_dio200_set_enhance);
1139
1140 int amplc_dio200_common_attach(struct comedi_device *dev, unsigned int irq,
1141                                unsigned long req_irq_flags)
1142 {
1143         const struct dio200_board *thisboard = comedi_board(dev);
1144         struct dio200_private *devpriv = dev->private;
1145         const struct dio200_layout *layout = dio200_board_layout(thisboard);
1146         struct comedi_subdevice *s;
1147         int sdx;
1148         unsigned int n;
1149         int ret;
1150
1151         devpriv->intr_sd = -1;
1152
1153         ret = comedi_alloc_subdevices(dev, layout->n_subdevs);
1154         if (ret)
1155                 return ret;
1156
1157         for (n = 0; n < dev->n_subdevices; n++) {
1158                 s = &dev->subdevices[n];
1159                 switch (layout->sdtype[n]) {
1160                 case sd_8254:
1161                         /* counter subdevice (8254) */
1162                         ret = dio200_subdev_8254_init(dev, s,
1163                                                       layout->sdinfo[n]);
1164                         if (ret < 0)
1165                                 return ret;
1166                         break;
1167                 case sd_8255:
1168                         /* digital i/o subdevice (8255) */
1169                         ret = dio200_subdev_8255_init(dev, s,
1170                                                       layout->sdinfo[n]);
1171                         if (ret < 0)
1172                                 return ret;
1173                         break;
1174                 case sd_intr:
1175                         /* 'INTERRUPT' subdevice */
1176                         if (irq) {
1177                                 ret = dio200_subdev_intr_init(dev, s,
1178                                                               DIO200_INT_SCE,
1179                                                               layout->sdinfo[n]
1180                                                              );
1181                                 if (ret < 0)
1182                                         return ret;
1183                                 devpriv->intr_sd = n;
1184                         } else {
1185                                 s->type = COMEDI_SUBD_UNUSED;
1186                         }
1187                         break;
1188                 case sd_timer:
1189                         ret = dio200_subdev_timer_init(dev, s);
1190                         if (ret < 0)
1191                                 return ret;
1192                         break;
1193                 default:
1194                         s->type = COMEDI_SUBD_UNUSED;
1195                         break;
1196                 }
1197         }
1198         sdx = devpriv->intr_sd;
1199         if (sdx >= 0 && sdx < dev->n_subdevices)
1200                 dev->read_subdev = &dev->subdevices[sdx];
1201         if (irq) {
1202                 if (request_irq(irq, dio200_interrupt, req_irq_flags,
1203                                 dev->board_name, dev) >= 0) {
1204                         dev->irq = irq;
1205                 } else {
1206                         dev_warn(dev->class_dev,
1207                                  "warning! irq %u unavailable!\n", irq);
1208                 }
1209         }
1210         dev_info(dev->class_dev, "attached\n");
1211         return 0;
1212 }
1213 EXPORT_SYMBOL_GPL(amplc_dio200_common_attach);
1214
1215 void amplc_dio200_common_detach(struct comedi_device *dev)
1216 {
1217         const struct dio200_board *thisboard = comedi_board(dev);
1218         struct dio200_private *devpriv = dev->private;
1219
1220         if (!thisboard || !devpriv)
1221                 return;
1222         if (dev->irq)
1223                 free_irq(dev->irq, dev);
1224 }
1225 EXPORT_SYMBOL_GPL(amplc_dio200_common_detach);
1226
1227 static int __init amplc_dio200_common_init(void)
1228 {
1229         return 0;
1230 }
1231 module_init(amplc_dio200_common_init);
1232
1233 static void __exit amplc_dio200_common_exit(void)
1234 {
1235 }
1236 module_exit(amplc_dio200_common_exit);
1237
1238 MODULE_AUTHOR("Comedi http://www.comedi.org");
1239 MODULE_DESCRIPTION("Comedi helper for amplc_dio200 and amplc_dio200_pci");
1240 MODULE_LICENSE("GPL");