1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include <linux/module.h>
24#include <linux/interrupt.h>
25#include <linux/sched.h>
26
27#include "../comedi_pci.h"
28
29#include "plx9052.h"
30
31#define ME2600_FIRMWARE "me2600_firmware.bin"
32
33#define XILINX_DOWNLOAD_RESET 0x42
34
35
36
37
38#define ME_CTRL1_REG 0x00
39#define ME_CTRL1_INT_ENA BIT(15)
40#define ME_CTRL1_COUNTER_B_IRQ BIT(12)
41#define ME_CTRL1_COUNTER_A_IRQ BIT(11)
42#define ME_CTRL1_CHANLIST_READY_IRQ BIT(10)
43#define ME_CTRL1_EXT_IRQ BIT(9)
44#define ME_CTRL1_ADFIFO_HALFFULL_IRQ BIT(8)
45#define ME_CTRL1_SCAN_COUNT_ENA BIT(5)
46#define ME_CTRL1_SIMULTANEOUS_ENA BIT(4)
47#define ME_CTRL1_TRIGGER_FALLING_EDGE BIT(3)
48#define ME_CTRL1_CONTINUOUS_MODE BIT(2)
49#define ME_CTRL1_ADC_MODE(x) (((x) & 0x3) << 0)
50#define ME_CTRL1_ADC_MODE_DISABLE ME_CTRL1_ADC_MODE(0)
51#define ME_CTRL1_ADC_MODE_SOFT_TRIG ME_CTRL1_ADC_MODE(1)
52#define ME_CTRL1_ADC_MODE_SCAN_TRIG ME_CTRL1_ADC_MODE(2)
53#define ME_CTRL1_ADC_MODE_EXT_TRIG ME_CTRL1_ADC_MODE(3)
54#define ME_CTRL1_ADC_MODE_MASK ME_CTRL1_ADC_MODE(3)
55#define ME_CTRL2_REG 0x02
56#define ME_CTRL2_ADFIFO_ENA BIT(10)
57#define ME_CTRL2_CHANLIST_ENA BIT(9)
58#define ME_CTRL2_PORT_B_ENA BIT(7)
59#define ME_CTRL2_PORT_A_ENA BIT(6)
60#define ME_CTRL2_COUNTER_B_ENA BIT(4)
61#define ME_CTRL2_COUNTER_A_ENA BIT(3)
62#define ME_CTRL2_DAC_ENA BIT(1)
63#define ME_CTRL2_BUFFERED_DAC BIT(0)
64#define ME_STATUS_REG 0x04
65#define ME_STATUS_COUNTER_B_IRQ BIT(12)
66#define ME_STATUS_COUNTER_A_IRQ BIT(11)
67#define ME_STATUS_CHANLIST_READY_IRQ BIT(10)
68#define ME_STATUS_EXT_IRQ BIT(9)
69#define ME_STATUS_ADFIFO_HALFFULL_IRQ BIT(8)
70#define ME_STATUS_ADFIFO_FULL BIT(4)
71#define ME_STATUS_ADFIFO_HALFFULL BIT(3)
72#define ME_STATUS_ADFIFO_EMPTY BIT(2)
73#define ME_STATUS_CHANLIST_FULL BIT(1)
74#define ME_STATUS_FST_ACTIVE BIT(0)
75#define ME_DIO_PORT_A_REG 0x06
76#define ME_DIO_PORT_B_REG 0x08
77#define ME_TIMER_DATA_REG(x) (0x0a + ((x) * 2))
78#define ME_AI_FIFO_REG 0x10
79#define ME_AI_FIFO_CHANLIST_DIFF BIT(7)
80#define ME_AI_FIFO_CHANLIST_UNIPOLAR BIT(6)
81#define ME_AI_FIFO_CHANLIST_GAIN(x) (((x) & 0x3) << 4)
82#define ME_AI_FIFO_CHANLIST_CHAN(x) (((x) & 0xf) << 0)
83#define ME_DAC_CTRL_REG 0x12
84#define ME_DAC_CTRL_BIPOLAR(x) BIT(7 - ((x) & 0x3))
85#define ME_DAC_CTRL_GAIN(x) BIT(11 - ((x) & 0x3))
86#define ME_DAC_CTRL_MASK(x) (ME_DAC_CTRL_BIPOLAR(x) | \
87 ME_DAC_CTRL_GAIN(x))
88#define ME_AO_DATA_REG(x) (0x14 + ((x) * 2))
89#define ME_COUNTER_ENDDATA_REG(x) (0x1c + ((x) * 2))
90#define ME_COUNTER_STARTDATA_REG(x) (0x20 + ((x) * 2))
91#define ME_COUNTER_VALUE_REG(x) (0x20 + ((x) * 2))
92
93static const struct comedi_lrange me_ai_range = {
94 8, {
95 BIP_RANGE(10),
96 BIP_RANGE(5),
97 BIP_RANGE(2.5),
98 BIP_RANGE(1.25),
99 UNI_RANGE(10),
100 UNI_RANGE(5),
101 UNI_RANGE(2.5),
102 UNI_RANGE(1.25)
103 }
104};
105
106static const struct comedi_lrange me_ao_range = {
107 3, {
108 BIP_RANGE(10),
109 BIP_RANGE(5),
110 UNI_RANGE(10)
111 }
112};
113
114enum me_boardid {
115 BOARD_ME2600,
116 BOARD_ME2000,
117};
118
119struct me_board {
120 const char *name;
121 int needs_firmware;
122 int has_ao;
123};
124
125static const struct me_board me_boards[] = {
126 [BOARD_ME2600] = {
127 .name = "me-2600i",
128 .needs_firmware = 1,
129 .has_ao = 1,
130 },
131 [BOARD_ME2000] = {
132 .name = "me-2000i",
133 },
134};
135
136struct me_private_data {
137 void __iomem *plx_regbase;
138
139 unsigned short ctrl1;
140 unsigned short ctrl2;
141 unsigned short dac_ctrl;
142};
143
144static inline void sleep(unsigned int sec)
145{
146 schedule_timeout_interruptible(sec * HZ);
147}
148
149static int me_dio_insn_config(struct comedi_device *dev,
150 struct comedi_subdevice *s,
151 struct comedi_insn *insn,
152 unsigned int *data)
153{
154 struct me_private_data *devpriv = dev->private;
155 unsigned int chan = CR_CHAN(insn->chanspec);
156 unsigned int mask;
157 int ret;
158
159 if (chan < 16)
160 mask = 0x0000ffff;
161 else
162 mask = 0xffff0000;
163
164 ret = comedi_dio_insn_config(dev, s, insn, data, mask);
165 if (ret)
166 return ret;
167
168 if (s->io_bits & 0x0000ffff)
169 devpriv->ctrl2 |= ME_CTRL2_PORT_A_ENA;
170 else
171 devpriv->ctrl2 &= ~ME_CTRL2_PORT_A_ENA;
172 if (s->io_bits & 0xffff0000)
173 devpriv->ctrl2 |= ME_CTRL2_PORT_B_ENA;
174 else
175 devpriv->ctrl2 &= ~ME_CTRL2_PORT_B_ENA;
176
177 writew(devpriv->ctrl2, dev->mmio + ME_CTRL2_REG);
178
179 return insn->n;
180}
181
182static int me_dio_insn_bits(struct comedi_device *dev,
183 struct comedi_subdevice *s,
184 struct comedi_insn *insn,
185 unsigned int *data)
186{
187 void __iomem *mmio_porta = dev->mmio + ME_DIO_PORT_A_REG;
188 void __iomem *mmio_portb = dev->mmio + ME_DIO_PORT_B_REG;
189 unsigned int mask;
190 unsigned int val;
191
192 mask = comedi_dio_update_state(s, data);
193 if (mask) {
194 if (mask & 0x0000ffff)
195 writew((s->state & 0xffff), mmio_porta);
196 if (mask & 0xffff0000)
197 writew(((s->state >> 16) & 0xffff), mmio_portb);
198 }
199
200 if (s->io_bits & 0x0000ffff)
201 val = s->state & 0xffff;
202 else
203 val = readw(mmio_porta);
204
205 if (s->io_bits & 0xffff0000)
206 val |= (s->state & 0xffff0000);
207 else
208 val |= (readw(mmio_portb) << 16);
209
210 data[1] = val;
211
212 return insn->n;
213}
214
215static int me_ai_eoc(struct comedi_device *dev,
216 struct comedi_subdevice *s,
217 struct comedi_insn *insn,
218 unsigned long context)
219{
220 unsigned int status;
221
222 status = readw(dev->mmio + ME_STATUS_REG);
223 if ((status & ME_STATUS_ADFIFO_EMPTY) == 0)
224 return 0;
225 return -EBUSY;
226}
227
228static int me_ai_insn_read(struct comedi_device *dev,
229 struct comedi_subdevice *s,
230 struct comedi_insn *insn,
231 unsigned int *data)
232{
233 struct me_private_data *devpriv = dev->private;
234 unsigned int chan = CR_CHAN(insn->chanspec);
235 unsigned int range = CR_RANGE(insn->chanspec);
236 unsigned int aref = CR_AREF(insn->chanspec);
237 unsigned int val;
238 int ret = 0;
239 int i;
240
241
242
243
244
245 if (aref & AREF_DIFF) {
246 if (chan > 7 || comedi_range_is_unipolar(s, range))
247 return -EINVAL;
248 }
249
250
251 devpriv->ctrl2 &= ~(ME_CTRL2_ADFIFO_ENA | ME_CTRL2_CHANLIST_ENA);
252 writew(devpriv->ctrl2, dev->mmio + ME_CTRL2_REG);
253
254 writew(0x00, dev->mmio + ME_STATUS_REG);
255
256
257 devpriv->ctrl2 |= (ME_CTRL2_ADFIFO_ENA | ME_CTRL2_CHANLIST_ENA);
258 writew(devpriv->ctrl2, dev->mmio + ME_CTRL2_REG);
259
260
261 val = ME_AI_FIFO_CHANLIST_CHAN(chan) | ME_AI_FIFO_CHANLIST_GAIN(range);
262 if (comedi_range_is_unipolar(s, range))
263 val |= ME_AI_FIFO_CHANLIST_UNIPOLAR;
264 if (aref & AREF_DIFF)
265 val |= ME_AI_FIFO_CHANLIST_DIFF;
266 writew(val, dev->mmio + ME_AI_FIFO_REG);
267
268
269 devpriv->ctrl1 |= ME_CTRL1_ADC_MODE_SOFT_TRIG;
270 writew(devpriv->ctrl1, dev->mmio + ME_CTRL1_REG);
271
272 for (i = 0; i < insn->n; i++) {
273
274 readw(dev->mmio + ME_CTRL1_REG);
275
276
277 ret = comedi_timeout(dev, s, insn, me_ai_eoc, 0);
278 if (ret)
279 break;
280
281
282 val = readw(dev->mmio + ME_AI_FIFO_REG) & s->maxdata;
283
284
285 data[i] = comedi_offset_munge(s, val);
286 }
287
288
289 devpriv->ctrl1 &= ~ME_CTRL1_ADC_MODE_MASK;
290 writew(devpriv->ctrl1, dev->mmio + ME_CTRL1_REG);
291
292 return ret ? ret : insn->n;
293}
294
295static int me_ao_insn_write(struct comedi_device *dev,
296 struct comedi_subdevice *s,
297 struct comedi_insn *insn,
298 unsigned int *data)
299{
300 struct me_private_data *devpriv = dev->private;
301 unsigned int chan = CR_CHAN(insn->chanspec);
302 unsigned int range = CR_RANGE(insn->chanspec);
303 unsigned int val = s->readback[chan];
304 int i;
305
306
307 devpriv->ctrl2 |= ME_CTRL2_DAC_ENA;
308 writew(devpriv->ctrl2, dev->mmio + ME_CTRL2_REG);
309
310
311 devpriv->ctrl2 |= ME_CTRL2_BUFFERED_DAC;
312 writew(devpriv->ctrl2, dev->mmio + ME_CTRL2_REG);
313
314
315 devpriv->dac_ctrl &= ~ME_DAC_CTRL_MASK(chan);
316 if (range == 0)
317 devpriv->dac_ctrl |= ME_DAC_CTRL_GAIN(chan);
318 if (comedi_range_is_bipolar(s, range))
319 devpriv->dac_ctrl |= ME_DAC_CTRL_BIPOLAR(chan);
320 writew(devpriv->dac_ctrl, dev->mmio + ME_DAC_CTRL_REG);
321
322
323 readw(dev->mmio + ME_DAC_CTRL_REG);
324
325
326 for (i = 0; i < insn->n; i++) {
327 val = data[i];
328
329 writew(val, dev->mmio + ME_AO_DATA_REG(chan));
330 }
331 s->readback[chan] = val;
332
333
334 readw(dev->mmio + ME_CTRL2_REG);
335
336 return insn->n;
337}
338
339static int me2600_xilinx_download(struct comedi_device *dev,
340 const u8 *data, size_t size,
341 unsigned long context)
342{
343 struct me_private_data *devpriv = dev->private;
344 unsigned int value;
345 unsigned int file_length;
346 unsigned int i;
347
348
349 writel(0x00, devpriv->plx_regbase + PLX9052_INTCSR);
350
351
352 value = readw(dev->mmio + XILINX_DOWNLOAD_RESET);
353
354
355 sleep(1);
356
357
358 writeb(0x00, dev->mmio + 0x0);
359 sleep(1);
360
361
362
363
364
365
366
367
368
369 if (size < 16)
370 return -EINVAL;
371
372 file_length = (((unsigned int)data[0] & 0xff) << 24) +
373 (((unsigned int)data[1] & 0xff) << 16) +
374 (((unsigned int)data[2] & 0xff) << 8) +
375 ((unsigned int)data[3] & 0xff);
376
377
378
379
380
381 for (i = 0; i < file_length; i++)
382 writeb((data[16 + i] & 0xff), dev->mmio + 0x0);
383
384
385 for (i = 0; i < 5; i++)
386 writeb(0x00, dev->mmio + 0x0);
387
388
389 value = readl(devpriv->plx_regbase + PLX9052_INTCSR);
390 if (value & PLX9052_INTCSR_LI2STAT) {
391
392 writel(0x00, devpriv->plx_regbase + PLX9052_INTCSR);
393 dev_err(dev->class_dev, "Xilinx download failed\n");
394 return -EIO;
395 }
396
397
398 sleep(1);
399
400
401 writel(PLX9052_INTCSR_LI1ENAB |
402 PLX9052_INTCSR_LI1POL |
403 PLX9052_INTCSR_PCIENAB,
404 devpriv->plx_regbase + PLX9052_INTCSR);
405
406 return 0;
407}
408
409static int me_reset(struct comedi_device *dev)
410{
411 struct me_private_data *devpriv = dev->private;
412
413
414 writew(0x00, dev->mmio + ME_CTRL1_REG);
415 writew(0x00, dev->mmio + ME_CTRL2_REG);
416 writew(0x00, dev->mmio + ME_STATUS_REG);
417 writew(0x00, dev->mmio + ME_DAC_CTRL_REG);
418
419
420 devpriv->dac_ctrl = 0;
421 devpriv->ctrl1 = 0;
422 devpriv->ctrl2 = 0;
423
424 return 0;
425}
426
427static int me_auto_attach(struct comedi_device *dev,
428 unsigned long context)
429{
430 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
431 const struct me_board *board = NULL;
432 struct me_private_data *devpriv;
433 struct comedi_subdevice *s;
434 int ret;
435
436 if (context < ARRAY_SIZE(me_boards))
437 board = &me_boards[context];
438 if (!board)
439 return -ENODEV;
440 dev->board_ptr = board;
441 dev->board_name = board->name;
442
443 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
444 if (!devpriv)
445 return -ENOMEM;
446
447 ret = comedi_pci_enable(dev);
448 if (ret)
449 return ret;
450
451 devpriv->plx_regbase = pci_ioremap_bar(pcidev, 0);
452 if (!devpriv->plx_regbase)
453 return -ENOMEM;
454
455 dev->mmio = pci_ioremap_bar(pcidev, 2);
456 if (!dev->mmio)
457 return -ENOMEM;
458
459
460 if (board->needs_firmware) {
461 ret = comedi_load_firmware(dev, &comedi_to_pci_dev(dev)->dev,
462 ME2600_FIRMWARE,
463 me2600_xilinx_download, 0);
464 if (ret < 0)
465 return ret;
466 }
467 me_reset(dev);
468
469 ret = comedi_alloc_subdevices(dev, 3);
470 if (ret)
471 return ret;
472
473 s = &dev->subdevices[0];
474 s->type = COMEDI_SUBD_AI;
475 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_DIFF;
476 s->n_chan = 16;
477 s->maxdata = 0x0fff;
478 s->len_chanlist = 16;
479 s->range_table = &me_ai_range;
480 s->insn_read = me_ai_insn_read;
481
482 s = &dev->subdevices[1];
483 if (board->has_ao) {
484 s->type = COMEDI_SUBD_AO;
485 s->subdev_flags = SDF_WRITABLE | SDF_COMMON;
486 s->n_chan = 4;
487 s->maxdata = 0x0fff;
488 s->len_chanlist = 4;
489 s->range_table = &me_ao_range;
490 s->insn_write = me_ao_insn_write;
491
492 ret = comedi_alloc_subdev_readback(s);
493 if (ret)
494 return ret;
495 } else {
496 s->type = COMEDI_SUBD_UNUSED;
497 }
498
499 s = &dev->subdevices[2];
500 s->type = COMEDI_SUBD_DIO;
501 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
502 s->n_chan = 32;
503 s->maxdata = 1;
504 s->len_chanlist = 32;
505 s->range_table = &range_digital;
506 s->insn_bits = me_dio_insn_bits;
507 s->insn_config = me_dio_insn_config;
508
509 return 0;
510}
511
512static void me_detach(struct comedi_device *dev)
513{
514 struct me_private_data *devpriv = dev->private;
515
516 if (devpriv) {
517 if (dev->mmio)
518 me_reset(dev);
519 if (devpriv->plx_regbase)
520 iounmap(devpriv->plx_regbase);
521 }
522 comedi_pci_detach(dev);
523}
524
525static struct comedi_driver me_daq_driver = {
526 .driver_name = "me_daq",
527 .module = THIS_MODULE,
528 .auto_attach = me_auto_attach,
529 .detach = me_detach,
530};
531
532static int me_daq_pci_probe(struct pci_dev *dev,
533 const struct pci_device_id *id)
534{
535 return comedi_pci_auto_config(dev, &me_daq_driver, id->driver_data);
536}
537
538static const struct pci_device_id me_daq_pci_table[] = {
539 { PCI_VDEVICE(MEILHAUS, 0x2600), BOARD_ME2600 },
540 { PCI_VDEVICE(MEILHAUS, 0x2000), BOARD_ME2000 },
541 { 0 }
542};
543MODULE_DEVICE_TABLE(pci, me_daq_pci_table);
544
545static struct pci_driver me_daq_pci_driver = {
546 .name = "me_daq",
547 .id_table = me_daq_pci_table,
548 .probe = me_daq_pci_probe,
549 .remove = comedi_pci_auto_unconfig,
550};
551module_comedi_pci_driver(me_daq_driver, me_daq_pci_driver);
552
553MODULE_AUTHOR("Comedi http://www.comedi.org");
554MODULE_DESCRIPTION("Comedi low-level driver");
555MODULE_LICENSE("GPL");
556MODULE_FIRMWARE(ME2600_FIRMWARE);
557