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#include <linux/module.h>
63#include <linux/delay.h>
64#include <linux/interrupt.h>
65#include <linux/kernel.h>
66#include <linux/types.h>
67
68#include "../comedi_pci.h"
69
70#include "s626.h"
71
72struct s626_buffer_dma {
73 dma_addr_t physical_base;
74 void *logical_base;
75};
76
77struct s626_private {
78 uint8_t ai_cmd_running;
79 unsigned int ai_sample_timer;
80
81 int ai_convert_count;
82 unsigned int ai_convert_timer;
83
84 uint16_t counter_int_enabs;
85
86 uint8_t adc_items;
87 struct s626_buffer_dma rps_buf;
88
89 struct s626_buffer_dma ana_buf;
90
91 uint32_t *dac_wbuf;
92
93 uint16_t dacpol;
94 uint8_t trim_setpoint[12];
95 uint32_t i2c_adrs;
96
97};
98
99
100#define S626_INDXMASK(C) (1 << (((C) > 2) ? ((C) * 2 - 1) : ((C) * 2 + 4)))
101#define S626_OVERMASK(C) (1 << (((C) > 2) ? ((C) * 2 + 5) : ((C) * 2 + 10)))
102
103
104
105
106
107static void s626_mc_enable(struct comedi_device *dev,
108 unsigned int cmd, unsigned int reg)
109{
110 unsigned int val = (cmd << 16) | cmd;
111
112 mmiowb();
113 writel(val, dev->mmio + reg);
114}
115
116static void s626_mc_disable(struct comedi_device *dev,
117 unsigned int cmd, unsigned int reg)
118{
119 writel(cmd << 16, dev->mmio + reg);
120 mmiowb();
121}
122
123static bool s626_mc_test(struct comedi_device *dev,
124 unsigned int cmd, unsigned int reg)
125{
126 unsigned int val;
127
128 val = readl(dev->mmio + reg);
129
130 return (val & cmd) ? true : false;
131}
132
133#define S626_BUGFIX_STREG(REGADRS) ((REGADRS) - 4)
134
135
136#define S626_VECTPORT(VECTNUM) (S626_P_TSL2 + ((VECTNUM) << 2))
137
138static const struct comedi_lrange s626_range_table = {
139 2, {
140 BIP_RANGE(5),
141 BIP_RANGE(10)
142 }
143};
144
145
146
147
148static void s626_debi_transfer(struct comedi_device *dev)
149{
150 static const int timeout = 10000;
151 int i;
152
153
154 s626_mc_enable(dev, S626_MC2_UPLD_DEBI, S626_P_MC2);
155
156
157
158
159
160 for (i = 0; i < timeout; i++) {
161 if (s626_mc_test(dev, S626_MC2_UPLD_DEBI, S626_P_MC2))
162 break;
163 udelay(1);
164 }
165 if (i == timeout)
166 dev_err(dev->class_dev,
167 "Timeout while uploading to DEBI control register\n");
168
169
170 for (i = 0; i < timeout; i++) {
171 if (!(readl(dev->mmio + S626_P_PSR) & S626_PSR_DEBI_S))
172 break;
173 udelay(1);
174 }
175 if (i == timeout)
176 dev_err(dev->class_dev, "DEBI transfer timeout\n");
177}
178
179
180
181
182static uint16_t s626_debi_read(struct comedi_device *dev, uint16_t addr)
183{
184
185 writel(S626_DEBI_CMD_RDWORD | addr, dev->mmio + S626_P_DEBICMD);
186
187
188 s626_debi_transfer(dev);
189
190 return readl(dev->mmio + S626_P_DEBIAD);
191}
192
193
194
195
196static void s626_debi_write(struct comedi_device *dev, uint16_t addr,
197 uint16_t wdata)
198{
199
200 writel(S626_DEBI_CMD_WRWORD | addr, dev->mmio + S626_P_DEBICMD);
201 writel(wdata, dev->mmio + S626_P_DEBIAD);
202
203
204 s626_debi_transfer(dev);
205}
206
207
208
209
210
211
212static void s626_debi_replace(struct comedi_device *dev, unsigned int addr,
213 unsigned int mask, unsigned int wdata)
214{
215 unsigned int val;
216
217 addr &= 0xffff;
218 writel(S626_DEBI_CMD_RDWORD | addr, dev->mmio + S626_P_DEBICMD);
219 s626_debi_transfer(dev);
220
221 writel(S626_DEBI_CMD_WRWORD | addr, dev->mmio + S626_P_DEBICMD);
222 val = readl(dev->mmio + S626_P_DEBIAD);
223 val &= mask;
224 val |= wdata;
225 writel(val & 0xffff, dev->mmio + S626_P_DEBIAD);
226 s626_debi_transfer(dev);
227}
228
229
230
231static int s626_i2c_handshake_eoc(struct comedi_device *dev,
232 struct comedi_subdevice *s,
233 struct comedi_insn *insn,
234 unsigned long context)
235{
236 bool status;
237
238 status = s626_mc_test(dev, S626_MC2_UPLD_IIC, S626_P_MC2);
239 if (status)
240 return 0;
241 return -EBUSY;
242}
243
244static int s626_i2c_handshake(struct comedi_device *dev, uint32_t val)
245{
246 unsigned int ctrl;
247 int ret;
248
249
250 writel(val, dev->mmio + S626_P_I2CCTRL);
251
252
253
254
255
256 s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2);
257 ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0);
258 if (ret)
259 return ret;
260
261
262 do {
263 ctrl = readl(dev->mmio + S626_P_I2CCTRL);
264 } while ((ctrl & (S626_I2C_BUSY | S626_I2C_ERR)) == S626_I2C_BUSY);
265
266
267 return ctrl & S626_I2C_ERR;
268}
269
270
271static uint8_t s626_i2c_read(struct comedi_device *dev, uint8_t addr)
272{
273 struct s626_private *devpriv = dev->private;
274
275
276
277
278
279
280
281 if (s626_i2c_handshake(dev, S626_I2C_B2(S626_I2C_ATTRSTART,
282 devpriv->i2c_adrs) |
283 S626_I2C_B1(S626_I2C_ATTRSTOP, addr) |
284 S626_I2C_B0(S626_I2C_ATTRNOP, 0)))
285
286 return 0;
287
288
289
290
291
292
293
294 if (s626_i2c_handshake(dev, S626_I2C_B2(S626_I2C_ATTRSTART,
295 (devpriv->i2c_adrs | 1)) |
296 S626_I2C_B1(S626_I2C_ATTRSTOP, 0) |
297 S626_I2C_B0(S626_I2C_ATTRNOP, 0)))
298
299 return 0;
300
301 return (readl(dev->mmio + S626_P_I2CCTRL) >> 16) & 0xff;
302}
303
304
305
306
307static const uint8_t s626_trimchan[] = { 10, 9, 8, 3, 2, 7, 6, 1, 0, 5, 4 };
308
309
310static const uint8_t s626_trimadrs[] = {
311 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x61, 0x62, 0x63
312};
313
314enum {
315 s626_send_dac_wait_not_mc1_a2out,
316 s626_send_dac_wait_ssr_af2_out,
317 s626_send_dac_wait_fb_buffer2_msb_00,
318 s626_send_dac_wait_fb_buffer2_msb_ff
319};
320
321static int s626_send_dac_eoc(struct comedi_device *dev,
322 struct comedi_subdevice *s,
323 struct comedi_insn *insn,
324 unsigned long context)
325{
326 unsigned int status;
327
328 switch (context) {
329 case s626_send_dac_wait_not_mc1_a2out:
330 status = readl(dev->mmio + S626_P_MC1);
331 if (!(status & S626_MC1_A2OUT))
332 return 0;
333 break;
334 case s626_send_dac_wait_ssr_af2_out:
335 status = readl(dev->mmio + S626_P_SSR);
336 if (status & S626_SSR_AF2_OUT)
337 return 0;
338 break;
339 case s626_send_dac_wait_fb_buffer2_msb_00:
340 status = readl(dev->mmio + S626_P_FB_BUFFER2);
341 if (!(status & 0xff000000))
342 return 0;
343 break;
344 case s626_send_dac_wait_fb_buffer2_msb_ff:
345 status = readl(dev->mmio + S626_P_FB_BUFFER2);
346 if (status & 0xff000000)
347 return 0;
348 break;
349 default:
350 return -EINVAL;
351 }
352 return -EBUSY;
353}
354
355
356
357
358
359
360static int s626_send_dac(struct comedi_device *dev, uint32_t val)
361{
362 struct s626_private *devpriv = dev->private;
363 int ret;
364
365
366
367
368
369
370
371
372
373
374
375
376
377 s626_debi_write(dev, S626_LP_DACPOL, devpriv->dacpol);
378
379
380
381
382
383 *devpriv->dac_wbuf = val;
384
385
386
387
388
389
390
391 s626_mc_enable(dev, S626_MC1_A2OUT, S626_P_MC1);
392
393
394
395
396
397
398
399
400 writel(S626_ISR_AFOU, dev->mmio + S626_P_ISR);
401
402
403
404
405
406
407
408
409 ret = comedi_timeout(dev, NULL, NULL, s626_send_dac_eoc,
410 s626_send_dac_wait_not_mc1_a2out);
411 if (ret) {
412 dev_err(dev->class_dev, "DMA transfer timeout\n");
413 return ret;
414 }
415
416
417
418
419
420
421
422
423
424 writel(S626_XSD2 | S626_RSD3 | S626_SIB_A2,
425 dev->mmio + S626_VECTPORT(0));
426
427
428
429
430
431
432
433
434 ret = comedi_timeout(dev, NULL, NULL, s626_send_dac_eoc,
435 s626_send_dac_wait_ssr_af2_out);
436 if (ret) {
437 dev_err(dev->class_dev,
438 "TSL timeout waiting for slot 1 to execute\n");
439 return ret;
440 }
441
442
443
444
445
446
447
448
449 writel(S626_XSD2 | S626_XFIFO_2 | S626_RSD2 | S626_SIB_A2 | S626_EOS,
450 dev->mmio + S626_VECTPORT(0));
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472 if (readl(dev->mmio + S626_P_FB_BUFFER2) & 0xff000000) {
473
474
475
476
477
478
479
480 ret = comedi_timeout(dev, NULL, NULL, s626_send_dac_eoc,
481 s626_send_dac_wait_fb_buffer2_msb_00);
482 if (ret) {
483 dev_err(dev->class_dev,
484 "TSL timeout waiting for slot 0 to execute\n");
485 return ret;
486 }
487 }
488
489
490
491
492
493
494
495
496
497 writel(S626_RSD3 | S626_SIB_A2 | S626_EOS,
498 dev->mmio + S626_VECTPORT(0));
499
500
501
502
503
504
505 ret = comedi_timeout(dev, NULL, NULL, s626_send_dac_eoc,
506 s626_send_dac_wait_fb_buffer2_msb_ff);
507 if (ret) {
508 dev_err(dev->class_dev,
509 "TSL timeout waiting for slot 0 to execute\n");
510 return ret;
511 }
512 return 0;
513}
514
515
516
517
518static int s626_set_dac(struct comedi_device *dev,
519 uint16_t chan, int16_t dacdata)
520{
521 struct s626_private *devpriv = dev->private;
522 uint16_t signmask;
523 uint32_t ws_image;
524 uint32_t val;
525
526
527
528
529 signmask = 1 << chan;
530 if (dacdata < 0) {
531 dacdata = -dacdata;
532 devpriv->dacpol |= signmask;
533 } else {
534 devpriv->dacpol &= ~signmask;
535 }
536
537
538 if ((uint16_t)dacdata > 0x1FFF)
539 dacdata = 0x1FFF;
540
541
542
543
544
545
546
547
548
549
550
551
552
553 ws_image = (chan & 2) ? S626_WS1 : S626_WS2;
554
555 writel(S626_XSD2 | S626_XFIFO_1 | ws_image,
556 dev->mmio + S626_VECTPORT(2));
557
558 writel(S626_XSD2 | S626_XFIFO_0 | ws_image,
559 dev->mmio + S626_VECTPORT(3));
560
561 writel(S626_XSD2 | S626_XFIFO_3 | S626_WS3,
562 dev->mmio + S626_VECTPORT(4));
563
564 writel(S626_XSD2 | S626_XFIFO_2 | S626_WS3 | S626_EOS,
565 dev->mmio + S626_VECTPORT(5));
566
567
568
569
570
571
572
573
574 val = 0x0F000000;
575
576 val |= 0x00004000;
577
578 val |= ((uint32_t)(chan & 1) << 15);
579
580 val |= (uint32_t)dacdata;
581 return s626_send_dac(dev, val);
582}
583
584static int s626_write_trim_dac(struct comedi_device *dev,
585 uint8_t logical_chan, uint8_t dac_data)
586{
587 struct s626_private *devpriv = dev->private;
588 uint32_t chan;
589
590
591
592
593
594 devpriv->trim_setpoint[logical_chan] = (uint8_t)dac_data;
595
596
597 chan = s626_trimchan[logical_chan];
598
599
600
601
602
603
604
605
606 writel(S626_XSD2 | S626_XFIFO_1 | S626_WS3,
607 dev->mmio + S626_VECTPORT(2));
608
609 writel(S626_XSD2 | S626_XFIFO_0 | S626_WS3,
610 dev->mmio + S626_VECTPORT(3));
611
612 writel(S626_XSD2 | S626_XFIFO_3 | S626_WS1,
613 dev->mmio + S626_VECTPORT(4));
614
615 writel(S626_XSD2 | S626_XFIFO_2 | S626_WS1 | S626_EOS,
616 dev->mmio + S626_VECTPORT(5));
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631 return s626_send_dac(dev, (chan << 8) | dac_data);
632}
633
634static int s626_load_trim_dacs(struct comedi_device *dev)
635{
636 uint8_t i;
637 int ret;
638
639
640 for (i = 0; i < ARRAY_SIZE(s626_trimchan); i++) {
641 ret = s626_write_trim_dac(dev, i,
642 s626_i2c_read(dev, s626_trimadrs[i]));
643 if (ret)
644 return ret;
645 }
646 return 0;
647}
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663static void s626_set_latch_source(struct comedi_device *dev,
664 unsigned int chan, uint16_t value)
665{
666 s626_debi_replace(dev, S626_LP_CRB(chan),
667 ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_LATCHSRC),
668 S626_SET_CRB_LATCHSRC(value));
669}
670
671
672
673
674static void s626_preload(struct comedi_device *dev,
675 unsigned int chan, uint32_t value)
676{
677 s626_debi_write(dev, S626_LP_CNTR(chan), value);
678 s626_debi_write(dev, S626_LP_CNTR(chan) + 2, value >> 16);
679}
680
681
682
683
684
685
686static void s626_reset_cap_flags(struct comedi_device *dev,
687 unsigned int chan)
688{
689 uint16_t set;
690
691 set = S626_SET_CRB_INTRESETCMD(1);
692 if (chan < 3)
693 set |= S626_SET_CRB_INTRESET_A(1);
694 else
695 set |= S626_SET_CRB_INTRESET_B(1);
696
697 s626_debi_replace(dev, S626_LP_CRB(chan), ~S626_CRBMSK_INTCTRL, set);
698}
699
700#ifdef unused
701
702
703
704
705static uint16_t s626_get_mode_a(struct comedi_device *dev,
706 unsigned int chan)
707{
708 uint16_t cra;
709 uint16_t crb;
710 uint16_t setup;
711 unsigned int cntsrc, clkmult, clkpol, encmode;
712
713
714 cra = s626_debi_read(dev, S626_LP_CRA(chan));
715 crb = s626_debi_read(dev, S626_LP_CRB(chan));
716
717
718
719
720 setup =
721
722 S626_SET_STD_LOADSRC(S626_GET_CRA_LOADSRC_A(cra)) |
723
724 S626_SET_STD_LATCHSRC(S626_GET_CRB_LATCHSRC(crb)) |
725
726 S626_SET_STD_INTSRC(S626_GET_CRA_INTSRC_A(cra)) |
727
728 S626_SET_STD_INDXSRC(S626_GET_CRA_INDXSRC_A(cra)) |
729
730 S626_SET_STD_INDXPOL(S626_GET_CRA_INDXPOL_A(cra)) |
731
732 S626_SET_STD_CLKENAB(S626_GET_CRB_CLKENAB_A(crb));
733
734
735 cntsrc = S626_GET_CRA_CNTSRC_A(cra);
736 if (cntsrc & S626_CNTSRC_SYSCLK) {
737
738 encmode = S626_ENCMODE_TIMER;
739
740 clkpol = cntsrc & 1;
741
742 clkmult = S626_CLKMULT_1X;
743 } else {
744
745 encmode = S626_ENCMODE_COUNTER;
746
747 clkpol = S626_GET_CRA_CLKPOL_A(cra);
748
749 clkmult = S626_GET_CRA_CLKMULT_A(cra);
750 if (clkmult == S626_CLKMULT_SPECIAL)
751 clkmult = S626_CLKMULT_1X;
752 }
753 setup |= S626_SET_STD_ENCMODE(encmode) | S626_SET_STD_CLKMULT(clkmult) |
754 S626_SET_STD_CLKPOL(clkpol);
755
756
757 return setup;
758}
759
760static uint16_t s626_get_mode_b(struct comedi_device *dev,
761 unsigned int chan)
762{
763 uint16_t cra;
764 uint16_t crb;
765 uint16_t setup;
766 unsigned int cntsrc, clkmult, clkpol, encmode;
767
768
769 cra = s626_debi_read(dev, S626_LP_CRA(chan));
770 crb = s626_debi_read(dev, S626_LP_CRB(chan));
771
772
773
774
775 setup =
776
777 S626_SET_STD_INTSRC(S626_GET_CRB_INTSRC_B(crb)) |
778
779 S626_SET_STD_LATCHSRC(S626_GET_CRB_LATCHSRC(crb)) |
780
781 S626_SET_STD_LOADSRC(S626_GET_CRB_LOADSRC_B(crb)) |
782
783 S626_SET_STD_INDXPOL(S626_GET_CRB_INDXPOL_B(crb)) |
784
785 S626_SET_STD_CLKENAB(S626_GET_CRB_CLKENAB_B(crb)) |
786
787 S626_SET_STD_INDXSRC(S626_GET_CRA_INDXSRC_B(cra));
788
789
790 cntsrc = S626_GET_CRA_CNTSRC_B(cra);
791 clkmult = S626_GET_CRB_CLKMULT_B(crb);
792 if (clkmult == S626_CLKMULT_SPECIAL) {
793
794 encmode = S626_ENCMODE_EXTENDER;
795
796 clkmult = S626_CLKMULT_1X;
797
798 clkpol = cntsrc & 1;
799 } else if (cntsrc & S626_CNTSRC_SYSCLK) {
800
801 encmode = S626_ENCMODE_TIMER;
802
803 clkmult = S626_CLKMULT_1X;
804
805 clkpol = cntsrc & 1;
806 } else {
807
808 encmode = S626_ENCMODE_COUNTER;
809
810
811 clkpol = S626_GET_CRB_CLKPOL_B(crb);
812 }
813 setup |= S626_SET_STD_ENCMODE(encmode) | S626_SET_STD_CLKMULT(clkmult) |
814 S626_SET_STD_CLKPOL(clkpol);
815
816
817 return setup;
818}
819
820static uint16_t s626_get_mode(struct comedi_device *dev,
821 unsigned int chan)
822{
823 return (chan < 3) ? s626_get_mode_a(dev, chan)
824 : s626_get_mode_b(dev, chan);
825}
826#endif
827
828
829
830
831
832
833
834static void s626_set_mode_a(struct comedi_device *dev,
835 unsigned int chan, uint16_t setup,
836 uint16_t disable_int_src)
837{
838 struct s626_private *devpriv = dev->private;
839 uint16_t cra;
840 uint16_t crb;
841 unsigned int cntsrc, clkmult, clkpol;
842
843
844
845 cra = S626_SET_CRA_LOADSRC_A(S626_GET_STD_LOADSRC(setup));
846
847 cra |= S626_SET_CRA_INDXSRC_A(S626_GET_STD_INDXSRC(setup));
848
849
850 crb = S626_SET_CRB_INTRESETCMD(1) | S626_SET_CRB_INTRESET_A(1);
851
852 crb |= S626_SET_CRB_CLKENAB_A(S626_GET_STD_CLKENAB(setup));
853
854
855 if (!disable_int_src)
856 cra |= S626_SET_CRA_INTSRC_A(S626_GET_STD_INTSRC(setup));
857
858
859 clkpol = S626_GET_STD_CLKPOL(setup);
860 switch (S626_GET_STD_ENCMODE(setup)) {
861 case S626_ENCMODE_EXTENDER:
862
863
864 case S626_ENCMODE_TIMER:
865
866 cntsrc = S626_CNTSRC_SYSCLK;
867
868 cntsrc |= clkpol;
869
870 clkpol = 1;
871
872 clkmult = S626_CLKMULT_1X;
873 break;
874 default:
875
876 cntsrc = S626_CNTSRC_ENCODER;
877
878
879 clkmult = S626_GET_STD_CLKMULT(setup);
880 if (clkmult == S626_CLKMULT_SPECIAL)
881 clkmult = S626_CLKMULT_1X;
882 break;
883 }
884 cra |= S626_SET_CRA_CNTSRC_A(cntsrc) | S626_SET_CRA_CLKPOL_A(clkpol) |
885 S626_SET_CRA_CLKMULT_A(clkmult);
886
887
888
889
890
891 if (S626_GET_STD_INDXSRC(setup) != S626_INDXSRC_SOFT)
892 cra |= S626_SET_CRA_INDXPOL_A(S626_GET_STD_INDXPOL(setup));
893
894
895
896
897
898 if (disable_int_src)
899 devpriv->counter_int_enabs &= ~(S626_OVERMASK(chan) |
900 S626_INDXMASK(chan));
901
902
903
904
905
906 s626_debi_replace(dev, S626_LP_CRA(chan),
907 S626_CRAMSK_INDXSRC_B | S626_CRAMSK_CNTSRC_B, cra);
908 s626_debi_replace(dev, S626_LP_CRB(chan),
909 ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_CLKENAB_A), crb);
910}
911
912static void s626_set_mode_b(struct comedi_device *dev,
913 unsigned int chan, uint16_t setup,
914 uint16_t disable_int_src)
915{
916 struct s626_private *devpriv = dev->private;
917 uint16_t cra;
918 uint16_t crb;
919 unsigned int cntsrc, clkmult, clkpol;
920
921
922
923 cra = S626_SET_CRA_INDXSRC_B(S626_GET_STD_INDXSRC(setup));
924
925
926 crb = S626_SET_CRB_INTRESETCMD(1) | S626_SET_CRB_INTRESET_B(1);
927
928 crb |= S626_SET_CRB_CLKENAB_B(S626_GET_STD_CLKENAB(setup));
929
930 crb |= S626_SET_CRB_LOADSRC_B(S626_GET_STD_LOADSRC(setup));
931
932
933 if (!disable_int_src)
934 crb |= S626_SET_CRB_INTSRC_B(S626_GET_STD_INTSRC(setup));
935
936
937 clkpol = S626_GET_STD_CLKPOL(setup);
938 switch (S626_GET_STD_ENCMODE(setup)) {
939 case S626_ENCMODE_TIMER:
940
941 cntsrc = S626_CNTSRC_SYSCLK;
942
943 cntsrc |= clkpol;
944
945 clkpol = 1;
946
947 clkmult = S626_CLKMULT_1X;
948 break;
949 case S626_ENCMODE_EXTENDER:
950
951 cntsrc = S626_CNTSRC_SYSCLK;
952
953 cntsrc |= clkpol;
954
955 clkpol = 1;
956
957 clkmult = S626_CLKMULT_SPECIAL;
958 break;
959 default:
960
961 cntsrc = S626_CNTSRC_ENCODER;
962
963
964 clkmult = S626_GET_STD_CLKMULT(setup);
965 if (clkmult == S626_CLKMULT_SPECIAL)
966 clkmult = S626_CLKMULT_1X;
967 break;
968 }
969 cra |= S626_SET_CRA_CNTSRC_B(cntsrc);
970 crb |= S626_SET_CRB_CLKPOL_B(clkpol) | S626_SET_CRB_CLKMULT_B(clkmult);
971
972
973
974
975
976 if (S626_GET_STD_INDXSRC(setup) != S626_INDXSRC_SOFT)
977 crb |= S626_SET_CRB_INDXPOL_B(S626_GET_STD_INDXPOL(setup));
978
979
980
981
982
983 if (disable_int_src)
984 devpriv->counter_int_enabs &= ~(S626_OVERMASK(chan) |
985 S626_INDXMASK(chan));
986
987
988
989
990
991 s626_debi_replace(dev, S626_LP_CRA(chan),
992 ~(S626_CRAMSK_INDXSRC_B | S626_CRAMSK_CNTSRC_B), cra);
993 s626_debi_replace(dev, S626_LP_CRB(chan),
994 S626_CRBMSK_CLKENAB_A | S626_CRBMSK_LATCHSRC, crb);
995}
996
997static void s626_set_mode(struct comedi_device *dev,
998 unsigned int chan,
999 uint16_t setup, uint16_t disable_int_src)
1000{
1001 if (chan < 3)
1002 s626_set_mode_a(dev, chan, setup, disable_int_src);
1003 else
1004 s626_set_mode_b(dev, chan, setup, disable_int_src);
1005}
1006
1007
1008
1009
1010static void s626_set_enable(struct comedi_device *dev,
1011 unsigned int chan, uint16_t enab)
1012{
1013 unsigned int mask = S626_CRBMSK_INTCTRL;
1014 unsigned int set;
1015
1016 if (chan < 3) {
1017 mask |= S626_CRBMSK_CLKENAB_A;
1018 set = S626_SET_CRB_CLKENAB_A(enab);
1019 } else {
1020 mask |= S626_CRBMSK_CLKENAB_B;
1021 set = S626_SET_CRB_CLKENAB_B(enab);
1022 }
1023 s626_debi_replace(dev, S626_LP_CRB(chan), ~mask, set);
1024}
1025
1026#ifdef unused
1027static uint16_t s626_get_enable(struct comedi_device *dev,
1028 unsigned int chan)
1029{
1030 uint16_t crb = s626_debi_read(dev, S626_LP_CRB(chan));
1031
1032 return (chan < 3) ? S626_GET_CRB_CLKENAB_A(crb)
1033 : S626_GET_CRB_CLKENAB_B(crb);
1034}
1035#endif
1036
1037#ifdef unused
1038static uint16_t s626_get_latch_source(struct comedi_device *dev,
1039 unsigned int chan)
1040{
1041 return S626_GET_CRB_LATCHSRC(s626_debi_read(dev, S626_LP_CRB(chan)));
1042}
1043#endif
1044
1045
1046
1047
1048
1049
1050static void s626_set_load_trig(struct comedi_device *dev,
1051 unsigned int chan, uint16_t trig)
1052{
1053 uint16_t reg;
1054 uint16_t mask;
1055 uint16_t set;
1056
1057 if (chan < 3) {
1058 reg = S626_LP_CRA(chan);
1059 mask = S626_CRAMSK_LOADSRC_A;
1060 set = S626_SET_CRA_LOADSRC_A(trig);
1061 } else {
1062 reg = S626_LP_CRB(chan);
1063 mask = S626_CRBMSK_LOADSRC_B | S626_CRBMSK_INTCTRL;
1064 set = S626_SET_CRB_LOADSRC_B(trig);
1065 }
1066 s626_debi_replace(dev, reg, ~mask, set);
1067}
1068
1069#ifdef unused
1070static uint16_t s626_get_load_trig(struct comedi_device *dev,
1071 unsigned int chan)
1072{
1073 if (chan < 3)
1074 return S626_GET_CRA_LOADSRC_A(s626_debi_read(dev,
1075 S626_LP_CRA(chan)));
1076 else
1077 return S626_GET_CRB_LOADSRC_B(s626_debi_read(dev,
1078 S626_LP_CRB(chan)));
1079}
1080#endif
1081
1082
1083
1084
1085
1086
1087static void s626_set_int_src(struct comedi_device *dev,
1088 unsigned int chan, uint16_t int_source)
1089{
1090 struct s626_private *devpriv = dev->private;
1091 uint16_t cra_reg = S626_LP_CRA(chan);
1092 uint16_t crb_reg = S626_LP_CRB(chan);
1093
1094 if (chan < 3) {
1095
1096 s626_debi_replace(dev, crb_reg, ~S626_CRBMSK_INTCTRL,
1097 S626_SET_CRB_INTRESETCMD(1) |
1098 S626_SET_CRB_INTRESET_A(1));
1099
1100
1101 s626_debi_replace(dev, cra_reg, ~S626_CRAMSK_INTSRC_A,
1102 S626_SET_CRA_INTSRC_A(int_source));
1103 } else {
1104 uint16_t crb;
1105
1106
1107 crb = s626_debi_read(dev, crb_reg);
1108 crb &= ~S626_CRBMSK_INTCTRL;
1109
1110
1111 s626_debi_write(dev, crb_reg,
1112 crb | S626_SET_CRB_INTRESETCMD(1) |
1113 S626_SET_CRB_INTRESET_B(1));
1114
1115
1116 s626_debi_write(dev, crb_reg,
1117 (crb & ~S626_CRBMSK_INTSRC_B) |
1118 S626_SET_CRB_INTSRC_B(int_source));
1119 }
1120
1121
1122 devpriv->counter_int_enabs &= ~(S626_OVERMASK(chan) |
1123 S626_INDXMASK(chan));
1124 switch (int_source) {
1125 case 0:
1126 default:
1127 break;
1128 case 1:
1129 devpriv->counter_int_enabs |= S626_OVERMASK(chan);
1130 break;
1131 case 2:
1132 devpriv->counter_int_enabs |= S626_INDXMASK(chan);
1133 break;
1134 case 3:
1135 devpriv->counter_int_enabs |= (S626_OVERMASK(chan) |
1136 S626_INDXMASK(chan));
1137 break;
1138 }
1139}
1140
1141#ifdef unused
1142static uint16_t s626_get_int_src(struct comedi_device *dev,
1143 unsigned int chan)
1144{
1145 if (chan < 3)
1146 return S626_GET_CRA_INTSRC_A(s626_debi_read(dev,
1147 S626_LP_CRA(chan)));
1148 else
1149 return S626_GET_CRB_INTSRC_B(s626_debi_read(dev,
1150 S626_LP_CRB(chan)));
1151}
1152#endif
1153
1154#ifdef unused
1155
1156
1157
1158static void s626_set_clk_mult(struct comedi_device *dev,
1159 unsigned int chan, uint16_t value)
1160{
1161 uint16_t mode;
1162
1163 mode = s626_get_mode(dev, chan);
1164 mode &= ~S626_STDMSK_CLKMULT;
1165 mode |= S626_SET_STD_CLKMULT(value);
1166
1167 s626_set_mode(dev, chan, mode, false);
1168}
1169
1170
1171
1172
1173static void s626_set_clk_pol(struct comedi_device *dev,
1174 unsigned int chan, uint16_t value)
1175{
1176 uint16_t mode;
1177
1178 mode = s626_get_mode(dev, chan);
1179 mode &= ~S626_STDMSK_CLKPOL;
1180 mode |= S626_SET_STD_CLKPOL(value);
1181
1182 s626_set_mode(dev, chan, mode, false);
1183}
1184
1185
1186
1187
1188static void s626_set_enc_mode(struct comedi_device *dev,
1189 unsigned int chan, uint16_t value)
1190{
1191 uint16_t mode;
1192
1193 mode = s626_get_mode(dev, chan);
1194 mode &= ~S626_STDMSK_ENCMODE;
1195 mode |= S626_SET_STD_ENCMODE(value);
1196
1197 s626_set_mode(dev, chan, mode, false);
1198}
1199
1200static uint16_t s626_get_index_pol(struct comedi_device *dev,
1201 unsigned int chan)
1202{
1203 return S626_GET_STD_INDXPOL(s626_get_mode(dev, chan));
1204}
1205
1206
1207
1208
1209static void s626_set_index_src(struct comedi_device *dev,
1210 unsigned int chan, uint16_t value)
1211{
1212 uint16_t mode;
1213
1214 mode = s626_get_mode(dev, chan);
1215 mode &= ~S626_STDMSK_INDXSRC;
1216 mode |= S626_SET_STD_INDXSRC(value != 0);
1217
1218 s626_set_mode(dev, chan, mode, false);
1219}
1220
1221static uint16_t s626_get_index_src(struct comedi_device *dev,
1222 unsigned int chan)
1223{
1224 return S626_GET_STD_INDXSRC(s626_get_mode(dev, chan));
1225}
1226#endif
1227
1228
1229
1230
1231static void s626_pulse_index(struct comedi_device *dev,
1232 unsigned int chan)
1233{
1234 if (chan < 3) {
1235 uint16_t cra;
1236
1237 cra = s626_debi_read(dev, S626_LP_CRA(chan));
1238
1239
1240 s626_debi_write(dev, S626_LP_CRA(chan),
1241 (cra ^ S626_CRAMSK_INDXPOL_A));
1242 s626_debi_write(dev, S626_LP_CRA(chan), cra);
1243 } else {
1244 uint16_t crb;
1245
1246 crb = s626_debi_read(dev, S626_LP_CRB(chan));
1247 crb &= ~S626_CRBMSK_INTCTRL;
1248
1249
1250 s626_debi_write(dev, S626_LP_CRB(chan),
1251 (crb ^ S626_CRBMSK_INDXPOL_B));
1252 s626_debi_write(dev, S626_LP_CRB(chan), crb);
1253 }
1254}
1255
1256static unsigned int s626_ai_reg_to_uint(unsigned int data)
1257{
1258 return ((data >> 18) & 0x3fff) ^ 0x2000;
1259}
1260
1261static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan)
1262{
1263 unsigned int group = chan / 16;
1264 unsigned int mask = 1 << (chan - (16 * group));
1265 unsigned int status;
1266
1267
1268 status = s626_debi_read(dev, S626_LP_RDEDGSEL(group));
1269 s626_debi_write(dev, S626_LP_WREDGSEL(group), mask | status);
1270
1271
1272 status = s626_debi_read(dev, S626_LP_RDINTSEL(group));
1273 s626_debi_write(dev, S626_LP_WRINTSEL(group), mask | status);
1274
1275
1276 s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_EDCAP);
1277
1278
1279 status = s626_debi_read(dev, S626_LP_RDCAPSEL(group));
1280 s626_debi_write(dev, S626_LP_WRCAPSEL(group), mask | status);
1281
1282 return 0;
1283}
1284
1285static int s626_dio_reset_irq(struct comedi_device *dev, unsigned int group,
1286 unsigned int mask)
1287{
1288
1289 s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_NOEDCAP);
1290
1291
1292 s626_debi_write(dev, S626_LP_WRCAPSEL(group), mask);
1293
1294 return 0;
1295}
1296
1297static int s626_dio_clear_irq(struct comedi_device *dev)
1298{
1299 unsigned int group;
1300
1301
1302 s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_NOEDCAP);
1303
1304
1305 for (group = 0; group < S626_DIO_BANKS; group++)
1306 s626_debi_write(dev, S626_LP_WRCAPSEL(group), 0xffff);
1307
1308 return 0;
1309}
1310
1311static void s626_handle_dio_interrupt(struct comedi_device *dev,
1312 uint16_t irqbit, uint8_t group)
1313{
1314 struct s626_private *devpriv = dev->private;
1315 struct comedi_subdevice *s = dev->read_subdev;
1316 struct comedi_cmd *cmd = &s->async->cmd;
1317
1318 s626_dio_reset_irq(dev, group, irqbit);
1319
1320 if (devpriv->ai_cmd_running) {
1321
1322 if ((irqbit >> (cmd->start_arg - (16 * group))) == 1 &&
1323 cmd->start_src == TRIG_EXT) {
1324
1325 s626_mc_enable(dev, S626_MC1_ERPS1, S626_P_MC1);
1326
1327 if (cmd->scan_begin_src == TRIG_EXT)
1328 s626_dio_set_irq(dev, cmd->scan_begin_arg);
1329 }
1330 if ((irqbit >> (cmd->scan_begin_arg - (16 * group))) == 1 &&
1331 cmd->scan_begin_src == TRIG_EXT) {
1332
1333 s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2);
1334
1335 if (cmd->convert_src == TRIG_EXT) {
1336 devpriv->ai_convert_count = cmd->chanlist_len;
1337
1338 s626_dio_set_irq(dev, cmd->convert_arg);
1339 }
1340
1341 if (cmd->convert_src == TRIG_TIMER) {
1342 devpriv->ai_convert_count = cmd->chanlist_len;
1343 s626_set_enable(dev, 5, S626_CLKENAB_ALWAYS);
1344 }
1345 }
1346 if ((irqbit >> (cmd->convert_arg - (16 * group))) == 1 &&
1347 cmd->convert_src == TRIG_EXT) {
1348
1349 s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2);
1350
1351 devpriv->ai_convert_count--;
1352 if (devpriv->ai_convert_count > 0)
1353 s626_dio_set_irq(dev, cmd->convert_arg);
1354 }
1355 }
1356}
1357
1358static void s626_check_dio_interrupts(struct comedi_device *dev)
1359{
1360 uint16_t irqbit;
1361 uint8_t group;
1362
1363 for (group = 0; group < S626_DIO_BANKS; group++) {
1364
1365 irqbit = s626_debi_read(dev, S626_LP_RDCAPFLG(group));
1366
1367
1368 if (irqbit) {
1369 s626_handle_dio_interrupt(dev, irqbit, group);
1370 return;
1371 }
1372 }
1373}
1374
1375static void s626_check_counter_interrupts(struct comedi_device *dev)
1376{
1377 struct s626_private *devpriv = dev->private;
1378 struct comedi_subdevice *s = dev->read_subdev;
1379 struct comedi_async *async = s->async;
1380 struct comedi_cmd *cmd = &async->cmd;
1381 uint16_t irqbit;
1382
1383
1384 irqbit = s626_debi_read(dev, S626_LP_RDMISC2);
1385
1386
1387 if (irqbit & S626_IRQ_COINT1A) {
1388
1389 s626_reset_cap_flags(dev, 0);
1390 }
1391 if (irqbit & S626_IRQ_COINT2A) {
1392
1393 s626_reset_cap_flags(dev, 1);
1394 }
1395 if (irqbit & S626_IRQ_COINT3A) {
1396
1397 s626_reset_cap_flags(dev, 2);
1398 }
1399 if (irqbit & S626_IRQ_COINT1B) {
1400
1401 s626_reset_cap_flags(dev, 3);
1402 }
1403 if (irqbit & S626_IRQ_COINT2B) {
1404
1405 s626_reset_cap_flags(dev, 4);
1406
1407 if (devpriv->ai_convert_count > 0) {
1408 devpriv->ai_convert_count--;
1409 if (devpriv->ai_convert_count == 0)
1410 s626_set_enable(dev, 4, S626_CLKENAB_INDEX);
1411
1412 if (cmd->convert_src == TRIG_TIMER) {
1413
1414 s626_mc_enable(dev, S626_MC2_ADC_RPS,
1415 S626_P_MC2);
1416 }
1417 }
1418 }
1419 if (irqbit & S626_IRQ_COINT3B) {
1420
1421 s626_reset_cap_flags(dev, 5);
1422
1423 if (cmd->scan_begin_src == TRIG_TIMER) {
1424
1425 s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2);
1426 }
1427
1428 if (cmd->convert_src == TRIG_TIMER) {
1429 devpriv->ai_convert_count = cmd->chanlist_len;
1430 s626_set_enable(dev, 4, S626_CLKENAB_ALWAYS);
1431 }
1432 }
1433}
1434
1435static bool s626_handle_eos_interrupt(struct comedi_device *dev)
1436{
1437 struct s626_private *devpriv = dev->private;
1438 struct comedi_subdevice *s = dev->read_subdev;
1439 struct comedi_async *async = s->async;
1440 struct comedi_cmd *cmd = &async->cmd;
1441
1442
1443
1444
1445
1446 uint32_t *readaddr = (uint32_t *)devpriv->ana_buf.logical_base + 1;
1447 int i;
1448
1449
1450 for (i = 0; i < cmd->chanlist_len; i++) {
1451 unsigned short tempdata;
1452
1453
1454
1455
1456
1457 tempdata = s626_ai_reg_to_uint(*readaddr);
1458 readaddr++;
1459
1460 comedi_buf_write_samples(s, &tempdata, 1);
1461 }
1462
1463 if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
1464 async->events |= COMEDI_CB_EOA;
1465
1466 if (async->events & COMEDI_CB_CANCEL_MASK)
1467 devpriv->ai_cmd_running = 0;
1468
1469 if (devpriv->ai_cmd_running && cmd->scan_begin_src == TRIG_EXT)
1470 s626_dio_set_irq(dev, cmd->scan_begin_arg);
1471
1472 comedi_handle_events(dev, s);
1473
1474 return !devpriv->ai_cmd_running;
1475}
1476
1477static irqreturn_t s626_irq_handler(int irq, void *d)
1478{
1479 struct comedi_device *dev = d;
1480 unsigned long flags;
1481 uint32_t irqtype, irqstatus;
1482
1483 if (!dev->attached)
1484 return IRQ_NONE;
1485
1486 spin_lock_irqsave(&dev->spinlock, flags);
1487
1488
1489 irqstatus = readl(dev->mmio + S626_P_IER);
1490
1491
1492 irqtype = readl(dev->mmio + S626_P_ISR);
1493
1494
1495 writel(0, dev->mmio + S626_P_IER);
1496
1497
1498 writel(irqtype, dev->mmio + S626_P_ISR);
1499
1500 switch (irqtype) {
1501 case S626_IRQ_RPS1:
1502 if (s626_handle_eos_interrupt(dev))
1503 irqstatus = 0;
1504 break;
1505 case S626_IRQ_GPIO3:
1506
1507 s626_check_dio_interrupts(dev);
1508 s626_check_counter_interrupts(dev);
1509 break;
1510 }
1511
1512
1513 writel(irqstatus, dev->mmio + S626_P_IER);
1514
1515 spin_unlock_irqrestore(&dev->spinlock, flags);
1516 return IRQ_HANDLED;
1517}
1518
1519
1520
1521
1522static void s626_reset_adc(struct comedi_device *dev, uint8_t *ppl)
1523{
1524 struct s626_private *devpriv = dev->private;
1525 struct comedi_subdevice *s = dev->read_subdev;
1526 struct comedi_cmd *cmd = &s->async->cmd;
1527 uint32_t *rps;
1528 uint32_t jmp_adrs;
1529 uint16_t i;
1530 uint16_t n;
1531 uint32_t local_ppl;
1532
1533
1534 s626_mc_disable(dev, S626_MC1_ERPS1, S626_P_MC1);
1535
1536
1537 rps = (uint32_t *)devpriv->rps_buf.logical_base;
1538
1539
1540 writel((uint32_t)devpriv->rps_buf.physical_base,
1541 dev->mmio + S626_P_RPSADDR1);
1542
1543
1544 if (cmd->scan_begin_src != TRIG_FOLLOW) {
1545
1546 *rps++ = S626_RPS_PAUSE | S626_RPS_SIGADC;
1547 *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_SIGADC;
1548 }
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559 *rps++ = S626_RPS_LDREG | (S626_P_DEBICMD >> 2);
1560 *rps++ = S626_DEBI_CMD_WRWORD | S626_LP_GSEL;
1561 *rps++ = S626_RPS_LDREG | (S626_P_DEBIAD >> 2);
1562
1563 *rps++ = S626_GSEL_BIPOLAR5V;
1564 *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_DEBI;
1565
1566
1567 *rps++ = S626_RPS_UPLOAD | S626_RPS_DEBI;
1568
1569 *rps++ = S626_RPS_PAUSE | S626_RPS_DEBI;
1570
1571
1572
1573
1574
1575
1576 for (devpriv->adc_items = 0; devpriv->adc_items < 16;
1577 devpriv->adc_items++) {
1578
1579
1580
1581
1582
1583
1584 local_ppl = (*ppl << 8) | (*ppl & 0x10 ? S626_GSEL_BIPOLAR5V :
1585 S626_GSEL_BIPOLAR10V);
1586
1587
1588
1589 *rps++ = S626_RPS_LDREG | (S626_P_DEBICMD >> 2);
1590 *rps++ = S626_DEBI_CMD_WRWORD | S626_LP_GSEL;
1591
1592 *rps++ = S626_RPS_LDREG | (S626_P_DEBIAD >> 2);
1593 *rps++ = local_ppl;
1594
1595 *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_DEBI;
1596
1597 *rps++ = S626_RPS_UPLOAD | S626_RPS_DEBI;
1598
1599 *rps++ = S626_RPS_PAUSE | S626_RPS_DEBI;
1600
1601 *rps++ = S626_RPS_LDREG | (S626_P_DEBICMD >> 2);
1602
1603 *rps++ = S626_DEBI_CMD_WRWORD | S626_LP_ISEL;
1604 *rps++ = S626_RPS_LDREG | (S626_P_DEBIAD >> 2);
1605
1606 *rps++ = local_ppl;
1607
1608 *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_DEBI;
1609
1610 *rps++ = S626_RPS_UPLOAD | S626_RPS_DEBI;
1611
1612 *rps++ = S626_RPS_PAUSE | S626_RPS_DEBI;
1613
1614
1615
1616
1617
1618
1619
1620
1621 jmp_adrs =
1622 (uint32_t)devpriv->rps_buf.physical_base +
1623 (uint32_t)((unsigned long)rps -
1624 (unsigned long)devpriv->
1625 rps_buf.logical_base);
1626 for (i = 0; i < (10 * S626_RPSCLK_PER_US / 2); i++) {
1627 jmp_adrs += 8;
1628
1629 *rps++ = S626_RPS_JUMP;
1630 *rps++ = jmp_adrs;
1631 }
1632
1633 if (cmd->convert_src != TRIG_NOW) {
1634
1635 *rps++ = S626_RPS_PAUSE | S626_RPS_SIGADC;
1636 *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_SIGADC;
1637 }
1638
1639
1640 *rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2);
1641 *rps++ = S626_GPIO_BASE | S626_GPIO1_LO;
1642 *rps++ = S626_RPS_NOP;
1643
1644
1645 *rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2);
1646 *rps++ = S626_GPIO_BASE | S626_GPIO1_HI;
1647
1648
1649
1650
1651
1652
1653 *rps++ = S626_RPS_PAUSE | S626_RPS_GPIO2;
1654
1655
1656 *rps++ = S626_RPS_STREG |
1657 (S626_BUGFIX_STREG(S626_P_FB_BUFFER1) >> 2);
1658 *rps++ = (uint32_t)devpriv->ana_buf.physical_base +
1659 (devpriv->adc_items << 2);
1660
1661
1662
1663
1664
1665 if (*ppl++ & S626_EOPL) {
1666 devpriv->adc_items++;
1667 break;
1668 }
1669 }
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679 for (n = 0; n < (2 * S626_RPSCLK_PER_US); n++)
1680 *rps++ = S626_RPS_NOP;
1681
1682
1683
1684
1685
1686
1687 *rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2);
1688 *rps++ = S626_GPIO_BASE | S626_GPIO1_LO;
1689 *rps++ = S626_RPS_NOP;
1690
1691 *rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2);
1692 *rps++ = S626_GPIO_BASE | S626_GPIO1_HI;
1693
1694
1695
1696
1697
1698 *rps++ = S626_RPS_PAUSE | S626_RPS_GPIO2;
1699
1700
1701 *rps++ = S626_RPS_STREG | (S626_BUGFIX_STREG(S626_P_FB_BUFFER1) >> 2);
1702 *rps++ = (uint32_t)devpriv->ana_buf.physical_base +
1703 (devpriv->adc_items << 2);
1704
1705
1706
1707
1708
1709
1710 if (devpriv->ai_cmd_running == 1)
1711 *rps++ = S626_RPS_IRQ;
1712
1713
1714 *rps++ = S626_RPS_JUMP;
1715 *rps++ = (uint32_t)devpriv->rps_buf.physical_base;
1716
1717
1718}
1719
1720#ifdef unused_code
1721static int s626_ai_rinsn(struct comedi_device *dev,
1722 struct comedi_subdevice *s,
1723 struct comedi_insn *insn,
1724 unsigned int *data)
1725{
1726 struct s626_private *devpriv = dev->private;
1727 uint8_t i;
1728 int32_t *readaddr;
1729
1730
1731 s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2);
1732
1733
1734 while (s626_mc_test(dev, S626_MC2_ADC_RPS, S626_P_MC2))
1735 ;
1736
1737
1738
1739
1740
1741
1742 readaddr = (uint32_t *)devpriv->ana_buf.logical_base + 1;
1743
1744
1745
1746
1747
1748 for (i = 0; i < devpriv->adc_items; i++) {
1749 *data = s626_ai_reg_to_uint(*readaddr++);
1750 data++;
1751 }
1752
1753 return i;
1754}
1755#endif
1756
1757static int s626_ai_eoc(struct comedi_device *dev,
1758 struct comedi_subdevice *s,
1759 struct comedi_insn *insn,
1760 unsigned long context)
1761{
1762 unsigned int status;
1763
1764 status = readl(dev->mmio + S626_P_PSR);
1765 if (status & S626_PSR_GPIO2)
1766 return 0;
1767 return -EBUSY;
1768}
1769
1770static int s626_ai_insn_read(struct comedi_device *dev,
1771 struct comedi_subdevice *s,
1772 struct comedi_insn *insn,
1773 unsigned int *data)
1774{
1775 uint16_t chan = CR_CHAN(insn->chanspec);
1776 uint16_t range = CR_RANGE(insn->chanspec);
1777 uint16_t adc_spec = 0;
1778 uint32_t gpio_image;
1779 uint32_t tmp;
1780 int ret;
1781 int n;
1782
1783
1784
1785
1786
1787 if (range == 0)
1788 adc_spec = (chan << 8) | (S626_GSEL_BIPOLAR5V);
1789 else
1790 adc_spec = (chan << 8) | (S626_GSEL_BIPOLAR10V);
1791
1792
1793 s626_debi_write(dev, S626_LP_GSEL, adc_spec);
1794
1795
1796 s626_debi_write(dev, S626_LP_ISEL, adc_spec);
1797
1798 for (n = 0; n < insn->n; n++) {
1799
1800 udelay(10);
1801
1802
1803 gpio_image = readl(dev->mmio + S626_P_GPIO);
1804
1805 writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
1806
1807 writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
1808 writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
1809
1810 writel(gpio_image | S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
1811
1812
1813
1814
1815
1816
1817
1818
1819 ret = comedi_timeout(dev, s, insn, s626_ai_eoc, 0);
1820 if (ret)
1821 return ret;
1822
1823
1824 if (n != 0) {
1825 tmp = readl(dev->mmio + S626_P_FB_BUFFER1);
1826 data[n - 1] = s626_ai_reg_to_uint(tmp);
1827 }
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838 udelay(4);
1839 }
1840
1841
1842
1843
1844
1845 gpio_image = readl(dev->mmio + S626_P_GPIO);
1846
1847 writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
1848
1849 writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
1850 writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
1851
1852 writel(gpio_image | S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
1853
1854
1855
1856
1857 ret = comedi_timeout(dev, s, insn, s626_ai_eoc, 0);
1858 if (ret)
1859 return ret;
1860
1861
1862
1863
1864 if (n != 0) {
1865 tmp = readl(dev->mmio + S626_P_FB_BUFFER1);
1866 data[n - 1] = s626_ai_reg_to_uint(tmp);
1867 }
1868
1869 return n;
1870}
1871
1872static int s626_ai_load_polllist(uint8_t *ppl, struct comedi_cmd *cmd)
1873{
1874 int n;
1875
1876 for (n = 0; n < cmd->chanlist_len; n++) {
1877 if (CR_RANGE(cmd->chanlist[n]) == 0)
1878 ppl[n] = CR_CHAN(cmd->chanlist[n]) | S626_RANGE_5V;
1879 else
1880 ppl[n] = CR_CHAN(cmd->chanlist[n]) | S626_RANGE_10V;
1881 }
1882 if (n != 0)
1883 ppl[n - 1] |= S626_EOPL;
1884
1885 return n;
1886}
1887
1888static int s626_ai_inttrig(struct comedi_device *dev,
1889 struct comedi_subdevice *s,
1890 unsigned int trig_num)
1891{
1892 struct comedi_cmd *cmd = &s->async->cmd;
1893
1894 if (trig_num != cmd->start_arg)
1895 return -EINVAL;
1896
1897
1898 s626_mc_enable(dev, S626_MC1_ERPS1, S626_P_MC1);
1899
1900 s->async->inttrig = NULL;
1901
1902 return 1;
1903}
1904
1905
1906
1907
1908
1909
1910
1911
1912static int s626_ns_to_timer(unsigned int *nanosec, unsigned int flags)
1913{
1914 int divider, base;
1915
1916 base = 500;
1917
1918 switch (flags & CMDF_ROUND_MASK) {
1919 case CMDF_ROUND_NEAREST:
1920 default:
1921 divider = DIV_ROUND_CLOSEST(*nanosec, base);
1922 break;
1923 case CMDF_ROUND_DOWN:
1924 divider = (*nanosec) / base;
1925 break;
1926 case CMDF_ROUND_UP:
1927 divider = DIV_ROUND_UP(*nanosec, base);
1928 break;
1929 }
1930
1931 *nanosec = base * divider;
1932 return divider - 1;
1933}
1934
1935static void s626_timer_load(struct comedi_device *dev,
1936 unsigned int chan, int tick)
1937{
1938 uint16_t setup =
1939
1940 S626_SET_STD_LOADSRC(S626_LOADSRC_INDX) |
1941
1942 S626_SET_STD_INDXSRC(S626_INDXSRC_SOFT) |
1943
1944 S626_SET_STD_ENCMODE(S626_ENCMODE_TIMER) |
1945
1946 S626_SET_STD_CLKPOL(S626_CNTDIR_DOWN) |
1947
1948 S626_SET_STD_CLKMULT(S626_CLKMULT_1X) |
1949
1950 S626_SET_STD_CLKENAB(S626_CLKENAB_INDEX);
1951 uint16_t value_latchsrc = S626_LATCHSRC_A_INDXA;
1952
1953
1954 s626_set_mode(dev, chan, setup, false);
1955
1956
1957 s626_preload(dev, chan, tick);
1958
1959
1960
1961
1962
1963 s626_set_load_trig(dev, chan, 0);
1964 s626_pulse_index(dev, chan);
1965
1966
1967 s626_set_load_trig(dev, chan, 1);
1968
1969
1970 s626_set_int_src(dev, chan, S626_INTSRC_OVER);
1971
1972 s626_set_latch_source(dev, chan, value_latchsrc);
1973
1974}
1975
1976
1977static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1978{
1979 struct s626_private *devpriv = dev->private;
1980 uint8_t ppl[16];
1981 struct comedi_cmd *cmd = &s->async->cmd;
1982 int tick;
1983
1984 if (devpriv->ai_cmd_running) {
1985 dev_err(dev->class_dev,
1986 "s626_ai_cmd: Another ai_cmd is running\n");
1987 return -EBUSY;
1988 }
1989
1990 writel(0, dev->mmio + S626_P_IER);
1991
1992
1993 writel(S626_IRQ_RPS1 | S626_IRQ_GPIO3, dev->mmio + S626_P_ISR);
1994
1995
1996 s626_dio_clear_irq(dev);
1997
1998
1999
2000 devpriv->ai_cmd_running = 0;
2001
2002 s626_ai_load_polllist(ppl, cmd);
2003 devpriv->ai_cmd_running = 1;
2004 devpriv->ai_convert_count = 0;
2005
2006 switch (cmd->scan_begin_src) {
2007 case TRIG_FOLLOW:
2008 break;
2009 case TRIG_TIMER:
2010
2011
2012
2013
2014 tick = s626_ns_to_timer(&cmd->scan_begin_arg, cmd->flags);
2015
2016
2017 s626_timer_load(dev, 5, tick);
2018 s626_set_enable(dev, 5, S626_CLKENAB_ALWAYS);
2019 break;
2020 case TRIG_EXT:
2021
2022 if (cmd->start_src != TRIG_EXT)
2023 s626_dio_set_irq(dev, cmd->scan_begin_arg);
2024 break;
2025 }
2026
2027 switch (cmd->convert_src) {
2028 case TRIG_NOW:
2029 break;
2030 case TRIG_TIMER:
2031
2032
2033
2034
2035 tick = s626_ns_to_timer(&cmd->convert_arg, cmd->flags);
2036
2037
2038 s626_timer_load(dev, 4, tick);
2039 s626_set_enable(dev, 4, S626_CLKENAB_INDEX);
2040 break;
2041 case TRIG_EXT:
2042
2043 if (cmd->scan_begin_src != TRIG_EXT &&
2044 cmd->start_src == TRIG_EXT)
2045 s626_dio_set_irq(dev, cmd->convert_arg);
2046 break;
2047 }
2048
2049 s626_reset_adc(dev, ppl);
2050
2051 switch (cmd->start_src) {
2052 case TRIG_NOW:
2053
2054
2055
2056
2057 s626_mc_enable(dev, S626_MC1_ERPS1, S626_P_MC1);
2058 s->async->inttrig = NULL;
2059 break;
2060 case TRIG_EXT:
2061
2062 s626_dio_set_irq(dev, cmd->start_arg);
2063 s->async->inttrig = NULL;
2064 break;
2065 case TRIG_INT:
2066 s->async->inttrig = s626_ai_inttrig;
2067 break;
2068 }
2069
2070
2071 writel(S626_IRQ_GPIO3 | S626_IRQ_RPS1, dev->mmio + S626_P_IER);
2072
2073 return 0;
2074}
2075
2076static int s626_ai_cmdtest(struct comedi_device *dev,
2077 struct comedi_subdevice *s, struct comedi_cmd *cmd)
2078{
2079 int err = 0;
2080 unsigned int arg;
2081
2082
2083
2084 err |= comedi_check_trigger_src(&cmd->start_src,
2085 TRIG_NOW | TRIG_INT | TRIG_EXT);
2086 err |= comedi_check_trigger_src(&cmd->scan_begin_src,
2087 TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW);
2088 err |= comedi_check_trigger_src(&cmd->convert_src,
2089 TRIG_TIMER | TRIG_EXT | TRIG_NOW);
2090 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
2091 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
2092
2093 if (err)
2094 return 1;
2095
2096
2097
2098 err |= comedi_check_trigger_is_unique(cmd->start_src);
2099 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
2100 err |= comedi_check_trigger_is_unique(cmd->convert_src);
2101 err |= comedi_check_trigger_is_unique(cmd->stop_src);
2102
2103
2104
2105 if (err)
2106 return 2;
2107
2108
2109
2110 switch (cmd->start_src) {
2111 case TRIG_NOW:
2112 case TRIG_INT:
2113 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
2114 break;
2115 case TRIG_EXT:
2116 err |= comedi_check_trigger_arg_max(&cmd->start_arg, 39);
2117 break;
2118 }
2119
2120 if (cmd->scan_begin_src == TRIG_EXT)
2121 err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg, 39);
2122 if (cmd->convert_src == TRIG_EXT)
2123 err |= comedi_check_trigger_arg_max(&cmd->convert_arg, 39);
2124
2125#define S626_MAX_SPEED 200000
2126#define S626_MIN_SPEED 2000000000
2127
2128 if (cmd->scan_begin_src == TRIG_TIMER) {
2129 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
2130 S626_MAX_SPEED);
2131 err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg,
2132 S626_MIN_SPEED);
2133 } else {
2134
2135
2136
2137
2138
2139
2140 }
2141 if (cmd->convert_src == TRIG_TIMER) {
2142 err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
2143 S626_MAX_SPEED);
2144 err |= comedi_check_trigger_arg_max(&cmd->convert_arg,
2145 S626_MIN_SPEED);
2146 } else {
2147
2148
2149
2150
2151 }
2152
2153 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
2154 cmd->chanlist_len);
2155
2156 if (cmd->stop_src == TRIG_COUNT)
2157 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
2158 else
2159 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
2160
2161 if (err)
2162 return 3;
2163
2164
2165
2166 if (cmd->scan_begin_src == TRIG_TIMER) {
2167 arg = cmd->scan_begin_arg;
2168 s626_ns_to_timer(&arg, cmd->flags);
2169 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
2170 }
2171
2172 if (cmd->convert_src == TRIG_TIMER) {
2173 arg = cmd->convert_arg;
2174 s626_ns_to_timer(&arg, cmd->flags);
2175 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
2176
2177 if (cmd->scan_begin_src == TRIG_TIMER) {
2178 arg = cmd->convert_arg * cmd->scan_end_arg;
2179 err |= comedi_check_trigger_arg_min(&cmd->
2180 scan_begin_arg,
2181 arg);
2182 }
2183 }
2184
2185 if (err)
2186 return 4;
2187
2188 return 0;
2189}
2190
2191static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
2192{
2193 struct s626_private *devpriv = dev->private;
2194
2195
2196 s626_mc_disable(dev, S626_MC1_ERPS1, S626_P_MC1);
2197
2198
2199 writel(0, dev->mmio + S626_P_IER);
2200
2201 devpriv->ai_cmd_running = 0;
2202
2203 return 0;
2204}
2205
2206static int s626_ao_insn_write(struct comedi_device *dev,
2207 struct comedi_subdevice *s,
2208 struct comedi_insn *insn,
2209 unsigned int *data)
2210{
2211 unsigned int chan = CR_CHAN(insn->chanspec);
2212 int i;
2213
2214 for (i = 0; i < insn->n; i++) {
2215 int16_t dacdata = (int16_t)data[i];
2216 int ret;
2217
2218 dacdata -= (0x1fff);
2219
2220 ret = s626_set_dac(dev, chan, dacdata);
2221 if (ret)
2222 return ret;
2223
2224 s->readback[chan] = data[i];
2225 }
2226
2227 return insn->n;
2228}
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238static void s626_dio_init(struct comedi_device *dev)
2239{
2240 uint16_t group;
2241
2242
2243 s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_NOEDCAP);
2244
2245
2246 for (group = 0; group < S626_DIO_BANKS; group++) {
2247
2248 s626_debi_write(dev, S626_LP_WRINTSEL(group), 0);
2249
2250 s626_debi_write(dev, S626_LP_WRCAPSEL(group), 0xffff);
2251
2252 s626_debi_write(dev, S626_LP_WREDGSEL(group), 0);
2253
2254 s626_debi_write(dev, S626_LP_WRDOUT(group), 0);
2255 }
2256}
2257
2258static int s626_dio_insn_bits(struct comedi_device *dev,
2259 struct comedi_subdevice *s,
2260 struct comedi_insn *insn,
2261 unsigned int *data)
2262{
2263 unsigned long group = (unsigned long)s->private;
2264
2265 if (comedi_dio_update_state(s, data))
2266 s626_debi_write(dev, S626_LP_WRDOUT(group), s->state);
2267
2268 data[1] = s626_debi_read(dev, S626_LP_RDDIN(group));
2269
2270 return insn->n;
2271}
2272
2273static int s626_dio_insn_config(struct comedi_device *dev,
2274 struct comedi_subdevice *s,
2275 struct comedi_insn *insn,
2276 unsigned int *data)
2277{
2278 unsigned long group = (unsigned long)s->private;
2279 int ret;
2280
2281 ret = comedi_dio_insn_config(dev, s, insn, data, 0);
2282 if (ret)
2283 return ret;
2284
2285 s626_debi_write(dev, S626_LP_WRDOUT(group), s->io_bits);
2286
2287 return insn->n;
2288}
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299static int s626_enc_insn_config(struct comedi_device *dev,
2300 struct comedi_subdevice *s,
2301 struct comedi_insn *insn, unsigned int *data)
2302{
2303 unsigned int chan = CR_CHAN(insn->chanspec);
2304 uint16_t setup =
2305
2306 S626_SET_STD_LOADSRC(S626_LOADSRC_INDX) |
2307
2308 S626_SET_STD_INDXSRC(S626_INDXSRC_SOFT) |
2309
2310 S626_SET_STD_ENCMODE(S626_ENCMODE_COUNTER) |
2311
2312 S626_SET_STD_CLKPOL(S626_CLKPOL_POS) |
2313
2314 S626_SET_STD_CLKMULT(S626_CLKMULT_1X) |
2315
2316 S626_SET_STD_CLKENAB(S626_CLKENAB_INDEX);
2317
2318
2319 uint16_t value_latchsrc = S626_LATCHSRC_AB_READ;
2320 uint16_t enab = S626_CLKENAB_ALWAYS;
2321
2322
2323
2324 s626_set_mode(dev, chan, setup, true);
2325 s626_preload(dev, chan, data[0]);
2326 s626_pulse_index(dev, chan);
2327 s626_set_latch_source(dev, chan, value_latchsrc);
2328 s626_set_enable(dev, chan, (enab != 0));
2329
2330 return insn->n;
2331}
2332
2333static int s626_enc_insn_read(struct comedi_device *dev,
2334 struct comedi_subdevice *s,
2335 struct comedi_insn *insn,
2336 unsigned int *data)
2337{
2338 unsigned int chan = CR_CHAN(insn->chanspec);
2339 uint16_t cntr_latch_reg = S626_LP_CNTR(chan);
2340 int i;
2341
2342 for (i = 0; i < insn->n; i++) {
2343 unsigned int val;
2344
2345
2346
2347
2348
2349 val = s626_debi_read(dev, cntr_latch_reg);
2350 val |= (s626_debi_read(dev, cntr_latch_reg + 2) << 16);
2351 data[i] = val;
2352 }
2353
2354 return insn->n;
2355}
2356
2357static int s626_enc_insn_write(struct comedi_device *dev,
2358 struct comedi_subdevice *s,
2359 struct comedi_insn *insn, unsigned int *data)
2360{
2361 unsigned int chan = CR_CHAN(insn->chanspec);
2362
2363
2364 s626_preload(dev, chan, data[0]);
2365
2366
2367
2368
2369
2370 s626_set_load_trig(dev, chan, 0);
2371 s626_pulse_index(dev, chan);
2372 s626_set_load_trig(dev, chan, 2);
2373
2374 return 1;
2375}
2376
2377static void s626_write_misc2(struct comedi_device *dev, uint16_t new_image)
2378{
2379 s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_WENABLE);
2380 s626_debi_write(dev, S626_LP_WRMISC2, new_image);
2381 s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_WDISABLE);
2382}
2383
2384static void s626_counters_init(struct comedi_device *dev)
2385{
2386 int chan;
2387 uint16_t setup =
2388
2389 S626_SET_STD_LOADSRC(S626_LOADSRC_INDX) |
2390
2391 S626_SET_STD_INDXSRC(S626_INDXSRC_SOFT) |
2392
2393 S626_SET_STD_ENCMODE(S626_ENCMODE_COUNTER) |
2394
2395 S626_SET_STD_CLKPOL(S626_CLKPOL_POS) |
2396
2397 S626_SET_STD_CLKMULT(S626_CLKMULT_1X) |
2398
2399 S626_SET_STD_CLKENAB(S626_CLKENAB_INDEX);
2400
2401
2402
2403
2404 for (chan = 0; chan < S626_ENCODER_CHANNELS; chan++) {
2405 s626_set_mode(dev, chan, setup, true);
2406 s626_set_int_src(dev, chan, 0);
2407 s626_reset_cap_flags(dev, chan);
2408 s626_set_enable(dev, chan, S626_CLKENAB_ALWAYS);
2409 }
2410}
2411
2412static int s626_allocate_dma_buffers(struct comedi_device *dev)
2413{
2414 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
2415 struct s626_private *devpriv = dev->private;
2416 void *addr;
2417 dma_addr_t appdma;
2418
2419 addr = pci_alloc_consistent(pcidev, S626_DMABUF_SIZE, &appdma);
2420 if (!addr)
2421 return -ENOMEM;
2422 devpriv->ana_buf.logical_base = addr;
2423 devpriv->ana_buf.physical_base = appdma;
2424
2425 addr = pci_alloc_consistent(pcidev, S626_DMABUF_SIZE, &appdma);
2426 if (!addr)
2427 return -ENOMEM;
2428 devpriv->rps_buf.logical_base = addr;
2429 devpriv->rps_buf.physical_base = appdma;
2430
2431 return 0;
2432}
2433
2434static void s626_free_dma_buffers(struct comedi_device *dev)
2435{
2436 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
2437 struct s626_private *devpriv = dev->private;
2438
2439 if (!devpriv)
2440 return;
2441
2442 if (devpriv->rps_buf.logical_base)
2443 pci_free_consistent(pcidev, S626_DMABUF_SIZE,
2444 devpriv->rps_buf.logical_base,
2445 devpriv->rps_buf.physical_base);
2446 if (devpriv->ana_buf.logical_base)
2447 pci_free_consistent(pcidev, S626_DMABUF_SIZE,
2448 devpriv->ana_buf.logical_base,
2449 devpriv->ana_buf.physical_base);
2450}
2451
2452static int s626_initialize(struct comedi_device *dev)
2453{
2454 struct s626_private *devpriv = dev->private;
2455 dma_addr_t phys_buf;
2456 uint16_t chan;
2457 int i;
2458 int ret;
2459
2460
2461 s626_mc_enable(dev, S626_MC1_DEBI | S626_MC1_AUDIO | S626_MC1_I2C,
2462 S626_P_MC1);
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472 writel(S626_DEBI_CFG_SLAVE16 |
2473 (S626_DEBI_TOUT << S626_DEBI_CFG_TOUT_BIT) | S626_DEBI_SWAP |
2474 S626_DEBI_CFG_INTEL, dev->mmio + S626_P_DEBICFG);
2475
2476
2477 writel(S626_DEBI_PAGE_DISABLE, dev->mmio + S626_P_DEBIPAGE);
2478
2479
2480 writel(S626_GPIO_BASE | S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
2481
2482
2483 devpriv->i2c_adrs = 0xA0;
2484
2485
2486
2487
2488
2489 writel(S626_I2C_CLKSEL | S626_I2C_ABORT,
2490 dev->mmio + S626_P_I2CSTAT);
2491 s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2);
2492 ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0);
2493 if (ret)
2494 return ret;
2495
2496
2497
2498
2499
2500 for (i = 0; i < 2; i++) {
2501 writel(S626_I2C_CLKSEL, dev->mmio + S626_P_I2CSTAT);
2502 s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2);
2503 ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0);
2504 if (ret)
2505 return ret;
2506 }
2507
2508
2509
2510
2511
2512
2513
2514 writel(S626_ACON2_INIT, dev->mmio + S626_P_ACON2);
2515
2516
2517
2518
2519
2520
2521
2522 writel(S626_RSD1 | S626_SIB_A1, dev->mmio + S626_P_TSL1);
2523 writel(S626_RSD1 | S626_SIB_A1 | S626_EOS,
2524 dev->mmio + S626_P_TSL1 + 4);
2525
2526
2527 writel(S626_ACON1_ADCSTART, dev->mmio + S626_P_ACON1);
2528
2529
2530
2531
2532
2533
2534 writel((uint32_t)devpriv->rps_buf.physical_base,
2535 dev->mmio + S626_P_RPSADDR1);
2536
2537 writel(0, dev->mmio + S626_P_RPSPAGE1);
2538
2539 writel(0, dev->mmio + S626_P_RPS1_TOUT);
2540
2541#if 0
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551 {
2552 struct comedi_subdevice *s = dev->read_subdev;
2553 uint8_t poll_list;
2554 uint16_t adc_data;
2555 uint16_t start_val;
2556 uint16_t index;
2557 unsigned int data[16];
2558
2559
2560 poll_list = S626_EOPL;
2561 s626_reset_adc(dev, &poll_list);
2562
2563
2564 s626_ai_rinsn(dev, s, NULL, data);
2565 start_val = data[0];
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577 for (index = 0; index < 500; index++) {
2578 s626_ai_rinsn(dev, s, NULL, data);
2579 adc_data = data[0];
2580 if (adc_data != start_val)
2581 break;
2582 }
2583 }
2584#endif
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595 writel(0, dev->mmio + S626_P_PCI_BT_A);
2596
2597
2598
2599
2600
2601
2602
2603 phys_buf = devpriv->ana_buf.physical_base +
2604 (S626_DAC_WDMABUF_OS * sizeof(uint32_t));
2605 writel((uint32_t)phys_buf, dev->mmio + S626_P_BASEA2_OUT);
2606 writel((uint32_t)(phys_buf + sizeof(uint32_t)),
2607 dev->mmio + S626_P_PROTA2_OUT);
2608
2609
2610
2611
2612
2613 devpriv->dac_wbuf = (uint32_t *)devpriv->ana_buf.logical_base +
2614 S626_DAC_WDMABUF_OS;
2615
2616
2617
2618
2619
2620
2621
2622 writel(8, dev->mmio + S626_P_PAGEA2_OUT);
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637 writel(S626_XSD2 | S626_RSD3 | S626_SIB_A2 | S626_EOS,
2638 dev->mmio + S626_VECTPORT(0));
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650 writel(S626_LF_A2, dev->mmio + S626_VECTPORT(1));
2651
2652
2653 writel(S626_ACON1_DACSTART, dev->mmio + S626_P_ACON1);
2654
2655
2656
2657
2658
2659
2660 s626_load_trim_dacs(dev);
2661 ret = s626_load_trim_dacs(dev);
2662 if (ret)
2663 return ret;
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677 for (chan = 0; chan < S626_DAC_CHANNELS; chan++) {
2678 ret = s626_set_dac(dev, chan, 0);
2679 if (ret)
2680 return ret;
2681 }
2682
2683
2684 s626_counters_init(dev);
2685
2686
2687
2688
2689
2690
2691
2692 s626_write_misc2(dev, (s626_debi_read(dev, S626_LP_RDMISC2) &
2693 S626_MISC2_BATT_ENABLE));
2694
2695
2696 s626_dio_init(dev);
2697
2698 return 0;
2699}
2700
2701static int s626_auto_attach(struct comedi_device *dev,
2702 unsigned long context_unused)
2703{
2704 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
2705 struct s626_private *devpriv;
2706 struct comedi_subdevice *s;
2707 int ret;
2708
2709 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
2710 if (!devpriv)
2711 return -ENOMEM;
2712
2713 ret = comedi_pci_enable(dev);
2714 if (ret)
2715 return ret;
2716
2717 dev->mmio = pci_ioremap_bar(pcidev, 0);
2718 if (!dev->mmio)
2719 return -ENOMEM;
2720
2721
2722 writel(0, dev->mmio + S626_P_IER);
2723
2724
2725 writel(S626_MC1_SOFT_RESET, dev->mmio + S626_P_MC1);
2726
2727
2728
2729 ret = s626_allocate_dma_buffers(dev);
2730 if (ret)
2731 return ret;
2732
2733 if (pcidev->irq) {
2734 ret = request_irq(pcidev->irq, s626_irq_handler, IRQF_SHARED,
2735 dev->board_name, dev);
2736
2737 if (ret == 0)
2738 dev->irq = pcidev->irq;
2739 }
2740
2741 ret = comedi_alloc_subdevices(dev, 6);
2742 if (ret)
2743 return ret;
2744
2745 s = &dev->subdevices[0];
2746
2747 s->type = COMEDI_SUBD_AI;
2748 s->subdev_flags = SDF_READABLE | SDF_DIFF;
2749 s->n_chan = S626_ADC_CHANNELS;
2750 s->maxdata = 0x3fff;
2751 s->range_table = &s626_range_table;
2752 s->len_chanlist = S626_ADC_CHANNELS;
2753 s->insn_read = s626_ai_insn_read;
2754 if (dev->irq) {
2755 dev->read_subdev = s;
2756 s->subdev_flags |= SDF_CMD_READ;
2757 s->do_cmd = s626_ai_cmd;
2758 s->do_cmdtest = s626_ai_cmdtest;
2759 s->cancel = s626_ai_cancel;
2760 }
2761
2762 s = &dev->subdevices[1];
2763
2764 s->type = COMEDI_SUBD_AO;
2765 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
2766 s->n_chan = S626_DAC_CHANNELS;
2767 s->maxdata = 0x3fff;
2768 s->range_table = &range_bipolar10;
2769 s->insn_write = s626_ao_insn_write;
2770
2771 ret = comedi_alloc_subdev_readback(s);
2772 if (ret)
2773 return ret;
2774
2775 s = &dev->subdevices[2];
2776
2777 s->type = COMEDI_SUBD_DIO;
2778 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
2779 s->n_chan = 16;
2780 s->maxdata = 1;
2781 s->io_bits = 0xffff;
2782 s->private = (void *)0;
2783 s->range_table = &range_digital;
2784 s->insn_config = s626_dio_insn_config;
2785 s->insn_bits = s626_dio_insn_bits;
2786
2787 s = &dev->subdevices[3];
2788
2789 s->type = COMEDI_SUBD_DIO;
2790 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
2791 s->n_chan = 16;
2792 s->maxdata = 1;
2793 s->io_bits = 0xffff;
2794 s->private = (void *)1;
2795 s->range_table = &range_digital;
2796 s->insn_config = s626_dio_insn_config;
2797 s->insn_bits = s626_dio_insn_bits;
2798
2799 s = &dev->subdevices[4];
2800
2801 s->type = COMEDI_SUBD_DIO;
2802 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
2803 s->n_chan = 16;
2804 s->maxdata = 1;
2805 s->io_bits = 0xffff;
2806 s->private = (void *)2;
2807 s->range_table = &range_digital;
2808 s->insn_config = s626_dio_insn_config;
2809 s->insn_bits = s626_dio_insn_bits;
2810
2811 s = &dev->subdevices[5];
2812
2813 s->type = COMEDI_SUBD_COUNTER;
2814 s->subdev_flags = SDF_WRITABLE | SDF_READABLE | SDF_LSAMPL;
2815 s->n_chan = S626_ENCODER_CHANNELS;
2816 s->maxdata = 0xffffff;
2817 s->range_table = &range_unknown;
2818 s->insn_config = s626_enc_insn_config;
2819 s->insn_read = s626_enc_insn_read;
2820 s->insn_write = s626_enc_insn_write;
2821
2822 return s626_initialize(dev);
2823}
2824
2825static void s626_detach(struct comedi_device *dev)
2826{
2827 struct s626_private *devpriv = dev->private;
2828
2829 if (devpriv) {
2830
2831 devpriv->ai_cmd_running = 0;
2832
2833 if (dev->mmio) {
2834
2835
2836 writel(0, dev->mmio + S626_P_IER);
2837
2838 writel(S626_IRQ_GPIO3 | S626_IRQ_RPS1,
2839 dev->mmio + S626_P_ISR);
2840
2841
2842 s626_write_misc2(dev, 0);
2843
2844
2845 writel(S626_MC1_SHUTDOWN, dev->mmio + S626_P_MC1);
2846 writel(S626_ACON1_BASE, dev->mmio + S626_P_ACON1);
2847 }
2848 }
2849 comedi_pci_detach(dev);
2850 s626_free_dma_buffers(dev);
2851}
2852
2853static struct comedi_driver s626_driver = {
2854 .driver_name = "s626",
2855 .module = THIS_MODULE,
2856 .auto_attach = s626_auto_attach,
2857 .detach = s626_detach,
2858};
2859
2860static int s626_pci_probe(struct pci_dev *dev,
2861 const struct pci_device_id *id)
2862{
2863 return comedi_pci_auto_config(dev, &s626_driver, id->driver_data);
2864}
2865
2866
2867
2868
2869
2870
2871static const struct pci_device_id s626_pci_table[] = {
2872 { PCI_DEVICE_SUB(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146,
2873 0x6000, 0x0272) },
2874 { 0 }
2875};
2876MODULE_DEVICE_TABLE(pci, s626_pci_table);
2877
2878static struct pci_driver s626_pci_driver = {
2879 .name = "s626",
2880 .id_table = s626_pci_table,
2881 .probe = s626_pci_probe,
2882 .remove = comedi_pci_auto_unconfig,
2883};
2884module_comedi_pci_driver(s626_driver, s626_pci_driver);
2885
2886MODULE_AUTHOR("Gianluca Palli <gpalli@deis.unibo.it>");
2887MODULE_DESCRIPTION("Sensoray 626 Comedi driver module");
2888MODULE_LICENSE("GPL");
2889