Version:  2.0.40 2.2.26 2.4.37 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5

Linux/drivers/staging/comedi/drivers/rtd520.c

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us