1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include <linux/module.h>
34#include <linux/pci.h>
35#include <linux/interrupt.h>
36#include <linux/sched.h>
37
38#include "../comedidev.h"
39
40#include "plx9052.h"
41
42#define ME2600_FIRMWARE "me2600_firmware.bin"
43
44#define XILINX_DOWNLOAD_RESET 0x42
45
46#define ME_CONTROL_1 0x0000
47#define INTERRUPT_ENABLE (1<<15)
48#define COUNTER_B_IRQ (1<<12)
49#define COUNTER_A_IRQ (1<<11)
50#define CHANLIST_READY_IRQ (1<<10)
51#define EXT_IRQ (1<<9)
52#define ADFIFO_HALFFULL_IRQ (1<<8)
53#define SCAN_COUNT_ENABLE (1<<5)
54#define SIMULTANEOUS_ENABLE (1<<4)
55#define TRIGGER_FALLING_EDGE (1<<3)
56#define CONTINUOUS_MODE (1<<2)
57#define DISABLE_ADC (0<<0)
58#define SOFTWARE_TRIGGERED_ADC (1<<0)
59#define SCAN_TRIGGERED_ADC (2<<0)
60#define EXT_TRIGGERED_ADC (3<<0)
61#define ME_ADC_START 0x0000
62#define ME_CONTROL_2 0x0002
63#define ENABLE_ADFIFO (1<<10)
64#define ENABLE_CHANLIST (1<<9)
65#define ENABLE_PORT_B (1<<7)
66#define ENABLE_PORT_A (1<<6)
67#define ENABLE_COUNTER_B (1<<4)
68#define ENABLE_COUNTER_A (1<<3)
69#define ENABLE_DAC (1<<1)
70#define BUFFERED_DAC (1<<0)
71#define ME_DAC_UPDATE 0x0002
72#define ME_STATUS 0x0004
73#define COUNTER_B_IRQ_PENDING (1<<12)
74#define COUNTER_A_IRQ_PENDING (1<<11)
75#define CHANLIST_READY_IRQ_PENDING (1<<10)
76#define EXT_IRQ_PENDING (1<<9)
77#define ADFIFO_HALFFULL_IRQ_PENDING (1<<8)
78#define ADFIFO_FULL (1<<4)
79#define ADFIFO_HALFFULL (1<<3)
80#define ADFIFO_EMPTY (1<<2)
81#define CHANLIST_FULL (1<<1)
82#define FST_ACTIVE (1<<0)
83#define ME_RESET_INTERRUPT 0x0004
84#define ME_DIO_PORT_A 0x0006
85#define ME_DIO_PORT_B 0x0008
86#define ME_TIMER_DATA_0 0x000A
87#define ME_TIMER_DATA_1 0x000C
88#define ME_TIMER_DATA_2 0x000E
89#define ME_CHANNEL_LIST 0x0010
90#define ADC_UNIPOLAR (1<<6)
91#define ADC_GAIN_0 (0<<4)
92#define ADC_GAIN_1 (1<<4)
93#define ADC_GAIN_2 (2<<4)
94#define ADC_GAIN_3 (3<<4)
95#define ME_READ_AD_FIFO 0x0010
96#define ME_DAC_CONTROL 0x0012
97#define DAC_UNIPOLAR_D (0<<4)
98#define DAC_BIPOLAR_D (1<<4)
99#define DAC_UNIPOLAR_C (0<<5)
100#define DAC_BIPOLAR_C (1<<5)
101#define DAC_UNIPOLAR_B (0<<6)
102#define DAC_BIPOLAR_B (1<<6)
103#define DAC_UNIPOLAR_A (0<<7)
104#define DAC_BIPOLAR_A (1<<7)
105#define DAC_GAIN_0_D (0<<8)
106#define DAC_GAIN_1_D (1<<8)
107#define DAC_GAIN_0_C (0<<9)
108#define DAC_GAIN_1_C (1<<9)
109#define DAC_GAIN_0_B (0<<10)
110#define DAC_GAIN_1_B (1<<10)
111#define DAC_GAIN_0_A (0<<11)
112#define DAC_GAIN_1_A (1<<11)
113#define ME_DAC_CONTROL_UPDATE 0x0012
114#define ME_DAC_DATA_A 0x0014
115#define ME_DAC_DATA_B 0x0016
116#define ME_DAC_DATA_C 0x0018
117#define ME_DAC_DATA_D 0x001A
118#define ME_COUNTER_ENDDATA_A 0x001C
119#define ME_COUNTER_ENDDATA_B 0x001E
120#define ME_COUNTER_STARTDATA_A 0x0020
121#define ME_COUNTER_VALUE_A 0x0020
122#define ME_COUNTER_STARTDATA_B 0x0022
123#define ME_COUNTER_VALUE_B 0x0022
124
125static const struct comedi_lrange me_ai_range = {
126 8, {
127 BIP_RANGE(10),
128 BIP_RANGE(5),
129 BIP_RANGE(2.5),
130 BIP_RANGE(1.25),
131 UNI_RANGE(10),
132 UNI_RANGE(5),
133 UNI_RANGE(2.5),
134 UNI_RANGE(1.25)
135 }
136};
137
138static const struct comedi_lrange me_ao_range = {
139 3, {
140 BIP_RANGE(10),
141 BIP_RANGE(5),
142 UNI_RANGE(10)
143 }
144};
145
146enum me_boardid {
147 BOARD_ME2600,
148 BOARD_ME2000,
149};
150
151struct me_board {
152 const char *name;
153 int needs_firmware;
154 int has_ao;
155};
156
157static const struct me_board me_boards[] = {
158 [BOARD_ME2600] = {
159 .name = "me-2600i",
160 .needs_firmware = 1,
161 .has_ao = 1,
162 },
163 [BOARD_ME2000] = {
164 .name = "me-2000i",
165 },
166};
167
168struct me_private_data {
169 void __iomem *plx_regbase;
170 void __iomem *me_regbase;
171
172 unsigned short control_1;
173 unsigned short control_2;
174 unsigned short dac_control;
175 int ao_readback[4];
176};
177
178static inline void sleep(unsigned sec)
179{
180 current->state = TASK_INTERRUPTIBLE;
181 schedule_timeout(sec * HZ);
182}
183
184static int me_dio_insn_config(struct comedi_device *dev,
185 struct comedi_subdevice *s,
186 struct comedi_insn *insn,
187 unsigned int *data)
188{
189 struct me_private_data *devpriv = dev->private;
190 unsigned int chan = CR_CHAN(insn->chanspec);
191 unsigned int mask;
192 int ret;
193
194 if (chan < 16)
195 mask = 0x0000ffff;
196 else
197 mask = 0xffff0000;
198
199 ret = comedi_dio_insn_config(dev, s, insn, data, mask);
200 if (ret)
201 return ret;
202
203 if (s->io_bits & 0x0000ffff)
204 devpriv->control_2 |= ENABLE_PORT_A;
205 else
206 devpriv->control_2 &= ~ENABLE_PORT_A;
207 if (s->io_bits & 0xffff0000)
208 devpriv->control_2 |= ENABLE_PORT_B;
209 else
210 devpriv->control_2 &= ~ENABLE_PORT_B;
211
212 writew(devpriv->control_2, devpriv->me_regbase + ME_CONTROL_2);
213
214 return insn->n;
215}
216
217static int me_dio_insn_bits(struct comedi_device *dev,
218 struct comedi_subdevice *s,
219 struct comedi_insn *insn,
220 unsigned int *data)
221{
222 struct me_private_data *dev_private = dev->private;
223 void __iomem *mmio_porta = dev_private->me_regbase + ME_DIO_PORT_A;
224 void __iomem *mmio_portb = dev_private->me_regbase + ME_DIO_PORT_B;
225 unsigned int mask = data[0];
226 unsigned int bits = data[1];
227 unsigned int val;
228
229 mask &= s->io_bits;
230 if (mask) {
231 s->state &= ~mask;
232 s->state |= (bits & mask);
233
234 if (mask & 0x0000ffff)
235 writew((s->state & 0xffff), mmio_porta);
236 if (mask & 0xffff0000)
237 writew(((s->state >> 16) & 0xffff), mmio_portb);
238 }
239
240 if (s->io_bits & 0x0000ffff)
241 val = s->state & 0xffff;
242 else
243 val = readw(mmio_porta);
244
245 if (s->io_bits & 0xffff0000)
246 val |= (s->state & 0xffff0000);
247 else
248 val |= (readw(mmio_portb) << 16);
249
250 data[1] = val;
251
252 return insn->n;
253}
254
255static int me_ai_insn_read(struct comedi_device *dev,
256 struct comedi_subdevice *s,
257 struct comedi_insn *insn,
258 unsigned int *data)
259{
260 struct me_private_data *dev_private = dev->private;
261 unsigned int chan = CR_CHAN(insn->chanspec);
262 unsigned int rang = CR_RANGE(insn->chanspec);
263 unsigned int aref = CR_AREF(insn->chanspec);
264 unsigned short val;
265 int i;
266
267
268 dev_private->control_1 &= 0xFFFC;
269 writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1);
270
271
272 dev_private->control_2 &= ~(ENABLE_ADFIFO | ENABLE_CHANLIST);
273 writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
274
275
276 writew(0x00, dev_private->me_regbase + ME_RESET_INTERRUPT);
277
278
279 dev_private->control_2 |= (ENABLE_ADFIFO | ENABLE_CHANLIST);
280 writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
281
282
283 val = chan & 0x0f;
284 val |= (rang & 0x03) << 4;
285 val |= (rang & 0x04) << 4;
286 val |= ((aref & AREF_DIFF) ? 0x80 : 0);
287 writew(val & 0xff, dev_private->me_regbase + ME_CHANNEL_LIST);
288
289
290 dev_private->control_1 |= SOFTWARE_TRIGGERED_ADC;
291 writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1);
292
293
294 readw(dev_private->me_regbase + ME_ADC_START);
295
296
297 for (i = 100000; i > 0; i--)
298 if (!(readw(dev_private->me_regbase + ME_STATUS) & 0x0004))
299 break;
300
301
302 if (i) {
303 val = readw(dev_private->me_regbase + ME_READ_AD_FIFO);
304 val = (val ^ 0x800) & 0x0fff;
305 data[0] = val;
306 } else {
307 dev_err(dev->class_dev, "Cannot get single value\n");
308 return -EIO;
309 }
310
311
312 dev_private->control_1 &= 0xFFFC;
313 writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1);
314
315 return 1;
316}
317
318static int me_ao_insn_write(struct comedi_device *dev,
319 struct comedi_subdevice *s,
320 struct comedi_insn *insn,
321 unsigned int *data)
322{
323 struct me_private_data *dev_private = dev->private;
324 unsigned int chan = CR_CHAN(insn->chanspec);
325 unsigned int rang = CR_RANGE(insn->chanspec);
326 int i;
327
328
329 dev_private->control_2 |= ENABLE_DAC;
330 writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
331
332
333 dev_private->control_2 |= BUFFERED_DAC;
334 writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
335
336
337 for (i = 0; i < insn->n; i++) {
338
339 dev_private->dac_control &= ~(0x0880 >> chan);
340 if (rang == 0)
341 dev_private->dac_control |=
342 ((DAC_BIPOLAR_A | DAC_GAIN_1_A) >> chan);
343 else if (rang == 1)
344 dev_private->dac_control |=
345 ((DAC_BIPOLAR_A | DAC_GAIN_0_A) >> chan);
346 }
347 writew(dev_private->dac_control,
348 dev_private->me_regbase + ME_DAC_CONTROL);
349
350
351 readw(dev_private->me_regbase + ME_DAC_CONTROL_UPDATE);
352
353
354 for (i = 0; i < insn->n; i++) {
355 writew((data[0] & s->maxdata),
356 dev_private->me_regbase + ME_DAC_DATA_A + (chan << 1));
357 dev_private->ao_readback[chan] = (data[0] & s->maxdata);
358 }
359
360
361 readw(dev_private->me_regbase + ME_DAC_UPDATE);
362
363 return insn->n;
364}
365
366static int me_ao_insn_read(struct comedi_device *dev,
367 struct comedi_subdevice *s,
368 struct comedi_insn *insn,
369 unsigned int *data)
370{
371 struct me_private_data *dev_private = dev->private;
372 unsigned int chan = CR_CHAN(insn->chanspec);
373 int i;
374
375 for (i = 0; i < insn->n; i++)
376 data[i] = dev_private->ao_readback[chan];
377
378 return insn->n;
379}
380
381static int me2600_xilinx_download(struct comedi_device *dev,
382 const u8 *data, size_t size,
383 unsigned long context)
384{
385 struct me_private_data *dev_private = dev->private;
386 unsigned int value;
387 unsigned int file_length;
388 unsigned int i;
389
390
391 writel(0x00, dev_private->plx_regbase + PLX9052_INTCSR);
392
393
394 value = readw(dev_private->me_regbase + XILINX_DOWNLOAD_RESET);
395
396
397 sleep(1);
398
399
400 writeb(0x00, dev_private->me_regbase + 0x0);
401 sleep(1);
402
403
404
405
406
407
408
409
410
411 if (size < 16)
412 return -EINVAL;
413
414 file_length = (((unsigned int)data[0] & 0xff) << 24) +
415 (((unsigned int)data[1] & 0xff) << 16) +
416 (((unsigned int)data[2] & 0xff) << 8) +
417 ((unsigned int)data[3] & 0xff);
418
419
420
421
422
423 for (i = 0; i < file_length; i++)
424 writeb((data[16 + i] & 0xff),
425 dev_private->me_regbase + 0x0);
426
427
428 for (i = 0; i < 5; i++)
429 writeb(0x00, dev_private->me_regbase + 0x0);
430
431
432 value = readl(dev_private->plx_regbase + PLX9052_INTCSR);
433 if (value & PLX9052_INTCSR_LI2STAT) {
434
435 writel(0x00, dev_private->plx_regbase + PLX9052_INTCSR);
436 dev_err(dev->class_dev, "Xilinx download failed\n");
437 return -EIO;
438 }
439
440
441 sleep(1);
442
443
444 writel(PLX9052_INTCSR_LI1ENAB |
445 PLX9052_INTCSR_LI1POL |
446 PLX9052_INTCSR_PCIENAB,
447 dev_private->plx_regbase + PLX9052_INTCSR);
448
449 return 0;
450}
451
452static int me_reset(struct comedi_device *dev)
453{
454 struct me_private_data *dev_private = dev->private;
455
456
457 writew(0x00, dev_private->me_regbase + ME_CONTROL_1);
458 writew(0x00, dev_private->me_regbase + ME_CONTROL_2);
459 writew(0x00, dev_private->me_regbase + ME_RESET_INTERRUPT);
460 writew(0x00, dev_private->me_regbase + ME_DAC_CONTROL);
461
462
463 dev_private->dac_control = 0;
464 dev_private->control_1 = 0;
465 dev_private->control_2 = 0;
466
467 return 0;
468}
469
470static int me_auto_attach(struct comedi_device *dev,
471 unsigned long context)
472{
473 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
474 const struct me_board *board = NULL;
475 struct me_private_data *dev_private;
476 struct comedi_subdevice *s;
477 int ret;
478
479 if (context < ARRAY_SIZE(me_boards))
480 board = &me_boards[context];
481 if (!board)
482 return -ENODEV;
483 dev->board_ptr = board;
484 dev->board_name = board->name;
485
486 dev_private = comedi_alloc_devpriv(dev, sizeof(*dev_private));
487 if (!dev_private)
488 return -ENOMEM;
489
490 ret = comedi_pci_enable(dev);
491 if (ret)
492 return ret;
493
494 dev_private->plx_regbase = pci_ioremap_bar(pcidev, 0);
495 if (!dev_private->plx_regbase)
496 return -ENOMEM;
497
498 dev_private->me_regbase = pci_ioremap_bar(pcidev, 2);
499 if (!dev_private->me_regbase)
500 return -ENOMEM;
501
502
503 if (board->needs_firmware) {
504 ret = comedi_load_firmware(dev, &comedi_to_pci_dev(dev)->dev,
505 ME2600_FIRMWARE,
506 me2600_xilinx_download, 0);
507 if (ret < 0)
508 return ret;
509 }
510 me_reset(dev);
511
512 ret = comedi_alloc_subdevices(dev, 3);
513 if (ret)
514 return ret;
515
516 s = &dev->subdevices[0];
517 s->type = COMEDI_SUBD_AI;
518 s->subdev_flags = SDF_READABLE | SDF_COMMON;
519 s->n_chan = 16;
520 s->maxdata = 0x0fff;
521 s->len_chanlist = 16;
522 s->range_table = &me_ai_range;
523 s->insn_read = me_ai_insn_read;
524
525 s = &dev->subdevices[1];
526 if (board->has_ao) {
527 s->type = COMEDI_SUBD_AO;
528 s->subdev_flags = SDF_WRITEABLE | SDF_COMMON;
529 s->n_chan = 4;
530 s->maxdata = 0x0fff;
531 s->len_chanlist = 4;
532 s->range_table = &me_ao_range;
533 s->insn_read = me_ao_insn_read;
534 s->insn_write = me_ao_insn_write;
535 } else {
536 s->type = COMEDI_SUBD_UNUSED;
537 }
538
539 s = &dev->subdevices[2];
540 s->type = COMEDI_SUBD_DIO;
541 s->subdev_flags = SDF_READABLE | SDF_WRITEABLE;
542 s->n_chan = 32;
543 s->maxdata = 1;
544 s->len_chanlist = 32;
545 s->range_table = &range_digital;
546 s->insn_bits = me_dio_insn_bits;
547 s->insn_config = me_dio_insn_config;
548 s->io_bits = 0;
549
550 dev_info(dev->class_dev, "%s: %s attached\n",
551 dev->driver->driver_name, dev->board_name);
552
553 return 0;
554}
555
556static void me_detach(struct comedi_device *dev)
557{
558 struct me_private_data *dev_private = dev->private;
559
560 if (dev_private) {
561 if (dev_private->me_regbase) {
562 me_reset(dev);
563 iounmap(dev_private->me_regbase);
564 }
565 if (dev_private->plx_regbase)
566 iounmap(dev_private->plx_regbase);
567 }
568 comedi_pci_disable(dev);
569}
570
571static struct comedi_driver me_daq_driver = {
572 .driver_name = "me_daq",
573 .module = THIS_MODULE,
574 .auto_attach = me_auto_attach,
575 .detach = me_detach,
576};
577
578static int me_daq_pci_probe(struct pci_dev *dev,
579 const struct pci_device_id *id)
580{
581 return comedi_pci_auto_config(dev, &me_daq_driver, id->driver_data);
582}
583
584static DEFINE_PCI_DEVICE_TABLE(me_daq_pci_table) = {
585 { PCI_VDEVICE(MEILHAUS, 0x2600), BOARD_ME2600 },
586 { PCI_VDEVICE(MEILHAUS, 0x2000), BOARD_ME2000 },
587 { 0 }
588};
589MODULE_DEVICE_TABLE(pci, me_daq_pci_table);
590
591static struct pci_driver me_daq_pci_driver = {
592 .name = "me_daq",
593 .id_table = me_daq_pci_table,
594 .probe = me_daq_pci_probe,
595 .remove = comedi_pci_auto_unconfig,
596};
597module_comedi_pci_driver(me_daq_driver, me_daq_pci_driver);
598
599MODULE_AUTHOR("Comedi http://www.comedi.org");
600MODULE_DESCRIPTION("Comedi low-level driver");
601MODULE_LICENSE("GPL");
602MODULE_FIRMWARE(ME2600_FIRMWARE);
603