File Index
Files and directories
Sign in
FILE

addi_apci_3120.c

File preview with syntax highlighting.

linux-6.19.14/drivers/comedi/drivers/addi_apci_3120.c C
   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");
~/ Read-only file preview.