190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski/* 290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski comedi/drivers/mpc624.c 390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski Hardware driver for a Micro/sys inc. MPC-624 PC/104 board 490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski COMEDI - Linux Control and Measurement Device Interface 690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski Copyright (C) 2000 David A. Schleef <ds@schleef.org> 790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski This program is free software; you can redistribute it and/or modify 990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski it under the terms of the GNU General Public License as published by 1090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski the Free Software Foundation; either version 2 of the License, or 1190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski (at your option) any later version. 1290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 1390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski This program is distributed in the hope that it will be useful, 1490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski but WITHOUT ANY WARRANTY; without even the implied warranty of 1590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski GNU General Public License for more details. 1790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 1890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski You should have received a copy of the GNU General Public License 1990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski along with this program; if not, write to the Free Software 2090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 2190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 2290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski*/ 2390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski/* 2490a5038d91db44a8a224936651fc33325989ad43Stanislaw RaczynskiDriver: mpc624 2590a5038d91db44a8a224936651fc33325989ad43Stanislaw RaczynskiDescription: Micro/sys MPC-624 PC/104 board 2690a5038d91db44a8a224936651fc33325989ad43Stanislaw RaczynskiDevices: [Micro/sys] MPC-624 (mpc624) 2790a5038d91db44a8a224936651fc33325989ad43Stanislaw RaczynskiAuthor: Stanislaw Raczynski <sraczynski@op.pl> 2890a5038d91db44a8a224936651fc33325989ad43Stanislaw RaczynskiUpdated: Thu, 15 Sep 2005 12:01:18 +0200 2990a5038d91db44a8a224936651fc33325989ad43Stanislaw RaczynskiStatus: working 3090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 3190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski The Micro/sys MPC-624 board is based on the LTC2440 24-bit sigma-delta 3290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski ADC chip. 3390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 3490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski Subdevices supported by the driver: 3590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski - Analog In: supported 3690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski - Digital I/O: not supported 3790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski - LEDs: not supported 3890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski - EEPROM: not supported 3990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 4090a5038d91db44a8a224936651fc33325989ad43Stanislaw RaczynskiConfiguration Options: 4190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski [0] - I/O base address 4225985edcedea6396277003854657b5f3cb31a628Lucas De Marchi [1] - conversion rate 4325985edcedea6396277003854657b5f3cb31a628Lucas De Marchi Conversion rate RMS noise Effective Number Of Bits 44b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher 0 3.52kHz 23uV 17 45b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher 1 1.76kHz 3.5uV 20 46b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher 2 880Hz 2uV 21.3 47b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher 3 440Hz 1.4uV 21.8 48b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher 4 220Hz 1uV 22.4 49b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher 5 110Hz 750uV 22.9 50b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher 6 55Hz 510nV 23.4 51b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher 7 27.5Hz 375nV 24 52b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher 8 13.75Hz 250nV 24.4 53b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher 9 6.875Hz 200nV 24.6 54b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher [2] - voltage range 55b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher 0 -1.01V .. +1.01V 56b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher 1 -10.1V .. +10.1V 5790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski*/ 5890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 5990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#include "../comedidev.h" 6090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 6190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#include <linux/ioport.h> 6290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#include <linux/delay.h> 6390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 6479a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton/* Consecutive I/O port addresses */ 6590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#define MPC624_SIZE 16 6690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 6779a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton/* Offsets of different ports */ 68b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher#define MPC624_MASTER_CONTROL 0 /* not used */ 69b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher#define MPC624_GNMUXCH 1 /* Gain, Mux, Channel of ADC */ 70b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher#define MPC624_ADC 2 /* read/write to/from ADC */ 71b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher#define MPC624_EE 3 /* read/write to/from serial EEPROM via I2C */ 72b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher#define MPC624_LEDS 4 /* write to LEDs */ 73b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher#define MPC624_DIO 5 /* read/write to/from digital I/O ports */ 74b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher#define MPC624_IRQ_MASK 6 /* IRQ masking enable/disable */ 7590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 7679a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton/* Register bits' names */ 7790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#define MPC624_ADBUSY (1<<5) 7890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#define MPC624_ADSDO (1<<4) 7990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#define MPC624_ADFO (1<<3) 8090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#define MPC624_ADCS (1<<2) 8190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#define MPC624_ADSCK (1<<1) 8290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#define MPC624_ADSDI (1<<0) 8390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 8479a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton/* SDI Speed/Resolution Programming bits */ 8590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#define MPC624_OSR4 (1<<31) 8690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#define MPC624_OSR3 (1<<30) 8790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#define MPC624_OSR2 (1<<29) 8890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#define MPC624_OSR1 (1<<28) 8990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#define MPC624_OSR0 (1<<27) 9090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 9179a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton/* 32-bit output value bits' names */ 9290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#define MPC624_EOC_BIT (1<<31) 9390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#define MPC624_DMY_BIT (1<<30) 9490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#define MPC624_SGN_BIT (1<<29) 9590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 9625985edcedea6396277003854657b5f3cb31a628Lucas De Marchi/* Conversion speeds */ 9725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi/* OSR4 OSR3 OSR2 OSR1 OSR0 Conversion rate RMS noise ENOB^ 9890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski * X 0 0 0 1 3.52kHz 23uV 17 9990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski * X 0 0 1 0 1.76kHz 3.5uV 20 10090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski * X 0 0 1 1 880Hz 2uV 21.3 10190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski * X 0 1 0 0 440Hz 1.4uV 21.8 10290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski * X 0 1 0 1 220Hz 1uV 22.4 10390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski * X 0 1 1 0 110Hz 750uV 22.9 10490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski * X 0 1 1 1 55Hz 510nV 23.4 10590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski * X 1 0 0 0 27.5Hz 375nV 24 10690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski * X 1 0 0 1 13.75Hz 250nV 24.4 10790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski * X 1 1 1 1 6.875Hz 200nV 24.6 10890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski * 10990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski * ^ - Effective Number Of Bits 11090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski */ 11190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 112b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher#define MPC624_SPEED_3_52_kHz (MPC624_OSR4 | MPC624_OSR0) 113b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher#define MPC624_SPEED_1_76_kHz (MPC624_OSR4 | MPC624_OSR1) 114b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher#define MPC624_SPEED_880_Hz (MPC624_OSR4 | MPC624_OSR1 | MPC624_OSR0) 115b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher#define MPC624_SPEED_440_Hz (MPC624_OSR4 | MPC624_OSR2) 116b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher#define MPC624_SPEED_220_Hz (MPC624_OSR4 | MPC624_OSR2 | MPC624_OSR0) 117b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher#define MPC624_SPEED_110_Hz (MPC624_OSR4 | MPC624_OSR2 | MPC624_OSR1) 118b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher#define MPC624_SPEED_55_Hz \ 119b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher (MPC624_OSR4 | MPC624_OSR2 | MPC624_OSR1 | MPC624_OSR0) 120b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher#define MPC624_SPEED_27_5_Hz (MPC624_OSR4 | MPC624_OSR3) 121b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher#define MPC624_SPEED_13_75_Hz (MPC624_OSR4 | MPC624_OSR3 | MPC624_OSR0) 122b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher#define MPC624_SPEED_6_875_Hz \ 123b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher (MPC624_OSR4 | MPC624_OSR3 | MPC624_OSR2 | MPC624_OSR1 | MPC624_OSR0) 124b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher/* -------------------------------------------------------------------------- */ 12516450130a9f7006c91c9f49d725b9029fe711240Bill Pembertonstruct skel_private { 12616450130a9f7006c91c9f49d725b9029fe711240Bill Pemberton 127b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher /* set by mpc624_attach() from driver's parameters */ 128b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher unsigned long int ulConvertionRate; 12916450130a9f7006c91c9f49d725b9029fe711240Bill Pemberton}; 13016450130a9f7006c91c9f49d725b9029fe711240Bill Pemberton 13116450130a9f7006c91c9f49d725b9029fe711240Bill Pemberton#define devpriv ((struct skel_private *)dev->private) 132b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher/* -------------------------------------------------------------------------- */ 1339ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_mpc624_bipolar1 = { 13490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 1, 13590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski { 13679a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton/* BIP_RANGE(1.01) this is correct, */ 1370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* but my MPC-624 actually seems to have a range of 2.02 */ 1380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(2.02) 1390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } 14090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski}; 1410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1429ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_mpc624_bipolar10 = { 14390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 1, 14490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski { 14579a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton/* BIP_RANGE(10.1) this is correct, */ 1460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral /* but my MPC-624 actually seems to have a range of 20.2 */ 1470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral BIP_RANGE(20.2) 1480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } 14990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski}; 15090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 151b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher/* -------------------------------------------------------------------------- */ 1520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int mpc624_attach(struct comedi_device *dev, 1530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_devconfig *it); 154da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int mpc624_detach(struct comedi_device *dev); 155b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher/* -------------------------------------------------------------------------- */ 156139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_mpc624 = { 15768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .driver_name = "mpc624", 15868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .module = THIS_MODULE, 15968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .attach = mpc624_attach, 16068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .detach = mpc624_detach 16190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski}; 16290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 163b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher/* -------------------------------------------------------------------------- */ 1640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int mpc624_ai_rinsn(struct comedi_device *dev, 1650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, struct comedi_insn *insn, 1660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int *data); 167b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher/* -------------------------------------------------------------------------- */ 168da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it) 16990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski{ 17034c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 17190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski unsigned long iobase; 17290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 17390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski iobase = it->options[0]; 174b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "comedi%d: mpc624 [0x%04lx, ", dev->minor, iobase); 17590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski if (request_region(iobase, MPC624_SIZE, "mpc624") == NULL) { 176b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_ERR "I/O port(s) in use\n"); 17790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski return -EIO; 17890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski } 17990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 18090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski dev->iobase = iobase; 18190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski dev->board_name = "mpc624"; 18290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 18379a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton /* Private structure initialization */ 18416450130a9f7006c91c9f49d725b9029fe711240Bill Pemberton if (alloc_private(dev, sizeof(struct skel_private)) < 0) 18590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski return -ENOMEM; 18690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 18790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski switch (it->options[1]) { 18890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski case 0: 18990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski devpriv->ulConvertionRate = MPC624_SPEED_3_52_kHz; 190b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "3.52 kHz, "); 19190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski break; 19290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski case 1: 19390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski devpriv->ulConvertionRate = MPC624_SPEED_1_76_kHz; 194b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "1.76 kHz, "); 19590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski break; 19690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski case 2: 19790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski devpriv->ulConvertionRate = MPC624_SPEED_880_Hz; 198b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "880 Hz, "); 19990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski break; 20090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski case 3: 20190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski devpriv->ulConvertionRate = MPC624_SPEED_440_Hz; 202b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "440 Hz, "); 20390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski break; 20490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski case 4: 20590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski devpriv->ulConvertionRate = MPC624_SPEED_220_Hz; 206b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "220 Hz, "); 20790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski break; 20890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski case 5: 20990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski devpriv->ulConvertionRate = MPC624_SPEED_110_Hz; 210b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "110 Hz, "); 21190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski break; 21290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski case 6: 21390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski devpriv->ulConvertionRate = MPC624_SPEED_55_Hz; 214b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "55 Hz, "); 21590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski break; 21690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski case 7: 21790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski devpriv->ulConvertionRate = MPC624_SPEED_27_5_Hz; 218b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "27.5 Hz, "); 21990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski break; 22090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski case 8: 22190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski devpriv->ulConvertionRate = MPC624_SPEED_13_75_Hz; 222b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "13.75 Hz, "); 22390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski break; 22490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski case 9: 22590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski devpriv->ulConvertionRate = MPC624_SPEED_6_875_Hz; 226b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "6.875 Hz, "); 22790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski break; 22890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski default: 2295f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman printk 23025985edcedea6396277003854657b5f3cb31a628Lucas De Marchi (KERN_ERR "illegal conversion rate setting!" 231b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher " Valid numbers are 0..9. Using 9 => 6.875 Hz, "); 23290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski devpriv->ulConvertionRate = MPC624_SPEED_3_52_kHz; 23390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski } 23490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 23579a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton /* Subdevices structures */ 23690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski if (alloc_subdevices(dev, 1) < 0) 23790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski return -ENOMEM; 23890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 23990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski s = dev->subdevices + 0; 24090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski s->type = COMEDI_SUBD_AI; 24190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski s->subdev_flags = SDF_READABLE | SDF_DIFF; 24290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski s->n_chan = 8; 24390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski switch (it->options[1]) { 24490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski default: 24590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski s->maxdata = 0x3FFFFFFF; 246b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "30 bit, "); 24790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski } 24890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 24990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski switch (it->options[1]) { 25090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski case 0: 25190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski s->range_table = &range_mpc624_bipolar1; 252b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "1.01V]: "); 25390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski break; 25490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski default: 25590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski s->range_table = &range_mpc624_bipolar10; 256b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "10.1V]: "); 25790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski } 25890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski s->len_chanlist = 1; 25990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski s->insn_read = mpc624_ai_rinsn; 26090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 261b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "attached\n"); 26290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 26390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski return 1; 26490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski} 26590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 266da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int mpc624_detach(struct comedi_device *dev) 26790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski{ 268b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "comedi%d: mpc624: remove\n", dev->minor); 26990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 27090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski if (dev->iobase) 27190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski release_region(dev->iobase, MPC624_SIZE); 27290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 27390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski return 0; 27490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski} 27590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 27679a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton/* Timeout 200ms */ 27790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski#define TIMEOUT 200 27890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 2790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int mpc624_ai_rinsn(struct comedi_device *dev, 2800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, struct comedi_insn *insn, 2810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int *data) 28290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski{ 28390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski int n, i; 28490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski unsigned long int data_in, data_out; 28590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski unsigned char ucPort; 28690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 287b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher /* 288b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * WARNING: 289b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * We always write 0 to GNSWA bit, so the channel range is +-/10.1Vdc 290b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher */ 29190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski outb(insn->chanspec, dev->iobase + MPC624_GNMUXCH); 292b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher/* printk("Channel %d:\n", insn->chanspec); */ 29390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski if (!insn->n) { 294b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "MPC624: Warning, no data to acquire\n"); 29590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski return 0; 29690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski } 29790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 29890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski for (n = 0; n < insn->n; n++) { 29925985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* Trigger the conversion */ 30090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski outb(MPC624_ADSCK, dev->iobase + MPC624_ADC); 3015f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 30290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski outb(MPC624_ADCS | MPC624_ADSCK, dev->iobase + MPC624_ADC); 3035f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 30490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski outb(0, dev->iobase + MPC624_ADC); 3055f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 30690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 30725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* Wait for the conversion to end */ 30890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski for (i = 0; i < TIMEOUT; i++) { 30990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski ucPort = inb(dev->iobase + MPC624_ADC); 31090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski if (ucPort & MPC624_ADBUSY) 3115f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1000); 31290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski else 31390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski break; 31490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski } 31590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski if (i == TIMEOUT) { 316b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_ERR "MPC624: timeout (%dms)\n", TIMEOUT); 31790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski data[n] = 0; 31890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski return -ETIMEDOUT; 31990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski } 32079a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton /* Start reading data */ 32190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski data_in = 0; 32290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski data_out = devpriv->ulConvertionRate; 3235f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 32490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski for (i = 0; i < 32; i++) { 32579a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton /* Set the clock low */ 32690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski outb(0, dev->iobase + MPC624_ADC); 3275f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 32890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 329b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher if (data_out & (1 << 31)) { /* the next bit is a 1 */ 33079a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton /* Set the ADSDI line (send to MPC624) */ 33190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski outb(MPC624_ADSDI, dev->iobase + MPC624_ADC); 3325f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 33379a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton /* Set the clock high */ 33490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski outb(MPC624_ADSCK | MPC624_ADSDI, 3350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral dev->iobase + MPC624_ADC); 3360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } else { /* the next bit is a 0 */ 3370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 33879a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton /* Set the ADSDI line (send to MPC624) */ 33990a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski outb(0, dev->iobase + MPC624_ADC); 3405f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 34179a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton /* Set the clock high */ 34290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski outb(MPC624_ADSCK, dev->iobase + MPC624_ADC); 34390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski } 34479a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton /* Read ADSDO on high clock (receive from MPC624) */ 3455f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 34690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski data_in <<= 1; 34790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski data_in |= 3480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (inb(dev->iobase + MPC624_ADC) & MPC624_ADSDO) >> 4; 3495f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 35090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 35190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski data_out <<= 1; 35290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski } 35390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 354b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher /* 355b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * Received 32-bit long value consist of: 356b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * 31: EOC - 357b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * (End Of Transmission) bit - should be 0 358b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * 30: DMY 359b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * (Dummy) bit - should be 0 360b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * 29: SIG 361b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * (Sign) bit- 1 if the voltage is positive, 362b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * 0 if negative 363b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * 28: MSB 364b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * (Most Significant Bit) - the first bit of 365b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * the conversion result 366b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * .... 367b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * 05: LSB 368b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * (Least Significant Bit)- the last bit of the 369b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * conversion result 370b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * 04-00: sub-LSB 371b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * - sub-LSBs are basically noise, but when 372b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * averaged properly, they can increase conversion 373b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * precision up to 29 bits; they can be discarded 374b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * without loss of resolution. 375b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher */ 37690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 37790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski if (data_in & MPC624_EOC_BIT) 378b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "MPC624:EOC bit is set (data_in=%lu)!", 3790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral data_in); 38090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski if (data_in & MPC624_DMY_BIT) 381b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher printk(KERN_INFO "MPC624:DMY bit is set (data_in=%lu)!", 3820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral data_in); 383b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher if (data_in & MPC624_SGN_BIT) { /* Volatge is positive */ 384b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher /* 385b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * comedi operates on unsigned numbers, so mask off EOC 386b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * and DMY and don't clear the SGN bit 387b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher */ 388b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher data_in &= 0x3FFFFFFF; 389b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher data[n] = data_in; 390b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher } else { /* The voltage is negative */ 391b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher /* 392b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * data_in contains a number in 30-bit two's complement 393b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher * code and we must deal with it 394b8c623e5dde98a00ada4af47bec92a708794c573Iain Churcher */ 39590a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski data_in |= MPC624_SGN_BIT; 39690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski data_in = ~data_in; 39790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski data_in += 1; 39890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski data_in &= ~(MPC624_EOC_BIT | MPC624_DMY_BIT); 39979a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton /* clear EOC and DMY bits */ 40090a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski data_in = 0x20000000 - data_in; 40190a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski data[n] = data_in; 40290a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski } 40390a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski } 40490a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 40579a31bae80df12e3cd19a831e7eacfbc4dc555a0Bill Pemberton /* Return the number of samples read/written */ 40690a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski return n; 40790a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski} 40890a5038d91db44a8a224936651fc33325989ad43Stanislaw Raczynski 4097114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic int __init driver_mpc624_init_module(void) 4107114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 4117114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas return comedi_driver_register(&driver_mpc624); 4127114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 4137114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 4147114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic void __exit driver_mpc624_cleanup_module(void) 4157114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 4167114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas comedi_driver_unregister(&driver_mpc624); 4177114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 4187114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 4197114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_init(driver_mpc624_init_module); 4207114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_exit(driver_mpc624_cleanup_module); 42190f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas 42290f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org"); 42390f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver"); 42490f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL"); 425