1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98#include <linux/module.h>
99#include <linux/pci.h>
100#include <linux/delay.h>
101#include <linux/interrupt.h>
102
103#include "../comedidev.h"
104
105#include "comedi_fc.h"
106#include "plx9080.h"
107
108
109
110
111#define LAS0_USER_IO 0x0008
112#define LAS0_ADC 0x0010
113#define FS_DAC1_NOT_EMPTY (1 << 0)
114#define FS_DAC1_HEMPTY (1 << 1)
115#define FS_DAC1_NOT_FULL (1 << 2)
116#define FS_DAC2_NOT_EMPTY (1 << 4)
117#define FS_DAC2_HEMPTY (1 << 5)
118#define FS_DAC2_NOT_FULL (1 << 6)
119#define FS_ADC_NOT_EMPTY (1 << 8)
120#define FS_ADC_HEMPTY (1 << 9)
121#define FS_ADC_NOT_FULL (1 << 10)
122#define FS_DIN_NOT_EMPTY (1 << 12)
123#define FS_DIN_HEMPTY (1 << 13)
124#define FS_DIN_NOT_FULL (1 << 14)
125#define LAS0_DAC1 0x0014
126#define LAS0_DAC2 0x0018
127#define LAS0_DAC 0x0024
128#define LAS0_PACER 0x0028
129#define LAS0_TIMER 0x002c
130#define LAS0_IT 0x0030
131#define IRQM_ADC_FIFO_WRITE (1 << 0)
132#define IRQM_CGT_RESET (1 << 1)
133#define IRQM_CGT_PAUSE (1 << 3)
134#define IRQM_ADC_ABOUT_CNT (1 << 4)
135#define IRQM_ADC_DELAY_CNT (1 << 5)
136#define IRQM_ADC_SAMPLE_CNT (1 << 6)
137#define IRQM_DAC1_UCNT (1 << 7)
138#define IRQM_DAC2_UCNT (1 << 8)
139#define IRQM_UTC1 (1 << 9)
140#define IRQM_UTC1_INV (1 << 10)
141#define IRQM_UTC2 (1 << 11)
142#define IRQM_DIGITAL_IT (1 << 12)
143#define IRQM_EXTERNAL_IT (1 << 13)
144#define IRQM_ETRIG_RISING (1 << 14)
145#define IRQM_ETRIG_FALLING (1 << 15)
146#define LAS0_CLEAR 0x0034
147#define LAS0_OVERRUN 0x0038
148#define LAS0_PCLK 0x0040
149#define LAS0_BCLK 0x0044
150#define LAS0_ADC_SCNT 0x0048
151#define LAS0_DAC1_UCNT 0x004c
152#define LAS0_DAC2_UCNT 0x0050
153#define LAS0_DCNT 0x0054
154#define LAS0_ACNT 0x0058
155#define LAS0_DAC_CLK 0x005c
156#define LAS0_UTC0 0x0060
157#define LAS0_UTC1 0x0064
158#define LAS0_UTC2 0x0068
159#define LAS0_UTC_CTRL 0x006c
160#define LAS0_DIO0 0x0070
161#define LAS0_DIO1 0x0074
162#define LAS0_DIO0_CTRL 0x0078
163#define LAS0_DIO_STATUS 0x007c
164#define LAS0_BOARD_RESET 0x0100
165#define LAS0_DMA0_SRC 0x0104
166#define LAS0_DMA1_SRC 0x0108
167#define LAS0_ADC_CONVERSION 0x010c
168#define LAS0_BURST_START 0x0110
169#define LAS0_PACER_START 0x0114
170#define LAS0_PACER_STOP 0x0118
171#define LAS0_ACNT_STOP_ENABLE 0x011c
172#define LAS0_PACER_REPEAT 0x0120
173#define LAS0_DIN_START 0x0124
174#define LAS0_DIN_FIFO_CLEAR 0x0128
175#define LAS0_ADC_FIFO_CLEAR 0x012c
176#define LAS0_CGT_WRITE 0x0130
177#define LAS0_CGL_WRITE 0x0134
178#define LAS0_CG_DATA 0x0138
179#define LAS0_CGT_ENABLE 0x013c
180#define LAS0_CG_ENABLE 0x0140
181#define LAS0_CGT_PAUSE 0x0144
182#define LAS0_CGT_RESET 0x0148
183#define LAS0_CGT_CLEAR 0x014c
184#define LAS0_DAC1_CTRL 0x0150
185#define LAS0_DAC1_SRC 0x0154
186#define LAS0_DAC1_CYCLE 0x0158
187#define LAS0_DAC1_RESET 0x015c
188#define LAS0_DAC1_FIFO_CLEAR 0x0160
189#define LAS0_DAC2_CTRL 0x0164
190#define LAS0_DAC2_SRC 0x0168
191#define LAS0_DAC2_CYCLE 0x016c
192#define LAS0_DAC2_RESET 0x0170
193#define LAS0_DAC2_FIFO_CLEAR 0x0174
194#define LAS0_ADC_SCNT_SRC 0x0178
195#define LAS0_PACER_SELECT 0x0180
196#define LAS0_SBUS0_SRC 0x0184
197#define LAS0_SBUS0_ENABLE 0x0188
198#define LAS0_SBUS1_SRC 0x018c
199#define LAS0_SBUS1_ENABLE 0x0190
200#define LAS0_SBUS2_SRC 0x0198
201#define LAS0_SBUS2_ENABLE 0x019c
202#define LAS0_ETRG_POLARITY 0x01a4
203#define LAS0_EINT_POLARITY 0x01a8
204#define LAS0_UTC0_CLOCK 0x01ac
205#define LAS0_UTC0_GATE 0x01b0
206#define LAS0_UTC1_CLOCK 0x01b4
207#define LAS0_UTC1_GATE 0x01b8
208#define LAS0_UTC2_CLOCK 0x01bc
209#define LAS0_UTC2_GATE 0x01c0
210#define LAS0_UOUT0_SELECT 0x01c4
211#define LAS0_UOUT1_SELECT 0x01c8
212#define LAS0_DMA0_RESET 0x01cc
213#define LAS0_DMA1_RESET 0x01d0
214
215
216
217
218#define LAS1_ADC_FIFO 0x0000
219#define LAS1_HDIO_FIFO 0x0004
220#define LAS1_DAC1_FIFO 0x0008
221#define LAS1_DAC2_FIFO 0x000c
222
223
224
225
226
227
228
229#define DMA_CHAIN_COUNT 2
230
231
232
233
234#define TRANS_TARGET_PERIOD 10000000
235
236
237
238#define RTD_MAX_CHANLIST 128
239
240
241#ifdef FAST_SPIN
242#define WAIT_QUIETLY
243#define RTD_ADC_TIMEOUT 66000
244#define RTD_DAC_TIMEOUT 66000
245#define RTD_DMA_TIMEOUT 33000
246#else
247
248#define WAIT_QUIETLY udelay(1)
249#define RTD_ADC_TIMEOUT 2000
250#define RTD_DAC_TIMEOUT 2000
251#define RTD_DMA_TIMEOUT 1000
252#endif
253
254
255
256
257
258#define RTD_CLOCK_RATE 8000000
259#define RTD_CLOCK_BASE 125
260
261
262#define RTD_MAX_SPEED 1625
263
264#define RTD_MAX_SPEED_1 875
265
266#define RTD_MIN_SPEED 2097151875
267
268#define RTD_MIN_SPEED_1 5000000
269
270
271#define DMA_MODE_BITS (\
272 PLX_LOCAL_BUS_16_WIDE_BITS \
273 | PLX_DMA_EN_READYIN_BIT \
274 | PLX_DMA_LOCAL_BURST_EN_BIT \
275 | PLX_EN_CHAIN_BIT \
276 | PLX_DMA_INTR_PCI_BIT \
277 | PLX_LOCAL_ADDR_CONST_BIT \
278 | PLX_DEMAND_MODE_BIT)
279
280#define DMA_TRANSFER_BITS (\
281 PLX_DESC_IN_PCI_BIT \
282 | PLX_INTR_TERM_COUNT \
283 | PLX_XFER_LOCAL_TO_PCI)
284
285
286
287
288
289
290
291
292static const struct comedi_lrange rtd_ai_7520_range = {
293 18, {
294
295 BIP_RANGE(5.0),
296 BIP_RANGE(5.0 / 2),
297 BIP_RANGE(5.0 / 4),
298 BIP_RANGE(5.0 / 8),
299 BIP_RANGE(5.0 / 16),
300 BIP_RANGE(5.0 / 32),
301
302 BIP_RANGE(10.0),
303 BIP_RANGE(10.0 / 2),
304 BIP_RANGE(10.0 / 4),
305 BIP_RANGE(10.0 / 8),
306 BIP_RANGE(10.0 / 16),
307 BIP_RANGE(10.0 / 32),
308
309 UNI_RANGE(10.0),
310 UNI_RANGE(10.0 / 2),
311 UNI_RANGE(10.0 / 4),
312 UNI_RANGE(10.0 / 8),
313 UNI_RANGE(10.0 / 16),
314 UNI_RANGE(10.0 / 32),
315 }
316};
317
318
319static const struct comedi_lrange rtd_ai_4520_range = {
320 24, {
321
322 BIP_RANGE(5.0),
323 BIP_RANGE(5.0 / 2),
324 BIP_RANGE(5.0 / 4),
325 BIP_RANGE(5.0 / 8),
326 BIP_RANGE(5.0 / 16),
327 BIP_RANGE(5.0 / 32),
328 BIP_RANGE(5.0 / 64),
329 BIP_RANGE(5.0 / 128),
330
331 BIP_RANGE(10.0),
332 BIP_RANGE(10.0 / 2),
333 BIP_RANGE(10.0 / 4),
334 BIP_RANGE(10.0 / 8),
335 BIP_RANGE(10.0 / 16),
336 BIP_RANGE(10.0 / 32),
337 BIP_RANGE(10.0 / 64),
338 BIP_RANGE(10.0 / 128),
339
340 UNI_RANGE(10.0),
341 UNI_RANGE(10.0 / 2),
342 UNI_RANGE(10.0 / 4),
343 UNI_RANGE(10.0 / 8),
344 UNI_RANGE(10.0 / 16),
345 UNI_RANGE(10.0 / 32),
346 UNI_RANGE(10.0 / 64),
347 UNI_RANGE(10.0 / 128),
348 }
349};
350
351
352static const struct comedi_lrange rtd_ao_range = {
353 4, {
354 UNI_RANGE(5),
355 UNI_RANGE(10),
356 BIP_RANGE(5),
357 BIP_RANGE(10),
358 }
359};
360
361enum rtd_boardid {
362 BOARD_DM7520,
363 BOARD_PCI4520,
364};
365
366struct rtd_boardinfo {
367 const char *name;
368 int range_bip10;
369 int range_uni10;
370 const struct comedi_lrange *ai_range;
371};
372
373static const struct rtd_boardinfo rtd520Boards[] = {
374 [BOARD_DM7520] = {
375 .name = "DM7520",
376 .range_bip10 = 6,
377 .range_uni10 = 12,
378 .ai_range = &rtd_ai_7520_range,
379 },
380 [BOARD_PCI4520] = {
381 .name = "PCI4520",
382 .range_bip10 = 8,
383 .range_uni10 = 16,
384 .ai_range = &rtd_ai_4520_range,
385 },
386};
387
388struct rtd_private {
389
390 void __iomem *las0;
391 void __iomem *las1;
392 void __iomem *lcfg;
393
394 long ai_count;
395 int xfer_count;
396 int flags;
397
398 unsigned char chan_is_bipolar[RTD_MAX_CHANLIST / 8];
399
400 unsigned int ao_readback[2];
401
402 unsigned fifosz;
403};
404
405
406#define SEND_EOS 0x01
407#define DMA0_ACTIVE 0x02
408#define DMA1_ACTIVE 0x04
409
410
411#define CHAN_ARRAY_TEST(array, index) \
412 (((array)[(index)/8] >> ((index) & 0x7)) & 0x1)
413#define CHAN_ARRAY_SET(array, index) \
414 (((array)[(index)/8] |= 1 << ((index) & 0x7)))
415#define CHAN_ARRAY_CLEAR(array, index) \
416 (((array)[(index)/8] &= ~(1 << ((index) & 0x7))))
417
418
419
420
421
422
423
424static int rtd_ns_to_timer_base(unsigned int *nanosec,
425 int round_mode, int base)
426{
427 int divider;
428
429 switch (round_mode) {
430 case TRIG_ROUND_NEAREST:
431 default:
432 divider = (*nanosec + base / 2) / base;
433 break;
434 case TRIG_ROUND_DOWN:
435 divider = (*nanosec) / base;
436 break;
437 case TRIG_ROUND_UP:
438 divider = (*nanosec + base - 1) / base;
439 break;
440 }
441 if (divider < 2)
442 divider = 2;
443
444
445
446
447 *nanosec = base * divider;
448 return divider - 1;
449}
450
451
452
453
454
455
456static int rtd_ns_to_timer(unsigned int *ns, int round_mode)
457{
458 return rtd_ns_to_timer_base(ns, round_mode, RTD_CLOCK_BASE);
459}
460
461
462
463
464static unsigned short rtd_convert_chan_gain(struct comedi_device *dev,
465 unsigned int chanspec, int index)
466{
467 const struct rtd_boardinfo *board = comedi_board(dev);
468 struct rtd_private *devpriv = dev->private;
469 unsigned int chan = CR_CHAN(chanspec);
470 unsigned int range = CR_RANGE(chanspec);
471 unsigned int aref = CR_AREF(chanspec);
472 unsigned short r = 0;
473
474 r |= chan & 0xf;
475
476
477 if (range < board->range_bip10) {
478
479 r |= 0x000;
480 r |= (range & 0x7) << 4;
481 CHAN_ARRAY_SET(devpriv->chan_is_bipolar, index);
482 } else if (range < board->range_uni10) {
483
484 r |= 0x100;
485 r |= ((range - board->range_bip10) & 0x7) << 4;
486 CHAN_ARRAY_SET(devpriv->chan_is_bipolar, index);
487 } else {
488
489 r |= 0x200;
490 r |= ((range - board->range_uni10) & 0x7) << 4;
491 CHAN_ARRAY_CLEAR(devpriv->chan_is_bipolar, index);
492 }
493
494 switch (aref) {
495 case AREF_GROUND:
496 break;
497
498 case AREF_COMMON:
499 r |= 0x80;
500 break;
501
502 case AREF_DIFF:
503 r |= 0x400;
504 break;
505
506 case AREF_OTHER:
507 break;
508 }
509
510
511 return r;
512}
513
514
515
516
517static void rtd_load_channelgain_list(struct comedi_device *dev,
518 unsigned int n_chan, unsigned int *list)
519{
520 struct rtd_private *devpriv = dev->private;
521
522 if (n_chan > 1) {
523 int ii;
524
525 writel(0, devpriv->las0 + LAS0_CGT_CLEAR);
526 writel(1, devpriv->las0 + LAS0_CGT_ENABLE);
527 for (ii = 0; ii < n_chan; ii++) {
528 writel(rtd_convert_chan_gain(dev, list[ii], ii),
529 devpriv->las0 + LAS0_CGT_WRITE);
530 }
531 } else {
532 writel(0, devpriv->las0 + LAS0_CGT_ENABLE);
533 writel(rtd_convert_chan_gain(dev, list[0], 0),
534 devpriv->las0 + LAS0_CGL_WRITE);
535 }
536}
537
538
539
540static int rtd520_probe_fifo_depth(struct comedi_device *dev)
541{
542 struct rtd_private *devpriv = dev->private;
543 unsigned int chanspec = CR_PACK(0, 0, AREF_GROUND);
544 unsigned i;
545 static const unsigned limit = 0x2000;
546 unsigned fifo_size = 0;
547
548 writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
549 rtd_load_channelgain_list(dev, 1, &chanspec);
550
551 writel(0, devpriv->las0 + LAS0_ADC_CONVERSION);
552
553 for (i = 0; i < limit; ++i) {
554 unsigned fifo_status;
555
556 writew(0, devpriv->las0 + LAS0_ADC);
557 udelay(1);
558 fifo_status = readl(devpriv->las0 + LAS0_ADC);
559 if ((fifo_status & FS_ADC_HEMPTY) == 0) {
560 fifo_size = 2 * i;
561 break;
562 }
563 }
564 if (i == limit) {
565 dev_info(dev->class_dev, "failed to probe fifo size.\n");
566 return -EIO;
567 }
568 writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
569 if (fifo_size != 0x400 && fifo_size != 0x2000) {
570 dev_info(dev->class_dev,
571 "unexpected fifo size of %i, expected 1024 or 8192.\n",
572 fifo_size);
573 return -EIO;
574 }
575 return fifo_size;
576}
577
578
579
580
581
582
583
584
585
586static int rtd_ai_rinsn(struct comedi_device *dev,
587 struct comedi_subdevice *s, struct comedi_insn *insn,
588 unsigned int *data)
589{
590 struct rtd_private *devpriv = dev->private;
591 int n, ii;
592 int stat;
593
594
595 writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
596
597
598 rtd_load_channelgain_list(dev, 1, &insn->chanspec);
599
600
601 writel(0, devpriv->las0 + LAS0_ADC_CONVERSION);
602
603
604 for (n = 0; n < insn->n; n++) {
605 s16 d;
606
607 writew(0, devpriv->las0 + LAS0_ADC);
608
609 for (ii = 0; ii < RTD_ADC_TIMEOUT; ++ii) {
610 stat = readl(devpriv->las0 + LAS0_ADC);
611 if (stat & FS_ADC_NOT_EMPTY)
612 break;
613 WAIT_QUIETLY;
614 }
615 if (ii >= RTD_ADC_TIMEOUT)
616 return -ETIMEDOUT;
617
618
619 d = readw(devpriv->las1 + LAS1_ADC_FIFO);
620
621 d = d >> 3;
622 if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar, 0))
623
624 data[n] = d + 2048;
625 else
626 data[n] = d;
627 }
628
629
630 return n;
631}
632
633
634
635
636
637
638
639static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s,
640 int count)
641{
642 struct rtd_private *devpriv = dev->private;
643 int ii;
644
645 for (ii = 0; ii < count; ii++) {
646 short sample;
647 s16 d;
648
649 if (0 == devpriv->ai_count) {
650 d = readw(devpriv->las1 + LAS1_ADC_FIFO);
651 continue;
652 }
653
654 d = readw(devpriv->las1 + LAS1_ADC_FIFO);
655 d = d >> 3;
656 if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar,
657 s->async->cur_chan)) {
658
659 sample = d + 2048;
660 } else
661 sample = d;
662
663 if (!comedi_buf_put(s->async, sample))
664 return -1;
665
666 if (devpriv->ai_count > 0)
667 devpriv->ai_count--;
668 }
669 return 0;
670}
671
672
673
674
675static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s)
676{
677 struct rtd_private *devpriv = dev->private;
678
679 while (readl(devpriv->las0 + LAS0_ADC) & FS_ADC_NOT_EMPTY) {
680 short sample;
681 s16 d = readw(devpriv->las1 + LAS1_ADC_FIFO);
682
683 if (0 == devpriv->ai_count) {
684 continue;
685 }
686
687 d = d >> 3;
688 if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar,
689 s->async->cur_chan)) {
690
691 sample = d + 2048;
692 } else
693 sample = d;
694
695 if (!comedi_buf_put(s->async, sample))
696 return -1;
697
698 if (devpriv->ai_count > 0)
699 devpriv->ai_count--;
700 }
701 return 0;
702}
703
704
705
706
707
708
709
710static irqreturn_t rtd_interrupt(int irq, void *d)
711{
712 struct comedi_device *dev = d;
713 struct comedi_subdevice *s = &dev->subdevices[0];
714 struct rtd_private *devpriv = dev->private;
715 u32 overrun;
716 u16 status;
717 u16 fifo_status;
718
719 if (!dev->attached)
720 return IRQ_NONE;
721
722 fifo_status = readl(devpriv->las0 + LAS0_ADC);
723
724 if (!(fifo_status & FS_ADC_NOT_FULL))
725 goto xfer_abort;
726
727 status = readw(devpriv->las0 + LAS0_IT);
728
729 if (0 == status)
730 return IRQ_HANDLED;
731
732 if (status & IRQM_ADC_ABOUT_CNT) {
733
734
735
736
737
738
739 if (!(fifo_status & FS_ADC_HEMPTY)) {
740
741 if (ai_read_n(dev, s, devpriv->fifosz / 2) < 0)
742 goto xfer_abort;
743
744 if (0 == devpriv->ai_count)
745 goto xfer_done;
746
747 comedi_event(dev, s);
748 } else if (devpriv->xfer_count > 0) {
749 if (fifo_status & FS_ADC_NOT_EMPTY) {
750
751 if (ai_read_n(dev, s, devpriv->xfer_count) < 0)
752 goto xfer_abort;
753
754 if (0 == devpriv->ai_count)
755 goto xfer_done;
756
757 comedi_event(dev, s);
758 }
759 }
760 }
761
762 overrun = readl(devpriv->las0 + LAS0_OVERRUN) & 0xffff;
763 if (overrun)
764 goto xfer_abort;
765
766
767 writew(status, devpriv->las0 + LAS0_CLEAR);
768 readw(devpriv->las0 + LAS0_CLEAR);
769 return IRQ_HANDLED;
770
771xfer_abort:
772 writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
773 s->async->events |= COMEDI_CB_ERROR;
774 devpriv->ai_count = 0;
775
776
777xfer_done:
778
779 writel(0, devpriv->las0 + LAS0_PACER_STOP);
780 writel(0, devpriv->las0 + LAS0_PACER);
781 writel(0, devpriv->las0 + LAS0_ADC_CONVERSION);
782 writew(0, devpriv->las0 + LAS0_IT);
783
784 if (devpriv->ai_count > 0) {
785 fifo_status = readl(devpriv->las0 + LAS0_ADC);
786 ai_read_dregs(dev, s);
787 }
788
789 s->async->events |= COMEDI_CB_EOA;
790 comedi_event(dev, s);
791
792
793 status = readw(devpriv->las0 + LAS0_IT);
794 writew(status, devpriv->las0 + LAS0_CLEAR);
795 readw(devpriv->las0 + LAS0_CLEAR);
796
797 fifo_status = readl(devpriv->las0 + LAS0_ADC);
798 overrun = readl(devpriv->las0 + LAS0_OVERRUN) & 0xffff;
799
800 return IRQ_HANDLED;
801}
802
803
804
805
806
807
808
809
810
811
812static int rtd_ai_cmdtest(struct comedi_device *dev,
813 struct comedi_subdevice *s, struct comedi_cmd *cmd)
814{
815 int err = 0;
816 int tmp;
817
818
819
820 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
821 err |= cfc_check_trigger_src(&cmd->scan_begin_src,
822 TRIG_TIMER | TRIG_EXT);
823 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
824 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
825 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
826
827 if (err)
828 return 1;
829
830
831
832 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
833 err |= cfc_check_trigger_is_unique(cmd->convert_src);
834 err |= cfc_check_trigger_is_unique(cmd->stop_src);
835
836
837
838 if (err)
839 return 2;
840
841
842
843 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
844
845 if (cmd->scan_begin_src == TRIG_TIMER) {
846
847 if (1 == cmd->chanlist_len) {
848 if (cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
849 RTD_MAX_SPEED_1)) {
850 rtd_ns_to_timer(&cmd->scan_begin_arg,
851 TRIG_ROUND_UP);
852 err |= -EINVAL;
853 }
854 if (cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
855 RTD_MIN_SPEED_1)) {
856 rtd_ns_to_timer(&cmd->scan_begin_arg,
857 TRIG_ROUND_DOWN);
858 err |= -EINVAL;
859 }
860 } else {
861 if (cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
862 RTD_MAX_SPEED)) {
863 rtd_ns_to_timer(&cmd->scan_begin_arg,
864 TRIG_ROUND_UP);
865 err |= -EINVAL;
866 }
867 if (cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
868 RTD_MIN_SPEED)) {
869 rtd_ns_to_timer(&cmd->scan_begin_arg,
870 TRIG_ROUND_DOWN);
871 err |= -EINVAL;
872 }
873 }
874 } else {
875
876
877
878 err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9);
879 }
880
881 if (cmd->convert_src == TRIG_TIMER) {
882 if (1 == cmd->chanlist_len) {
883 if (cfc_check_trigger_arg_min(&cmd->convert_arg,
884 RTD_MAX_SPEED_1)) {
885 rtd_ns_to_timer(&cmd->convert_arg,
886 TRIG_ROUND_UP);
887 err |= -EINVAL;
888 }
889 if (cfc_check_trigger_arg_max(&cmd->convert_arg,
890 RTD_MIN_SPEED_1)) {
891 rtd_ns_to_timer(&cmd->convert_arg,
892 TRIG_ROUND_DOWN);
893 err |= -EINVAL;
894 }
895 } else {
896 if (cfc_check_trigger_arg_min(&cmd->convert_arg,
897 RTD_MAX_SPEED)) {
898 rtd_ns_to_timer(&cmd->convert_arg,
899 TRIG_ROUND_UP);
900 err |= -EINVAL;
901 }
902 if (cfc_check_trigger_arg_max(&cmd->convert_arg,
903 RTD_MIN_SPEED)) {
904 rtd_ns_to_timer(&cmd->convert_arg,
905 TRIG_ROUND_DOWN);
906 err |= -EINVAL;
907 }
908 }
909 } else {
910
911
912 err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 9);
913 }
914
915 if (cmd->stop_src == TRIG_COUNT) {
916
917 } else {
918
919 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
920 }
921
922 if (err)
923 return 3;
924
925
926
927
928 if (cmd->chanlist_len > RTD_MAX_CHANLIST) {
929 cmd->chanlist_len = RTD_MAX_CHANLIST;
930 err++;
931 }
932 if (cmd->scan_begin_src == TRIG_TIMER) {
933 tmp = cmd->scan_begin_arg;
934 rtd_ns_to_timer(&cmd->scan_begin_arg,
935 cmd->flags & TRIG_ROUND_MASK);
936 if (tmp != cmd->scan_begin_arg)
937 err++;
938
939 }
940 if (cmd->convert_src == TRIG_TIMER) {
941 tmp = cmd->convert_arg;
942 rtd_ns_to_timer(&cmd->convert_arg,
943 cmd->flags & TRIG_ROUND_MASK);
944 if (tmp != cmd->convert_arg)
945 err++;
946
947 if (cmd->scan_begin_src == TRIG_TIMER
948 && (cmd->scan_begin_arg
949 < (cmd->convert_arg * cmd->scan_end_arg))) {
950 cmd->scan_begin_arg =
951 cmd->convert_arg * cmd->scan_end_arg;
952 err++;
953 }
954 }
955
956 if (err)
957 return 4;
958
959 return 0;
960}
961
962
963
964
965
966
967
968static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
969{
970 struct rtd_private *devpriv = dev->private;
971 struct comedi_cmd *cmd = &s->async->cmd;
972 int timer;
973
974
975
976 writel(0, devpriv->las0 + LAS0_PACER_STOP);
977 writel(0, devpriv->las0 + LAS0_PACER);
978 writel(0, devpriv->las0 + LAS0_ADC_CONVERSION);
979 writew(0, devpriv->las0 + LAS0_IT);
980 writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
981 writel(0, devpriv->las0 + LAS0_OVERRUN);
982
983
984
985 rtd_load_channelgain_list(dev, cmd->chanlist_len, cmd->chanlist);
986
987
988 if (cmd->chanlist_len > 1) {
989
990 writel(0, devpriv->las0 + LAS0_PACER_START);
991
992 writel(1, devpriv->las0 + LAS0_BURST_START);
993
994 writel(2, devpriv->las0 + LAS0_ADC_CONVERSION);
995 } else {
996
997 writel(0, devpriv->las0 + LAS0_PACER_START);
998
999 writel(1, devpriv->las0 + LAS0_ADC_CONVERSION);
1000 }
1001 writel((devpriv->fifosz / 2 - 1) & 0xffff, devpriv->las0 + LAS0_ACNT);
1002
1003 if (TRIG_TIMER == cmd->scan_begin_src) {
1004
1005
1006 if (cmd->flags & TRIG_WAKE_EOS) {
1007
1008
1009
1010
1011
1012 devpriv->xfer_count = cmd->chanlist_len;
1013 devpriv->flags |= SEND_EOS;
1014 } else {
1015
1016 devpriv->xfer_count =
1017 (TRANS_TARGET_PERIOD * cmd->chanlist_len) /
1018 cmd->scan_begin_arg;
1019 if (devpriv->xfer_count < cmd->chanlist_len) {
1020
1021 devpriv->xfer_count = cmd->chanlist_len;
1022 } else {
1023 devpriv->xfer_count =
1024 (devpriv->xfer_count +
1025 cmd->chanlist_len - 1)
1026 / cmd->chanlist_len;
1027 devpriv->xfer_count *= cmd->chanlist_len;
1028 }
1029 devpriv->flags |= SEND_EOS;
1030 }
1031 if (devpriv->xfer_count >= (devpriv->fifosz / 2)) {
1032
1033 devpriv->xfer_count = 0;
1034 devpriv->flags &= ~SEND_EOS;
1035 } else {
1036
1037 writel((devpriv->xfer_count - 1) & 0xffff,
1038 devpriv->las0 + LAS0_ACNT);
1039 }
1040 } else {
1041 devpriv->xfer_count = 0;
1042 devpriv->flags &= ~SEND_EOS;
1043 }
1044
1045 writel(1, devpriv->las0 + LAS0_PACER_SELECT);
1046
1047 writel(1, devpriv->las0 + LAS0_ACNT_STOP_ENABLE);
1048
1049
1050
1051
1052 switch (cmd->stop_src) {
1053 case TRIG_COUNT:
1054 devpriv->ai_count = cmd->stop_arg * cmd->chanlist_len;
1055 if ((devpriv->xfer_count > 0)
1056 && (devpriv->xfer_count > devpriv->ai_count)) {
1057 devpriv->xfer_count = devpriv->ai_count;
1058 }
1059 break;
1060
1061 case TRIG_NONE:
1062 devpriv->ai_count = -1;
1063 break;
1064 }
1065
1066
1067 switch (cmd->scan_begin_src) {
1068 case TRIG_TIMER:
1069 timer = rtd_ns_to_timer(&cmd->scan_begin_arg,
1070 TRIG_ROUND_NEAREST);
1071
1072 writel(timer & 0xffffff, devpriv->las0 + LAS0_PCLK);
1073
1074 break;
1075
1076 case TRIG_EXT:
1077
1078 writel(1, devpriv->las0 + LAS0_PACER_START);
1079 break;
1080 }
1081
1082
1083 switch (cmd->convert_src) {
1084 case TRIG_TIMER:
1085 if (cmd->chanlist_len > 1) {
1086
1087 timer = rtd_ns_to_timer(&cmd->convert_arg,
1088 TRIG_ROUND_NEAREST);
1089
1090 writel(timer & 0x3ff, devpriv->las0 + LAS0_BCLK);
1091 }
1092
1093 break;
1094
1095 case TRIG_EXT:
1096
1097 writel(2, devpriv->las0 + LAS0_BURST_START);
1098 break;
1099 }
1100
1101
1102
1103
1104 writew(~0, devpriv->las0 + LAS0_CLEAR);
1105 readw(devpriv->las0 + LAS0_CLEAR);
1106
1107
1108 if (devpriv->xfer_count > 0) {
1109 writew(IRQM_ADC_ABOUT_CNT, devpriv->las0 + LAS0_IT);
1110 } else {
1111 writew(IRQM_ADC_ABOUT_CNT, devpriv->las0 + LAS0_IT);
1112 }
1113
1114
1115
1116 readl(devpriv->las0 + LAS0_PACER);
1117 return 0;
1118}
1119
1120
1121
1122
1123static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
1124{
1125 struct rtd_private *devpriv = dev->private;
1126 u32 overrun;
1127 u16 status;
1128
1129
1130 writel(0, devpriv->las0 + LAS0_PACER_STOP);
1131 writel(0, devpriv->las0 + LAS0_PACER);
1132 writel(0, devpriv->las0 + LAS0_ADC_CONVERSION);
1133 writew(0, devpriv->las0 + LAS0_IT);
1134 devpriv->ai_count = 0;
1135 status = readw(devpriv->las0 + LAS0_IT);
1136 overrun = readl(devpriv->las0 + LAS0_OVERRUN) & 0xffff;
1137 return 0;
1138}
1139
1140
1141
1142
1143static int rtd_ao_winsn(struct comedi_device *dev,
1144 struct comedi_subdevice *s, struct comedi_insn *insn,
1145 unsigned int *data)
1146{
1147 struct rtd_private *devpriv = dev->private;
1148 int i;
1149 int chan = CR_CHAN(insn->chanspec);
1150 int range = CR_RANGE(insn->chanspec);
1151
1152
1153 writew(range & 7, devpriv->las0 +
1154 ((chan == 0) ? LAS0_DAC1_CTRL : LAS0_DAC2_CTRL));
1155
1156
1157
1158 for (i = 0; i < insn->n; ++i) {
1159 int val = data[i] << 3;
1160 int stat = 0;
1161 int ii;
1162
1163
1164
1165 if ((range > 1)
1166 && (data[i] < 2048)) {
1167
1168 val = (((int)data[i]) - 2048) << 3;
1169 } else {
1170 val = data[i] << 3;
1171 }
1172
1173
1174 writew(val, devpriv->las1 +
1175 ((chan == 0) ? LAS1_DAC1_FIFO : LAS1_DAC2_FIFO));
1176 writew(0, devpriv->las0 +
1177 ((chan == 0) ? LAS0_DAC1 : LAS0_DAC2));
1178
1179 devpriv->ao_readback[chan] = data[i];
1180
1181 for (ii = 0; ii < RTD_DAC_TIMEOUT; ++ii) {
1182 stat = readl(devpriv->las0 + LAS0_ADC);
1183
1184 if (stat & ((0 == chan) ? FS_DAC1_NOT_EMPTY :
1185 FS_DAC2_NOT_EMPTY))
1186 break;
1187 WAIT_QUIETLY;
1188 }
1189 if (ii >= RTD_DAC_TIMEOUT)
1190 return -ETIMEDOUT;
1191 }
1192
1193
1194 return i;
1195}
1196
1197
1198
1199static int rtd_ao_rinsn(struct comedi_device *dev,
1200 struct comedi_subdevice *s, struct comedi_insn *insn,
1201 unsigned int *data)
1202{
1203 struct rtd_private *devpriv = dev->private;
1204 int i;
1205 int chan = CR_CHAN(insn->chanspec);
1206
1207 for (i = 0; i < insn->n; i++)
1208 data[i] = devpriv->ao_readback[chan];
1209
1210
1211 return i;
1212}
1213
1214static int rtd_dio_insn_bits(struct comedi_device *dev,
1215 struct comedi_subdevice *s,
1216 struct comedi_insn *insn,
1217 unsigned int *data)
1218{
1219 struct rtd_private *devpriv = dev->private;
1220 unsigned int mask = data[0];
1221 unsigned int bits = data[1];
1222
1223 if (mask) {
1224 s->state &= ~mask;
1225 s->state |= (bits & mask);
1226
1227 writew(s->state & 0xff, devpriv->las0 + LAS0_DIO0);
1228 }
1229
1230 data[1] = readw(devpriv->las0 + LAS0_DIO0) & 0xff;
1231
1232 return insn->n;
1233}
1234
1235static int rtd_dio_insn_config(struct comedi_device *dev,
1236 struct comedi_subdevice *s,
1237 struct comedi_insn *insn,
1238 unsigned int *data)
1239{
1240 struct rtd_private *devpriv = dev->private;
1241 int ret;
1242
1243 ret = comedi_dio_insn_config(dev, s, insn, data, 0);
1244 if (ret)
1245 return ret;
1246
1247
1248
1249
1250 writew(0x01, devpriv->las0 + LAS0_DIO_STATUS);
1251 writew(s->io_bits & 0xff, devpriv->las0 + LAS0_DIO0_CTRL);
1252
1253
1254 writew(0x00, devpriv->las0 + LAS0_DIO_STATUS);
1255
1256
1257
1258
1259
1260 return insn->n;
1261}
1262
1263static void rtd_reset(struct comedi_device *dev)
1264{
1265 struct rtd_private *devpriv = dev->private;
1266
1267 writel(0, devpriv->las0 + LAS0_BOARD_RESET);
1268 udelay(100);
1269 writel(0, devpriv->lcfg + PLX_INTRCS_REG);
1270 writew(0, devpriv->las0 + LAS0_IT);
1271 writew(~0, devpriv->las0 + LAS0_CLEAR);
1272 readw(devpriv->las0 + LAS0_CLEAR);
1273}
1274
1275
1276
1277
1278
1279static void rtd_init_board(struct comedi_device *dev)
1280{
1281 struct rtd_private *devpriv = dev->private;
1282
1283 rtd_reset(dev);
1284
1285 writel(0, devpriv->las0 + LAS0_OVERRUN);
1286 writel(0, devpriv->las0 + LAS0_CGT_CLEAR);
1287 writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
1288 writel(0, devpriv->las0 + LAS0_DAC1_RESET);
1289 writel(0, devpriv->las0 + LAS0_DAC2_RESET);
1290
1291 writew(0, devpriv->las0 + LAS0_DIO_STATUS);
1292 writeb((0 << 6) | 0x30, devpriv->las0 + LAS0_UTC_CTRL);
1293 writeb((1 << 6) | 0x30, devpriv->las0 + LAS0_UTC_CTRL);
1294 writeb((2 << 6) | 0x30, devpriv->las0 + LAS0_UTC_CTRL);
1295 writeb((3 << 6) | 0x00, devpriv->las0 + LAS0_UTC_CTRL);
1296
1297}
1298
1299
1300static void rtd_pci_latency_quirk(struct comedi_device *dev,
1301 struct pci_dev *pcidev)
1302{
1303 unsigned char pci_latency;
1304
1305 pci_read_config_byte(pcidev, PCI_LATENCY_TIMER, &pci_latency);
1306 if (pci_latency < 32) {
1307 dev_info(dev->class_dev,
1308 "PCI latency changed from %d to %d\n",
1309 pci_latency, 32);
1310 pci_write_config_byte(pcidev, PCI_LATENCY_TIMER, 32);
1311 }
1312}
1313
1314static int rtd_auto_attach(struct comedi_device *dev,
1315 unsigned long context)
1316{
1317 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1318 const struct rtd_boardinfo *board = NULL;
1319 struct rtd_private *devpriv;
1320 struct comedi_subdevice *s;
1321 int ret;
1322
1323 if (context < ARRAY_SIZE(rtd520Boards))
1324 board = &rtd520Boards[context];
1325 if (!board)
1326 return -ENODEV;
1327 dev->board_ptr = board;
1328 dev->board_name = board->name;
1329
1330 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1331 if (!devpriv)
1332 return -ENOMEM;
1333
1334 ret = comedi_pci_enable(dev);
1335 if (ret)
1336 return ret;
1337
1338 devpriv->las0 = pci_ioremap_bar(pcidev, 2);
1339 devpriv->las1 = pci_ioremap_bar(pcidev, 3);
1340 devpriv->lcfg = pci_ioremap_bar(pcidev, 0);
1341 if (!devpriv->las0 || !devpriv->las1 || !devpriv->lcfg)
1342 return -ENOMEM;
1343
1344 rtd_pci_latency_quirk(dev, pcidev);
1345
1346 if (pcidev->irq) {
1347 ret = request_irq(pcidev->irq, rtd_interrupt, IRQF_SHARED,
1348 dev->board_name, dev);
1349 if (ret == 0)
1350 dev->irq = pcidev->irq;
1351 }
1352
1353 ret = comedi_alloc_subdevices(dev, 4);
1354 if (ret)
1355 return ret;
1356
1357 s = &dev->subdevices[0];
1358
1359 s->type = COMEDI_SUBD_AI;
1360 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF;
1361 s->n_chan = 16;
1362 s->maxdata = 0x0fff;
1363 s->range_table = board->ai_range;
1364 s->len_chanlist = RTD_MAX_CHANLIST;
1365 s->insn_read = rtd_ai_rinsn;
1366 if (dev->irq) {
1367 dev->read_subdev = s;
1368 s->subdev_flags |= SDF_CMD_READ;
1369 s->do_cmd = rtd_ai_cmd;
1370 s->do_cmdtest = rtd_ai_cmdtest;
1371 s->cancel = rtd_ai_cancel;
1372 }
1373
1374 s = &dev->subdevices[1];
1375
1376 s->type = COMEDI_SUBD_AO;
1377 s->subdev_flags = SDF_WRITABLE;
1378 s->n_chan = 2;
1379 s->maxdata = 0x0fff;
1380 s->range_table = &rtd_ao_range;
1381 s->insn_write = rtd_ao_winsn;
1382 s->insn_read = rtd_ao_rinsn;
1383
1384 s = &dev->subdevices[2];
1385
1386 s->type = COMEDI_SUBD_DIO;
1387 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1388
1389 s->n_chan = 8;
1390 s->maxdata = 1;
1391 s->range_table = &range_digital;
1392 s->insn_bits = rtd_dio_insn_bits;
1393 s->insn_config = rtd_dio_insn_config;
1394
1395
1396 s = &dev->subdevices[3];
1397 s->type = COMEDI_SUBD_COUNTER;
1398 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1399 s->n_chan = 3;
1400 s->maxdata = 0xffff;
1401
1402 rtd_init_board(dev);
1403
1404 ret = rtd520_probe_fifo_depth(dev);
1405 if (ret < 0)
1406 return ret;
1407 devpriv->fifosz = ret;
1408
1409 if (dev->irq)
1410 writel(ICS_PIE | ICS_PLIE, devpriv->lcfg + PLX_INTRCS_REG);
1411
1412 dev_info(dev->class_dev, "%s attached\n", dev->board_name);
1413
1414 return 0;
1415}
1416
1417static void rtd_detach(struct comedi_device *dev)
1418{
1419 struct rtd_private *devpriv = dev->private;
1420
1421 if (devpriv) {
1422
1423 if (devpriv->las0 && devpriv->lcfg)
1424 rtd_reset(dev);
1425 if (dev->irq) {
1426 writel(readl(devpriv->lcfg + PLX_INTRCS_REG) &
1427 ~(ICS_PLIE | ICS_DMA0_E | ICS_DMA1_E),
1428 devpriv->lcfg + PLX_INTRCS_REG);
1429 free_irq(dev->irq, dev);
1430 }
1431 if (devpriv->las0)
1432 iounmap(devpriv->las0);
1433 if (devpriv->las1)
1434 iounmap(devpriv->las1);
1435 if (devpriv->lcfg)
1436 iounmap(devpriv->lcfg);
1437 }
1438 comedi_pci_disable(dev);
1439}
1440
1441static struct comedi_driver rtd520_driver = {
1442 .driver_name = "rtd520",
1443 .module = THIS_MODULE,
1444 .auto_attach = rtd_auto_attach,
1445 .detach = rtd_detach,
1446};
1447
1448static int rtd520_pci_probe(struct pci_dev *dev,
1449 const struct pci_device_id *id)
1450{
1451 return comedi_pci_auto_config(dev, &rtd520_driver, id->driver_data);
1452}
1453
1454static DEFINE_PCI_DEVICE_TABLE(rtd520_pci_table) = {
1455 { PCI_VDEVICE(RTD, 0x7520), BOARD_DM7520 },
1456 { PCI_VDEVICE(RTD, 0x4520), BOARD_PCI4520 },
1457 { 0 }
1458};
1459MODULE_DEVICE_TABLE(pci, rtd520_pci_table);
1460
1461static struct pci_driver rtd520_pci_driver = {
1462 .name = "rtd520",
1463 .id_table = rtd520_pci_table,
1464 .probe = rtd520_pci_probe,
1465 .remove = comedi_pci_auto_unconfig,
1466};
1467module_comedi_pci_driver(rtd520_driver, rtd520_pci_driver);
1468
1469MODULE_AUTHOR("Comedi http://www.comedi.org");
1470MODULE_DESCRIPTION("Comedi low-level driver");
1471MODULE_LICENSE("GPL");
1472