addi_apci_3120.c (30505B)
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * addi_apci_3120.c 4 * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. 5 * 6 * ADDI-DATA GmbH 7 * Dieselstrasse 3 8 * D-77833 Ottersweier 9 * Tel: +19(0)7223/9493-0 10 * Fax: +49(0)7223/9493-92 11 * http://www.addi-data.com 12 * info@addi-data.com 13 */ 14 15#include <linux/module.h> 16#include <linux/interrupt.h> 17#include <linux/comedi/comedi_pci.h> 18 19#include "amcc_s5933.h" 20 21/* 22 * PCI BAR 0 register map (devpriv->amcc) 23 * see amcc_s5933.h for register and bit defines 24 */ 25#define APCI3120_FIFO_ADVANCE_ON_BYTE_2 BIT(29) 26 27/* 28 * PCI BAR 1 register map (dev->iobase) 29 */ 30#define APCI3120_AI_FIFO_REG 0x00 31#define APCI3120_CTRL_REG 0x00 32#define APCI3120_CTRL_EXT_TRIG BIT(15) 33#define APCI3120_CTRL_GATE(x) BIT(12 + (x)) 34#define APCI3120_CTRL_PR(x) (((x) & 0xf) << 8) 35#define APCI3120_CTRL_PA(x) (((x) & 0xf) << 0) 36#define APCI3120_AI_SOFTTRIG_REG 0x02 37#define APCI3120_STATUS_REG 0x02 38#define APCI3120_STATUS_EOC_INT BIT(15) 39#define APCI3120_STATUS_AMCC_INT BIT(14) 40#define APCI3120_STATUS_EOS_INT BIT(13) 41#define APCI3120_STATUS_TIMER2_INT BIT(12) 42#define APCI3120_STATUS_INT_MASK (0xf << 12) 43#define APCI3120_STATUS_TO_DI_BITS(x) (((x) >> 8) & 0xf) 44#define APCI3120_STATUS_TO_VERSION(x) (((x) >> 4) & 0xf) 45#define APCI3120_STATUS_FIFO_FULL BIT(2) 46#define APCI3120_STATUS_FIFO_EMPTY BIT(1) 47#define APCI3120_STATUS_DA_READY BIT(0) 48#define APCI3120_TIMER_REG 0x04 49#define APCI3120_CHANLIST_REG 0x06 50#define APCI3120_CHANLIST_INDEX(x) (((x) & 0xf) << 8) 51#define APCI3120_CHANLIST_UNIPOLAR BIT(7) 52#define APCI3120_CHANLIST_GAIN(x) (((x) & 0x3) << 4) 53#define APCI3120_CHANLIST_MUX(x) (((x) & 0xf) << 0) 54#define APCI3120_AO_REG(x) (0x08 + (((x) / 4) * 2)) 55#define APCI3120_AO_MUX(x) (((x) & 0x3) << 14) 56#define APCI3120_AO_DATA(x) ((x) << 0) 57#define APCI3120_TIMER_MODE_REG 0x0c 58#define APCI3120_TIMER_MODE(_t, _m) ((_m) << ((_t) * 2)) 59#define APCI3120_TIMER_MODE0 0 /* I8254_MODE0 */ 60#define APCI3120_TIMER_MODE2 1 /* I8254_MODE2 */ 61#define APCI3120_TIMER_MODE4 2 /* I8254_MODE4 */ 62#define APCI3120_TIMER_MODE5 3 /* I8254_MODE5 */ 63#define APCI3120_TIMER_MODE_MASK(_t) (3 << ((_t) * 2)) 64#define APCI3120_CTR0_REG 0x0d 65#define APCI3120_CTR0_DO_BITS(x) ((x) << 4) 66#define APCI3120_CTR0_TIMER_SEL(x) ((x) << 0) 67#define APCI3120_MODE_REG 0x0e 68#define APCI3120_MODE_TIMER2_CLK(x) (((x) & 0x3) << 6) 69#define APCI3120_MODE_TIMER2_CLK_OSC APCI3120_MODE_TIMER2_CLK(0) 70#define APCI3120_MODE_TIMER2_CLK_OUT1 APCI3120_MODE_TIMER2_CLK(1) 71#define APCI3120_MODE_TIMER2_CLK_EOC APCI3120_MODE_TIMER2_CLK(2) 72#define APCI3120_MODE_TIMER2_CLK_EOS APCI3120_MODE_TIMER2_CLK(3) 73#define APCI3120_MODE_TIMER2_CLK_MASK APCI3120_MODE_TIMER2_CLK(3) 74#define APCI3120_MODE_TIMER2_AS(x) (((x) & 0x3) << 4) 75#define APCI3120_MODE_TIMER2_AS_TIMER APCI3120_MODE_TIMER2_AS(0) 76#define APCI3120_MODE_TIMER2_AS_COUNTER APCI3120_MODE_TIMER2_AS(1) 77#define APCI3120_MODE_TIMER2_AS_WDOG APCI3120_MODE_TIMER2_AS(2) 78#define APCI3120_MODE_TIMER2_AS_MASK APCI3120_MODE_TIMER2_AS(3) 79#define APCI3120_MODE_SCAN_ENA BIT(3) 80#define APCI3120_MODE_TIMER2_IRQ_ENA BIT(2) 81#define APCI3120_MODE_EOS_IRQ_ENA BIT(1) 82#define APCI3120_MODE_EOC_IRQ_ENA BIT(0) 83 84/* 85 * PCI BAR 2 register map (devpriv->addon) 86 */ 87#define APCI3120_ADDON_ADDR_REG 0x00 88#define APCI3120_ADDON_DATA_REG 0x02 89#define APCI3120_ADDON_CTRL_REG 0x04 90#define APCI3120_ADDON_CTRL_AMWEN_ENA BIT(1) 91#define APCI3120_ADDON_CTRL_A2P_FIFO_ENA BIT(0) 92 93/* 94 * Board revisions 95 */ 96#define APCI3120_REVA 0xa 97#define APCI3120_REVB 0xb 98#define APCI3120_REVA_OSC_BASE 70 /* 70ns = 14.29MHz */ 99#define APCI3120_REVB_OSC_BASE 50 /* 50ns = 20MHz */ 100 101static const struct comedi_lrange apci3120_ai_range = { 102 8, { 103 BIP_RANGE(10), 104 BIP_RANGE(5), 105 BIP_RANGE(2), 106 BIP_RANGE(1), 107 UNI_RANGE(10), 108 UNI_RANGE(5), 109 UNI_RANGE(2), 110 UNI_RANGE(1) 111 } 112}; 113 114enum apci3120_boardid { 115 BOARD_APCI3120, 116 BOARD_APCI3001, 117}; 118 119struct apci3120_board { 120 const char *name; 121 unsigned int ai_is_16bit:1; 122 unsigned int has_ao:1; 123}; 124 125static const struct apci3120_board apci3120_boardtypes[] = { 126 [BOARD_APCI3120] = { 127 .name = "apci3120", 128 .ai_is_16bit = 1, 129 .has_ao = 1, 130 }, 131 [BOARD_APCI3001] = { 132 .name = "apci3001", 133 }, 134}; 135 136struct apci3120_dmabuf { 137 unsigned short *virt; 138 dma_addr_t hw; 139 unsigned int size; 140 unsigned int use_size; 141}; 142 143struct apci3120_private { 144 unsigned long amcc; 145 unsigned long addon; 146 unsigned int osc_base; 147 unsigned int use_dma:1; 148 unsigned int use_double_buffer:1; 149 unsigned int cur_dmabuf:1; 150 struct apci3120_dmabuf dmabuf[2]; 151 unsigned char do_bits; 152 unsigned char timer_mode; 153 unsigned char mode; 154 unsigned short ctrl; 155}; 156 157static void apci3120_addon_write(struct comedi_device *dev, 158 unsigned int val, unsigned int reg) 159{ 160 struct apci3120_private *devpriv = dev->private; 161 162 /* 16-bit interface for AMCC add-on registers */ 163 164 outw(reg, devpriv->addon + APCI3120_ADDON_ADDR_REG); 165 outw(val & 0xffff, devpriv->addon + APCI3120_ADDON_DATA_REG); 166 167 outw(reg + 2, devpriv->addon + APCI3120_ADDON_ADDR_REG); 168 outw((val >> 16) & 0xffff, devpriv->addon + APCI3120_ADDON_DATA_REG); 169} 170 171static void apci3120_init_dma(struct comedi_device *dev, 172 struct apci3120_dmabuf *dmabuf) 173{ 174 struct apci3120_private *devpriv = dev->private; 175 176 /* AMCC - enable transfer count and reset A2P FIFO */ 177 outl(AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO, 178 devpriv->amcc + AMCC_OP_REG_AGCSTS); 179 180 /* Add-On - enable transfer count and reset A2P FIFO */ 181 apci3120_addon_write(dev, AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO, 182 AMCC_OP_REG_AGCSTS); 183 184 /* AMCC - enable transfers and reset A2P flags */ 185 outl(RESET_A2P_FLAGS | EN_A2P_TRANSFERS, 186 devpriv->amcc + AMCC_OP_REG_MCSR); 187 188 /* Add-On - DMA start address */ 189 apci3120_addon_write(dev, dmabuf->hw, AMCC_OP_REG_AMWAR); 190 191 /* Add-On - Number of acquisitions */ 192 apci3120_addon_write(dev, dmabuf->use_size, AMCC_OP_REG_AMWTC); 193 194 /* AMCC - enable write complete (DMA) and set FIFO advance */ 195 outl(APCI3120_FIFO_ADVANCE_ON_BYTE_2 | AINT_WRITE_COMPL, 196 devpriv->amcc + AMCC_OP_REG_INTCSR); 197 198 /* Add-On - enable DMA */ 199 outw(APCI3120_ADDON_CTRL_AMWEN_ENA | APCI3120_ADDON_CTRL_A2P_FIFO_ENA, 200 devpriv->addon + APCI3120_ADDON_CTRL_REG); 201} 202 203static void apci3120_setup_dma(struct comedi_device *dev, 204 struct comedi_subdevice *s) 205{ 206 struct apci3120_private *devpriv = dev->private; 207 struct comedi_cmd *cmd = &s->async->cmd; 208 struct apci3120_dmabuf *dmabuf0 = &devpriv->dmabuf[0]; 209 struct apci3120_dmabuf *dmabuf1 = &devpriv->dmabuf[1]; 210 unsigned int dmalen0 = dmabuf0->size; 211 unsigned int dmalen1 = dmabuf1->size; 212 unsigned int scan_bytes; 213 214 scan_bytes = comedi_samples_to_bytes(s, cmd->scan_end_arg); 215 216 if (cmd->stop_src == TRIG_COUNT) { 217 /* 218 * Must we fill full first buffer? And must we fill 219 * full second buffer when first is once filled? 220 */ 221 if (dmalen0 > (cmd->stop_arg * scan_bytes)) 222 dmalen0 = cmd->stop_arg * scan_bytes; 223 else if (dmalen1 > (cmd->stop_arg * scan_bytes - dmalen0)) 224 dmalen1 = cmd->stop_arg * scan_bytes - dmalen0; 225 } 226 227 if (cmd->flags & CMDF_WAKE_EOS) { 228 /* don't we want wake up every scan? */ 229 if (dmalen0 > scan_bytes) { 230 dmalen0 = scan_bytes; 231 if (cmd->scan_end_arg & 1) 232 dmalen0 += 2; 233 } 234 if (dmalen1 > scan_bytes) { 235 dmalen1 = scan_bytes; 236 if (cmd->scan_end_arg & 1) 237 dmalen1 -= 2; 238 if (dmalen1 < 4) 239 dmalen1 = 4; 240 } 241 } else { 242 /* isn't output buff smaller that our DMA buff? */ 243 if (dmalen0 > s->async->prealloc_bufsz) 244 dmalen0 = s->async->prealloc_bufsz; 245 if (dmalen1 > s->async->prealloc_bufsz) 246 dmalen1 = s->async->prealloc_bufsz; 247 } 248 dmabuf0->use_size = dmalen0; 249 dmabuf1->use_size = dmalen1; 250 251 apci3120_init_dma(dev, dmabuf0); 252} 253 254/* 255 * There are three timers on the board. They all use the same base 256 * clock with a fixed prescaler for each timer. The base clock used 257 * depends on the board version and type. 258 * 259 * APCI-3120 Rev A boards OSC = 14.29MHz base clock (~70ns) 260 * APCI-3120 Rev B boards OSC = 20MHz base clock (50ns) 261 * APCI-3001 boards OSC = 20MHz base clock (50ns) 262 * 263 * The prescalers for each timer are: 264 * Timer 0 CLK = OSC/10 265 * Timer 1 CLK = OSC/1000 266 * Timer 2 CLK = OSC/1000 267 */ 268static unsigned int apci3120_ns_to_timer(struct comedi_device *dev, 269 unsigned int timer, 270 unsigned int ns, 271 unsigned int flags) 272{ 273 struct apci3120_private *devpriv = dev->private; 274 unsigned int prescale = (timer == 0) ? 10 : 1000; 275 unsigned int timer_base = devpriv->osc_base * prescale; 276 unsigned int divisor; 277 278 switch (flags & CMDF_ROUND_MASK) { 279 case CMDF_ROUND_UP: 280 divisor = DIV_ROUND_UP(ns, timer_base); 281 break; 282 case CMDF_ROUND_DOWN: 283 divisor = ns / timer_base; 284 break; 285 case CMDF_ROUND_NEAREST: 286 default: 287 divisor = DIV_ROUND_CLOSEST(ns, timer_base); 288 break; 289 } 290 291 if (timer == 2) { 292 /* timer 2 is 24-bits */ 293 if (divisor > 0x00ffffff) 294 divisor = 0x00ffffff; 295 } else { 296 /* timers 0 and 1 are 16-bits */ 297 if (divisor > 0xffff) 298 divisor = 0xffff; 299 } 300 /* the timers require a minimum divisor of 2 */ 301 if (divisor < 2) 302 divisor = 2; 303 304 return divisor; 305} 306 307static void apci3120_clr_timer2_interrupt(struct comedi_device *dev) 308{ 309 /* a dummy read of APCI3120_CTR0_REG clears the timer 2 interrupt */ 310 inb(dev->iobase + APCI3120_CTR0_REG); 311} 312 313static void apci3120_timer_write(struct comedi_device *dev, 314 unsigned int timer, unsigned int val) 315{ 316 struct apci3120_private *devpriv = dev->private; 317 318 /* write 16-bit value to timer (lower 16-bits of timer 2) */ 319 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) | 320 APCI3120_CTR0_TIMER_SEL(timer), 321 dev->iobase + APCI3120_CTR0_REG); 322 outw(val & 0xffff, dev->iobase + APCI3120_TIMER_REG); 323 324 if (timer == 2) { 325 /* write upper 16-bits to timer 2 */ 326 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) | 327 APCI3120_CTR0_TIMER_SEL(timer + 1), 328 dev->iobase + APCI3120_CTR0_REG); 329 outw((val >> 16) & 0xffff, dev->iobase + APCI3120_TIMER_REG); 330 } 331} 332 333static unsigned int apci3120_timer_read(struct comedi_device *dev, 334 unsigned int timer) 335{ 336 struct apci3120_private *devpriv = dev->private; 337 unsigned int val; 338 339 /* read 16-bit value from timer (lower 16-bits of timer 2) */ 340 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) | 341 APCI3120_CTR0_TIMER_SEL(timer), 342 dev->iobase + APCI3120_CTR0_REG); 343 val = inw(dev->iobase + APCI3120_TIMER_REG); 344 345 if (timer == 2) { 346 /* read upper 16-bits from timer 2 */ 347 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) | 348 APCI3120_CTR0_TIMER_SEL(timer + 1), 349 dev->iobase + APCI3120_CTR0_REG); 350 val |= (inw(dev->iobase + APCI3120_TIMER_REG) << 16); 351 } 352 353 return val; 354} 355 356static void apci3120_timer_set_mode(struct comedi_device *dev, 357 unsigned int timer, unsigned int mode) 358{ 359 struct apci3120_private *devpriv = dev->private; 360 361 devpriv->timer_mode &= ~APCI3120_TIMER_MODE_MASK(timer); 362 devpriv->timer_mode |= APCI3120_TIMER_MODE(timer, mode); 363 outb(devpriv->timer_mode, dev->iobase + APCI3120_TIMER_MODE_REG); 364} 365 366static void apci3120_timer_enable(struct comedi_device *dev, 367 unsigned int timer, bool enable) 368{ 369 struct apci3120_private *devpriv = dev->private; 370 371 if (enable) 372 devpriv->ctrl |= APCI3120_CTRL_GATE(timer); 373 else 374 devpriv->ctrl &= ~APCI3120_CTRL_GATE(timer); 375 outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG); 376} 377 378static void apci3120_exttrig_enable(struct comedi_device *dev, bool enable) 379{ 380 struct apci3120_private *devpriv = dev->private; 381 382 if (enable) 383 devpriv->ctrl |= APCI3120_CTRL_EXT_TRIG; 384 else 385 devpriv->ctrl &= ~APCI3120_CTRL_EXT_TRIG; 386 outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG); 387} 388 389static void apci3120_set_chanlist(struct comedi_device *dev, 390 struct comedi_subdevice *s, 391 int n_chan, unsigned int *chanlist) 392{ 393 struct apci3120_private *devpriv = dev->private; 394 int i; 395 396 /* set chanlist for scan */ 397 for (i = 0; i < n_chan; i++) { 398 unsigned int chan = CR_CHAN(chanlist[i]); 399 unsigned int range = CR_RANGE(chanlist[i]); 400 unsigned int val; 401 402 val = APCI3120_CHANLIST_MUX(chan) | 403 APCI3120_CHANLIST_GAIN(range) | 404 APCI3120_CHANLIST_INDEX(i); 405 406 if (comedi_range_is_unipolar(s, range)) 407 val |= APCI3120_CHANLIST_UNIPOLAR; 408 409 outw(val, dev->iobase + APCI3120_CHANLIST_REG); 410 } 411 412 /* a dummy read of APCI3120_TIMER_MODE_REG resets the ai FIFO */ 413 inw(dev->iobase + APCI3120_TIMER_MODE_REG); 414 415 /* set scan length (PR) and scan start (PA) */ 416 devpriv->ctrl = APCI3120_CTRL_PR(n_chan - 1) | APCI3120_CTRL_PA(0); 417 outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG); 418 419 /* enable chanlist scanning if necessary */ 420 if (n_chan > 1) 421 devpriv->mode |= APCI3120_MODE_SCAN_ENA; 422} 423 424static void apci3120_interrupt_dma(struct comedi_device *dev, 425 struct comedi_subdevice *s) 426{ 427 struct apci3120_private *devpriv = dev->private; 428 struct comedi_async *async = s->async; 429 struct comedi_cmd *cmd = &async->cmd; 430 struct apci3120_dmabuf *dmabuf; 431 unsigned int nbytes; 432 unsigned int nsamples; 433 434 dmabuf = &devpriv->dmabuf[devpriv->cur_dmabuf]; 435 436 nbytes = dmabuf->use_size - inl(devpriv->amcc + AMCC_OP_REG_MWTC); 437 438 if (nbytes < dmabuf->use_size) 439 dev_err(dev->class_dev, "Interrupted DMA transfer!\n"); 440 if (nbytes & 1) { 441 dev_err(dev->class_dev, "Odd count of bytes in DMA ring!\n"); 442 async->events |= COMEDI_CB_ERROR; 443 return; 444 } 445 446 nsamples = comedi_bytes_to_samples(s, nbytes); 447 if (nsamples) { 448 comedi_buf_write_samples(s, dmabuf->virt, nsamples); 449 450 if (!(cmd->flags & CMDF_WAKE_EOS)) 451 async->events |= COMEDI_CB_EOS; 452 } 453 454 if ((async->events & COMEDI_CB_CANCEL_MASK) || 455 (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)) 456 return; 457 458 if (devpriv->use_double_buffer) { 459 /* switch DMA buffers for next interrupt */ 460 devpriv->cur_dmabuf = !devpriv->cur_dmabuf; 461 dmabuf = &devpriv->dmabuf[devpriv->cur_dmabuf]; 462 apci3120_init_dma(dev, dmabuf); 463 } else { 464 /* restart DMA if not using double buffering */ 465 apci3120_init_dma(dev, dmabuf); 466 } 467} 468 469static irqreturn_t apci3120_interrupt(int irq, void *d) 470{ 471 struct comedi_device *dev = d; 472 struct apci3120_private *devpriv = dev->private; 473 struct comedi_subdevice *s = dev->read_subdev; 474 struct comedi_async *async = s->async; 475 struct comedi_cmd *cmd = &async->cmd; 476 unsigned int status; 477 unsigned int int_amcc; 478 479 status = inw(dev->iobase + APCI3120_STATUS_REG); 480 int_amcc = inl(devpriv->amcc + AMCC_OP_REG_INTCSR); 481 482 if (!(status & APCI3120_STATUS_INT_MASK) && 483 !(int_amcc & ANY_S593X_INT)) { 484 dev_err(dev->class_dev, "IRQ from unknown source\n"); 485 return IRQ_NONE; 486 } 487 488 outl(int_amcc | AINT_INT_MASK, devpriv->amcc + AMCC_OP_REG_INTCSR); 489 490 if (devpriv->ctrl & APCI3120_CTRL_EXT_TRIG) 491 apci3120_exttrig_enable(dev, false); 492 493 if (int_amcc & MASTER_ABORT_INT) 494 dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n"); 495 if (int_amcc & TARGET_ABORT_INT) 496 dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n"); 497 498 if ((status & APCI3120_STATUS_EOS_INT) && 499 (devpriv->mode & APCI3120_MODE_EOS_IRQ_ENA)) { 500 unsigned short val; 501 int i; 502 503 for (i = 0; i < cmd->chanlist_len; i++) { 504 val = inw(dev->iobase + APCI3120_AI_FIFO_REG); 505 comedi_buf_write_samples(s, &val, 1); 506 } 507 508 devpriv->mode |= APCI3120_MODE_EOS_IRQ_ENA; 509 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG); 510 } 511 512 if (status & APCI3120_STATUS_TIMER2_INT) { 513 /* 514 * for safety... 515 * timer2 interrupts are not enabled in the driver 516 */ 517 apci3120_clr_timer2_interrupt(dev); 518 } 519 520 if (status & APCI3120_STATUS_AMCC_INT) { 521 /* AMCC- Clear write complete interrupt (DMA) */ 522 outl(AINT_WT_COMPLETE, devpriv->amcc + AMCC_OP_REG_INTCSR); 523 524 /* do some data transfer */ 525 apci3120_interrupt_dma(dev, s); 526 } 527 528 if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg) 529 async->events |= COMEDI_CB_EOA; 530 531 comedi_handle_events(dev, s); 532 533 return IRQ_HANDLED; 534} 535 536static int apci3120_ai_cmd(struct comedi_device *dev, 537 struct comedi_subdevice *s) 538{ 539 struct apci3120_private *devpriv = dev->private; 540 struct comedi_cmd *cmd = &s->async->cmd; 541 unsigned int divisor; 542 543 /* set default mode bits */ 544 devpriv->mode = APCI3120_MODE_TIMER2_CLK_OSC | 545 APCI3120_MODE_TIMER2_AS_TIMER; 546 547 /* AMCC- Clear write complete interrupt (DMA) */ 548 outl(AINT_WT_COMPLETE, devpriv->amcc + AMCC_OP_REG_INTCSR); 549 550 devpriv->cur_dmabuf = 0; 551 552 /* load chanlist for command scan */ 553 apci3120_set_chanlist(dev, s, cmd->chanlist_len, cmd->chanlist); 554 555 if (cmd->start_src == TRIG_EXT) 556 apci3120_exttrig_enable(dev, true); 557 558 if (cmd->scan_begin_src == TRIG_TIMER) { 559 /* 560 * Timer 1 is used in MODE2 (rate generator) to set the 561 * start time for each scan. 562 */ 563 divisor = apci3120_ns_to_timer(dev, 1, cmd->scan_begin_arg, 564 cmd->flags); 565 apci3120_timer_set_mode(dev, 1, APCI3120_TIMER_MODE2); 566 apci3120_timer_write(dev, 1, divisor); 567 } 568 569 /* 570 * Timer 0 is used in MODE2 (rate generator) to set the conversion 571 * time for each acquisition. 572 */ 573 divisor = apci3120_ns_to_timer(dev, 0, cmd->convert_arg, cmd->flags); 574 apci3120_timer_set_mode(dev, 0, APCI3120_TIMER_MODE2); 575 apci3120_timer_write(dev, 0, divisor); 576 577 if (devpriv->use_dma) 578 apci3120_setup_dma(dev, s); 579 else 580 devpriv->mode |= APCI3120_MODE_EOS_IRQ_ENA; 581 582 /* set mode to enable acquisition */ 583 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG); 584 585 if (cmd->scan_begin_src == TRIG_TIMER) 586 apci3120_timer_enable(dev, 1, true); 587 apci3120_timer_enable(dev, 0, true); 588 589 return 0; 590} 591 592static int apci3120_ai_cmdtest(struct comedi_device *dev, 593 struct comedi_subdevice *s, 594 struct comedi_cmd *cmd) 595{ 596 unsigned int arg; 597 int err = 0; 598 599 /* Step 1 : check if triggers are trivially valid */ 600 601 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); 602 err |= comedi_check_trigger_src(&cmd->scan_begin_src, 603 TRIG_TIMER | TRIG_FOLLOW); 604 err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_TIMER); 605 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); 606 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); 607 608 if (err) 609 return 1; 610 611 /* Step 2a : make sure trigger sources are unique */ 612 613 err |= comedi_check_trigger_is_unique(cmd->start_src); 614 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src); 615 err |= comedi_check_trigger_is_unique(cmd->stop_src); 616 617 /* Step 2b : and mutually compatible */ 618 619 if (err) 620 return 2; 621 622 /* Step 3: check if arguments are trivially valid */ 623 624 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); 625 626 if (cmd->scan_begin_src == TRIG_TIMER) { /* Test Delay timing */ 627 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, 628 100000); 629 } 630 631 /* minimum conversion time per sample is 10us */ 632 err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 10000); 633 634 err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); 635 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, 636 cmd->chanlist_len); 637 638 if (cmd->stop_src == TRIG_COUNT) 639 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1); 640 else /* TRIG_NONE */ 641 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); 642 643 if (err) 644 return 3; 645 646 /* Step 4: fix up any arguments */ 647 648 if (cmd->scan_begin_src == TRIG_TIMER) { 649 /* scan begin must be larger than the scan time */ 650 arg = cmd->convert_arg * cmd->scan_end_arg; 651 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, arg); 652 } 653 654 if (err) 655 return 4; 656 657 /* Step 5: check channel list if it exists */ 658 659 return 0; 660} 661 662static int apci3120_cancel(struct comedi_device *dev, 663 struct comedi_subdevice *s) 664{ 665 struct apci3120_private *devpriv = dev->private; 666 667 /* Add-On - disable DMA */ 668 outw(0, devpriv->addon + 4); 669 670 /* Add-On - disable bus master */ 671 apci3120_addon_write(dev, 0, AMCC_OP_REG_AGCSTS); 672 673 /* AMCC - disable bus master */ 674 outl(0, devpriv->amcc + AMCC_OP_REG_MCSR); 675 676 /* disable all counters, ext trigger, and reset scan */ 677 devpriv->ctrl = 0; 678 outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG); 679 680 /* DISABLE_ALL_INTERRUPT */ 681 devpriv->mode = 0; 682 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG); 683 684 inw(dev->iobase + APCI3120_STATUS_REG); 685 devpriv->cur_dmabuf = 0; 686 687 return 0; 688} 689 690static int apci3120_ai_eoc(struct comedi_device *dev, 691 struct comedi_subdevice *s, 692 struct comedi_insn *insn, 693 unsigned long context) 694{ 695 unsigned int status; 696 697 status = inw(dev->iobase + APCI3120_STATUS_REG); 698 if ((status & APCI3120_STATUS_EOC_INT) == 0) 699 return 0; 700 return -EBUSY; 701} 702 703static int apci3120_ai_insn_read(struct comedi_device *dev, 704 struct comedi_subdevice *s, 705 struct comedi_insn *insn, 706 unsigned int *data) 707{ 708 struct apci3120_private *devpriv = dev->private; 709 unsigned int divisor; 710 int ret; 711 int i; 712 713 /* set mode for A/D conversions by software trigger with timer 0 */ 714 devpriv->mode = APCI3120_MODE_TIMER2_CLK_OSC | 715 APCI3120_MODE_TIMER2_AS_TIMER; 716 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG); 717 718 /* load chanlist for single channel scan */ 719 apci3120_set_chanlist(dev, s, 1, &insn->chanspec); 720 721 /* 722 * Timer 0 is used in MODE4 (software triggered strobe) to set the 723 * conversion time for each acquisition. Each conversion is triggered 724 * when the divisor is written to the timer, The conversion is done 725 * when the EOC bit in the status register is '0'. 726 */ 727 apci3120_timer_set_mode(dev, 0, APCI3120_TIMER_MODE4); 728 apci3120_timer_enable(dev, 0, true); 729 730 /* fixed conversion time of 10 us */ 731 divisor = apci3120_ns_to_timer(dev, 0, 10000, CMDF_ROUND_NEAREST); 732 733 for (i = 0; i < insn->n; i++) { 734 /* trigger conversion */ 735 apci3120_timer_write(dev, 0, divisor); 736 737 ret = comedi_timeout(dev, s, insn, apci3120_ai_eoc, 0); 738 if (ret) 739 return ret; 740 741 data[i] = inw(dev->iobase + APCI3120_AI_FIFO_REG); 742 } 743 744 return insn->n; 745} 746 747static int apci3120_ao_ready(struct comedi_device *dev, 748 struct comedi_subdevice *s, 749 struct comedi_insn *insn, 750 unsigned long context) 751{ 752 unsigned int status; 753 754 status = inw(dev->iobase + APCI3120_STATUS_REG); 755 if (status & APCI3120_STATUS_DA_READY) 756 return 0; 757 return -EBUSY; 758} 759 760static int apci3120_ao_insn_write(struct comedi_device *dev, 761 struct comedi_subdevice *s, 762 struct comedi_insn *insn, 763 unsigned int *data) 764{ 765 unsigned int chan = CR_CHAN(insn->chanspec); 766 int i; 767 768 for (i = 0; i < insn->n; i++) { 769 unsigned int val = data[i]; 770 int ret; 771 772 ret = comedi_timeout(dev, s, insn, apci3120_ao_ready, 0); 773 if (ret) 774 return ret; 775 776 outw(APCI3120_AO_MUX(chan) | APCI3120_AO_DATA(val), 777 dev->iobase + APCI3120_AO_REG(chan)); 778 779 s->readback[chan] = val; 780 } 781 782 return insn->n; 783} 784 785static int apci3120_di_insn_bits(struct comedi_device *dev, 786 struct comedi_subdevice *s, 787 struct comedi_insn *insn, 788 unsigned int *data) 789{ 790 unsigned int status; 791 792 status = inw(dev->iobase + APCI3120_STATUS_REG); 793 data[1] = APCI3120_STATUS_TO_DI_BITS(status); 794 795 return insn->n; 796} 797 798static int apci3120_do_insn_bits(struct comedi_device *dev, 799 struct comedi_subdevice *s, 800 struct comedi_insn *insn, 801 unsigned int *data) 802{ 803 struct apci3120_private *devpriv = dev->private; 804 805 if (comedi_dio_update_state(s, data)) { 806 devpriv->do_bits = s->state; 807 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits), 808 dev->iobase + APCI3120_CTR0_REG); 809 } 810 811 data[1] = s->state; 812 813 return insn->n; 814} 815 816static int apci3120_timer_insn_config(struct comedi_device *dev, 817 struct comedi_subdevice *s, 818 struct comedi_insn *insn, 819 unsigned int *data) 820{ 821 struct apci3120_private *devpriv = dev->private; 822 unsigned int divisor; 823 unsigned int status; 824 unsigned int mode; 825 unsigned int timer_mode; 826 827 switch (data[0]) { 828 case INSN_CONFIG_ARM: 829 apci3120_clr_timer2_interrupt(dev); 830 divisor = apci3120_ns_to_timer(dev, 2, data[1], 831 CMDF_ROUND_DOWN); 832 apci3120_timer_write(dev, 2, divisor); 833 apci3120_timer_enable(dev, 2, true); 834 break; 835 836 case INSN_CONFIG_DISARM: 837 apci3120_timer_enable(dev, 2, false); 838 apci3120_clr_timer2_interrupt(dev); 839 break; 840 841 case INSN_CONFIG_GET_COUNTER_STATUS: 842 data[1] = 0; 843 data[2] = COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING | 844 COMEDI_COUNTER_TERMINAL_COUNT; 845 846 if (devpriv->ctrl & APCI3120_CTRL_GATE(2)) { 847 data[1] |= COMEDI_COUNTER_ARMED; 848 data[1] |= COMEDI_COUNTER_COUNTING; 849 } 850 status = inw(dev->iobase + APCI3120_STATUS_REG); 851 if (status & APCI3120_STATUS_TIMER2_INT) { 852 data[1] &= ~COMEDI_COUNTER_COUNTING; 853 data[1] |= COMEDI_COUNTER_TERMINAL_COUNT; 854 } 855 break; 856 857 case INSN_CONFIG_SET_COUNTER_MODE: 858 switch (data[1]) { 859 case I8254_MODE0: 860 mode = APCI3120_MODE_TIMER2_AS_COUNTER; 861 timer_mode = APCI3120_TIMER_MODE0; 862 break; 863 case I8254_MODE2: 864 mode = APCI3120_MODE_TIMER2_AS_TIMER; 865 timer_mode = APCI3120_TIMER_MODE2; 866 break; 867 case I8254_MODE4: 868 mode = APCI3120_MODE_TIMER2_AS_TIMER; 869 timer_mode = APCI3120_TIMER_MODE4; 870 break; 871 case I8254_MODE5: 872 mode = APCI3120_MODE_TIMER2_AS_WDOG; 873 timer_mode = APCI3120_TIMER_MODE5; 874 break; 875 default: 876 return -EINVAL; 877 } 878 apci3120_timer_enable(dev, 2, false); 879 apci3120_clr_timer2_interrupt(dev); 880 apci3120_timer_set_mode(dev, 2, timer_mode); 881 devpriv->mode &= ~APCI3120_MODE_TIMER2_AS_MASK; 882 devpriv->mode |= mode; 883 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG); 884 break; 885 886 default: 887 return -EINVAL; 888 } 889 890 return insn->n; 891} 892 893static int apci3120_timer_insn_read(struct comedi_device *dev, 894 struct comedi_subdevice *s, 895 struct comedi_insn *insn, 896 unsigned int *data) 897{ 898 int i; 899 900 for (i = 0; i < insn->n; i++) 901 data[i] = apci3120_timer_read(dev, 2); 902 903 return insn->n; 904} 905 906static void apci3120_dma_alloc(struct comedi_device *dev) 907{ 908 struct apci3120_private *devpriv = dev->private; 909 struct apci3120_dmabuf *dmabuf; 910 int order; 911 int i; 912 913 for (i = 0; i < 2; i++) { 914 dmabuf = &devpriv->dmabuf[i]; 915 for (order = 2; order >= 0; order--) { 916 dmabuf->virt = dma_alloc_coherent(dev->hw_dev, 917 PAGE_SIZE << order, 918 &dmabuf->hw, 919 GFP_KERNEL); 920 if (dmabuf->virt) 921 break; 922 } 923 if (!dmabuf->virt) 924 break; 925 dmabuf->size = PAGE_SIZE << order; 926 927 if (i == 0) 928 devpriv->use_dma = 1; 929 if (i == 1) 930 devpriv->use_double_buffer = 1; 931 } 932} 933 934static void apci3120_dma_free(struct comedi_device *dev) 935{ 936 struct apci3120_private *devpriv = dev->private; 937 struct apci3120_dmabuf *dmabuf; 938 int i; 939 940 if (!devpriv) 941 return; 942 943 for (i = 0; i < 2; i++) { 944 dmabuf = &devpriv->dmabuf[i]; 945 if (dmabuf->virt) { 946 dma_free_coherent(dev->hw_dev, dmabuf->size, 947 dmabuf->virt, dmabuf->hw); 948 } 949 } 950} 951 952static void apci3120_reset(struct comedi_device *dev) 953{ 954 /* disable all interrupt sources */ 955 outb(0, dev->iobase + APCI3120_MODE_REG); 956 957 /* disable all counters, ext trigger, and reset scan */ 958 outw(0, dev->iobase + APCI3120_CTRL_REG); 959 960 /* clear interrupt status */ 961 inw(dev->iobase + APCI3120_STATUS_REG); 962} 963 964static int apci3120_auto_attach(struct comedi_device *dev, 965 unsigned long context) 966{ 967 struct pci_dev *pcidev = comedi_to_pci_dev(dev); 968 const struct apci3120_board *board = NULL; 969 struct apci3120_private *devpriv; 970 struct comedi_subdevice *s; 971 unsigned int status; 972 int ret; 973 974 if (context < ARRAY_SIZE(apci3120_boardtypes)) 975 board = &apci3120_boardtypes[context]; 976 if (!board) 977 return -ENODEV; 978 dev->board_ptr = board; 979 dev->board_name = board->name; 980 981 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); 982 if (!devpriv) 983 return -ENOMEM; 984 985 ret = comedi_pci_enable(dev); 986 if (ret) 987 return ret; 988 pci_set_master(pcidev); 989 990 dev->iobase = pci_resource_start(pcidev, 1); 991 devpriv->amcc = pci_resource_start(pcidev, 0); 992 devpriv->addon = pci_resource_start(pcidev, 2); 993 994 apci3120_reset(dev); 995 996 if (pcidev->irq > 0) { 997 ret = request_irq(pcidev->irq, apci3120_interrupt, IRQF_SHARED, 998 dev->board_name, dev); 999 if (ret == 0) { 1000 dev->irq = pcidev->irq; 1001 1002 apci3120_dma_alloc(dev); 1003 } 1004 } 1005 1006 status = inw(dev->iobase + APCI3120_STATUS_REG); 1007 if (APCI3120_STATUS_TO_VERSION(status) == APCI3120_REVB || 1008 context == BOARD_APCI3001) 1009 devpriv->osc_base = APCI3120_REVB_OSC_BASE; 1010 else 1011 devpriv->osc_base = APCI3120_REVA_OSC_BASE; 1012 1013 ret = comedi_alloc_subdevices(dev, 5); 1014 if (ret) 1015 return ret; 1016 1017 /* Analog Input subdevice */ 1018 s = &dev->subdevices[0]; 1019 s->type = COMEDI_SUBD_AI; 1020 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; 1021 s->n_chan = 16; 1022 s->maxdata = board->ai_is_16bit ? 0xffff : 0x0fff; 1023 s->range_table = &apci3120_ai_range; 1024 s->insn_read = apci3120_ai_insn_read; 1025 if (dev->irq) { 1026 dev->read_subdev = s; 1027 s->subdev_flags |= SDF_CMD_READ; 1028 s->len_chanlist = s->n_chan; 1029 s->do_cmdtest = apci3120_ai_cmdtest; 1030 s->do_cmd = apci3120_ai_cmd; 1031 s->cancel = apci3120_cancel; 1032 } 1033 1034 /* Analog Output subdevice */ 1035 s = &dev->subdevices[1]; 1036 if (board->has_ao) { 1037 s->type = COMEDI_SUBD_AO; 1038 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; 1039 s->n_chan = 8; 1040 s->maxdata = 0x3fff; 1041 s->range_table = &range_bipolar10; 1042 s->insn_write = apci3120_ao_insn_write; 1043 1044 ret = comedi_alloc_subdev_readback(s); 1045 if (ret) 1046 return ret; 1047 } else { 1048 s->type = COMEDI_SUBD_UNUSED; 1049 } 1050 1051 /* Digital Input subdevice */ 1052 s = &dev->subdevices[2]; 1053 s->type = COMEDI_SUBD_DI; 1054 s->subdev_flags = SDF_READABLE; 1055 s->n_chan = 4; 1056 s->maxdata = 1; 1057 s->range_table = &range_digital; 1058 s->insn_bits = apci3120_di_insn_bits; 1059 1060 /* Digital Output subdevice */ 1061 s = &dev->subdevices[3]; 1062 s->type = COMEDI_SUBD_DO; 1063 s->subdev_flags = SDF_WRITABLE; 1064 s->n_chan = 4; 1065 s->maxdata = 1; 1066 s->range_table = &range_digital; 1067 s->insn_bits = apci3120_do_insn_bits; 1068 1069 /* Timer subdevice */ 1070 s = &dev->subdevices[4]; 1071 s->type = COMEDI_SUBD_TIMER; 1072 s->subdev_flags = SDF_READABLE; 1073 s->n_chan = 1; 1074 s->maxdata = 0x00ffffff; 1075 s->insn_config = apci3120_timer_insn_config; 1076 s->insn_read = apci3120_timer_insn_read; 1077 1078 return 0; 1079} 1080 1081static void apci3120_detach(struct comedi_device *dev) 1082{ 1083 comedi_pci_detach(dev); 1084 apci3120_dma_free(dev); 1085} 1086 1087static struct comedi_driver apci3120_driver = { 1088 .driver_name = "addi_apci_3120", 1089 .module = THIS_MODULE, 1090 .auto_attach = apci3120_auto_attach, 1091 .detach = apci3120_detach, 1092}; 1093 1094static int apci3120_pci_probe(struct pci_dev *dev, 1095 const struct pci_device_id *id) 1096{ 1097 return comedi_pci_auto_config(dev, &apci3120_driver, id->driver_data); 1098} 1099 1100static const struct pci_device_id apci3120_pci_table[] = { 1101 { PCI_VDEVICE(AMCC, 0x818d), BOARD_APCI3120 }, 1102 { PCI_VDEVICE(AMCC, 0x828d), BOARD_APCI3001 }, 1103 { 0 } 1104}; 1105MODULE_DEVICE_TABLE(pci, apci3120_pci_table); 1106 1107static struct pci_driver apci3120_pci_driver = { 1108 .name = "addi_apci_3120", 1109 .id_table = apci3120_pci_table, 1110 .probe = apci3120_pci_probe, 1111 .remove = comedi_pci_auto_unconfig, 1112}; 1113module_comedi_pci_driver(apci3120_driver, apci3120_pci_driver); 1114 1115MODULE_AUTHOR("Comedi https://www.comedi.org"); 1116MODULE_DESCRIPTION("ADDI-DATA APCI-3120, Analog input board"); 1117MODULE_LICENSE("GPL");