3 * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
4 * Project manager: Eric Stolz
9 * Tel: +19(0)7223/9493-0
10 * Fax: +49(0)7223/9493-92
11 * http://www.addi-data.com
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version.
19 * This program is distributed in the hope that it will be useful, but WITHOUT
20 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
25 #include <linux/pci.h>
26 #include <linux/interrupt.h>
27 #include <linux/sched.h>
29 #include "../comedidev.h"
30 #include "comedi_fc.h"
31 #include "amcc_s5933.h"
34 * PCI bar 1 register I/O map
36 #define APCI3501_AO_CTRL_STATUS_REG 0x00
37 #define APCI3501_AO_CTRL_BIPOLAR (1 << 0)
38 #define APCI3501_AO_STATUS_READY (1 << 8)
39 #define APCI3501_AO_DATA_REG 0x04
40 #define APCI3501_AO_DATA_CHAN(x) ((x) << 0)
41 #define APCI3501_AO_DATA_VAL(x) ((x) << 8)
42 #define APCI3501_AO_DATA_BIPOLAR (1 << 31)
43 #define APCI3501_AO_TRIG_SCS_REG 0x08
44 #define APCI3501_TIMER_SYNC_REG 0x20
45 #define APCI3501_TIMER_RELOAD_REG 0x24
46 #define APCI3501_TIMER_TIMEBASE_REG 0x28
47 #define APCI3501_TIMER_CTRL_REG 0x2c
48 #define APCI3501_TIMER_STATUS_REG 0x30
49 #define APCI3501_TIMER_IRQ_REG 0x34
50 #define APCI3501_TIMER_WARN_RELOAD_REG 0x38
51 #define APCI3501_TIMER_WARN_TIMEBASE_REG 0x3c
52 #define APCI3501_DO_REG 0x40
53 #define APCI3501_DI_REG 0x50
58 #define NVRAM_USER_DATA_START 0x100
60 #define NVCMD_BEGIN_READ (0x7 << 5)
61 #define NVCMD_LOAD_LOW (0x4 << 5)
62 #define NVCMD_LOAD_HIGH (0x5 << 5)
65 * Function types stored in the eeprom
67 #define EEPROM_DIGITALINPUT 0
68 #define EEPROM_DIGITALOUTPUT 1
69 #define EEPROM_ANALOGINPUT 2
70 #define EEPROM_ANALOGOUTPUT 3
71 #define EEPROM_TIMER 4
72 #define EEPROM_WATCHDOG 5
73 #define EEPROM_TIMER_WATCHDOG_COUNTER 10
75 struct apci3501_private
{
77 struct task_struct
*tsk_Current
;
78 unsigned char b_TimerSelectMode
;
81 static struct comedi_lrange apci3501_ao_range
= {
88 static int apci3501_wait_for_dac(struct comedi_device
*dev
)
93 status
= inl(dev
->iobase
+ APCI3501_AO_CTRL_STATUS_REG
);
94 } while (!(status
& APCI3501_AO_STATUS_READY
));
99 static int apci3501_ao_insn_write(struct comedi_device
*dev
,
100 struct comedi_subdevice
*s
,
101 struct comedi_insn
*insn
,
104 unsigned int chan
= CR_CHAN(insn
->chanspec
);
105 unsigned int range
= CR_RANGE(insn
->chanspec
);
106 unsigned int val
= 0;
111 * All analog output channels have the same output range.
112 * 14-bit bipolar: 0-10V
113 * 13-bit unipolar: +/-10V
114 * Changing the range of one channel changes all of them!
117 outl(0, dev
->iobase
+ APCI3501_AO_CTRL_STATUS_REG
);
119 val
|= APCI3501_AO_DATA_BIPOLAR
;
120 outl(APCI3501_AO_CTRL_BIPOLAR
,
121 dev
->iobase
+ APCI3501_AO_CTRL_STATUS_REG
);
124 val
|= APCI3501_AO_DATA_CHAN(chan
);
126 for (i
= 0; i
< insn
->n
; i
++) {
128 if (data
[i
] > 0x1fff) {
129 dev_err(dev
->class_dev
,
130 "Unipolar resolution is only 13-bits\n");
135 ret
= apci3501_wait_for_dac(dev
);
139 outl(val
| APCI3501_AO_DATA_VAL(data
[i
]),
140 dev
->iobase
+ APCI3501_AO_DATA_REG
);
146 #include "addi-data/hwdrv_apci3501.c"
148 static int apci3501_di_insn_bits(struct comedi_device
*dev
,
149 struct comedi_subdevice
*s
,
150 struct comedi_insn
*insn
,
153 data
[1] = inl(dev
->iobase
+ APCI3501_DI_REG
) & 0x3;
158 static int apci3501_do_insn_bits(struct comedi_device
*dev
,
159 struct comedi_subdevice
*s
,
160 struct comedi_insn
*insn
,
163 unsigned int mask
= data
[0];
164 unsigned int bits
= data
[1];
166 s
->state
= inl(dev
->iobase
+ APCI3501_DO_REG
);
169 s
->state
|= (bits
& mask
);
171 outl(s
->state
, dev
->iobase
+ APCI3501_DO_REG
);
179 static void apci3501_eeprom_wait(unsigned long iobase
)
184 val
= inb(iobase
+ AMCC_OP_REG_MCSR_NVCMD
);
185 } while (val
& 0x80);
188 static unsigned short apci3501_eeprom_readw(unsigned long iobase
,
191 unsigned short val
= 0;
195 /* Add the offset to the start of the user data */
196 addr
+= NVRAM_USER_DATA_START
;
198 for (i
= 0; i
< 2; i
++) {
199 /* Load the low 8 bit address */
200 outb(NVCMD_LOAD_LOW
, iobase
+ AMCC_OP_REG_MCSR_NVCMD
);
201 apci3501_eeprom_wait(iobase
);
202 outb((addr
+ i
) & 0xff, iobase
+ AMCC_OP_REG_MCSR_NVDATA
);
203 apci3501_eeprom_wait(iobase
);
205 /* Load the high 8 bit address */
206 outb(NVCMD_LOAD_HIGH
, iobase
+ AMCC_OP_REG_MCSR_NVCMD
);
207 apci3501_eeprom_wait(iobase
);
208 outb(((addr
+ i
) >> 8) & 0xff,
209 iobase
+ AMCC_OP_REG_MCSR_NVDATA
);
210 apci3501_eeprom_wait(iobase
);
212 /* Read the eeprom data byte */
213 outb(NVCMD_BEGIN_READ
, iobase
+ AMCC_OP_REG_MCSR_NVCMD
);
214 apci3501_eeprom_wait(iobase
);
215 tmp
= inb(iobase
+ AMCC_OP_REG_MCSR_NVDATA
);
216 apci3501_eeprom_wait(iobase
);
227 static int apci3501_eeprom_get_ao_n_chan(struct comedi_device
*dev
)
229 struct apci3501_private
*devpriv
= dev
->private;
230 unsigned long iobase
= devpriv
->i_IobaseAmcc
;
231 unsigned char nfuncs
;
234 nfuncs
= apci3501_eeprom_readw(iobase
, 10) & 0xff;
236 /* Read functionality details */
237 for (i
= 0; i
< nfuncs
; i
++) {
238 unsigned short offset
= i
* 4;
243 func
= apci3501_eeprom_readw(iobase
, 12 + offset
) & 0x3f;
244 addr
= apci3501_eeprom_readw(iobase
, 14 + offset
);
246 if (func
== EEPROM_ANALOGOUTPUT
) {
247 val
= apci3501_eeprom_readw(iobase
, addr
+ 10);
248 return (val
>> 4) & 0x3ff;
254 static int apci3501_eeprom_insn_read(struct comedi_device
*dev
,
255 struct comedi_subdevice
*s
,
256 struct comedi_insn
*insn
,
259 struct apci3501_private
*devpriv
= dev
->private;
260 unsigned short addr
= CR_CHAN(insn
->chanspec
);
262 data
[0] = apci3501_eeprom_readw(devpriv
->i_IobaseAmcc
, 2 * addr
);
267 static irqreturn_t
apci3501_interrupt(int irq
, void *d
)
269 struct comedi_device
*dev
= d
;
270 struct apci3501_private
*devpriv
= dev
->private;
271 unsigned int ui_Timer_AOWatchdog
;
272 unsigned long ul_Command1
;
275 /* Disable Interrupt */
276 ul_Command1
= inl(dev
->iobase
+ APCI3501_TIMER_CTRL_REG
);
277 ul_Command1
= (ul_Command1
& 0xFFFFF9FDul
);
278 outl(ul_Command1
, dev
->iobase
+ APCI3501_TIMER_CTRL_REG
);
280 ui_Timer_AOWatchdog
= inl(dev
->iobase
+ APCI3501_TIMER_IRQ_REG
) & 0x1;
281 if ((!ui_Timer_AOWatchdog
)) {
282 comedi_error(dev
, "IRQ from unknown source");
286 /* Enable Interrupt Send a signal to from kernel to user space */
287 send_sig(SIGIO
, devpriv
->tsk_Current
, 0);
288 ul_Command1
= inl(dev
->iobase
+ APCI3501_TIMER_CTRL_REG
);
289 ul_Command1
= ((ul_Command1
& 0xFFFFF9FDul
) | 1 << 1);
290 outl(ul_Command1
, dev
->iobase
+ APCI3501_TIMER_CTRL_REG
);
291 i_temp
= inl(dev
->iobase
+ APCI3501_TIMER_STATUS_REG
) & 0x1;
296 static int apci3501_reset(struct comedi_device
*dev
)
302 /* Reset all digital outputs to "0" */
303 outl(0x0, dev
->iobase
+ APCI3501_DO_REG
);
305 /* Default all analog outputs to 0V (bipolar) */
306 outl(APCI3501_AO_CTRL_BIPOLAR
,
307 dev
->iobase
+ APCI3501_AO_CTRL_STATUS_REG
);
308 val
= APCI3501_AO_DATA_BIPOLAR
| APCI3501_AO_DATA_VAL(0);
310 /* Set all analog output channels */
311 for (chan
= 0; chan
< 8; chan
++) {
312 ret
= apci3501_wait_for_dac(dev
);
314 dev_warn(dev
->class_dev
,
315 "%s: DAC not-ready for channel %i\n",
318 outl(val
| APCI3501_AO_DATA_CHAN(chan
),
319 dev
->iobase
+ APCI3501_AO_DATA_REG
);
326 static int apci3501_auto_attach(struct comedi_device
*dev
,
327 unsigned long context_unused
)
329 struct pci_dev
*pcidev
= comedi_to_pci_dev(dev
);
330 struct apci3501_private
*devpriv
;
331 struct comedi_subdevice
*s
;
335 devpriv
= kzalloc(sizeof(*devpriv
), GFP_KERNEL
);
338 dev
->private = devpriv
;
340 ret
= comedi_pci_enable(dev
);
344 dev
->iobase
= pci_resource_start(pcidev
, 1);
345 devpriv
->i_IobaseAmcc
= pci_resource_start(pcidev
, 0);
347 ao_n_chan
= apci3501_eeprom_get_ao_n_chan(dev
);
349 if (pcidev
->irq
> 0) {
350 ret
= request_irq(pcidev
->irq
, apci3501_interrupt
, IRQF_SHARED
,
351 dev
->board_name
, dev
);
353 dev
->irq
= pcidev
->irq
;
356 ret
= comedi_alloc_subdevices(dev
, 5);
360 /* Initialize the analog output subdevice */
361 s
= &dev
->subdevices
[0];
363 s
->type
= COMEDI_SUBD_AO
;
364 s
->subdev_flags
= SDF_WRITEABLE
| SDF_GROUND
| SDF_COMMON
;
365 s
->n_chan
= ao_n_chan
;
367 s
->range_table
= &apci3501_ao_range
;
368 s
->insn_write
= apci3501_ao_insn_write
;
370 s
->type
= COMEDI_SUBD_UNUSED
;
373 /* Initialize the digital input subdevice */
374 s
= &dev
->subdevices
[1];
375 s
->type
= COMEDI_SUBD_DI
;
376 s
->subdev_flags
= SDF_READABLE
;
379 s
->range_table
= &range_digital
;
380 s
->insn_bits
= apci3501_di_insn_bits
;
382 /* Initialize the digital output subdevice */
383 s
= &dev
->subdevices
[2];
384 s
->type
= COMEDI_SUBD_DO
;
385 s
->subdev_flags
= SDF_WRITEABLE
;
388 s
->range_table
= &range_digital
;
389 s
->insn_bits
= apci3501_do_insn_bits
;
391 /* Initialize the timer/watchdog subdevice */
392 s
= &dev
->subdevices
[3];
393 s
->type
= COMEDI_SUBD_TIMER
;
394 s
->subdev_flags
= SDF_WRITEABLE
| SDF_GROUND
| SDF_COMMON
;
398 s
->range_table
= &range_digital
;
399 s
->insn_write
= i_APCI3501_StartStopWriteTimerCounterWatchdog
;
400 s
->insn_read
= i_APCI3501_ReadTimerCounterWatchdog
;
401 s
->insn_config
= i_APCI3501_ConfigTimerCounterWatchdog
;
403 /* Initialize the eeprom subdevice */
404 s
= &dev
->subdevices
[4];
405 s
->type
= COMEDI_SUBD_MEMORY
;
406 s
->subdev_flags
= SDF_READABLE
| SDF_INTERNAL
;
409 s
->insn_read
= apci3501_eeprom_insn_read
;
415 static void apci3501_detach(struct comedi_device
*dev
)
420 free_irq(dev
->irq
, dev
);
421 comedi_pci_disable(dev
);
424 static struct comedi_driver apci3501_driver
= {
425 .driver_name
= "addi_apci_3501",
426 .module
= THIS_MODULE
,
427 .auto_attach
= apci3501_auto_attach
,
428 .detach
= apci3501_detach
,
431 static int apci3501_pci_probe(struct pci_dev
*dev
,
432 const struct pci_device_id
*id
)
434 return comedi_pci_auto_config(dev
, &apci3501_driver
, id
->driver_data
);
437 static DEFINE_PCI_DEVICE_TABLE(apci3501_pci_table
) = {
438 { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA
, 0x3001) },
441 MODULE_DEVICE_TABLE(pci
, apci3501_pci_table
);
443 static struct pci_driver apci3501_pci_driver
= {
444 .name
= "addi_apci_3501",
445 .id_table
= apci3501_pci_table
,
446 .probe
= apci3501_pci_probe
,
447 .remove
= comedi_pci_auto_unconfig
,
449 module_comedi_pci_driver(apci3501_driver
, apci3501_pci_driver
);
451 MODULE_DESCRIPTION("ADDI-DATA APCI-3501 Analog output board");
452 MODULE_AUTHOR("Comedi http://www.comedi.org");
453 MODULE_LICENSE("GPL");