]> Pileus Git - ~andy/linux/blob - drivers/staging/comedi/drivers/cb_pcidda.c
cc34afcea487c8d92934c7b8146e6a2b713385ed
[~andy/linux] / drivers / staging / comedi / drivers / cb_pcidda.c
1 /*
2     comedi/drivers/cb_pcidda.c
3     This intends to be a driver for the ComputerBoards / MeasurementComputing
4     PCI-DDA series.
5
6          Copyright (C) 2001 Ivan Martinez <ivanmr@altavista.com>
7     Copyright (C) 2001 Frank Mori Hess <fmhess@users.sourceforge.net>
8
9     COMEDI - Linux Control and Measurement Device Interface
10     Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
11
12     This program is free software; you can redistribute it and/or modify
13     it under the terms of the GNU General Public License as published by
14     the Free Software Foundation; either version 2 of the License, or
15     (at your option) any later version.
16
17     This program is distributed in the hope that it will be useful,
18     but WITHOUT ANY WARRANTY; without even the implied warranty of
19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20     GNU General Public License for more details.
21
22     You should have received a copy of the GNU General Public License
23     along with this program; if not, write to the Free Software
24     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
26 */
27 /*
28 Driver: cb_pcidda
29 Description: MeasurementComputing PCI-DDA series
30 Author: Ivan Martinez <ivanmr@altavista.com>, Frank Mori Hess <fmhess@users.sourceforge.net>
31 Status: Supports 08/16, 04/16, 02/16, 08/12, 04/12, and 02/12
32 Devices: [Measurement Computing] PCI-DDA08/12 (cb_pcidda), PCI-DDA04/12,
33   PCI-DDA02/12, PCI-DDA08/16, PCI-DDA04/16, PCI-DDA02/16
34
35 Configuration options:
36   [0] - PCI bus of device (optional)
37   [1] - PCI slot of device (optional)
38   If bus/slot is not specified, the first available PCI
39   device will be used.
40
41 Only simple analog output writing is supported.
42
43 So far it has only been tested with:
44   - PCI-DDA08/12
45 Please report success/failure with other different cards to
46 <comedi@comedi.org>.
47 */
48
49 #include "../comedidev.h"
50
51 #include "comedi_fc.h"
52 #include "8255.h"
53
54 /*
55  * ComputerBoards PCI Device ID's supported by this driver
56  */
57 #define PCI_VENDOR_ID_CB                0x1307
58 #define PCI_DEVICE_ID_DDA02_12          0x0020
59 #define PCI_DEVICE_ID_DDA04_12          0x0021
60 #define PCI_DEVICE_ID_DDA08_12          0x0022
61 #define PCI_DEVICE_ID_DDA02_16          0x0023
62 #define PCI_DEVICE_ID_DDA04_16          0x0024
63 #define PCI_DEVICE_ID_DDA08_16          0x0025
64
65 #define EEPROM_SIZE     128     /*  number of entries in eeprom */
66 /* maximum number of ao channels for supported boards */
67 #define MAX_AO_CHANNELS 8
68
69 /* Digital I/O registers */
70 #define PORT1A 0                /*  PORT 1A DATA */
71
72 #define PORT1B 1                /*  PORT 1B DATA */
73
74 #define PORT1C 2                /*  PORT 1C DATA */
75
76 #define CONTROL1 3              /*  CONTROL REGISTER 1 */
77
78 #define PORT2A 4                /*  PORT 2A DATA */
79
80 #define PORT2B 5                /*  PORT 2B DATA */
81
82 #define PORT2C 6                /*  PORT 2C DATA */
83
84 #define CONTROL2 7              /*  CONTROL REGISTER 2 */
85
86 /* DAC registers */
87 #define DACONTROL       0       /*  D/A CONTROL REGISTER */
88 #define SU      0000001         /*  Simultaneous update enabled */
89 #define NOSU    0000000         /*  Simultaneous update disabled */
90 #define ENABLEDAC       0000002 /*  Enable specified DAC */
91 #define DISABLEDAC      0000000 /*  Disable specified DAC */
92 #define RANGE2V5        0000000 /*  2.5V */
93 #define RANGE5V 0000200         /*  5V */
94 #define RANGE10V        0000300 /*  10V */
95 #define UNIP    0000400         /*  Unipolar outputs */
96 #define BIP     0000000         /*  Bipolar outputs */
97
98 #define DACALIBRATION1  4       /*  D/A CALIBRATION REGISTER 1 */
99 /* write bits */
100 /* serial data input for eeprom, caldacs, reference dac */
101 #define SERIAL_IN_BIT   0x1
102 #define CAL_CHANNEL_MASK        (0x7 << 1)
103 #define CAL_CHANNEL_BITS(channel)       (((channel) << 1) & CAL_CHANNEL_MASK)
104 /* read bits */
105 #define CAL_COUNTER_MASK        0x1f
106 /* calibration counter overflow status bit */
107 #define CAL_COUNTER_OVERFLOW_BIT        0x20
108 /* analog output is less than reference dac voltage */
109 #define AO_BELOW_REF_BIT        0x40
110 #define SERIAL_OUT_BIT  0x80    /*  serial data out, for reading from eeprom */
111
112 #define DACALIBRATION2  6       /*  D/A CALIBRATION REGISTER 2 */
113 #define SELECT_EEPROM_BIT       0x1     /*  send serial data in to eeprom */
114 /* don't send serial data to MAX542 reference dac */
115 #define DESELECT_REF_DAC_BIT    0x2
116 /* don't send serial data to caldac n */
117 #define DESELECT_CALDAC_BIT(n)  (0x4 << (n))
118 /* manual says to set this bit with no explanation */
119 #define DUMMY_BIT       0x40
120
121 #define DADATA  8               /*  FIRST D/A DATA REGISTER (0) */
122
123 static const struct comedi_lrange cb_pcidda_ranges = {
124         6,
125         {
126          BIP_RANGE(10),
127          BIP_RANGE(5),
128          BIP_RANGE(2.5),
129          UNI_RANGE(10),
130          UNI_RANGE(5),
131          UNI_RANGE(2.5),
132          }
133 };
134
135 /*
136  * Board descriptions for two imaginary boards.  Describing the
137  * boards in this way is optional, and completely driver-dependent.
138  * Some drivers use arrays such as this, other do not.
139  */
140 struct cb_pcidda_board {
141         const char *name;
142         char status;            /*  Driver status: */
143
144         /*
145          * 0 - tested
146          * 1 - manual read, not tested
147          * 2 - manual not read
148          */
149
150         unsigned short device_id;
151         int ao_chans;
152         int ao_bits;
153         const struct comedi_lrange *ranges;
154 };
155
156 static const struct cb_pcidda_board cb_pcidda_boards[] = {
157         {
158          .name = "pci-dda02/12",
159          .status = 1,
160          .device_id = PCI_DEVICE_ID_DDA02_12,
161          .ao_chans = 2,
162          .ao_bits = 12,
163          .ranges = &cb_pcidda_ranges,
164          },
165         {
166          .name = "pci-dda04/12",
167          .status = 1,
168          .device_id = PCI_DEVICE_ID_DDA04_12,
169          .ao_chans = 4,
170          .ao_bits = 12,
171          .ranges = &cb_pcidda_ranges,
172          },
173         {
174          .name = "pci-dda08/12",
175          .status = 0,
176          .device_id = PCI_DEVICE_ID_DDA08_12,
177          .ao_chans = 8,
178          .ao_bits = 12,
179          .ranges = &cb_pcidda_ranges,
180          },
181         {
182          .name = "pci-dda02/16",
183          .status = 2,
184          .device_id = PCI_DEVICE_ID_DDA02_16,
185          .ao_chans = 2,
186          .ao_bits = 16,
187          .ranges = &cb_pcidda_ranges,
188          },
189         {
190          .name = "pci-dda04/16",
191          .status = 2,
192          .device_id = PCI_DEVICE_ID_DDA04_16,
193          .ao_chans = 4,
194          .ao_bits = 16,
195          .ranges = &cb_pcidda_ranges,
196          },
197         {
198          .name = "pci-dda08/16",
199          .status = 0,
200          .device_id = PCI_DEVICE_ID_DDA08_16,
201          .ao_chans = 8,
202          .ao_bits = 16,
203          .ranges = &cb_pcidda_ranges,
204          },
205 };
206
207 /*
208  * this structure is for data unique to this hardware driver.  If
209  * several hardware drivers keep similar information in this structure,
210  * feel free to suggest moving the variable to the struct comedi_device
211  * struct.
212  */
213 struct cb_pcidda_private {
214         int data;
215
216         unsigned long digitalio;
217         unsigned long dac;
218
219         /* unsigned long control_status; */
220         /* unsigned long adc_fifo; */
221
222         /* bits last written to da calibration register 1 */
223         unsigned int dac_cal1_bits;
224         /* current range settings for output channels */
225         unsigned int ao_range[MAX_AO_CHANNELS];
226         u16 eeprom_data[EEPROM_SIZE];   /*  software copy of board's eeprom */
227 };
228
229 /* lowlevel read from eeprom */
230 static unsigned int cb_pcidda_serial_in(struct comedi_device *dev)
231 {
232         struct cb_pcidda_private *devpriv = dev->private;
233         unsigned int value = 0;
234         int i;
235         const int value_width = 16;     /*  number of bits wide values are */
236
237         for (i = 1; i <= value_width; i++) {
238                 /*  read bits most significant bit first */
239                 if (inw_p(devpriv->dac + DACALIBRATION1) & SERIAL_OUT_BIT)
240                         value |= 1 << (value_width - i);
241         }
242
243         return value;
244 }
245
246 /* lowlevel write to eeprom/dac */
247 static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
248                                  unsigned int num_bits)
249 {
250         struct cb_pcidda_private *devpriv = dev->private;
251         int i;
252
253         for (i = 1; i <= num_bits; i++) {
254                 /*  send bits most significant bit first */
255                 if (value & (1 << (num_bits - i)))
256                         devpriv->dac_cal1_bits |= SERIAL_IN_BIT;
257                 else
258                         devpriv->dac_cal1_bits &= ~SERIAL_IN_BIT;
259                 outw_p(devpriv->dac_cal1_bits, devpriv->dac + DACALIBRATION1);
260         }
261 }
262
263 /* reads a 16 bit value from board's eeprom */
264 static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
265                                           unsigned int address)
266 {
267         struct cb_pcidda_private *devpriv = dev->private;
268         unsigned int i;
269         unsigned int cal2_bits;
270         unsigned int value;
271         /* one caldac for every two dac channels */
272         const int max_num_caldacs = 4;
273         /* bits to send to tell eeprom we want to read */
274         const int read_instruction = 0x6;
275         const int instruction_length = 3;
276         const int address_length = 8;
277
278         /*  send serial output stream to eeprom */
279         cal2_bits = SELECT_EEPROM_BIT | DESELECT_REF_DAC_BIT | DUMMY_BIT;
280         /*  deactivate caldacs (one caldac for every two channels) */
281         for (i = 0; i < max_num_caldacs; i++)
282                 cal2_bits |= DESELECT_CALDAC_BIT(i);
283         outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
284
285         /*  tell eeprom we want to read */
286         cb_pcidda_serial_out(dev, read_instruction, instruction_length);
287         /*  send address we want to read from */
288         cb_pcidda_serial_out(dev, address, address_length);
289
290         value = cb_pcidda_serial_in(dev);
291
292         /*  deactivate eeprom */
293         cal2_bits &= ~SELECT_EEPROM_BIT;
294         outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
295
296         return value;
297 }
298
299 /* writes to 8 bit calibration dacs */
300 static void cb_pcidda_write_caldac(struct comedi_device *dev,
301                                    unsigned int caldac, unsigned int channel,
302                                    unsigned int value)
303 {
304         struct cb_pcidda_private *devpriv = dev->private;
305         unsigned int cal2_bits;
306         unsigned int i;
307         /* caldacs use 3 bit channel specification */
308         const int num_channel_bits = 3;
309         const int num_caldac_bits = 8;  /*  8 bit calibration dacs */
310         /* one caldac for every two dac channels */
311         const int max_num_caldacs = 4;
312
313         /* write 3 bit channel */
314         cb_pcidda_serial_out(dev, channel, num_channel_bits);
315         /*  write 8 bit caldac value */
316         cb_pcidda_serial_out(dev, value, num_caldac_bits);
317
318 /*
319 * latch stream into appropriate caldac deselect reference dac
320 */
321         cal2_bits = DESELECT_REF_DAC_BIT | DUMMY_BIT;
322         /*  deactivate caldacs (one caldac for every two channels) */
323         for (i = 0; i < max_num_caldacs; i++)
324                 cal2_bits |= DESELECT_CALDAC_BIT(i);
325         /*  activate the caldac we want */
326         cal2_bits &= ~DESELECT_CALDAC_BIT(caldac);
327         outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
328         /*  deactivate caldac */
329         cal2_bits |= DESELECT_CALDAC_BIT(caldac);
330         outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
331 }
332
333 /* returns caldac that calibrates given analog out channel */
334 static unsigned int caldac_number(unsigned int channel)
335 {
336         return channel / 2;
337 }
338
339 /* returns caldac channel that provides fine gain for given ao channel */
340 static unsigned int fine_gain_channel(unsigned int ao_channel)
341 {
342         return 4 * (ao_channel % 2);
343 }
344
345 /* returns caldac channel that provides coarse gain for given ao channel */
346 static unsigned int coarse_gain_channel(unsigned int ao_channel)
347 {
348         return 1 + 4 * (ao_channel % 2);
349 }
350
351 /* returns caldac channel that provides coarse offset for given ao channel */
352 static unsigned int coarse_offset_channel(unsigned int ao_channel)
353 {
354         return 2 + 4 * (ao_channel % 2);
355 }
356
357 /* returns caldac channel that provides fine offset for given ao channel */
358 static unsigned int fine_offset_channel(unsigned int ao_channel)
359 {
360         return 3 + 4 * (ao_channel % 2);
361 }
362
363 /* returns eeprom address that provides offset for given ao channel and range */
364 static unsigned int offset_eeprom_address(unsigned int ao_channel,
365                                           unsigned int range)
366 {
367         return 0x7 + 2 * range + 12 * ao_channel;
368 }
369
370 /*
371  * returns eeprom address that provides gain calibration for given ao
372  * channel and range
373  */
374 static unsigned int gain_eeprom_address(unsigned int ao_channel,
375                                         unsigned int range)
376 {
377         return 0x8 + 2 * range + 12 * ao_channel;
378 }
379
380 /*
381  * returns upper byte of eeprom entry, which gives the coarse adjustment
382  * values
383  */
384 static unsigned int eeprom_coarse_byte(unsigned int word)
385 {
386         return (word >> 8) & 0xff;
387 }
388
389 /* returns lower byte of eeprom entry, which gives the fine adjustment values */
390 static unsigned int eeprom_fine_byte(unsigned int word)
391 {
392         return word & 0xff;
393 }
394
395 /* set caldacs to eeprom values for given channel and range */
396 static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
397                                 unsigned int range)
398 {
399         struct cb_pcidda_private *devpriv = dev->private;
400         unsigned int coarse_offset, fine_offset, coarse_gain, fine_gain;
401
402         /* remember range so we can tell when we need to readjust calibration */
403         devpriv->ao_range[channel] = range;
404
405         /*  get values from eeprom data */
406         coarse_offset =
407             eeprom_coarse_byte(devpriv->eeprom_data
408                                [offset_eeprom_address(channel, range)]);
409         fine_offset =
410             eeprom_fine_byte(devpriv->eeprom_data
411                              [offset_eeprom_address(channel, range)]);
412         coarse_gain =
413             eeprom_coarse_byte(devpriv->eeprom_data
414                                [gain_eeprom_address(channel, range)]);
415         fine_gain =
416             eeprom_fine_byte(devpriv->eeprom_data
417                              [gain_eeprom_address(channel, range)]);
418
419         /*  set caldacs */
420         cb_pcidda_write_caldac(dev, caldac_number(channel),
421                                coarse_offset_channel(channel), coarse_offset);
422         cb_pcidda_write_caldac(dev, caldac_number(channel),
423                                fine_offset_channel(channel), fine_offset);
424         cb_pcidda_write_caldac(dev, caldac_number(channel),
425                                coarse_gain_channel(channel), coarse_gain);
426         cb_pcidda_write_caldac(dev, caldac_number(channel),
427                                fine_gain_channel(channel), fine_gain);
428 }
429
430 static int cb_pcidda_ao_winsn(struct comedi_device *dev,
431                               struct comedi_subdevice *s,
432                               struct comedi_insn *insn, unsigned int *data)
433 {
434         struct cb_pcidda_private *devpriv = dev->private;
435         unsigned int command;
436         unsigned int channel, range;
437
438         channel = CR_CHAN(insn->chanspec);
439         range = CR_RANGE(insn->chanspec);
440
441         /*  adjust calibration dacs if range has changed */
442         if (range != devpriv->ao_range[channel])
443                 cb_pcidda_calibrate(dev, channel, range);
444
445         /* output channel configuration */
446         command = NOSU | ENABLEDAC;
447
448         /* output channel range */
449         switch (range) {
450         case 0:
451                 command |= BIP | RANGE10V;
452                 break;
453         case 1:
454                 command |= BIP | RANGE5V;
455                 break;
456         case 2:
457                 command |= BIP | RANGE2V5;
458                 break;
459         case 3:
460                 command |= UNIP | RANGE10V;
461                 break;
462         case 4:
463                 command |= UNIP | RANGE5V;
464                 break;
465         case 5:
466                 command |= UNIP | RANGE2V5;
467                 break;
468         }
469
470         /* output channel specification */
471         command |= channel << 2;
472         outw(command, devpriv->dac + DACONTROL);
473
474         /* write data */
475         outw(data[0], devpriv->dac + DADATA + channel * 2);
476
477         /* return the number of samples read/written */
478         return 1;
479 }
480
481 static const void *cb_pcidda_find_boardinfo(struct comedi_device *dev,
482                                             struct pci_dev *pcidev)
483 {
484         const struct cb_pcidda_board *thisboard;
485         int i;
486
487         for (i = 0; i < ARRAY_SIZE(cb_pcidda_boards); i++) {
488                 thisboard = &cb_pcidda_boards[i];
489                 if (thisboard->device_id != pcidev->device)
490                         return thisboard;
491         }
492         return NULL;
493 }
494
495 static int cb_pcidda_attach_pci(struct comedi_device *dev,
496                                 struct pci_dev *pcidev)
497 {
498         const struct cb_pcidda_board *thisboard;
499         struct cb_pcidda_private *devpriv;
500         struct comedi_subdevice *s;
501         int index;
502         int ret;
503
504         thisboard = cb_pcidda_find_boardinfo(dev, pcidev);
505         if (!thisboard)
506                 return -ENODEV;
507         dev->board_ptr = thisboard;
508         dev->board_name = thisboard->name;
509
510         devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
511         if (!devpriv)
512                 return -ENOMEM;
513         dev->private = devpriv;
514
515         ret = comedi_pci_enable(pcidev, dev->board_name);
516         if (ret)
517                 return ret;
518
519         devpriv->digitalio = pci_resource_start(pcidev, 2);
520         devpriv->dac = pci_resource_start(pcidev, 3);
521         dev->iobase = devpriv->dac;
522
523         if (thisboard->status == 2)
524                 printk
525                     ("WARNING: DRIVER FOR THIS BOARD NOT CHECKED WITH MANUAL. "
526                      "WORKS ASSUMING FULL COMPATIBILITY WITH PCI-DDA08/12. "
527                      "PLEASE REPORT USAGE TO <ivanmr@altavista.com>.\n");
528
529         ret = comedi_alloc_subdevices(dev, 3);
530         if (ret)
531                 return ret;
532
533         s = &dev->subdevices[0];
534         /* analog output subdevice */
535         s->type = COMEDI_SUBD_AO;
536         s->subdev_flags = SDF_WRITABLE;
537         s->n_chan = thisboard->ao_chans;
538         s->maxdata = (1 << thisboard->ao_bits) - 1;
539         s->range_table = thisboard->ranges;
540         s->insn_write = cb_pcidda_ao_winsn;
541
542         /*  two 8255 digital io subdevices */
543         s = &dev->subdevices[1];
544         subdev_8255_init(dev, s, NULL, devpriv->digitalio);
545         s = &dev->subdevices[2];
546         subdev_8255_init(dev, s, NULL, devpriv->digitalio + PORT2A);
547
548         dev_dbg(dev->class_dev, "eeprom:\n");
549         for (index = 0; index < EEPROM_SIZE; index++) {
550                 devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index);
551                 dev_dbg(dev->class_dev, "%i:0x%x\n", index,
552                         devpriv->eeprom_data[index]);
553         }
554
555         /*  set calibrations dacs */
556         for (index = 0; index < thisboard->ao_chans; index++)
557                 cb_pcidda_calibrate(dev, index, devpriv->ao_range[index]);
558
559         dev_info(dev->class_dev, "%s attached\n", dev->board_name);
560
561         return 0;
562 }
563
564 static void cb_pcidda_detach(struct comedi_device *dev)
565 {
566         struct pci_dev *pcidev = comedi_to_pci_dev(dev);
567
568         if (dev->subdevices) {
569                 subdev_8255_cleanup(dev, &dev->subdevices[1]);
570                 subdev_8255_cleanup(dev, &dev->subdevices[2]);
571         }
572         if (pcidev) {
573                 if (dev->iobase)
574                         comedi_pci_disable(pcidev);
575         }
576 }
577
578 static struct comedi_driver cb_pcidda_driver = {
579         .driver_name    = "cb_pcidda",
580         .module         = THIS_MODULE,
581         .attach_pci     = cb_pcidda_attach_pci,
582         .detach         = cb_pcidda_detach,
583 };
584
585 static int __devinit cb_pcidda_pci_probe(struct pci_dev *dev,
586                                          const struct pci_device_id *ent)
587 {
588         return comedi_pci_auto_config(dev, &cb_pcidda_driver);
589 }
590
591 static void __devexit cb_pcidda_pci_remove(struct pci_dev *dev)
592 {
593         comedi_pci_auto_unconfig(dev);
594 }
595
596 static DEFINE_PCI_DEVICE_TABLE(cb_pcidda_pci_table) = {
597         { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA02_12) },
598         { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA04_12) },
599         { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA08_12) },
600         { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA02_16) },
601         { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA04_16) },
602         { PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA08_16) },
603         { 0 }
604 };
605 MODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table);
606
607 static struct pci_driver cb_pcidda_pci_driver = {
608         .name           = "cb_pcidda",
609         .id_table       = cb_pcidda_pci_table,
610         .probe          = cb_pcidda_pci_probe,
611         .remove         = __devexit_p(cb_pcidda_pci_remove),
612 };
613 module_comedi_pci_driver(cb_pcidda_driver, cb_pcidda_pci_driver);
614
615 MODULE_AUTHOR("Comedi http://www.comedi.org");
616 MODULE_DESCRIPTION("Comedi low-level driver");
617 MODULE_LICENSE("GPL");