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