Version:  2.0.40 2.2.26 2.4.37 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 4.6

Linux/drivers/staging/comedi/drivers/adl_pci9118.c

  1 /*
  2  *  comedi/drivers/adl_pci9118.c
  3  *
  4  *  hardware driver for ADLink cards:
  5  *   card:   PCI-9118DG, PCI-9118HG, PCI-9118HR
  6  *   driver: pci9118dg,  pci9118hg,  pci9118hr
  7  *
  8  * Author: Michal Dobes <dobes@tesnet.cz>
  9  *
 10  */
 11 
 12 /*
 13  * Driver: adl_pci9118
 14  * Description: Adlink PCI-9118DG, PCI-9118HG, PCI-9118HR
 15  * Author: Michal Dobes <dobes@tesnet.cz>
 16  * Devices: [ADLink] PCI-9118DG (pci9118dg), PCI-9118HG (pci9118hg),
 17  * PCI-9118HR (pci9118hr)
 18  * Status: works
 19  *
 20  * This driver supports AI, AO, DI and DO subdevices.
 21  * AI subdevice supports cmd and insn interface,
 22  * other subdevices support only insn interface.
 23  * For AI:
 24  * - If cmd->scan_begin_src=TRIG_EXT then trigger input is TGIN (pin 46).
 25  * - If cmd->convert_src=TRIG_EXT then trigger input is EXTTRG (pin 44).
 26  * - If cmd->start_src/stop_src=TRIG_EXT then trigger input is TGIN (pin 46).
 27  * - It is not necessary to have cmd.scan_end_arg=cmd.chanlist_len but
 28  * cmd.scan_end_arg modulo cmd.chanlist_len must by 0.
 29  * - If return value of cmdtest is 5 then you've bad channel list
 30  * (it isn't possible mixture S.E. and DIFF inputs or bipolar and unipolar
 31  * ranges).
 32  *
 33  * There are some hardware limitations:
 34  * a) You cann't use mixture of unipolar/bipoar ranges or differencial/single
 35  *  ended inputs.
 36  * b) DMA transfers must have the length aligned to two samples (32 bit),
 37  *  so there is some problems if cmd->chanlist_len is odd. This driver tries
 38  *  bypass this with adding one sample to the end of the every scan and discard
 39  *  it on output but this can't be used if cmd->scan_begin_src=TRIG_FOLLOW
 40  *  and is used flag CMDF_WAKE_EOS, then driver switch to interrupt driven mode
 41  *  with interrupt after every sample.
 42  * c) If isn't used DMA then you can use only mode where
 43  *  cmd->scan_begin_src=TRIG_FOLLOW.
 44  *
 45  * Configuration options:
 46  * [0] - PCI bus of device (optional)
 47  * [1] - PCI slot of device (optional)
 48  *       If bus/slot is not specified, then first available PCI
 49  *       card will be used.
 50  * [2] - 0= standard 8 DIFF/16 SE channels configuration
 51  *       n = external multiplexer connected, 1 <= n <= 256
 52  * [3] - ignored
 53  * [4] - sample&hold signal - card can generate signal for external S&H board
 54  *       0 = use SSHO(pin 45) signal is generated in onboard hardware S&H logic
 55  *       0 != use ADCHN7(pin 23) signal is generated from driver, number say how
 56  *              long delay is requested in ns and sign polarity of the hold
 57  *              (in this case external multiplexor can serve only 128 channels)
 58  * [5] - ignored
 59  */
 60 
 61 /*
 62  * FIXME
 63  *
 64  * All the supported boards have the same PCI vendor and device IDs, so
 65  * auto-attachment of PCI devices will always find the first board type.
 66  *
 67  * Perhaps the boards have different subdevice IDs that we could use to
 68  * distinguish them?
 69  *
 70  * Need some device attributes so the board type can be corrected after
 71  * attachment if necessary, and possibly to set other options supported by
 72  * manual attachment.
 73  */
 74 
 75 #include <linux/module.h>
 76 #include <linux/delay.h>
 77 #include <linux/gfp.h>
 78 #include <linux/interrupt.h>
 79 #include <linux/io.h>
 80 
 81 #include "../comedi_pci.h"
 82 
 83 #include "amcc_s5933.h"
 84 #include "comedi_8254.h"
 85 
 86 /*
 87  * PCI BAR2 Register map (dev->iobase)
 88  */
 89 #define PCI9118_TIMER_BASE              0x00
 90 #define PCI9118_AI_FIFO_REG             0x10
 91 #define PCI9118_AO_REG(x)               (0x10 + ((x) * 4))
 92 #define PCI9118_AI_STATUS_REG           0x18
 93 #define PCI9118_AI_STATUS_NFULL         BIT(8)  /* 0=FIFO full (fatal) */
 94 #define PCI9118_AI_STATUS_NHFULL        BIT(7)  /* 0=FIFO half full */
 95 #define PCI9118_AI_STATUS_NEPTY         BIT(6)  /* 0=FIFO empty */
 96 #define PCI9118_AI_STATUS_ACMP          BIT(5)  /* 1=about trigger complete */
 97 #define PCI9118_AI_STATUS_DTH           BIT(4)  /* 1=ext. digital trigger */
 98 #define PCI9118_AI_STATUS_BOVER         BIT(3)  /* 1=burst overrun (fatal) */
 99 #define PCI9118_AI_STATUS_ADOS          BIT(2)  /* 1=A/D over speed (warn) */
100 #define PCI9118_AI_STATUS_ADOR          BIT(1)  /* 1=A/D overrun (fatal) */
101 #define PCI9118_AI_STATUS_ADRDY         BIT(0)  /* 1=A/D ready */
102 #define PCI9118_AI_CTRL_REG             0x18
103 #define PCI9118_AI_CTRL_UNIP            BIT(7)  /* 1=unipolar */
104 #define PCI9118_AI_CTRL_DIFF            BIT(6)  /* 1=differential inputs */
105 #define PCI9118_AI_CTRL_SOFTG           BIT(5)  /* 1=8254 software gate */
106 #define PCI9118_AI_CTRL_EXTG            BIT(4)  /* 1=8254 TGIN(pin 46) gate */
107 #define PCI9118_AI_CTRL_EXTM            BIT(3)  /* 1=ext. trigger (pin 44) */
108 #define PCI9118_AI_CTRL_TMRTR           BIT(2)  /* 1=8254 is trigger source */
109 #define PCI9118_AI_CTRL_INT             BIT(1)  /* 1=enable interrupt */
110 #define PCI9118_AI_CTRL_DMA             BIT(0)  /* 1=enable DMA */
111 #define PCI9118_DIO_REG                 0x1c
112 #define PCI9118_SOFTTRG_REG             0x20
113 #define PCI9118_AI_CHANLIST_REG         0x24
114 #define PCI9118_AI_CHANLIST_RANGE(x)    (((x) & 0x3) << 8)
115 #define PCI9118_AI_CHANLIST_CHAN(x)     ((x) << 0)
116 #define PCI9118_AI_BURST_NUM_REG        0x28
117 #define PCI9118_AI_AUTOSCAN_MODE_REG    0x2c
118 #define PCI9118_AI_CFG_REG              0x30
119 #define PCI9118_AI_CFG_PDTRG            BIT(7)  /* 1=positive trigger */
120 #define PCI9118_AI_CFG_PETRG            BIT(6)  /* 1=positive ext. trigger */
121 #define PCI9118_AI_CFG_BSSH             BIT(5)  /* 1=with sample & hold */
122 #define PCI9118_AI_CFG_BM               BIT(4)  /* 1=burst mode */
123 #define PCI9118_AI_CFG_BS               BIT(3)  /* 1=burst mode start */
124 #define PCI9118_AI_CFG_PM               BIT(2)  /* 1=post trigger */
125 #define PCI9118_AI_CFG_AM               BIT(1)  /* 1=about trigger */
126 #define PCI9118_AI_CFG_START            BIT(0)  /* 1=trigger start */
127 #define PCI9118_FIFO_RESET_REG          0x34
128 #define PCI9118_INT_CTRL_REG            0x38
129 #define PCI9118_INT_CTRL_TIMER          BIT(3)  /* timer interrupt */
130 #define PCI9118_INT_CTRL_ABOUT          BIT(2)  /* about trigger complete */
131 #define PCI9118_INT_CTRL_HFULL          BIT(1)  /* A/D FIFO half full */
132 #define PCI9118_INT_CTRL_DTRG           BIT(0)  /* ext. digital trigger */
133 
134 #define START_AI_EXT    0x01    /* start measure on external trigger */
135 #define STOP_AI_EXT     0x02    /* stop measure on external trigger */
136 #define STOP_AI_INT     0x08    /* stop measure on internal trigger */
137 
138 static const struct comedi_lrange pci9118_ai_range = {
139         8, {
140                 BIP_RANGE(5),
141                 BIP_RANGE(2.5),
142                 BIP_RANGE(1.25),
143                 BIP_RANGE(0.625),
144                 UNI_RANGE(10),
145                 UNI_RANGE(5),
146                 UNI_RANGE(2.5),
147                 UNI_RANGE(1.25)
148         }
149 };
150 
151 static const struct comedi_lrange pci9118hg_ai_range = {
152         8, {
153                 BIP_RANGE(5),
154                 BIP_RANGE(0.5),
155                 BIP_RANGE(0.05),
156                 BIP_RANGE(0.005),
157                 UNI_RANGE(10),
158                 UNI_RANGE(1),
159                 UNI_RANGE(0.1),
160                 UNI_RANGE(0.01)
161         }
162 };
163 
164 enum pci9118_boardid {
165         BOARD_PCI9118DG,
166         BOARD_PCI9118HG,
167         BOARD_PCI9118HR,
168 };
169 
170 struct pci9118_boardinfo {
171         const char *name;
172         unsigned int ai_is_16bit:1;
173         unsigned int is_hg:1;
174 };
175 
176 static const struct pci9118_boardinfo pci9118_boards[] = {
177         [BOARD_PCI9118DG] = {
178                 .name           = "pci9118dg",
179         },
180         [BOARD_PCI9118HG] = {
181                 .name           = "pci9118hg",
182                 .is_hg          = 1,
183         },
184         [BOARD_PCI9118HR] = {
185                 .name           = "pci9118hr",
186                 .ai_is_16bit    = 1,
187         },
188 };
189 
190 struct pci9118_dmabuf {
191         unsigned short *virt;   /* virtual address of buffer */
192         dma_addr_t hw;          /* hardware (bus) address of buffer */
193         unsigned int size;      /* size of dma buffer in bytes */
194         unsigned int use_size;  /* which size we may now use for transfer */
195 };
196 
197 struct pci9118_private {
198         unsigned long iobase_a; /* base+size for AMCC chip */
199         unsigned int master:1;
200         unsigned int dma_doublebuf:1;
201         unsigned int ai_neverending:1;
202         unsigned int usedma:1;
203         unsigned int usemux:1;
204         unsigned char ai_ctrl;
205         unsigned char int_ctrl;
206         unsigned char ai_cfg;
207         unsigned int ai_do;             /* what do AI? 0=nothing, 1 to 4 mode */
208         unsigned int ai_n_realscanlen;  /*
209                                          * what we must transfer for one
210                                          * outgoing scan include front/back adds
211                                          */
212         unsigned int ai_act_dmapos;     /* position in actual real stream */
213         unsigned int ai_add_front;      /*
214                                          * how many channels we must add
215                                          * before scan to satisfy S&H?
216                                          */
217         unsigned int ai_add_back;       /*
218                                          * how many channels we must add
219                                          * before scan to satisfy DMA?
220                                          */
221         unsigned int ai_flags;
222         char ai12_startstop;            /*
223                                          * measure can start/stop
224                                          * on external trigger
225                                          */
226         unsigned int dma_actbuf;                /* which buffer is used now */
227         struct pci9118_dmabuf dmabuf[2];
228         int softsshdelay;               /*
229                                          * >0 use software S&H,
230                                          * numer is requested delay in ns
231                                          */
232         unsigned char softsshsample;    /*
233                                          * polarity of S&H signal
234                                          * in sample state
235                                          */
236         unsigned char softsshhold;      /*
237                                          * polarity of S&H signal
238                                          * in hold state
239                                          */
240         unsigned int ai_ns_min;
241 };
242 
243 static void pci9118_amcc_setup_dma(struct comedi_device *dev, unsigned int buf)
244 {
245         struct pci9118_private *devpriv = dev->private;
246         struct pci9118_dmabuf *dmabuf = &devpriv->dmabuf[buf];
247 
248         /* set the master write address and transfer count */
249         outl(dmabuf->hw, devpriv->iobase_a + AMCC_OP_REG_MWAR);
250         outl(dmabuf->use_size, devpriv->iobase_a + AMCC_OP_REG_MWTC);
251 }
252 
253 static void pci9118_amcc_dma_ena(struct comedi_device *dev, bool enable)
254 {
255         struct pci9118_private *devpriv = dev->private;
256         unsigned int mcsr;
257 
258         mcsr = inl(devpriv->iobase_a + AMCC_OP_REG_MCSR);
259         if (enable)
260                 mcsr |= RESET_A2P_FLAGS | A2P_HI_PRIORITY | EN_A2P_TRANSFERS;
261         else
262                 mcsr &= ~EN_A2P_TRANSFERS;
263         outl(mcsr, devpriv->iobase_a + AMCC_OP_REG_MCSR);
264 }
265 
266 static void pci9118_amcc_int_ena(struct comedi_device *dev, bool enable)
267 {
268         struct pci9118_private *devpriv = dev->private;
269         unsigned int intcsr;
270 
271         /* enable/disable interrupt for AMCC Incoming Mailbox 4 (32-bit) */
272         intcsr = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR);
273         if (enable)
274                 intcsr |= 0x1f00;
275         else
276                 intcsr &= ~0x1f00;
277         outl(intcsr, devpriv->iobase_a + AMCC_OP_REG_INTCSR);
278 }
279 
280 static void pci9118_ai_reset_fifo(struct comedi_device *dev)
281 {
282         /* writing any value resets the A/D FIFO */
283         outl(0, dev->iobase + PCI9118_FIFO_RESET_REG);
284 }
285 
286 static int pci9118_ai_check_chanlist(struct comedi_device *dev,
287                                      struct comedi_subdevice *s,
288                                      struct comedi_cmd *cmd)
289 {
290         struct pci9118_private *devpriv = dev->private;
291         unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
292         unsigned int aref0 = CR_AREF(cmd->chanlist[0]);
293         int i;
294 
295         /* single channel scans are always ok */
296         if (cmd->chanlist_len == 1)
297                 return 0;
298 
299         for (i = 1; i < cmd->chanlist_len; i++) {
300                 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
301                 unsigned int range = CR_RANGE(cmd->chanlist[i]);
302                 unsigned int aref = CR_AREF(cmd->chanlist[i]);
303 
304                 if (aref != aref0) {
305                         dev_err(dev->class_dev,
306                                 "Differential and single ended inputs can't be mixed!\n");
307                         return -EINVAL;
308                 }
309                 if (comedi_range_is_bipolar(s, range) !=
310                     comedi_range_is_bipolar(s, range0)) {
311                         dev_err(dev->class_dev,
312                                 "Bipolar and unipolar ranges can't be mixed!\n");
313                         return -EINVAL;
314                 }
315                 if (!devpriv->usemux && aref == AREF_DIFF &&
316                     (chan >= (s->n_chan / 2))) {
317                         dev_err(dev->class_dev,
318                                 "AREF_DIFF is only available for the first 8 channels!\n");
319                         return -EINVAL;
320                 }
321         }
322 
323         return 0;
324 }
325 
326 static void pci9118_set_chanlist(struct comedi_device *dev,
327                                  struct comedi_subdevice *s,
328                                  int n_chan, unsigned int *chanlist,
329                                  int frontadd, int backadd)
330 {
331         struct pci9118_private *devpriv = dev->private;
332         unsigned int chan0 = CR_CHAN(chanlist[0]);
333         unsigned int range0 = CR_RANGE(chanlist[0]);
334         unsigned int aref0 = CR_AREF(chanlist[0]);
335         unsigned int ssh = 0x00;
336         unsigned int val;
337         int i;
338 
339         /*
340          * Configure analog input based on the first chanlist entry.
341          * All entries are either unipolar or bipolar and single-ended
342          * or differential.
343          */
344         devpriv->ai_ctrl = 0;
345         if (comedi_range_is_unipolar(s, range0))
346                 devpriv->ai_ctrl |= PCI9118_AI_CTRL_UNIP;
347         if (aref0 == AREF_DIFF)
348                 devpriv->ai_ctrl |= PCI9118_AI_CTRL_DIFF;
349         outl(devpriv->ai_ctrl, dev->iobase + PCI9118_AI_CTRL_REG);
350 
351         /* gods know why this sequence! */
352         outl(2, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
353         outl(0, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
354         outl(1, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
355 
356         /* insert channels for S&H */
357         if (frontadd) {
358                 val = PCI9118_AI_CHANLIST_CHAN(chan0) |
359                       PCI9118_AI_CHANLIST_RANGE(range0);
360                 ssh = devpriv->softsshsample;
361                 for (i = 0; i < frontadd; i++) {
362                         outl(val | ssh, dev->iobase + PCI9118_AI_CHANLIST_REG);
363                         ssh = devpriv->softsshhold;
364                 }
365         }
366 
367         /* store chanlist */
368         for (i = 0; i < n_chan; i++) {
369                 unsigned int chan = CR_CHAN(chanlist[i]);
370                 unsigned int range = CR_RANGE(chanlist[i]);
371 
372                 val = PCI9118_AI_CHANLIST_CHAN(chan) |
373                       PCI9118_AI_CHANLIST_RANGE(range);
374                 outl(val | ssh, dev->iobase + PCI9118_AI_CHANLIST_REG);
375         }
376 
377         /* insert channels to fit onto 32bit DMA */
378         if (backadd) {
379                 val = PCI9118_AI_CHANLIST_CHAN(chan0) |
380                       PCI9118_AI_CHANLIST_RANGE(range0);
381                 for (i = 0; i < backadd; i++)
382                         outl(val | ssh, dev->iobase + PCI9118_AI_CHANLIST_REG);
383         }
384         /* close scan queue */
385         outl(0, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
386         /* udelay(100); important delay, or first sample will be crippled */
387 }
388 
389 static void pci9118_ai_mode4_switch(struct comedi_device *dev,
390                                     unsigned int next_buf)
391 {
392         struct pci9118_private *devpriv = dev->private;
393         struct pci9118_dmabuf *dmabuf = &devpriv->dmabuf[next_buf];
394 
395         devpriv->ai_cfg = PCI9118_AI_CFG_PDTRG | PCI9118_AI_CFG_PETRG |
396                           PCI9118_AI_CFG_AM;
397         outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
398         comedi_8254_load(dev->pacer, 0, dmabuf->hw >> 1,
399                          I8254_MODE0 | I8254_BINARY);
400         devpriv->ai_cfg |= PCI9118_AI_CFG_START;
401         outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
402 }
403 
404 static unsigned int pci9118_ai_samples_ready(struct comedi_device *dev,
405                                              struct comedi_subdevice *s,
406                                              unsigned int n_raw_samples)
407 {
408         struct pci9118_private *devpriv = dev->private;
409         struct comedi_cmd *cmd = &s->async->cmd;
410         unsigned int start_pos = devpriv->ai_add_front;
411         unsigned int stop_pos = start_pos + cmd->chanlist_len;
412         unsigned int span_len = stop_pos + devpriv->ai_add_back;
413         unsigned int dma_pos = devpriv->ai_act_dmapos;
414         unsigned int whole_spans, n_samples, x;
415 
416         if (span_len == cmd->chanlist_len)
417                 return n_raw_samples;   /* use all samples */
418 
419         /*
420          * Not all samples are to be used.  Buffer contents consist of a
421          * possibly non-whole number of spans and a region of each span
422          * is to be used.
423          *
424          * Account for samples in whole number of spans.
425          */
426         whole_spans = n_raw_samples / span_len;
427         n_samples = whole_spans * cmd->chanlist_len;
428         n_raw_samples -= whole_spans * span_len;
429 
430         /*
431          * Deal with remaining samples which could overlap up to two spans.
432          */
433         while (n_raw_samples) {
434                 if (dma_pos < start_pos) {
435                         /* Skip samples before start position. */
436                         x = start_pos - dma_pos;
437                         if (x > n_raw_samples)
438                                 x = n_raw_samples;
439                         dma_pos += x;
440                         n_raw_samples -= x;