1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * comedi/drivers/rtd520.c
4 * Comedi driver for Real Time Devices (RTD) PCI4520/DM7520
5 *
6 * COMEDI - Linux Control and Measurement Device Interface
7 * Copyright (C) 2001 David A. Schleef <ds@schleef.org>
8 */
9
10/*
11 * Driver: rtd520
12 * Description: Real Time Devices PCI4520/DM7520
13 * Devices: [Real Time Devices] DM7520HR-1 (DM7520), DM7520HR-8,
14 * PCI4520 (PCI4520), PCI4520-8
15 * Author: Dan Christian
16 * Status: Works. Only tested on DM7520-8. Not SMP safe.
17 *
18 * Configuration options: not applicable, uses PCI auto config
19 */
20
21/*
22 * Created by Dan Christian, NASA Ames Research Center.
23 *
24 * The PCI4520 is a PCI card. The DM7520 is a PC/104-plus card.
25 * Both have:
26 * 8/16 12 bit ADC with FIFO and channel gain table
27 * 8 bits high speed digital out (for external MUX) (or 8 in or 8 out)
28 * 8 bits high speed digital in with FIFO and interrupt on change (or 8 IO)
29 * 2 12 bit DACs with FIFOs
30 * 2 bits output
31 * 2 bits input
32 * bus mastering DMA
33 * timers: ADC sample, pacer, burst, about, delay, DA1, DA2
34 * sample counter
35 * 3 user timer/counters (8254)
36 * external interrupt
37 *
38 * The DM7520 has slightly fewer features (fewer gain steps).
39 *
40 * These boards can support external multiplexors and multi-board
41 * synchronization, but this driver doesn't support that.
42 *
43 * Board docs: http://www.rtdusa.com/PC104/DM/analog%20IO/dm7520.htm
44 * Data sheet: http://www.rtdusa.com/pdf/dm7520.pdf
45 * Example source: http://www.rtdusa.com/examples/dm/dm7520.zip
46 * Call them and ask for the register level manual.
47 * PCI chip: http://www.plxtech.com/products/io/pci9080
48 *
49 * Notes:
50 * This board is memory mapped. There is some IO stuff, but it isn't needed.
51 *
52 * I use a pretty loose naming style within the driver (rtd_blah).
53 * All externally visible names should be rtd520_blah.
54 * I use camelCase for structures (and inside them).
55 * I may also use upper CamelCase for function names (old habit).
56 *
57 * This board is somewhat related to the RTD PCI4400 board.
58 *
59 * I borrowed heavily from the ni_mio_common, ni_atmio16d, mite, and
60 * das1800, since they have the best documented code. Driver cb_pcidas64.c
61 * uses the same DMA controller.
62 *
63 * As far as I can tell, the About interrupt doesn't work if Sample is
64 * also enabled. It turns out that About really isn't needed, since
65 * we always count down samples read.
66 */
67
68/*
69 * driver status:
70 *
71 * Analog-In supports instruction and command mode.
72 *
73 * With DMA, you can sample at 1.15Mhz with 70% idle on a 400Mhz K6-2
74 * (single channel, 64K read buffer). I get random system lockups when
75 * using DMA with ALI-15xx based systems. I haven't been able to test
76 * any other chipsets. The lockups happen soon after the start of an
77 * acquistion, not in the middle of a long run.
78 *
79 * Without DMA, you can do 620Khz sampling with 20% idle on a 400Mhz K6-2
80 * (with a 256K read buffer).
81 *
82 * Digital-IO and Analog-Out only support instruction mode.
83 */
84
85#include <linux/module.h>
86#include <linux/delay.h>
87#include <linux/interrupt.h>
88#include <linux/comedi/comedi_pci.h>
89#include <linux/comedi/comedi_8254.h>
90
91#include "plx9080.h"
92
93/*
94 * Local Address Space 0 Offsets
95 */
96#define LAS0_USER_IO 0x0008 /* User I/O */
97#define LAS0_ADC 0x0010 /* FIFO Status/Software A/D Start */
98#define FS_DAC1_NOT_EMPTY BIT(0) /* DAC1 FIFO not empty */
99#define FS_DAC1_HEMPTY BIT(1) /* DAC1 FIFO half empty */
100#define FS_DAC1_NOT_FULL BIT(2) /* DAC1 FIFO not full */
101#define FS_DAC2_NOT_EMPTY BIT(4) /* DAC2 FIFO not empty */
102#define FS_DAC2_HEMPTY BIT(5) /* DAC2 FIFO half empty */
103#define FS_DAC2_NOT_FULL BIT(6) /* DAC2 FIFO not full */
104#define FS_ADC_NOT_EMPTY BIT(8) /* ADC FIFO not empty */
105#define FS_ADC_HEMPTY BIT(9) /* ADC FIFO half empty */
106#define FS_ADC_NOT_FULL BIT(10) /* ADC FIFO not full */
107#define FS_DIN_NOT_EMPTY BIT(12) /* DIN FIFO not empty */
108#define FS_DIN_HEMPTY BIT(13) /* DIN FIFO half empty */
109#define FS_DIN_NOT_FULL BIT(14) /* DIN FIFO not full */
110#define LAS0_UPDATE_DAC(x) (0x0014 + ((x) * 0x4)) /* D/Ax Update (w) */
111#define LAS0_DAC 0x0024 /* Software Simultaneous Update (w) */
112#define LAS0_PACER 0x0028 /* Software Pacer Start/Stop */
113#define LAS0_TIMER 0x002c /* Timer Status/HDIN Software Trig. */
114#define LAS0_IT 0x0030 /* Interrupt Status/Enable */
115#define IRQM_ADC_FIFO_WRITE BIT(0) /* ADC FIFO Write */
116#define IRQM_CGT_RESET BIT(1) /* Reset CGT */
117#define IRQM_CGT_PAUSE BIT(3) /* Pause CGT */
118#define IRQM_ADC_ABOUT_CNT BIT(4) /* About Counter out */
119#define IRQM_ADC_DELAY_CNT BIT(5) /* Delay Counter out */
120#define IRQM_ADC_SAMPLE_CNT BIT(6) /* ADC Sample Counter */
121#define IRQM_DAC1_UCNT BIT(7) /* DAC1 Update Counter */
122#define IRQM_DAC2_UCNT BIT(8) /* DAC2 Update Counter */
123#define IRQM_UTC1 BIT(9) /* User TC1 out */
124#define IRQM_UTC1_INV BIT(10) /* User TC1 out, inverted */
125#define IRQM_UTC2 BIT(11) /* User TC2 out */
126#define IRQM_DIGITAL_IT BIT(12) /* Digital Interrupt */
127#define IRQM_EXTERNAL_IT BIT(13) /* External Interrupt */
128#define IRQM_ETRIG_RISING BIT(14) /* Ext Trigger rising-edge */
129#define IRQM_ETRIG_FALLING BIT(15) /* Ext Trigger falling-edge */
130#define LAS0_CLEAR 0x0034 /* Clear/Set Interrupt Clear Mask */
131#define LAS0_OVERRUN 0x0038 /* Pending interrupts/Clear Overrun */
132#define LAS0_PCLK 0x0040 /* Pacer Clock (24bit) */
133#define LAS0_BCLK 0x0044 /* Burst Clock (10bit) */
134#define LAS0_ADC_SCNT 0x0048 /* A/D Sample counter (10bit) */
135#define LAS0_DAC1_UCNT 0x004c /* D/A1 Update counter (10 bit) */
136#define LAS0_DAC2_UCNT 0x0050 /* D/A2 Update counter (10 bit) */
137#define LAS0_DCNT 0x0054 /* Delay counter (16 bit) */
138#define LAS0_ACNT 0x0058 /* About counter (16 bit) */
139#define LAS0_DAC_CLK 0x005c /* DAC clock (16bit) */
140#define LAS0_8254_TIMER_BASE 0x0060 /* 8254 timer/counter base */
141#define LAS0_DIO0 0x0070 /* Digital I/O Port 0 */
142#define LAS0_DIO1 0x0074 /* Digital I/O Port 1 */
143#define LAS0_DIO0_CTRL 0x0078 /* Digital I/O Control */
144#define LAS0_DIO_STATUS 0x007c /* Digital I/O Status */
145#define LAS0_BOARD_RESET 0x0100 /* Board reset */
146#define LAS0_DMA0_SRC 0x0104 /* DMA 0 Sources select */
147#define LAS0_DMA1_SRC 0x0108 /* DMA 1 Sources select */
148#define LAS0_ADC_CONVERSION 0x010c /* A/D Conversion Signal select */
149#define LAS0_BURST_START 0x0110 /* Burst Clock Start Trigger select */
150#define LAS0_PACER_START 0x0114 /* Pacer Clock Start Trigger select */
151#define LAS0_PACER_STOP 0x0118 /* Pacer Clock Stop Trigger select */
152#define LAS0_ACNT_STOP_ENABLE 0x011c /* About Counter Stop Enable */
153#define LAS0_PACER_REPEAT 0x0120 /* Pacer Start Trigger Mode select */
154#define LAS0_DIN_START 0x0124 /* HiSpd DI Sampling Signal select */
155#define LAS0_DIN_FIFO_CLEAR 0x0128 /* Digital Input FIFO Clear */
156#define LAS0_ADC_FIFO_CLEAR 0x012c /* A/D FIFO Clear */
157#define LAS0_CGT_WRITE 0x0130 /* Channel Gain Table Write */
158#define LAS0_CGL_WRITE 0x0134 /* Channel Gain Latch Write */
159#define LAS0_CG_DATA 0x0138 /* Digital Table Write */
160#define LAS0_CGT_ENABLE 0x013c /* Channel Gain Table Enable */
161#define LAS0_CG_ENABLE 0x0140 /* Digital Table Enable */
162#define LAS0_CGT_PAUSE 0x0144 /* Table Pause Enable */
163#define LAS0_CGT_RESET 0x0148 /* Reset Channel Gain Table */
164#define LAS0_CGT_CLEAR 0x014c /* Clear Channel Gain Table */
165#define LAS0_DAC_CTRL(x) (0x0150 + ((x) * 0x14)) /* D/Ax type/range */
166#define LAS0_DAC_SRC(x) (0x0154 + ((x) * 0x14)) /* D/Ax update source */
167#define LAS0_DAC_CYCLE(x) (0x0158 + ((x) * 0x14)) /* D/Ax cycle mode */
168#define LAS0_DAC_RESET(x) (0x015c + ((x) * 0x14)) /* D/Ax FIFO reset */
169#define LAS0_DAC_FIFO_CLEAR(x) (0x0160 + ((x) * 0x14)) /* D/Ax FIFO clear */
170#define LAS0_ADC_SCNT_SRC 0x0178 /* A/D Sample Counter Source select */
171#define LAS0_PACER_SELECT 0x0180 /* Pacer Clock select */
172#define LAS0_SBUS0_SRC 0x0184 /* SyncBus 0 Source select */
173#define LAS0_SBUS0_ENABLE 0x0188 /* SyncBus 0 enable */
174#define LAS0_SBUS1_SRC 0x018c /* SyncBus 1 Source select */
175#define LAS0_SBUS1_ENABLE 0x0190 /* SyncBus 1 enable */
176#define LAS0_SBUS2_SRC 0x0198 /* SyncBus 2 Source select */
177#define LAS0_SBUS2_ENABLE 0x019c /* SyncBus 2 enable */
178#define LAS0_ETRG_POLARITY 0x01a4 /* Ext. Trigger polarity select */
179#define LAS0_EINT_POLARITY 0x01a8 /* Ext. Interrupt polarity select */
180#define LAS0_8254_CLK_SEL(x) (0x01ac + ((x) * 0x8)) /* 8254 clock select */
181#define LAS0_8254_GATE_SEL(x) (0x01b0 + ((x) * 0x8)) /* 8254 gate select */
182#define LAS0_UOUT0_SELECT 0x01c4 /* User Output 0 source select */
183#define LAS0_UOUT1_SELECT 0x01c8 /* User Output 1 source select */
184#define LAS0_DMA0_RESET 0x01cc /* DMA0 Request state machine reset */
185#define LAS0_DMA1_RESET 0x01d0 /* DMA1 Request state machine reset */
186
187/*
188 * Local Address Space 1 Offsets
189 */
190#define LAS1_ADC_FIFO 0x0000 /* A/D FIFO (16bit) */
191#define LAS1_HDIO_FIFO 0x0004 /* HiSpd DI FIFO (16bit) */
192#define LAS1_DAC_FIFO(x) (0x0008 + ((x) * 0x4)) /* D/Ax FIFO (16bit) */
193
194/*
195 * Driver specific stuff (tunable)
196 */
197
198/*
199 * We really only need 2 buffers. More than that means being much
200 * smarter about knowing which ones are full.
201 */
202#define DMA_CHAIN_COUNT 2 /* max DMA segments/buffers in a ring (min 2) */
203
204/* Target period for periodic transfers. This sets the user read latency. */
205/* Note: There are certain rates where we give this up and transfer 1/2 FIFO */
206/* If this is too low, efficiency is poor */
207#define TRANS_TARGET_PERIOD 10000000 /* 10 ms (in nanoseconds) */
208
209/* Set a practical limit on how long a list to support (affects memory use) */
210/* The board support a channel list up to the FIFO length (1K or 8K) */
211#define RTD_MAX_CHANLIST 128 /* max channel list that we allow */
212
213/*
214 * Board specific stuff
215 */
216
217#define RTD_CLOCK_RATE 8000000 /* 8Mhz onboard clock */
218#define RTD_CLOCK_BASE 125 /* clock period in ns */
219
220/* Note: these speed are slower than the spec, but fit the counter resolution*/
221#define RTD_MAX_SPEED 1625 /* when sampling, in nanoseconds */
222/* max speed if we don't have to wait for settling */
223#define RTD_MAX_SPEED_1 875 /* if single channel, in nanoseconds */
224
225#define RTD_MIN_SPEED 2097151875 /* (24bit counter) in nanoseconds */
226/* min speed when only 1 channel (no burst counter) */
227#define RTD_MIN_SPEED_1 5000000 /* 200Hz, in nanoseconds */
228
229/* Setup continuous ring of 1/2 FIFO transfers. See RTD manual p91 */
230#define DMA_MODE_BITS (\
231 PLX_LOCAL_BUS_16_WIDE_BITS \
232 | PLX_DMA_EN_READYIN_BIT \
233 | PLX_DMA_LOCAL_BURST_EN_BIT \
234 | PLX_EN_CHAIN_BIT \
235 | PLX_DMA_INTR_PCI_BIT \
236 | PLX_LOCAL_ADDR_CONST_BIT \
237 | PLX_DEMAND_MODE_BIT)
238
239#define DMA_TRANSFER_BITS (\
240/* descriptors in PCI memory*/ PLX_DESC_IN_PCI_BIT \
241/* interrupt at end of block */ | PLX_INTR_TERM_COUNT \
242/* from board to PCI */ | PLX_XFER_LOCAL_TO_PCI)
243
244/*
245 * Comedi specific stuff
246 */
247
248/*
249 * The board has 3 input modes and the gains of 1,2,4,...32 (, 64, 128)
250 */
251static const struct comedi_lrange rtd_ai_7520_range = {
252 18, {
253 /* +-5V input range gain steps */
254 BIP_RANGE(5.0),
255 BIP_RANGE(5.0 / 2),
256 BIP_RANGE(5.0 / 4),
257 BIP_RANGE(5.0 / 8),
258 BIP_RANGE(5.0 / 16),
259 BIP_RANGE(5.0 / 32),
260 /* +-10V input range gain steps */
261 BIP_RANGE(10.0),
262 BIP_RANGE(10.0 / 2),
263 BIP_RANGE(10.0 / 4),
264 BIP_RANGE(10.0 / 8),
265 BIP_RANGE(10.0 / 16),
266 BIP_RANGE(10.0 / 32),
267 /* +10V input range gain steps */
268 UNI_RANGE(10.0),
269 UNI_RANGE(10.0 / 2),
270 UNI_RANGE(10.0 / 4),
271 UNI_RANGE(10.0 / 8),
272 UNI_RANGE(10.0 / 16),
273 UNI_RANGE(10.0 / 32),
274 }
275};
276
277/* PCI4520 has two more gains (6 more entries) */
278static const struct comedi_lrange rtd_ai_4520_range = {
279 24, {
280 /* +-5V input range gain steps */
281 BIP_RANGE(5.0),
282 BIP_RANGE(5.0 / 2),
283 BIP_RANGE(5.0 / 4),
284 BIP_RANGE(5.0 / 8),
285 BIP_RANGE(5.0 / 16),
286 BIP_RANGE(5.0 / 32),
287 BIP_RANGE(5.0 / 64),
288 BIP_RANGE(5.0 / 128),
289 /* +-10V input range gain steps */
290 BIP_RANGE(10.0),
291 BIP_RANGE(10.0 / 2),
292 BIP_RANGE(10.0 / 4),
293 BIP_RANGE(10.0 / 8),
294 BIP_RANGE(10.0 / 16),
295 BIP_RANGE(10.0 / 32),
296 BIP_RANGE(10.0 / 64),
297 BIP_RANGE(10.0 / 128),
298 /* +10V input range gain steps */
299 UNI_RANGE(10.0),
300 UNI_RANGE(10.0 / 2),
301 UNI_RANGE(10.0 / 4),
302 UNI_RANGE(10.0 / 8),
303 UNI_RANGE(10.0 / 16),
304 UNI_RANGE(10.0 / 32),
305 UNI_RANGE(10.0 / 64),
306 UNI_RANGE(10.0 / 128),
307 }
308};
309
310/* Table order matches range values */
311static const struct comedi_lrange rtd_ao_range = {
312 4, {
313 UNI_RANGE(5),
314 UNI_RANGE(10),
315 BIP_RANGE(5),
316 BIP_RANGE(10),
317 }
318};
319
320enum rtd_boardid {
321 BOARD_DM7520,
322 BOARD_PCI4520,
323};
324
325struct rtd_boardinfo {
326 const char *name;
327 int range_bip10; /* start of +-10V range */
328 int range_uni10; /* start of +10V range */
329 const struct comedi_lrange *ai_range;
330};
331
332static const struct rtd_boardinfo rtd520_boards[] = {
333 [BOARD_DM7520] = {
334 .name = "DM7520",
335 .range_bip10 = 6,
336 .range_uni10 = 12,
337 .ai_range = &rtd_ai_7520_range,
338 },
339 [BOARD_PCI4520] = {
340 .name = "PCI4520",
341 .range_bip10 = 8,
342 .range_uni10 = 16,
343 .ai_range = &rtd_ai_4520_range,
344 },
345};
346
347struct rtd_private {
348 /* memory mapped board structures */
349 void __iomem *las1;
350 void __iomem *lcfg;
351
352 long ai_count; /* total transfer size (samples) */
353 int xfer_count; /* # to transfer data. 0->1/2FIFO */
354 int flags; /* flag event modes */
355 unsigned int fifosz;
356
357 /* 8254 Timer/Counter gate and clock sources */
358 unsigned char timer_gate_src[3];
359 unsigned char timer_clk_src[3];
360};
361
362/* bit defines for "flags" */
363#define SEND_EOS 0x01 /* send End Of Scan events */
364#define DMA0_ACTIVE 0x02 /* DMA0 is active */
365#define DMA1_ACTIVE 0x04 /* DMA1 is active */
366
367/*
368 * Given a desired period and the clock period (both in ns), return the
369 * proper counter value (divider-1). Sets the original period to be the
370 * true value.
371 * Note: you have to check if the value is larger than the counter range!
372 */
373static int rtd_ns_to_timer_base(unsigned int *nanosec,
374 unsigned int flags, int base)
375{
376 int divider;
377
378 switch (flags & CMDF_ROUND_MASK) {
379 case CMDF_ROUND_NEAREST:
380 default:
381 divider = DIV_ROUND_CLOSEST(*nanosec, base);
382 break;
383 case CMDF_ROUND_DOWN:
384 divider = (*nanosec) / base;
385 break;
386 case CMDF_ROUND_UP:
387 divider = DIV_ROUND_UP(*nanosec, base);
388 break;
389 }
390 if (divider < 2)
391 divider = 2; /* min is divide by 2 */
392
393 /*
394 * Note: we don't check for max, because different timers
395 * have different ranges
396 */
397
398 *nanosec = base * divider;
399 return divider - 1; /* countdown is divisor+1 */
400}
401
402/*
403 * Given a desired period (in ns), return the proper counter value
404 * (divider-1) for the internal clock. Sets the original period to
405 * be the true value.
406 */
407static int rtd_ns_to_timer(unsigned int *ns, unsigned int flags)
408{
409 return rtd_ns_to_timer_base(nanosec: ns, flags, RTD_CLOCK_BASE);
410}
411
412/* Convert a single comedi channel-gain entry to a RTD520 table entry */
413static unsigned short rtd_convert_chan_gain(struct comedi_device *dev,
414 unsigned int chanspec, int index)
415{
416 const struct rtd_boardinfo *board = dev->board_ptr;
417 unsigned int chan = CR_CHAN(chanspec);
418 unsigned int range = CR_RANGE(chanspec);
419 unsigned int aref = CR_AREF(chanspec);
420 unsigned short r = 0;
421
422 r |= chan & 0xf;
423
424 /* Note: we also setup the channel list bipolar flag array */
425 if (range < board->range_bip10) {
426 /* +-5 range */
427 r |= 0x000;
428 r |= (range & 0x7) << 4;
429 } else if (range < board->range_uni10) {
430 /* +-10 range */
431 r |= 0x100;
432 r |= ((range - board->range_bip10) & 0x7) << 4;
433 } else {
434 /* +10 range */
435 r |= 0x200;
436 r |= ((range - board->range_uni10) & 0x7) << 4;
437 }
438
439 switch (aref) {
440 case AREF_GROUND: /* on-board ground */
441 break;
442
443 case AREF_COMMON:
444 r |= 0x80; /* ref external analog common */
445 break;
446
447 case AREF_DIFF:
448 r |= 0x400; /* differential inputs */
449 break;
450
451 case AREF_OTHER: /* ??? */
452 break;
453 }
454 return r;
455}
456
457/* Setup the channel-gain table from a comedi list */
458static void rtd_load_channelgain_list(struct comedi_device *dev,
459 unsigned int n_chan, unsigned int *list)
460{
461 if (n_chan > 1) { /* setup channel gain table */
462 int ii;
463
464 writel(val: 0, addr: dev->mmio + LAS0_CGT_CLEAR);
465 writel(val: 1, addr: dev->mmio + LAS0_CGT_ENABLE);
466 for (ii = 0; ii < n_chan; ii++) {
467 writel(val: rtd_convert_chan_gain(dev, chanspec: list[ii], index: ii),
468 addr: dev->mmio + LAS0_CGT_WRITE);
469 }
470 } else { /* just use the channel gain latch */
471 writel(val: 0, addr: dev->mmio + LAS0_CGT_ENABLE);
472 writel(val: rtd_convert_chan_gain(dev, chanspec: list[0], index: 0),
473 addr: dev->mmio + LAS0_CGL_WRITE);
474 }
475}
476
477/*
478 * Determine fifo size by doing adc conversions until the fifo half
479 * empty status flag clears.
480 */
481static int rtd520_probe_fifo_depth(struct comedi_device *dev)
482{
483 unsigned int chanspec = CR_PACK(0, 0, AREF_GROUND);
484 unsigned int i;
485 static const unsigned int limit = 0x2000;
486 unsigned int fifo_size = 0;
487
488 writel(val: 0, addr: dev->mmio + LAS0_ADC_FIFO_CLEAR);
489 rtd_load_channelgain_list(dev, n_chan: 1, list: &chanspec);
490 /* ADC conversion trigger source: SOFTWARE */
491 writel(val: 0, addr: dev->mmio + LAS0_ADC_CONVERSION);
492 /* convert samples */
493 for (i = 0; i < limit; ++i) {
494 unsigned int fifo_status;
495 /* trigger conversion */
496 writew(val: 0, addr: dev->mmio + LAS0_ADC);
497 usleep_range(min: 1, max: 1000);
498 fifo_status = readl(addr: dev->mmio + LAS0_ADC);
499 if ((fifo_status & FS_ADC_HEMPTY) == 0) {
500 fifo_size = 2 * i;
501 break;
502 }
503 }
504 if (i == limit) {
505 dev_info(dev->class_dev, "failed to probe fifo size.\n");
506 return -EIO;
507 }
508 writel(val: 0, addr: dev->mmio + LAS0_ADC_FIFO_CLEAR);
509 if (fifo_size != 0x400 && fifo_size != 0x2000) {
510 dev_info(dev->class_dev,
511 "unexpected fifo size of %i, expected 1024 or 8192.\n",
512 fifo_size);
513 return -EIO;
514 }
515 return fifo_size;
516}
517
518static int rtd_ai_eoc(struct comedi_device *dev,
519 struct comedi_subdevice *s,
520 struct comedi_insn *insn,
521 unsigned long context)
522{
523 unsigned int status;
524
525 status = readl(addr: dev->mmio + LAS0_ADC);
526 if (status & FS_ADC_NOT_EMPTY)
527 return 0;
528 return -EBUSY;
529}
530
531static int rtd_ai_rinsn(struct comedi_device *dev,
532 struct comedi_subdevice *s, struct comedi_insn *insn,
533 unsigned int *data)
534{
535 struct rtd_private *devpriv = dev->private;
536 unsigned int range = CR_RANGE(insn->chanspec);
537 int ret;
538 int n;
539
540 /* clear any old fifo data */
541 writel(val: 0, addr: dev->mmio + LAS0_ADC_FIFO_CLEAR);
542
543 /* write channel to multiplexer and clear channel gain table */
544 rtd_load_channelgain_list(dev, n_chan: 1, list: &insn->chanspec);
545
546 /* ADC conversion trigger source: SOFTWARE */
547 writel(val: 0, addr: dev->mmio + LAS0_ADC_CONVERSION);
548
549 /* convert n samples */
550 for (n = 0; n < insn->n; n++) {
551 unsigned short d;
552 /* trigger conversion */
553 writew(val: 0, addr: dev->mmio + LAS0_ADC);
554
555 ret = comedi_timeout(dev, s, insn, cb: rtd_ai_eoc, context: 0);
556 if (ret)
557 return ret;
558
559 /* read data */
560 d = readw(addr: devpriv->las1 + LAS1_ADC_FIFO);
561 d >>= 3; /* low 3 bits are marker lines */
562
563 /* convert bipolar data to comedi unsigned data */
564 if (comedi_range_is_bipolar(s, range))
565 d = comedi_offset_munge(s, val: d);
566
567 data[n] = d & s->maxdata;
568 }
569
570 /* return the number of samples read/written */
571 return n;
572}
573
574static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s,
575 int count)
576{
577 struct rtd_private *devpriv = dev->private;
578 struct comedi_async *async = s->async;
579 struct comedi_cmd *cmd = &async->cmd;
580 int ii;
581
582 for (ii = 0; ii < count; ii++) {
583 unsigned int range = CR_RANGE(cmd->chanlist[async->cur_chan]);
584 unsigned short d;
585
586 if (devpriv->ai_count == 0) { /* done */
587 d = readw(addr: devpriv->las1 + LAS1_ADC_FIFO);
588 continue;
589 }
590
591 d = readw(addr: devpriv->las1 + LAS1_ADC_FIFO);
592 d >>= 3; /* low 3 bits are marker lines */
593
594 /* convert bipolar data to comedi unsigned data */
595 if (comedi_range_is_bipolar(s, range))
596 d = comedi_offset_munge(s, val: d);
597 d &= s->maxdata;
598
599 if (!comedi_buf_write_samples(s, data: &d, nsamples: 1))
600 return -1;
601
602 if (devpriv->ai_count > 0) /* < 0, means read forever */
603 devpriv->ai_count--;
604 }
605 return 0;
606}
607
608static irqreturn_t rtd_interrupt(int irq, void *d)
609{
610 struct comedi_device *dev = d;
611 struct comedi_subdevice *s = dev->read_subdev;
612 struct rtd_private *devpriv = dev->private;
613 u32 overrun;
614 u16 status;
615 u16 fifo_status;
616
617 if (!dev->attached)
618 return IRQ_NONE;
619
620 fifo_status = readl(addr: dev->mmio + LAS0_ADC);
621 /* check for FIFO full, this automatically halts the ADC! */
622 if (!(fifo_status & FS_ADC_NOT_FULL)) /* 0 -> full */
623 goto xfer_abort;
624
625 status = readw(addr: dev->mmio + LAS0_IT);
626 /* if interrupt was not caused by our board, or handled above */
627 if (status == 0)
628 return IRQ_HANDLED;
629
630 if (status & IRQM_ADC_ABOUT_CNT) { /* sample count -> read FIFO */
631 /*
632 * since the priority interrupt controller may have queued
633 * a sample counter interrupt, even though we have already
634 * finished, we must handle the possibility that there is
635 * no data here
636 */
637 if (!(fifo_status & FS_ADC_HEMPTY)) {
638 /* FIFO half full */
639 if (ai_read_n(dev, s, count: devpriv->fifosz / 2) < 0)
640 goto xfer_abort;
641
642 if (devpriv->ai_count == 0)
643 goto xfer_done;
644 } else if (devpriv->xfer_count > 0) {
645 if (fifo_status & FS_ADC_NOT_EMPTY) {
646 /* FIFO not empty */
647 if (ai_read_n(dev, s, count: devpriv->xfer_count) < 0)
648 goto xfer_abort;
649
650 if (devpriv->ai_count == 0)
651 goto xfer_done;
652 }
653 }
654 }
655
656 overrun = readl(addr: dev->mmio + LAS0_OVERRUN) & 0xffff;
657 if (overrun)
658 goto xfer_abort;
659
660 /* clear the interrupt */
661 writew(val: status, addr: dev->mmio + LAS0_CLEAR);
662 readw(addr: dev->mmio + LAS0_CLEAR);
663
664 comedi_handle_events(dev, s);
665
666 return IRQ_HANDLED;
667
668xfer_abort:
669 s->async->events |= COMEDI_CB_ERROR;
670
671xfer_done:
672 s->async->events |= COMEDI_CB_EOA;
673
674 /* clear the interrupt */
675 status = readw(addr: dev->mmio + LAS0_IT);
676 writew(val: status, addr: dev->mmio + LAS0_CLEAR);
677 readw(addr: dev->mmio + LAS0_CLEAR);
678
679 fifo_status = readl(addr: dev->mmio + LAS0_ADC);
680 overrun = readl(addr: dev->mmio + LAS0_OVERRUN) & 0xffff;
681
682 comedi_handle_events(dev, s);
683
684 return IRQ_HANDLED;
685}
686
687static int rtd_ai_cmdtest(struct comedi_device *dev,
688 struct comedi_subdevice *s, struct comedi_cmd *cmd)
689{
690 int err = 0;
691 unsigned int arg;
692
693 /* Step 1 : check if triggers are trivially valid */
694
695 err |= comedi_check_trigger_src(src: &cmd->start_src, TRIG_NOW);
696 err |= comedi_check_trigger_src(src: &cmd->scan_begin_src,
697 TRIG_TIMER | TRIG_EXT);
698 err |= comedi_check_trigger_src(src: &cmd->convert_src,
699 TRIG_TIMER | TRIG_EXT);
700 err |= comedi_check_trigger_src(src: &cmd->scan_end_src, TRIG_COUNT);
701 err |= comedi_check_trigger_src(src: &cmd->stop_src, TRIG_COUNT | TRIG_NONE);
702
703 if (err)
704 return 1;
705
706 /* Step 2a : make sure trigger sources are unique */
707
708 err |= comedi_check_trigger_is_unique(src: cmd->scan_begin_src);
709 err |= comedi_check_trigger_is_unique(src: cmd->convert_src);
710 err |= comedi_check_trigger_is_unique(src: cmd->stop_src);
711
712 /* Step 2b : and mutually compatible */
713
714 if (err)
715 return 2;
716
717 /* Step 3: check if arguments are trivially valid */
718
719 err |= comedi_check_trigger_arg_is(arg: &cmd->start_arg, val: 0);
720
721 if (cmd->scan_begin_src == TRIG_TIMER) {
722 /* Note: these are time periods, not actual rates */
723 if (cmd->chanlist_len == 1) { /* no scanning */
724 if (comedi_check_trigger_arg_min(arg: &cmd->scan_begin_arg,
725 RTD_MAX_SPEED_1)) {
726 rtd_ns_to_timer(ns: &cmd->scan_begin_arg,
727 CMDF_ROUND_UP);
728 err |= -EINVAL;
729 }
730 if (comedi_check_trigger_arg_max(arg: &cmd->scan_begin_arg,
731 RTD_MIN_SPEED_1)) {
732 rtd_ns_to_timer(ns: &cmd->scan_begin_arg,
733 CMDF_ROUND_DOWN);
734 err |= -EINVAL;
735 }
736 } else {
737 if (comedi_check_trigger_arg_min(arg: &cmd->scan_begin_arg,
738 RTD_MAX_SPEED)) {
739 rtd_ns_to_timer(ns: &cmd->scan_begin_arg,
740 CMDF_ROUND_UP);
741 err |= -EINVAL;
742 }
743 if (comedi_check_trigger_arg_max(arg: &cmd->scan_begin_arg,
744 RTD_MIN_SPEED)) {
745 rtd_ns_to_timer(ns: &cmd->scan_begin_arg,
746 CMDF_ROUND_DOWN);
747 err |= -EINVAL;
748 }
749 }
750 } else {
751 /* external trigger */
752 /* should be level/edge, hi/lo specification here */
753 /* should specify multiple external triggers */
754 err |= comedi_check_trigger_arg_max(arg: &cmd->scan_begin_arg, val: 9);
755 }
756
757 if (cmd->convert_src == TRIG_TIMER) {
758 if (cmd->chanlist_len == 1) { /* no scanning */
759 if (comedi_check_trigger_arg_min(arg: &cmd->convert_arg,
760 RTD_MAX_SPEED_1)) {
761 rtd_ns_to_timer(ns: &cmd->convert_arg,
762 CMDF_ROUND_UP);
763 err |= -EINVAL;
764 }
765 if (comedi_check_trigger_arg_max(arg: &cmd->convert_arg,
766 RTD_MIN_SPEED_1)) {
767 rtd_ns_to_timer(ns: &cmd->convert_arg,
768 CMDF_ROUND_DOWN);
769 err |= -EINVAL;
770 }
771 } else {
772 if (comedi_check_trigger_arg_min(arg: &cmd->convert_arg,
773 RTD_MAX_SPEED)) {
774 rtd_ns_to_timer(ns: &cmd->convert_arg,
775 CMDF_ROUND_UP);
776 err |= -EINVAL;
777 }
778 if (comedi_check_trigger_arg_max(arg: &cmd->convert_arg,
779 RTD_MIN_SPEED)) {
780 rtd_ns_to_timer(ns: &cmd->convert_arg,
781 CMDF_ROUND_DOWN);
782 err |= -EINVAL;
783 }
784 }
785 } else {
786 /* external trigger */
787 /* see above */
788 err |= comedi_check_trigger_arg_max(arg: &cmd->convert_arg, val: 9);
789 }
790
791 err |= comedi_check_trigger_arg_is(arg: &cmd->scan_end_arg,
792 val: cmd->chanlist_len);
793
794 if (cmd->stop_src == TRIG_COUNT)
795 err |= comedi_check_trigger_arg_min(arg: &cmd->stop_arg, val: 1);
796 else /* TRIG_NONE */
797 err |= comedi_check_trigger_arg_is(arg: &cmd->stop_arg, val: 0);
798
799 if (err)
800 return 3;
801
802 /* step 4: fix up any arguments */
803
804 if (cmd->scan_begin_src == TRIG_TIMER) {
805 arg = cmd->scan_begin_arg;
806 rtd_ns_to_timer(ns: &arg, flags: cmd->flags);
807 err |= comedi_check_trigger_arg_is(arg: &cmd->scan_begin_arg, val: arg);
808 }
809
810 if (cmd->convert_src == TRIG_TIMER) {
811 arg = cmd->convert_arg;
812 rtd_ns_to_timer(ns: &arg, flags: cmd->flags);
813 err |= comedi_check_trigger_arg_is(arg: &cmd->convert_arg, val: arg);
814
815 if (cmd->scan_begin_src == TRIG_TIMER) {
816 arg = cmd->convert_arg * cmd->scan_end_arg;
817 err |= comedi_check_trigger_arg_min(
818 arg: &cmd->scan_begin_arg, val: arg);
819 }
820 }
821
822 if (err)
823 return 4;
824
825 return 0;
826}
827
828static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
829{
830 struct rtd_private *devpriv = dev->private;
831 struct comedi_cmd *cmd = &s->async->cmd;
832 int timer;
833
834 /* stop anything currently running */
835 /* pacer stop source: SOFTWARE */
836 writel(val: 0, addr: dev->mmio + LAS0_PACER_STOP);
837 writel(val: 0, addr: dev->mmio + LAS0_PACER); /* stop pacer */
838 writel(val: 0, addr: dev->mmio + LAS0_ADC_CONVERSION);
839 writew(val: 0, addr: dev->mmio + LAS0_IT);
840 writel(val: 0, addr: dev->mmio + LAS0_ADC_FIFO_CLEAR);
841 writel(val: 0, addr: dev->mmio + LAS0_OVERRUN);
842
843 /* start configuration */
844 /* load channel list and reset CGT */
845 rtd_load_channelgain_list(dev, n_chan: cmd->chanlist_len, list: cmd->chanlist);
846
847 /* setup the common case and override if needed */
848 if (cmd->chanlist_len > 1) {
849 /* pacer start source: SOFTWARE */
850 writel(val: 0, addr: dev->mmio + LAS0_PACER_START);
851 /* burst trigger source: PACER */
852 writel(val: 1, addr: dev->mmio + LAS0_BURST_START);
853 /* ADC conversion trigger source: BURST */
854 writel(val: 2, addr: dev->mmio + LAS0_ADC_CONVERSION);
855 } else { /* single channel */
856 /* pacer start source: SOFTWARE */
857 writel(val: 0, addr: dev->mmio + LAS0_PACER_START);
858 /* ADC conversion trigger source: PACER */
859 writel(val: 1, addr: dev->mmio + LAS0_ADC_CONVERSION);
860 }
861 writel(val: (devpriv->fifosz / 2 - 1) & 0xffff, addr: dev->mmio + LAS0_ACNT);
862
863 if (cmd->scan_begin_src == TRIG_TIMER) {
864 /* scan_begin_arg is in nanoseconds */
865 /* find out how many samples to wait before transferring */
866 if (cmd->flags & CMDF_WAKE_EOS) {
867 /*
868 * this may generate un-sustainable interrupt rates
869 * the application is responsible for doing the
870 * right thing
871 */
872 devpriv->xfer_count = cmd->chanlist_len;
873 devpriv->flags |= SEND_EOS;
874 } else {
875 /* arrange to transfer data periodically */
876 devpriv->xfer_count =
877 (TRANS_TARGET_PERIOD * cmd->chanlist_len) /
878 cmd->scan_begin_arg;
879 if (devpriv->xfer_count < cmd->chanlist_len) {
880 /* transfer after each scan (and avoid 0) */
881 devpriv->xfer_count = cmd->chanlist_len;
882 } else { /* make a multiple of scan length */
883 devpriv->xfer_count =
884 DIV_ROUND_UP(devpriv->xfer_count,
885 cmd->chanlist_len);
886 devpriv->xfer_count *= cmd->chanlist_len;
887 }
888 devpriv->flags |= SEND_EOS;
889 }
890 if (devpriv->xfer_count >= (devpriv->fifosz / 2)) {
891 /* out of counter range, use 1/2 fifo instead */
892 devpriv->xfer_count = 0;
893 devpriv->flags &= ~SEND_EOS;
894 } else {
895 /* interrupt for each transfer */
896 writel(val: (devpriv->xfer_count - 1) & 0xffff,
897 addr: dev->mmio + LAS0_ACNT);
898 }
899 } else { /* unknown timing, just use 1/2 FIFO */
900 devpriv->xfer_count = 0;
901 devpriv->flags &= ~SEND_EOS;
902 }
903 /* pacer clock source: INTERNAL 8MHz */
904 writel(val: 1, addr: dev->mmio + LAS0_PACER_SELECT);
905 /* just interrupt, don't stop */
906 writel(val: 1, addr: dev->mmio + LAS0_ACNT_STOP_ENABLE);
907
908 /* BUG??? these look like enumerated values, but they are bit fields */
909
910 /* First, setup when to stop */
911 switch (cmd->stop_src) {
912 case TRIG_COUNT: /* stop after N scans */
913 devpriv->ai_count = cmd->stop_arg * cmd->chanlist_len;
914 if ((devpriv->xfer_count > 0) &&
915 (devpriv->xfer_count > devpriv->ai_count)) {
916 devpriv->xfer_count = devpriv->ai_count;
917 }
918 break;
919
920 case TRIG_NONE: /* stop when cancel is called */
921 devpriv->ai_count = -1; /* read forever */
922 break;
923 }
924
925 /* Scan timing */
926 switch (cmd->scan_begin_src) {
927 case TRIG_TIMER: /* periodic scanning */
928 timer = rtd_ns_to_timer(ns: &cmd->scan_begin_arg,
929 CMDF_ROUND_NEAREST);
930 /* set PACER clock */
931 writel(val: timer & 0xffffff, addr: dev->mmio + LAS0_PCLK);
932
933 break;
934
935 case TRIG_EXT:
936 /* pacer start source: EXTERNAL */
937 writel(val: 1, addr: dev->mmio + LAS0_PACER_START);
938 break;
939 }
940
941 /* Sample timing within a scan */
942 switch (cmd->convert_src) {
943 case TRIG_TIMER: /* periodic */
944 if (cmd->chanlist_len > 1) {
945 /* only needed for multi-channel */
946 timer = rtd_ns_to_timer(ns: &cmd->convert_arg,
947 CMDF_ROUND_NEAREST);
948 /* setup BURST clock */
949 writel(val: timer & 0x3ff, addr: dev->mmio + LAS0_BCLK);
950 }
951
952 break;
953
954 case TRIG_EXT: /* external */
955 /* burst trigger source: EXTERNAL */
956 writel(val: 2, addr: dev->mmio + LAS0_BURST_START);
957 break;
958 }
959 /* end configuration */
960
961 /*
962 * This doesn't seem to work. There is no way to clear an interrupt
963 * that the priority controller has queued!
964 */
965 writew(val: ~0, addr: dev->mmio + LAS0_CLEAR);
966 readw(addr: dev->mmio + LAS0_CLEAR);
967
968 /* TODO: allow multiple interrupt sources */
969 /* transfer every N samples */
970 writew(IRQM_ADC_ABOUT_CNT, addr: dev->mmio + LAS0_IT);
971
972 /* BUG: start_src is ASSUMED to be TRIG_NOW */
973 /* BUG? it seems like things are running before the "start" */
974 readl(addr: dev->mmio + LAS0_PACER); /* start pacer */
975 return 0;
976}
977
978static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
979{
980 struct rtd_private *devpriv = dev->private;
981
982 /* pacer stop source: SOFTWARE */
983 writel(val: 0, addr: dev->mmio + LAS0_PACER_STOP);
984 writel(val: 0, addr: dev->mmio + LAS0_PACER); /* stop pacer */
985 writel(val: 0, addr: dev->mmio + LAS0_ADC_CONVERSION);
986 writew(val: 0, addr: dev->mmio + LAS0_IT);
987 devpriv->ai_count = 0; /* stop and don't transfer any more */
988 writel(val: 0, addr: dev->mmio + LAS0_ADC_FIFO_CLEAR);
989 return 0;
990}
991
992static int rtd_ao_eoc(struct comedi_device *dev,
993 struct comedi_subdevice *s,
994 struct comedi_insn *insn,
995 unsigned long context)
996{
997 unsigned int chan = CR_CHAN(insn->chanspec);
998 unsigned int bit = (chan == 0) ? FS_DAC1_NOT_EMPTY : FS_DAC2_NOT_EMPTY;
999 unsigned int status;
1000
1001 status = readl(addr: dev->mmio + LAS0_ADC);
1002 if (status & bit)
1003 return 0;
1004 return -EBUSY;
1005}
1006
1007static int rtd_ao_insn_write(struct comedi_device *dev,
1008 struct comedi_subdevice *s,
1009 struct comedi_insn *insn,
1010 unsigned int *data)
1011{
1012 struct rtd_private *devpriv = dev->private;
1013 unsigned int chan = CR_CHAN(insn->chanspec);
1014 unsigned int range = CR_RANGE(insn->chanspec);
1015 int ret;
1016 int i;
1017
1018 /* Configure the output range (table index matches the range values) */
1019 writew(val: range & 7, addr: dev->mmio + LAS0_DAC_CTRL(chan));
1020
1021 for (i = 0; i < insn->n; ++i) {
1022 unsigned int val = data[i];
1023
1024 /* bipolar uses 2's complement values with an extended sign */
1025 if (comedi_range_is_bipolar(s, range)) {
1026 val = comedi_offset_munge(s, val);
1027 val |= (val & ((s->maxdata + 1) >> 1)) << 1;
1028 }
1029
1030 /* shift the 12-bit data (+ sign) to match the register */
1031 val <<= 3;
1032
1033 writew(val, addr: devpriv->las1 + LAS1_DAC_FIFO(chan));
1034 writew(val: 0, addr: dev->mmio + LAS0_UPDATE_DAC(chan));
1035
1036 ret = comedi_timeout(dev, s, insn, cb: rtd_ao_eoc, context: 0);
1037 if (ret)
1038 return ret;
1039
1040 s->readback[chan] = data[i];
1041 }
1042
1043 return insn->n;
1044}
1045
1046static int rtd_dio_insn_bits(struct comedi_device *dev,
1047 struct comedi_subdevice *s,
1048 struct comedi_insn *insn,
1049 unsigned int *data)
1050{
1051 if (comedi_dio_update_state(s, data))
1052 writew(val: s->state & 0xff, addr: dev->mmio + LAS0_DIO0);
1053
1054 data[1] = readw(addr: dev->mmio + LAS0_DIO0) & 0xff;
1055
1056 return insn->n;
1057}
1058
1059static int rtd_dio_insn_config(struct comedi_device *dev,
1060 struct comedi_subdevice *s,
1061 struct comedi_insn *insn,
1062 unsigned int *data)
1063{
1064 int ret;
1065
1066 ret = comedi_dio_insn_config(dev, s, insn, data, mask: 0);
1067 if (ret)
1068 return ret;
1069
1070 /* TODO support digital match interrupts and strobes */
1071
1072 /* set direction */
1073 writew(val: 0x01, addr: dev->mmio + LAS0_DIO_STATUS);
1074 writew(val: s->io_bits & 0xff, addr: dev->mmio + LAS0_DIO0_CTRL);
1075
1076 /* clear interrupts */
1077 writew(val: 0x00, addr: dev->mmio + LAS0_DIO_STATUS);
1078
1079 /* port1 can only be all input or all output */
1080
1081 /* there are also 2 user input lines and 2 user output lines */
1082
1083 return insn->n;
1084}
1085
1086static int rtd_counter_insn_config(struct comedi_device *dev,
1087 struct comedi_subdevice *s,
1088 struct comedi_insn *insn,
1089 unsigned int *data)
1090{
1091 struct rtd_private *devpriv = dev->private;
1092 unsigned int chan = CR_CHAN(insn->chanspec);
1093 unsigned int max_src;
1094 unsigned int src;
1095
1096 switch (data[0]) {
1097 case INSN_CONFIG_SET_GATE_SRC:
1098 /*
1099 * 8254 Timer/Counter gate sources:
1100 *
1101 * 0 = Not gated, free running (reset state)
1102 * 1 = Gated, off
1103 * 2 = Ext. TC Gate 1
1104 * 3 = Ext. TC Gate 2
1105 * 4 = Previous TC out (chan 1 and 2 only)
1106 */
1107 src = data[2];
1108 max_src = (chan == 0) ? 3 : 4;
1109 if (src > max_src)
1110 return -EINVAL;
1111
1112 devpriv->timer_gate_src[chan] = src;
1113 writeb(val: src, addr: dev->mmio + LAS0_8254_GATE_SEL(chan));
1114 break;
1115 case INSN_CONFIG_GET_GATE_SRC:
1116 data[2] = devpriv->timer_gate_src[chan];
1117 break;
1118 case INSN_CONFIG_SET_CLOCK_SRC:
1119 /*
1120 * 8254 Timer/Counter clock sources:
1121 *
1122 * 0 = 8 MHz (reset state)
1123 * 1 = Ext. TC Clock 1
1124 * 2 = Ext. TX Clock 2
1125 * 3 = Ext. Pacer Clock
1126 * 4 = Previous TC out (chan 1 and 2 only)
1127 * 5 = High-Speed Digital Input Sampling signal (chan 1 only)
1128 */
1129 src = data[1];
1130 switch (chan) {
1131 case 0:
1132 max_src = 3;
1133 break;
1134 case 1:
1135 max_src = 5;
1136 break;
1137 case 2:
1138 max_src = 4;
1139 break;
1140 default:
1141 return -EINVAL;
1142 }
1143 if (src > max_src)
1144 return -EINVAL;
1145
1146 devpriv->timer_clk_src[chan] = src;
1147 writeb(val: src, addr: dev->mmio + LAS0_8254_CLK_SEL(chan));
1148 break;
1149 case INSN_CONFIG_GET_CLOCK_SRC:
1150 src = devpriv->timer_clk_src[chan];
1151 data[1] = devpriv->timer_clk_src[chan];
1152 data[2] = (src == 0) ? RTD_CLOCK_BASE : 0;
1153 break;
1154 default:
1155 return -EINVAL;
1156 }
1157
1158 return insn->n;
1159}
1160
1161static void rtd_reset(struct comedi_device *dev)
1162{
1163 struct rtd_private *devpriv = dev->private;
1164
1165 writel(val: 0, addr: dev->mmio + LAS0_BOARD_RESET);
1166 usleep_range(min: 100, max: 1000); /* needed? */
1167 writel(val: 0, addr: devpriv->lcfg + PLX_REG_INTCSR);
1168 writew(val: 0, addr: dev->mmio + LAS0_IT);
1169 writew(val: ~0, addr: dev->mmio + LAS0_CLEAR);
1170 readw(addr: dev->mmio + LAS0_CLEAR);
1171}
1172
1173/*
1174 * initialize board, per RTD spec
1175 * also, initialize shadow registers
1176 */
1177static void rtd_init_board(struct comedi_device *dev)
1178{
1179 rtd_reset(dev);
1180
1181 writel(val: 0, addr: dev->mmio + LAS0_OVERRUN);
1182 writel(val: 0, addr: dev->mmio + LAS0_CGT_CLEAR);
1183 writel(val: 0, addr: dev->mmio + LAS0_ADC_FIFO_CLEAR);
1184 writel(val: 0, addr: dev->mmio + LAS0_DAC_RESET(0));
1185 writel(val: 0, addr: dev->mmio + LAS0_DAC_RESET(1));
1186 /* clear digital IO fifo */
1187 writew(val: 0, addr: dev->mmio + LAS0_DIO_STATUS);
1188 /* TODO: set user out source ??? */
1189}
1190
1191/* The RTD driver does this */
1192static void rtd_pci_latency_quirk(struct comedi_device *dev,
1193 struct pci_dev *pcidev)
1194{
1195 unsigned char pci_latency;
1196
1197 pci_read_config_byte(dev: pcidev, PCI_LATENCY_TIMER, val: &pci_latency);
1198 if (pci_latency < 32) {
1199 dev_info(dev->class_dev,
1200 "PCI latency changed from %d to %d\n",
1201 pci_latency, 32);
1202 pci_write_config_byte(dev: pcidev, PCI_LATENCY_TIMER, val: 32);
1203 }
1204}
1205
1206static int rtd_auto_attach(struct comedi_device *dev,
1207 unsigned long context)
1208{
1209 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1210 const struct rtd_boardinfo *board = NULL;
1211 struct rtd_private *devpriv;
1212 struct comedi_subdevice *s;
1213 int ret;
1214
1215 if (context < ARRAY_SIZE(rtd520_boards))
1216 board = &rtd520_boards[context];
1217 if (!board)
1218 return -ENODEV;
1219 dev->board_ptr = board;
1220 dev->board_name = board->name;
1221
1222 devpriv = comedi_alloc_devpriv(dev, size: sizeof(*devpriv));
1223 if (!devpriv)
1224 return -ENOMEM;
1225
1226 ret = comedi_pci_enable(dev);
1227 if (ret)
1228 return ret;
1229
1230 dev->mmio = pci_ioremap_bar(pdev: pcidev, bar: 2);
1231 devpriv->las1 = pci_ioremap_bar(pdev: pcidev, bar: 3);
1232 devpriv->lcfg = pci_ioremap_bar(pdev: pcidev, bar: 0);
1233 if (!dev->mmio || !devpriv->las1 || !devpriv->lcfg)
1234 return -ENOMEM;
1235
1236 rtd_pci_latency_quirk(dev, pcidev);
1237
1238 if (pcidev->irq) {
1239 ret = request_irq(irq: pcidev->irq, handler: rtd_interrupt, IRQF_SHARED,
1240 name: dev->board_name, dev);
1241 if (ret == 0)
1242 dev->irq = pcidev->irq;
1243 }
1244
1245 ret = comedi_alloc_subdevices(dev, num_subdevices: 4);
1246 if (ret)
1247 return ret;
1248
1249 s = &dev->subdevices[0];
1250 /* analog input subdevice */
1251 s->type = COMEDI_SUBD_AI;
1252 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF;
1253 s->n_chan = 16;
1254 s->maxdata = 0x0fff;
1255 s->range_table = board->ai_range;
1256 s->len_chanlist = RTD_MAX_CHANLIST;
1257 s->insn_read = rtd_ai_rinsn;
1258 if (dev->irq) {
1259 dev->read_subdev = s;
1260 s->subdev_flags |= SDF_CMD_READ;
1261 s->do_cmd = rtd_ai_cmd;
1262 s->do_cmdtest = rtd_ai_cmdtest;
1263 s->cancel = rtd_ai_cancel;
1264 }
1265
1266 s = &dev->subdevices[1];
1267 /* analog output subdevice */
1268 s->type = COMEDI_SUBD_AO;
1269 s->subdev_flags = SDF_WRITABLE;
1270 s->n_chan = 2;
1271 s->maxdata = 0x0fff;
1272 s->range_table = &rtd_ao_range;
1273 s->insn_write = rtd_ao_insn_write;
1274
1275 ret = comedi_alloc_subdev_readback(s);
1276 if (ret)
1277 return ret;
1278
1279 s = &dev->subdevices[2];
1280 /* digital i/o subdevice */
1281 s->type = COMEDI_SUBD_DIO;
1282 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1283 /* we only support port 0 right now. Ignoring port 1 and user IO */
1284 s->n_chan = 8;
1285 s->maxdata = 1;
1286 s->range_table = &range_digital;
1287 s->insn_bits = rtd_dio_insn_bits;
1288 s->insn_config = rtd_dio_insn_config;
1289
1290 /* 8254 Timer/Counter subdevice */
1291 s = &dev->subdevices[3];
1292 dev->pacer = comedi_8254_mm_alloc(mmio: dev->mmio + LAS0_8254_TIMER_BASE,
1293 RTD_CLOCK_BASE, I8254_IO8, regshift: 2);
1294 if (IS_ERR(ptr: dev->pacer))
1295 return -ENOMEM;
1296
1297 comedi_8254_subdevice_init(s, i8254: dev->pacer);
1298 dev->pacer->insn_config = rtd_counter_insn_config;
1299
1300 rtd_init_board(dev);
1301
1302 ret = rtd520_probe_fifo_depth(dev);
1303 if (ret < 0)
1304 return ret;
1305 devpriv->fifosz = ret;
1306
1307 if (dev->irq)
1308 writel(PLX_INTCSR_PIEN | PLX_INTCSR_PLIEN,
1309 addr: devpriv->lcfg + PLX_REG_INTCSR);
1310
1311 return 0;
1312}
1313
1314static void rtd_detach(struct comedi_device *dev)
1315{
1316 struct rtd_private *devpriv = dev->private;
1317
1318 if (devpriv) {
1319 /* Shut down any board ops by resetting it */
1320 if (dev->mmio && devpriv->lcfg)
1321 rtd_reset(dev);
1322 if (dev->irq)
1323 free_irq(dev->irq, dev);
1324 if (dev->mmio)
1325 iounmap(addr: dev->mmio);
1326 if (devpriv->las1)
1327 iounmap(addr: devpriv->las1);
1328 if (devpriv->lcfg)
1329 iounmap(addr: devpriv->lcfg);
1330 }
1331 comedi_pci_disable(dev);
1332}
1333
1334static struct comedi_driver rtd520_driver = {
1335 .driver_name = "rtd520",
1336 .module = THIS_MODULE,
1337 .auto_attach = rtd_auto_attach,
1338 .detach = rtd_detach,
1339};
1340
1341static int rtd520_pci_probe(struct pci_dev *dev,
1342 const struct pci_device_id *id)
1343{
1344 return comedi_pci_auto_config(pcidev: dev, driver: &rtd520_driver, context: id->driver_data);
1345}
1346
1347static const struct pci_device_id rtd520_pci_table[] = {
1348 { PCI_VDEVICE(RTD, 0x7520), BOARD_DM7520 },
1349 { PCI_VDEVICE(RTD, 0x4520), BOARD_PCI4520 },
1350 { 0 }
1351};
1352MODULE_DEVICE_TABLE(pci, rtd520_pci_table);
1353
1354static struct pci_driver rtd520_pci_driver = {
1355 .name = "rtd520",
1356 .id_table = rtd520_pci_table,
1357 .probe = rtd520_pci_probe,
1358 .remove = comedi_pci_auto_unconfig,
1359};
1360module_comedi_pci_driver(rtd520_driver, rtd520_pci_driver);
1361
1362MODULE_AUTHOR("Comedi https://www.comedi.org");
1363MODULE_DESCRIPTION("Comedi low-level driver");
1364MODULE_LICENSE("GPL");
1365

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