staging: comedi: ni_at_a2150: use comedi_buf_write_samples()
[linux-2.6-block.git] / drivers / staging / comedi / drivers / s626.c
CommitLineData
11e865c1 1/*
7f32c7c4
IA
2 * comedi/drivers/s626.c
3 * Sensoray s626 Comedi driver
4 *
5 * COMEDI - Linux Control and Measurement Device Interface
6 * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
7 *
8 * Based on Sensoray Model 626 Linux driver Version 0.2
9 * Copyright (C) 2002-2004 Sensoray Co., Inc.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 */
11e865c1
GP
21
22/*
7f32c7c4
IA
23 * Driver: s626
24 * Description: Sensoray 626 driver
25 * Devices: [Sensoray] 626 (s626)
26 * Authors: Gianluca Palli <gpalli@deis.unibo.it>,
27 * Updated: Fri, 15 Feb 2008 10:28:42 +0000
28 * Status: experimental
29
30 * Configuration options: not applicable, uses PCI auto config
31
32 * INSN_CONFIG instructions:
33 * analog input:
34 * none
35 *
36 * analog output:
37 * none
38 *
39 * digital channel:
40 * s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels
41 * supported configuration options:
42 * INSN_CONFIG_DIO_QUERY
43 * COMEDI_INPUT
44 * COMEDI_OUTPUT
45 *
46 * encoder:
47 * Every channel must be configured before reading.
48 *
49 * Example code
50 *
51 * insn.insn=INSN_CONFIG; //configuration instruction
52 * insn.n=1; //number of operation (must be 1)
53 * insn.data=&initialvalue; //initial value loaded into encoder
54 * //during configuration
55 * insn.subdev=5; //encoder subdevice
56 * insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); //encoder_channel
57 * //to configure
58 *
59 * comedi_do_insn(cf,&insn); //executing configuration
60 */
11e865c1 61
ce157f80
HS
62#include <linux/module.h>
63#include <linux/delay.h>
33782dd5 64#include <linux/pci.h>
25436dc9 65#include <linux/interrupt.h>
11e865c1
GP
66#include <linux/kernel.h>
67#include <linux/types.h>
68
69#include "../comedidev.h"
70
11e865c1
GP
71#include "comedi_fc.h"
72#include "s626.h"
73
dbb263f5 74struct s626_buffer_dma {
8e06d662
IA
75 dma_addr_t physical_base;
76 void *logical_base;
77};
78
eb5e029e 79struct s626_private {
8ee52611 80 uint8_t ai_cmd_running; /* ai_cmd is running */
8ee52611
IA
81 int ai_sample_count; /* number of samples to acquire */
82 unsigned int ai_sample_timer; /* time between samples in
83 * units of the timer */
84 int ai_convert_count; /* conversion counter */
85 unsigned int ai_convert_timer; /* time between conversion in
86 * units of the timer */
07a36d66 87 uint16_t counter_int_enabs; /* counter interrupt enable mask
8ee52611 88 * for MISC2 register */
07a36d66 89 uint8_t adc_items; /* number of items in ADC poll list */
dbb263f5 90 struct s626_buffer_dma rps_buf; /* DMA buffer used to hold ADC (RPS1)
8ee52611 91 * program */
dbb263f5 92 struct s626_buffer_dma ana_buf; /* DMA buffer used to receive ADC data
8ee52611 93 * and hold DAC data */
07a36d66 94 uint32_t *dac_wbuf; /* pointer to logical adrs of DMA buffer
8ee52611 95 * used to hold DAC data */
07a36d66
IA
96 uint16_t dacpol; /* image of DAC polarity register */
97 uint8_t trim_setpoint[12]; /* images of TrimDAC setpoints */
98 uint32_t i2c_adrs; /* I2C device address for onboard EEPROM
8ee52611 99 * (board rev dependent) */
eb5e029e 100};
11e865c1 101
8ee52611 102/* Counter overflow/index event flag masks for RDMISC2. */
676921c9
IA
103#define S626_INDXMASK(C) (1 << (((C) > 2) ? ((C) * 2 - 1) : ((C) * 2 + 4)))
104#define S626_OVERMASK(C) (1 << (((C) > 2) ? ((C) * 2 + 5) : ((C) * 2 + 10)))
11e865c1 105
ddd9813e
HS
106/*
107 * Enable/disable a function or test status bit(s) that are accessed
108 * through Main Control Registers 1 or 2.
109 */
110static void s626_mc_enable(struct comedi_device *dev,
111 unsigned int cmd, unsigned int reg)
112{
ddd9813e
HS
113 unsigned int val = (cmd << 16) | cmd;
114
bb49cddc 115 mmiowb();
de9cd5ca 116 writel(val, dev->mmio + reg);
ddd9813e 117}
11e865c1 118
c5cf4606
HS
119static void s626_mc_disable(struct comedi_device *dev,
120 unsigned int cmd, unsigned int reg)
121{
de9cd5ca 122 writel(cmd << 16 , dev->mmio + reg);
bb49cddc 123 mmiowb();
c5cf4606 124}
11e865c1 125
95bb7982
HS
126static bool s626_mc_test(struct comedi_device *dev,
127 unsigned int cmd, unsigned int reg)
128{
95bb7982
HS
129 unsigned int val;
130
de9cd5ca 131 val = readl(dev->mmio + reg);
95bb7982
HS
132
133 return (val & cmd) ? true : false;
134}
11e865c1 135
676921c9 136#define S626_BUGFIX_STREG(REGADRS) ((REGADRS) - 4)
11e865c1 137
8ee52611 138/* Write a time slot control record to TSL2. */
d8515652 139#define S626_VECTPORT(VECTNUM) (S626_P_TSL2 + ((VECTNUM) << 2))
11e865c1 140
90d54ff2
HS
141static const struct comedi_lrange s626_range_table = {
142 2, {
143 BIP_RANGE(5),
481ac510 144 BIP_RANGE(10)
90d54ff2 145 }
11e865c1
GP
146};
147
8ee52611
IA
148/*
149 * Execute a DEBI transfer. This must be called from within a critical section.
150 */
31de1948 151static void s626_debi_transfer(struct comedi_device *dev)
6b387b70 152{
59a32a46
CS
153 static const int timeout = 10000;
154 int i;
7f2f7e05 155
ddd9813e 156 /* Initiate upload of shadow RAM to DEBI control register */
d8515652 157 s626_mc_enable(dev, S626_MC2_UPLD_DEBI, S626_P_MC2);
6b387b70 158
95bb7982
HS
159 /*
160 * Wait for completion of upload from shadow RAM to
161 * DEBI control register.
162 */
59a32a46
CS
163 for (i = 0; i < timeout; i++) {
164 if (s626_mc_test(dev, S626_MC2_UPLD_DEBI, S626_P_MC2))
165 break;
166 udelay(1);
167 }
168 if (i == timeout)
cefe9336
HS
169 dev_err(dev->class_dev,
170 "Timeout while uploading to DEBI control register\n");
6b387b70 171
be008602 172 /* Wait until DEBI transfer is done */
59a32a46 173 for (i = 0; i < timeout; i++) {
de9cd5ca 174 if (!(readl(dev->mmio + S626_P_PSR) & S626_PSR_DEBI_S))
59a32a46
CS
175 break;
176 udelay(1);
177 }
178 if (i == timeout)
cefe9336 179 dev_err(dev->class_dev, "DEBI transfer timeout\n");
6b387b70
HS
180}
181
8ee52611
IA
182/*
183 * Read a value from a gate array register.
184 */
31de1948 185static uint16_t s626_debi_read(struct comedi_device *dev, uint16_t addr)
6b387b70 186{
25f8fd5e 187 /* Set up DEBI control register value in shadow RAM */
de9cd5ca 188 writel(S626_DEBI_CMD_RDWORD | addr, dev->mmio + S626_P_DEBICMD);
6b387b70
HS
189
190 /* Execute the DEBI transfer. */
31de1948 191 s626_debi_transfer(dev);
6b387b70 192
de9cd5ca 193 return readl(dev->mmio + S626_P_DEBIAD);
6b387b70
HS
194}
195
8ee52611
IA
196/*
197 * Write a value to a gate array register.
198 */
31de1948
IA
199static void s626_debi_write(struct comedi_device *dev, uint16_t addr,
200 uint16_t wdata)
6b387b70 201{
25f8fd5e 202 /* Set up DEBI control register value in shadow RAM */
de9cd5ca
HS
203 writel(S626_DEBI_CMD_WRWORD | addr, dev->mmio + S626_P_DEBICMD);
204 writel(wdata, dev->mmio + S626_P_DEBIAD);
6b387b70
HS
205
206 /* Execute the DEBI transfer. */
31de1948 207 s626_debi_transfer(dev);
6b387b70
HS
208}
209
8ee52611
IA
210/*
211 * Replace the specified bits in a gate array register. Imports: mask
6b387b70
HS
212 * specifies bits that are to be preserved, wdata is new value to be
213 * or'd with the masked original.
214 */
31de1948
IA
215static void s626_debi_replace(struct comedi_device *dev, unsigned int addr,
216 unsigned int mask, unsigned int wdata)
6b387b70 217{
be008602 218 unsigned int val;
6b387b70 219
12f4e2f2 220 addr &= 0xffff;
de9cd5ca 221 writel(S626_DEBI_CMD_RDWORD | addr, dev->mmio + S626_P_DEBICMD);
31de1948 222 s626_debi_transfer(dev);
6b387b70 223
de9cd5ca
HS
224 writel(S626_DEBI_CMD_WRWORD | addr, dev->mmio + S626_P_DEBICMD);
225 val = readl(dev->mmio + S626_P_DEBIAD);
be008602
HS
226 val &= mask;
227 val |= wdata;
de9cd5ca 228 writel(val & 0xffff, dev->mmio + S626_P_DEBIAD);
31de1948 229 s626_debi_transfer(dev);
6b387b70
HS
230}
231
982e3d11
HS
232/* ************** EEPROM ACCESS FUNCTIONS ************** */
233
571845c6
CS
234static int s626_i2c_handshake_eoc(struct comedi_device *dev,
235 struct comedi_subdevice *s,
236 struct comedi_insn *insn,
237 unsigned long context)
238{
239 bool status;
240
241 status = s626_mc_test(dev, S626_MC2_UPLD_IIC, S626_P_MC2);
242 if (status)
243 return 0;
244 return -EBUSY;
245}
246
247static int s626_i2c_handshake(struct comedi_device *dev, uint32_t val)
982e3d11 248{
be008602 249 unsigned int ctrl;
571845c6 250 int ret;
7f2f7e05 251
25f8fd5e 252 /* Write I2C command to I2C Transfer Control shadow register */
de9cd5ca 253 writel(val, dev->mmio + S626_P_I2CCTRL);
982e3d11 254
ddd9813e
HS
255 /*
256 * Upload I2C shadow registers into working registers and
257 * wait for upload confirmation.
258 */
d8515652 259 s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2);
571845c6
CS
260 ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0);
261 if (ret)
262 return ret;
982e3d11 263
be008602
HS
264 /* Wait until I2C bus transfer is finished or an error occurs */
265 do {
de9cd5ca 266 ctrl = readl(dev->mmio + S626_P_I2CCTRL);
d8515652 267 } while ((ctrl & (S626_I2C_BUSY | S626_I2C_ERR)) == S626_I2C_BUSY);
982e3d11 268
be008602 269 /* Return non-zero if I2C error occurred */
d8515652 270 return ctrl & S626_I2C_ERR;
982e3d11
HS
271}
272
8ee52611 273/* Read uint8_t from EEPROM. */
31de1948 274static uint8_t s626_i2c_read(struct comedi_device *dev, uint8_t addr)
982e3d11 275{
7f2f7e05 276 struct s626_private *devpriv = dev->private;
982e3d11 277
8ee52611
IA
278 /*
279 * Send EEPROM target address:
280 * Byte2 = I2C command: write to I2C EEPROM device.
281 * Byte1 = EEPROM internal target address.
282 * Byte0 = Not sent.
283 */
d8515652
IA
284 if (s626_i2c_handshake(dev, S626_I2C_B2(S626_I2C_ATTRSTART,
285 devpriv->i2c_adrs) |
286 S626_I2C_B1(S626_I2C_ATTRSTOP, addr) |
287 S626_I2C_B0(S626_I2C_ATTRNOP, 0)))
8ee52611 288 /* Abort function and declare error if handshake failed. */
982e3d11 289 return 0;
982e3d11 290
8ee52611
IA
291 /*
292 * Execute EEPROM read:
293 * Byte2 = I2C command: read from I2C EEPROM device.
294 * Byte1 receives uint8_t from EEPROM.
295 * Byte0 = Not sent.
296 */
d8515652 297 if (s626_i2c_handshake(dev, S626_I2C_B2(S626_I2C_ATTRSTART,
31de1948 298 (devpriv->i2c_adrs | 1)) |
d8515652
IA
299 S626_I2C_B1(S626_I2C_ATTRSTOP, 0) |
300 S626_I2C_B0(S626_I2C_ATTRNOP, 0)))
8ee52611 301 /* Abort function and declare error if handshake failed. */
982e3d11 302 return 0;
be008602 303
de9cd5ca 304 return (readl(dev->mmio + S626_P_I2CCTRL) >> 16) & 0xff;
982e3d11
HS
305}
306
95414729
HS
307/* *********** DAC FUNCTIONS *********** */
308
8ee52611 309/* TrimDac LogicalChan-to-PhysicalChan mapping table. */
31de1948 310static const uint8_t s626_trimchan[] = { 10, 9, 8, 3, 2, 7, 6, 1, 0, 5, 4 };
95414729 311
8ee52611 312/* TrimDac LogicalChan-to-EepromAdrs mapping table. */
31de1948 313static const uint8_t s626_trimadrs[] = {
8ee52611
IA
314 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x61, 0x62, 0x63
315};
95414729 316
59a32a46
CS
317enum {
318 s626_send_dac_wait_not_mc1_a2out,
319 s626_send_dac_wait_ssr_af2_out,
320 s626_send_dac_wait_fb_buffer2_msb_00,
321 s626_send_dac_wait_fb_buffer2_msb_ff
322};
323
324static int s626_send_dac_eoc(struct comedi_device *dev,
325 struct comedi_subdevice *s,
326 struct comedi_insn *insn,
327 unsigned long context)
328{
59a32a46
CS
329 unsigned int status;
330
331 switch (context) {
332 case s626_send_dac_wait_not_mc1_a2out:
de9cd5ca 333 status = readl(dev->mmio + S626_P_MC1);
59a32a46
CS
334 if (!(status & S626_MC1_A2OUT))
335 return 0;
336 break;
337 case s626_send_dac_wait_ssr_af2_out:
de9cd5ca 338 status = readl(dev->mmio + S626_P_SSR);
59a32a46
CS
339 if (status & S626_SSR_AF2_OUT)
340 return 0;
341 break;
342 case s626_send_dac_wait_fb_buffer2_msb_00:
de9cd5ca 343 status = readl(dev->mmio + S626_P_FB_BUFFER2);
59a32a46
CS
344 if (!(status & 0xff000000))
345 return 0;
346 break;
347 case s626_send_dac_wait_fb_buffer2_msb_ff:
de9cd5ca 348 status = readl(dev->mmio + S626_P_FB_BUFFER2);
59a32a46
CS
349 if (status & 0xff000000)
350 return 0;
351 break;
352 default:
353 return -EINVAL;
354 }
355 return -EBUSY;
356}
357
8ee52611
IA
358/*
359 * Private helper function: Transmit serial data to DAC via Audio
95414729 360 * channel 2. Assumes: (1) TSL2 slot records initialized, and (2)
07a36d66 361 * dacpol contains valid target image.
95414729 362 */
a7aa94ce 363static int s626_send_dac(struct comedi_device *dev, uint32_t val)
95414729 364{
7f2f7e05 365 struct s626_private *devpriv = dev->private;
59a32a46 366 int ret;
95414729
HS
367
368 /* START THE SERIAL CLOCK RUNNING ------------- */
369
8ee52611
IA
370 /*
371 * Assert DAC polarity control and enable gating of DAC serial clock
95414729
HS
372 * and audio bit stream signals. At this point in time we must be
373 * assured of being in time slot 0. If we are not in slot 0, the
374 * serial clock and audio stream signals will be disabled; this is
31de1948
IA
375 * because the following s626_debi_write statement (which enables
376 * signals to be passed through the gate array) would execute before
377 * the trailing edge of WS1/WS3 (which turns off the signals), thus
95414729
HS
378 * causing the signals to be inactive during the DAC write.
379 */
d8515652 380 s626_debi_write(dev, S626_LP_DACPOL, devpriv->dacpol);
95414729
HS
381
382 /* TRANSFER OUTPUT DWORD VALUE INTO A2'S OUTPUT FIFO ---------------- */
383
384 /* Copy DAC setpoint value to DAC's output DMA buffer. */
de9cd5ca 385 /* writel(val, dev->mmio + (uint32_t)devpriv->dac_wbuf); */
07a36d66 386 *devpriv->dac_wbuf = val;
95414729 387
ddd9813e
HS
388 /*
389 * Enable the output DMA transfer. This will cause the DMAC to copy
390 * the DAC's data value to A2's output FIFO. The DMA transfer will
95414729
HS
391 * then immediately terminate because the protection address is
392 * reached upon transfer of the first DWORD value.
393 */
d8515652 394 s626_mc_enable(dev, S626_MC1_A2OUT, S626_P_MC1);
95414729 395
8ee52611 396 /* While the DMA transfer is executing ... */
95414729 397
25f8fd5e
HS
398 /*
399 * Reset Audio2 output FIFO's underflow flag (along with any
400 * other FIFO underflow/overflow flags). When set, this flag
401 * will indicate that we have emerged from slot 0.
95414729 402 */
de9cd5ca 403 writel(S626_ISR_AFOU, dev->mmio + S626_P_ISR);
95414729 404
8ee52611
IA
405 /*
406 * Wait for the DMA transfer to finish so that there will be data
95414729
HS
407 * available in the FIFO when time slot 1 tries to transfer a DWORD
408 * from the FIFO to the output buffer register. We test for DMA
409 * Done by polling the DMAC enable flag; this flag is automatically
410 * cleared when the transfer has finished.
411 */
59a32a46
CS
412 ret = comedi_timeout(dev, NULL, NULL, s626_send_dac_eoc,
413 s626_send_dac_wait_not_mc1_a2out);
a7aa94ce 414 if (ret) {
cefe9336 415 dev_err(dev->class_dev, "DMA transfer timeout\n");
a7aa94ce
CS
416 return ret;
417 }
95414729
HS
418
419 /* START THE OUTPUT STREAM TO THE TARGET DAC -------------------- */
420
8ee52611
IA
421 /*
422 * FIFO data is now available, so we enable execution of time slots
95414729
HS
423 * 1 and higher by clearing the EOS flag in slot 0. Note that SD3
424 * will be shifted in and stored in FB_BUFFER2 for end-of-slot-list
425 * detection.
426 */
d8515652 427 writel(S626_XSD2 | S626_RSD3 | S626_SIB_A2,
de9cd5ca 428 dev->mmio + S626_VECTPORT(0));
95414729 429
8ee52611
IA
430 /*
431 * Wait for slot 1 to execute to ensure that the Packet will be
95414729
HS
432 * transmitted. This is detected by polling the Audio2 output FIFO
433 * underflow flag, which will be set when slot 1 execution has
434 * finished transferring the DAC's data DWORD from the output FIFO
435 * to the output buffer register.
436 */
59a32a46
CS
437 ret = comedi_timeout(dev, NULL, NULL, s626_send_dac_eoc,
438 s626_send_dac_wait_ssr_af2_out);
a7aa94ce 439 if (ret) {
cefe9336
HS
440 dev_err(dev->class_dev,
441 "TSL timeout waiting for slot 1 to execute\n");
a7aa94ce
CS
442 return ret;
443 }
95414729 444
8ee52611
IA
445 /*
446 * Set up to trap execution at slot 0 when the TSL sequencer cycles
95414729
HS
447 * back to slot 0 after executing the EOS in slot 5. Also,
448 * simultaneously shift out and in the 0x00 that is ALWAYS the value
449 * stored in the last byte to be shifted out of the FIFO's DWORD
450 * buffer register.
451 */
d8515652 452 writel(S626_XSD2 | S626_XFIFO_2 | S626_RSD2 | S626_SIB_A2 | S626_EOS,
de9cd5ca 453 dev->mmio + S626_VECTPORT(0));
95414729
HS
454
455 /* WAIT FOR THE TRANSACTION TO FINISH ----------------------- */
456
8ee52611
IA
457 /*
458 * Wait for the TSL to finish executing all time slots before
95414729
HS
459 * exiting this function. We must do this so that the next DAC
460 * write doesn't start, thereby enabling clock/chip select signals:
461 *
462 * 1. Before the TSL sequence cycles back to slot 0, which disables
463 * the clock/cs signal gating and traps slot // list execution.
464 * we have not yet finished slot 5 then the clock/cs signals are
465 * still gated and we have not finished transmitting the stream.
466 *
467 * 2. While slots 2-5 are executing due to a late slot 0 trap. In
468 * this case, the slot sequence is currently repeating, but with
469 * clock/cs signals disabled. We must wait for slot 0 to trap
470 * execution before setting up the next DAC setpoint DMA transfer
471 * and enabling the clock/cs signals. To detect the end of slot 5,
472 * we test for the FB_BUFFER2 MSB contents to be equal to 0xFF. If
473 * the TSL has not yet finished executing slot 5 ...
474 */
de9cd5ca 475 if (readl(dev->mmio + S626_P_FB_BUFFER2) & 0xff000000) {
8ee52611
IA
476 /*
477 * The trap was set on time and we are still executing somewhere
95414729
HS
478 * in slots 2-5, so we now wait for slot 0 to execute and trap
479 * TSL execution. This is detected when FB_BUFFER2 MSB changes
480 * from 0xFF to 0x00, which slot 0 causes to happen by shifting
481 * out/in on SD2 the 0x00 that is always referenced by slot 5.
482 */
59a32a46
CS
483 ret = comedi_timeout(dev, NULL, NULL, s626_send_dac_eoc,
484 s626_send_dac_wait_fb_buffer2_msb_00);
a7aa94ce 485 if (ret) {
cefe9336
HS
486 dev_err(dev->class_dev,
487 "TSL timeout waiting for slot 0 to execute\n");
a7aa94ce
CS
488 return ret;
489 }
95414729 490 }
8ee52611
IA
491 /*
492 * Either (1) we were too late setting the slot 0 trap; the TSL
95414729
HS
493 * sequencer restarted slot 0 before we could set the EOS trap flag,
494 * or (2) we were not late and execution is now trapped at slot 0.
495 * In either case, we must now change slot 0 so that it will store
496 * value 0xFF (instead of 0x00) to FB_BUFFER2 next time it executes.
497 * In order to do this, we reprogram slot 0 so that it will shift in
498 * SD3, which is driven only by a pull-up resistor.
499 */
d8515652 500 writel(S626_RSD3 | S626_SIB_A2 | S626_EOS,
de9cd5ca 501 dev->mmio + S626_VECTPORT(0));
95414729 502
8ee52611
IA
503 /*
504 * Wait for slot 0 to execute, at which time the TSL is setup for
95414729
HS
505 * the next DAC write. This is detected when FB_BUFFER2 MSB changes
506 * from 0x00 to 0xFF.
507 */
59a32a46
CS
508 ret = comedi_timeout(dev, NULL, NULL, s626_send_dac_eoc,
509 s626_send_dac_wait_fb_buffer2_msb_ff);
a7aa94ce 510 if (ret) {
cefe9336
HS
511 dev_err(dev->class_dev,
512 "TSL timeout waiting for slot 0 to execute\n");
a7aa94ce
CS
513 return ret;
514 }
515 return 0;
95414729
HS
516}
517
8ee52611
IA
518/*
519 * Private helper function: Write setpoint to an application DAC channel.
520 */
a7aa94ce 521static int s626_set_dac(struct comedi_device *dev, uint16_t chan,
3de00ee4 522 int16_t dacdata)
95414729 523{
7f2f7e05 524 struct s626_private *devpriv = dev->private;
8ee52611 525 uint16_t signmask;
f1f7efce 526 uint32_t ws_image;
8ee52611 527 uint32_t val;
95414729 528
8ee52611
IA
529 /*
530 * Adjust DAC data polarity and set up Polarity Control Register image.
531 */
95414729
HS
532 signmask = 1 << chan;
533 if (dacdata < 0) {
534 dacdata = -dacdata;
07a36d66 535 devpriv->dacpol |= signmask;
8ee52611 536 } else {
07a36d66 537 devpriv->dacpol &= ~signmask;
8ee52611 538 }
95414729 539
8ee52611
IA
540 /* Limit DAC setpoint value to valid range. */
541 if ((uint16_t)dacdata > 0x1FFF)
95414729
HS
542 dacdata = 0x1FFF;
543
8ee52611
IA
544 /*
545 * Set up TSL2 records (aka "vectors") for DAC update. Vectors V2
95414729
HS
546 * and V3 transmit the setpoint to the target DAC. V4 and V5 send
547 * data to a non-existent TrimDac channel just to keep the clock
548 * running after sending data to the target DAC. This is necessary
549 * to eliminate the clock glitch that would otherwise occur at the
550 * end of the target DAC's serial data stream. When the sequence
551 * restarts at V0 (after executing V5), the gate array automatically
552 * disables gating for the DAC clock and all DAC chip selects.
553 */
554
25f8fd5e 555 /* Choose DAC chip select to be asserted */
d8515652 556 ws_image = (chan & 2) ? S626_WS1 : S626_WS2;
25f8fd5e 557 /* Slot 2: Transmit high data byte to target DAC */
d8515652 558 writel(S626_XSD2 | S626_XFIFO_1 | ws_image,
de9cd5ca 559 dev->mmio + S626_VECTPORT(2));
25f8fd5e 560 /* Slot 3: Transmit low data byte to target DAC */
d8515652 561 writel(S626_XSD2 | S626_XFIFO_0 | ws_image,
de9cd5ca 562 dev->mmio + S626_VECTPORT(3));
95414729 563 /* Slot 4: Transmit to non-existent TrimDac channel to keep clock */
d8515652 564 writel(S626_XSD2 | S626_XFIFO_3 | S626_WS3,
de9cd5ca 565 dev->mmio + S626_VECTPORT(4));
25f8fd5e 566 /* Slot 5: running after writing target DAC's low data byte */
d8515652 567 writel(S626_XSD2 | S626_XFIFO_2 | S626_WS3 | S626_EOS,
de9cd5ca 568 dev->mmio + S626_VECTPORT(5));
95414729 569
8ee52611
IA
570 /*
571 * Construct and transmit target DAC's serial packet:
572 * (A10D DDDD), (DDDD DDDD), (0x0F), (0x00) where A is chan<0>,
95414729
HS
573 * and D<12:0> is the DAC setpoint. Append a WORD value (that writes
574 * to a non-existent TrimDac channel) that serves to keep the clock
575 * running after the packet has been sent to the target DAC.
576 */
8ee52611
IA
577 val = 0x0F000000; /* Continue clock after target DAC data
578 * (write to non-existent trimdac). */
579 val |= 0x00004000; /* Address the two main dual-DAC devices
580 * (TSL's chip select enables target device). */
581 val |= ((uint32_t)(chan & 1) << 15); /* Address the DAC channel
582 * within the device. */
583 val |= (uint32_t)dacdata; /* Include DAC setpoint data. */
a7aa94ce 584 return s626_send_dac(dev, val);
95414729
HS
585}
586
a7aa94ce 587static int s626_write_trim_dac(struct comedi_device *dev, uint8_t logical_chan,
31de1948 588 uint8_t dac_data)
95414729 589{
7f2f7e05 590 struct s626_private *devpriv = dev->private;
95414729
HS
591 uint32_t chan;
592
8ee52611
IA
593 /*
594 * Save the new setpoint in case the application needs to read it back
595 * later.
596 */
f1f7efce 597 devpriv->trim_setpoint[logical_chan] = (uint8_t)dac_data;
95414729 598
8ee52611 599 /* Map logical channel number to physical channel number. */
31de1948 600 chan = s626_trimchan[logical_chan];
95414729 601
8ee52611
IA
602 /*
603 * Set up TSL2 records for TrimDac write operation. All slots shift
95414729
HS
604 * 0xFF in from pulled-up SD3 so that the end of the slot sequence
605 * can be detected.
606 */
607
25f8fd5e 608 /* Slot 2: Send high uint8_t to target TrimDac */
d8515652 609 writel(S626_XSD2 | S626_XFIFO_1 | S626_WS3,
de9cd5ca 610 dev->mmio + S626_VECTPORT(2));
25f8fd5e 611 /* Slot 3: Send low uint8_t to target TrimDac */
d8515652 612 writel(S626_XSD2 | S626_XFIFO_0 | S626_WS3,
de9cd5ca 613 dev->mmio + S626_VECTPORT(3));
25f8fd5e 614 /* Slot 4: Send NOP high uint8_t to DAC0 to keep clock running */
d8515652 615 writel(S626_XSD2 | S626_XFIFO_3 | S626_WS1,
de9cd5ca 616 dev->mmio + S626_VECTPORT(4));
25f8fd5e 617 /* Slot 5: Send NOP low uint8_t to DAC0 */
d8515652 618 writel(S626_XSD2 | S626_XFIFO_2 | S626_WS1 | S626_EOS,
de9cd5ca 619 dev->mmio + S626_VECTPORT(5));
95414729 620
8ee52611
IA
621 /*
622 * Construct and transmit target DAC's serial packet:
623 * (0000 AAAA), (DDDD DDDD), (0x00), (0x00) where A<3:0> is the
95414729
HS
624 * DAC channel's address, and D<7:0> is the DAC setpoint. Append a
625 * WORD value (that writes a channel 0 NOP command to a non-existent
626 * main DAC channel) that serves to keep the clock running after the
627 * packet has been sent to the target DAC.
628 */
629
8ee52611
IA
630 /*
631 * Address the DAC channel within the trimdac device.
632 * Include DAC setpoint data.
633 */
a7aa94ce 634 return s626_send_dac(dev, (chan << 8) | dac_data);
95414729
HS
635}
636
a7aa94ce 637static int s626_load_trim_dacs(struct comedi_device *dev)
95414729 638{
8ee52611 639 uint8_t i;
a7aa94ce 640 int ret;
95414729 641
8ee52611 642 /* Copy TrimDac setpoint values from EEPROM to TrimDacs. */
a7aa94ce
CS
643 for (i = 0; i < ARRAY_SIZE(s626_trimchan); i++) {
644 ret = s626_write_trim_dac(dev, i,
31de1948 645 s626_i2c_read(dev, s626_trimadrs[i]));
a7aa94ce
CS
646 if (ret)
647 return ret;
648 }
649 return 0;
95414729
HS
650}
651
e3eb08d0 652/* ****** COUNTER FUNCTIONS ******* */
8ee52611
IA
653
654/*
655 * All counter functions address a specific counter by means of the
e3eb08d0
HS
656 * "Counter" argument, which is a logical counter number. The Counter
657 * argument may have any of the following legal values: 0=0A, 1=1A,
658 * 2=2A, 3=0B, 4=1B, 5=2B.
659 */
660
8ee52611
IA
661/*
662 * Return/set a counter pair's latch trigger source. 0: On read
e3eb08d0
HS
663 * access, 1: A index latches A, 2: B index latches B, 3: A overflow
664 * latches B.
665 */
31de1948 666static void s626_set_latch_source(struct comedi_device *dev,
0c9a057c 667 unsigned int chan, uint16_t value)
e3eb08d0 668{
0c9a057c 669 s626_debi_replace(dev, S626_LP_CRB(chan),
d8515652 670 ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_LATCHSRC),
0830ada5 671 S626_SET_CRB_LATCHSRC(value));
e3eb08d0
HS
672}
673
8ee52611
IA
674/*
675 * Write value into counter preload register.
676 */
31de1948 677static void s626_preload(struct comedi_device *dev,
0c9a057c 678 unsigned int chan, uint32_t value)
e3eb08d0 679{
0c9a057c
HS
680 s626_debi_write(dev, S626_LP_CNTR(chan), value);
681 s626_debi_write(dev, S626_LP_CNTR(chan) + 2, value >> 16);
e3eb08d0
HS
682}
683
010be96f
IA
684/* ****** PRIVATE COUNTER FUNCTIONS ****** */
685
686/*
687 * Reset a counter's index and overflow event capture flags.
688 */
26499b8b 689static void s626_reset_cap_flags(struct comedi_device *dev,
0c9a057c 690 unsigned int chan)
010be96f 691{
26499b8b 692 uint16_t set;
010be96f 693
26499b8b 694 set = S626_SET_CRB_INTRESETCMD(1);
0c9a057c 695 if (chan < 3)
26499b8b
HS
696 set |= S626_SET_CRB_INTRESET_A(1);
697 else
698 set |= S626_SET_CRB_INTRESET_B(1);
699
0c9a057c 700 s626_debi_replace(dev, S626_LP_CRB(chan), ~S626_CRBMSK_INTCTRL, set);
010be96f
IA
701}
702
0a984491 703#ifdef unused
010be96f
IA
704/*
705 * Return counter setup in a format (COUNTER_SETUP) that is consistent
706 * for both A and B counters.
707 */
31de1948 708static uint16_t s626_get_mode_a(struct comedi_device *dev,
0c9a057c 709 unsigned int chan)
010be96f
IA
710{
711 uint16_t cra;
712 uint16_t crb;
713 uint16_t setup;
0830ada5 714 unsigned cntsrc, clkmult, clkpol, encmode;
010be96f
IA
715
716 /* Fetch CRA and CRB register images. */
0c9a057c
HS
717 cra = s626_debi_read(dev, S626_LP_CRA(chan));
718 crb = s626_debi_read(dev, S626_LP_CRB(chan));
010be96f
IA
719
720 /*
721 * Populate the standardized counter setup bit fields.
010be96f 722 */
0830ada5
IA
723 setup =
724 /* LoadSrc = LoadSrcA. */
725 S626_SET_STD_LOADSRC(S626_GET_CRA_LOADSRC_A(cra)) |
726 /* LatchSrc = LatchSrcA. */
727 S626_SET_STD_LATCHSRC(S626_GET_CRB_LATCHSRC(crb)) |
728 /* IntSrc = IntSrcA. */
729 S626_SET_STD_INTSRC(S626_GET_CRA_INTSRC_A(cra)) |
2cea19fa
IA
730 /* IndxSrc = IndxSrcA. */
731 S626_SET_STD_INDXSRC(S626_GET_CRA_INDXSRC_A(cra)) |
0830ada5
IA
732 /* IndxPol = IndxPolA. */
733 S626_SET_STD_INDXPOL(S626_GET_CRA_INDXPOL_A(cra)) |
734 /* ClkEnab = ClkEnabA. */
735 S626_SET_STD_CLKENAB(S626_GET_CRB_CLKENAB_A(crb));
010be96f
IA
736
737 /* Adjust mode-dependent parameters. */
0830ada5
IA
738 cntsrc = S626_GET_CRA_CNTSRC_A(cra);
739 if (cntsrc & S626_CNTSRC_SYSCLK) {
622ec01a 740 /* Timer mode (CntSrcA<1> == 1): */
0830ada5 741 encmode = S626_ENCMODE_TIMER;
622ec01a 742 /* Set ClkPol to indicate count direction (CntSrcA<0>). */
0830ada5 743 clkpol = cntsrc & 1;
010be96f 744 /* ClkMult must be 1x in Timer mode. */
7a1046e5 745 clkmult = S626_CLKMULT_1X;
010be96f 746 } else {
622ec01a 747 /* Counter mode (CntSrcA<1> == 0): */
0830ada5 748 encmode = S626_ENCMODE_COUNTER;
010be96f 749 /* Pass through ClkPol. */
0830ada5 750 clkpol = S626_GET_CRA_CLKPOL_A(cra);
010be96f 751 /* Force ClkMult to 1x if not legal, else pass through. */
0830ada5 752 clkmult = S626_GET_CRA_CLKMULT_A(cra);
7a1046e5
IA
753 if (clkmult == S626_CLKMULT_SPECIAL)
754 clkmult = S626_CLKMULT_1X;
010be96f 755 }
0830ada5
IA
756 setup |= S626_SET_STD_ENCMODE(encmode) | S626_SET_STD_CLKMULT(clkmult) |
757 S626_SET_STD_CLKPOL(clkpol);
010be96f
IA
758
759 /* Return adjusted counter setup. */
760 return setup;
761}
762
31de1948 763static uint16_t s626_get_mode_b(struct comedi_device *dev,
0c9a057c 764 unsigned int chan)
010be96f
IA
765{
766 uint16_t cra;
767 uint16_t crb;
768 uint16_t setup;
0830ada5 769 unsigned cntsrc, clkmult, clkpol, encmode;
010be96f
IA
770
771 /* Fetch CRA and CRB register images. */
0c9a057c
HS
772 cra = s626_debi_read(dev, S626_LP_CRA(chan));
773 crb = s626_debi_read(dev, S626_LP_CRB(chan));
010be96f
IA
774
775 /*
776 * Populate the standardized counter setup bit fields.
010be96f 777 */
0830ada5
IA
778 setup =
779 /* IntSrc = IntSrcB. */
780 S626_SET_STD_INTSRC(S626_GET_CRB_INTSRC_B(crb)) |
781 /* LatchSrc = LatchSrcB. */
782 S626_SET_STD_LATCHSRC(S626_GET_CRB_LATCHSRC(crb)) |
783 /* LoadSrc = LoadSrcB. */
784 S626_SET_STD_LOADSRC(S626_GET_CRB_LOADSRC_B(crb)) |
785 /* IndxPol = IndxPolB. */
786 S626_SET_STD_INDXPOL(S626_GET_CRB_INDXPOL_B(crb)) |
787 /* ClkEnab = ClkEnabB. */
788 S626_SET_STD_CLKENAB(S626_GET_CRB_CLKENAB_B(crb)) |
2cea19fa
IA
789 /* IndxSrc = IndxSrcB. */
790 S626_SET_STD_INDXSRC(S626_GET_CRA_INDXSRC_B(cra));
010be96f
IA
791
792 /* Adjust mode-dependent parameters. */
0830ada5
IA
793 cntsrc = S626_GET_CRA_CNTSRC_B(cra);
794 clkmult = S626_GET_CRB_CLKMULT_B(crb);
7a1046e5
IA
795 if (clkmult == S626_CLKMULT_SPECIAL) {
796 /* Extender mode (ClkMultB == S626_CLKMULT_SPECIAL): */
0830ada5 797 encmode = S626_ENCMODE_EXTENDER;
010be96f 798 /* Indicate multiplier is 1x. */
7a1046e5 799 clkmult = S626_CLKMULT_1X;
622ec01a 800 /* Set ClkPol equal to Timer count direction (CntSrcB<0>). */
0830ada5
IA
801 clkpol = cntsrc & 1;
802 } else if (cntsrc & S626_CNTSRC_SYSCLK) {
622ec01a 803 /* Timer mode (CntSrcB<1> == 1): */
0830ada5 804 encmode = S626_ENCMODE_TIMER;
010be96f 805 /* Indicate multiplier is 1x. */
7a1046e5 806 clkmult = S626_CLKMULT_1X;
622ec01a 807 /* Set ClkPol equal to Timer count direction (CntSrcB<0>). */
0830ada5 808 clkpol = cntsrc & 1;
010be96f 809 } else {
622ec01a 810 /* If Counter mode (CntSrcB<1> == 0): */
0830ada5 811 encmode = S626_ENCMODE_COUNTER;
010be96f 812 /* Clock multiplier is passed through. */
010be96f 813 /* Clock polarity is passed through. */
0830ada5 814 clkpol = S626_GET_CRB_CLKPOL_B(crb);
010be96f 815 }
0830ada5
IA
816 setup |= S626_SET_STD_ENCMODE(encmode) | S626_SET_STD_CLKMULT(clkmult) |
817 S626_SET_STD_CLKPOL(clkpol);
010be96f
IA
818
819 /* Return adjusted counter setup. */
820 return setup;
821}
822
0a984491 823static uint16_t s626_get_mode(struct comedi_device *dev,
0c9a057c 824 unsigned int chan)
0a984491 825{
193725ba
HS
826 return (chan < 3) ? s626_get_mode_a(dev, chan)
827 : s626_get_mode_b(dev, chan);
0a984491
HS
828}
829#endif
830
17afeac2
IA
831/*
832 * Set the operating mode for the specified counter. The setup
833 * parameter is treated as a COUNTER_SETUP data type. The following
834 * parameters are programmable (all other parms are ignored): ClkMult,
835 * ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc.
836 */
31de1948 837static void s626_set_mode_a(struct comedi_device *dev,
0c9a057c 838 unsigned int chan, uint16_t setup,
31de1948 839 uint16_t disable_int_src)
17afeac2
IA
840{
841 struct s626_private *devpriv = dev->private;
842 uint16_t cra;
843 uint16_t crb;
0830ada5 844 unsigned cntsrc, clkmult, clkpol;
17afeac2
IA
845
846 /* Initialize CRA and CRB images. */
847 /* Preload trigger is passed through. */
0830ada5 848 cra = S626_SET_CRA_LOADSRC_A(S626_GET_STD_LOADSRC(setup));
2cea19fa
IA
849 /* IndexSrc is passed through. */
850 cra |= S626_SET_CRA_INDXSRC_A(S626_GET_STD_INDXSRC(setup));
17afeac2
IA
851
852 /* Reset any pending CounterA event captures. */
0830ada5 853 crb = S626_SET_CRB_INTRESETCMD(1) | S626_SET_CRB_INTRESET_A(1);
17afeac2 854 /* Clock enable is passed through. */
0830ada5 855 crb |= S626_SET_CRB_CLKENAB_A(S626_GET_STD_CLKENAB(setup));
17afeac2
IA
856
857 /* Force IntSrc to Disabled if disable_int_src is asserted. */
858 if (!disable_int_src)
0830ada5 859 cra |= S626_SET_CRA_INTSRC_A(S626_GET_STD_INTSRC(setup));
17afeac2
IA
860
861 /* Populate all mode-dependent attributes of CRA & CRB images. */
0830ada5
IA
862 clkpol = S626_GET_STD_CLKPOL(setup);
863 switch (S626_GET_STD_ENCMODE(setup)) {
622ec01a 864 case S626_ENCMODE_EXTENDER: /* Extender Mode: */
d8515652 865 /* Force to Timer mode (Extender valid only for B counters). */
622ec01a
IA
866 /* Fall through to case S626_ENCMODE_TIMER: */
867 case S626_ENCMODE_TIMER: /* Timer Mode: */
868 /* CntSrcA<1> selects system clock */
0830ada5 869 cntsrc = S626_CNTSRC_SYSCLK;
622ec01a 870 /* Count direction (CntSrcA<0>) obtained from ClkPol. */
0830ada5 871 cntsrc |= clkpol;
17afeac2 872 /* ClkPolA behaves as always-on clock enable. */
0830ada5 873 clkpol = 1;
17afeac2 874 /* ClkMult must be 1x. */
7a1046e5 875 clkmult = S626_CLKMULT_1X;
17afeac2
IA
876 break;
877 default: /* Counter Mode: */
878 /* Select ENC_C and ENC_D as clock/direction inputs. */
0830ada5 879 cntsrc = S626_CNTSRC_ENCODER;
17afeac2 880 /* Clock polarity is passed through. */
17afeac2 881 /* Force multiplier to x1 if not legal, else pass through. */
0830ada5 882 clkmult = S626_GET_STD_CLKMULT(setup);
7a1046e5
IA
883 if (clkmult == S626_CLKMULT_SPECIAL)
884 clkmult = S626_CLKMULT_1X;
17afeac2
IA
885 break;
886 }
0830ada5
IA
887 cra |= S626_SET_CRA_CNTSRC_A(cntsrc) | S626_SET_CRA_CLKPOL_A(clkpol) |
888 S626_SET_CRA_CLKMULT_A(clkmult);
17afeac2
IA
889
890 /*
891 * Force positive index polarity if IndxSrc is software-driven only,
892 * otherwise pass it through.
893 */
2cea19fa 894 if (S626_GET_STD_INDXSRC(setup) != S626_INDXSRC_SOFT)
0830ada5 895 cra |= S626_SET_CRA_INDXPOL_A(S626_GET_STD_INDXPOL(setup));
17afeac2
IA
896
897 /*
898 * If IntSrc has been forced to Disabled, update the MISC2 interrupt
899 * enable mask to indicate the counter interrupt is disabled.
900 */
901 if (disable_int_src)
0c9a057c
HS
902 devpriv->counter_int_enabs &= ~(S626_OVERMASK(chan) |
903 S626_INDXMASK(chan));
17afeac2
IA
904
905 /*
906 * While retaining CounterB and LatchSrc configurations, program the
907 * new counter operating mode.
908 */
0c9a057c 909 s626_debi_replace(dev, S626_LP_CRA(chan),
622ec01a 910 S626_CRAMSK_INDXSRC_B | S626_CRAMSK_CNTSRC_B, cra);
0c9a057c 911 s626_debi_replace(dev, S626_LP_CRB(chan),
d8515652 912 ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_CLKENAB_A), crb);
17afeac2
IA
913}
914
31de1948 915static void s626_set_mode_b(struct comedi_device *dev,
0c9a057c 916 unsigned int chan, uint16_t setup,
31de1948 917 uint16_t disable_int_src)
17afeac2
IA
918{
919 struct s626_private *devpriv = dev->private;
920 uint16_t cra;
921 uint16_t crb;
0830ada5 922 unsigned cntsrc, clkmult, clkpol;
17afeac2
IA
923
924 /* Initialize CRA and CRB images. */
2cea19fa
IA
925 /* IndexSrc is passed through. */
926 cra = S626_SET_CRA_INDXSRC_B(S626_GET_STD_INDXSRC(setup));
17afeac2
IA
927
928 /* Reset event captures and disable interrupts. */
0830ada5 929 crb = S626_SET_CRB_INTRESETCMD(1) | S626_SET_CRB_INTRESET_B(1);
17afeac2 930 /* Clock enable is passed through. */
0830ada5 931 crb |= S626_SET_CRB_CLKENAB_B(S626_GET_STD_CLKENAB(setup));
17afeac2 932 /* Preload trigger source is passed through. */
0830ada5 933 crb |= S626_SET_CRB_LOADSRC_B(S626_GET_STD_LOADSRC(setup));
17afeac2
IA
934
935 /* Force IntSrc to Disabled if disable_int_src is asserted. */
936 if (!disable_int_src)
0830ada5 937 crb |= S626_SET_CRB_INTSRC_B(S626_GET_STD_INTSRC(setup));
17afeac2
IA
938
939 /* Populate all mode-dependent attributes of CRA & CRB images. */
0830ada5
IA
940 clkpol = S626_GET_STD_CLKPOL(setup);
941 switch (S626_GET_STD_ENCMODE(setup)) {
622ec01a
IA
942 case S626_ENCMODE_TIMER: /* Timer Mode: */
943 /* CntSrcB<1> selects system clock */
0830ada5 944 cntsrc = S626_CNTSRC_SYSCLK;
622ec01a 945 /* with direction (CntSrcB<0>) obtained from ClkPol. */
0830ada5 946 cntsrc |= clkpol;
17afeac2 947 /* ClkPolB behaves as always-on clock enable. */
0830ada5 948 clkpol = 1;
17afeac2 949 /* ClkMultB must be 1x. */
7a1046e5 950 clkmult = S626_CLKMULT_1X;
17afeac2 951 break;
622ec01a
IA
952 case S626_ENCMODE_EXTENDER: /* Extender Mode: */
953 /* CntSrcB source is OverflowA (same as "timer") */
0830ada5 954 cntsrc = S626_CNTSRC_SYSCLK;
17afeac2 955 /* with direction obtained from ClkPol. */
0830ada5 956 cntsrc |= clkpol;
17afeac2 957 /* ClkPolB controls IndexB -- always set to active. */
0830ada5 958 clkpol = 1;
17afeac2 959 /* ClkMultB selects OverflowA as the clock source. */
7a1046e5 960 clkmult = S626_CLKMULT_SPECIAL;
17afeac2
IA
961 break;
962 default: /* Counter Mode: */
963 /* Select ENC_C and ENC_D as clock/direction inputs. */
0830ada5 964 cntsrc = S626_CNTSRC_ENCODER;
17afeac2 965 /* ClkPol is passed through. */
17afeac2 966 /* Force ClkMult to x1 if not legal, otherwise pass through. */
0830ada5 967 clkmult = S626_GET_STD_CLKMULT(setup);
7a1046e5
IA
968 if (clkmult == S626_CLKMULT_SPECIAL)
969 clkmult = S626_CLKMULT_1X;
17afeac2
IA
970 break;
971 }
0830ada5
IA
972 cra |= S626_SET_CRA_CNTSRC_B(cntsrc);
973 crb |= S626_SET_CRB_CLKPOL_B(clkpol) | S626_SET_CRB_CLKMULT_B(clkmult);
17afeac2
IA
974
975 /*
976 * Force positive index polarity if IndxSrc is software-driven only,
977 * otherwise pass it through.
978 */
2cea19fa 979 if (S626_GET_STD_INDXSRC(setup) != S626_INDXSRC_SOFT)
0830ada5 980 crb |= S626_SET_CRB_INDXPOL_B(S626_GET_STD_INDXPOL(setup));
17afeac2
IA
981
982 /*
983 * If IntSrc has been forced to Disabled, update the MISC2 interrupt
984 * enable mask to indicate the counter interrupt is disabled.
985 */
986 if (disable_int_src)
0c9a057c
HS
987 devpriv->counter_int_enabs &= ~(S626_OVERMASK(chan) |
988 S626_INDXMASK(chan));
17afeac2
IA
989
990 /*
991 * While retaining CounterA and LatchSrc configurations, program the
992 * new counter operating mode.
993 */
0c9a057c 994 s626_debi_replace(dev, S626_LP_CRA(chan),
622ec01a 995 ~(S626_CRAMSK_INDXSRC_B | S626_CRAMSK_CNTSRC_B), cra);
0c9a057c 996 s626_debi_replace(dev, S626_LP_CRB(chan),
d8515652 997 S626_CRBMSK_CLKENAB_A | S626_CRBMSK_LATCHSRC, crb);
17afeac2
IA
998}
999
b35d6a38 1000static void s626_set_mode(struct comedi_device *dev,
0c9a057c 1001 unsigned int chan,
b35d6a38
HS
1002 uint16_t setup, uint16_t disable_int_src)
1003{
0c9a057c
HS
1004 if (chan < 3)
1005 s626_set_mode_a(dev, chan, setup, disable_int_src);
b35d6a38 1006 else
0c9a057c 1007 s626_set_mode_b(dev, chan, setup, disable_int_src);
b35d6a38
HS
1008}
1009
17afeac2
IA
1010/*
1011 * Return/set a counter's enable. enab: 0=always enabled, 1=enabled by index.
1012 */
c718f4a1 1013static void s626_set_enable(struct comedi_device *dev,
0c9a057c 1014 unsigned int chan, uint16_t enab)
17afeac2 1015{
c718f4a1
HS
1016 unsigned int mask = S626_CRBMSK_INTCTRL;
1017 unsigned int set;
17afeac2 1018
0c9a057c 1019 if (chan < 3) {
c718f4a1
HS
1020 mask |= S626_CRBMSK_CLKENAB_A;
1021 set = S626_SET_CRB_CLKENAB_A(enab);
1022 } else {
1023 mask |= S626_CRBMSK_CLKENAB_B;
1024 set = S626_SET_CRB_CLKENAB_B(enab);
1025 }
0c9a057c 1026 s626_debi_replace(dev, S626_LP_CRB(chan), ~mask, set);
17afeac2
IA
1027}
1028
4487502e
HS
1029#ifdef unused
1030static uint16_t s626_get_enable(struct comedi_device *dev,
0c9a057c 1031 unsigned int chan)
17afeac2 1032{
0c9a057c 1033 uint16_t crb = s626_debi_read(dev, S626_LP_CRB(chan));
17afeac2 1034
193725ba
HS
1035 return (chan < 3) ? S626_GET_CRB_CLKENAB_A(crb)
1036 : S626_GET_CRB_CLKENAB_B(crb);
17afeac2 1037}
4487502e 1038#endif
17afeac2
IA
1039
1040#ifdef unused
31de1948 1041static uint16_t s626_get_latch_source(struct comedi_device *dev,
0c9a057c 1042 unsigned int chan)
17afeac2 1043{
0c9a057c 1044 return S626_GET_CRB_LATCHSRC(s626_debi_read(dev, S626_LP_CRB(chan)));
17afeac2
IA
1045}
1046#endif
1047
1048/*
1049 * Return/set the event that will trigger transfer of the preload
1050 * register into the counter. 0=ThisCntr_Index, 1=ThisCntr_Overflow,
1051 * 2=OverflowA (B counters only), 3=disabled.
1052 */
7f03b749 1053static void s626_set_load_trig(struct comedi_device *dev,
0c9a057c 1054 unsigned int chan, uint16_t trig)
17afeac2 1055{
7f03b749
HS
1056 uint16_t reg;
1057 uint16_t mask;
1058 uint16_t set;
17afeac2 1059
0c9a057c
HS
1060 if (chan < 3) {
1061 reg = S626_LP_CRA(chan);
7f03b749
HS
1062 mask = S626_CRAMSK_LOADSRC_A;
1063 set = S626_SET_CRA_LOADSRC_A(trig);
1064 } else {
0c9a057c 1065 reg = S626_LP_CRB(chan);
7f03b749
HS
1066 mask = S626_CRBMSK_LOADSRC_B | S626_CRBMSK_INTCTRL;
1067 set = S626_SET_CRB_LOADSRC_B(trig);
1068 }
1069 s626_debi_replace(dev, reg, ~mask, set);
17afeac2
IA
1070}
1071
c35b86a7
HS
1072#ifdef unused
1073static uint16_t s626_get_load_trig(struct comedi_device *dev,
0c9a057c 1074 unsigned int chan)
17afeac2 1075{
0c9a057c 1076 if (chan < 3)
c35b86a7 1077 return S626_GET_CRA_LOADSRC_A(s626_debi_read(dev,
0c9a057c 1078 S626_LP_CRA(chan)));
c35b86a7
HS
1079 else
1080 return S626_GET_CRB_LOADSRC_B(s626_debi_read(dev,
0c9a057c 1081 S626_LP_CRB(chan)));
17afeac2 1082}
c35b86a7 1083#endif
17afeac2 1084
bc284a2a
IA
1085/*
1086 * Return/set counter interrupt source and clear any captured
1087 * index/overflow events. int_source: 0=Disabled, 1=OverflowOnly,
1088 * 2=IndexOnly, 3=IndexAndOverflow.
1089 */
253e2ee4 1090static void s626_set_int_src(struct comedi_device *dev,
0c9a057c 1091 unsigned int chan, uint16_t int_source)
bc284a2a
IA
1092{
1093 struct s626_private *devpriv = dev->private;
0c9a057c
HS
1094 uint16_t cra_reg = S626_LP_CRA(chan);
1095 uint16_t crb_reg = S626_LP_CRB(chan);
bc284a2a 1096
0c9a057c 1097 if (chan < 3) {
253e2ee4
HS
1098 /* Reset any pending counter overflow or index captures */
1099 s626_debi_replace(dev, crb_reg, ~S626_CRBMSK_INTCTRL,
1100 S626_SET_CRB_INTRESETCMD(1) |
1101 S626_SET_CRB_INTRESET_A(1));
1102
1103 /* Program counter interrupt source */
1104 s626_debi_replace(dev, cra_reg, ~S626_CRAMSK_INTSRC_A,
1105 S626_SET_CRA_INTSRC_A(int_source));
1106 } else {
1107 uint16_t crb;
bc284a2a 1108
253e2ee4
HS
1109 /* Cache writeable CRB register image */
1110 crb = s626_debi_read(dev, crb_reg);
1111 crb &= ~S626_CRBMSK_INTCTRL;
bc284a2a 1112
253e2ee4
HS
1113 /* Reset any pending counter overflow or index captures */
1114 s626_debi_write(dev, crb_reg,
1115 crb | S626_SET_CRB_INTRESETCMD(1) |
1116 S626_SET_CRB_INTRESET_B(1));
bc284a2a 1117
253e2ee4
HS
1118 /* Program counter interrupt source */
1119 s626_debi_write(dev, crb_reg,
1120 (crb & ~S626_CRBMSK_INTSRC_B) |
1121 S626_SET_CRB_INTSRC_B(int_source));
1122 }
bc284a2a
IA
1123
1124 /* Update MISC2 interrupt enable mask. */
0c9a057c
HS
1125 devpriv->counter_int_enabs &= ~(S626_OVERMASK(chan) |
1126 S626_INDXMASK(chan));
f76d02f8
HS
1127 switch (int_source) {
1128 case 0:
1129 default:
1130 break;
1131 case 1:
0c9a057c 1132 devpriv->counter_int_enabs |= S626_OVERMASK(chan);
f76d02f8
HS
1133 break;
1134 case 2:
0c9a057c 1135 devpriv->counter_int_enabs |= S626_INDXMASK(chan);
f76d02f8
HS
1136 break;
1137 case 3:
0c9a057c
HS
1138 devpriv->counter_int_enabs |= (S626_OVERMASK(chan) |
1139 S626_INDXMASK(chan));
f76d02f8
HS
1140 break;
1141 }
bc284a2a
IA
1142}
1143
13f2609d
HS
1144#ifdef unused
1145static uint16_t s626_get_int_src(struct comedi_device *dev,
0c9a057c 1146 unsigned int chan)
bc284a2a 1147{
13f2609d
HS
1148 if (chan < 3)
1149 return S626_GET_CRA_INTSRC_A(s626_debi_read(dev,
0c9a057c 1150 S626_LP_CRA(chan)));
13f2609d
HS
1151 else
1152 return S626_GET_CRB_INTSRC_B(s626_debi_read(dev,
0c9a057c 1153 S626_LP_CRB(chan)));
bc284a2a 1154}
13f2609d 1155#endif
bc284a2a
IA
1156
1157#ifdef unused
1158/*
1159 * Return/set the clock multiplier.
1160 */
31de1948 1161static void s626_set_clk_mult(struct comedi_device *dev,
0c9a057c 1162 unsigned int chan, uint16_t value)
bc284a2a 1163{
0c9a057c
HS
1164 uint16_t mode;
1165
1166 mode = s626_get_mode(dev, chan);
1167 mode &= ~S626_STDMSK_CLKMULT;
1168 mode |= S626_SET_STD_CLKMULT(value);
1169
1170 s626_set_mode(dev, chan, mode, false);
bc284a2a
IA
1171}
1172
31de1948 1173static uint16_t s626_get_clk_mult(struct comedi_device *dev,
0c9a057c 1174 unsigned int chan)
bc284a2a 1175{
0c9a057c 1176 return S626_GET_STD_CLKMULT(s626_get_mode(dev, chan));
bc284a2a
IA
1177}
1178
1179/*
1180 * Return/set the clock polarity.
1181 */
31de1948 1182static void s626_set_clk_pol(struct comedi_device *dev,
0c9a057c 1183 unsigned int chan, uint16_t value)
bc284a2a 1184{
0c9a057c
HS
1185 uint16_t mode;
1186
1187 mode = s626_get_mode(dev, chan);
1188 mode &= ~S626_STDMSK_CLKPOL;
1189 mode |= S626_SET_STD_CLKPOL(value);
1190
1191 s626_set_mode(dev, chan, mode, false);
bc284a2a
IA
1192}
1193
31de1948 1194static uint16_t s626_get_clk_pol(struct comedi_device *dev,
0c9a057c 1195 unsigned int chan)
bc284a2a 1196{
0c9a057c 1197 return S626_GET_STD_CLKPOL(s626_get_mode(dev, chan));
bc284a2a
IA
1198}
1199
1200/*
622ec01a 1201 * Return/set the encoder mode.
bc284a2a 1202 */
622ec01a 1203static void s626_set_enc_mode(struct comedi_device *dev,
0c9a057c 1204 unsigned int chan, uint16_t value)
bc284a2a 1205{
0c9a057c
HS
1206 uint16_t mode;
1207
1208 mode = s626_get_mode(dev, chan);
1209 mode &= ~S626_STDMSK_ENCMODE;
1210 mode |= S626_SET_STD_ENCMODE(value);
1211
1212 s626_set_mode(dev, chan, mode, false);
bc284a2a
IA
1213}
1214
622ec01a 1215static uint16_t s626_get_enc_mode(struct comedi_device *dev,
0c9a057c 1216 unsigned int chan)
bc284a2a 1217{
0c9a057c 1218 return S626_GET_STD_ENCMODE(s626_get_mode(dev, chan));
bc284a2a
IA
1219}
1220
1221/*
1222 * Return/set the index polarity.
1223 */
31de1948 1224static void s626_set_index_pol(struct comedi_device *dev,
0c9a057c 1225 unsigned int chan, uint16_t value)
bc284a2a 1226{
0c9a057c
HS
1227 uint16_t mode;
1228
1229 mode = s626_get_mode(dev, chan);
1230 mode &= ~S626_STDMSK_INDXPOL;
1231 mode |= S626_SET_STD_INDXPOL(value != 0);
1232
1233 s626_set_mode(dev, chan, mode, false);
bc284a2a
IA
1234}
1235
31de1948 1236static uint16_t s626_get_index_pol(struct comedi_device *dev,
0c9a057c 1237 unsigned int chan)
bc284a2a 1238{
0c9a057c 1239 return S626_GET_STD_INDXPOL(s626_get_mode(dev, chan));
bc284a2a
IA
1240}
1241
1242/*
1243 * Return/set the index source.
1244 */
31de1948 1245static void s626_set_index_src(struct comedi_device *dev,
0c9a057c 1246 unsigned int chan, uint16_t value)
bc284a2a 1247{
0c9a057c
HS
1248 uint16_t mode;
1249
1250 mode = s626_get_mode(dev, chan);
1251 mode &= ~S626_STDMSK_INDXSRC;
1252 mode |= S626_SET_STD_INDXSRC(value != 0);
1253
1254 s626_set_mode(dev, chan, mode, false);
bc284a2a
IA
1255}
1256
31de1948 1257static uint16_t s626_get_index_src(struct comedi_device *dev,
0c9a057c 1258 unsigned int chan)
bc284a2a 1259{
0c9a057c 1260 return S626_GET_STD_INDXSRC(s626_get_mode(dev, chan));
bc284a2a
IA
1261}
1262#endif
1263
1264/*
1265 * Generate an index pulse.
1266 */
92249e1f 1267static void s626_pulse_index(struct comedi_device *dev,
0c9a057c 1268 unsigned int chan)
bc284a2a 1269{
0c9a057c 1270 if (chan < 3) {
92249e1f 1271 uint16_t cra;
bc284a2a 1272
0c9a057c 1273 cra = s626_debi_read(dev, S626_LP_CRA(chan));
bc284a2a 1274
92249e1f 1275 /* Pulse index */
0c9a057c 1276 s626_debi_write(dev, S626_LP_CRA(chan),
92249e1f 1277 (cra ^ S626_CRAMSK_INDXPOL_A));
0c9a057c 1278 s626_debi_write(dev, S626_LP_CRA(chan), cra);
92249e1f
HS
1279 } else {
1280 uint16_t crb;
bc284a2a 1281
0c9a057c 1282 crb = s626_debi_read(dev, S626_LP_CRB(chan));
92249e1f
HS
1283 crb &= ~S626_CRBMSK_INTCTRL;
1284
1285 /* Pulse index */
0c9a057c 1286 s626_debi_write(dev, S626_LP_CRB(chan),
92249e1f 1287 (crb ^ S626_CRBMSK_INDXPOL_B));
0c9a057c 1288 s626_debi_write(dev, S626_LP_CRB(chan), crb);
92249e1f 1289 }
bc284a2a
IA
1290}
1291
5fd4b711 1292static unsigned int s626_ai_reg_to_uint(unsigned int data)
11e865c1 1293{
5fd4b711 1294 return ((data >> 18) & 0x3fff) ^ 0x2000;
020c44f3 1295}
8231eb56 1296
6baffbc2
HS
1297static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan)
1298{
100b4edc
HS
1299 unsigned int group = chan / 16;
1300 unsigned int mask = 1 << (chan - (16 * group));
6baffbc2
HS
1301 unsigned int status;
1302
6baffbc2 1303 /* set channel to capture positive edge */
d8515652
IA
1304 status = s626_debi_read(dev, S626_LP_RDEDGSEL(group));
1305 s626_debi_write(dev, S626_LP_WREDGSEL(group), mask | status);
6baffbc2
HS
1306
1307 /* enable interrupt on selected channel */
d8515652
IA
1308 status = s626_debi_read(dev, S626_LP_RDINTSEL(group));
1309 s626_debi_write(dev, S626_LP_WRINTSEL(group), mask | status);
6baffbc2
HS
1310
1311 /* enable edge capture write command */
d8515652 1312 s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_EDCAP);
6baffbc2
HS
1313
1314 /* enable edge capture on selected channel */
d8515652
IA
1315 status = s626_debi_read(dev, S626_LP_RDCAPSEL(group));
1316 s626_debi_write(dev, S626_LP_WRCAPSEL(group), mask | status);
6baffbc2
HS
1317
1318 return 0;
1319}
1320
1321static int s626_dio_reset_irq(struct comedi_device *dev, unsigned int group,
1322 unsigned int mask)
1323{
6baffbc2 1324 /* disable edge capture write command */
d8515652 1325 s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_NOEDCAP);
6baffbc2
HS
1326
1327 /* enable edge capture on selected channel */
d8515652 1328 s626_debi_write(dev, S626_LP_WRCAPSEL(group), mask);
6baffbc2
HS
1329
1330 return 0;
1331}
1332
1333static int s626_dio_clear_irq(struct comedi_device *dev)
1334{
1335 unsigned int group;
1336
1337 /* disable edge capture write command */
d8515652 1338 s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_NOEDCAP);
6baffbc2 1339
100b4edc
HS
1340 /* clear all dio pending events and interrupt */
1341 for (group = 0; group < S626_DIO_BANKS; group++)
d8515652 1342 s626_debi_write(dev, S626_LP_WRCAPSEL(group), 0xffff);
6baffbc2
HS
1343
1344 return 0;
1345}
1346
31de1948
IA
1347static void s626_handle_dio_interrupt(struct comedi_device *dev,
1348 uint16_t irqbit, uint8_t group)
65a17c29
HS
1349{
1350 struct s626_private *devpriv = dev->private;
1351 struct comedi_subdevice *s = dev->read_subdev;
1352 struct comedi_cmd *cmd = &s->async->cmd;
1353
1354 s626_dio_reset_irq(dev, group, irqbit);
1355
1356 if (devpriv->ai_cmd_running) {
1357 /* check if interrupt is an ai acquisition start trigger */
1358 if ((irqbit >> (cmd->start_arg - (16 * group))) == 1 &&
1359 cmd->start_src == TRIG_EXT) {
1360 /* Start executing the RPS program */
d8515652 1361 s626_mc_enable(dev, S626_MC1_ERPS1, S626_P_MC1);
65a17c29
HS
1362
1363 if (cmd->scan_begin_src == TRIG_EXT)
1364 s626_dio_set_irq(dev, cmd->scan_begin_arg);
1365 }
1366 if ((irqbit >> (cmd->scan_begin_arg - (16 * group))) == 1 &&
1367 cmd->scan_begin_src == TRIG_EXT) {
ddd9813e 1368 /* Trigger ADC scan loop start */
d8515652 1369 s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2);
65a17c29
HS
1370
1371 if (cmd->convert_src == TRIG_EXT) {
1372 devpriv->ai_convert_count = cmd->chanlist_len;
1373
1374 s626_dio_set_irq(dev, cmd->convert_arg);
1375 }
1376
1377 if (cmd->convert_src == TRIG_TIMER) {
65a17c29 1378 devpriv->ai_convert_count = cmd->chanlist_len;
0c9a057c 1379 s626_set_enable(dev, 5, S626_CLKENAB_ALWAYS);
65a17c29
HS
1380 }
1381 }
1382 if ((irqbit >> (cmd->convert_arg - (16 * group))) == 1 &&
1383 cmd->convert_src == TRIG_EXT) {
ddd9813e 1384 /* Trigger ADC scan loop start */
d8515652 1385 s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2);
65a17c29
HS
1386
1387 devpriv->ai_convert_count--;
1388 if (devpriv->ai_convert_count > 0)
1389 s626_dio_set_irq(dev, cmd->convert_arg);
1390 }
1391 }
1392}
1393
31de1948 1394static void s626_check_dio_interrupts(struct comedi_device *dev)
65a17c29
HS
1395{
1396 uint16_t irqbit;
1397 uint8_t group;
1398
1399 for (group = 0; group < S626_DIO_BANKS; group++) {
65a17c29 1400 /* read interrupt type */
d8515652 1401 irqbit = s626_debi_read(dev, S626_LP_RDCAPFLG(group));
65a17c29
HS
1402
1403 /* check if interrupt is generated from dio channels */
1404 if (irqbit) {
31de1948 1405 s626_handle_dio_interrupt(dev, irqbit, group);
65a17c29
HS
1406 return;
1407 }
1408 }
1409}
1410
31de1948 1411static void s626_check_counter_interrupts(struct comedi_device *dev)
0b9675d5
HS
1412{
1413 struct s626_private *devpriv = dev->private;
1414 struct comedi_subdevice *s = dev->read_subdev;
1415 struct comedi_async *async = s->async;
1416 struct comedi_cmd *cmd = &async->cmd;
0b9675d5
HS
1417 uint16_t irqbit;
1418
1419 /* read interrupt type */
d8515652 1420 irqbit = s626_debi_read(dev, S626_LP_RDMISC2);
0b9675d5
HS
1421
1422 /* check interrupt on counters */
d8515652 1423 if (irqbit & S626_IRQ_COINT1A) {
0b9675d5 1424 /* clear interrupt capture flag */
0c9a057c 1425 s626_reset_cap_flags(dev, 0);
0b9675d5 1426 }
d8515652 1427 if (irqbit & S626_IRQ_COINT2A) {
0b9675d5 1428 /* clear interrupt capture flag */
0c9a057c 1429 s626_reset_cap_flags(dev, 1);
0b9675d5 1430 }
d8515652 1431 if (irqbit & S626_IRQ_COINT3A) {
0b9675d5 1432 /* clear interrupt capture flag */
0c9a057c 1433 s626_reset_cap_flags(dev, 2);
0b9675d5 1434 }
d8515652 1435 if (irqbit & S626_IRQ_COINT1B) {
0b9675d5 1436 /* clear interrupt capture flag */
0c9a057c 1437 s626_reset_cap_flags(dev, 3);
0b9675d5 1438 }
d8515652 1439 if (irqbit & S626_IRQ_COINT2B) {
0b9675d5 1440 /* clear interrupt capture flag */
0c9a057c 1441 s626_reset_cap_flags(dev, 4);
0b9675d5
HS
1442
1443 if (devpriv->ai_convert_count > 0) {
1444 devpriv->ai_convert_count--;
1445 if (devpriv->ai_convert_count == 0)
0c9a057c 1446 s626_set_enable(dev, 4, S626_CLKENAB_INDEX);
0b9675d5
HS
1447
1448 if (cmd->convert_src == TRIG_TIMER) {
ddd9813e 1449 /* Trigger ADC scan loop start */
d8515652
IA
1450 s626_mc_enable(dev, S626_MC2_ADC_RPS,
1451 S626_P_MC2);
0b9675d5
HS
1452 }
1453 }
1454 }
d8515652 1455 if (irqbit & S626_IRQ_COINT3B) {
0b9675d5 1456 /* clear interrupt capture flag */
0c9a057c 1457 s626_reset_cap_flags(dev, 5);
0b9675d5
HS
1458
1459 if (cmd->scan_begin_src == TRIG_TIMER) {
ddd9813e 1460 /* Trigger ADC scan loop start */
d8515652 1461 s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2);
0b9675d5
HS
1462 }
1463
1464 if (cmd->convert_src == TRIG_TIMER) {
0b9675d5 1465 devpriv->ai_convert_count = cmd->chanlist_len;
0c9a057c 1466 s626_set_enable(dev, 4, S626_CLKENAB_ALWAYS);
0b9675d5
HS
1467 }
1468 }
1469}
1470
31de1948 1471static bool s626_handle_eos_interrupt(struct comedi_device *dev)
4c2d13e0
HS
1472{
1473 struct s626_private *devpriv = dev->private;
1474 struct comedi_subdevice *s = dev->read_subdev;
1475 struct comedi_async *async = s->async;
1476 struct comedi_cmd *cmd = &async->cmd;
1477 /*
1478 * Init ptr to DMA buffer that holds new ADC data. We skip the
1479 * first uint16_t in the buffer because it contains junk data
1480 * from the final ADC of the previous poll list scan.
1481 */
5fd4b711 1482 uint32_t *readaddr = (uint32_t *)devpriv->ana_buf.logical_base + 1;
4c2d13e0
HS
1483 int i;
1484
1485 /* get the data and hand it over to comedi */
1486 for (i = 0; i < cmd->chanlist_len; i++) {
5fd4b711 1487 unsigned short tempdata;
4c2d13e0
HS
1488
1489 /*
1490 * Convert ADC data to 16-bit integer values and copy
1491 * to application buffer.
1492 */
5fd4b711 1493 tempdata = s626_ai_reg_to_uint(*readaddr);
4c2d13e0
HS
1494 readaddr++;
1495
1496 /* put data into read buffer */
4c2d13e0
HS
1497 cfc_write_to_buffer(s, tempdata);
1498 }
1499
1500 /* end of scan occurs */
1501 async->events |= COMEDI_CB_EOS;
1502
27cb9814 1503 if (cmd->stop_src == TRIG_COUNT) {
4c2d13e0 1504 devpriv->ai_sample_count--;
27cb9814
HS
1505 if (devpriv->ai_sample_count <= 0) {
1506 devpriv->ai_cmd_running = 0;
27cb9814 1507 async->events |= COMEDI_CB_EOA;
27cb9814 1508 }
4c2d13e0
HS
1509 }
1510
1511 if (devpriv->ai_cmd_running && cmd->scan_begin_src == TRIG_EXT)
1512 s626_dio_set_irq(dev, cmd->scan_begin_arg);
1513
365dae93 1514 comedi_handle_events(dev, s);
4c2d13e0 1515
365dae93 1516 return !devpriv->ai_cmd_running;
4c2d13e0
HS
1517}
1518
020c44f3
HS
1519static irqreturn_t s626_irq_handler(int irq, void *d)
1520{
1521 struct comedi_device *dev = d;
020c44f3 1522 unsigned long flags;
020c44f3 1523 uint32_t irqtype, irqstatus;
11e865c1 1524
a7401cdd 1525 if (!dev->attached)
020c44f3 1526 return IRQ_NONE;
8ee52611 1527 /* lock to avoid race with comedi_poll */
020c44f3 1528 spin_lock_irqsave(&dev->spinlock, flags);
11e865c1 1529
020c44f3 1530 /* save interrupt enable register state */
de9cd5ca 1531 irqstatus = readl(dev->mmio + S626_P_IER);
11e865c1 1532
020c44f3 1533 /* read interrupt type */
de9cd5ca 1534 irqtype = readl(dev->mmio + S626_P_ISR);
11e865c1 1535
020c44f3 1536 /* disable master interrupt */
de9cd5ca 1537 writel(0, dev->mmio + S626_P_IER);
11e865c1 1538
020c44f3 1539 /* clear interrupt */
de9cd5ca 1540 writel(irqtype, dev->mmio + S626_P_ISR);
11e865c1 1541
020c44f3 1542 switch (irqtype) {
d8515652 1543 case S626_IRQ_RPS1: /* end_of_scan occurs */
31de1948 1544 if (s626_handle_eos_interrupt(dev))
020c44f3 1545 irqstatus = 0;
020c44f3 1546 break;
d8515652 1547 case S626_IRQ_GPIO3: /* check dio and counter interrupt */
020c44f3 1548 /* s626_dio_clear_irq(dev); */
31de1948
IA
1549 s626_check_dio_interrupts(dev);
1550 s626_check_counter_interrupts(dev);
0b9675d5 1551 break;
020c44f3 1552 }
11e865c1 1553
020c44f3 1554 /* enable interrupt */
de9cd5ca 1555 writel(irqstatus, dev->mmio + S626_P_IER);
b6c77757 1556
020c44f3
HS
1557 spin_unlock_irqrestore(&dev->spinlock, flags);
1558 return IRQ_HANDLED;
1559}
b6c77757 1560
020c44f3 1561/*
8ee52611 1562 * This function builds the RPS program for hardware driven acquisition.
020c44f3 1563 */
31de1948 1564static void s626_reset_adc(struct comedi_device *dev, uint8_t *ppl)
020c44f3 1565{
7f2f7e05 1566 struct s626_private *devpriv = dev->private;
9c9ab3c1
HS
1567 struct comedi_subdevice *s = dev->read_subdev;
1568 struct comedi_cmd *cmd = &s->async->cmd;
f1f7efce
IA
1569 uint32_t *rps;
1570 uint32_t jmp_adrs;
020c44f3
HS
1571 uint16_t i;
1572 uint16_t n;
f1f7efce 1573 uint32_t local_ppl;
11e865c1 1574
c5cf4606 1575 /* Stop RPS program in case it is currently running */
d8515652 1576 s626_mc_disable(dev, S626_MC1_ERPS1, S626_P_MC1);
11e865c1 1577
8ee52611 1578 /* Set starting logical address to write RPS commands. */
f1f7efce 1579 rps = (uint32_t *)devpriv->rps_buf.logical_base;
11e865c1 1580
25f8fd5e 1581 /* Initialize RPS instruction pointer */
07a36d66 1582 writel((uint32_t)devpriv->rps_buf.physical_base,
de9cd5ca 1583 dev->mmio + S626_P_RPSADDR1);
11e865c1 1584
07a36d66 1585 /* Construct RPS program in rps_buf DMA buffer */
020c44f3 1586 if (cmd != NULL && cmd->scan_begin_src != TRIG_FOLLOW) {
8ee52611 1587 /* Wait for Start trigger. */
d8515652
IA
1588 *rps++ = S626_RPS_PAUSE | S626_RPS_SIGADC;
1589 *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_SIGADC;
020c44f3 1590 }
11e865c1 1591
8ee52611
IA
1592 /*
1593 * SAA7146 BUG WORKAROUND Do a dummy DEBI Write. This is necessary
020c44f3
HS
1594 * because the first RPS DEBI Write following a non-RPS DEBI write
1595 * seems to always fail. If we don't do this dummy write, the ADC
1596 * gain might not be set to the value required for the first slot in
1597 * the poll list; the ADC gain would instead remain unchanged from
1598 * the previously programmed value.
1599 */
020c44f3 1600 /* Write DEBI Write command and address to shadow RAM. */
d8515652
IA
1601 *rps++ = S626_RPS_LDREG | (S626_P_DEBICMD >> 2);
1602 *rps++ = S626_DEBI_CMD_WRWORD | S626_LP_GSEL;
1603 *rps++ = S626_RPS_LDREG | (S626_P_DEBIAD >> 2);
8ee52611 1604 /* Write DEBI immediate data to shadow RAM: */
d8515652
IA
1605 *rps++ = S626_GSEL_BIPOLAR5V; /* arbitrary immediate data value. */
1606 *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_DEBI;
8ee52611 1607 /* Reset "shadow RAM uploaded" flag. */
d8515652
IA
1608 /* Invoke shadow RAM upload. */
1609 *rps++ = S626_RPS_UPLOAD | S626_RPS_DEBI;
1610 /* Wait for shadow upload to finish. */
1611 *rps++ = S626_RPS_PAUSE | S626_RPS_DEBI;
11e865c1 1612
8ee52611
IA
1613 /*
1614 * Digitize all slots in the poll list. This is implemented as a
020c44f3 1615 * for loop to limit the slot count to 16 in case the application
d8515652 1616 * forgot to set the S626_EOPL flag in the final slot.
020c44f3 1617 */
07a36d66
IA
1618 for (devpriv->adc_items = 0; devpriv->adc_items < 16;
1619 devpriv->adc_items++) {
8ee52611
IA
1620 /*
1621 * Convert application's poll list item to private board class
020c44f3
HS
1622 * format. Each app poll list item is an uint8_t with form
1623 * (EOPL,x,x,RANGE,CHAN<3:0>), where RANGE code indicates 0 =
1624 * +-10V, 1 = +-5V, and EOPL = End of Poll List marker.
b6c77757 1625 */
d8515652
IA
1626 local_ppl = (*ppl << 8) | (*ppl & 0x10 ? S626_GSEL_BIPOLAR5V :
1627 S626_GSEL_BIPOLAR10V);
8ee52611
IA
1628
1629 /* Switch ADC analog gain. */
1630 /* Write DEBI command and address to shadow RAM. */
d8515652
IA
1631 *rps++ = S626_RPS_LDREG | (S626_P_DEBICMD >> 2);
1632 *rps++ = S626_DEBI_CMD_WRWORD | S626_LP_GSEL;
8ee52611 1633 /* Write DEBI immediate data to shadow RAM. */
d8515652 1634 *rps++ = S626_RPS_LDREG | (S626_P_DEBIAD >> 2);
f1f7efce 1635 *rps++ = local_ppl;
8ee52611 1636 /* Reset "shadow RAM uploaded" flag. */
d8515652 1637 *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_DEBI;
8ee52611 1638 /* Invoke shadow RAM upload. */
d8515652 1639 *rps++ = S626_RPS_UPLOAD | S626_RPS_DEBI;
8ee52611 1640 /* Wait for shadow upload to finish. */
d8515652 1641 *rps++ = S626_RPS_PAUSE | S626_RPS_DEBI;
8ee52611 1642 /* Select ADC analog input channel. */
d8515652 1643 *rps++ = S626_RPS_LDREG | (S626_P_DEBICMD >> 2);
8ee52611 1644 /* Write DEBI command and address to shadow RAM. */
d8515652
IA
1645 *rps++ = S626_DEBI_CMD_WRWORD | S626_LP_ISEL;
1646 *rps++ = S626_RPS_LDREG | (S626_P_DEBIAD >> 2);
8ee52611 1647 /* Write DEBI immediate data to shadow RAM. */
f1f7efce 1648 *rps++ = local_ppl;
8ee52611 1649 /* Reset "shadow RAM uploaded" flag. */
d8515652 1650 *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_DEBI;
8ee52611 1651 /* Invoke shadow RAM upload. */
d8515652 1652 *rps++ = S626_RPS_UPLOAD | S626_RPS_DEBI;
8ee52611 1653 /* Wait for shadow upload to finish. */
d8515652 1654 *rps++ = S626_RPS_PAUSE | S626_RPS_DEBI;
11e865c1 1655
8ee52611
IA
1656 /*
1657 * Delay at least 10 microseconds for analog input settling.
d8515652
IA
1658 * Instead of padding with NOPs, we use S626_RPS_JUMP
1659 * instructions here; this allows us to produce a longer delay
1660 * than is possible with NOPs because each S626_RPS_JUMP
1661 * flushes the RPS' instruction prefetch pipeline.
020c44f3 1662 */
f1f7efce 1663 jmp_adrs =
07a36d66 1664 (uint32_t)devpriv->rps_buf.physical_base +
f1f7efce 1665 (uint32_t)((unsigned long)rps -
07a36d66
IA
1666 (unsigned long)devpriv->
1667 rps_buf.logical_base);
d8515652 1668 for (i = 0; i < (10 * S626_RPSCLK_PER_US / 2); i++) {
f1f7efce 1669 jmp_adrs += 8; /* Repeat to implement time delay: */
d8515652
IA
1670 /* Jump to next RPS instruction. */
1671 *rps++ = S626_RPS_JUMP;
f1f7efce 1672 *rps++ = jmp_adrs;
020c44f3 1673 }
11e865c1 1674
020c44f3 1675 if (cmd != NULL && cmd->convert_src != TRIG_NOW) {
8ee52611 1676 /* Wait for Start trigger. */
d8515652
IA
1677 *rps++ = S626_RPS_PAUSE | S626_RPS_SIGADC;
1678 *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_SIGADC;
020c44f3 1679 }
8ee52611
IA
1680 /* Start ADC by pulsing GPIO1. */
1681 /* Begin ADC Start pulse. */
d8515652
IA
1682 *rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2);
1683 *rps++ = S626_GPIO_BASE | S626_GPIO1_LO;
1684 *rps++ = S626_RPS_NOP;
8ee52611
IA
1685 /* VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. */
1686 /* End ADC Start pulse. */
d8515652
IA
1687 *rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2);
1688 *rps++ = S626_GPIO_BASE | S626_GPIO1_HI;
8ee52611
IA
1689 /*
1690 * Wait for ADC to complete (GPIO2 is asserted high when ADC not
020c44f3
HS
1691 * busy) and for data from previous conversion to shift into FB
1692 * BUFFER 1 register.
1693 */
d8515652
IA
1694 /* Wait for ADC done. */
1695 *rps++ = S626_RPS_PAUSE | S626_RPS_GPIO2;
11e865c1 1696
8ee52611 1697 /* Transfer ADC data from FB BUFFER 1 register to DMA buffer. */
d8515652
IA
1698 *rps++ = S626_RPS_STREG |
1699 (S626_BUGFIX_STREG(S626_P_FB_BUFFER1) >> 2);
f1f7efce
IA
1700 *rps++ = (uint32_t)devpriv->ana_buf.physical_base +
1701 (devpriv->adc_items << 2);
11e865c1 1702
8ee52611
IA
1703 /*
1704 * If this slot's EndOfPollList flag is set, all channels have
1705 * now been processed.
1706 */
d8515652 1707 if (*ppl++ & S626_EOPL) {
07a36d66 1708 devpriv->adc_items++; /* Adjust poll list item count. */
8ee52611 1709 break; /* Exit poll list processing loop. */
020c44f3
HS
1710 }
1711 }
11e865c1 1712
8ee52611
IA
1713 /*
1714 * VERSION 2.01 CHANGE: DELAY CHANGED FROM 250NS to 2US. Allow the
020c44f3
HS
1715 * ADC to stabilize for 2 microseconds before starting the final
1716 * (dummy) conversion. This delay is necessary to allow sufficient
1717 * time between last conversion finished and the start of the dummy
1718 * conversion. Without this delay, the last conversion's data value
1719 * is sometimes set to the previous conversion's data value.
1720 */
d8515652
IA
1721 for (n = 0; n < (2 * S626_RPSCLK_PER_US); n++)
1722 *rps++ = S626_RPS_NOP;
11e865c1 1723
8ee52611
IA
1724 /*
1725 * Start a dummy conversion to cause the data from the last
020c44f3
HS
1726 * conversion of interest to be shifted in.
1727 */
d8515652
IA
1728 /* Begin ADC Start pulse. */
1729 *rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2);
1730 *rps++ = S626_GPIO_BASE | S626_GPIO1_LO;
1731 *rps++ = S626_RPS_NOP;
020c44f3 1732 /* VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. */
d8515652
IA
1733 *rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2); /* End ADC Start pulse. */
1734 *rps++ = S626_GPIO_BASE | S626_GPIO1_HI;
11e865c1 1735
8ee52611
IA
1736 /*
1737 * Wait for the data from the last conversion of interest to arrive
020c44f3
HS
1738 * in FB BUFFER 1 register.
1739 */
d8515652 1740 *rps++ = S626_RPS_PAUSE | S626_RPS_GPIO2; /* Wait for ADC done. */
11e865c1 1741
8ee52611 1742 /* Transfer final ADC data from FB BUFFER 1 register to DMA buffer. */
d8515652 1743 *rps++ = S626_RPS_STREG | (S626_BUGFIX_STREG(S626_P_FB_BUFFER1) >> 2);
f1f7efce
IA
1744 *rps++ = (uint32_t)devpriv->ana_buf.physical_base +
1745 (devpriv->adc_items << 2);
11e865c1 1746
8ee52611
IA
1747 /* Indicate ADC scan loop is finished. */
1748 /* Signal ReadADC() that scan is done. */
d8515652 1749 /* *rps++= S626_RPS_CLRSIGNAL | S626_RPS_SIGADC; */
11e865c1 1750
020c44f3 1751 /* invoke interrupt */
8ee52611 1752 if (devpriv->ai_cmd_running == 1)
d8515652 1753 *rps++ = S626_RPS_IRQ;
11e865c1 1754
8ee52611 1755 /* Restart RPS program at its beginning. */
d8515652 1756 *rps++ = S626_RPS_JUMP; /* Branch to start of RPS program. */
f1f7efce 1757 *rps++ = (uint32_t)devpriv->rps_buf.physical_base;
8ee52611
IA
1758
1759 /* End of RPS program build */
020c44f3 1760}
11e865c1 1761
e4632a71
HS
1762#ifdef unused_code
1763static int s626_ai_rinsn(struct comedi_device *dev,
1764 struct comedi_subdevice *s,
1765 struct comedi_insn *insn,
1766 unsigned int *data)
1767{
1768 struct s626_private *devpriv = dev->private;
8ee52611
IA
1769 uint8_t i;
1770 int32_t *readaddr;
11e865c1 1771
ddd9813e 1772 /* Trigger ADC scan loop start */
d8515652 1773 s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2);
11e865c1 1774
e4632a71 1775 /* Wait until ADC scan loop is finished (RPS Signal 0 reset) */
d8515652 1776 while (s626_mc_test(dev, S626_MC2_ADC_RPS, S626_P_MC2))
e4632a71 1777 ;
11e865c1 1778
e4632a71
HS
1779 /*
1780 * Init ptr to DMA buffer that holds new ADC data. We skip the
1781 * first uint16_t in the buffer because it contains junk data from
1782 * the final ADC of the previous poll list scan.
1783 */
07a36d66 1784 readaddr = (uint32_t *)devpriv->ana_buf.logical_base + 1;
11e865c1 1785
e4632a71
HS
1786 /*
1787 * Convert ADC data to 16-bit integer values and
1788 * copy to application buffer.
1789 */
07a36d66 1790 for (i = 0; i < devpriv->adc_items; i++) {
e4632a71
HS
1791 *data = s626_ai_reg_to_uint(*readaddr++);
1792 data++;
1793 }
11e865c1 1794
e4632a71
HS
1795 return i;
1796}
1797#endif
11e865c1 1798
45b281e4
HS
1799static int s626_ai_eoc(struct comedi_device *dev,
1800 struct comedi_subdevice *s,
1801 struct comedi_insn *insn,
1802 unsigned long context)
1803{
45b281e4
HS
1804 unsigned int status;
1805
de9cd5ca 1806 status = readl(dev->mmio + S626_P_PSR);
45b281e4
HS
1807 if (status & S626_PSR_GPIO2)
1808 return 0;
1809 return -EBUSY;
1810}
1811
020c44f3
HS
1812static int s626_ai_insn_read(struct comedi_device *dev,
1813 struct comedi_subdevice *s,
de9cd5ca
HS
1814 struct comedi_insn *insn,
1815 unsigned int *data)
020c44f3
HS
1816{
1817 uint16_t chan = CR_CHAN(insn->chanspec);
1818 uint16_t range = CR_RANGE(insn->chanspec);
f1f7efce
IA
1819 uint16_t adc_spec = 0;
1820 uint32_t gpio_image;
5fd4b711 1821 uint32_t tmp;
45b281e4 1822 int ret;
020c44f3 1823 int n;
11e865c1 1824
8ee52611
IA
1825 /*
1826 * Convert application's ADC specification into form
020c44f3
HS
1827 * appropriate for register programming.
1828 */
1829 if (range == 0)
d8515652 1830 adc_spec = (chan << 8) | (S626_GSEL_BIPOLAR5V);
020c44f3 1831 else
d8515652 1832 adc_spec = (chan << 8) | (S626_GSEL_BIPOLAR10V);
11e865c1 1833
8ee52611 1834 /* Switch ADC analog gain. */
d8515652 1835 s626_debi_write(dev, S626_LP_GSEL, adc_spec); /* Set gain. */
11e865c1 1836
8ee52611 1837 /* Select ADC analog input channel. */
d8515652 1838 s626_debi_write(dev, S626_LP_ISEL, adc_spec); /* Select channel. */
11e865c1 1839
020c44f3 1840 for (n = 0; n < insn->n; n++) {
8ee52611 1841 /* Delay 10 microseconds for analog input settling. */
020c44f3 1842 udelay(10);
11e865c1 1843
be008602 1844 /* Start ADC by pulsing GPIO1 low */
de9cd5ca 1845 gpio_image = readl(dev->mmio + S626_P_GPIO);
25f8fd5e 1846 /* Assert ADC Start command */
de9cd5ca 1847 writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
25f8fd5e 1848 /* and stretch it out */
de9cd5ca
HS
1849 writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
1850 writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
25f8fd5e 1851 /* Negate ADC Start command */
de9cd5ca 1852 writel(gpio_image | S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
11e865c1 1853
8ee52611
IA
1854 /*
1855 * Wait for ADC to complete (GPIO2 is asserted high when
1856 * ADC not busy) and for data from previous conversion to
1857 * shift into FB BUFFER 1 register.
1858 */
11e865c1 1859
be008602 1860 /* Wait for ADC done */
45b281e4
HS
1861 ret = comedi_timeout(dev, s, insn, s626_ai_eoc, 0);
1862 if (ret)
1863 return ret;
11e865c1 1864
be008602
HS
1865 /* Fetch ADC data */
1866 if (n != 0) {
de9cd5ca 1867 tmp = readl(dev->mmio + S626_P_FB_BUFFER1);
be008602
HS
1868 data[n - 1] = s626_ai_reg_to_uint(tmp);
1869 }
11e865c1 1870
8ee52611
IA
1871 /*
1872 * Allow the ADC to stabilize for 4 microseconds before
020c44f3
HS
1873 * starting the next (final) conversion. This delay is
1874 * necessary to allow sufficient time between last
1875 * conversion finished and the start of the next
1876 * conversion. Without this delay, the last conversion's
1877 * data value is sometimes set to the previous
1878 * conversion's data value.
1879 */
1880 udelay(4);
1881 }
11e865c1 1882
8ee52611
IA
1883 /*
1884 * Start a dummy conversion to cause the data from the
1885 * previous conversion to be shifted in.
1886 */
de9cd5ca 1887 gpio_image = readl(dev->mmio + S626_P_GPIO);
020c44f3 1888 /* Assert ADC Start command */
de9cd5ca 1889 writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
25f8fd5e 1890 /* and stretch it out */
de9cd5ca
HS
1891 writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
1892 writel(gpio_image & ~S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
25f8fd5e 1893 /* Negate ADC Start command */
de9cd5ca 1894 writel(gpio_image | S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
11e865c1 1895
8ee52611 1896 /* Wait for the data to arrive in FB BUFFER 1 register. */
11e865c1 1897
be008602 1898 /* Wait for ADC done */
571845c6
CS
1899 ret = comedi_timeout(dev, s, insn, s626_ai_eoc, 0);
1900 if (ret)
1901 return ret;
11e865c1 1902
8ee52611 1903 /* Fetch ADC data from audio interface's input shift register. */
11e865c1 1904
be008602
HS
1905 /* Fetch ADC data */
1906 if (n != 0) {
de9cd5ca 1907 tmp = readl(dev->mmio + S626_P_FB_BUFFER1);
be008602
HS
1908 data[n - 1] = s626_ai_reg_to_uint(tmp);
1909 }
11e865c1 1910
020c44f3
HS
1911 return n;
1912}
11e865c1 1913
020c44f3
HS
1914static int s626_ai_load_polllist(uint8_t *ppl, struct comedi_cmd *cmd)
1915{
020c44f3 1916 int n;
11e865c1 1917
020c44f3 1918 for (n = 0; n < cmd->chanlist_len; n++) {
8ee52611 1919 if (CR_RANGE(cmd->chanlist[n]) == 0)
d8515652 1920 ppl[n] = CR_CHAN(cmd->chanlist[n]) | S626_RANGE_5V;
020c44f3 1921 else
d8515652 1922 ppl[n] = CR_CHAN(cmd->chanlist[n]) | S626_RANGE_10V;
020c44f3
HS
1923 }
1924 if (n != 0)
d8515652 1925 ppl[n - 1] |= S626_EOPL;
11e865c1 1926
020c44f3
HS
1927 return n;
1928}
11e865c1 1929
020c44f3 1930static int s626_ai_inttrig(struct comedi_device *dev,
478da5c9
HS
1931 struct comedi_subdevice *s,
1932 unsigned int trig_num)
020c44f3 1933{
478da5c9
HS
1934 struct comedi_cmd *cmd = &s->async->cmd;
1935
1936 if (trig_num != cmd->start_arg)
020c44f3 1937 return -EINVAL;
11e865c1 1938
ddd9813e 1939 /* Start executing the RPS program */
d8515652 1940 s626_mc_enable(dev, S626_MC1_ERPS1, S626_P_MC1);
11e865c1 1941
020c44f3 1942 s->async->inttrig = NULL;
11e865c1 1943
020c44f3
HS
1944 return 1;
1945}
11e865c1 1946
8ee52611
IA
1947/*
1948 * This function doesn't require a particular form, this is just what
6baffbc2
HS
1949 * happens to be used in some of the drivers. It should convert ns
1950 * nanoseconds to a counter value suitable for programming the device.
1951 * Also, it should adjust ns so that it cooresponds to the actual time
8ee52611
IA
1952 * that the device will use.
1953 */
a207c12f 1954static int s626_ns_to_timer(unsigned int *nanosec, unsigned int flags)
6baffbc2
HS
1955{
1956 int divider, base;
1957
1958 base = 500; /* 2MHz internal clock */
1959
889277b9
IA
1960 switch (flags & CMDF_ROUND_MASK) {
1961 case CMDF_ROUND_NEAREST:
6baffbc2 1962 default:
d9798aa6 1963 divider = DIV_ROUND_CLOSEST(*nanosec, base);
6baffbc2 1964 break;
889277b9 1965 case CMDF_ROUND_DOWN:
6baffbc2
HS
1966 divider = (*nanosec) / base;
1967 break;
889277b9 1968 case CMDF_ROUND_UP:
97996da1 1969 divider = DIV_ROUND_UP(*nanosec, base);
6baffbc2
HS
1970 break;
1971 }
1972
1973 *nanosec = base * divider;
1974 return divider - 1;
1975}
1976
3a305a66 1977static void s626_timer_load(struct comedi_device *dev,
0c9a057c 1978 unsigned int chan, int tick)
e3eb08d0 1979{
f1f7efce 1980 uint16_t setup =
d8515652 1981 /* Preload upon index. */
0830ada5 1982 S626_SET_STD_LOADSRC(S626_LOADSRC_INDX) |
d8515652 1983 /* Disable hardware index. */
0830ada5 1984 S626_SET_STD_INDXSRC(S626_INDXSRC_SOFT) |
d8515652 1985 /* Operating mode is Timer. */
0830ada5 1986 S626_SET_STD_ENCMODE(S626_ENCMODE_TIMER) |
d8515652 1987 /* Count direction is Down. */
0830ada5 1988 S626_SET_STD_CLKPOL(S626_CNTDIR_DOWN) |
d8515652 1989 /* Clock multiplier is 1x. */
0830ada5
IA
1990 S626_SET_STD_CLKMULT(S626_CLKMULT_1X) |
1991 /* Enabled by index */
1992 S626_SET_STD_CLKENAB(S626_CLKENAB_INDEX);
d8515652
IA
1993 uint16_t value_latchsrc = S626_LATCHSRC_A_INDXA;
1994 /* uint16_t enab = S626_CLKENAB_ALWAYS; */
e3eb08d0 1995
0c9a057c 1996 s626_set_mode(dev, chan, setup, false);
e3eb08d0 1997
8ee52611 1998 /* Set the preload register */
0c9a057c 1999 s626_preload(dev, chan, tick);
e3eb08d0 2000
8ee52611
IA
2001 /*
2002 * Software index pulse forces the preload register to load
2003 * into the counter
2004 */
0c9a057c
HS
2005 s626_set_load_trig(dev, chan, 0);
2006 s626_pulse_index(dev, chan);
e3eb08d0
HS
2007
2008 /* set reload on counter overflow */
0c9a057c 2009 s626_set_load_trig(dev, chan, 1);
e3eb08d0
HS
2010
2011 /* set interrupt on overflow */
0c9a057c 2012 s626_set_int_src(dev, chan, S626_INTSRC_OVER);
e3eb08d0 2013
0c9a057c
HS
2014 s626_set_latch_source(dev, chan, value_latchsrc);
2015 /* s626_set_enable(dev, chan, (uint16_t)(enab != 0)); */
e3eb08d0
HS
2016}
2017
8ee52611 2018/* TO COMPLETE */
020c44f3
HS
2019static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
2020{
7f2f7e05 2021 struct s626_private *devpriv = dev->private;
020c44f3
HS
2022 uint8_t ppl[16];
2023 struct comedi_cmd *cmd = &s->async->cmd;
020c44f3 2024 int tick;
11e865c1 2025
020c44f3 2026 if (devpriv->ai_cmd_running) {
730b8e15
IA
2027 dev_err(dev->class_dev,
2028 "s626_ai_cmd: Another ai_cmd is running\n");
020c44f3
HS
2029 return -EBUSY;
2030 }
2031 /* disable interrupt */
de9cd5ca 2032 writel(0, dev->mmio + S626_P_IER);
11e865c1 2033
020c44f3 2034 /* clear interrupt request */
de9cd5ca 2035 writel(S626_IRQ_RPS1 | S626_IRQ_GPIO3, dev->mmio + S626_P_ISR);
11e865c1 2036
020c44f3
HS
2037 /* clear any pending interrupt */
2038 s626_dio_clear_irq(dev);
8ee52611 2039 /* s626_enc_clear_irq(dev); */
11e865c1 2040
020c44f3
HS
2041 /* reset ai_cmd_running flag */
2042 devpriv->ai_cmd_running = 0;
11e865c1 2043
8ee52611 2044 /* test if cmd is valid */
bdf5aa39 2045 if (cmd == NULL)
020c44f3 2046 return -EINVAL;
11e865c1 2047
020c44f3
HS
2048 s626_ai_load_polllist(ppl, cmd);
2049 devpriv->ai_cmd_running = 1;
2050 devpriv->ai_convert_count = 0;
11e865c1 2051
020c44f3
HS
2052 switch (cmd->scan_begin_src) {
2053 case TRIG_FOLLOW:
2054 break;
2055 case TRIG_TIMER:
8ee52611
IA
2056 /*
2057 * set a counter to generate adc trigger at scan_begin_arg
2058 * interval
2059 */
a207c12f 2060 tick = s626_ns_to_timer(&cmd->scan_begin_arg, cmd->flags);
11e865c1 2061
020c44f3 2062 /* load timer value and enable interrupt */
0c9a057c
HS
2063 s626_timer_load(dev, 5, tick);
2064 s626_set_enable(dev, 5, S626_CLKENAB_ALWAYS);
020c44f3
HS
2065 break;
2066 case TRIG_EXT:
8ee52611 2067 /* set the digital line and interrupt for scan trigger */
020c44f3
HS
2068 if (cmd->start_src != TRIG_EXT)
2069 s626_dio_set_irq(dev, cmd->scan_begin_arg);
020c44f3
HS
2070 break;
2071 }
11e865c1 2072
020c44f3
HS
2073 switch (cmd->convert_src) {
2074 case TRIG_NOW:
2075 break;
2076 case TRIG_TIMER:
8ee52611
IA
2077 /*
2078 * set a counter to generate adc trigger at convert_arg
2079 * interval
2080 */
a207c12f 2081 tick = s626_ns_to_timer(&cmd->convert_arg, cmd->flags);
11e865c1 2082
020c44f3 2083 /* load timer value and enable interrupt */
0c9a057c
HS
2084 s626_timer_load(dev, 4, tick);
2085 s626_set_enable(dev, 4, S626_CLKENAB_INDEX);
020c44f3
HS
2086 break;
2087 case TRIG_EXT:
8ee52611
IA
2088 /* set the digital line and interrupt for convert trigger */
2089 if (cmd->scan_begin_src != TRIG_EXT &&
2090 cmd->start_src == TRIG_EXT)
020c44f3 2091 s626_dio_set_irq(dev, cmd->convert_arg);
020c44f3
HS
2092 break;
2093 }
11e865c1 2094
8b950552 2095 devpriv->ai_sample_count = cmd->stop_arg;
11e865c1 2096
31de1948 2097 s626_reset_adc(dev, ppl);
11e865c1 2098
020c44f3
HS
2099 switch (cmd->start_src) {
2100 case TRIG_NOW:
ddd9813e 2101 /* Trigger ADC scan loop start */
d8515652 2102 /* s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2); */
11e865c1 2103
ddd9813e 2104 /* Start executing the RPS program */
d8515652 2105 s626_mc_enable(dev, S626_MC1_ERPS1, S626_P_MC1);
020c44f3
HS
2106 s->async->inttrig = NULL;
2107 break;
2108 case TRIG_EXT:
2109 /* configure DIO channel for acquisition trigger */
2110 s626_dio_set_irq(dev, cmd->start_arg);
020c44f3
HS
2111 s->async->inttrig = NULL;
2112 break;
2113 case TRIG_INT:
2114 s->async->inttrig = s626_ai_inttrig;
2115 break;
11e865c1 2116 }
b6c77757 2117
020c44f3 2118 /* enable interrupt */
de9cd5ca 2119 writel(S626_IRQ_GPIO3 | S626_IRQ_RPS1, dev->mmio + S626_P_IER);
b6c77757 2120
020c44f3
HS
2121 return 0;
2122}
b6c77757 2123
020c44f3
HS
2124static int s626_ai_cmdtest(struct comedi_device *dev,
2125 struct comedi_subdevice *s, struct comedi_cmd *cmd)
2126{
2127 int err = 0;
c646efe1 2128 unsigned int arg;
b6c77757 2129
27020ffe 2130 /* Step 1 : check if triggers are trivially valid */
b6c77757 2131
27020ffe 2132 err |= cfc_check_trigger_src(&cmd->start_src,
8ee52611 2133 TRIG_NOW | TRIG_INT | TRIG_EXT);
27020ffe 2134 err |= cfc_check_trigger_src(&cmd->scan_begin_src,
8ee52611 2135 TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW);
27020ffe 2136 err |= cfc_check_trigger_src(&cmd->convert_src,
8ee52611 2137 TRIG_TIMER | TRIG_EXT | TRIG_NOW);
27020ffe
HS
2138 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
2139 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
11e865c1 2140
020c44f3
HS
2141 if (err)
2142 return 1;
11e865c1 2143
27020ffe 2144 /* Step 2a : make sure trigger sources are unique */
11e865c1 2145
27020ffe
HS
2146 err |= cfc_check_trigger_is_unique(cmd->start_src);
2147 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
2148 err |= cfc_check_trigger_is_unique(cmd->convert_src);
2149 err |= cfc_check_trigger_is_unique(cmd->stop_src);
2150
2151 /* Step 2b : and mutually compatible */
020c44f3
HS
2152
2153 if (err)
2154 return 2;
2155
478da5c9 2156 /* Step 3: check if arguments are trivially valid */
020c44f3 2157
478da5c9
HS
2158 switch (cmd->start_src) {
2159 case TRIG_NOW:
2160 case TRIG_INT:
53a254b9 2161 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
478da5c9
HS
2162 break;
2163 case TRIG_EXT:
53a254b9 2164 err |= cfc_check_trigger_arg_max(&cmd->start_arg, 39);
478da5c9
HS
2165 break;
2166 }
2167
53a254b9
HS
2168 if (cmd->scan_begin_src == TRIG_EXT)
2169 err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 39);
53a254b9
HS
2170 if (cmd->convert_src == TRIG_EXT)
2171 err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 39);
11e865c1 2172
676921c9
IA
2173#define S626_MAX_SPEED 200000 /* in nanoseconds */
2174#define S626_MIN_SPEED 2000000000 /* in nanoseconds */
11e865c1 2175
020c44f3 2176 if (cmd->scan_begin_src == TRIG_TIMER) {
53a254b9 2177 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
676921c9 2178 S626_MAX_SPEED);
53a254b9 2179 err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
676921c9 2180 S626_MIN_SPEED);
020c44f3
HS
2181 } else {
2182 /* external trigger */
2183 /* should be level/edge, hi/lo specification here */
2184 /* should specify multiple external triggers */
8ee52611 2185 /* err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */
020c44f3
HS
2186 }
2187 if (cmd->convert_src == TRIG_TIMER) {
676921c9
IA
2188 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
2189 S626_MAX_SPEED);
2190 err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
2191 S626_MIN_SPEED);
020c44f3
HS
2192 } else {
2193 /* external trigger */
2194 /* see above */
8ee52611 2195 /* err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */
020c44f3 2196 }
11e865c1 2197
53a254b9
HS
2198 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
2199
2200 if (cmd->stop_src == TRIG_COUNT)
32f9ff70 2201 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
53a254b9
HS
2202 else /* TRIG_NONE */
2203 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
11e865c1 2204
020c44f3
HS
2205 if (err)
2206 return 3;
2207
2208 /* step 4: fix up any arguments */
2209
2210 if (cmd->scan_begin_src == TRIG_TIMER) {
c646efe1 2211 arg = cmd->scan_begin_arg;
a207c12f 2212 s626_ns_to_timer(&arg, cmd->flags);
c646efe1 2213 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
020c44f3 2214 }
c646efe1 2215
020c44f3 2216 if (cmd->convert_src == TRIG_TIMER) {
c646efe1 2217 arg = cmd->convert_arg;
a207c12f 2218 s626_ns_to_timer(&arg, cmd->flags);
c646efe1
HS
2219 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
2220
2221 if (cmd->scan_begin_src == TRIG_TIMER) {
2222 arg = cmd->convert_arg * cmd->scan_end_arg;
2223 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
2224 arg);
020c44f3 2225 }
11e865c1 2226 }
11e865c1 2227
020c44f3
HS
2228 if (err)
2229 return 4;
2230
2231 return 0;
11e865c1
GP
2232}
2233
020c44f3 2234static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
11e865c1 2235{
7f2f7e05
HS
2236 struct s626_private *devpriv = dev->private;
2237
c5cf4606 2238 /* Stop RPS program in case it is currently running */
d8515652 2239 s626_mc_disable(dev, S626_MC1_ERPS1, S626_P_MC1);
11e865c1 2240
020c44f3 2241 /* disable master interrupt */
de9cd5ca 2242 writel(0, dev->mmio + S626_P_IER);
11e865c1 2243
020c44f3 2244 devpriv->ai_cmd_running = 0;
11e865c1 2245
020c44f3
HS
2246 return 0;
2247}
11e865c1 2248
18259ffc
HS
2249static int s626_ao_insn_write(struct comedi_device *dev,
2250 struct comedi_subdevice *s,
2251 struct comedi_insn *insn,
2252 unsigned int *data)
11e865c1 2253{
18259ffc 2254 unsigned int chan = CR_CHAN(insn->chanspec);
020c44f3 2255 int i;
11e865c1 2256
020c44f3 2257 for (i = 0; i < insn->n; i++) {
18259ffc
HS
2258 int16_t dacdata = (int16_t)data[i];
2259 int ret;
2260
020c44f3 2261 dacdata -= (0x1fff);
11e865c1 2262
a7aa94ce
CS
2263 ret = s626_set_dac(dev, chan, dacdata);
2264 if (ret)
2265 return ret;
11e865c1 2266
18259ffc
HS
2267 s->readback[chan] = data[i];
2268 }
11e865c1 2269
18259ffc 2270 return insn->n;
020c44f3 2271}
11e865c1 2272
8ee52611
IA
2273/* *************** DIGITAL I/O FUNCTIONS *************** */
2274
2275/*
020c44f3
HS
2276 * All DIO functions address a group of DIO channels by means of
2277 * "group" argument. group may be 0, 1 or 2, which correspond to DIO
2278 * ports A, B and C, respectively.
2279 */
11e865c1 2280
020c44f3
HS
2281static void s626_dio_init(struct comedi_device *dev)
2282{
2283 uint16_t group;
11e865c1 2284
8ee52611 2285 /* Prepare to treat writes to WRCapSel as capture disables. */
d8515652 2286 s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_NOEDCAP);
11e865c1 2287
8ee52611 2288 /* For each group of sixteen channels ... */
020c44f3 2289 for (group = 0; group < S626_DIO_BANKS; group++) {
100b4edc 2290 /* Disable all interrupts */
d8515652 2291 s626_debi_write(dev, S626_LP_WRINTSEL(group), 0);
100b4edc 2292 /* Disable all event captures */
d8515652 2293 s626_debi_write(dev, S626_LP_WRCAPSEL(group), 0xffff);
100b4edc 2294 /* Init all DIOs to default edge polarity */
d8515652 2295 s626_debi_write(dev, S626_LP_WREDGSEL(group), 0);
100b4edc 2296 /* Program all outputs to inactive state */
d8515652 2297 s626_debi_write(dev, S626_LP_WRDOUT(group), 0);
11e865c1 2298 }
020c44f3 2299}
11e865c1 2300
020c44f3
HS
2301static int s626_dio_insn_bits(struct comedi_device *dev,
2302 struct comedi_subdevice *s,
1515e522
HS
2303 struct comedi_insn *insn,
2304 unsigned int *data)
020c44f3 2305{
100b4edc 2306 unsigned long group = (unsigned long)s->private;
11e865c1 2307
6ea79c1d 2308 if (comedi_dio_update_state(s, data))
d8515652 2309 s626_debi_write(dev, S626_LP_WRDOUT(group), s->state);
6ea79c1d 2310
d8515652 2311 data[1] = s626_debi_read(dev, S626_LP_RDDIN(group));
11e865c1 2312
020c44f3 2313 return insn->n;
11e865c1
GP
2314}
2315
020c44f3
HS
2316static int s626_dio_insn_config(struct comedi_device *dev,
2317 struct comedi_subdevice *s,
e920fad2
HS
2318 struct comedi_insn *insn,
2319 unsigned int *data)
11e865c1 2320{
100b4edc 2321 unsigned long group = (unsigned long)s->private;
ddf62f2c
HS
2322 int ret;
2323
2324 ret = comedi_dio_insn_config(dev, s, insn, data, 0);
2325 if (ret)
2326 return ret;
11e865c1 2327
d8515652 2328 s626_debi_write(dev, S626_LP_WRDOUT(group), s->io_bits);
11e865c1 2329
e920fad2 2330 return insn->n;
11e865c1
GP
2331}
2332
8ee52611
IA
2333/*
2334 * Now this function initializes the value of the counter (data[0])
2335 * and set the subdevice. To complete with trigger and interrupt
2336 * configuration.
2337 *
2338 * FIXME: data[0] is supposed to be an INSN_CONFIG_xxx constant indicating
affdc230 2339 * what is being configured, but this function appears to be using data[0]
8ee52611
IA
2340 * as a variable.
2341 */
020c44f3
HS
2342static int s626_enc_insn_config(struct comedi_device *dev,
2343 struct comedi_subdevice *s,
2344 struct comedi_insn *insn, unsigned int *data)
2345{
0c9a057c 2346 unsigned int chan = CR_CHAN(insn->chanspec);
f1f7efce 2347 uint16_t setup =
d8515652 2348 /* Preload upon index. */
0830ada5 2349 S626_SET_STD_LOADSRC(S626_LOADSRC_INDX) |
d8515652 2350 /* Disable hardware index. */
0830ada5 2351 S626_SET_STD_INDXSRC(S626_INDXSRC_SOFT) |
d8515652 2352 /* Operating mode is Counter. */
0830ada5 2353 S626_SET_STD_ENCMODE(S626_ENCMODE_COUNTER) |
d8515652 2354 /* Active high clock. */
0830ada5 2355 S626_SET_STD_CLKPOL(S626_CLKPOL_POS) |
d8515652 2356 /* Clock multiplier is 1x. */
0830ada5
IA
2357 S626_SET_STD_CLKMULT(S626_CLKMULT_1X) |
2358 /* Enabled by index */
2359 S626_SET_STD_CLKENAB(S626_CLKENAB_INDEX);
c3e3a56d 2360 /* uint16_t disable_int_src = true; */
8ee52611 2361 /* uint32_t Preloadvalue; //Counter initial value */
d8515652
IA
2362 uint16_t value_latchsrc = S626_LATCHSRC_AB_READ;
2363 uint16_t enab = S626_CLKENAB_ALWAYS;
11e865c1 2364
8ee52611 2365 /* (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */
11e865c1 2366
0c9a057c
HS
2367 s626_set_mode(dev, chan, setup, true);
2368 s626_preload(dev, chan, data[0]);
2369 s626_pulse_index(dev, chan);
2370 s626_set_latch_source(dev, chan, value_latchsrc);
2371 s626_set_enable(dev, chan, (enab != 0));
11e865c1 2372
020c44f3
HS
2373 return insn->n;
2374}
11e865c1 2375
020c44f3
HS
2376static int s626_enc_insn_read(struct comedi_device *dev,
2377 struct comedi_subdevice *s,
81202ecf
HS
2378 struct comedi_insn *insn,
2379 unsigned int *data)
020c44f3 2380{
81202ecf
HS
2381 unsigned int chan = CR_CHAN(insn->chanspec);
2382 uint16_t cntr_latch_reg = S626_LP_CNTR(chan);
2383 int i;
11e865c1 2384
81202ecf
HS
2385 for (i = 0; i < insn->n; i++) {
2386 unsigned int val;
11e865c1 2387
81202ecf
HS
2388 /*
2389 * Read the counter's output latch LSW/MSW.
2390 * Latches on LSW read.
2391 */
2392 val = s626_debi_read(dev, cntr_latch_reg);
2393 val |= (s626_debi_read(dev, cntr_latch_reg + 2) << 16);
2394 data[i] = val;
2395 }
2396
2397 return insn->n;
020c44f3 2398}
11e865c1 2399
020c44f3
HS
2400static int s626_enc_insn_write(struct comedi_device *dev,
2401 struct comedi_subdevice *s,
2402 struct comedi_insn *insn, unsigned int *data)
2403{
0c9a057c 2404 unsigned int chan = CR_CHAN(insn->chanspec);
11e865c1 2405
8ee52611 2406 /* Set the preload register */
0c9a057c 2407 s626_preload(dev, chan, data[0]);
11e865c1 2408
8ee52611
IA
2409 /*
2410 * Software index pulse forces the preload register to load
2411 * into the counter
2412 */
0c9a057c
HS
2413 s626_set_load_trig(dev, chan, 0);
2414 s626_pulse_index(dev, chan);
2415 s626_set_load_trig(dev, chan, 2);
11e865c1 2416
020c44f3 2417 return 1;
11e865c1
GP
2418}
2419
31de1948 2420static void s626_write_misc2(struct comedi_device *dev, uint16_t new_image)
11e865c1 2421{
d8515652
IA
2422 s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_WENABLE);
2423 s626_debi_write(dev, S626_LP_WRMISC2, new_image);
2424 s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_WDISABLE);
020c44f3 2425}
11e865c1 2426
31de1948 2427static void s626_counters_init(struct comedi_device *dev)
11e865c1 2428{
020c44f3 2429 int chan;
f1f7efce 2430 uint16_t setup =
d8515652 2431 /* Preload upon index. */
0830ada5 2432 S626_SET_STD_LOADSRC(S626_LOADSRC_INDX) |
d8515652 2433 /* Disable hardware index. */
0830ada5 2434 S626_SET_STD_INDXSRC(S626_INDXSRC_SOFT) |
d8515652 2435 /* Operating mode is counter. */
0830ada5 2436 S626_SET_STD_ENCMODE(S626_ENCMODE_COUNTER) |
d8515652 2437 /* Active high clock. */
0830ada5 2438 S626_SET_STD_CLKPOL(S626_CLKPOL_POS) |
d8515652 2439 /* Clock multiplier is 1x. */
0830ada5 2440 S626_SET_STD_CLKMULT(S626_CLKMULT_1X) |
d8515652 2441 /* Enabled by index */
0830ada5 2442 S626_SET_STD_CLKENAB(S626_CLKENAB_INDEX);
8ee52611
IA
2443
2444 /*
2445 * Disable all counter interrupts and clear any captured counter events.
2446 */
020c44f3 2447 for (chan = 0; chan < S626_ENCODER_CHANNELS; chan++) {
0c9a057c
HS
2448 s626_set_mode(dev, chan, setup, true);
2449 s626_set_int_src(dev, chan, 0);
2450 s626_reset_cap_flags(dev, chan);
2451 s626_set_enable(dev, chan, S626_CLKENAB_ALWAYS);
020c44f3 2452 }
020c44f3 2453}
11e865c1 2454
b7047895
HS
2455static int s626_allocate_dma_buffers(struct comedi_device *dev)
2456{
2457 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
7f2f7e05 2458 struct s626_private *devpriv = dev->private;
b7047895
HS
2459 void *addr;
2460 dma_addr_t appdma;
2461
d8515652 2462 addr = pci_alloc_consistent(pcidev, S626_DMABUF_SIZE, &appdma);
b7047895
HS
2463 if (!addr)
2464 return -ENOMEM;
07a36d66
IA
2465 devpriv->ana_buf.logical_base = addr;
2466 devpriv->ana_buf.physical_base = appdma;
b7047895 2467
d8515652 2468 addr = pci_alloc_consistent(pcidev, S626_DMABUF_SIZE, &appdma);
b7047895
HS
2469 if (!addr)
2470 return -ENOMEM;
07a36d66
IA
2471 devpriv->rps_buf.logical_base = addr;
2472 devpriv->rps_buf.physical_base = appdma;
b7047895 2473
b7047895
HS
2474 return 0;
2475}
2476
3757e795
HS
2477static void s626_free_dma_buffers(struct comedi_device *dev)
2478{
2479 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
2480 struct s626_private *devpriv = dev->private;
2481
2482 if (!devpriv)
2483 return;
2484
2485 if (devpriv->rps_buf.logical_base)
2486 pci_free_consistent(pcidev, S626_DMABUF_SIZE,
2487 devpriv->rps_buf.logical_base,
2488 devpriv->rps_buf.physical_base);
2489 if (devpriv->ana_buf.logical_base)
2490 pci_free_consistent(pcidev, S626_DMABUF_SIZE,
2491 devpriv->ana_buf.logical_base,
2492 devpriv->ana_buf.physical_base);
2493}
2494
a7aa94ce 2495static int s626_initialize(struct comedi_device *dev)
020c44f3 2496{
7f2f7e05 2497 struct s626_private *devpriv = dev->private;
f1f7efce 2498 dma_addr_t phys_buf;
68ad0ae0 2499 uint16_t chan;
020c44f3 2500 int i;
a7aa94ce 2501 int ret;
11e865c1 2502
54a2a02e 2503 /* Enable DEBI and audio pins, enable I2C interface */
d8515652
IA
2504 s626_mc_enable(dev, S626_MC1_DEBI | S626_MC1_AUDIO | S626_MC1_I2C,
2505 S626_P_MC1);
54a2a02e
HS
2506
2507 /*
8ee52611 2508 * Configure DEBI operating mode
54a2a02e 2509 *
8ee52611
IA
2510 * Local bus is 16 bits wide
2511 * Declare DEBI transfer timeout interval
2512 * Set up byte lane steering
2513 * Intel-compatible local bus (DEBI never times out)
54a2a02e 2514 */
d8515652
IA
2515 writel(S626_DEBI_CFG_SLAVE16 |
2516 (S626_DEBI_TOUT << S626_DEBI_CFG_TOUT_BIT) | S626_DEBI_SWAP |
de9cd5ca 2517 S626_DEBI_CFG_INTEL, dev->mmio + S626_P_DEBICFG);
54a2a02e
HS
2518
2519 /* Disable MMU paging */
de9cd5ca 2520 writel(S626_DEBI_PAGE_DISABLE, dev->mmio + S626_P_DEBIPAGE);
54a2a02e
HS
2521
2522 /* Init GPIO so that ADC Start* is negated */
de9cd5ca 2523 writel(S626_GPIO_BASE | S626_GPIO1_HI, dev->mmio + S626_P_GPIO);
68ad0ae0 2524
17553c88 2525 /* I2C device address for onboard eeprom (revb) */
07a36d66 2526 devpriv->i2c_adrs = 0xA0;
11e865c1 2527
54a2a02e
HS
2528 /*
2529 * Issue an I2C ABORT command to halt any I2C
2530 * operation in progress and reset BUSY flag.
2531 */
d8515652 2532 writel(S626_I2C_CLKSEL | S626_I2C_ABORT,
de9cd5ca 2533 dev->mmio + S626_P_I2CSTAT);
d8515652 2534 s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2);
571845c6
CS
2535 ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0);
2536 if (ret)
2537 return ret;
68ad0ae0 2538
54a2a02e
HS
2539 /*
2540 * Per SAA7146 data sheet, write to STATUS
2541 * reg twice to reset all I2C error flags.
2542 */
68ad0ae0 2543 for (i = 0; i < 2; i++) {
de9cd5ca 2544 writel(S626_I2C_CLKSEL, dev->mmio + S626_P_I2CSTAT);
d8515652 2545 s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2);
571845c6
CS
2546 ret = comedi_timeout(dev, NULL, NULL, s626_i2c_handshake_eoc, 0);
2547 if (ret)
2548 return ret;
68ad0ae0 2549 }
11e865c1 2550
54a2a02e
HS
2551 /*
2552 * Init audio interface functional attributes: set DAC/ADC
68ad0ae0
HS
2553 * serial clock rates, invert DAC serial clock so that
2554 * DAC data setup times are satisfied, enable DAC serial
2555 * clock out.
2556 */
de9cd5ca 2557 writel(S626_ACON2_INIT, dev->mmio + S626_P_ACON2);
11e865c1 2558
54a2a02e
HS
2559 /*
2560 * Set up TSL1 slot list, which is used to control the
d8515652
IA
2561 * accumulation of ADC data: S626_RSD1 = shift data in on SD1.
2562 * S626_SIB_A1 = store data uint8_t at next available location
54a2a02e
HS
2563 * in FB BUFFER1 register.
2564 */
de9cd5ca 2565 writel(S626_RSD1 | S626_SIB_A1, dev->mmio + S626_P_TSL1);
d8515652 2566 writel(S626_RSD1 | S626_SIB_A1 | S626_EOS,
de9cd5ca 2567 dev->mmio + S626_P_TSL1 + 4);
11e865c1 2568
54a2a02e 2569 /* Enable TSL1 slot list so that it executes all the time */
de9cd5ca 2570 writel(S626_ACON1_ADCSTART, dev->mmio + S626_P_ACON1);
11e865c1 2571
54a2a02e
HS
2572 /*
2573 * Initialize RPS registers used for ADC
2574 */
11e865c1 2575
54a2a02e 2576 /* Physical start of RPS program */
07a36d66 2577 writel((uint32_t)devpriv->rps_buf.physical_base,
de9cd5ca 2578 dev->mmio + S626_P_RPSADDR1);
54a2a02e 2579 /* RPS program performs no explicit mem writes */
de9cd5ca 2580 writel(0, dev->mmio + S626_P_RPSPAGE1);
54a2a02e 2581 /* Disable RPS timeouts */
de9cd5ca 2582 writel(0, dev->mmio + S626_P_RPS1_TOUT);
11e865c1 2583
59747847
HS
2584#if 0
2585 /*
2586 * SAA7146 BUG WORKAROUND
2587 *
2588 * Initialize SAA7146 ADC interface to a known state by
2589 * invoking ADCs until FB BUFFER 1 register shows that it
2590 * is correctly receiving ADC data. This is necessary
2591 * because the SAA7146 ADC interface does not start up in
2592 * a defined state after a PCI reset.
68ad0ae0 2593 */
59747847 2594 {
9c9ab3c1 2595 struct comedi_subdevice *s = dev->read_subdev;
f1f7efce
IA
2596 uint8_t poll_list;
2597 uint16_t adc_data;
2598 uint16_t start_val;
8ee52611
IA
2599 uint16_t index;
2600 unsigned int data[16];
59747847 2601
8ee52611 2602 /* Create a simple polling list for analog input channel 0 */
d8515652 2603 poll_list = S626_EOPL;
31de1948 2604 s626_reset_adc(dev, &poll_list);
59747847 2605
8ee52611 2606 /* Get initial ADC value */
9c9ab3c1 2607 s626_ai_rinsn(dev, s, NULL, data);
f1f7efce 2608 start_val = data[0];
59747847 2609
8ee52611
IA
2610 /*
2611 * VERSION 2.01 CHANGE: TIMEOUT ADDED TO PREVENT HANGED
2612 * EXECUTION.
2613 *
2614 * Invoke ADCs until the new ADC value differs from the initial
2615 * value or a timeout occurs. The timeout protects against the
2616 * possibility that the driver is restarting and the ADC data is
2617 * a fixed value resulting from the applied ADC analog input
2618 * being unusually quiet or at the rail.
2619 */
2620 for (index = 0; index < 500; index++) {
9c9ab3c1 2621 s626_ai_rinsn(dev, s, NULL, data);
f1f7efce
IA
2622 adc_data = data[0];
2623 if (adc_data != start_val)
8ee52611
IA
2624 break;
2625 }
59747847
HS
2626 }
2627#endif /* SAA7146 BUG WORKAROUND */
11e865c1 2628
54a2a02e
HS
2629 /*
2630 * Initialize the DAC interface
2631 */
11e865c1 2632
54a2a02e
HS
2633 /*
2634 * Init Audio2's output DMAC attributes:
2635 * burst length = 1 DWORD
2636 * threshold = 1 DWORD.
68ad0ae0 2637 */
de9cd5ca 2638 writel(0, dev->mmio + S626_P_PCI_BT_A);
68ad0ae0 2639
54a2a02e
HS
2640 /*
2641 * Init Audio2's output DMA physical addresses. The protection
68ad0ae0
HS
2642 * address is set to 1 DWORD past the base address so that a
2643 * single DWORD will be transferred each time a DMA transfer is
54a2a02e
HS
2644 * enabled.
2645 */
f1f7efce 2646 phys_buf = devpriv->ana_buf.physical_base +
d8515652 2647 (S626_DAC_WDMABUF_OS * sizeof(uint32_t));
de9cd5ca 2648 writel((uint32_t)phys_buf, dev->mmio + S626_P_BASEA2_OUT);
f1f7efce 2649 writel((uint32_t)(phys_buf + sizeof(uint32_t)),
de9cd5ca 2650 dev->mmio + S626_P_PROTA2_OUT);
68ad0ae0 2651
54a2a02e
HS
2652 /*
2653 * Cache Audio2's output DMA buffer logical address. This is
2654 * where DAC data is buffered for A2 output DMA transfers.
2655 */
07a36d66 2656 devpriv->dac_wbuf = (uint32_t *)devpriv->ana_buf.logical_base +
d8515652 2657 S626_DAC_WDMABUF_OS;
68ad0ae0 2658
54a2a02e
HS
2659 /*
2660 * Audio2's output channels does not use paging. The
2661 * protection violation handling bit is set so that the
2662 * DMAC will automatically halt and its PCI address pointer
2663 * will be reset when the protection address is reached.
2664 */
de9cd5ca 2665 writel(8, dev->mmio + S626_P_PAGEA2_OUT);
68ad0ae0 2666
54a2a02e
HS
2667 /*
2668 * Initialize time slot list 2 (TSL2), which is used to control
68ad0ae0
HS
2669 * the clock generation for and serialization of data to be sent
2670 * to the DAC devices. Slot 0 is a NOP that is used to trap TSL
2671 * execution; this permits other slots to be safely modified
2672 * without first turning off the TSL sequencer (which is
2673 * apparently impossible to do). Also, SD3 (which is driven by a
2674 * pull-up resistor) is shifted in and stored to the MSB of
2675 * FB_BUFFER2 to be used as evidence that the slot sequence has
2676 * not yet finished executing.
2677 */
11e865c1 2678
54a2a02e 2679 /* Slot 0: Trap TSL execution, shift 0xFF into FB_BUFFER2 */
d8515652 2680 writel(S626_XSD2 | S626_RSD3 | S626_SIB_A2 | S626_EOS,
de9cd5ca 2681 dev->mmio + S626_VECTPORT(0));
11e865c1 2682
54a2a02e
HS
2683 /*
2684 * Initialize slot 1, which is constant. Slot 1 causes a
68ad0ae0
HS
2685 * DWORD to be transferred from audio channel 2's output FIFO
2686 * to the FIFO's output buffer so that it can be serialized
2687 * and sent to the DAC during subsequent slots. All remaining
2688 * slots are dynamically populated as required by the target
2689 * DAC device.
2690 */
54a2a02e
HS
2691
2692 /* Slot 1: Fetch DWORD from Audio2's output FIFO */
de9cd5ca 2693 writel(S626_LF_A2, dev->mmio + S626_VECTPORT(1));
11e865c1 2694
54a2a02e 2695 /* Start DAC's audio interface (TSL2) running */
de9cd5ca 2696 writel(S626_ACON1_DACSTART, dev->mmio + S626_P_ACON1);
11e865c1 2697
54a2a02e
HS
2698 /*
2699 * Init Trim DACs to calibrated values. Do it twice because the
68ad0ae0
HS
2700 * SAA7146 audio channel does not always reset properly and
2701 * sometimes causes the first few TrimDAC writes to malfunction.
2702 */
31de1948 2703 s626_load_trim_dacs(dev);
a7aa94ce
CS
2704 ret = s626_load_trim_dacs(dev);
2705 if (ret)
2706 return ret;
11e865c1 2707
54a2a02e
HS
2708 /*
2709 * Manually init all gate array hardware in case this is a soft
68ad0ae0
HS
2710 * reset (we have no way of determining whether this is a warm
2711 * or cold start). This is necessary because the gate array will
2712 * reset only in response to a PCI hard reset; there is no soft
54a2a02e
HS
2713 * reset function.
2714 */
11e865c1 2715
54a2a02e
HS
2716 /*
2717 * Init all DAC outputs to 0V and init all DAC setpoint and
68ad0ae0
HS
2718 * polarity images.
2719 */
a7aa94ce
CS
2720 for (chan = 0; chan < S626_DAC_CHANNELS; chan++) {
2721 ret = s626_set_dac(dev, chan, 0);
2722 if (ret)
2723 return ret;
2724 }
11e865c1 2725
54a2a02e 2726 /* Init counters */
31de1948 2727 s626_counters_init(dev);
11e865c1 2728
54a2a02e
HS
2729 /*
2730 * Without modifying the state of the Battery Backup enab, disable
68ad0ae0
HS
2731 * the watchdog timer, set DIO channels 0-5 to operate in the
2732 * standard DIO (vs. counter overflow) mode, disable the battery
2733 * charger, and reset the watchdog interval selector to zero.
2734 */
d8515652
IA
2735 s626_write_misc2(dev, (s626_debi_read(dev, S626_LP_RDMISC2) &
2736 S626_MISC2_BATT_ENABLE));
11e865c1 2737
54a2a02e 2738 /* Initialize the digital I/O subsystem */
68ad0ae0 2739 s626_dio_init(dev);
a7aa94ce
CS
2740
2741 return 0;
80ec9510
HS
2742}
2743
a690b7e5 2744static int s626_auto_attach(struct comedi_device *dev,
750af5e5 2745 unsigned long context_unused)
80ec9510 2746{
750af5e5 2747 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
7f2f7e05 2748 struct s626_private *devpriv;
80ec9510
HS
2749 struct comedi_subdevice *s;
2750 int ret;
2751
0bdab509 2752 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
c34fa261
HS
2753 if (!devpriv)
2754 return -ENOMEM;
80ec9510 2755
818f569f 2756 ret = comedi_pci_enable(dev);
80ec9510
HS
2757 if (ret)
2758 return ret;
80ec9510 2759
de9cd5ca
HS
2760 dev->mmio = pci_ioremap_bar(pcidev, 0);
2761 if (!dev->mmio)
80ec9510
HS
2762 return -ENOMEM;
2763
2764 /* disable master interrupt */
de9cd5ca 2765 writel(0, dev->mmio + S626_P_IER);
80ec9510
HS
2766
2767 /* soft reset */
de9cd5ca 2768 writel(S626_MC1_SOFT_RESET, dev->mmio + S626_P_MC1);
80ec9510
HS
2769
2770 /* DMA FIXME DMA// */
2771
2772 ret = s626_allocate_dma_buffers(dev);
2773 if (ret)
2774 return ret;
2775
2776 if (pcidev->irq) {
2777 ret = request_irq(pcidev->irq, s626_irq_handler, IRQF_SHARED,
2778 dev->board_name, dev);
2779
2780 if (ret == 0)
2781 dev->irq = pcidev->irq;
2782 }
2783
2784 ret = comedi_alloc_subdevices(dev, 6);
2785 if (ret)
2786 return ret;
2787
f0717f5d 2788 s = &dev->subdevices[0];
80ec9510 2789 /* analog input subdevice */
ca2f1091 2790 s->type = COMEDI_SUBD_AI;
f95321f3 2791 s->subdev_flags = SDF_READABLE | SDF_DIFF;
ca2f1091
HS
2792 s->n_chan = S626_ADC_CHANNELS;
2793 s->maxdata = 0x3fff;
2794 s->range_table = &s626_range_table;
2795 s->len_chanlist = S626_ADC_CHANNELS;
ca2f1091 2796 s->insn_read = s626_ai_insn_read;
2281befd
HS
2797 if (dev->irq) {
2798 dev->read_subdev = s;
f95321f3 2799 s->subdev_flags |= SDF_CMD_READ;
2281befd
HS
2800 s->do_cmd = s626_ai_cmd;
2801 s->do_cmdtest = s626_ai_cmdtest;
2802 s->cancel = s626_ai_cancel;
2803 }
80ec9510 2804
f0717f5d 2805 s = &dev->subdevices[1];
80ec9510 2806 /* analog output subdevice */
ca2f1091
HS
2807 s->type = COMEDI_SUBD_AO;
2808 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
2809 s->n_chan = S626_DAC_CHANNELS;
2810 s->maxdata = 0x3fff;
2811 s->range_table = &range_bipolar10;
18259ffc
HS
2812 s->insn_write = s626_ao_insn_write;
2813 s->insn_read = comedi_readback_insn_read;
2814
2815 ret = comedi_alloc_subdev_readback(s);
2816 if (ret)
2817 return ret;
80ec9510 2818
f0717f5d 2819 s = &dev->subdevices[2];
80ec9510 2820 /* digital I/O subdevice */
ca2f1091
HS
2821 s->type = COMEDI_SUBD_DIO;
2822 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
2823 s->n_chan = 16;
2824 s->maxdata = 1;
2825 s->io_bits = 0xffff;
2826 s->private = (void *)0; /* DIO group 0 */
2827 s->range_table = &range_digital;
2828 s->insn_config = s626_dio_insn_config;
2829 s->insn_bits = s626_dio_insn_bits;
80ec9510 2830
f0717f5d 2831 s = &dev->subdevices[3];
80ec9510 2832 /* digital I/O subdevice */
ca2f1091
HS
2833 s->type = COMEDI_SUBD_DIO;
2834 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
2835 s->n_chan = 16;
2836 s->maxdata = 1;
2837 s->io_bits = 0xffff;
2838 s->private = (void *)1; /* DIO group 1 */
2839 s->range_table = &range_digital;
2840 s->insn_config = s626_dio_insn_config;
2841 s->insn_bits = s626_dio_insn_bits;
80ec9510 2842
f0717f5d 2843 s = &dev->subdevices[4];
80ec9510 2844 /* digital I/O subdevice */
ca2f1091
HS
2845 s->type = COMEDI_SUBD_DIO;
2846 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
2847 s->n_chan = 16;
2848 s->maxdata = 1;
2849 s->io_bits = 0xffff;
2850 s->private = (void *)2; /* DIO group 2 */
2851 s->range_table = &range_digital;
8ee52611 2852 s->insn_config = s626_dio_insn_config;
ca2f1091 2853 s->insn_bits = s626_dio_insn_bits;
80ec9510 2854
f0717f5d 2855 s = &dev->subdevices[5];
80ec9510 2856 /* encoder (counter) subdevice */
ca2f1091
HS
2857 s->type = COMEDI_SUBD_COUNTER;
2858 s->subdev_flags = SDF_WRITABLE | SDF_READABLE | SDF_LSAMPL;
2859 s->n_chan = S626_ENCODER_CHANNELS;
2860 s->maxdata = 0xffffff;
ca2f1091
HS
2861 s->range_table = &range_unknown;
2862 s->insn_config = s626_enc_insn_config;
2863 s->insn_read = s626_enc_insn_read;
2864 s->insn_write = s626_enc_insn_write;
80ec9510 2865
a7aa94ce
CS
2866 ret = s626_initialize(dev);
2867 if (ret)
2868 return ret;
11e865c1 2869
f996ab29 2870 return 0;
11e865c1
GP
2871}
2872
020c44f3 2873static void s626_detach(struct comedi_device *dev)
11e865c1 2874{
7f2f7e05 2875 struct s626_private *devpriv = dev->private;
f574af6d 2876
020c44f3
HS
2877 if (devpriv) {
2878 /* stop ai_command */
2879 devpriv->ai_cmd_running = 0;
11e865c1 2880
de9cd5ca 2881 if (dev->mmio) {
020c44f3 2882 /* interrupt mask */
25f8fd5e 2883 /* Disable master interrupt */
de9cd5ca 2884 writel(0, dev->mmio + S626_P_IER);
25f8fd5e 2885 /* Clear board's IRQ status flag */
d8515652 2886 writel(S626_IRQ_GPIO3 | S626_IRQ_RPS1,
de9cd5ca 2887 dev->mmio + S626_P_ISR);
11e865c1 2888
8ee52611 2889 /* Disable the watchdog timer and battery charger. */
31de1948 2890 s626_write_misc2(dev, 0);
11e865c1 2891
25f8fd5e 2892 /* Close all interfaces on 7146 device */
de9cd5ca
HS
2893 writel(S626_MC1_SHUTDOWN, dev->mmio + S626_P_MC1);
2894 writel(S626_ACON1_BASE, dev->mmio + S626_P_ACON1);
020c44f3 2895 }
f574af6d 2896 }
8075bfb6 2897 comedi_pci_detach(dev);
3757e795 2898 s626_free_dma_buffers(dev);
11e865c1 2899}
7122b76d 2900
75e6301b 2901static struct comedi_driver s626_driver = {
7122b76d
HS
2902 .driver_name = "s626",
2903 .module = THIS_MODULE,
750af5e5 2904 .auto_attach = s626_auto_attach,
7122b76d
HS
2905 .detach = s626_detach,
2906};
2907
a690b7e5 2908static int s626_pci_probe(struct pci_dev *dev,
b8f4ac23 2909 const struct pci_device_id *id)
7122b76d 2910{
b8f4ac23 2911 return comedi_pci_auto_config(dev, &s626_driver, id->driver_data);
7122b76d
HS
2912}
2913
7122b76d
HS
2914/*
2915 * For devices with vendor:device id == 0x1131:0x7146 you must specify
2916 * also subvendor:subdevice ids, because otherwise it will conflict with
2917 * Philips SAA7146 media/dvb based cards.
2918 */
41e043fc 2919static const struct pci_device_id s626_pci_table[] = {
498c5070
IA
2920 { PCI_DEVICE_SUB(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146,
2921 0x6000, 0x0272) },
7122b76d
HS
2922 { 0 }
2923};
2924MODULE_DEVICE_TABLE(pci, s626_pci_table);
2925
75e6301b
HS
2926static struct pci_driver s626_pci_driver = {
2927 .name = "s626",
7122b76d 2928 .id_table = s626_pci_table,
75e6301b 2929 .probe = s626_pci_probe,
9901a4d7 2930 .remove = comedi_pci_auto_unconfig,
7122b76d 2931};
75e6301b 2932module_comedi_pci_driver(s626_driver, s626_pci_driver);
7122b76d
HS
2933
2934MODULE_AUTHOR("Gianluca Palli <gpalli@deis.unibo.it>");
2935MODULE_DESCRIPTION("Sensoray 626 Comedi driver module");
2936MODULE_LICENSE("GPL");