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