1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * comedi/drivers/ni_labpc_common.c
4 *
5 * Common support code for "ni_labpc", "ni_labpc_pci" and "ni_labpc_cs".
6 *
7 * Copyright (C) 2001-2003 Frank Mori Hess <fmhess@users.sourceforge.net>
8 */
9
10#include <linux/module.h>
11#include <linux/interrupt.h>
12#include <linux/io.h>
13#include <linux/delay.h>
14#include <linux/slab.h>
15#include <linux/comedi/comedidev.h>
16#include <linux/comedi/comedi_8255.h>
17#include <linux/comedi/comedi_8254.h>
18
19#include "ni_labpc.h"
20#include "ni_labpc_regs.h"
21#include "ni_labpc_isadma.h"
22
23enum scan_mode {
24 MODE_SINGLE_CHAN,
25 MODE_SINGLE_CHAN_INTERVAL,
26 MODE_MULT_CHAN_UP,
27 MODE_MULT_CHAN_DOWN,
28};
29
30static const struct comedi_lrange range_labpc_plus_ai = {
31 16, {
32 BIP_RANGE(5),
33 BIP_RANGE(4),
34 BIP_RANGE(2.5),
35 BIP_RANGE(1),
36 BIP_RANGE(0.5),
37 BIP_RANGE(0.25),
38 BIP_RANGE(0.1),
39 BIP_RANGE(0.05),
40 UNI_RANGE(10),
41 UNI_RANGE(8),
42 UNI_RANGE(5),
43 UNI_RANGE(2),
44 UNI_RANGE(1),
45 UNI_RANGE(0.5),
46 UNI_RANGE(0.2),
47 UNI_RANGE(0.1)
48 }
49};
50
51static const struct comedi_lrange range_labpc_1200_ai = {
52 14, {
53 BIP_RANGE(5),
54 BIP_RANGE(2.5),
55 BIP_RANGE(1),
56 BIP_RANGE(0.5),
57 BIP_RANGE(0.25),
58 BIP_RANGE(0.1),
59 BIP_RANGE(0.05),
60 UNI_RANGE(10),
61 UNI_RANGE(5),
62 UNI_RANGE(2),
63 UNI_RANGE(1),
64 UNI_RANGE(0.5),
65 UNI_RANGE(0.2),
66 UNI_RANGE(0.1)
67 }
68};
69
70static const struct comedi_lrange range_labpc_ao = {
71 2, {
72 BIP_RANGE(5),
73 UNI_RANGE(10)
74 }
75};
76
77/*
78 * functions that do inb/outb and readb/writeb so we can use
79 * function pointers to decide which to use
80 */
81
82#ifdef CONFIG_HAS_IOPORT
83
84static unsigned int labpc_inb(struct comedi_device *dev, unsigned long reg)
85{
86 return inb(port: dev->iobase + reg);
87}
88
89static void labpc_outb(struct comedi_device *dev,
90 unsigned int byte, unsigned long reg)
91{
92 outb(value: byte, port: dev->iobase + reg);
93}
94
95#endif /* CONFIG_HAS_IOPORT */
96
97static unsigned int labpc_readb(struct comedi_device *dev, unsigned long reg)
98{
99 return readb(addr: dev->mmio + reg);
100}
101
102static void labpc_writeb(struct comedi_device *dev,
103 unsigned int byte, unsigned long reg)
104{
105 writeb(val: byte, addr: dev->mmio + reg);
106}
107
108static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
109{
110 struct labpc_private *devpriv = dev->private;
111 unsigned long flags;
112
113 spin_lock_irqsave(&dev->spinlock, flags);
114 devpriv->cmd2 &= ~(CMD2_SWTRIG | CMD2_HWTRIG | CMD2_PRETRIG);
115 devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG);
116 spin_unlock_irqrestore(lock: &dev->spinlock, flags);
117
118 devpriv->cmd3 = 0;
119 devpriv->write_byte(dev, devpriv->cmd3, CMD3_REG);
120
121 return 0;
122}
123
124static void labpc_ai_set_chan_and_gain(struct comedi_device *dev,
125 enum scan_mode mode,
126 unsigned int chan,
127 unsigned int range,
128 unsigned int aref)
129{
130 const struct labpc_boardinfo *board = dev->board_ptr;
131 struct labpc_private *devpriv = dev->private;
132
133 if (board->is_labpc1200) {
134 /*
135 * The LabPC-1200 boards do not have a gain
136 * of '0x10'. Skip the range values that would
137 * result in this gain.
138 */
139 range += (range > 0) + (range > 7);
140 }
141
142 /* munge channel bits for differential/scan disabled mode */
143 if ((mode == MODE_SINGLE_CHAN || mode == MODE_SINGLE_CHAN_INTERVAL) &&
144 aref == AREF_DIFF)
145 chan *= 2;
146 devpriv->cmd1 = CMD1_MA(chan);
147 devpriv->cmd1 |= CMD1_GAIN(range);
148
149 devpriv->write_byte(dev, devpriv->cmd1, CMD1_REG);
150}
151
152static void labpc_setup_cmd6_reg(struct comedi_device *dev,
153 struct comedi_subdevice *s,
154 enum scan_mode mode,
155 enum transfer_type xfer,
156 unsigned int range,
157 unsigned int aref,
158 bool ena_intr)
159{
160 const struct labpc_boardinfo *board = dev->board_ptr;
161 struct labpc_private *devpriv = dev->private;
162
163 if (!board->is_labpc1200)
164 return;
165
166 /* reference inputs to ground or common? */
167 if (aref != AREF_GROUND)
168 devpriv->cmd6 |= CMD6_NRSE;
169 else
170 devpriv->cmd6 &= ~CMD6_NRSE;
171
172 /* bipolar or unipolar range? */
173 if (comedi_range_is_unipolar(s, range))
174 devpriv->cmd6 |= CMD6_ADCUNI;
175 else
176 devpriv->cmd6 &= ~CMD6_ADCUNI;
177
178 /* interrupt on fifo half full? */
179 if (xfer == fifo_half_full_transfer)
180 devpriv->cmd6 |= CMD6_HFINTEN;
181 else
182 devpriv->cmd6 &= ~CMD6_HFINTEN;
183
184 /* enable interrupt on counter a1 terminal count? */
185 if (ena_intr)
186 devpriv->cmd6 |= CMD6_DQINTEN;
187 else
188 devpriv->cmd6 &= ~CMD6_DQINTEN;
189
190 /* are we scanning up or down through channels? */
191 if (mode == MODE_MULT_CHAN_UP)
192 devpriv->cmd6 |= CMD6_SCANUP;
193 else
194 devpriv->cmd6 &= ~CMD6_SCANUP;
195
196 devpriv->write_byte(dev, devpriv->cmd6, CMD6_REG);
197}
198
199static unsigned int labpc_read_adc_fifo(struct comedi_device *dev)
200{
201 struct labpc_private *devpriv = dev->private;
202 unsigned int lsb = devpriv->read_byte(dev, ADC_FIFO_REG);
203 unsigned int msb = devpriv->read_byte(dev, ADC_FIFO_REG);
204
205 return (msb << 8) | lsb;
206}
207
208static void labpc_clear_adc_fifo(struct comedi_device *dev)
209{
210 struct labpc_private *devpriv = dev->private;
211
212 devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG);
213 labpc_read_adc_fifo(dev);
214}
215
216static int labpc_ai_eoc(struct comedi_device *dev,
217 struct comedi_subdevice *s,
218 struct comedi_insn *insn,
219 unsigned long context)
220{
221 struct labpc_private *devpriv = dev->private;
222
223 devpriv->stat1 = devpriv->read_byte(dev, STAT1_REG);
224 if (devpriv->stat1 & STAT1_DAVAIL)
225 return 0;
226 return -EBUSY;
227}
228
229static int labpc_ai_insn_read(struct comedi_device *dev,
230 struct comedi_subdevice *s,
231 struct comedi_insn *insn,
232 unsigned int *data)
233{
234 struct labpc_private *devpriv = dev->private;
235 unsigned int chan = CR_CHAN(insn->chanspec);
236 unsigned int range = CR_RANGE(insn->chanspec);
237 unsigned int aref = CR_AREF(insn->chanspec);
238 int ret;
239 int i;
240
241 /* disable timed conversions, interrupt generation and dma */
242 labpc_cancel(dev, s);
243
244 labpc_ai_set_chan_and_gain(dev, mode: MODE_SINGLE_CHAN, chan, range, aref);
245
246 labpc_setup_cmd6_reg(dev, s, mode: MODE_SINGLE_CHAN, xfer: fifo_not_empty_transfer,
247 range, aref, ena_intr: false);
248
249 /* setup cmd4 register */
250 devpriv->cmd4 = 0;
251 devpriv->cmd4 |= CMD4_ECLKRCV;
252 /* single-ended/differential */
253 if (aref == AREF_DIFF)
254 devpriv->cmd4 |= CMD4_SEDIFF;
255 devpriv->write_byte(dev, devpriv->cmd4, CMD4_REG);
256
257 /* initialize pacer counter to prevent any problems */
258 comedi_8254_set_mode(i8254: devpriv->counter, counter: 0, mode: I8254_MODE2 | I8254_BINARY);
259
260 labpc_clear_adc_fifo(dev);
261
262 for (i = 0; i < insn->n; i++) {
263 /* trigger conversion */
264 devpriv->write_byte(dev, 0x1, ADC_START_CONVERT_REG);
265
266 ret = comedi_timeout(dev, s, insn, cb: labpc_ai_eoc, context: 0);
267 if (ret)
268 return ret;
269
270 data[i] = labpc_read_adc_fifo(dev);
271 }
272
273 return insn->n;
274}
275
276static bool labpc_use_continuous_mode(const struct comedi_cmd *cmd,
277 enum scan_mode mode)
278{
279 if (mode == MODE_SINGLE_CHAN || cmd->scan_begin_src == TRIG_FOLLOW)
280 return true;
281
282 return false;
283}
284
285static unsigned int labpc_ai_convert_period(const struct comedi_cmd *cmd,
286 enum scan_mode mode)
287{
288 if (cmd->convert_src != TRIG_TIMER)
289 return 0;
290
291 if (mode == MODE_SINGLE_CHAN && cmd->scan_begin_src == TRIG_TIMER)
292 return cmd->scan_begin_arg;
293
294 return cmd->convert_arg;
295}
296
297static void labpc_set_ai_convert_period(struct comedi_cmd *cmd,
298 enum scan_mode mode, unsigned int ns)
299{
300 if (cmd->convert_src != TRIG_TIMER)
301 return;
302
303 if (mode == MODE_SINGLE_CHAN &&
304 cmd->scan_begin_src == TRIG_TIMER) {
305 cmd->scan_begin_arg = ns;
306 if (cmd->convert_arg > cmd->scan_begin_arg)
307 cmd->convert_arg = cmd->scan_begin_arg;
308 } else {
309 cmd->convert_arg = ns;
310 }
311}
312
313static unsigned int labpc_ai_scan_period(const struct comedi_cmd *cmd,
314 enum scan_mode mode)
315{
316 if (cmd->scan_begin_src != TRIG_TIMER)
317 return 0;
318
319 if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER)
320 return 0;
321
322 return cmd->scan_begin_arg;
323}
324
325static void labpc_set_ai_scan_period(struct comedi_cmd *cmd,
326 enum scan_mode mode, unsigned int ns)
327{
328 if (cmd->scan_begin_src != TRIG_TIMER)
329 return;
330
331 if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER)
332 return;
333
334 cmd->scan_begin_arg = ns;
335}
336
337/* figures out what counter values to use based on command */
338static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd,
339 enum scan_mode mode)
340{
341 struct comedi_8254 *pacer = dev->pacer;
342 unsigned int convert_period = labpc_ai_convert_period(cmd, mode);
343 unsigned int scan_period = labpc_ai_scan_period(cmd, mode);
344 unsigned int base_period;
345
346 /*
347 * If both convert and scan triggers are TRIG_TIMER, then they
348 * both rely on counter b0. If only one TRIG_TIMER is used, we
349 * can use the generic cascaded timing functions.
350 */
351 if (convert_period && scan_period) {
352 /*
353 * pick the lowest divisor value we can (for maximum input
354 * clock speed on convert and scan counters)
355 */
356 pacer->next_div1 = (scan_period - 1) /
357 (pacer->osc_base * I8254_MAX_COUNT) + 1;
358
359 comedi_check_trigger_arg_min(arg: &pacer->next_div1, val: 2);
360 comedi_check_trigger_arg_max(arg: &pacer->next_div1,
361 I8254_MAX_COUNT);
362
363 base_period = pacer->osc_base * pacer->next_div1;
364
365 /* set a0 for conversion frequency and b1 for scan frequency */
366 switch (cmd->flags & CMDF_ROUND_MASK) {
367 default:
368 case CMDF_ROUND_NEAREST:
369 pacer->next_div = DIV_ROUND_CLOSEST(convert_period,
370 base_period);
371 pacer->next_div2 = DIV_ROUND_CLOSEST(scan_period,
372 base_period);
373 break;
374 case CMDF_ROUND_UP:
375 pacer->next_div = DIV_ROUND_UP(convert_period,
376 base_period);
377 pacer->next_div2 = DIV_ROUND_UP(scan_period,
378 base_period);
379 break;
380 case CMDF_ROUND_DOWN:
381 pacer->next_div = convert_period / base_period;
382 pacer->next_div2 = scan_period / base_period;
383 break;
384 }
385 /* make sure a0 and b1 values are acceptable */
386 comedi_check_trigger_arg_min(arg: &pacer->next_div, val: 2);
387 comedi_check_trigger_arg_max(arg: &pacer->next_div, I8254_MAX_COUNT);
388 comedi_check_trigger_arg_min(arg: &pacer->next_div2, val: 2);
389 comedi_check_trigger_arg_max(arg: &pacer->next_div2,
390 I8254_MAX_COUNT);
391
392 /* write corrected timings to command */
393 labpc_set_ai_convert_period(cmd, mode,
394 ns: base_period * pacer->next_div);
395 labpc_set_ai_scan_period(cmd, mode,
396 ns: base_period * pacer->next_div2);
397 } else if (scan_period) {
398 /*
399 * calculate cascaded counter values
400 * that give desired scan timing
401 * (pacer->next_div2 / pacer->next_div1)
402 */
403 comedi_8254_cascade_ns_to_timer(i8254: pacer, nanosec: &scan_period,
404 flags: cmd->flags);
405 labpc_set_ai_scan_period(cmd, mode, ns: scan_period);
406 } else if (convert_period) {
407 /*
408 * calculate cascaded counter values
409 * that give desired conversion timing
410 * (pacer->next_div / pacer->next_div1)
411 */
412 comedi_8254_cascade_ns_to_timer(i8254: pacer, nanosec: &convert_period,
413 flags: cmd->flags);
414 /* transfer div2 value so correct timer gets updated */
415 pacer->next_div = pacer->next_div2;
416 labpc_set_ai_convert_period(cmd, mode, ns: convert_period);
417 }
418}
419
420static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd *cmd)
421{
422 unsigned int chan0;
423 unsigned int chan1;
424
425 if (cmd->chanlist_len == 1)
426 return MODE_SINGLE_CHAN;
427
428 /* chanlist may be NULL during cmdtest */
429 if (!cmd->chanlist)
430 return MODE_MULT_CHAN_UP;
431
432 chan0 = CR_CHAN(cmd->chanlist[0]);
433 chan1 = CR_CHAN(cmd->chanlist[1]);
434
435 if (chan0 < chan1)
436 return MODE_MULT_CHAN_UP;
437
438 if (chan0 > chan1)
439 return MODE_MULT_CHAN_DOWN;
440
441 return MODE_SINGLE_CHAN_INTERVAL;
442}
443
444static int labpc_ai_check_chanlist(struct comedi_device *dev,
445 struct comedi_subdevice *s,
446 struct comedi_cmd *cmd)
447{
448 enum scan_mode mode = labpc_ai_scan_mode(cmd);
449 unsigned int chan0 = CR_CHAN(cmd->chanlist[0]);
450 unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
451 unsigned int aref0 = CR_AREF(cmd->chanlist[0]);
452 int i;
453
454 for (i = 0; i < cmd->chanlist_len; i++) {
455 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
456 unsigned int range = CR_RANGE(cmd->chanlist[i]);
457 unsigned int aref = CR_AREF(cmd->chanlist[i]);
458
459 switch (mode) {
460 case MODE_SINGLE_CHAN:
461 break;
462 case MODE_SINGLE_CHAN_INTERVAL:
463 if (chan != chan0) {
464 dev_dbg(dev->class_dev,
465 "channel scanning order specified in chanlist is not supported by hardware\n");
466 return -EINVAL;
467 }
468 break;
469 case MODE_MULT_CHAN_UP:
470 if (chan != i) {
471 dev_dbg(dev->class_dev,
472 "channel scanning order specified in chanlist is not supported by hardware\n");
473 return -EINVAL;
474 }
475 break;
476 case MODE_MULT_CHAN_DOWN:
477 if (chan != (cmd->chanlist_len - i - 1)) {
478 dev_dbg(dev->class_dev,
479 "channel scanning order specified in chanlist is not supported by hardware\n");
480 return -EINVAL;
481 }
482 break;
483 }
484
485 if (range != range0) {
486 dev_dbg(dev->class_dev,
487 "entries in chanlist must all have the same range\n");
488 return -EINVAL;
489 }
490
491 if (aref != aref0) {
492 dev_dbg(dev->class_dev,
493 "entries in chanlist must all have the same reference\n");
494 return -EINVAL;
495 }
496 }
497
498 return 0;
499}
500
501static int labpc_ai_cmdtest(struct comedi_device *dev,
502 struct comedi_subdevice *s, struct comedi_cmd *cmd)
503{
504 const struct labpc_boardinfo *board = dev->board_ptr;
505 int err = 0;
506 int tmp, tmp2;
507 unsigned int stop_mask;
508 enum scan_mode mode;
509
510 /* Step 1 : check if triggers are trivially valid */
511
512 err |= comedi_check_trigger_src(src: &cmd->start_src, TRIG_NOW | TRIG_EXT);
513 err |= comedi_check_trigger_src(src: &cmd->scan_begin_src,
514 TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
515 err |= comedi_check_trigger_src(src: &cmd->convert_src,
516 TRIG_TIMER | TRIG_EXT);
517 err |= comedi_check_trigger_src(src: &cmd->scan_end_src, TRIG_COUNT);
518
519 stop_mask = TRIG_COUNT | TRIG_NONE;
520 if (board->is_labpc1200)
521 stop_mask |= TRIG_EXT;
522 err |= comedi_check_trigger_src(src: &cmd->stop_src, flags: stop_mask);
523
524 if (err)
525 return 1;
526
527 /* Step 2a : make sure trigger sources are unique */
528
529 err |= comedi_check_trigger_is_unique(src: cmd->start_src);
530 err |= comedi_check_trigger_is_unique(src: cmd->scan_begin_src);
531 err |= comedi_check_trigger_is_unique(src: cmd->convert_src);
532 err |= comedi_check_trigger_is_unique(src: cmd->stop_src);
533
534 /* Step 2b : and mutually compatible */
535
536 /* can't have external stop and start triggers at once */
537 if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT)
538 err++;
539
540 if (err)
541 return 2;
542
543 /* Step 3: check if arguments are trivially valid */
544
545 switch (cmd->start_src) {
546 case TRIG_NOW:
547 err |= comedi_check_trigger_arg_is(arg: &cmd->start_arg, val: 0);
548 break;
549 case TRIG_EXT:
550 /* start_arg value is ignored */
551 break;
552 }
553
554 if (!cmd->chanlist_len)
555 err |= -EINVAL;
556 err |= comedi_check_trigger_arg_is(arg: &cmd->scan_end_arg,
557 val: cmd->chanlist_len);
558
559 if (cmd->convert_src == TRIG_TIMER) {
560 err |= comedi_check_trigger_arg_min(arg: &cmd->convert_arg,
561 val: board->ai_speed);
562 }
563
564 /* make sure scan timing is not too fast */
565 if (cmd->scan_begin_src == TRIG_TIMER) {
566 if (cmd->convert_src == TRIG_TIMER) {
567 err |= comedi_check_trigger_arg_min(
568 arg: &cmd->scan_begin_arg,
569 val: cmd->convert_arg * cmd->chanlist_len);
570 }
571 err |= comedi_check_trigger_arg_min(
572 arg: &cmd->scan_begin_arg,
573 val: board->ai_speed * cmd->chanlist_len);
574 }
575
576 switch (cmd->stop_src) {
577 case TRIG_COUNT:
578 err |= comedi_check_trigger_arg_min(arg: &cmd->stop_arg, val: 1);
579 break;
580 case TRIG_NONE:
581 err |= comedi_check_trigger_arg_is(arg: &cmd->stop_arg, val: 0);
582 break;
583 /*
584 * TRIG_EXT doesn't care since it doesn't
585 * trigger off a numbered channel
586 */
587 default:
588 break;
589 }
590
591 if (err)
592 return 3;
593
594 /* step 4: fix up any arguments */
595
596 tmp = cmd->convert_arg;
597 tmp2 = cmd->scan_begin_arg;
598 mode = labpc_ai_scan_mode(cmd);
599 labpc_adc_timing(dev, cmd, mode);
600 if (tmp != cmd->convert_arg || tmp2 != cmd->scan_begin_arg)
601 err++;
602
603 if (err)
604 return 4;
605
606 /* Step 5: check channel list if it exists */
607 if (cmd->chanlist && cmd->chanlist_len > 0)
608 err |= labpc_ai_check_chanlist(dev, s, cmd);
609
610 if (err)
611 return 5;
612
613 return 0;
614}
615
616static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
617{
618 const struct labpc_boardinfo *board = dev->board_ptr;
619 struct labpc_private *devpriv = dev->private;
620 struct comedi_async *async = s->async;
621 struct comedi_cmd *cmd = &async->cmd;
622 enum scan_mode mode = labpc_ai_scan_mode(cmd);
623 unsigned int chanspec = (mode == MODE_MULT_CHAN_UP) ?
624 cmd->chanlist[cmd->chanlist_len - 1] :
625 cmd->chanlist[0];
626 unsigned int chan = CR_CHAN(chanspec);
627 unsigned int range = CR_RANGE(chanspec);
628 unsigned int aref = CR_AREF(chanspec);
629 enum transfer_type xfer;
630 unsigned long flags;
631
632 /* make sure board is disabled before setting up acquisition */
633 labpc_cancel(dev, s);
634
635 /* initialize software conversion count */
636 if (cmd->stop_src == TRIG_COUNT)
637 devpriv->count = cmd->stop_arg * cmd->chanlist_len;
638
639 /* setup hardware conversion counter */
640 if (cmd->stop_src == TRIG_EXT) {
641 /*
642 * load counter a1 with count of 3
643 * (pc+ manual says this is minimum allowed) using mode 0
644 */
645 comedi_8254_load(i8254: devpriv->counter, counter: 1,
646 val: 3, mode: I8254_MODE0 | I8254_BINARY);
647 } else {
648 /* just put counter a1 in mode 0 to set its output low */
649 comedi_8254_set_mode(i8254: devpriv->counter, counter: 1,
650 mode: I8254_MODE0 | I8254_BINARY);
651 }
652
653 /* figure out what method we will use to transfer data */
654 if (devpriv->dma &&
655 (cmd->flags & (CMDF_WAKE_EOS | CMDF_PRIORITY)) == 0) {
656 /*
657 * dma unsafe at RT priority,
658 * and too much setup time for CMDF_WAKE_EOS
659 */
660 xfer = isa_dma_transfer;
661 } else if (board->is_labpc1200 &&
662 (cmd->flags & CMDF_WAKE_EOS) == 0 &&
663 (cmd->stop_src != TRIG_COUNT || devpriv->count > 256)) {
664 /*
665 * pc-plus has no fifo-half full interrupt
666 * wake-end-of-scan should interrupt on fifo not empty
667 * make sure we are taking more than just a few points
668 */
669 xfer = fifo_half_full_transfer;
670 } else {
671 xfer = fifo_not_empty_transfer;
672 }
673 devpriv->current_transfer = xfer;
674
675 labpc_ai_set_chan_and_gain(dev, mode, chan, range, aref);
676
677 labpc_setup_cmd6_reg(dev, s, mode, xfer, range, aref,
678 ena_intr: (cmd->stop_src == TRIG_EXT));
679
680 /* manual says to set scan enable bit on second pass */
681 if (mode == MODE_MULT_CHAN_UP || mode == MODE_MULT_CHAN_DOWN) {
682 devpriv->cmd1 |= CMD1_SCANEN;
683 /*
684 * Need a brief delay before enabling scan, or scan
685 * list will get screwed when you switch between
686 * scan up to scan down mode - dunno why.
687 */
688 udelay(1);
689 devpriv->write_byte(dev, devpriv->cmd1, CMD1_REG);
690 }
691
692 devpriv->write_byte(dev, cmd->chanlist_len, INTERVAL_COUNT_REG);
693 /* load count */
694 devpriv->write_byte(dev, 0x1, INTERVAL_STROBE_REG);
695
696 if (cmd->convert_src == TRIG_TIMER ||
697 cmd->scan_begin_src == TRIG_TIMER) {
698 struct comedi_8254 *pacer = dev->pacer;
699 struct comedi_8254 *counter = devpriv->counter;
700
701 comedi_8254_update_divisors(i8254: pacer);
702
703 /* set up pacing */
704 comedi_8254_load(i8254: pacer, counter: 0, val: pacer->divisor1,
705 mode: I8254_MODE3 | I8254_BINARY);
706
707 /* set up conversion pacing */
708 comedi_8254_set_mode(i8254: counter, counter: 0, mode: I8254_MODE2 | I8254_BINARY);
709 if (labpc_ai_convert_period(cmd, mode))
710 comedi_8254_write(i8254: counter, counter: 0, val: pacer->divisor);
711
712 /* set up scan pacing */
713 if (labpc_ai_scan_period(cmd, mode))
714 comedi_8254_load(i8254: pacer, counter: 1, val: pacer->divisor2,
715 mode: I8254_MODE2 | I8254_BINARY);
716 }
717
718 labpc_clear_adc_fifo(dev);
719
720 if (xfer == isa_dma_transfer)
721 labpc_setup_dma(dev, s);
722
723 /* enable error interrupts */
724 devpriv->cmd3 |= CMD3_ERRINTEN;
725 /* enable fifo not empty interrupt? */
726 if (xfer == fifo_not_empty_transfer)
727 devpriv->cmd3 |= CMD3_FIFOINTEN;
728 devpriv->write_byte(dev, devpriv->cmd3, CMD3_REG);
729
730 /* setup any external triggering/pacing (cmd4 register) */
731 devpriv->cmd4 = 0;
732 if (cmd->convert_src != TRIG_EXT)
733 devpriv->cmd4 |= CMD4_ECLKRCV;
734 /*
735 * XXX should discard first scan when using interval scanning
736 * since manual says it is not synced with scan clock.
737 */
738 if (!labpc_use_continuous_mode(cmd, mode)) {
739 devpriv->cmd4 |= CMD4_INTSCAN;
740 if (cmd->scan_begin_src == TRIG_EXT)
741 devpriv->cmd4 |= CMD4_EOIRCV;
742 }
743 /* single-ended/differential */
744 if (aref == AREF_DIFF)
745 devpriv->cmd4 |= CMD4_SEDIFF;
746 devpriv->write_byte(dev, devpriv->cmd4, CMD4_REG);
747
748 /* startup acquisition */
749
750 spin_lock_irqsave(&dev->spinlock, flags);
751
752 /* use 2 cascaded counters for pacing */
753 devpriv->cmd2 |= CMD2_TBSEL;
754
755 devpriv->cmd2 &= ~(CMD2_SWTRIG | CMD2_HWTRIG | CMD2_PRETRIG);
756 if (cmd->start_src == TRIG_EXT)
757 devpriv->cmd2 |= CMD2_HWTRIG;
758 else
759 devpriv->cmd2 |= CMD2_SWTRIG;
760 if (cmd->stop_src == TRIG_EXT)
761 devpriv->cmd2 |= (CMD2_HWTRIG | CMD2_PRETRIG);
762
763 devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG);
764
765 spin_unlock_irqrestore(lock: &dev->spinlock, flags);
766
767 return 0;
768}
769
770/* read all available samples from ai fifo */
771static int labpc_drain_fifo(struct comedi_device *dev)
772{
773 struct labpc_private *devpriv = dev->private;
774 struct comedi_async *async = dev->read_subdev->async;
775 struct comedi_cmd *cmd = &async->cmd;
776 unsigned short data;
777 const int timeout = 10000;
778 unsigned int i;
779
780 devpriv->stat1 = devpriv->read_byte(dev, STAT1_REG);
781
782 for (i = 0; (devpriv->stat1 & STAT1_DAVAIL) && i < timeout;
783 i++) {
784 /* quit if we have all the data we want */
785 if (cmd->stop_src == TRIG_COUNT) {
786 if (devpriv->count == 0)
787 break;
788 devpriv->count--;
789 }
790 data = labpc_read_adc_fifo(dev);
791 comedi_buf_write_samples(s: dev->read_subdev, data: &data, nsamples: 1);
792 devpriv->stat1 = devpriv->read_byte(dev, STAT1_REG);
793 }
794 if (i == timeout) {
795 dev_err(dev->class_dev, "ai timeout, fifo never empties\n");
796 async->events |= COMEDI_CB_ERROR;
797 return -1;
798 }
799
800 return 0;
801}
802
803/*
804 * Makes sure all data acquired by board is transferred to comedi (used
805 * when acquisition is terminated by stop_src == TRIG_EXT).
806 */
807static void labpc_drain_dregs(struct comedi_device *dev)
808{
809 struct labpc_private *devpriv = dev->private;
810
811 if (devpriv->current_transfer == isa_dma_transfer)
812 labpc_drain_dma(dev);
813
814 labpc_drain_fifo(dev);
815}
816
817/* interrupt service routine */
818static irqreturn_t labpc_interrupt(int irq, void *d)
819{
820 struct comedi_device *dev = d;
821 const struct labpc_boardinfo *board = dev->board_ptr;
822 struct labpc_private *devpriv = dev->private;
823 struct comedi_subdevice *s = dev->read_subdev;
824 struct comedi_async *async;
825 struct comedi_cmd *cmd;
826
827 if (!dev->attached) {
828 dev_err(dev->class_dev, "premature interrupt\n");
829 return IRQ_HANDLED;
830 }
831
832 async = s->async;
833 cmd = &async->cmd;
834
835 /* read board status */
836 devpriv->stat1 = devpriv->read_byte(dev, STAT1_REG);
837 if (board->is_labpc1200)
838 devpriv->stat2 = devpriv->read_byte(dev, STAT2_REG);
839
840 if ((devpriv->stat1 & (STAT1_GATA0 | STAT1_CNTINT | STAT1_OVERFLOW |
841 STAT1_OVERRUN | STAT1_DAVAIL)) == 0 &&
842 (devpriv->stat2 & STAT2_OUTA1) == 0 &&
843 (devpriv->stat2 & STAT2_FIFONHF)) {
844 return IRQ_NONE;
845 }
846
847 if (devpriv->stat1 & STAT1_OVERRUN) {
848 /* clear error interrupt */
849 devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG);
850 async->events |= COMEDI_CB_ERROR;
851 comedi_handle_events(dev, s);
852 dev_err(dev->class_dev, "overrun\n");
853 return IRQ_HANDLED;
854 }
855
856 if (devpriv->current_transfer == isa_dma_transfer)
857 labpc_handle_dma_status(dev);
858 else
859 labpc_drain_fifo(dev);
860
861 if (devpriv->stat1 & STAT1_CNTINT) {
862 dev_err(dev->class_dev, "handled timer interrupt?\n");
863 /* clear it */
864 devpriv->write_byte(dev, 0x1, TIMER_CLEAR_REG);
865 }
866
867 if (devpriv->stat1 & STAT1_OVERFLOW) {
868 /* clear error interrupt */
869 devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG);
870 async->events |= COMEDI_CB_ERROR;
871 comedi_handle_events(dev, s);
872 dev_err(dev->class_dev, "overflow\n");
873 return IRQ_HANDLED;
874 }
875 /* handle external stop trigger */
876 if (cmd->stop_src == TRIG_EXT) {
877 if (devpriv->stat2 & STAT2_OUTA1) {
878 labpc_drain_dregs(dev);
879 async->events |= COMEDI_CB_EOA;
880 }
881 }
882
883 /* TRIG_COUNT end of acquisition */
884 if (cmd->stop_src == TRIG_COUNT) {
885 if (devpriv->count == 0)
886 async->events |= COMEDI_CB_EOA;
887 }
888
889 comedi_handle_events(dev, s);
890 return IRQ_HANDLED;
891}
892
893static void labpc_ao_write(struct comedi_device *dev,
894 struct comedi_subdevice *s,
895 unsigned int chan, unsigned int val)
896{
897 struct labpc_private *devpriv = dev->private;
898
899 devpriv->write_byte(dev, val & 0xff, DAC_LSB_REG(chan));
900 devpriv->write_byte(dev, (val >> 8) & 0xff, DAC_MSB_REG(chan));
901
902 s->readback[chan] = val;
903}
904
905static int labpc_ao_insn_write(struct comedi_device *dev,
906 struct comedi_subdevice *s,
907 struct comedi_insn *insn,
908 unsigned int *data)
909{
910 const struct labpc_boardinfo *board = dev->board_ptr;
911 struct labpc_private *devpriv = dev->private;
912 unsigned int channel;
913 unsigned int range;
914 unsigned int i;
915 unsigned long flags;
916
917 channel = CR_CHAN(insn->chanspec);
918
919 /*
920 * Turn off pacing of analog output channel.
921 * NOTE: hardware bug in daqcard-1200 means pacing cannot
922 * be independently enabled/disabled for its the two channels.
923 */
924 spin_lock_irqsave(&dev->spinlock, flags);
925 devpriv->cmd2 &= ~CMD2_LDAC(channel);
926 devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG);
927 spin_unlock_irqrestore(lock: &dev->spinlock, flags);
928
929 /* set range */
930 if (board->is_labpc1200) {
931 range = CR_RANGE(insn->chanspec);
932 if (comedi_range_is_unipolar(s, range))
933 devpriv->cmd6 |= CMD6_DACUNI(channel);
934 else
935 devpriv->cmd6 &= ~CMD6_DACUNI(channel);
936 /* write to register */
937 devpriv->write_byte(dev, devpriv->cmd6, CMD6_REG);
938 }
939 /* send data */
940 for (i = 0; i < insn->n; i++)
941 labpc_ao_write(dev, s, chan: channel, val: data[i]);
942
943 return insn->n;
944}
945
946/* lowlevel write to eeprom/dac */
947static void labpc_serial_out(struct comedi_device *dev, unsigned int value,
948 unsigned int value_width)
949{
950 struct labpc_private *devpriv = dev->private;
951 int i;
952
953 for (i = 1; i <= value_width; i++) {
954 /* clear serial clock */
955 devpriv->cmd5 &= ~CMD5_SCLK;
956 /* send bits most significant bit first */
957 if (value & (1 << (value_width - i)))
958 devpriv->cmd5 |= CMD5_SDATA;
959 else
960 devpriv->cmd5 &= ~CMD5_SDATA;
961 udelay(1);
962 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
963 /* set clock to load bit */
964 devpriv->cmd5 |= CMD5_SCLK;
965 udelay(1);
966 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
967 }
968}
969
970/* lowlevel read from eeprom */
971static unsigned int labpc_serial_in(struct comedi_device *dev)
972{
973 struct labpc_private *devpriv = dev->private;
974 unsigned int value = 0;
975 int i;
976 const int value_width = 8; /* number of bits wide values are */
977
978 for (i = 1; i <= value_width; i++) {
979 /* set serial clock */
980 devpriv->cmd5 |= CMD5_SCLK;
981 udelay(1);
982 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
983 /* clear clock bit */
984 devpriv->cmd5 &= ~CMD5_SCLK;
985 udelay(1);
986 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
987 /* read bits most significant bit first */
988 udelay(1);
989 devpriv->stat2 = devpriv->read_byte(dev, STAT2_REG);
990 if (devpriv->stat2 & STAT2_PROMOUT)
991 value |= 1 << (value_width - i);
992 }
993
994 return value;
995}
996
997static unsigned int labpc_eeprom_read(struct comedi_device *dev,
998 unsigned int address)
999{
1000 struct labpc_private *devpriv = dev->private;
1001 unsigned int value;
1002 /* bits to tell eeprom to expect a read */
1003 const int read_instruction = 0x3;
1004 /* 8 bit write lengths to eeprom */
1005 const int write_length = 8;
1006
1007 /* enable read/write to eeprom */
1008 devpriv->cmd5 &= ~CMD5_EEPROMCS;
1009 udelay(1);
1010 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1011 devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT);
1012 udelay(1);
1013 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1014
1015 /* send read instruction */
1016 labpc_serial_out(dev, value: read_instruction, value_width: write_length);
1017 /* send 8 bit address to read from */
1018 labpc_serial_out(dev, value: address, value_width: write_length);
1019 /* read result */
1020 value = labpc_serial_in(dev);
1021
1022 /* disable read/write to eeprom */
1023 devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT);
1024 udelay(1);
1025 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1026
1027 return value;
1028}
1029
1030static unsigned int labpc_eeprom_read_status(struct comedi_device *dev)
1031{
1032 struct labpc_private *devpriv = dev->private;
1033 unsigned int value;
1034 const int read_status_instruction = 0x5;
1035 const int write_length = 8; /* 8 bit write lengths to eeprom */
1036
1037 /* enable read/write to eeprom */
1038 devpriv->cmd5 &= ~CMD5_EEPROMCS;
1039 udelay(1);
1040 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1041 devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT);
1042 udelay(1);
1043 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1044
1045 /* send read status instruction */
1046 labpc_serial_out(dev, value: read_status_instruction, value_width: write_length);
1047 /* read result */
1048 value = labpc_serial_in(dev);
1049
1050 /* disable read/write to eeprom */
1051 devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT);
1052 udelay(1);
1053 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1054
1055 return value;
1056}
1057
1058static void labpc_eeprom_write(struct comedi_device *dev,
1059 unsigned int address, unsigned int value)
1060{
1061 struct labpc_private *devpriv = dev->private;
1062 const int write_enable_instruction = 0x6;
1063 const int write_instruction = 0x2;
1064 const int write_length = 8; /* 8 bit write lengths to eeprom */
1065
1066 /* enable read/write to eeprom */
1067 devpriv->cmd5 &= ~CMD5_EEPROMCS;
1068 udelay(1);
1069 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1070 devpriv->cmd5 |= (CMD5_EEPROMCS | CMD5_WRTPRT);
1071 udelay(1);
1072 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1073
1074 /* send write_enable instruction */
1075 labpc_serial_out(dev, value: write_enable_instruction, value_width: write_length);
1076 devpriv->cmd5 &= ~CMD5_EEPROMCS;
1077 udelay(1);
1078 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1079
1080 /* send write instruction */
1081 devpriv->cmd5 |= CMD5_EEPROMCS;
1082 udelay(1);
1083 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1084 labpc_serial_out(dev, value: write_instruction, value_width: write_length);
1085 /* send 8 bit address to write to */
1086 labpc_serial_out(dev, value: address, value_width: write_length);
1087 /* write value */
1088 labpc_serial_out(dev, value, value_width: write_length);
1089 devpriv->cmd5 &= ~CMD5_EEPROMCS;
1090 udelay(1);
1091 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1092
1093 /* disable read/write to eeprom */
1094 devpriv->cmd5 &= ~(CMD5_EEPROMCS | CMD5_WRTPRT);
1095 udelay(1);
1096 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1097}
1098
1099/* writes to 8 bit calibration dacs */
1100static void write_caldac(struct comedi_device *dev, unsigned int channel,
1101 unsigned int value)
1102{
1103 struct labpc_private *devpriv = dev->private;
1104
1105 /* clear caldac load bit and make sure we don't write to eeprom */
1106 devpriv->cmd5 &= ~(CMD5_CALDACLD | CMD5_EEPROMCS | CMD5_WRTPRT);
1107 udelay(1);
1108 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1109
1110 /* write 4 bit channel */
1111 labpc_serial_out(dev, value: channel, value_width: 4);
1112 /* write 8 bit caldac value */
1113 labpc_serial_out(dev, value, value_width: 8);
1114
1115 /* set and clear caldac bit to load caldac value */
1116 devpriv->cmd5 |= CMD5_CALDACLD;
1117 udelay(1);
1118 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1119 devpriv->cmd5 &= ~CMD5_CALDACLD;
1120 udelay(1);
1121 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1122}
1123
1124static int labpc_calib_insn_write(struct comedi_device *dev,
1125 struct comedi_subdevice *s,
1126 struct comedi_insn *insn,
1127 unsigned int *data)
1128{
1129 unsigned int chan = CR_CHAN(insn->chanspec);
1130
1131 /*
1132 * Only write the last data value to the caldac. Preceding
1133 * data would be overwritten anyway.
1134 */
1135 if (insn->n > 0) {
1136 unsigned int val = data[insn->n - 1];
1137
1138 if (s->readback[chan] != val) {
1139 write_caldac(dev, channel: chan, value: val);
1140 s->readback[chan] = val;
1141 }
1142 }
1143
1144 return insn->n;
1145}
1146
1147static int labpc_eeprom_ready(struct comedi_device *dev,
1148 struct comedi_subdevice *s,
1149 struct comedi_insn *insn,
1150 unsigned long context)
1151{
1152 unsigned int status;
1153
1154 /* make sure there isn't already a write in progress */
1155 status = labpc_eeprom_read_status(dev);
1156 if ((status & 0x1) == 0)
1157 return 0;
1158 return -EBUSY;
1159}
1160
1161static int labpc_eeprom_insn_write(struct comedi_device *dev,
1162 struct comedi_subdevice *s,
1163 struct comedi_insn *insn,
1164 unsigned int *data)
1165{
1166 unsigned int chan = CR_CHAN(insn->chanspec);
1167 int ret;
1168
1169 /* only allow writes to user area of eeprom */
1170 if (chan < 16 || chan > 127)
1171 return -EINVAL;
1172
1173 /*
1174 * Only write the last data value to the eeprom. Preceding
1175 * data would be overwritten anyway.
1176 */
1177 if (insn->n > 0) {
1178 unsigned int val = data[insn->n - 1];
1179
1180 ret = comedi_timeout(dev, s, insn, cb: labpc_eeprom_ready, context: 0);
1181 if (ret)
1182 return ret;
1183
1184 labpc_eeprom_write(dev, address: chan, value: val);
1185 s->readback[chan] = val;
1186 }
1187
1188 return insn->n;
1189}
1190
1191int labpc_common_attach(struct comedi_device *dev,
1192 unsigned int irq, unsigned long isr_flags)
1193{
1194 const struct labpc_boardinfo *board = dev->board_ptr;
1195 struct labpc_private *devpriv;
1196 struct comedi_subdevice *s;
1197 int ret;
1198 int i;
1199
1200 devpriv = comedi_alloc_devpriv(dev, size: sizeof(*devpriv));
1201 if (!devpriv)
1202 return -ENOMEM;
1203
1204 if (dev->mmio) {
1205 devpriv->read_byte = labpc_readb;
1206 devpriv->write_byte = labpc_writeb;
1207 } else {
1208#ifdef CONFIG_HAS_IOPORT
1209 devpriv->read_byte = labpc_inb;
1210 devpriv->write_byte = labpc_outb;
1211#else
1212 return -ENXIO;
1213#endif
1214 }
1215
1216 /* initialize board's command registers */
1217 devpriv->write_byte(dev, devpriv->cmd1, CMD1_REG);
1218 devpriv->write_byte(dev, devpriv->cmd2, CMD2_REG);
1219 devpriv->write_byte(dev, devpriv->cmd3, CMD3_REG);
1220 devpriv->write_byte(dev, devpriv->cmd4, CMD4_REG);
1221 if (board->is_labpc1200) {
1222 devpriv->write_byte(dev, devpriv->cmd5, CMD5_REG);
1223 devpriv->write_byte(dev, devpriv->cmd6, CMD6_REG);
1224 }
1225
1226 if (irq) {
1227 ret = request_irq(irq, handler: labpc_interrupt, flags: isr_flags,
1228 name: dev->board_name, dev);
1229 if (ret == 0)
1230 dev->irq = irq;
1231 }
1232
1233 if (dev->mmio) {
1234 dev->pacer =
1235 comedi_8254_mm_alloc(mmio: dev->mmio + COUNTER_B_BASE_REG,
1236 I8254_OSC_BASE_2MHZ, I8254_IO8, regshift: 0);
1237 devpriv->counter =
1238 comedi_8254_mm_alloc(mmio: dev->mmio + COUNTER_A_BASE_REG,
1239 I8254_OSC_BASE_2MHZ, I8254_IO8, regshift: 0);
1240 } else {
1241 dev->pacer =
1242 comedi_8254_io_alloc(iobase: dev->iobase + COUNTER_B_BASE_REG,
1243 I8254_OSC_BASE_2MHZ, I8254_IO8, regshift: 0);
1244 devpriv->counter =
1245 comedi_8254_io_alloc(iobase: dev->iobase + COUNTER_A_BASE_REG,
1246 I8254_OSC_BASE_2MHZ, I8254_IO8, regshift: 0);
1247 }
1248 if (IS_ERR(ptr: dev->pacer))
1249 return PTR_ERR(ptr: dev->pacer);
1250 if (IS_ERR(ptr: devpriv->counter))
1251 return PTR_ERR(ptr: devpriv->counter);
1252
1253 ret = comedi_alloc_subdevices(dev, num_subdevices: 5);
1254 if (ret)
1255 return ret;
1256
1257 /* analog input subdevice */
1258 s = &dev->subdevices[0];
1259 s->type = COMEDI_SUBD_AI;
1260 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF;
1261 s->n_chan = 8;
1262 s->len_chanlist = 8;
1263 s->maxdata = 0x0fff;
1264 s->range_table = board->is_labpc1200 ?
1265 &range_labpc_1200_ai : &range_labpc_plus_ai;
1266 s->insn_read = labpc_ai_insn_read;
1267 if (dev->irq) {
1268 dev->read_subdev = s;
1269 s->subdev_flags |= SDF_CMD_READ;
1270 s->do_cmd = labpc_ai_cmd;
1271 s->do_cmdtest = labpc_ai_cmdtest;
1272 s->cancel = labpc_cancel;
1273 }
1274
1275 /* analog output */
1276 s = &dev->subdevices[1];
1277 if (board->has_ao) {
1278 s->type = COMEDI_SUBD_AO;
1279 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
1280 s->n_chan = 2;
1281 s->maxdata = 0x0fff;
1282 s->range_table = &range_labpc_ao;
1283 s->insn_write = labpc_ao_insn_write;
1284
1285 ret = comedi_alloc_subdev_readback(s);
1286 if (ret)
1287 return ret;
1288
1289 /* initialize analog outputs to a known value */
1290 for (i = 0; i < s->n_chan; i++)
1291 labpc_ao_write(dev, s, chan: i, val: s->maxdata / 2);
1292 } else {
1293 s->type = COMEDI_SUBD_UNUSED;
1294 }
1295
1296 /* 8255 dio */
1297 s = &dev->subdevices[2];
1298 if (dev->mmio)
1299 ret = subdev_8255_mm_init(dev, s, DIO_BASE_REG);
1300 else
1301 ret = subdev_8255_io_init(dev, s, DIO_BASE_REG);
1302 if (ret)
1303 return ret;
1304
1305 /* calibration subdevices for boards that have one */
1306 s = &dev->subdevices[3];
1307 if (board->is_labpc1200) {
1308 s->type = COMEDI_SUBD_CALIB;
1309 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1310 s->n_chan = 16;
1311 s->maxdata = 0xff;
1312 s->insn_write = labpc_calib_insn_write;
1313
1314 ret = comedi_alloc_subdev_readback(s);
1315 if (ret)
1316 return ret;
1317
1318 for (i = 0; i < s->n_chan; i++) {
1319 write_caldac(dev, channel: i, value: s->maxdata / 2);
1320 s->readback[i] = s->maxdata / 2;
1321 }
1322 } else {
1323 s->type = COMEDI_SUBD_UNUSED;
1324 }
1325
1326 /* EEPROM (256 bytes) */
1327 s = &dev->subdevices[4];
1328 if (board->is_labpc1200) {
1329 s->type = COMEDI_SUBD_MEMORY;
1330 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1331 s->n_chan = 256;
1332 s->maxdata = 0xff;
1333 s->insn_write = labpc_eeprom_insn_write;
1334
1335 ret = comedi_alloc_subdev_readback(s);
1336 if (ret)
1337 return ret;
1338
1339 for (i = 0; i < s->n_chan; i++)
1340 s->readback[i] = labpc_eeprom_read(dev, address: i);
1341 } else {
1342 s->type = COMEDI_SUBD_UNUSED;
1343 }
1344
1345 return 0;
1346}
1347EXPORT_SYMBOL_GPL(labpc_common_attach);
1348
1349void labpc_common_detach(struct comedi_device *dev)
1350{
1351 struct labpc_private *devpriv = dev->private;
1352
1353 if (devpriv) {
1354 if (!IS_ERR(ptr: devpriv->counter))
1355 kfree(objp: devpriv->counter);
1356 }
1357}
1358EXPORT_SYMBOL_GPL(labpc_common_detach);
1359
1360static int __init labpc_common_init(void)
1361{
1362 return 0;
1363}
1364module_init(labpc_common_init);
1365
1366static void __exit labpc_common_exit(void)
1367{
1368}
1369module_exit(labpc_common_exit);
1370
1371MODULE_AUTHOR("Comedi https://www.comedi.org");
1372MODULE_DESCRIPTION("Comedi helper for ni_labpc, ni_labpc_pci, ni_labpc_cs");
1373MODULE_LICENSE("GPL");
1374

source code of linux/drivers/comedi/drivers/ni_labpc_common.c