196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit/* 296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit comedi/drivers/icp_multi.c 396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit COMEDI - Linux Control and Measurement Device Interface 596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit Copyright (C) 1997-2002 David A. Schleef <ds@schleef.org> 696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit This program is free software; you can redistribute it and/or modify 896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit it under the terms of the GNU General Public License as published by 996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit the Free Software Foundation; either version 2 of the License, or 1096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit (at your option) any later version. 1196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 1296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit This program is distributed in the hope that it will be useful, 1396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit but WITHOUT ANY WARRANTY; without even the implied warranty of 1496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit GNU General Public License for more details. 1696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit*/ 1796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 1896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit/* 1996341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitDriver: icp_multi 2096341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitDescription: Inova ICP_MULTI 2196341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitAuthor: Anne Smorthit <anne.smorthit@sfwte.ch> 2296341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitDevices: [Inova] ICP_MULTI (icp_multi) 2396341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitStatus: works 2496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 2596341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitThe driver works for analog input and output and digital input and output. 2696341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitIt does not work with interrupts or with the counters. Currently no support 2796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthitfor DMA. 2896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 2996341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitIt has 16 single-ended or 8 differential Analogue Input channels with 12-bit 3096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthitresolution. Ranges : 5V, 10V, +/-5V, +/-10V, 0..20mA and 4..20mA. Input 3196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthitranges can be individually programmed for each channel. Voltage or current 3296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthitmeasurement is selected by jumper. 3396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 3496341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitThere are 4 x 12-bit Analogue Outputs. Ranges : 5V, 10V, +/-5V, +/-10V 3596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 3696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit16 x Digital Inputs, 24V 3796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 3896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit8 x Digital Outputs, 24V, 1A 3996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 4096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit4 x 16-bit counters 4196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 42194b9e3cf49319231e8b47125dc5d043350f4406H Hartley SweetenConfiguration options: not applicable, uses PCI auto config 4396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit*/ 4496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 45ce157f8032bbd46d9427034c335b0afd751da25dH Hartley Sweeten#include <linux/module.h> 4633782dd5edf8db3cdb7c81a3523bf743dd0209b7H Hartley Sweeten#include <linux/pci.h> 4733782dd5edf8db3cdb7c81a3523bf743dd0209b7H Hartley Sweeten#include <linux/delay.h> 4825436dc9d84f1be60ff549c9ab712bba2835f284Greg Kroah-Hartman#include <linux/interrupt.h> 4996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 5033782dd5edf8db3cdb7c81a3523bf743dd0209b7H Hartley Sweeten#include "../comedidev.h" 5196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 5296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_ADC_CSR 0 /* R/W: ADC command/status register */ 5396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_AI 2 /* R: Analogue input data */ 5496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_DAC_CSR 4 /* R/W: DAC command/status register */ 5596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_AO 6 /* R/W: Analogue output data */ 5696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_DI 8 /* R/W: Digital inouts */ 5796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_DO 0x0A /* R/W: Digital outputs */ 5896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_INT_EN 0x0C /* R/W: Interrupt enable register */ 5996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_INT_STAT 0x0E /* R/W: Interrupt status register */ 6096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_CNTR0 0x10 /* R/W: Counter 0 */ 6196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_CNTR1 0x12 /* R/W: counter 1 */ 6296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_CNTR2 0x14 /* R/W: Counter 2 */ 6396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_CNTR3 0x16 /* R/W: Counter 3 */ 6496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 65b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton/* Define bits from ADC command/status register */ 6696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ADC_ST 0x0001 /* Start ADC */ 6796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ADC_BSY 0x0001 /* ADC busy */ 6896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ADC_BI 0x0010 /* Bipolar input range 1 = bipolar */ 6996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ADC_RA 0x0020 /* Input range 0 = 5V, 1 = 10V */ 7096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ADC_DI 0x0040 /* Differential input mode 1 = differential */ 7196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 72b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton/* Define bits from DAC command/status register */ 7396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define DAC_ST 0x0001 /* Start DAC */ 7496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define DAC_BSY 0x0001 /* DAC busy */ 7596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define DAC_BI 0x0010 /* Bipolar input range 1 = bipolar */ 7696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define DAC_RA 0x0020 /* Input range 0 = 5V, 1 = 10V */ 7796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 78b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton/* Define bits from interrupt enable/status registers */ 7996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ADC_READY 0x0001 /* A/d conversion ready interrupt */ 8096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define DAC_READY 0x0002 /* D/a conversion ready interrupt */ 8196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define DOUT_ERROR 0x0004 /* Digital output error interrupt */ 8296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define DIN_STATUS 0x0008 /* Digital input status change interrupt */ 8396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define CIE0 0x0010 /* Counter 0 overrun interrupt */ 8496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define CIE1 0x0020 /* Counter 1 overrun interrupt */ 8596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define CIE2 0x0040 /* Counter 2 overrun interrupt */ 8696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define CIE3 0x0080 /* Counter 3 overrun interrupt */ 8796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 88b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton/* Useful definitions */ 89b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton#define Status_IRQ 0x00ff /* All interrupts */ 9096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 91b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton/* Define analogue range */ 923e54cdb1fd094d4483b03128a4dce53cfb6c9855H Hartley Sweetenstatic const struct comedi_lrange range_analog = { 933e54cdb1fd094d4483b03128a4dce53cfb6c9855H Hartley Sweeten 4, { 943e54cdb1fd094d4483b03128a4dce53cfb6c9855H Hartley Sweeten UNI_RANGE(5), 953e54cdb1fd094d4483b03128a4dce53cfb6c9855H Hartley Sweeten UNI_RANGE(10), 963e54cdb1fd094d4483b03128a4dce53cfb6c9855H Hartley Sweeten BIP_RANGE(5), 973e54cdb1fd094d4483b03128a4dce53cfb6c9855H Hartley Sweeten BIP_RANGE(10) 983e54cdb1fd094d4483b03128a4dce53cfb6c9855H Hartley Sweeten } 9996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit}; 10096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 10196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthitstatic const char range_codes_analog[] = { 0x00, 0x20, 0x10, 0x30 }; 10296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 10396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit/* 10496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit============================================================================== 10596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit Data & Structure declarations 10696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit============================================================================== 10796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit*/ 10896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 10952bfe6c8e8746591e276de2594b8c98a51222d49Bill Pembertonstruct icp_multi_private { 110b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton unsigned int AdcCmdStatus; /* ADC Command/Status register */ 111b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton unsigned int DacCmdStatus; /* DAC Command/Status register */ 112b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton unsigned int IntEnable; /* Interrupt Enable register */ 113b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton unsigned int IntStatus; /* Interrupt Status register */ 11420ce161d2f53af092fe8dabfef6fb0d7af846c43Masanari Iida unsigned int act_chanlist[32]; /* list of scanned channel */ 115b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton unsigned char act_chanlist_len; /* len of scanlist */ 116b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton unsigned char act_chanlist_pos; /* actual position in MUX list */ 117b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton unsigned int *ai_chanlist; /* actaul chanlist */ 118b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton unsigned int do_data; /* Remember digital output data */ 11952bfe6c8e8746591e276de2594b8c98a51222d49Bill Pemberton}; 12096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 1210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void setup_channel_list(struct comedi_device *dev, 1220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 123d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten unsigned int *chanlist, unsigned int n_chan) 124d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten{ 12565e9e2dc2cca5590affcc299454a783578c9457bH Hartley Sweeten struct icp_multi_private *devpriv = dev->private; 126d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten unsigned int i, range, chanprog; 127d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten unsigned int diff; 12896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 129d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten devpriv->act_chanlist_len = n_chan; 130d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten devpriv->act_chanlist_pos = 0; 131d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten 132d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten for (i = 0; i < n_chan; i++) { 133d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten /* Get channel */ 134d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten chanprog = CR_CHAN(chanlist[i]); 135d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten 136d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten /* Determine if it is a differential channel (Bit 15 = 1) */ 137d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten if (CR_AREF(chanlist[i]) == AREF_DIFF) { 138d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten diff = 1; 139d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten chanprog &= 0x0007; 140d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten } else { 141d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten diff = 0; 142d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten chanprog &= 0x000f; 143d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten } 144d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten 145d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten /* Clear channel, range and input mode bits 146d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten * in A/D command/status register */ 147d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten devpriv->AdcCmdStatus &= 0xf00f; 148d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten 149d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten /* Set channel number and differential mode status bit */ 150d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten if (diff) { 151d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten /* Set channel number, bits 9-11 & mode, bit 6 */ 152d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten devpriv->AdcCmdStatus |= (chanprog << 9); 153d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten devpriv->AdcCmdStatus |= ADC_DI; 154d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten } else 155d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten /* Set channel number, bits 8-11 */ 156d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten devpriv->AdcCmdStatus |= (chanprog << 8); 157d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten 158d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten /* Get range for current channel */ 159d68a8635c5b706e3c037d89fd130e62ddce5c823H Hartley Sweeten range = range_codes_analog[CR_RANGE(chanlist[i])]; 160d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten /* Set range. bits 4-5 */ 161d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten devpriv->AdcCmdStatus |= range; 162d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten 163d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten /* Output channel, range, mode to ICP Multi */ 164a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten writew(devpriv->AdcCmdStatus, dev->mmio + ICP_MULTI_ADC_CSR); 165d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten } 166d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten} 16796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 168e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweetenstatic int icp_multi_ai_eoc(struct comedi_device *dev, 169e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten struct comedi_subdevice *s, 170e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten struct comedi_insn *insn, 171e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten unsigned long context) 172e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten{ 173e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten unsigned int status; 174e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten 175a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten status = readw(dev->mmio + ICP_MULTI_ADC_CSR); 176e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten if ((status & ADC_BSY) == 0) 177e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten return 0; 178e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten return -EBUSY; 179e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten} 180e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten 1810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int icp_multi_insn_read_ai(struct comedi_device *dev, 1820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 183a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten struct comedi_insn *insn, 184a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten unsigned int *data) 18596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{ 18665e9e2dc2cca5590affcc299454a783578c9457bH Hartley Sweeten struct icp_multi_private *devpriv = dev->private; 187e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten int ret = 0; 188e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten int n; 18996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 190b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Disable A/D conversion ready interrupt */ 19196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit devpriv->IntEnable &= ~ADC_READY; 192a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten writew(devpriv->IntEnable, dev->mmio + ICP_MULTI_INT_EN); 19396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 194b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Clear interrupt status */ 19596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit devpriv->IntStatus |= ADC_READY; 196a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten writew(devpriv->IntStatus, dev->mmio + ICP_MULTI_INT_STAT); 19796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 198a622afcb7e4c7d24bb29b07e82fd8b7fcd81c0c0Dirk Hohndel /* Set up appropriate channel, mode and range data, for specified ch */ 19996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit setup_channel_list(dev, s, &insn->chanspec, 1); 20096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 20196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit for (n = 0; n < insn->n; n++) { 202b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Set start ADC bit */ 20396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit devpriv->AdcCmdStatus |= ADC_ST; 204a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten writew(devpriv->AdcCmdStatus, dev->mmio + ICP_MULTI_ADC_CSR); 20596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit devpriv->AdcCmdStatus &= ~ADC_ST; 20696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 2075f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(1); 20896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 209b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Wait for conversion to complete, or get fed up waiting */ 210e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten ret = comedi_timeout(dev, s, insn, icp_multi_ai_eoc, 0); 211dbd446fc7aab519c213e63eefa15c82586a50989H Hartley Sweeten if (ret) 212e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten break; 21396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 214a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten data[n] = (readw(dev->mmio + ICP_MULTI_AI) >> 4) & 0x0fff; 21596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit } 21696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 217b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Disable interrupt */ 21896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit devpriv->IntEnable &= ~ADC_READY; 219a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten writew(devpriv->IntEnable, dev->mmio + ICP_MULTI_INT_EN); 22096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 221b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Clear interrupt status */ 22296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit devpriv->IntStatus |= ADC_READY; 223a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten writew(devpriv->IntStatus, dev->mmio + ICP_MULTI_INT_STAT); 22496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 225e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten return ret ? ret : n; 226e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten} 227e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten 228e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweetenstatic int icp_multi_ao_eoc(struct comedi_device *dev, 229e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten struct comedi_subdevice *s, 230e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten struct comedi_insn *insn, 231e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten unsigned long context) 232e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten{ 233e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten unsigned int status; 234e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten 235a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten status = readw(dev->mmio + ICP_MULTI_DAC_CSR); 236e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten if ((status & DAC_BSY) == 0) 237e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten return 0; 238e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten return -EBUSY; 23996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit} 24096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 241bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweetenstatic int icp_multi_ao_insn_write(struct comedi_device *dev, 2420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 243a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten struct comedi_insn *insn, 244a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten unsigned int *data) 24596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{ 24665e9e2dc2cca5590affcc299454a783578c9457bH Hartley Sweeten struct icp_multi_private *devpriv = dev->private; 247bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten unsigned int chan = CR_CHAN(insn->chanspec); 248bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten unsigned int range = CR_RANGE(insn->chanspec); 249bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten int i; 25096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 251b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Disable D/A conversion ready interrupt */ 25296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit devpriv->IntEnable &= ~DAC_READY; 253a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten writew(devpriv->IntEnable, dev->mmio + ICP_MULTI_INT_EN); 25496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 255b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Clear interrupt status */ 25696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit devpriv->IntStatus |= DAC_READY; 257a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten writew(devpriv->IntStatus, dev->mmio + ICP_MULTI_INT_STAT); 25896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 259b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Set up range and channel data */ 260b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Bit 4 = 1 : Bipolar */ 261b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Bit 5 = 0 : 5V */ 262b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Bit 5 = 1 : 10V */ 263b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Bits 8-9 : Channel number */ 26496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit devpriv->DacCmdStatus &= 0xfccf; 265d68a8635c5b706e3c037d89fd130e62ddce5c823H Hartley Sweeten devpriv->DacCmdStatus |= range_codes_analog[range]; 26696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit devpriv->DacCmdStatus |= (chan << 8); 26796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 268a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten writew(devpriv->DacCmdStatus, dev->mmio + ICP_MULTI_DAC_CSR); 26996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 270bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten for (i = 0; i < insn->n; i++) { 271bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten unsigned int val = data[i]; 272bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten int ret; 273bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten 274a622afcb7e4c7d24bb29b07e82fd8b7fcd81c0c0Dirk Hohndel /* Wait for analogue output data register to be 275a622afcb7e4c7d24bb29b07e82fd8b7fcd81c0c0Dirk Hohndel * ready for new data, or get fed up waiting */ 276e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten ret = comedi_timeout(dev, s, insn, icp_multi_ao_eoc, 0); 277e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten if (ret) { 278e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten /* Disable interrupt */ 279e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten devpriv->IntEnable &= ~DAC_READY; 280e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten writew(devpriv->IntEnable, 281a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten dev->mmio + ICP_MULTI_INT_EN); 28296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 283e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten /* Clear interrupt status */ 284e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten devpriv->IntStatus |= DAC_READY; 285e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten writew(devpriv->IntStatus, 286a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten dev->mmio + ICP_MULTI_INT_STAT); 28796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 288e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten return ret; 289e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten } 29096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 291bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten writew(val, dev->mmio + ICP_MULTI_AO); 29296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 293b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Set DAC_ST bit to write the data to selected channel */ 29496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit devpriv->DacCmdStatus |= DAC_ST; 295a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten writew(devpriv->DacCmdStatus, dev->mmio + ICP_MULTI_DAC_CSR); 29696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit devpriv->DacCmdStatus &= ~DAC_ST; 29796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 298bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten s->readback[chan] = val; 29996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit } 30096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 301bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten return insn->n; 30296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit} 30396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 3040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int icp_multi_insn_bits_di(struct comedi_device *dev, 3050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 306a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten struct comedi_insn *insn, 307a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten unsigned int *data) 30896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{ 309a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten data[1] = readw(dev->mmio + ICP_MULTI_DI); 31096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 311a2714e3e42e746d6c8525c35fdcc58fb60c2830dH Hartley Sweeten return insn->n; 31296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit} 31396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 3140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int icp_multi_insn_bits_do(struct comedi_device *dev, 3150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 31697f4289ad08cffe55de06d4ac4f89ac540450aeeH Hartley Sweeten struct comedi_insn *insn, 31797f4289ad08cffe55de06d4ac4f89ac540450aeeH Hartley Sweeten unsigned int *data) 31896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{ 31997f4289ad08cffe55de06d4ac4f89ac540450aeeH Hartley Sweeten if (comedi_dio_update_state(s, data)) 320a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten writew(s->state, dev->mmio + ICP_MULTI_DO); 32196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 322a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten data[1] = readw(dev->mmio + ICP_MULTI_DI); 32396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 324a2714e3e42e746d6c8525c35fdcc58fb60c2830dH Hartley Sweeten return insn->n; 32596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit} 32696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 3270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int icp_multi_insn_read_ctr(struct comedi_device *dev, 3280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 3290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 33096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{ 33196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit return 0; 33296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit} 33396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 3340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int icp_multi_insn_write_ctr(struct comedi_device *dev, 3350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 3360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, 3370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int *data) 33896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{ 33996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit return 0; 34096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit} 34196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 34270265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t interrupt_service_icp_multi(int irq, void *d) 34396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{ 34471b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton struct comedi_device *dev = d; 34596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit int int_no; 34696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 347b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Is this interrupt from our board? */ 348a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten int_no = readw(dev->mmio + ICP_MULTI_INT_STAT) & Status_IRQ; 34996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit if (!int_no) 350b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* No, exit */ 35196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit return IRQ_NONE; 35296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 353b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Determine which interrupt is active & handle it */ 35496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit switch (int_no) { 35596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit case ADC_READY: 35696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit break; 35796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit case DAC_READY: 35896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit break; 35996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit case DOUT_ERROR: 36096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit break; 36196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit case DIN_STATUS: 36296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit break; 36396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit case CIE0: 36496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit break; 36596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit case CIE1: 36696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit break; 36796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit case CIE2: 36896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit break; 36996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit case CIE3: 37096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit break; 37196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit default: 37296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit break; 37396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 37496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit } 37596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 37696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit return IRQ_HANDLED; 37796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit} 37896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 37996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#if 0 3800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int check_channel_list(struct comedi_device *dev, 3810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 3820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned int *chanlist, unsigned int n_chan) 38396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{ 38496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit unsigned int i; 38596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 386b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Check that we at least have one channel to check */ 38796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit if (n_chan < 1) { 3883df73e07d552051dfaf98c07f9bb818bbff08268H Hartley Sweeten dev_err(dev->class_dev, "range/channel list is empty!\n"); 38996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit return 0; 39096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit } 391b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Check all channels */ 39296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit for (i = 0; i < n_chan; i++) { 393b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Check that channel number is < maximum */ 39496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit if (CR_AREF(chanlist[i]) == AREF_DIFF) { 39508567ce9b6b6235897d0895630b88d4cb84f9784H Hartley Sweeten if (CR_CHAN(chanlist[i]) > (s->nchan / 2)) { 3963df73e07d552051dfaf98c07f9bb818bbff08268H Hartley Sweeten dev_err(dev->class_dev, 3973df73e07d552051dfaf98c07f9bb818bbff08268H Hartley Sweeten "Incorrect differential ai ch-nr\n"); 39896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit return 0; 39996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit } 40096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit } else { 401281ecb066de68938ce551a7a22d139bc103251a4H Hartley Sweeten if (CR_CHAN(chanlist[i]) > s->n_chan) { 4023df73e07d552051dfaf98c07f9bb818bbff08268H Hartley Sweeten dev_err(dev->class_dev, 4033df73e07d552051dfaf98c07f9bb818bbff08268H Hartley Sweeten "Incorrect ai channel number\n"); 40496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit return 0; 40596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit } 40696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit } 40796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit } 40896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit return 1; 40996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit} 41096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#endif 41196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 41271b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int icp_multi_reset(struct comedi_device *dev) 41396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{ 41465e9e2dc2cca5590affcc299454a783578c9457bH Hartley Sweeten struct icp_multi_private *devpriv = dev->private; 41596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit unsigned int i; 41696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 417b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton /* Clear INT enables and requests */ 418a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten writew(0, dev->mmio + ICP_MULTI_INT_EN); 419a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten writew(0x00ff, dev->mmio + ICP_MULTI_INT_STAT); 42096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 421fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten /* Set DACs to 0..5V range and 0V output */ 422fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten for (i = 0; i < 4; i++) { 423fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten devpriv->DacCmdStatus &= 0xfcce; 42496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 425fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten /* Set channel number */ 426fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten devpriv->DacCmdStatus |= (i << 8); 42796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 428fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten /* Output 0V */ 429a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten writew(0, dev->mmio + ICP_MULTI_AO); 43096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 431fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten /* Set start conversion bit */ 432fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten devpriv->DacCmdStatus |= DAC_ST; 43396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 434fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten /* Output to command / status register */ 435a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten writew(devpriv->DacCmdStatus, dev->mmio + ICP_MULTI_DAC_CSR); 43696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 437fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten /* Delay to allow DAC time to recover */ 438fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten udelay(1); 439fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten } 440fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten 441fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten /* Digital outputs to 0 */ 442a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten writew(0, dev->mmio + ICP_MULTI_DO); 44396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 44496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit return 0; 44596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit} 44696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 447a690b7e535f2f97a3a05ee570715abeb60a8910fBill Pembertonstatic int icp_multi_auto_attach(struct comedi_device *dev, 448750af5e568d060ec6994cdcb4e86cdddfcd473c0Ian Abbott unsigned long context_unused) 44996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{ 450750af5e568d060ec6994cdcb4e86cdddfcd473c0Ian Abbott struct pci_dev *pcidev = comedi_to_pci_dev(dev); 45165e9e2dc2cca5590affcc299454a783578c9457bH Hartley Sweeten struct icp_multi_private *devpriv; 45234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 45312b4a097b6fd6d7c7e18dbb40d2ed62cdc26cd3bH Hartley Sweeten int ret; 454194b9e3cf49319231e8b47125dc5d043350f4406H Hartley Sweeten 4550bdab509bf9c6d838dc0a3b1d68bbf841fc20b5aH Hartley Sweeten devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); 456c34fa261b0ac3a862ccd3f71ee55a16b920dfc83H Hartley Sweeten if (!devpriv) 457c34fa261b0ac3a862ccd3f71ee55a16b920dfc83H Hartley Sweeten return -ENOMEM; 45896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 459818f569fe930c5b8a05d1a44ece3c63c99c13c88H Hartley Sweeten ret = comedi_pci_enable(dev); 460194b9e3cf49319231e8b47125dc5d043350f4406H Hartley Sweeten if (ret) 461194b9e3cf49319231e8b47125dc5d043350f4406H Hartley Sweeten return ret; 46296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 463a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten dev->mmio = pci_ioremap_bar(pcidev, 2); 464a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten if (!dev->mmio) 46596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit return -ENOMEM; 46696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 46712b4a097b6fd6d7c7e18dbb40d2ed62cdc26cd3bH Hartley Sweeten ret = comedi_alloc_subdevices(dev, 5); 4688b6c56949ffa83dbc2a6e8fa3f98b10a19372207H Hartley Sweeten if (ret) 46996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit return ret; 47096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 47196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit icp_multi_reset(dev); 47296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 473194b9e3cf49319231e8b47125dc5d043350f4406H Hartley Sweeten if (pcidev->irq) { 474194b9e3cf49319231e8b47125dc5d043350f4406H Hartley Sweeten ret = request_irq(pcidev->irq, interrupt_service_icp_multi, 475194b9e3cf49319231e8b47125dc5d043350f4406H Hartley Sweeten IRQF_SHARED, dev->board_name, dev); 476194b9e3cf49319231e8b47125dc5d043350f4406H Hartley Sweeten if (ret == 0) 477194b9e3cf49319231e8b47125dc5d043350f4406H Hartley Sweeten dev->irq = pcidev->irq; 478798cdd05e00f2ffb2aa763f5bc2605cd9c08a265H Hartley Sweeten } 47996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 48012b4a097b6fd6d7c7e18dbb40d2ed62cdc26cd3bH Hartley Sweeten s = &dev->subdevices[0]; 481281ecb066de68938ce551a7a22d139bc103251a4H Hartley Sweeten dev->read_subdev = s; 482281ecb066de68938ce551a7a22d139bc103251a4H Hartley Sweeten s->type = COMEDI_SUBD_AI; 48308567ce9b6b6235897d0895630b88d4cb84f9784H Hartley Sweeten s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; 484281ecb066de68938ce551a7a22d139bc103251a4H Hartley Sweeten s->n_chan = 16; 485efac035ca6eaaf6ca353e730055022cdf03ae7bbH Hartley Sweeten s->maxdata = 0x0fff; 486281ecb066de68938ce551a7a22d139bc103251a4H Hartley Sweeten s->len_chanlist = 16; 487abdeac3fd65534dd9b8f46a0fa3ce5c9d545a8f7H Hartley Sweeten s->range_table = &range_analog; 488281ecb066de68938ce551a7a22d139bc103251a4H Hartley Sweeten s->insn_read = icp_multi_insn_read_ai; 48996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 49012b4a097b6fd6d7c7e18dbb40d2ed62cdc26cd3bH Hartley Sweeten s = &dev->subdevices[1]; 491fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten s->type = COMEDI_SUBD_AO; 492fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; 493fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten s->n_chan = 4; 49468b82e0954c3a80b230722f5315f7d41eca3d0a2H Hartley Sweeten s->maxdata = 0x0fff; 495fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten s->len_chanlist = 4; 496fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten s->range_table = &range_analog; 497bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten s->insn_write = icp_multi_ao_insn_write; 498bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten s->insn_read = comedi_readback_insn_read; 499bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten 500bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten ret = comedi_alloc_subdev_readback(s); 501bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten if (ret) 502bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten return ret; 50396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 50412b4a097b6fd6d7c7e18dbb40d2ed62cdc26cd3bH Hartley Sweeten s = &dev->subdevices[2]; 50548f31251264c3cabcec274da184ad669c195a627H Hartley Sweeten s->type = COMEDI_SUBD_DI; 50648f31251264c3cabcec274da184ad669c195a627H Hartley Sweeten s->subdev_flags = SDF_READABLE; 50748f31251264c3cabcec274da184ad669c195a627H Hartley Sweeten s->n_chan = 16; 50848f31251264c3cabcec274da184ad669c195a627H Hartley Sweeten s->maxdata = 1; 50948f31251264c3cabcec274da184ad669c195a627H Hartley Sweeten s->len_chanlist = 16; 51048f31251264c3cabcec274da184ad669c195a627H Hartley Sweeten s->range_table = &range_digital; 51148f31251264c3cabcec274da184ad669c195a627H Hartley Sweeten s->insn_bits = icp_multi_insn_bits_di; 51296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 51312b4a097b6fd6d7c7e18dbb40d2ed62cdc26cd3bH Hartley Sweeten s = &dev->subdevices[3]; 5142aa707058ffa3c31abf8b7480c7773400cc87d01H Hartley Sweeten s->type = COMEDI_SUBD_DO; 5152aa707058ffa3c31abf8b7480c7773400cc87d01H Hartley Sweeten s->subdev_flags = SDF_WRITABLE | SDF_READABLE; 5162aa707058ffa3c31abf8b7480c7773400cc87d01H Hartley Sweeten s->n_chan = 8; 5172aa707058ffa3c31abf8b7480c7773400cc87d01H Hartley Sweeten s->maxdata = 1; 5182aa707058ffa3c31abf8b7480c7773400cc87d01H Hartley Sweeten s->len_chanlist = 8; 5192aa707058ffa3c31abf8b7480c7773400cc87d01H Hartley Sweeten s->range_table = &range_digital; 5202aa707058ffa3c31abf8b7480c7773400cc87d01H Hartley Sweeten s->insn_bits = icp_multi_insn_bits_do; 52196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 52212b4a097b6fd6d7c7e18dbb40d2ed62cdc26cd3bH Hartley Sweeten s = &dev->subdevices[4]; 5235b93da54bf0a55fd53b96cfb1ac0ce0f8905d1e0H Hartley Sweeten s->type = COMEDI_SUBD_COUNTER; 5245b93da54bf0a55fd53b96cfb1ac0ce0f8905d1e0H Hartley Sweeten s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; 5255b93da54bf0a55fd53b96cfb1ac0ce0f8905d1e0H Hartley Sweeten s->n_chan = 4; 5265b93da54bf0a55fd53b96cfb1ac0ce0f8905d1e0H Hartley Sweeten s->maxdata = 0xffff; 5275b93da54bf0a55fd53b96cfb1ac0ce0f8905d1e0H Hartley Sweeten s->len_chanlist = 4; 5285b93da54bf0a55fd53b96cfb1ac0ce0f8905d1e0H Hartley Sweeten s->state = 0; 5295b93da54bf0a55fd53b96cfb1ac0ce0f8905d1e0H Hartley Sweeten s->insn_read = icp_multi_insn_read_ctr; 5305b93da54bf0a55fd53b96cfb1ac0ce0f8905d1e0H Hartley Sweeten s->insn_write = icp_multi_insn_write_ctr; 53196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 53296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit return 0; 53396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit} 53496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit 535484ecc95d9cdfa8b2f7029e2f3409cf078aed4abH Hartley Sweetenstatic void icp_multi_detach(struct comedi_device *dev) 53696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{ 537caf6d12d036ea78e8f54c40fa99320416b040c71H Hartley Sweeten if (dev->mmio) 538caf6d12d036ea78e8f54c40fa99320416b040c71H Hartley Sweeten icp_multi_reset(dev); 539aac307f9dd5ce1fe651140a036ab4b0a0571b54aH Hartley Sweeten comedi_pci_detach(dev); 54096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit} 54190f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas 542d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweetenstatic struct comedi_driver icp_multi_driver = { 543d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten .driver_name = "icp_multi", 544d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten .module = THIS_MODULE, 545750af5e568d060ec6994cdcb4e86cdddfcd473c0Ian Abbott .auto_attach = icp_multi_auto_attach, 546d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten .detach = icp_multi_detach, 547d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten}; 548554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten 549a690b7e535f2f97a3a05ee570715abeb60a8910fBill Pembertonstatic int icp_multi_pci_probe(struct pci_dev *dev, 550b8f4ac237e382accd4b30c75043939f7ed9e79a6H Hartley Sweeten const struct pci_device_id *id) 551554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten{ 552b8f4ac237e382accd4b30c75043939f7ed9e79a6H Hartley Sweeten return comedi_pci_auto_config(dev, &icp_multi_driver, id->driver_data); 553554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten} 554554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten 55541e043fcfa2236bb2c4a8335eb09f4c8cee224b3Jingoo Hanstatic const struct pci_device_id icp_multi_pci_table[] = { 556472cd3db7b47a0720678e4c7cc1a472d2c06c218H Hartley Sweeten { PCI_DEVICE(PCI_VENDOR_ID_ICP, 0x8000) }, 557554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten { 0 } 558554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten}; 559554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley SweetenMODULE_DEVICE_TABLE(pci, icp_multi_pci_table); 560554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten 561554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweetenstatic struct pci_driver icp_multi_pci_driver = { 562554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten .name = "icp_multi", 563554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten .id_table = icp_multi_pci_table, 564554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten .probe = icp_multi_pci_probe, 5659901a4d75d007686e8f6473189cafc4b216b7449Peter Huewe .remove = comedi_pci_auto_unconfig, 566554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten}; 567554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweetenmodule_comedi_pci_driver(icp_multi_driver, icp_multi_pci_driver); 568d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten 56990f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org"); 57090f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver"); 57190f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL"); 572