staging/comedi: Use dev_ printks in drivers/ii_pci20kc.c
[deliverable/linux.git] / drivers / staging / comedi / drivers / dt9812.c
CommitLineData
63274cd7
AB
1/*
2 * comedi/drivers/dt9812.c
3 * COMEDI driver for DataTranslation DT9812 USB module
4 *
5 * Copyright (C) 2005 Anders Blomdell <anders.blomdell@control.lth.se>
6 *
7 * COMEDI - Linux Control and Measurement Device Interface
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25/*
26Driver: dt9812
27Description: Data Translation DT9812 USB module
28Author: anders.blomdell@control.lth.se (Anders Blomdell)
29Status: in development
30Devices: [Data Translation] DT9812 (dt9812)
31Updated: Sun Nov 20 20:18:34 EST 2005
32
33This driver works, but bulk transfers not implemented. Might be a starting point
34for someone else. I found out too late that USB has too high latencies (>1 ms)
35for my needs.
36*/
37
38/*
39 * Nota Bene:
40 * 1. All writes to command pipe has to be 32 bytes (ISP1181B SHRTP=0 ?)
41 * 2. The DDK source (as of sep 2005) is in error regarding the
42 * input MUX bits (example code says P4, but firmware schematics
43 * says P1).
44 */
45
63274cd7
AB
46#include <linux/kernel.h>
47#include <linux/errno.h>
48#include <linux/init.h>
49#include <linux/slab.h>
50#include <linux/module.h>
51#include <linux/kref.h>
f52a8af7 52#include <linux/uaccess.h>
63274cd7 53#include <linux/usb.h>
f52a8af7 54
63274cd7 55#include "../comedidev.h"
c73190fa
GKH
56
57#define DT9812_DIAGS_BOARD_INFO_ADDR 0xFBFF
58#define DT9812_MAX_WRITE_CMD_PIPE_SIZE 32
59#define DT9812_MAX_READ_CMD_PIPE_SIZE 32
60
61/*
62 * See Silican Laboratories C8051F020/1/2/3 manual
63 */
64#define F020_SFR_P4 0x84
65#define F020_SFR_P1 0x90
66#define F020_SFR_P2 0xa0
67#define F020_SFR_P3 0xb0
68#define F020_SFR_AMX0CF 0xba
69#define F020_SFR_AMX0SL 0xbb
70#define F020_SFR_ADC0CF 0xbc
71#define F020_SFR_ADC0L 0xbe
72#define F020_SFR_ADC0H 0xbf
73#define F020_SFR_DAC0L 0xd2
74#define F020_SFR_DAC0H 0xd3
75#define F020_SFR_DAC0CN 0xd4
76#define F020_SFR_DAC1L 0xd5
77#define F020_SFR_DAC1H 0xd6
78#define F020_SFR_DAC1CN 0xd7
79#define F020_SFR_ADC0CN 0xe8
80
81#define F020_MASK_ADC0CF_AMP0GN0 0x01
82#define F020_MASK_ADC0CF_AMP0GN1 0x02
83#define F020_MASK_ADC0CF_AMP0GN2 0x04
84
85#define F020_MASK_ADC0CN_AD0EN 0x80
86#define F020_MASK_ADC0CN_AD0INT 0x20
87#define F020_MASK_ADC0CN_AD0BUSY 0x10
88
89#define F020_MASK_DACxCN_DACxEN 0x80
90
98f3c672 91enum {
0a85b6f0 92 /* A/D D/A DI DO CT */
c73190fa 93 DT9812_DEVID_DT9812_10, /* 8 2 8 8 1 +/- 10V */
0a85b6f0 94 DT9812_DEVID_DT9812_2PT5, /* 8 2 8 8 1 0-2.44V */
c73190fa
GKH
95#if 0
96 DT9812_DEVID_DT9813, /* 16 2 4 4 1 +/- 10V */
97 DT9812_DEVID_DT9814 /* 24 2 0 0 1 +/- 10V */
98#endif
98f3c672 99};
c73190fa 100
98f3c672 101enum dt9812_gain {
c73190fa
GKH
102 DT9812_GAIN_0PT25 = 1,
103 DT9812_GAIN_0PT5 = 2,
104 DT9812_GAIN_1 = 4,
105 DT9812_GAIN_2 = 8,
106 DT9812_GAIN_4 = 16,
107 DT9812_GAIN_8 = 32,
108 DT9812_GAIN_16 = 64,
98f3c672 109};
c73190fa 110
98f3c672 111enum {
c73190fa
GKH
112 DT9812_LEAST_USB_FIRMWARE_CMD_CODE = 0,
113 /* Write Flash memory */
114 DT9812_W_FLASH_DATA = 0,
115 /* Read Flash memory misc config info */
116 DT9812_R_FLASH_DATA = 1,
117
118 /*
119 * Register read/write commands for processor
120 */
121
122 /* Read a single byte of USB memory */
123 DT9812_R_SINGLE_BYTE_REG = 2,
124 /* Write a single byte of USB memory */
125 DT9812_W_SINGLE_BYTE_REG = 3,
126 /* Multiple Reads of USB memory */
127 DT9812_R_MULTI_BYTE_REG = 4,
128 /* Multiple Writes of USB memory */
129 DT9812_W_MULTI_BYTE_REG = 5,
130 /* Read, (AND) with mask, OR value, then write (single) */
131 DT9812_RMW_SINGLE_BYTE_REG = 6,
132 /* Read, (AND) with mask, OR value, then write (multiple) */
133 DT9812_RMW_MULTI_BYTE_REG = 7,
134
135 /*
136 * Register read/write commands for SMBus
137 */
138
139 /* Read a single byte of SMBus */
140 DT9812_R_SINGLE_BYTE_SMBUS = 8,
141 /* Write a single byte of SMBus */
142 DT9812_W_SINGLE_BYTE_SMBUS = 9,
143 /* Multiple Reads of SMBus */
144 DT9812_R_MULTI_BYTE_SMBUS = 10,
145 /* Multiple Writes of SMBus */
146 DT9812_W_MULTI_BYTE_SMBUS = 11,
147
148 /*
149 * Register read/write commands for a device
150 */
151
152 /* Read a single byte of a device */
153 DT9812_R_SINGLE_BYTE_DEV = 12,
154 /* Write a single byte of a device */
155 DT9812_W_SINGLE_BYTE_DEV = 13,
156 /* Multiple Reads of a device */
157 DT9812_R_MULTI_BYTE_DEV = 14,
158 /* Multiple Writes of a device */
159 DT9812_W_MULTI_BYTE_DEV = 15,
160
161 /* Not sure if we'll need this */
162 DT9812_W_DAC_THRESHOLD = 16,
163
164 /* Set interrupt on change mask */
165 DT9812_W_INT_ON_CHANGE_MASK = 17,
166
167 /* Write (or Clear) the CGL for the ADC */
168 DT9812_W_CGL = 18,
169 /* Multiple Reads of USB memory */
170 DT9812_R_MULTI_BYTE_USBMEM = 19,
171 /* Multiple Writes to USB memory */
172 DT9812_W_MULTI_BYTE_USBMEM = 20,
173
174 /* Issue a start command to a given subsystem */
175 DT9812_START_SUBSYSTEM = 21,
176 /* Issue a stop command to a given subsystem */
177 DT9812_STOP_SUBSYSTEM = 22,
178
179 /* calibrate the board using CAL_POT_CMD */
180 DT9812_CALIBRATE_POT = 23,
181 /* set the DAC FIFO size */
182 DT9812_W_DAC_FIFO_SIZE = 24,
183 /* Write or Clear the CGL for the DAC */
184 DT9812_W_CGL_DAC = 25,
185 /* Read a single value from a subsystem */
186 DT9812_R_SINGLE_VALUE_CMD = 26,
187 /* Write a single value to a subsystem */
188 DT9812_W_SINGLE_VALUE_CMD = 27,
189 /* Valid DT9812_USB_FIRMWARE_CMD_CODE's will be less than this number */
190 DT9812_MAX_USB_FIRMWARE_CMD_CODE,
98f3c672 191};
c73190fa 192
98f3c672 193struct dt9812_flash_data {
c73190fa
GKH
194 u16 numbytes;
195 u16 address;
98f3c672 196};
c73190fa
GKH
197
198#define DT9812_MAX_NUM_MULTI_BYTE_RDS \
65c5cfa6 199 ((DT9812_MAX_WRITE_CMD_PIPE_SIZE - 4 - 1) / sizeof(u8))
c73190fa 200
98f3c672 201struct dt9812_read_multi {
c73190fa
GKH
202 u8 count;
203 u8 address[DT9812_MAX_NUM_MULTI_BYTE_RDS];
98f3c672 204};
c73190fa 205
98f3c672 206struct dt9812_write_byte {
c73190fa
GKH
207 u8 address;
208 u8 value;
98f3c672 209};
c73190fa
GKH
210
211#define DT9812_MAX_NUM_MULTI_BYTE_WRTS \
65c5cfa6
RKM
212 ((DT9812_MAX_WRITE_CMD_PIPE_SIZE - 4 - 1) / \
213 sizeof(struct dt9812_write_byte))
c73190fa 214
98f3c672 215struct dt9812_write_multi {
c73190fa 216 u8 count;
98f3c672
GKH
217 struct dt9812_write_byte write[DT9812_MAX_NUM_MULTI_BYTE_WRTS];
218};
c73190fa 219
98f3c672 220struct dt9812_rmw_byte {
c73190fa
GKH
221 u8 address;
222 u8 and_mask;
223 u8 or_value;
98f3c672 224};
c73190fa
GKH
225
226#define DT9812_MAX_NUM_MULTI_BYTE_RMWS \
65c5cfa6
RKM
227 ((DT9812_MAX_WRITE_CMD_PIPE_SIZE - 4 - 1) / \
228 sizeof(struct dt9812_rmw_byte))
c73190fa 229
98f3c672 230struct dt9812_rmw_multi {
c73190fa 231 u8 count;
98f3c672
GKH
232 struct dt9812_rmw_byte rmw[DT9812_MAX_NUM_MULTI_BYTE_RMWS];
233};
c73190fa 234
98f3c672 235struct dt9812_usb_cmd {
c73190fa
GKH
236 u32 cmd;
237 union {
98f3c672
GKH
238 struct dt9812_flash_data flash_data_info;
239 struct dt9812_read_multi read_multi_info;
240 struct dt9812_write_multi write_multi_info;
241 struct dt9812_rmw_multi rmw_multi_info;
c73190fa
GKH
242 } u;
243#if 0
244 WRITE_BYTE_INFO WriteByteInfo;
245 READ_BYTE_INFO ReadByteInfo;
246 WRITE_MULTI_INFO WriteMultiInfo;
247 READ_MULTI_INFO ReadMultiInfo;
248 RMW_BYTE_INFO RMWByteInfo;
249 RMW_MULTI_INFO RMWMultiInfo;
250 DAC_THRESHOLD_INFO DacThresholdInfo;
251 INT_ON_CHANGE_MASK_INFO IntOnChangeMaskInfo;
252 CGL_INFO CglInfo;
253 SUBSYSTEM_INFO SubsystemInfo;
254 CAL_POT_CMD CalPotCmd;
255 WRITE_DEV_BYTE_INFO WriteDevByteInfo;
256 READ_DEV_BYTE_INFO ReadDevByteInfo;
257 WRITE_DEV_MULTI_INFO WriteDevMultiInfo;
258 READ_DEV_MULTI_INFO ReadDevMultiInfo;
259 READ_SINGLE_VALUE_INFO ReadSingleValueInfo;
260 WRITE_SINGLE_VALUE_INFO WriteSingleValueInfo;
261#endif
98f3c672 262};
63274cd7 263
f52a8af7 264#define DT9812_NUM_SLOTS 16
63274cd7 265
45f4d024 266static DEFINE_SEMAPHORE(dt9812_mutex);
63274cd7 267
a457732b 268static const struct usb_device_id dt9812_table[] = {
63274cd7 269 {USB_DEVICE(0x0867, 0x9812)},
0a85b6f0 270 {} /* Terminating entry */
63274cd7
AB
271};
272
273MODULE_DEVICE_TABLE(usb, dt9812_table);
274
98f3c672 275struct usb_dt9812 {
63274cd7
AB
276 struct slot_dt9812 *slot;
277 struct usb_device *udev;
278 struct usb_interface *interface;
279 u16 vendor;
280 u16 product;
281 u16 device;
282 u32 serial;
283 struct {
284 __u8 addr;
285 size_t size;
286 } message_pipe, command_write, command_read, write_stream, read_stream;
287 struct kref kref;
288 u16 analog_out_shadow[2];
289 u8 digital_out_shadow;
98f3c672 290};
63274cd7 291
98f3c672 292struct comedi_dt9812 {
63274cd7
AB
293 struct slot_dt9812 *slot;
294 u32 serial;
98f3c672 295};
63274cd7 296
98f3c672 297struct slot_dt9812 {
63274cd7
AB
298 struct semaphore mutex;
299 u32 serial;
98f3c672
GKH
300 struct usb_dt9812 *usb;
301 struct comedi_dt9812 *comedi;
302};
63274cd7 303
9ced1de6 304static const struct comedi_lrange dt9812_10_ain_range = { 1, {
0a85b6f0
MT
305 BIP_RANGE(10),
306 }
63274cd7
AB
307};
308
9ced1de6 309static const struct comedi_lrange dt9812_2pt5_ain_range = { 1, {
0a85b6f0
MT
310 UNI_RANGE(2.5),
311 }
63274cd7
AB
312};
313
9ced1de6 314static const struct comedi_lrange dt9812_10_aout_range = { 1, {
0a85b6f0
MT
315 BIP_RANGE(10),
316 }
63274cd7
AB
317};
318
9ced1de6 319static const struct comedi_lrange dt9812_2pt5_aout_range = { 1, {
0a85b6f0
MT
320 UNI_RANGE(2.5),
321 }
63274cd7
AB
322};
323
98f3c672 324static struct slot_dt9812 dt9812[DT9812_NUM_SLOTS];
63274cd7 325
98f3c672 326static inline struct usb_dt9812 *to_dt9812_dev(struct kref *d)
63274cd7 327{
98f3c672 328 return container_of(d, struct usb_dt9812, kref);
63274cd7
AB
329}
330
331static void dt9812_delete(struct kref *kref)
332{
98f3c672 333 struct usb_dt9812 *dev = to_dt9812_dev(kref);
63274cd7
AB
334
335 usb_put_dev(dev->udev);
336 kfree(dev);
337}
338
98f3c672 339static int dt9812_read_info(struct usb_dt9812 *dev, int offset, void *buf,
f52a8af7 340 size_t buf_size)
63274cd7 341{
98f3c672 342 struct dt9812_usb_cmd cmd;
63274cd7
AB
343 int count, retval;
344
345 cmd.cmd = cpu_to_le32(DT9812_R_FLASH_DATA);
346 cmd.u.flash_data_info.address =
0a85b6f0 347 cpu_to_le16(DT9812_DIAGS_BOARD_INFO_ADDR + offset);
63274cd7
AB
348 cmd.u.flash_data_info.numbytes = cpu_to_le16(buf_size);
349
f52a8af7 350 /* DT9812 only responds to 32 byte writes!! */
63274cd7 351 count = 32;
f52a8af7
GKH
352 retval = usb_bulk_msg(dev->udev,
353 usb_sndbulkpipe(dev->udev,
354 dev->command_write.addr),
355 &cmd, 32, &count, HZ * 1);
356 if (retval)
357 return retval;
358 retval = usb_bulk_msg(dev->udev,
359 usb_rcvbulkpipe(dev->udev,
360 dev->command_read.addr),
361 buf, buf_size, &count, HZ * 1);
63274cd7
AB
362 return retval;
363}
364
98f3c672 365static int dt9812_read_multiple_registers(struct usb_dt9812 *dev, int reg_count,
a7a55d4a 366 u8 *address, u8 *value)
63274cd7 367{
98f3c672 368 struct dt9812_usb_cmd cmd;
63274cd7
AB
369 int i, count, retval;
370
371 cmd.cmd = cpu_to_le32(DT9812_R_MULTI_BYTE_REG);
372 cmd.u.read_multi_info.count = reg_count;
f52a8af7 373 for (i = 0; i < reg_count; i++)
63274cd7 374 cmd.u.read_multi_info.address[i] = address[i];
f52a8af7
GKH
375
376 /* DT9812 only responds to 32 byte writes!! */
63274cd7 377 count = 32;
f52a8af7
GKH
378 retval = usb_bulk_msg(dev->udev,
379 usb_sndbulkpipe(dev->udev,
380 dev->command_write.addr),
381 &cmd, 32, &count, HZ * 1);
382 if (retval)
383 return retval;
384 retval = usb_bulk_msg(dev->udev,
385 usb_rcvbulkpipe(dev->udev,
386 dev->command_read.addr),
387 value, reg_count, &count, HZ * 1);
63274cd7
AB
388 return retval;
389}
390
98f3c672 391static int dt9812_write_multiple_registers(struct usb_dt9812 *dev,
a7a55d4a
RKM
392 int reg_count, u8 *address,
393 u8 *value)
63274cd7 394{
98f3c672 395 struct dt9812_usb_cmd cmd;
63274cd7
AB
396 int i, count, retval;
397
398 cmd.cmd = cpu_to_le32(DT9812_W_MULTI_BYTE_REG);
399 cmd.u.read_multi_info.count = reg_count;
400 for (i = 0; i < reg_count; i++) {
401 cmd.u.write_multi_info.write[i].address = address[i];
402 cmd.u.write_multi_info.write[i].value = value[i];
403 }
f52a8af7
GKH
404 /* DT9812 only responds to 32 byte writes!! */
405 retval = usb_bulk_msg(dev->udev,
406 usb_sndbulkpipe(dev->udev,
407 dev->command_write.addr),
408 &cmd, 32, &count, HZ * 1);
63274cd7
AB
409 return retval;
410}
411
98f3c672
GKH
412static int dt9812_rmw_multiple_registers(struct usb_dt9812 *dev, int reg_count,
413 struct dt9812_rmw_byte *rmw)
63274cd7 414{
98f3c672 415 struct dt9812_usb_cmd cmd;
63274cd7
AB
416 int i, count, retval;
417
418 cmd.cmd = cpu_to_le32(DT9812_RMW_MULTI_BYTE_REG);
419 cmd.u.rmw_multi_info.count = reg_count;
f52a8af7 420 for (i = 0; i < reg_count; i++)
63274cd7 421 cmd.u.rmw_multi_info.rmw[i] = rmw[i];
f52a8af7
GKH
422
423 /* DT9812 only responds to 32 byte writes!! */
424 retval = usb_bulk_msg(dev->udev,
425 usb_sndbulkpipe(dev->udev,
426 dev->command_write.addr),
427 &cmd, 32, &count, HZ * 1);
63274cd7
AB
428 return retval;
429}
430
a7a55d4a 431static int dt9812_digital_in(struct slot_dt9812 *slot, u8 *bits)
63274cd7
AB
432{
433 int result = -ENODEV;
434
435 down(&slot->mutex);
436 if (slot->usb) {
437 u8 reg[2] = { F020_SFR_P3, F020_SFR_P1 };
438 u8 value[2];
439
440 result = dt9812_read_multiple_registers(slot->usb, 2, reg,
f52a8af7 441 value);
63274cd7 442 if (result == 0) {
f52a8af7
GKH
443 /*
444 * bits 0-6 in F020_SFR_P3 are bits 0-6 in the digital
445 * input port bit 3 in F020_SFR_P1 is bit 7 in the
446 * digital input port
447 */
63274cd7 448 *bits = (value[0] & 0x7f) | ((value[1] & 0x08) << 4);
f52a8af7 449 /* printk("%2.2x, %2.2x -> %2.2x\n",
0a85b6f0 450 value[0], value[1], *bits); */
63274cd7
AB
451 }
452 }
453 up(&slot->mutex);
454
455 return result;
456}
457
98f3c672 458static int dt9812_digital_out(struct slot_dt9812 *slot, u8 bits)
63274cd7
AB
459{
460 int result = -ENODEV;
461
462 down(&slot->mutex);
463 if (slot->usb) {
464 u8 reg[1];
465 u8 value[1];
466
467 reg[0] = F020_SFR_P2;
468 value[0] = bits;
469 result = dt9812_write_multiple_registers(slot->usb, 1, reg,
f52a8af7 470 value);
63274cd7
AB
471 slot->usb->digital_out_shadow = bits;
472 }
473 up(&slot->mutex);
474 return result;
475}
476
a7a55d4a 477static int dt9812_digital_out_shadow(struct slot_dt9812 *slot, u8 *bits)
63274cd7
AB
478{
479 int result = -ENODEV;
480
481 down(&slot->mutex);
482 if (slot->usb) {
483 *bits = slot->usb->digital_out_shadow;
484 result = 0;
485 }
486 up(&slot->mutex);
487 return result;
488}
489
98f3c672
GKH
490static void dt9812_configure_mux(struct usb_dt9812 *dev,
491 struct dt9812_rmw_byte *rmw, int channel)
63274cd7
AB
492{
493 if (dev->device == DT9812_DEVID_DT9812_10) {
f52a8af7 494 /* In the DT9812/10V MUX is selected by P1.5-7 */
63274cd7
AB
495 rmw->address = F020_SFR_P1;
496 rmw->and_mask = 0xe0;
497 rmw->or_value = channel << 5;
498 } else {
f52a8af7 499 /* In the DT9812/2.5V, internal mux is selected by bits 0:2 */
63274cd7
AB
500 rmw->address = F020_SFR_AMX0SL;
501 rmw->and_mask = 0xff;
502 rmw->or_value = channel & 0x07;
503 }
504}
505
98f3c672
GKH
506static void dt9812_configure_gain(struct usb_dt9812 *dev,
507 struct dt9812_rmw_byte *rmw,
508 enum dt9812_gain gain)
63274cd7
AB
509{
510 if (dev->device == DT9812_DEVID_DT9812_10) {
f52a8af7 511 /* In the DT9812/10V, there is an external gain of 0.5 */
63274cd7
AB
512 gain <<= 1;
513 }
514
515 rmw->address = F020_SFR_ADC0CF;
f52a8af7 516 rmw->and_mask = F020_MASK_ADC0CF_AMP0GN2 |
0a85b6f0 517 F020_MASK_ADC0CF_AMP0GN1 | F020_MASK_ADC0CF_AMP0GN0;
63274cd7 518 switch (gain) {
f52a8af7
GKH
519 /*
520 * 000 -> Gain = 1
521 * 001 -> Gain = 2
522 * 010 -> Gain = 4
523 * 011 -> Gain = 8
524 * 10x -> Gain = 16
525 * 11x -> Gain = 0.5
526 */
527 case DT9812_GAIN_0PT5:
cba2c993 528 rmw->or_value = F020_MASK_ADC0CF_AMP0GN2 |
0a85b6f0 529 F020_MASK_ADC0CF_AMP0GN1;
63274cd7 530 break;
f52a8af7
GKH
531 case DT9812_GAIN_1:
532 rmw->or_value = 0x00;
63274cd7 533 break;
f52a8af7
GKH
534 case DT9812_GAIN_2:
535 rmw->or_value = F020_MASK_ADC0CF_AMP0GN0;
63274cd7 536 break;
f52a8af7
GKH
537 case DT9812_GAIN_4:
538 rmw->or_value = F020_MASK_ADC0CF_AMP0GN1;
63274cd7 539 break;
f52a8af7 540 case DT9812_GAIN_8:
cba2c993 541 rmw->or_value = F020_MASK_ADC0CF_AMP0GN1 |
0a85b6f0 542 F020_MASK_ADC0CF_AMP0GN0;
63274cd7 543 break;
f52a8af7
GKH
544 case DT9812_GAIN_16:
545 rmw->or_value = F020_MASK_ADC0CF_AMP0GN2;
63274cd7 546 break;
f52a8af7 547 default:
923faa6a 548 dev_err(&dev->interface->dev, "Illegal gain %d\n", gain);
f52a8af7 549
63274cd7
AB
550 }
551}
552
a7a55d4a 553static int dt9812_analog_in(struct slot_dt9812 *slot, int channel, u16 *value,
98f3c672 554 enum dt9812_gain gain)
63274cd7 555{
98f3c672 556 struct dt9812_rmw_byte rmw[3];
f52a8af7
GKH
557 u8 reg[3] = {
558 F020_SFR_ADC0CN,
559 F020_SFR_ADC0H,
560 F020_SFR_ADC0L
561 };
562 u8 val[3];
63274cd7
AB
563 int result = -ENODEV;
564
565 down(&slot->mutex);
f52a8af7
GKH
566 if (!slot->usb)
567 goto exit;
568
569 /* 1 select the gain */
570 dt9812_configure_gain(slot->usb, &rmw[0], gain);
571
572 /* 2 set the MUX to select the channel */
573 dt9812_configure_mux(slot->usb, &rmw[1], channel);
574
575 /* 3 start conversion */
576 rmw[2].address = F020_SFR_ADC0CN;
577 rmw[2].and_mask = 0xff;
578 rmw[2].or_value = F020_MASK_ADC0CN_AD0EN | F020_MASK_ADC0CN_AD0BUSY;
579
580 result = dt9812_rmw_multiple_registers(slot->usb, 3, rmw);
581 if (result)
582 goto exit;
583
584 /* read the status and ADC */
585 result = dt9812_read_multiple_registers(slot->usb, 3, reg, val);
586 if (result)
587 goto exit;
588 /*
589 * An ADC conversion takes 16 SAR clocks cycles, i.e. about 9us.
590 * Therefore, between the instant that AD0BUSY was set via
591 * dt9812_rmw_multiple_registers and the read of AD0BUSY via
592 * dt9812_read_multiple_registers, the conversion should be complete
593 * since these two operations require two USB transactions each taking
594 * at least a millisecond to complete. However, lets make sure that
595 * conversion is finished.
596 */
597 if ((val[0] & (F020_MASK_ADC0CN_AD0INT | F020_MASK_ADC0CN_AD0BUSY)) ==
598 F020_MASK_ADC0CN_AD0INT) {
599 switch (slot->usb->device) {
600 case DT9812_DEVID_DT9812_10:
601 /*
602 * For DT9812-10V the personality module set the
603 * encoding to 2's complement. Hence, convert it before
604 * returning it
605 */
606 *value = ((val[1] << 8) | val[2]) + 0x800;
607 break;
608 case DT9812_DEVID_DT9812_2PT5:
609 *value = (val[1] << 8) | val[2];
610 break;
63274cd7
AB
611 }
612 }
f52a8af7
GKH
613
614exit:
63274cd7
AB
615 up(&slot->mutex);
616 return result;
617}
618
98f3c672 619static int dt9812_analog_out_shadow(struct slot_dt9812 *slot, int channel,
a7a55d4a 620 u16 *value)
63274cd7
AB
621{
622 int result = -ENODEV;
623
624 down(&slot->mutex);
625 if (slot->usb) {
626 *value = slot->usb->analog_out_shadow[channel];
627 result = 0;
628 }
629 up(&slot->mutex);
630
631 return result;
632}
633
98f3c672 634static int dt9812_analog_out(struct slot_dt9812 *slot, int channel, u16 value)
63274cd7
AB
635{
636 int result = -ENODEV;
637
638 down(&slot->mutex);
639 if (slot->usb) {
98f3c672 640 struct dt9812_rmw_byte rmw[3];
63274cd7
AB
641
642 switch (channel) {
f52a8af7
GKH
643 case 0:
644 /* 1. Set DAC mode */
645 rmw[0].address = F020_SFR_DAC0CN;
646 rmw[0].and_mask = 0xff;
647 rmw[0].or_value = F020_MASK_DACxCN_DACxEN;
648
649 /* 2 load low byte of DAC value first */
650 rmw[1].address = F020_SFR_DAC0L;
651 rmw[1].and_mask = 0xff;
652 rmw[1].or_value = value & 0xff;
653
654 /* 3 load high byte of DAC value next to latch the
655 12-bit value */
656 rmw[2].address = F020_SFR_DAC0H;
657 rmw[2].and_mask = 0xff;
658 rmw[2].or_value = (value >> 8) & 0xf;
63274cd7 659 break;
f52a8af7
GKH
660
661 case 1:
662 /* 1. Set DAC mode */
663 rmw[0].address = F020_SFR_DAC1CN;
664 rmw[0].and_mask = 0xff;
665 rmw[0].or_value = F020_MASK_DACxCN_DACxEN;
666
667 /* 2 load low byte of DAC value first */
668 rmw[1].address = F020_SFR_DAC1L;
669 rmw[1].and_mask = 0xff;
670 rmw[1].or_value = value & 0xff;
671
672 /* 3 load high byte of DAC value next to latch the
673 12-bit value */
674 rmw[2].address = F020_SFR_DAC1H;
675 rmw[2].and_mask = 0xff;
676 rmw[2].or_value = (value >> 8) & 0xf;
63274cd7
AB
677 break;
678 }
679 result = dt9812_rmw_multiple_registers(slot->usb, 3, rmw);
680 slot->usb->analog_out_shadow[channel] = value;
681 }
682 up(&slot->mutex);
683
684 return result;
685}
686
687/*
688 * USB framework functions
689 */
690
691static int dt9812_probe(struct usb_interface *interface,
f52a8af7 692 const struct usb_device_id *id)
63274cd7
AB
693{
694 int retval = -ENOMEM;
98f3c672 695 struct usb_dt9812 *dev = NULL;
63274cd7
AB
696 struct usb_host_interface *iface_desc;
697 struct usb_endpoint_descriptor *endpoint;
698 int i;
699 u8 fw;
700
f52a8af7 701 /* allocate memory for our device state and initialize it */
63274cd7
AB
702 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
703 if (dev == NULL) {
f52a8af7 704 dev_err(&interface->dev, "Out of memory\n");
63274cd7
AB
705 goto error;
706 }
707 kref_init(&dev->kref);
708
709 dev->udev = usb_get_dev(interface_to_usbdev(interface));
710 dev->interface = interface;
711
f52a8af7 712 /* Check endpoints */
63274cd7
AB
713 iface_desc = interface->cur_altsetting;
714
715 if (iface_desc->desc.bNumEndpoints != 5) {
923faa6a 716 dev_err(&interface->dev, "Wrong number of endpoints.\n");
63274cd7
AB
717 retval = -ENODEV;
718 goto error;
719 }
720
721 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
722 int direction = -1;
723 endpoint = &iface_desc->endpoint[i].desc;
724 switch (i) {
f52a8af7
GKH
725 case 0:
726 direction = USB_DIR_IN;
727 dev->message_pipe.addr = endpoint->bEndpointAddress;
728 dev->message_pipe.size =
0a85b6f0 729 le16_to_cpu(endpoint->wMaxPacketSize);
f52a8af7 730
63274cd7 731 break;
f52a8af7
GKH
732 case 1:
733 direction = USB_DIR_OUT;
734 dev->command_write.addr = endpoint->bEndpointAddress;
735 dev->command_write.size =
0a85b6f0 736 le16_to_cpu(endpoint->wMaxPacketSize);
63274cd7 737 break;
f52a8af7
GKH
738 case 2:
739 direction = USB_DIR_IN;
740 dev->command_read.addr = endpoint->bEndpointAddress;
741 dev->command_read.size =
0a85b6f0 742 le16_to_cpu(endpoint->wMaxPacketSize);
63274cd7 743 break;
f52a8af7
GKH
744 case 3:
745 direction = USB_DIR_OUT;
746 dev->write_stream.addr = endpoint->bEndpointAddress;
747 dev->write_stream.size =
0a85b6f0 748 le16_to_cpu(endpoint->wMaxPacketSize);
63274cd7 749 break;
f52a8af7
GKH
750 case 4:
751 direction = USB_DIR_IN;
752 dev->read_stream.addr = endpoint->bEndpointAddress;
753 dev->read_stream.size =
0a85b6f0 754 le16_to_cpu(endpoint->wMaxPacketSize);
63274cd7
AB
755 break;
756 }
757 if ((endpoint->bEndpointAddress & USB_DIR_IN) != direction) {
f52a8af7
GKH
758 dev_err(&interface->dev,
759 "Endpoint has wrong direction.\n");
63274cd7
AB
760 retval = -ENODEV;
761 goto error;
762 }
763 }
764 if (dt9812_read_info(dev, 0, &fw, sizeof(fw)) != 0) {
f52a8af7
GKH
765 /*
766 * Seems like a configuration reset is necessary if driver is
767 * reloaded while device is attached
768 */
63274cd7
AB
769 usb_reset_configuration(dev->udev);
770 for (i = 0; i < 10; i++) {
771 retval = dt9812_read_info(dev, 1, &fw, sizeof(fw));
772 if (retval == 0) {
f52a8af7 773 dev_info(&interface->dev,
25985edc 774 "usb_reset_configuration succeeded "
f52a8af7 775 "after %d iterations\n", i);
63274cd7
AB
776 break;
777 }
778 }
779 }
780
781 if (dt9812_read_info(dev, 1, &dev->vendor, sizeof(dev->vendor)) != 0) {
923faa6a 782 dev_err(&interface->dev, "Failed to read vendor.\n");
63274cd7
AB
783 retval = -ENODEV;
784 goto error;
785 }
0a85b6f0 786 if (dt9812_read_info(dev, 3, &dev->product, sizeof(dev->product)) != 0) {
923faa6a 787 dev_err(&interface->dev, "Failed to read product.\n");
63274cd7
AB
788 retval = -ENODEV;
789 goto error;
790 }
791 if (dt9812_read_info(dev, 5, &dev->device, sizeof(dev->device)) != 0) {
923faa6a 792 dev_err(&interface->dev, "Failed to read device.\n");
63274cd7
AB
793 retval = -ENODEV;
794 goto error;
795 }
796 if (dt9812_read_info(dev, 7, &dev->serial, sizeof(dev->serial)) != 0) {
923faa6a 797 dev_err(&interface->dev, "Failed to read serial.\n");
63274cd7
AB
798 retval = -ENODEV;
799 goto error;
800 }
801
802 dev->vendor = le16_to_cpu(dev->vendor);
803 dev->product = le16_to_cpu(dev->product);
804 dev->device = le16_to_cpu(dev->device);
805 dev->serial = le32_to_cpu(dev->serial);
806 switch (dev->device) {
f52a8af7
GKH
807 case DT9812_DEVID_DT9812_10:
808 dev->analog_out_shadow[0] = 0x0800;
809 dev->analog_out_shadow[1] = 0x800;
63274cd7 810 break;
f52a8af7
GKH
811 case DT9812_DEVID_DT9812_2PT5:
812 dev->analog_out_shadow[0] = 0x0000;
813 dev->analog_out_shadow[1] = 0x0000;
63274cd7
AB
814 break;
815 }
816 dev->digital_out_shadow = 0;
817
f52a8af7 818 /* save our data pointer in this interface device */
63274cd7
AB
819 usb_set_intfdata(interface, dev);
820
f52a8af7 821 /* let the user know what node this device is now attached to */
63274cd7
AB
822 dev_info(&interface->dev, "USB DT9812 (%4.4x.%4.4x.%4.4x) #0x%8.8x\n",
823 dev->vendor, dev->product, dev->device, dev->serial);
824
825 down(&dt9812_mutex);
826 {
f52a8af7 827 /* Find a slot for the USB device */
98f3c672
GKH
828 struct slot_dt9812 *first = NULL;
829 struct slot_dt9812 *best = NULL;
63274cd7
AB
830
831 for (i = 0; i < DT9812_NUM_SLOTS; i++) {
f52a8af7 832 if (!first && !dt9812[i].usb && dt9812[i].serial == 0)
63274cd7 833 first = &dt9812[i];
f52a8af7 834 if (!best && dt9812[i].serial == dev->serial)
63274cd7 835 best = &dt9812[i];
63274cd7
AB
836 }
837
f52a8af7 838 if (!best)
63274cd7 839 best = first;
63274cd7
AB
840
841 if (best) {
842 down(&best->mutex);
843 best->usb = dev;
844 dev->slot = best;
845 up(&best->mutex);
846 }
847 }
848 up(&dt9812_mutex);
849
850 return 0;
851
f52a8af7
GKH
852error:
853 if (dev)
63274cd7 854 kref_put(&dev->kref, dt9812_delete);
63274cd7
AB
855 return retval;
856}
857
858static void dt9812_disconnect(struct usb_interface *interface)
859{
98f3c672 860 struct usb_dt9812 *dev;
63274cd7
AB
861 int minor = interface->minor;
862
863 down(&dt9812_mutex);
864 dev = usb_get_intfdata(interface);
865 if (dev->slot) {
866 down(&dev->slot->mutex);
867 dev->slot->usb = NULL;
868 up(&dev->slot->mutex);
869 dev->slot = NULL;
870 }
871 usb_set_intfdata(interface, NULL);
872 up(&dt9812_mutex);
873
874 /* queue final destruction */
875 kref_put(&dev->kref, dt9812_delete);
876
877 dev_info(&interface->dev, "USB Dt9812 #%d now disconnected\n", minor);
878}
879
880static struct usb_driver dt9812_usb_driver = {
63274cd7
AB
881 .name = "dt9812",
882 .probe = dt9812_probe,
883 .disconnect = dt9812_disconnect,
884 .id_table = dt9812_table,
885};
886
887/*
888 * Comedi functions
889 */
890
3c17ba07 891static int dt9812_comedi_open(struct comedi_device *dev)
63274cd7 892{
9a1a6cf8 893 struct comedi_dt9812 *devpriv = dev->private;
3c17ba07
IA
894 int result = -ENODEV;
895
63274cd7
AB
896 down(&devpriv->slot->mutex);
897 if (devpriv->slot->usb) {
f52a8af7 898 /* We have an attached device, fill in current range info */
34c43922 899 struct comedi_subdevice *s;
63274cd7
AB
900
901 s = &dev->subdevices[0];
902 s->n_chan = 8;
903 s->maxdata = 1;
904
905 s = &dev->subdevices[1];
906 s->n_chan = 8;
907 s->maxdata = 1;
908
909 s = &dev->subdevices[2];
910 s->n_chan = 8;
911 switch (devpriv->slot->usb->device) {
912 case 0:{
913 s->maxdata = 4095;
914 s->range_table = &dt9812_10_ain_range;
915 }
916 break;
917 case 1:{
918 s->maxdata = 4095;
919 s->range_table = &dt9812_2pt5_ain_range;
920 }
921 break;
922 }
923
924 s = &dev->subdevices[3];
925 s->n_chan = 2;
926 switch (devpriv->slot->usb->device) {
927 case 0:{
928 s->maxdata = 4095;
929 s->range_table = &dt9812_10_aout_range;
930 }
931 break;
932 case 1:{
933 s->maxdata = 4095;
934 s->range_table = &dt9812_2pt5_aout_range;
935 }
936 break;
937 }
3c17ba07 938 result = 0;
63274cd7
AB
939 }
940 up(&devpriv->slot->mutex);
3c17ba07 941 return result;
63274cd7
AB
942}
943
0a85b6f0
MT
944static int dt9812_di_rinsn(struct comedi_device *dev,
945 struct comedi_subdevice *s, struct comedi_insn *insn,
946 unsigned int *data)
63274cd7 947{
9a1a6cf8 948 struct comedi_dt9812 *devpriv = dev->private;
63274cd7
AB
949 int n;
950 u8 bits = 0;
951
952 dt9812_digital_in(devpriv->slot, &bits);
f52a8af7 953 for (n = 0; n < insn->n; n++)
63274cd7 954 data[n] = ((1 << insn->chanspec) & bits) != 0;
63274cd7
AB
955 return n;
956}
957
0a85b6f0
MT
958static int dt9812_do_winsn(struct comedi_device *dev,
959 struct comedi_subdevice *s, struct comedi_insn *insn,
960 unsigned int *data)
63274cd7 961{
9a1a6cf8 962 struct comedi_dt9812 *devpriv = dev->private;
63274cd7
AB
963 int n;
964 u8 bits = 0;
965
966 dt9812_digital_out_shadow(devpriv->slot, &bits);
967 for (n = 0; n < insn->n; n++) {
968 u8 mask = 1 << insn->chanspec;
969
970 bits &= ~mask;
f52a8af7 971 if (data[n])
63274cd7 972 bits |= mask;
63274cd7
AB
973 }
974 dt9812_digital_out(devpriv->slot, bits);
975 return n;
976}
977
0a85b6f0
MT
978static int dt9812_ai_rinsn(struct comedi_device *dev,
979 struct comedi_subdevice *s, struct comedi_insn *insn,
980 unsigned int *data)
63274cd7 981{
9a1a6cf8 982 struct comedi_dt9812 *devpriv = dev->private;
63274cd7
AB
983 int n;
984
985 for (n = 0; n < insn->n; n++) {
986 u16 value = 0;
987
988 dt9812_analog_in(devpriv->slot, insn->chanspec, &value,
f52a8af7 989 DT9812_GAIN_1);
63274cd7
AB
990 data[n] = value;
991 }
992 return n;
993}
994
0a85b6f0
MT
995static int dt9812_ao_rinsn(struct comedi_device *dev,
996 struct comedi_subdevice *s, struct comedi_insn *insn,
997 unsigned int *data)
63274cd7 998{
9a1a6cf8 999 struct comedi_dt9812 *devpriv = dev->private;
63274cd7 1000 int n;
f52a8af7 1001 u16 value;
63274cd7
AB
1002
1003 for (n = 0; n < insn->n; n++) {
f52a8af7 1004 value = 0;
63274cd7
AB
1005 dt9812_analog_out_shadow(devpriv->slot, insn->chanspec, &value);
1006 data[n] = value;
1007 }
1008 return n;
1009}
1010
0a85b6f0
MT
1011static int dt9812_ao_winsn(struct comedi_device *dev,
1012 struct comedi_subdevice *s, struct comedi_insn *insn,
1013 unsigned int *data)
63274cd7 1014{
9a1a6cf8 1015 struct comedi_dt9812 *devpriv = dev->private;
63274cd7
AB
1016 int n;
1017
f52a8af7 1018 for (n = 0; n < insn->n; n++)
63274cd7 1019 dt9812_analog_out(devpriv->slot, insn->chanspec, data[n]);
63274cd7
AB
1020 return n;
1021}
1022
0707bb04 1023static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
63274cd7 1024{
9a1a6cf8 1025 struct comedi_dt9812 *devpriv;
63274cd7 1026 int i;
34c43922 1027 struct comedi_subdevice *s;
8b6c5694 1028 int ret;
63274cd7
AB
1029
1030 dev->board_name = "dt9812";
1031
9a1a6cf8
HS
1032 ret = alloc_private(dev, sizeof(*devpriv));
1033 if (ret)
1034 return ret;
1035 devpriv = dev->private;
f52a8af7
GKH
1036
1037 /*
1038 * Special open routine, since USB unit may be unattached at
1039 * comedi_config time, hence range can not be determined
1040 */
63274cd7
AB
1041 dev->open = dt9812_comedi_open;
1042
1043 devpriv->serial = it->options[0];
1044
8b6c5694
HS
1045 ret = comedi_alloc_subdevices(dev, 4);
1046 if (ret)
1047 return ret;
63274cd7
AB
1048
1049 /* digital input subdevice */
3a207891 1050 s = &dev->subdevices[0];
63274cd7
AB
1051 s->type = COMEDI_SUBD_DI;
1052 s->subdev_flags = SDF_READABLE;
1053 s->n_chan = 0;
1054 s->maxdata = 1;
1055 s->range_table = &range_digital;
1056 s->insn_read = &dt9812_di_rinsn;
1057
1058 /* digital output subdevice */
3a207891 1059 s = &dev->subdevices[1];
63274cd7
AB
1060 s->type = COMEDI_SUBD_DO;
1061 s->subdev_flags = SDF_WRITEABLE;
1062 s->n_chan = 0;
1063 s->maxdata = 1;
1064 s->range_table = &range_digital;
1065 s->insn_write = &dt9812_do_winsn;
1066
1067 /* analog input subdevice */
3a207891 1068 s = &dev->subdevices[2];
63274cd7
AB
1069 s->type = COMEDI_SUBD_AI;
1070 s->subdev_flags = SDF_READABLE | SDF_GROUND;
1071 s->n_chan = 0;
1072 s->maxdata = 1;
b1853a4f 1073 s->range_table = NULL;
63274cd7
AB
1074 s->insn_read = &dt9812_ai_rinsn;
1075
1076 /* analog output subdevice */
3a207891 1077 s = &dev->subdevices[3];
63274cd7
AB
1078 s->type = COMEDI_SUBD_AO;
1079 s->subdev_flags = SDF_WRITEABLE;
1080 s->n_chan = 0;
1081 s->maxdata = 1;
b1853a4f 1082 s->range_table = NULL;
63274cd7
AB
1083 s->insn_write = &dt9812_ao_winsn;
1084 s->insn_read = &dt9812_ao_rinsn;
1085
f52a8af7
GKH
1086 printk(KERN_INFO "comedi%d: successfully attached to dt9812.\n",
1087 dev->minor);
63274cd7
AB
1088
1089 down(&dt9812_mutex);
f52a8af7 1090 /* Find a slot for the comedi device */
63274cd7 1091 {
98f3c672
GKH
1092 struct slot_dt9812 *first = NULL;
1093 struct slot_dt9812 *best = NULL;
63274cd7
AB
1094 for (i = 0; i < DT9812_NUM_SLOTS; i++) {
1095 if (!first && !dt9812[i].comedi) {
f52a8af7 1096 /* First free slot from comedi side */
63274cd7
AB
1097 first = &dt9812[i];
1098 }
1099 if (!best &&
f52a8af7
GKH
1100 dt9812[i].usb &&
1101 dt9812[i].usb->serial == devpriv->serial) {
1102 /* We have an attaced device with matching ID */
63274cd7
AB
1103 best = &dt9812[i];
1104 }
1105 }
f52a8af7 1106 if (!best)
63274cd7 1107 best = first;
63274cd7
AB
1108 if (best) {
1109 down(&best->mutex);
1110 best->comedi = devpriv;
1111 best->serial = devpriv->serial;
1112 devpriv->slot = best;
1113 up(&best->mutex);
1114 }
1115 }
1116 up(&dt9812_mutex);
1117
1118 return 0;
1119}
1120
484ecc95 1121static void dt9812_detach(struct comedi_device *dev)
63274cd7 1122{
484ecc95 1123 /* Nothing to cleanup */
63274cd7
AB
1124}
1125
139dfbdf 1126static struct comedi_driver dt9812_comedi_driver = {
63274cd7
AB
1127 .module = THIS_MODULE,
1128 .driver_name = "dt9812",
1129 .attach = dt9812_attach,
1130 .detach = dt9812_detach,
1131};
1132
1133static int __init usb_dt9812_init(void)
1134{
1135 int result, i;
1136
f52a8af7 1137 /* Initialize all driver slots */
63274cd7 1138 for (i = 0; i < DT9812_NUM_SLOTS; i++) {
0f0800f1 1139 sema_init(&dt9812[i].mutex, 1);
63274cd7
AB
1140 dt9812[i].serial = 0;
1141 dt9812[i].usb = NULL;
1142 dt9812[i].comedi = NULL;
1143 }
1144 dt9812[12].serial = 0x0;
1145
f52a8af7 1146 /* register with the USB subsystem */
63274cd7
AB
1147 result = usb_register(&dt9812_usb_driver);
1148 if (result) {
f52a8af7
GKH
1149 printk(KERN_ERR KBUILD_MODNAME
1150 ": usb_register failed. Error number %d\n", result);
1151 return result;
63274cd7 1152 }
f52a8af7 1153 /* register with comedi */
63274cd7
AB
1154 result = comedi_driver_register(&dt9812_comedi_driver);
1155 if (result) {
1156 usb_deregister(&dt9812_usb_driver);
923faa6a
GKH
1157 printk(KERN_ERR KBUILD_MODNAME
1158 ": comedi_driver_register failed. Error number %d\n",
1159 result);
63274cd7
AB
1160 }
1161
1162 return result;
1163}
1164
1165static void __exit usb_dt9812_exit(void)
1166{
f52a8af7 1167 /* unregister with comedi */
63274cd7
AB
1168 comedi_driver_unregister(&dt9812_comedi_driver);
1169
1170 /* deregister this driver with the USB subsystem */
1171 usb_deregister(&dt9812_usb_driver);
1172}
1173
1174module_init(usb_dt9812_init);
1175module_exit(usb_dt9812_exit);
1176
1177MODULE_AUTHOR("Anders Blomdell <anders.blomdell@control.lth.se>");
1178MODULE_DESCRIPTION("Comedi DT9812 driver");
1179MODULE_LICENSE("GPL");
This page took 0.41257 seconds and 5 git commands to generate.