Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 1 | /* |
| 2 | comedi/drivers/ni_atmio16d.c |
| 3 | Hardware driver for National Instruments AT-MIO16D board |
| 4 | Copyright (C) 2000 Chris R. Baugher <baugher@enteract.com> |
| 5 | |
| 6 | This program is free software; you can redistribute it and/or modify |
| 7 | it under the terms of the GNU General Public License as published by |
| 8 | the Free Software Foundation; either version 2 of the License, or |
| 9 | (at your option) any later version. |
| 10 | |
| 11 | This program is distributed in the hope that it will be useful, |
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | GNU General Public License for more details. |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 15 | */ |
| 16 | /* |
| 17 | Driver: ni_atmio16d |
| 18 | Description: National Instruments AT-MIO-16D |
| 19 | Author: Chris R. Baugher <baugher@enteract.com> |
| 20 | Status: unknown |
| 21 | Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d) |
| 22 | */ |
| 23 | /* |
| 24 | * I must give credit here to Michal Dobes <dobes@tesnet.cz> who |
| 25 | * wrote the driver for Advantec's pcl812 boards. I used the interrupt |
| 26 | * handling code from his driver as an example for this one. |
| 27 | * |
| 28 | * Chris Baugher |
| 29 | * 5/1/2000 |
| 30 | * |
| 31 | */ |
| 32 | |
H Hartley Sweeten | ce157f8 | 2013-06-24 17:04:43 -0700 | [diff] [blame] | 33 | #include <linux/module.h> |
Greg Kroah-Hartman | 25436dc | 2009-04-27 15:14:34 -0700 | [diff] [blame] | 34 | #include <linux/interrupt.h> |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 35 | #include "../comedidev.h" |
| 36 | |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 37 | #include "8255.h" |
| 38 | |
| 39 | /* Configuration and Status Registers */ |
| 40 | #define COM_REG_1 0x00 /* wo 16 */ |
| 41 | #define STAT_REG 0x00 /* ro 16 */ |
| 42 | #define COM_REG_2 0x02 /* wo 16 */ |
| 43 | /* Event Strobe Registers */ |
| 44 | #define START_CONVERT_REG 0x08 /* wo 16 */ |
| 45 | #define START_DAQ_REG 0x0A /* wo 16 */ |
| 46 | #define AD_CLEAR_REG 0x0C /* wo 16 */ |
| 47 | #define EXT_STROBE_REG 0x0E /* wo 16 */ |
| 48 | /* Analog Output Registers */ |
| 49 | #define DAC0_REG 0x10 /* wo 16 */ |
| 50 | #define DAC1_REG 0x12 /* wo 16 */ |
| 51 | #define INT2CLR_REG 0x14 /* wo 16 */ |
| 52 | /* Analog Input Registers */ |
| 53 | #define MUX_CNTR_REG 0x04 /* wo 16 */ |
| 54 | #define MUX_GAIN_REG 0x06 /* wo 16 */ |
| 55 | #define AD_FIFO_REG 0x16 /* ro 16 */ |
| 56 | #define DMA_TC_INT_CLR_REG 0x16 /* wo 16 */ |
| 57 | /* AM9513A Counter/Timer Registers */ |
| 58 | #define AM9513A_DATA_REG 0x18 /* rw 16 */ |
| 59 | #define AM9513A_COM_REG 0x1A /* wo 16 */ |
| 60 | #define AM9513A_STAT_REG 0x1A /* ro 16 */ |
| 61 | /* MIO-16 Digital I/O Registers */ |
| 62 | #define MIO_16_DIG_IN_REG 0x1C /* ro 16 */ |
| 63 | #define MIO_16_DIG_OUT_REG 0x1C /* wo 16 */ |
| 64 | /* RTSI Switch Registers */ |
| 65 | #define RTSI_SW_SHIFT_REG 0x1E /* wo 8 */ |
| 66 | #define RTSI_SW_STROBE_REG 0x1F /* wo 8 */ |
| 67 | /* DIO-24 Registers */ |
| 68 | #define DIO_24_PORTA_REG 0x00 /* rw 8 */ |
| 69 | #define DIO_24_PORTB_REG 0x01 /* rw 8 */ |
| 70 | #define DIO_24_PORTC_REG 0x02 /* rw 8 */ |
| 71 | #define DIO_24_CNFG_REG 0x03 /* wo 8 */ |
| 72 | |
| 73 | /* Command Register bits */ |
| 74 | #define COMREG1_2SCADC 0x0001 |
| 75 | #define COMREG1_1632CNT 0x0002 |
| 76 | #define COMREG1_SCANEN 0x0008 |
| 77 | #define COMREG1_DAQEN 0x0010 |
| 78 | #define COMREG1_DMAEN 0x0020 |
| 79 | #define COMREG1_CONVINTEN 0x0080 |
| 80 | #define COMREG2_SCN2 0x0010 |
| 81 | #define COMREG2_INTEN 0x0080 |
| 82 | #define COMREG2_DOUTEN0 0x0100 |
| 83 | #define COMREG2_DOUTEN1 0x0200 |
| 84 | /* Status Register bits */ |
| 85 | #define STAT_AD_OVERRUN 0x0100 |
| 86 | #define STAT_AD_OVERFLOW 0x0200 |
| 87 | #define STAT_AD_DAQPROG 0x0800 |
| 88 | #define STAT_AD_CONVAVAIL 0x2000 |
| 89 | #define STAT_AD_DAQSTOPINT 0x4000 |
| 90 | /* AM9513A Counter/Timer defines */ |
| 91 | #define CLOCK_1_MHZ 0x8B25 |
| 92 | #define CLOCK_100_KHZ 0x8C25 |
| 93 | #define CLOCK_10_KHZ 0x8D25 |
| 94 | #define CLOCK_1_KHZ 0x8E25 |
| 95 | #define CLOCK_100_HZ 0x8F25 |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 96 | |
Bill Pemberton | 9f30c24 | 2009-03-16 22:16:18 -0400 | [diff] [blame] | 97 | struct atmio16_board_t { |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 98 | const char *name; |
| 99 | int has_8255; |
Bill Pemberton | 9f30c24 | 2009-03-16 22:16:18 -0400 | [diff] [blame] | 100 | }; |
| 101 | |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 102 | /* range structs */ |
H Hartley Sweeten | af71a89 | 2013-12-09 17:31:06 -0700 | [diff] [blame] | 103 | static const struct comedi_lrange range_atmio16d_ai_10_bipolar = { |
| 104 | 4, { |
| 105 | BIP_RANGE(10), |
| 106 | BIP_RANGE(1), |
| 107 | BIP_RANGE(0.1), |
| 108 | BIP_RANGE(0.02) |
| 109 | } |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 110 | }; |
| 111 | |
H Hartley Sweeten | af71a89 | 2013-12-09 17:31:06 -0700 | [diff] [blame] | 112 | static const struct comedi_lrange range_atmio16d_ai_5_bipolar = { |
| 113 | 4, { |
| 114 | BIP_RANGE(5), |
| 115 | BIP_RANGE(0.5), |
| 116 | BIP_RANGE(0.05), |
| 117 | BIP_RANGE(0.01) |
| 118 | } |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 119 | }; |
| 120 | |
H Hartley Sweeten | af71a89 | 2013-12-09 17:31:06 -0700 | [diff] [blame] | 121 | static const struct comedi_lrange range_atmio16d_ai_unipolar = { |
| 122 | 4, { |
| 123 | UNI_RANGE(10), |
| 124 | UNI_RANGE(1), |
| 125 | UNI_RANGE(0.1), |
| 126 | UNI_RANGE(0.02) |
| 127 | } |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 128 | }; |
| 129 | |
| 130 | /* private data struct */ |
Bill Pemberton | 8c8a288 | 2009-03-19 17:59:28 -0400 | [diff] [blame] | 131 | struct atmio16d_private { |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 132 | enum { adc_diff, adc_singleended } adc_mux; |
| 133 | enum { adc_bipolar10, adc_bipolar5, adc_unipolar10 } adc_range; |
| 134 | enum { adc_2comp, adc_straight } adc_coding; |
| 135 | enum { dac_bipolar, dac_unipolar } dac0_range, dac1_range; |
| 136 | enum { dac_internal, dac_external } dac0_reference, dac1_reference; |
| 137 | enum { dac_2comp, dac_straight } dac0_coding, dac1_coding; |
Bill Pemberton | 9ced1de | 2009-03-16 22:05:31 -0400 | [diff] [blame] | 138 | const struct comedi_lrange *ao_range_type_list[2]; |
Bruce Jones | 2c14681 | 2009-09-24 14:59:52 -0700 | [diff] [blame] | 139 | unsigned int com_reg_1_state; /* current state of command register 1 */ |
| 140 | unsigned int com_reg_2_state; /* current state of command register 2 */ |
Bill Pemberton | 8c8a288 | 2009-03-19 17:59:28 -0400 | [diff] [blame] | 141 | }; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 142 | |
Bill Pemberton | da91b26 | 2009-04-09 16:07:03 -0400 | [diff] [blame] | 143 | static void reset_counters(struct comedi_device *dev) |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 144 | { |
| 145 | /* Counter 2 */ |
| 146 | outw(0xFFC2, dev->iobase + AM9513A_COM_REG); |
| 147 | outw(0xFF02, dev->iobase + AM9513A_COM_REG); |
| 148 | outw(0x4, dev->iobase + AM9513A_DATA_REG); |
| 149 | outw(0xFF0A, dev->iobase + AM9513A_COM_REG); |
| 150 | outw(0x3, dev->iobase + AM9513A_DATA_REG); |
| 151 | outw(0xFF42, dev->iobase + AM9513A_COM_REG); |
| 152 | outw(0xFF42, dev->iobase + AM9513A_COM_REG); |
| 153 | /* Counter 3 */ |
| 154 | outw(0xFFC4, dev->iobase + AM9513A_COM_REG); |
| 155 | outw(0xFF03, dev->iobase + AM9513A_COM_REG); |
| 156 | outw(0x4, dev->iobase + AM9513A_DATA_REG); |
| 157 | outw(0xFF0B, dev->iobase + AM9513A_COM_REG); |
| 158 | outw(0x3, dev->iobase + AM9513A_DATA_REG); |
| 159 | outw(0xFF44, dev->iobase + AM9513A_COM_REG); |
| 160 | outw(0xFF44, dev->iobase + AM9513A_COM_REG); |
| 161 | /* Counter 4 */ |
| 162 | outw(0xFFC8, dev->iobase + AM9513A_COM_REG); |
| 163 | outw(0xFF04, dev->iobase + AM9513A_COM_REG); |
| 164 | outw(0x4, dev->iobase + AM9513A_DATA_REG); |
| 165 | outw(0xFF0C, dev->iobase + AM9513A_COM_REG); |
| 166 | outw(0x3, dev->iobase + AM9513A_DATA_REG); |
| 167 | outw(0xFF48, dev->iobase + AM9513A_COM_REG); |
| 168 | outw(0xFF48, dev->iobase + AM9513A_COM_REG); |
| 169 | /* Counter 5 */ |
| 170 | outw(0xFFD0, dev->iobase + AM9513A_COM_REG); |
| 171 | outw(0xFF05, dev->iobase + AM9513A_COM_REG); |
| 172 | outw(0x4, dev->iobase + AM9513A_DATA_REG); |
| 173 | outw(0xFF0D, dev->iobase + AM9513A_COM_REG); |
| 174 | outw(0x3, dev->iobase + AM9513A_DATA_REG); |
| 175 | outw(0xFF50, dev->iobase + AM9513A_COM_REG); |
| 176 | outw(0xFF50, dev->iobase + AM9513A_COM_REG); |
| 177 | |
| 178 | outw(0, dev->iobase + AD_CLEAR_REG); |
| 179 | } |
| 180 | |
Bill Pemberton | da91b26 | 2009-04-09 16:07:03 -0400 | [diff] [blame] | 181 | static void reset_atmio16d(struct comedi_device *dev) |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 182 | { |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 183 | struct atmio16d_private *devpriv = dev->private; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 184 | int i; |
| 185 | |
| 186 | /* now we need to initialize the board */ |
| 187 | outw(0, dev->iobase + COM_REG_1); |
| 188 | outw(0, dev->iobase + COM_REG_2); |
| 189 | outw(0, dev->iobase + MUX_GAIN_REG); |
| 190 | /* init AM9513A timer */ |
| 191 | outw(0xFFFF, dev->iobase + AM9513A_COM_REG); |
| 192 | outw(0xFFEF, dev->iobase + AM9513A_COM_REG); |
| 193 | outw(0xFF17, dev->iobase + AM9513A_COM_REG); |
| 194 | outw(0xF000, dev->iobase + AM9513A_DATA_REG); |
| 195 | for (i = 1; i <= 5; ++i) { |
| 196 | outw(0xFF00 + i, dev->iobase + AM9513A_COM_REG); |
| 197 | outw(0x0004, dev->iobase + AM9513A_DATA_REG); |
| 198 | outw(0xFF08 + i, dev->iobase + AM9513A_COM_REG); |
| 199 | outw(0x3, dev->iobase + AM9513A_DATA_REG); |
| 200 | } |
| 201 | outw(0xFF5F, dev->iobase + AM9513A_COM_REG); |
| 202 | /* timer init done */ |
| 203 | outw(0, dev->iobase + AD_CLEAR_REG); |
| 204 | outw(0, dev->iobase + INT2CLR_REG); |
| 205 | /* select straight binary mode for Analog Input */ |
| 206 | devpriv->com_reg_1_state |= 1; |
| 207 | outw(devpriv->com_reg_1_state, dev->iobase + COM_REG_1); |
| 208 | devpriv->adc_coding = adc_straight; |
| 209 | /* zero the analog outputs */ |
| 210 | outw(2048, dev->iobase + DAC0_REG); |
| 211 | outw(2048, dev->iobase + DAC1_REG); |
| 212 | } |
| 213 | |
Jiri Slaby | 70265d2 | 2009-03-26 09:34:06 +0100 | [diff] [blame] | 214 | static irqreturn_t atmio16d_interrupt(int irq, void *d) |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 215 | { |
Bill Pemberton | 71b5f4f | 2009-03-16 22:05:08 -0400 | [diff] [blame] | 216 | struct comedi_device *dev = d; |
H Hartley Sweeten | bea70d0 | 2013-12-05 13:43:46 -0700 | [diff] [blame] | 217 | struct comedi_subdevice *s = dev->read_subdev; |
H Hartley Sweeten | 67fdc30 | 2014-10-22 15:36:59 -0700 | [diff] [blame] | 218 | unsigned short val; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 219 | |
H Hartley Sweeten | 67fdc30 | 2014-10-22 15:36:59 -0700 | [diff] [blame] | 220 | val = inw(dev->iobase + AD_FIFO_REG); |
| 221 | comedi_buf_write_samples(s, &val, 1); |
H Hartley Sweeten | c827d2b | 2014-09-18 11:35:28 -0700 | [diff] [blame] | 222 | comedi_handle_events(dev, s); |
H Hartley Sweeten | 67fdc30 | 2014-10-22 15:36:59 -0700 | [diff] [blame] | 223 | |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 224 | return IRQ_HANDLED; |
| 225 | } |
| 226 | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 227 | static int atmio16d_ai_cmdtest(struct comedi_device *dev, |
| 228 | struct comedi_subdevice *s, |
| 229 | struct comedi_cmd *cmd) |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 230 | { |
H Hartley Sweeten | 27020ff | 2012-09-26 14:11:10 -0700 | [diff] [blame] | 231 | int err = 0; |
H Hartley Sweeten | 985eb50 | 2012-06-13 18:09:51 -0700 | [diff] [blame] | 232 | |
H Hartley Sweeten | 27020ff | 2012-09-26 14:11:10 -0700 | [diff] [blame] | 233 | /* Step 1 : check if triggers are trivially valid */ |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 234 | |
Ian Abbott | 2684a5e | 2015-03-27 19:14:22 +0000 | [diff] [blame] | 235 | err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW); |
| 236 | err |= comedi_check_trigger_src(&cmd->scan_begin_src, |
H Hartley Sweeten | 27020ff | 2012-09-26 14:11:10 -0700 | [diff] [blame] | 237 | TRIG_FOLLOW | TRIG_TIMER); |
Ian Abbott | 2684a5e | 2015-03-27 19:14:22 +0000 | [diff] [blame] | 238 | err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_TIMER); |
| 239 | err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); |
| 240 | err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 241 | |
| 242 | if (err) |
| 243 | return 1; |
| 244 | |
H Hartley Sweeten | 27020ff | 2012-09-26 14:11:10 -0700 | [diff] [blame] | 245 | /* Step 2a : make sure trigger sources are unique */ |
| 246 | |
Ian Abbott | 2684a5e | 2015-03-27 19:14:22 +0000 | [diff] [blame] | 247 | err |= comedi_check_trigger_is_unique(cmd->scan_begin_src); |
| 248 | err |= comedi_check_trigger_is_unique(cmd->stop_src); |
H Hartley Sweeten | 27020ff | 2012-09-26 14:11:10 -0700 | [diff] [blame] | 249 | |
| 250 | /* Step 2b : and mutually compatible */ |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 251 | |
| 252 | if (err) |
| 253 | return 2; |
| 254 | |
H Hartley Sweeten | ec3ffe6 | 2012-11-13 17:56:41 -0700 | [diff] [blame] | 255 | /* Step 3: check if arguments are trivially valid */ |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 256 | |
Ian Abbott | 2684a5e | 2015-03-27 19:14:22 +0000 | [diff] [blame] | 257 | err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); |
H Hartley Sweeten | ec3ffe6 | 2012-11-13 17:56:41 -0700 | [diff] [blame] | 258 | |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 259 | if (cmd->scan_begin_src == TRIG_FOLLOW) { |
| 260 | /* internal trigger */ |
Ian Abbott | 2684a5e | 2015-03-27 19:14:22 +0000 | [diff] [blame] | 261 | err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0); |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 262 | } else { |
| 263 | #if 0 |
| 264 | /* external trigger */ |
| 265 | /* should be level/edge, hi/lo specification here */ |
Ian Abbott | 2684a5e | 2015-03-27 19:14:22 +0000 | [diff] [blame] | 266 | err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0); |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 267 | #endif |
| 268 | } |
| 269 | |
Ian Abbott | 2684a5e | 2015-03-27 19:14:22 +0000 | [diff] [blame] | 270 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 10000); |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 271 | #if 0 |
Ian Abbott | 2684a5e | 2015-03-27 19:14:22 +0000 | [diff] [blame] | 272 | err |= comedi_check_trigger_arg_max(&cmd->convert_arg, SLOWEST_TIMER); |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 273 | #endif |
H Hartley Sweeten | ec3ffe6 | 2012-11-13 17:56:41 -0700 | [diff] [blame] | 274 | |
Ian Abbott | 2684a5e | 2015-03-27 19:14:22 +0000 | [diff] [blame] | 275 | err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, |
| 276 | cmd->chanlist_len); |
H Hartley Sweeten | ec3ffe6 | 2012-11-13 17:56:41 -0700 | [diff] [blame] | 277 | |
H Hartley Sweeten | fd6887b | 2014-09-09 16:15:50 -0700 | [diff] [blame] | 278 | if (cmd->stop_src == TRIG_COUNT) |
Ian Abbott | 2684a5e | 2015-03-27 19:14:22 +0000 | [diff] [blame] | 279 | err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1); |
H Hartley Sweeten | fd6887b | 2014-09-09 16:15:50 -0700 | [diff] [blame] | 280 | else /* TRIG_NONE */ |
Ian Abbott | 2684a5e | 2015-03-27 19:14:22 +0000 | [diff] [blame] | 281 | err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 282 | |
| 283 | if (err) |
| 284 | return 3; |
| 285 | |
| 286 | return 0; |
| 287 | } |
| 288 | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 289 | static int atmio16d_ai_cmd(struct comedi_device *dev, |
| 290 | struct comedi_subdevice *s) |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 291 | { |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 292 | struct atmio16d_private *devpriv = dev->private; |
Bill Pemberton | ea6d0d4 | 2009-03-16 22:05:47 -0400 | [diff] [blame] | 293 | struct comedi_cmd *cmd = &s->async->cmd; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 294 | unsigned int timer, base_clock; |
| 295 | unsigned int sample_count, tmp, chan, gain; |
| 296 | int i; |
H Hartley Sweeten | 985eb50 | 2012-06-13 18:09:51 -0700 | [diff] [blame] | 297 | |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 298 | /* This is slowly becoming a working command interface. * |
| 299 | * It is still uber-experimental */ |
| 300 | |
| 301 | reset_counters(dev); |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 302 | |
| 303 | /* check if scanning multiple channels */ |
| 304 | if (cmd->chanlist_len < 2) { |
| 305 | devpriv->com_reg_1_state &= ~COMREG1_SCANEN; |
| 306 | outw(devpriv->com_reg_1_state, dev->iobase + COM_REG_1); |
| 307 | } else { |
| 308 | devpriv->com_reg_1_state |= COMREG1_SCANEN; |
| 309 | devpriv->com_reg_2_state |= COMREG2_SCN2; |
| 310 | outw(devpriv->com_reg_1_state, dev->iobase + COM_REG_1); |
| 311 | outw(devpriv->com_reg_2_state, dev->iobase + COM_REG_2); |
| 312 | } |
| 313 | |
| 314 | /* Setup the Mux-Gain Counter */ |
| 315 | for (i = 0; i < cmd->chanlist_len; ++i) { |
| 316 | chan = CR_CHAN(cmd->chanlist[i]); |
| 317 | gain = CR_RANGE(cmd->chanlist[i]); |
| 318 | outw(i, dev->iobase + MUX_CNTR_REG); |
| 319 | tmp = chan | (gain << 6); |
| 320 | if (i == cmd->scan_end_arg - 1) |
| 321 | tmp |= 0x0010; /* set LASTONE bit */ |
| 322 | outw(tmp, dev->iobase + MUX_GAIN_REG); |
| 323 | } |
| 324 | |
| 325 | /* Now program the sample interval timer */ |
| 326 | /* Figure out which clock to use then get an |
| 327 | * appropriate timer value */ |
| 328 | if (cmd->convert_arg < 65536000) { |
| 329 | base_clock = CLOCK_1_MHZ; |
| 330 | timer = cmd->convert_arg / 1000; |
| 331 | } else if (cmd->convert_arg < 655360000) { |
| 332 | base_clock = CLOCK_100_KHZ; |
| 333 | timer = cmd->convert_arg / 10000; |
Andrey Utkin | d2fd4d3 | 2014-07-11 15:38:30 +0100 | [diff] [blame] | 334 | } else /* cmd->convert_arg < 6553600000 */ { |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 335 | base_clock = CLOCK_10_KHZ; |
| 336 | timer = cmd->convert_arg / 100000; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 337 | } |
| 338 | outw(0xFF03, dev->iobase + AM9513A_COM_REG); |
| 339 | outw(base_clock, dev->iobase + AM9513A_DATA_REG); |
| 340 | outw(0xFF0B, dev->iobase + AM9513A_COM_REG); |
| 341 | outw(0x2, dev->iobase + AM9513A_DATA_REG); |
| 342 | outw(0xFF44, dev->iobase + AM9513A_COM_REG); |
| 343 | outw(0xFFF3, dev->iobase + AM9513A_COM_REG); |
| 344 | outw(timer, dev->iobase + AM9513A_DATA_REG); |
| 345 | outw(0xFF24, dev->iobase + AM9513A_COM_REG); |
| 346 | |
| 347 | /* Now figure out how many samples to get */ |
| 348 | /* and program the sample counter */ |
| 349 | sample_count = cmd->stop_arg * cmd->scan_end_arg; |
| 350 | outw(0xFF04, dev->iobase + AM9513A_COM_REG); |
| 351 | outw(0x1025, dev->iobase + AM9513A_DATA_REG); |
| 352 | outw(0xFF0C, dev->iobase + AM9513A_COM_REG); |
| 353 | if (sample_count < 65536) { |
| 354 | /* use only Counter 4 */ |
| 355 | outw(sample_count, dev->iobase + AM9513A_DATA_REG); |
| 356 | outw(0xFF48, dev->iobase + AM9513A_COM_REG); |
| 357 | outw(0xFFF4, dev->iobase + AM9513A_COM_REG); |
| 358 | outw(0xFF28, dev->iobase + AM9513A_COM_REG); |
| 359 | devpriv->com_reg_1_state &= ~COMREG1_1632CNT; |
| 360 | outw(devpriv->com_reg_1_state, dev->iobase + COM_REG_1); |
| 361 | } else { |
| 362 | /* Counter 4 and 5 are needed */ |
Bill Pemberton | c374413 | 2009-04-22 21:11:47 -0400 | [diff] [blame] | 363 | |
| 364 | tmp = sample_count & 0xFFFF; |
| 365 | if (tmp) |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 366 | outw(tmp - 1, dev->iobase + AM9513A_DATA_REG); |
Bill Pemberton | c374413 | 2009-04-22 21:11:47 -0400 | [diff] [blame] | 367 | else |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 368 | outw(0xFFFF, dev->iobase + AM9513A_DATA_REG); |
Bill Pemberton | c374413 | 2009-04-22 21:11:47 -0400 | [diff] [blame] | 369 | |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 370 | outw(0xFF48, dev->iobase + AM9513A_COM_REG); |
| 371 | outw(0, dev->iobase + AM9513A_DATA_REG); |
| 372 | outw(0xFF28, dev->iobase + AM9513A_COM_REG); |
| 373 | outw(0xFF05, dev->iobase + AM9513A_COM_REG); |
| 374 | outw(0x25, dev->iobase + AM9513A_DATA_REG); |
| 375 | outw(0xFF0D, dev->iobase + AM9513A_COM_REG); |
| 376 | tmp = sample_count & 0xFFFF; |
| 377 | if ((tmp == 0) || (tmp == 1)) { |
| 378 | outw((sample_count >> 16) & 0xFFFF, |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 379 | dev->iobase + AM9513A_DATA_REG); |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 380 | } else { |
| 381 | outw(((sample_count >> 16) & 0xFFFF) + 1, |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 382 | dev->iobase + AM9513A_DATA_REG); |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 383 | } |
| 384 | outw(0xFF70, dev->iobase + AM9513A_COM_REG); |
| 385 | devpriv->com_reg_1_state |= COMREG1_1632CNT; |
| 386 | outw(devpriv->com_reg_1_state, dev->iobase + COM_REG_1); |
| 387 | } |
| 388 | |
| 389 | /* Program the scan interval timer ONLY IF SCANNING IS ENABLED */ |
| 390 | /* Figure out which clock to use then get an |
| 391 | * appropriate timer value */ |
| 392 | if (cmd->chanlist_len > 1) { |
| 393 | if (cmd->scan_begin_arg < 65536000) { |
| 394 | base_clock = CLOCK_1_MHZ; |
| 395 | timer = cmd->scan_begin_arg / 1000; |
| 396 | } else if (cmd->scan_begin_arg < 655360000) { |
| 397 | base_clock = CLOCK_100_KHZ; |
| 398 | timer = cmd->scan_begin_arg / 10000; |
Andrey Utkin | d2fd4d3 | 2014-07-11 15:38:30 +0100 | [diff] [blame] | 399 | } else /* cmd->scan_begin_arg < 6553600000 */ { |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 400 | base_clock = CLOCK_10_KHZ; |
| 401 | timer = cmd->scan_begin_arg / 100000; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 402 | } |
| 403 | outw(0xFF02, dev->iobase + AM9513A_COM_REG); |
| 404 | outw(base_clock, dev->iobase + AM9513A_DATA_REG); |
| 405 | outw(0xFF0A, dev->iobase + AM9513A_COM_REG); |
| 406 | outw(0x2, dev->iobase + AM9513A_DATA_REG); |
| 407 | outw(0xFF42, dev->iobase + AM9513A_COM_REG); |
| 408 | outw(0xFFF2, dev->iobase + AM9513A_COM_REG); |
| 409 | outw(timer, dev->iobase + AM9513A_DATA_REG); |
| 410 | outw(0xFF22, dev->iobase + AM9513A_COM_REG); |
| 411 | } |
| 412 | |
| 413 | /* Clear the A/D FIFO and reset the MUX counter */ |
| 414 | outw(0, dev->iobase + AD_CLEAR_REG); |
| 415 | outw(0, dev->iobase + MUX_CNTR_REG); |
| 416 | outw(0, dev->iobase + INT2CLR_REG); |
| 417 | /* enable this acquisition operation */ |
| 418 | devpriv->com_reg_1_state |= COMREG1_DAQEN; |
| 419 | outw(devpriv->com_reg_1_state, dev->iobase + COM_REG_1); |
| 420 | /* enable interrupts for conversion completion */ |
| 421 | devpriv->com_reg_1_state |= COMREG1_CONVINTEN; |
| 422 | devpriv->com_reg_2_state |= COMREG2_INTEN; |
| 423 | outw(devpriv->com_reg_1_state, dev->iobase + COM_REG_1); |
| 424 | outw(devpriv->com_reg_2_state, dev->iobase + COM_REG_2); |
| 425 | /* apply a trigger. this starts the counters! */ |
| 426 | outw(0, dev->iobase + START_DAQ_REG); |
| 427 | |
| 428 | return 0; |
| 429 | } |
| 430 | |
| 431 | /* This will cancel a running acquisition operation */ |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 432 | static int atmio16d_ai_cancel(struct comedi_device *dev, |
| 433 | struct comedi_subdevice *s) |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 434 | { |
| 435 | reset_atmio16d(dev); |
| 436 | |
| 437 | return 0; |
| 438 | } |
| 439 | |
H Hartley Sweeten | 03ff589 | 2014-02-10 11:49:26 -0700 | [diff] [blame] | 440 | static int atmio16d_ai_eoc(struct comedi_device *dev, |
| 441 | struct comedi_subdevice *s, |
| 442 | struct comedi_insn *insn, |
| 443 | unsigned long context) |
| 444 | { |
| 445 | unsigned int status; |
| 446 | |
| 447 | status = inw(dev->iobase + STAT_REG); |
| 448 | if (status & STAT_AD_CONVAVAIL) |
| 449 | return 0; |
| 450 | if (status & STAT_AD_OVERFLOW) { |
| 451 | outw(0, dev->iobase + AD_CLEAR_REG); |
| 452 | return -EOVERFLOW; |
| 453 | } |
| 454 | return -EBUSY; |
| 455 | } |
| 456 | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 457 | static int atmio16d_ai_insn_read(struct comedi_device *dev, |
| 458 | struct comedi_subdevice *s, |
| 459 | struct comedi_insn *insn, unsigned int *data) |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 460 | { |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 461 | struct atmio16d_private *devpriv = dev->private; |
H Hartley Sweeten | 03ff589 | 2014-02-10 11:49:26 -0700 | [diff] [blame] | 462 | int i; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 463 | int chan; |
| 464 | int gain; |
H Hartley Sweeten | 03ff589 | 2014-02-10 11:49:26 -0700 | [diff] [blame] | 465 | int ret; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 466 | |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 467 | chan = CR_CHAN(insn->chanspec); |
| 468 | gain = CR_RANGE(insn->chanspec); |
| 469 | |
| 470 | /* reset the Analog input circuitry */ |
Bill Pemberton | 2696fb5 | 2009-03-27 11:29:34 -0400 | [diff] [blame] | 471 | /* outw( 0, dev->iobase+AD_CLEAR_REG ); */ |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 472 | /* reset the Analog Input MUX Counter to 0 */ |
Bill Pemberton | 2696fb5 | 2009-03-27 11:29:34 -0400 | [diff] [blame] | 473 | /* outw( 0, dev->iobase+MUX_CNTR_REG ); */ |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 474 | |
| 475 | /* set the Input MUX gain */ |
| 476 | outw(chan | (gain << 6), dev->iobase + MUX_GAIN_REG); |
| 477 | |
| 478 | for (i = 0; i < insn->n; i++) { |
| 479 | /* start the conversion */ |
| 480 | outw(0, dev->iobase + START_CONVERT_REG); |
H Hartley Sweeten | 03ff589 | 2014-02-10 11:49:26 -0700 | [diff] [blame] | 481 | |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 482 | /* wait for it to finish */ |
H Hartley Sweeten | 03ff589 | 2014-02-10 11:49:26 -0700 | [diff] [blame] | 483 | ret = comedi_timeout(dev, s, insn, atmio16d_ai_eoc, 0); |
| 484 | if (ret) |
| 485 | return ret; |
| 486 | |
| 487 | /* read the data now */ |
| 488 | data[i] = inw(dev->iobase + AD_FIFO_REG); |
| 489 | /* change to two's complement if need be */ |
| 490 | if (devpriv->adc_coding == adc_2comp) |
| 491 | data[i] ^= 0x800; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 492 | } |
| 493 | |
| 494 | return i; |
| 495 | } |
| 496 | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 497 | static int atmio16d_ao_insn_write(struct comedi_device *dev, |
| 498 | struct comedi_subdevice *s, |
H Hartley Sweeten | 898fb5c | 2014-08-25 16:04:26 -0700 | [diff] [blame] | 499 | struct comedi_insn *insn, |
| 500 | unsigned int *data) |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 501 | { |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 502 | struct atmio16d_private *devpriv = dev->private; |
H Hartley Sweeten | 898fb5c | 2014-08-25 16:04:26 -0700 | [diff] [blame] | 503 | unsigned int chan = CR_CHAN(insn->chanspec); |
| 504 | unsigned int reg = (chan) ? DAC1_REG : DAC0_REG; |
| 505 | bool munge = false; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 506 | int i; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 507 | |
H Hartley Sweeten | 898fb5c | 2014-08-25 16:04:26 -0700 | [diff] [blame] | 508 | if (chan == 0 && devpriv->dac0_coding == dac_2comp) |
| 509 | munge = true; |
| 510 | if (chan == 1 && devpriv->dac1_coding == dac_2comp) |
| 511 | munge = true; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 512 | |
| 513 | for (i = 0; i < insn->n; i++) { |
H Hartley Sweeten | 898fb5c | 2014-08-25 16:04:26 -0700 | [diff] [blame] | 514 | unsigned int val = data[i]; |
| 515 | |
H Hartley Sweeten | e892875 | 2014-08-25 16:04:27 -0700 | [diff] [blame] | 516 | s->readback[chan] = val; |
H Hartley Sweeten | 898fb5c | 2014-08-25 16:04:26 -0700 | [diff] [blame] | 517 | |
| 518 | if (munge) |
| 519 | val ^= 0x800; |
| 520 | |
| 521 | outw(val, dev->iobase + reg); |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 522 | } |
H Hartley Sweeten | 898fb5c | 2014-08-25 16:04:26 -0700 | [diff] [blame] | 523 | |
| 524 | return insn->n; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 525 | } |
| 526 | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 527 | static int atmio16d_dio_insn_bits(struct comedi_device *dev, |
| 528 | struct comedi_subdevice *s, |
H Hartley Sweeten | 97f4289 | 2013-08-30 11:05:58 -0700 | [diff] [blame] | 529 | struct comedi_insn *insn, |
| 530 | unsigned int *data) |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 531 | { |
H Hartley Sweeten | 97f4289 | 2013-08-30 11:05:58 -0700 | [diff] [blame] | 532 | if (comedi_dio_update_state(s, data)) |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 533 | outw(s->state, dev->iobase + MIO_16_DIG_OUT_REG); |
H Hartley Sweeten | 97f4289 | 2013-08-30 11:05:58 -0700 | [diff] [blame] | 534 | |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 535 | data[1] = inw(dev->iobase + MIO_16_DIG_IN_REG); |
| 536 | |
H Hartley Sweeten | a2714e3 | 2012-06-18 13:16:35 -0700 | [diff] [blame] | 537 | return insn->n; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 538 | } |
| 539 | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 540 | static int atmio16d_dio_insn_config(struct comedi_device *dev, |
| 541 | struct comedi_subdevice *s, |
| 542 | struct comedi_insn *insn, |
| 543 | unsigned int *data) |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 544 | { |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 545 | struct atmio16d_private *devpriv = dev->private; |
H Hartley Sweeten | f9f34d5 | 2013-08-26 15:29:33 -0700 | [diff] [blame] | 546 | unsigned int chan = CR_CHAN(insn->chanspec); |
| 547 | unsigned int mask; |
| 548 | int ret; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 549 | |
H Hartley Sweeten | f9f34d5 | 2013-08-26 15:29:33 -0700 | [diff] [blame] | 550 | if (chan < 4) |
| 551 | mask = 0x0f; |
| 552 | else |
| 553 | mask = 0xf0; |
| 554 | |
| 555 | ret = comedi_dio_insn_config(dev, s, insn, data, mask); |
| 556 | if (ret) |
| 557 | return ret; |
| 558 | |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 559 | devpriv->com_reg_2_state &= ~(COMREG2_DOUTEN0 | COMREG2_DOUTEN1); |
| 560 | if (s->io_bits & 0x0f) |
| 561 | devpriv->com_reg_2_state |= COMREG2_DOUTEN0; |
| 562 | if (s->io_bits & 0xf0) |
| 563 | devpriv->com_reg_2_state |= COMREG2_DOUTEN1; |
| 564 | outw(devpriv->com_reg_2_state, dev->iobase + COM_REG_2); |
| 565 | |
H Hartley Sweeten | f9f34d5 | 2013-08-26 15:29:33 -0700 | [diff] [blame] | 566 | return insn->n; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 567 | } |
| 568 | |
| 569 | /* |
| 570 | options[0] - I/O port |
| 571 | options[1] - MIO irq |
Bruce Jones | ce5ade4 | 2009-09-24 15:02:36 -0700 | [diff] [blame] | 572 | 0 == no irq |
| 573 | N == irq N {3,4,5,6,7,9,10,11,12,14,15} |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 574 | options[2] - DIO irq |
Bruce Jones | ce5ade4 | 2009-09-24 15:02:36 -0700 | [diff] [blame] | 575 | 0 == no irq |
| 576 | N == irq N {3,4,5,6,7,9} |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 577 | options[3] - DMA1 channel |
Bruce Jones | ce5ade4 | 2009-09-24 15:02:36 -0700 | [diff] [blame] | 578 | 0 == no DMA |
| 579 | N == DMA N {5,6,7} |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 580 | options[4] - DMA2 channel |
Bruce Jones | ce5ade4 | 2009-09-24 15:02:36 -0700 | [diff] [blame] | 581 | 0 == no DMA |
| 582 | N == DMA N {5,6,7} |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 583 | |
| 584 | options[5] - a/d mux |
Bruce Jones | ce5ade4 | 2009-09-24 15:02:36 -0700 | [diff] [blame] | 585 | 0=differential, 1=single |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 586 | options[6] - a/d range |
Bruce Jones | ce5ade4 | 2009-09-24 15:02:36 -0700 | [diff] [blame] | 587 | 0=bipolar10, 1=bipolar5, 2=unipolar10 |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 588 | |
| 589 | options[7] - dac0 range |
Bruce Jones | ce5ade4 | 2009-09-24 15:02:36 -0700 | [diff] [blame] | 590 | 0=bipolar, 1=unipolar |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 591 | options[8] - dac0 reference |
Bruce Jones | ce5ade4 | 2009-09-24 15:02:36 -0700 | [diff] [blame] | 592 | 0=internal, 1=external |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 593 | options[9] - dac0 coding |
Bruce Jones | ce5ade4 | 2009-09-24 15:02:36 -0700 | [diff] [blame] | 594 | 0=2's comp, 1=straight binary |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 595 | |
| 596 | options[10] - dac1 range |
| 597 | options[11] - dac1 reference |
| 598 | options[12] - dac1 coding |
| 599 | */ |
| 600 | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 601 | static int atmio16d_attach(struct comedi_device *dev, |
| 602 | struct comedi_devconfig *it) |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 603 | { |
Ian Abbott | 967b3eb | 2014-09-09 11:26:40 +0100 | [diff] [blame] | 604 | const struct atmio16_board_t *board = dev->board_ptr; |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 605 | struct atmio16d_private *devpriv; |
H Hartley Sweeten | 2028bdc | 2013-04-09 16:25:48 -0700 | [diff] [blame] | 606 | struct comedi_subdevice *s; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 607 | int ret; |
| 608 | |
H Hartley Sweeten | 862755e | 2014-07-18 17:01:22 -0700 | [diff] [blame] | 609 | ret = comedi_request_region(dev, it->options[0], 0x20); |
H Hartley Sweeten | 2028bdc | 2013-04-09 16:25:48 -0700 | [diff] [blame] | 610 | if (ret) |
| 611 | return ret; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 612 | |
H Hartley Sweeten | 2f0b9d0 | 2012-06-11 17:45:15 -0700 | [diff] [blame] | 613 | ret = comedi_alloc_subdevices(dev, 4); |
H Hartley Sweeten | 8b6c569 | 2012-06-12 11:59:33 -0700 | [diff] [blame] | 614 | if (ret) |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 615 | return ret; |
Bill Pemberton | c374413 | 2009-04-22 21:11:47 -0400 | [diff] [blame] | 616 | |
H Hartley Sweeten | 0bdab50 | 2013-06-24 16:55:44 -0700 | [diff] [blame] | 617 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
H Hartley Sweeten | c34fa26 | 2012-10-23 13:22:37 -0700 | [diff] [blame] | 618 | if (!devpriv) |
| 619 | return -ENOMEM; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 620 | |
| 621 | /* reset the atmio16d hardware */ |
| 622 | reset_atmio16d(dev); |
| 623 | |
H Hartley Sweeten | ec9b2f4 | 2013-11-26 16:42:30 -0700 | [diff] [blame] | 624 | if (it->options[1]) { |
| 625 | ret = request_irq(it->options[1], atmio16d_interrupt, 0, |
| 626 | dev->board_name, dev); |
| 627 | if (ret == 0) |
| 628 | dev->irq = it->options[1]; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 629 | } |
| 630 | |
| 631 | /* set device options */ |
| 632 | devpriv->adc_mux = it->options[5]; |
| 633 | devpriv->adc_range = it->options[6]; |
| 634 | |
| 635 | devpriv->dac0_range = it->options[7]; |
| 636 | devpriv->dac0_reference = it->options[8]; |
| 637 | devpriv->dac0_coding = it->options[9]; |
| 638 | devpriv->dac1_range = it->options[10]; |
| 639 | devpriv->dac1_reference = it->options[11]; |
| 640 | devpriv->dac1_coding = it->options[12]; |
| 641 | |
| 642 | /* setup sub-devices */ |
H Hartley Sweeten | 3f507ce | 2012-09-05 18:48:58 -0700 | [diff] [blame] | 643 | s = &dev->subdevices[0]; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 644 | /* ai subdevice */ |
| 645 | s->type = COMEDI_SUBD_AI; |
H Hartley Sweeten | ec9b2f4 | 2013-11-26 16:42:30 -0700 | [diff] [blame] | 646 | s->subdev_flags = SDF_READABLE | SDF_GROUND; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 647 | s->n_chan = (devpriv->adc_mux ? 16 : 8); |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 648 | s->insn_read = atmio16d_ai_insn_read; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 649 | s->maxdata = 0xfff; /* 4095 decimal */ |
| 650 | switch (devpriv->adc_range) { |
| 651 | case adc_bipolar10: |
| 652 | s->range_table = &range_atmio16d_ai_10_bipolar; |
| 653 | break; |
| 654 | case adc_bipolar5: |
| 655 | s->range_table = &range_atmio16d_ai_5_bipolar; |
| 656 | break; |
| 657 | case adc_unipolar10: |
| 658 | s->range_table = &range_atmio16d_ai_unipolar; |
| 659 | break; |
| 660 | } |
H Hartley Sweeten | ec9b2f4 | 2013-11-26 16:42:30 -0700 | [diff] [blame] | 661 | if (dev->irq) { |
| 662 | dev->read_subdev = s; |
| 663 | s->subdev_flags |= SDF_CMD_READ; |
| 664 | s->len_chanlist = 16; |
| 665 | s->do_cmdtest = atmio16d_ai_cmdtest; |
| 666 | s->do_cmd = atmio16d_ai_cmd; |
| 667 | s->cancel = atmio16d_ai_cancel; |
| 668 | } |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 669 | |
| 670 | /* ao subdevice */ |
H Hartley Sweeten | 3f507ce | 2012-09-05 18:48:58 -0700 | [diff] [blame] | 671 | s = &dev->subdevices[1]; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 672 | s->type = COMEDI_SUBD_AO; |
| 673 | s->subdev_flags = SDF_WRITABLE; |
| 674 | s->n_chan = 2; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 675 | s->maxdata = 0xfff; /* 4095 decimal */ |
| 676 | s->range_table_list = devpriv->ao_range_type_list; |
| 677 | switch (devpriv->dac0_range) { |
| 678 | case dac_bipolar: |
| 679 | devpriv->ao_range_type_list[0] = &range_bipolar10; |
| 680 | break; |
| 681 | case dac_unipolar: |
| 682 | devpriv->ao_range_type_list[0] = &range_unipolar10; |
| 683 | break; |
| 684 | } |
| 685 | switch (devpriv->dac1_range) { |
| 686 | case dac_bipolar: |
| 687 | devpriv->ao_range_type_list[1] = &range_bipolar10; |
| 688 | break; |
| 689 | case dac_unipolar: |
| 690 | devpriv->ao_range_type_list[1] = &range_unipolar10; |
| 691 | break; |
| 692 | } |
H Hartley Sweeten | e892875 | 2014-08-25 16:04:27 -0700 | [diff] [blame] | 693 | s->insn_write = atmio16d_ao_insn_write; |
H Hartley Sweeten | e892875 | 2014-08-25 16:04:27 -0700 | [diff] [blame] | 694 | |
| 695 | ret = comedi_alloc_subdev_readback(s); |
| 696 | if (ret) |
| 697 | return ret; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 698 | |
| 699 | /* Digital I/O */ |
H Hartley Sweeten | 3f507ce | 2012-09-05 18:48:58 -0700 | [diff] [blame] | 700 | s = &dev->subdevices[2]; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 701 | s->type = COMEDI_SUBD_DIO; |
| 702 | s->subdev_flags = SDF_WRITABLE | SDF_READABLE; |
| 703 | s->n_chan = 8; |
| 704 | s->insn_bits = atmio16d_dio_insn_bits; |
| 705 | s->insn_config = atmio16d_dio_insn_config; |
| 706 | s->maxdata = 1; |
| 707 | s->range_table = &range_digital; |
| 708 | |
| 709 | /* 8255 subdevice */ |
H Hartley Sweeten | 3f507ce | 2012-09-05 18:48:58 -0700 | [diff] [blame] | 710 | s = &dev->subdevices[3]; |
H Hartley Sweeten | e6439a4 | 2014-02-03 10:43:25 -0700 | [diff] [blame] | 711 | if (board->has_8255) { |
H Hartley Sweeten | 4085e93 | 2014-08-12 11:41:26 -0700 | [diff] [blame] | 712 | ret = subdev_8255_init(dev, s, NULL, 0x00); |
H Hartley Sweeten | e6439a4 | 2014-02-03 10:43:25 -0700 | [diff] [blame] | 713 | if (ret) |
| 714 | return ret; |
| 715 | } else { |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 716 | s->type = COMEDI_SUBD_UNUSED; |
H Hartley Sweeten | e6439a4 | 2014-02-03 10:43:25 -0700 | [diff] [blame] | 717 | } |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 718 | |
| 719 | /* don't yet know how to deal with counter/timers */ |
| 720 | #if 0 |
H Hartley Sweeten | 3f507ce | 2012-09-05 18:48:58 -0700 | [diff] [blame] | 721 | s = &dev->subdevices[4]; |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 722 | /* do */ |
| 723 | s->type = COMEDI_SUBD_TIMER; |
| 724 | s->n_chan = 0; |
| 725 | s->maxdata = 0 |
| 726 | #endif |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 727 | |
| 728 | return 0; |
| 729 | } |
| 730 | |
H Hartley Sweeten | 484ecc9 | 2012-05-17 17:11:14 -0700 | [diff] [blame] | 731 | static void atmio16d_detach(struct comedi_device *dev) |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 732 | { |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 733 | reset_atmio16d(dev); |
H Hartley Sweeten | a32c6d0 | 2013-04-18 14:34:19 -0700 | [diff] [blame] | 734 | comedi_legacy_detach(dev); |
Chris R. Baugher | 2323b27 | 2009-02-19 10:03:23 -0800 | [diff] [blame] | 735 | } |
Arun Thomas | 90f703d | 2010-06-06 22:23:29 +0200 | [diff] [blame] | 736 | |
H Hartley Sweeten | fbf0e45 | 2012-05-15 17:28:53 -0700 | [diff] [blame] | 737 | static const struct atmio16_board_t atmio16_boards[] = { |
| 738 | { |
| 739 | .name = "atmio16", |
| 740 | .has_8255 = 0, |
| 741 | }, { |
| 742 | .name = "atmio16d", |
| 743 | .has_8255 = 1, |
| 744 | }, |
| 745 | }; |
| 746 | |
| 747 | static struct comedi_driver atmio16d_driver = { |
| 748 | .driver_name = "atmio16", |
| 749 | .module = THIS_MODULE, |
| 750 | .attach = atmio16d_attach, |
| 751 | .detach = atmio16d_detach, |
| 752 | .board_name = &atmio16_boards[0].name, |
| 753 | .num_names = ARRAY_SIZE(atmio16_boards), |
| 754 | .offset = sizeof(struct atmio16_board_t), |
| 755 | }; |
| 756 | module_comedi_driver(atmio16d_driver); |
| 757 | |
Arun Thomas | 90f703d | 2010-06-06 22:23:29 +0200 | [diff] [blame] | 758 | MODULE_AUTHOR("Comedi http://www.comedi.org"); |
| 759 | MODULE_DESCRIPTION("Comedi low-level driver"); |
| 760 | MODULE_LICENSE("GPL"); |