1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * comedi/drivers/pcl812.c 4 * 5 * Author: Michal Dobes <dobes@tesnet.cz> 6 * 7 * hardware driver for Advantech cards 8 * card: PCL-812, PCL-812PG, PCL-813, PCL-813B 9 * driver: pcl812, pcl812pg, pcl813, pcl813b 10 * and for ADlink cards 11 * card: ACL-8112DG, ACL-8112HG, ACL-8112PG, ACL-8113, ACL-8216 12 * driver: acl8112dg, acl8112hg, acl8112pg, acl8113, acl8216 13 * and for ICP DAS cards 14 * card: ISO-813, A-821PGH, A-821PGL, A-821PGL-NDA, A-822PGH, A-822PGL, 15 * driver: iso813, a821pgh, a-821pgl, a-821pglnda, a822pgh, a822pgl, 16 * card: A-823PGH, A-823PGL, A-826PG 17 * driver: a823pgh, a823pgl, a826pg 18 */ 19 20 /* 21 * Driver: pcl812 22 * Description: Advantech PCL-812/PG, PCL-813/B, 23 * ADLink ACL-8112DG/HG/PG, ACL-8113, ACL-8216, 24 * ICP DAS A-821PGH/PGL/PGL-NDA, A-822PGH/PGL, A-823PGH/PGL, A-826PG, 25 * ICP DAS ISO-813 26 * Author: Michal Dobes <dobes@tesnet.cz> 27 * Devices: [Advantech] PCL-812 (pcl812), PCL-812PG (pcl812pg), 28 * PCL-813 (pcl813), PCL-813B (pcl813b), [ADLink] ACL-8112DG (acl8112dg), 29 * ACL-8112HG (acl8112hg), ACL-8113 (acl-8113), ACL-8216 (acl8216), 30 * [ICP] ISO-813 (iso813), A-821PGH (a821pgh), A-821PGL (a821pgl), 31 * A-821PGL-NDA (a821pclnda), A-822PGH (a822pgh), A-822PGL (a822pgl), 32 * A-823PGH (a823pgh), A-823PGL (a823pgl), A-826PG (a826pg) 33 * Updated: Mon, 06 Aug 2007 12:03:15 +0100 34 * Status: works (I hope. My board fire up under my hands 35 * and I cann't test all features.) 36 * 37 * This driver supports insn and cmd interfaces. Some boards support only insn 38 * because their hardware don't allow more (PCL-813/B, ACL-8113, ISO-813). 39 * Data transfer over DMA is supported only when you measure only one 40 * channel, this is too hardware limitation of these boards. 41 * 42 * Options for PCL-812: 43 * [0] - IO Base 44 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) 45 * [2] - DMA (0=disable, 1, 3) 46 * [3] - 0=trigger source is internal 8253 with 2MHz clock 47 * 1=trigger source is external 48 * [4] - 0=A/D input range is +/-10V 49 * 1=A/D input range is +/-5V 50 * 2=A/D input range is +/-2.5V 51 * 3=A/D input range is +/-1.25V 52 * 4=A/D input range is +/-0.625V 53 * 5=A/D input range is +/-0.3125V 54 * [5] - 0=D/A outputs 0-5V (internal reference -5V) 55 * 1=D/A outputs 0-10V (internal reference -10V) 56 * 2=D/A outputs unknown (external reference) 57 * 58 * Options for PCL-812PG, ACL-8112PG: 59 * [0] - IO Base 60 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) 61 * [2] - DMA (0=disable, 1, 3) 62 * [3] - 0=trigger source is internal 8253 with 2MHz clock 63 * 1=trigger source is external 64 * [4] - 0=A/D have max +/-5V input 65 * 1=A/D have max +/-10V input 66 * [5] - 0=D/A outputs 0-5V (internal reference -5V) 67 * 1=D/A outputs 0-10V (internal reference -10V) 68 * 2=D/A outputs unknown (external reference) 69 * 70 * Options for ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH, ACL-8216, A-826PG: 71 * [0] - IO Base 72 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) 73 * [2] - DMA (0=disable, 1, 3) 74 * [3] - 0=trigger source is internal 8253 with 2MHz clock 75 * 1=trigger source is external 76 * [4] - 0=A/D channels are S.E. 77 * 1=A/D channels are DIFF 78 * [5] - 0=D/A outputs 0-5V (internal reference -5V) 79 * 1=D/A outputs 0-10V (internal reference -10V) 80 * 2=D/A outputs unknown (external reference) 81 * 82 * Options for A-821PGL/PGH: 83 * [0] - IO Base 84 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) 85 * [2] - 0=A/D channels are S.E. 86 * 1=A/D channels are DIFF 87 * [3] - 0=D/A output 0-5V (internal reference -5V) 88 * 1=D/A output 0-10V (internal reference -10V) 89 * 90 * Options for A-821PGL-NDA: 91 * [0] - IO Base 92 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) 93 * [2] - 0=A/D channels are S.E. 94 * 1=A/D channels are DIFF 95 * 96 * Options for PCL-813: 97 * [0] - IO Base 98 * 99 * Options for PCL-813B: 100 * [0] - IO Base 101 * [1] - 0= bipolar inputs 102 * 1= unipolar inputs 103 * 104 * Options for ACL-8113, ISO-813: 105 * [0] - IO Base 106 * [1] - 0= 10V bipolar inputs 107 * 1= 10V unipolar inputs 108 * 2= 20V bipolar inputs 109 * 3= 20V unipolar inputs 110 */ 111 112 #include <linux/module.h> 113 #include <linux/interrupt.h> 114 #include <linux/gfp.h> 115 #include <linux/delay.h> 116 #include <linux/io.h> 117 #include <linux/comedi/comedidev.h> 118 #include <linux/comedi/comedi_8254.h> 119 #include <linux/comedi/comedi_isadma.h> 120 121 /* 122 * Register I/O map 123 */ 124 #define PCL812_TIMER_BASE 0x00 125 #define PCL812_AI_LSB_REG 0x04 126 #define PCL812_AI_MSB_REG 0x05 127 #define PCL812_AI_MSB_DRDY BIT(4) 128 #define PCL812_AO_LSB_REG(x) (0x04 + ((x) * 2)) 129 #define PCL812_AO_MSB_REG(x) (0x05 + ((x) * 2)) 130 #define PCL812_DI_LSB_REG 0x06 131 #define PCL812_DI_MSB_REG 0x07 132 #define PCL812_STATUS_REG 0x08 133 #define PCL812_STATUS_DRDY BIT(5) 134 #define PCL812_RANGE_REG 0x09 135 #define PCL812_MUX_REG 0x0a 136 #define PCL812_MUX_CHAN(x) ((x) << 0) 137 #define PCL812_MUX_CS0 BIT(4) 138 #define PCL812_MUX_CS1 BIT(5) 139 #define PCL812_CTRL_REG 0x0b 140 #define PCL812_CTRL_TRIG(x) (((x) & 0x7) << 0) 141 #define PCL812_CTRL_DISABLE_TRIG PCL812_CTRL_TRIG(0) 142 #define PCL812_CTRL_SOFT_TRIG PCL812_CTRL_TRIG(1) 143 #define PCL812_CTRL_PACER_DMA_TRIG PCL812_CTRL_TRIG(2) 144 #define PCL812_CTRL_PACER_EOC_TRIG PCL812_CTRL_TRIG(6) 145 #define PCL812_SOFTTRIG_REG 0x0c 146 #define PCL812_DO_LSB_REG 0x0d 147 #define PCL812_DO_MSB_REG 0x0e 148 149 #define MAX_CHANLIST_LEN 256 /* length of scan list */ 150 151 static const struct comedi_lrange range_pcl812pg_ai = { 152 5, { 153 BIP_RANGE(5), 154 BIP_RANGE(2.5), 155 BIP_RANGE(1.25), 156 BIP_RANGE(0.625), 157 BIP_RANGE(0.3125) 158 } 159 }; 160 161 static const struct comedi_lrange range_pcl812pg2_ai = { 162 5, { 163 BIP_RANGE(10), 164 BIP_RANGE(5), 165 BIP_RANGE(2.5), 166 BIP_RANGE(1.25), 167 BIP_RANGE(0.625) 168 } 169 }; 170 171 static const struct comedi_lrange range812_bipolar1_25 = { 172 1, { 173 BIP_RANGE(1.25) 174 } 175 }; 176 177 static const struct comedi_lrange range812_bipolar0_625 = { 178 1, { 179 BIP_RANGE(0.625) 180 } 181 }; 182 183 static const struct comedi_lrange range812_bipolar0_3125 = { 184 1, { 185 BIP_RANGE(0.3125) 186 } 187 }; 188 189 static const struct comedi_lrange range_pcl813b_ai = { 190 4, { 191 BIP_RANGE(5), 192 BIP_RANGE(2.5), 193 BIP_RANGE(1.25), 194 BIP_RANGE(0.625) 195 } 196 }; 197 198 static const struct comedi_lrange range_pcl813b2_ai = { 199 4, { 200 UNI_RANGE(10), 201 UNI_RANGE(5), 202 UNI_RANGE(2.5), 203 UNI_RANGE(1.25) 204 } 205 }; 206 207 static const struct comedi_lrange range_iso813_1_ai = { 208 5, { 209 BIP_RANGE(5), 210 BIP_RANGE(2.5), 211 BIP_RANGE(1.25), 212 BIP_RANGE(0.625), 213 BIP_RANGE(0.3125) 214 } 215 }; 216 217 static const struct comedi_lrange range_iso813_1_2_ai = { 218 5, { 219 UNI_RANGE(10), 220 UNI_RANGE(5), 221 UNI_RANGE(2.5), 222 UNI_RANGE(1.25), 223 UNI_RANGE(0.625) 224 } 225 }; 226 227 static const struct comedi_lrange range_iso813_2_ai = { 228 4, { 229 BIP_RANGE(5), 230 BIP_RANGE(2.5), 231 BIP_RANGE(1.25), 232 BIP_RANGE(0.625) 233 } 234 }; 235 236 static const struct comedi_lrange range_iso813_2_2_ai = { 237 4, { 238 UNI_RANGE(10), 239 UNI_RANGE(5), 240 UNI_RANGE(2.5), 241 UNI_RANGE(1.25) 242 } 243 }; 244 245 static const struct comedi_lrange range_acl8113_1_ai = { 246 4, { 247 BIP_RANGE(5), 248 BIP_RANGE(2.5), 249 BIP_RANGE(1.25), 250 BIP_RANGE(0.625) 251 } 252 }; 253 254 static const struct comedi_lrange range_acl8113_1_2_ai = { 255 4, { 256 UNI_RANGE(10), 257 UNI_RANGE(5), 258 UNI_RANGE(2.5), 259 UNI_RANGE(1.25) 260 } 261 }; 262 263 static const struct comedi_lrange range_acl8113_2_ai = { 264 3, { 265 BIP_RANGE(5), 266 BIP_RANGE(2.5), 267 BIP_RANGE(1.25) 268 } 269 }; 270 271 static const struct comedi_lrange range_acl8113_2_2_ai = { 272 3, { 273 UNI_RANGE(10), 274 UNI_RANGE(5), 275 UNI_RANGE(2.5) 276 } 277 }; 278 279 static const struct comedi_lrange range_acl8112dg_ai = { 280 9, { 281 BIP_RANGE(5), 282 BIP_RANGE(2.5), 283 BIP_RANGE(1.25), 284 BIP_RANGE(0.625), 285 UNI_RANGE(10), 286 UNI_RANGE(5), 287 UNI_RANGE(2.5), 288 UNI_RANGE(1.25), 289 BIP_RANGE(10) 290 } 291 }; 292 293 static const struct comedi_lrange range_acl8112hg_ai = { 294 12, { 295 BIP_RANGE(5), 296 BIP_RANGE(0.5), 297 BIP_RANGE(0.05), 298 BIP_RANGE(0.005), 299 UNI_RANGE(10), 300 UNI_RANGE(1), 301 UNI_RANGE(0.1), 302 UNI_RANGE(0.01), 303 BIP_RANGE(10), 304 BIP_RANGE(1), 305 BIP_RANGE(0.1), 306 BIP_RANGE(0.01) 307 } 308 }; 309 310 static const struct comedi_lrange range_a821pgh_ai = { 311 4, { 312 BIP_RANGE(5), 313 BIP_RANGE(0.5), 314 BIP_RANGE(0.05), 315 BIP_RANGE(0.005) 316 } 317 }; 318 319 enum pcl812_boardtype { 320 BOARD_PCL812PG = 0, /* and ACL-8112PG */ 321 BOARD_PCL813B = 1, 322 BOARD_PCL812 = 2, 323 BOARD_PCL813 = 3, 324 BOARD_ISO813 = 5, 325 BOARD_ACL8113 = 6, 326 BOARD_ACL8112 = 7, /* ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH */ 327 BOARD_ACL8216 = 8, /* and ICP DAS A-826PG */ 328 BOARD_A821 = 9, /* PGH, PGL, PGL/NDA versions */ 329 }; 330 331 struct pcl812_board { 332 const char *name; 333 enum pcl812_boardtype board_type; 334 int n_aichan; 335 int n_aochan; 336 unsigned int ai_ns_min; 337 const struct comedi_lrange *rangelist_ai; 338 unsigned int irq_bits; 339 unsigned int has_dma:1; 340 unsigned int has_16bit_ai:1; 341 unsigned int has_mpc508_mux:1; 342 unsigned int has_dio:1; 343 }; 344 345 static const struct pcl812_board boardtypes[] = { 346 { 347 .name = "pcl812", 348 .board_type = BOARD_PCL812, 349 .n_aichan = 16, 350 .n_aochan = 2, 351 .ai_ns_min = 33000, 352 .rangelist_ai = &range_bipolar10, 353 .irq_bits = 0xdcfc, 354 .has_dma = 1, 355 .has_dio = 1, 356 }, { 357 .name = "pcl812pg", 358 .board_type = BOARD_PCL812PG, 359 .n_aichan = 16, 360 .n_aochan = 2, 361 .ai_ns_min = 33000, 362 .rangelist_ai = &range_pcl812pg_ai, 363 .irq_bits = 0xdcfc, 364 .has_dma = 1, 365 .has_dio = 1, 366 }, { 367 .name = "acl8112pg", 368 .board_type = BOARD_PCL812PG, 369 .n_aichan = 16, 370 .n_aochan = 2, 371 .ai_ns_min = 10000, 372 .rangelist_ai = &range_pcl812pg_ai, 373 .irq_bits = 0xdcfc, 374 .has_dma = 1, 375 .has_dio = 1, 376 }, { 377 .name = "acl8112dg", 378 .board_type = BOARD_ACL8112, 379 .n_aichan = 16, /* 8 differential */ 380 .n_aochan = 2, 381 .ai_ns_min = 10000, 382 .rangelist_ai = &range_acl8112dg_ai, 383 .irq_bits = 0xdcfc, 384 .has_dma = 1, 385 .has_mpc508_mux = 1, 386 .has_dio = 1, 387 }, { 388 .name = "acl8112hg", 389 .board_type = BOARD_ACL8112, 390 .n_aichan = 16, /* 8 differential */ 391 .n_aochan = 2, 392 .ai_ns_min = 10000, 393 .rangelist_ai = &range_acl8112hg_ai, 394 .irq_bits = 0xdcfc, 395 .has_dma = 1, 396 .has_mpc508_mux = 1, 397 .has_dio = 1, 398 }, { 399 .name = "a821pgl", 400 .board_type = BOARD_A821, 401 .n_aichan = 16, /* 8 differential */ 402 .n_aochan = 1, 403 .ai_ns_min = 10000, 404 .rangelist_ai = &range_pcl813b_ai, 405 .irq_bits = 0x000c, 406 .has_dio = 1, 407 }, { 408 .name = "a821pglnda", 409 .board_type = BOARD_A821, 410 .n_aichan = 16, /* 8 differential */ 411 .ai_ns_min = 10000, 412 .rangelist_ai = &range_pcl813b_ai, 413 .irq_bits = 0x000c, 414 }, { 415 .name = "a821pgh", 416 .board_type = BOARD_A821, 417 .n_aichan = 16, /* 8 differential */ 418 .n_aochan = 1, 419 .ai_ns_min = 10000, 420 .rangelist_ai = &range_a821pgh_ai, 421 .irq_bits = 0x000c, 422 .has_dio = 1, 423 }, { 424 .name = "a822pgl", 425 .board_type = BOARD_ACL8112, 426 .n_aichan = 16, /* 8 differential */ 427 .n_aochan = 2, 428 .ai_ns_min = 10000, 429 .rangelist_ai = &range_acl8112dg_ai, 430 .irq_bits = 0xdcfc, 431 .has_dma = 1, 432 .has_dio = 1, 433 }, { 434 .name = "a822pgh", 435 .board_type = BOARD_ACL8112, 436 .n_aichan = 16, /* 8 differential */ 437 .n_aochan = 2, 438 .ai_ns_min = 10000, 439 .rangelist_ai = &range_acl8112hg_ai, 440 .irq_bits = 0xdcfc, 441 .has_dma = 1, 442 .has_dio = 1, 443 }, { 444 .name = "a823pgl", 445 .board_type = BOARD_ACL8112, 446 .n_aichan = 16, /* 8 differential */ 447 .n_aochan = 2, 448 .ai_ns_min = 8000, 449 .rangelist_ai = &range_acl8112dg_ai, 450 .irq_bits = 0xdcfc, 451 .has_dma = 1, 452 .has_dio = 1, 453 }, { 454 .name = "a823pgh", 455 .board_type = BOARD_ACL8112, 456 .n_aichan = 16, /* 8 differential */ 457 .n_aochan = 2, 458 .ai_ns_min = 8000, 459 .rangelist_ai = &range_acl8112hg_ai, 460 .irq_bits = 0xdcfc, 461 .has_dma = 1, 462 .has_dio = 1, 463 }, { 464 .name = "pcl813", 465 .board_type = BOARD_PCL813, 466 .n_aichan = 32, 467 .rangelist_ai = &range_pcl813b_ai, 468 }, { 469 .name = "pcl813b", 470 .board_type = BOARD_PCL813B, 471 .n_aichan = 32, 472 .rangelist_ai = &range_pcl813b_ai, 473 }, { 474 .name = "acl8113", 475 .board_type = BOARD_ACL8113, 476 .n_aichan = 32, 477 .rangelist_ai = &range_acl8113_1_ai, 478 }, { 479 .name = "iso813", 480 .board_type = BOARD_ISO813, 481 .n_aichan = 32, 482 .rangelist_ai = &range_iso813_1_ai, 483 }, { 484 .name = "acl8216", 485 .board_type = BOARD_ACL8216, 486 .n_aichan = 16, /* 8 differential */ 487 .n_aochan = 2, 488 .ai_ns_min = 10000, 489 .rangelist_ai = &range_pcl813b2_ai, 490 .irq_bits = 0xdcfc, 491 .has_dma = 1, 492 .has_16bit_ai = 1, 493 .has_mpc508_mux = 1, 494 .has_dio = 1, 495 }, { 496 .name = "a826pg", 497 .board_type = BOARD_ACL8216, 498 .n_aichan = 16, /* 8 differential */ 499 .n_aochan = 2, 500 .ai_ns_min = 10000, 501 .rangelist_ai = &range_pcl813b2_ai, 502 .irq_bits = 0xdcfc, 503 .has_dma = 1, 504 .has_16bit_ai = 1, 505 .has_dio = 1, 506 }, 507 }; 508 509 struct pcl812_private { 510 struct comedi_isadma *dma; 511 unsigned char range_correction; /* =1 we must add 1 to range number */ 512 unsigned int last_ai_chanspec; 513 unsigned char mode_reg_int; /* stored INT number for some cards */ 514 unsigned int ai_poll_ptr; /* how many samples transfer poll */ 515 unsigned int max_812_ai_mode0_rangewait; /* settling time for gain */ 516 unsigned int use_diff:1; 517 unsigned int use_mpc508:1; 518 unsigned int use_ext_trg:1; 519 unsigned int ai_dma:1; 520 unsigned int ai_eos:1; 521 }; 522 523 static void pcl812_ai_setup_dma(struct comedi_device *dev, 524 struct comedi_subdevice *s, 525 unsigned int unread_samples) 526 { 527 struct pcl812_private *devpriv = dev->private; 528 struct comedi_isadma *dma = devpriv->dma; 529 struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; 530 unsigned int bytes; 531 unsigned int max_samples; 532 unsigned int nsamples; 533 534 comedi_isadma_disable(dma->chan); 535 536 /* if using EOS, adapt DMA buffer to one scan */ 537 bytes = devpriv->ai_eos ? comedi_bytes_per_scan(s) : desc->maxsize; 538 max_samples = comedi_bytes_to_samples(s, bytes); 539 540 /* 541 * Determine dma size based on the buffer size plus the number of 542 * unread samples and the number of samples remaining in the command. 543 */ 544 nsamples = comedi_nsamples_left(s, max_samples + unread_samples); 545 if (nsamples > unread_samples) { 546 nsamples -= unread_samples; 547 desc->size = comedi_samples_to_bytes(s, nsamples); 548 comedi_isadma_program(desc); 549 } 550 } 551 552 static void pcl812_ai_set_chan_range(struct comedi_device *dev, 553 unsigned int chanspec, char wait) 554 { 555 struct pcl812_private *devpriv = dev->private; 556 unsigned int chan = CR_CHAN(chanspec); 557 unsigned int range = CR_RANGE(chanspec); 558 unsigned int mux = 0; 559 560 if (chanspec == devpriv->last_ai_chanspec) 561 return; 562 563 devpriv->last_ai_chanspec = chanspec; 564 565 if (devpriv->use_mpc508) { 566 if (devpriv->use_diff) { 567 mux |= PCL812_MUX_CS0 | PCL812_MUX_CS1; 568 } else { 569 if (chan < 8) 570 mux |= PCL812_MUX_CS0; 571 else 572 mux |= PCL812_MUX_CS1; 573 } 574 } 575 576 outb(mux | PCL812_MUX_CHAN(chan), dev->iobase + PCL812_MUX_REG); 577 outb(range + devpriv->range_correction, dev->iobase + PCL812_RANGE_REG); 578 579 if (wait) 580 /* 581 * XXX this depends on selected range and can be very long for 582 * some high gain ranges! 583 */ 584 udelay(devpriv->max_812_ai_mode0_rangewait); 585 } 586 587 static void pcl812_ai_clear_eoc(struct comedi_device *dev) 588 { 589 /* writing any value clears the interrupt request */ 590 outb(0, dev->iobase + PCL812_STATUS_REG); 591 } 592 593 static void pcl812_ai_soft_trig(struct comedi_device *dev) 594 { 595 /* writing any value triggers a software conversion */ 596 outb(255, dev->iobase + PCL812_SOFTTRIG_REG); 597 } 598 599 static unsigned int pcl812_ai_get_sample(struct comedi_device *dev, 600 struct comedi_subdevice *s) 601 { 602 unsigned int val; 603 604 val = inb(dev->iobase + PCL812_AI_MSB_REG) << 8; 605 val |= inb(dev->iobase + PCL812_AI_LSB_REG); 606 607 return val & s->maxdata; 608 } 609 610 static int pcl812_ai_eoc(struct comedi_device *dev, 611 struct comedi_subdevice *s, 612 struct comedi_insn *insn, 613 unsigned long context) 614 { 615 unsigned int status; 616 617 if (s->maxdata > 0x0fff) { 618 status = inb(dev->iobase + PCL812_STATUS_REG); 619 if ((status & PCL812_STATUS_DRDY) == 0) 620 return 0; 621 } else { 622 status = inb(dev->iobase + PCL812_AI_MSB_REG); 623 if ((status & PCL812_AI_MSB_DRDY) == 0) 624 return 0; 625 } 626 return -EBUSY; 627 } 628 629 static int pcl812_ai_cmdtest(struct comedi_device *dev, 630 struct comedi_subdevice *s, struct comedi_cmd *cmd) 631 { 632 const struct pcl812_board *board = dev->board_ptr; 633 struct pcl812_private *devpriv = dev->private; 634 int err = 0; 635 unsigned int flags; 636 637 /* Step 1 : check if triggers are trivially valid */ 638 639 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW); 640 err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW); 641 642 if (devpriv->use_ext_trg) 643 flags = TRIG_EXT; 644 else 645 flags = TRIG_TIMER; 646 err |= comedi_check_trigger_src(&cmd->convert_src, flags); 647 648 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); 649 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); 650 651 if (err) 652 return 1; 653 654 /* Step 2a : make sure trigger sources are unique */ 655 656 err |= comedi_check_trigger_is_unique(cmd->stop_src); 657 658 /* Step 2b : and mutually compatible */ 659 660 if (err) 661 return 2; 662 663 /* Step 3: check if arguments are trivially valid */ 664 665 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); 666 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0); 667 668 if (cmd->convert_src == TRIG_TIMER) { 669 err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 670 board->ai_ns_min); 671 } else { /* TRIG_EXT */ 672 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0); 673 } 674 675 err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); 676 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, 677 cmd->chanlist_len); 678 679 if (cmd->stop_src == TRIG_COUNT) 680 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1); 681 else /* TRIG_NONE */ 682 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); 683 684 if (err) 685 return 3; 686 687 /* step 4: fix up any arguments */ 688 689 if (cmd->convert_src == TRIG_TIMER) { 690 unsigned int arg = cmd->convert_arg; 691 692 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags); 693 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg); 694 } 695 696 if (err) 697 return 4; 698 699 return 0; 700 } 701 702 static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 703 { 704 struct pcl812_private *devpriv = dev->private; 705 struct comedi_isadma *dma = devpriv->dma; 706 struct comedi_cmd *cmd = &s->async->cmd; 707 unsigned int ctrl = 0; 708 unsigned int i; 709 710 pcl812_ai_set_chan_range(dev, cmd->chanlist[0], 1); 711 712 if (dma) { /* check if we can use DMA transfer */ 713 devpriv->ai_dma = 1; 714 for (i = 1; i < cmd->chanlist_len; i++) 715 if (cmd->chanlist[0] != cmd->chanlist[i]) { 716 /* we cann't use DMA :-( */ 717 devpriv->ai_dma = 0; 718 break; 719 } 720 } else { 721 devpriv->ai_dma = 0; 722 } 723 724 devpriv->ai_poll_ptr = 0; 725 726 /* don't we want wake up every scan? */ 727 if (cmd->flags & CMDF_WAKE_EOS) { 728 devpriv->ai_eos = 1; 729 730 /* DMA is useless for this situation */ 731 if (cmd->chanlist_len == 1) 732 devpriv->ai_dma = 0; 733 } 734 735 if (devpriv->ai_dma) { 736 /* setup and enable dma for the first buffer */ 737 dma->cur_dma = 0; 738 pcl812_ai_setup_dma(dev, s, 0); 739 } 740 741 switch (cmd->convert_src) { 742 case TRIG_TIMER: 743 comedi_8254_update_divisors(dev->pacer); 744 comedi_8254_pacer_enable(dev->pacer, 1, 2, true); 745 break; 746 } 747 748 if (devpriv->ai_dma) 749 ctrl |= PCL812_CTRL_PACER_DMA_TRIG; 750 else 751 ctrl |= PCL812_CTRL_PACER_EOC_TRIG; 752 outb(devpriv->mode_reg_int | ctrl, dev->iobase + PCL812_CTRL_REG); 753 754 return 0; 755 } 756 757 static bool pcl812_ai_next_chan(struct comedi_device *dev, 758 struct comedi_subdevice *s) 759 { 760 struct comedi_cmd *cmd = &s->async->cmd; 761 762 if (cmd->stop_src == TRIG_COUNT && 763 s->async->scans_done >= cmd->stop_arg) { 764 s->async->events |= COMEDI_CB_EOA; 765 return false; 766 } 767 768 return true; 769 } 770 771 static void pcl812_handle_eoc(struct comedi_device *dev, 772 struct comedi_subdevice *s) 773 { 774 struct comedi_cmd *cmd = &s->async->cmd; 775 unsigned int chan = s->async->cur_chan; 776 unsigned int next_chan; 777 unsigned short val; 778 779 if (pcl812_ai_eoc(dev, s, NULL, 0)) { 780 dev_dbg(dev->class_dev, "A/D cmd IRQ without DRDY!\n"); 781 s->async->events |= COMEDI_CB_ERROR; 782 return; 783 } 784 785 val = pcl812_ai_get_sample(dev, s); 786 comedi_buf_write_samples(s, &val, 1); 787 788 /* Set up next channel. Added by abbotti 2010-01-20, but untested. */ 789 next_chan = s->async->cur_chan; 790 if (cmd->chanlist[chan] != cmd->chanlist[next_chan]) 791 pcl812_ai_set_chan_range(dev, cmd->chanlist[next_chan], 0); 792 793 pcl812_ai_next_chan(dev, s); 794 } 795 796 static void transfer_from_dma_buf(struct comedi_device *dev, 797 struct comedi_subdevice *s, 798 unsigned short *ptr, 799 unsigned int bufptr, unsigned int len) 800 { 801 unsigned int i; 802 unsigned short val; 803 804 for (i = len; i; i--) { 805 val = ptr[bufptr++]; 806 comedi_buf_write_samples(s, &val, 1); 807 808 if (!pcl812_ai_next_chan(dev, s)) 809 break; 810 } 811 } 812 813 static void pcl812_handle_dma(struct comedi_device *dev, 814 struct comedi_subdevice *s) 815 { 816 struct pcl812_private *devpriv = dev->private; 817 struct comedi_isadma *dma = devpriv->dma; 818 struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; 819 unsigned int nsamples; 820 int bufptr; 821 822 nsamples = comedi_bytes_to_samples(s, desc->size) - 823 devpriv->ai_poll_ptr; 824 bufptr = devpriv->ai_poll_ptr; 825 devpriv->ai_poll_ptr = 0; 826 827 /* restart dma with the next buffer */ 828 dma->cur_dma = 1 - dma->cur_dma; 829 pcl812_ai_setup_dma(dev, s, nsamples); 830 831 transfer_from_dma_buf(dev, s, desc->virt_addr, bufptr, nsamples); 832 } 833 834 static irqreturn_t pcl812_interrupt(int irq, void *d) 835 { 836 struct comedi_device *dev = d; 837 struct comedi_subdevice *s = dev->read_subdev; 838 struct pcl812_private *devpriv = dev->private; 839 840 if (!dev->attached) { 841 pcl812_ai_clear_eoc(dev); 842 return IRQ_HANDLED; 843 } 844 845 if (devpriv->ai_dma) 846 pcl812_handle_dma(dev, s); 847 else 848 pcl812_handle_eoc(dev, s); 849 850 pcl812_ai_clear_eoc(dev); 851 852 comedi_handle_events(dev, s); 853 return IRQ_HANDLED; 854 } 855 856 static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) 857 { 858 struct pcl812_private *devpriv = dev->private; 859 struct comedi_isadma *dma = devpriv->dma; 860 struct comedi_isadma_desc *desc; 861 unsigned long flags; 862 unsigned int poll; 863 int ret; 864 865 /* poll is valid only for DMA transfer */ 866 if (!devpriv->ai_dma) 867 return 0; 868 869 spin_lock_irqsave(&dev->spinlock, flags); 870 871 poll = comedi_isadma_poll(dma); 872 poll = comedi_bytes_to_samples(s, poll); 873 if (poll > devpriv->ai_poll_ptr) { 874 desc = &dma->desc[dma->cur_dma]; 875 transfer_from_dma_buf(dev, s, desc->virt_addr, 876 devpriv->ai_poll_ptr, 877 poll - devpriv->ai_poll_ptr); 878 /* new buffer position */ 879 devpriv->ai_poll_ptr = poll; 880 881 ret = comedi_buf_n_bytes_ready(s); 882 } else { 883 /* no new samples */ 884 ret = 0; 885 } 886 887 spin_unlock_irqrestore(&dev->spinlock, flags); 888 889 return ret; 890 } 891 892 static int pcl812_ai_cancel(struct comedi_device *dev, 893 struct comedi_subdevice *s) 894 { 895 struct pcl812_private *devpriv = dev->private; 896 897 if (devpriv->ai_dma) 898 comedi_isadma_disable(devpriv->dma->chan); 899 900 outb(devpriv->mode_reg_int | PCL812_CTRL_DISABLE_TRIG, 901 dev->iobase + PCL812_CTRL_REG); 902 comedi_8254_pacer_enable(dev->pacer, 1, 2, false); 903 pcl812_ai_clear_eoc(dev); 904 return 0; 905 } 906 907 static int pcl812_ai_insn_read(struct comedi_device *dev, 908 struct comedi_subdevice *s, 909 struct comedi_insn *insn, 910 unsigned int *data) 911 { 912 struct pcl812_private *devpriv = dev->private; 913 int ret = 0; 914 int i; 915 916 outb(devpriv->mode_reg_int | PCL812_CTRL_SOFT_TRIG, 917 dev->iobase + PCL812_CTRL_REG); 918 919 pcl812_ai_set_chan_range(dev, insn->chanspec, 1); 920 921 for (i = 0; i < insn->n; i++) { 922 pcl812_ai_clear_eoc(dev); 923 pcl812_ai_soft_trig(dev); 924 925 ret = comedi_timeout(dev, s, insn, pcl812_ai_eoc, 0); 926 if (ret) 927 break; 928 929 data[i] = pcl812_ai_get_sample(dev, s); 930 } 931 outb(devpriv->mode_reg_int | PCL812_CTRL_DISABLE_TRIG, 932 dev->iobase + PCL812_CTRL_REG); 933 pcl812_ai_clear_eoc(dev); 934 935 return ret ? ret : insn->n; 936 } 937 938 static int pcl812_ao_insn_write(struct comedi_device *dev, 939 struct comedi_subdevice *s, 940 struct comedi_insn *insn, 941 unsigned int *data) 942 { 943 unsigned int chan = CR_CHAN(insn->chanspec); 944 unsigned int val = s->readback[chan]; 945 int i; 946 947 for (i = 0; i < insn->n; i++) { 948 val = data[i]; 949 outb(val & 0xff, dev->iobase + PCL812_AO_LSB_REG(chan)); 950 outb((val >> 8) & 0x0f, dev->iobase + PCL812_AO_MSB_REG(chan)); 951 } 952 s->readback[chan] = val; 953 954 return insn->n; 955 } 956 957 static int pcl812_di_insn_bits(struct comedi_device *dev, 958 struct comedi_subdevice *s, 959 struct comedi_insn *insn, 960 unsigned int *data) 961 { 962 data[1] = inb(dev->iobase + PCL812_DI_LSB_REG) | 963 (inb(dev->iobase + PCL812_DI_MSB_REG) << 8); 964 965 return insn->n; 966 } 967 968 static int pcl812_do_insn_bits(struct comedi_device *dev, 969 struct comedi_subdevice *s, 970 struct comedi_insn *insn, 971 unsigned int *data) 972 { 973 if (comedi_dio_update_state(s, data)) { 974 outb(s->state & 0xff, dev->iobase + PCL812_DO_LSB_REG); 975 outb((s->state >> 8), dev->iobase + PCL812_DO_MSB_REG); 976 } 977 978 data[1] = s->state; 979 980 return insn->n; 981 } 982 983 static void pcl812_reset(struct comedi_device *dev) 984 { 985 const struct pcl812_board *board = dev->board_ptr; 986 struct pcl812_private *devpriv = dev->private; 987 unsigned int chan; 988 989 /* disable analog input trigger */ 990 outb(devpriv->mode_reg_int | PCL812_CTRL_DISABLE_TRIG, 991 dev->iobase + PCL812_CTRL_REG); 992 pcl812_ai_clear_eoc(dev); 993 994 /* 995 * Invalidate last_ai_chanspec then set analog input to 996 * known channel/range. 997 */ 998 devpriv->last_ai_chanspec = CR_PACK(16, 0, 0); 999 pcl812_ai_set_chan_range(dev, CR_PACK(0, 0, 0), 0); 1000 1001 /* set analog output channels to 0V */ 1002 for (chan = 0; chan < board->n_aochan; chan++) { 1003 outb(0, dev->iobase + PCL812_AO_LSB_REG(chan)); 1004 outb(0, dev->iobase + PCL812_AO_MSB_REG(chan)); 1005 } 1006 1007 /* set all digital outputs low */ 1008 if (board->has_dio) { 1009 outb(0, dev->iobase + PCL812_DO_MSB_REG); 1010 outb(0, dev->iobase + PCL812_DO_LSB_REG); 1011 } 1012 } 1013 1014 static void pcl812_set_ai_range_table(struct comedi_device *dev, 1015 struct comedi_subdevice *s, 1016 struct comedi_devconfig *it) 1017 { 1018 const struct pcl812_board *board = dev->board_ptr; 1019 struct pcl812_private *devpriv = dev->private; 1020 1021 switch (board->board_type) { 1022 case BOARD_PCL812PG: 1023 if (it->options[4] == 1) 1024 s->range_table = &range_pcl812pg2_ai; 1025 else 1026 s->range_table = board->rangelist_ai; 1027 break; 1028 case BOARD_PCL812: 1029 switch (it->options[4]) { 1030 case 0: 1031 s->range_table = &range_bipolar10; 1032 break; 1033 case 1: 1034 s->range_table = &range_bipolar5; 1035 break; 1036 case 2: 1037 s->range_table = &range_bipolar2_5; 1038 break; 1039 case 3: 1040 s->range_table = &range812_bipolar1_25; 1041 break; 1042 case 4: 1043 s->range_table = &range812_bipolar0_625; 1044 break; 1045 case 5: 1046 s->range_table = &range812_bipolar0_3125; 1047 break; 1048 default: 1049 s->range_table = &range_bipolar10; 1050 break; 1051 } 1052 break; 1053 case BOARD_PCL813B: 1054 if (it->options[1] == 1) 1055 s->range_table = &range_pcl813b2_ai; 1056 else 1057 s->range_table = board->rangelist_ai; 1058 break; 1059 case BOARD_ISO813: 1060 switch (it->options[1]) { 1061 case 0: 1062 s->range_table = &range_iso813_1_ai; 1063 break; 1064 case 1: 1065 s->range_table = &range_iso813_1_2_ai; 1066 break; 1067 case 2: 1068 s->range_table = &range_iso813_2_ai; 1069 devpriv->range_correction = 1; 1070 break; 1071 case 3: 1072 s->range_table = &range_iso813_2_2_ai; 1073 devpriv->range_correction = 1; 1074 break; 1075 default: 1076 s->range_table = &range_iso813_1_ai; 1077 break; 1078 } 1079 break; 1080 case BOARD_ACL8113: 1081 switch (it->options[1]) { 1082 case 0: 1083 s->range_table = &range_acl8113_1_ai; 1084 break; 1085 case 1: 1086 s->range_table = &range_acl8113_1_2_ai; 1087 break; 1088 case 2: 1089 s->range_table = &range_acl8113_2_ai; 1090 devpriv->range_correction = 1; 1091 break; 1092 case 3: 1093 s->range_table = &range_acl8113_2_2_ai; 1094 devpriv->range_correction = 1; 1095 break; 1096 default: 1097 s->range_table = &range_acl8113_1_ai; 1098 break; 1099 } 1100 break; 1101 default: 1102 s->range_table = board->rangelist_ai; 1103 break; 1104 } 1105 } 1106 1107 static void pcl812_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) 1108 { 1109 struct pcl812_private *devpriv = dev->private; 1110 1111 /* only DMA channels 3 and 1 are valid */ 1112 if (!(dma_chan == 3 || dma_chan == 1)) 1113 return; 1114 1115 /* DMA uses two 8K buffers */ 1116 devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan, dma_chan, 1117 PAGE_SIZE * 2, COMEDI_ISADMA_READ); 1118 } 1119 1120 static void pcl812_free_dma(struct comedi_device *dev) 1121 { 1122 struct pcl812_private *devpriv = dev->private; 1123 1124 if (devpriv) 1125 comedi_isadma_free(devpriv->dma); 1126 } 1127 1128 static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) 1129 { 1130 const struct pcl812_board *board = dev->board_ptr; 1131 struct pcl812_private *devpriv; 1132 struct comedi_subdevice *s; 1133 int n_subdevices; 1134 int subdev; 1135 int ret; 1136 1137 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); 1138 if (!devpriv) 1139 return -ENOMEM; 1140 1141 ret = comedi_request_region(dev, it->options[0], 0x10); 1142 if (ret) 1143 return ret; 1144 1145 if (board->irq_bits) { 1146 dev->pacer = comedi_8254_init(dev->iobase + PCL812_TIMER_BASE, 1147 I8254_OSC_BASE_2MHZ, 1148 I8254_IO8, 0); 1149 if (!dev->pacer) 1150 return -ENOMEM; 1151 1152 if ((1 << it->options[1]) & board->irq_bits) { 1153 ret = request_irq(it->options[1], pcl812_interrupt, 0, 1154 dev->board_name, dev); 1155 if (ret == 0) 1156 dev->irq = it->options[1]; 1157 } 1158 } 1159 1160 /* we need an IRQ to do DMA on channel 3 or 1 */ 1161 if (dev->irq && board->has_dma) 1162 pcl812_alloc_dma(dev, it->options[2]); 1163 1164 /* differential analog inputs? */ 1165 switch (board->board_type) { 1166 case BOARD_A821: 1167 if (it->options[2] == 1) 1168 devpriv->use_diff = 1; 1169 break; 1170 case BOARD_ACL8112: 1171 case BOARD_ACL8216: 1172 if (it->options[4] == 1) 1173 devpriv->use_diff = 1; 1174 break; 1175 default: 1176 break; 1177 } 1178 1179 n_subdevices = 1; /* all boardtypes have analog inputs */ 1180 if (board->n_aochan > 0) 1181 n_subdevices++; 1182 if (board->has_dio) 1183 n_subdevices += 2; 1184 1185 ret = comedi_alloc_subdevices(dev, n_subdevices); 1186 if (ret) 1187 return ret; 1188 1189 subdev = 0; 1190 1191 /* Analog Input subdevice */ 1192 s = &dev->subdevices[subdev]; 1193 s->type = COMEDI_SUBD_AI; 1194 s->subdev_flags = SDF_READABLE; 1195 if (devpriv->use_diff) { 1196 s->subdev_flags |= SDF_DIFF; 1197 s->n_chan = board->n_aichan / 2; 1198 } else { 1199 s->subdev_flags |= SDF_GROUND; 1200 s->n_chan = board->n_aichan; 1201 } 1202 s->maxdata = board->has_16bit_ai ? 0xffff : 0x0fff; 1203 1204 pcl812_set_ai_range_table(dev, s, it); 1205 1206 s->insn_read = pcl812_ai_insn_read; 1207 1208 if (dev->irq) { 1209 dev->read_subdev = s; 1210 s->subdev_flags |= SDF_CMD_READ; 1211 s->len_chanlist = MAX_CHANLIST_LEN; 1212 s->do_cmdtest = pcl812_ai_cmdtest; 1213 s->do_cmd = pcl812_ai_cmd; 1214 s->poll = pcl812_ai_poll; 1215 s->cancel = pcl812_ai_cancel; 1216 } 1217 1218 devpriv->use_mpc508 = board->has_mpc508_mux; 1219 1220 subdev++; 1221 1222 /* analog output */ 1223 if (board->n_aochan > 0) { 1224 s = &dev->subdevices[subdev]; 1225 s->type = COMEDI_SUBD_AO; 1226 s->subdev_flags = SDF_WRITABLE | SDF_GROUND; 1227 s->n_chan = board->n_aochan; 1228 s->maxdata = 0xfff; 1229 switch (board->board_type) { 1230 case BOARD_A821: 1231 if (it->options[3] == 1) 1232 s->range_table = &range_unipolar10; 1233 else 1234 s->range_table = &range_unipolar5; 1235 break; 1236 case BOARD_PCL812: 1237 case BOARD_ACL8112: 1238 case BOARD_PCL812PG: 1239 case BOARD_ACL8216: 1240 switch (it->options[5]) { 1241 case 1: 1242 s->range_table = &range_unipolar10; 1243 break; 1244 case 2: 1245 s->range_table = &range_unknown; 1246 break; 1247 default: 1248 s->range_table = &range_unipolar5; 1249 break; 1250 } 1251 break; 1252 default: 1253 s->range_table = &range_unipolar5; 1254 break; 1255 } 1256 s->insn_write = pcl812_ao_insn_write; 1257 1258 ret = comedi_alloc_subdev_readback(s); 1259 if (ret) 1260 return ret; 1261 1262 subdev++; 1263 } 1264 1265 if (board->has_dio) { 1266 /* Digital Input subdevice */ 1267 s = &dev->subdevices[subdev]; 1268 s->type = COMEDI_SUBD_DI; 1269 s->subdev_flags = SDF_READABLE; 1270 s->n_chan = 16; 1271 s->maxdata = 1; 1272 s->range_table = &range_digital; 1273 s->insn_bits = pcl812_di_insn_bits; 1274 subdev++; 1275 1276 /* Digital Output subdevice */ 1277 s = &dev->subdevices[subdev]; 1278 s->type = COMEDI_SUBD_DO; 1279 s->subdev_flags = SDF_WRITABLE; 1280 s->n_chan = 16; 1281 s->maxdata = 1; 1282 s->range_table = &range_digital; 1283 s->insn_bits = pcl812_do_insn_bits; 1284 subdev++; 1285 } 1286 1287 switch (board->board_type) { 1288 case BOARD_ACL8216: 1289 case BOARD_PCL812PG: 1290 case BOARD_PCL812: 1291 case BOARD_ACL8112: 1292 devpriv->max_812_ai_mode0_rangewait = 1; 1293 if (it->options[3] > 0) 1294 /* we use external trigger */ 1295 devpriv->use_ext_trg = 1; 1296 break; 1297 case BOARD_A821: 1298 devpriv->max_812_ai_mode0_rangewait = 1; 1299 devpriv->mode_reg_int = (dev->irq << 4) & 0xf0; 1300 break; 1301 case BOARD_PCL813B: 1302 case BOARD_PCL813: 1303 case BOARD_ISO813: 1304 case BOARD_ACL8113: 1305 /* maybe there must by greatest timeout */ 1306 devpriv->max_812_ai_mode0_rangewait = 5; 1307 break; 1308 } 1309 1310 pcl812_reset(dev); 1311 1312 return 0; 1313 } 1314 1315 static void pcl812_detach(struct comedi_device *dev) 1316 { 1317 pcl812_free_dma(dev); 1318 comedi_legacy_detach(dev); 1319 } 1320 1321 static struct comedi_driver pcl812_driver = { 1322 .driver_name = "pcl812", 1323 .module = THIS_MODULE, 1324 .attach = pcl812_attach, 1325 .detach = pcl812_detach, 1326 .board_name = &boardtypes[0].name, 1327 .num_names = ARRAY_SIZE(boardtypes), 1328 .offset = sizeof(struct pcl812_board), 1329 }; 1330 module_comedi_driver(pcl812_driver); 1331 1332 MODULE_AUTHOR("Comedi https://www.comedi.org"); 1333 MODULE_DESCRIPTION("Comedi low-level driver"); 1334 MODULE_LICENSE("GPL"); 1335