Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Counter driver for the ACCES 104-QUAD-8
   4 * Copyright (C) 2016 William Breathitt Gray
   5 *
   6 * This driver supports the ACCES 104-QUAD-8 and ACCES 104-QUAD-4.
   7 */
   8#include <linux/bitops.h>
   9#include <linux/counter.h>
  10#include <linux/device.h>
  11#include <linux/errno.h>
  12#include <linux/io.h>
  13#include <linux/ioport.h>
  14#include <linux/interrupt.h>
  15#include <linux/isa.h>
  16#include <linux/kernel.h>
  17#include <linux/list.h>
  18#include <linux/module.h>
  19#include <linux/moduleparam.h>
  20#include <linux/types.h>
  21#include <linux/spinlock.h>
  22
  23#define QUAD8_EXTENT 32
  24
  25static unsigned int base[max_num_isa_dev(QUAD8_EXTENT)];
  26static unsigned int num_quad8;
  27module_param_hw_array(base, uint, ioport, &num_quad8, 0);
  28MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");
  29
  30static unsigned int irq[max_num_isa_dev(QUAD8_EXTENT)];
  31static unsigned int num_irq;
  32module_param_hw_array(irq, uint, irq, &num_irq, 0);
  33MODULE_PARM_DESC(irq, "ACCES 104-QUAD-8 interrupt line numbers");
  34
  35#define QUAD8_NUM_COUNTERS 8
  36
  37/**
  38 * struct channel_reg - channel register structure
  39 * @data:	Count data
  40 * @control:	Channel flags and control
  41 */
  42struct channel_reg {
  43	u8 data;
  44	u8 control;
  45};
  46
  47/**
  48 * struct quad8_reg - device register structure
  49 * @channel:		quadrature counter data and control
  50 * @interrupt_status:	channel interrupt status
  51 * @channel_oper:	enable/reset counters and interrupt functions
  52 * @index_interrupt:	enable channel interrupts
  53 * @reserved:		reserved for Factory Use
  54 * @index_input_levels:	index signal logical input level
  55 * @cable_status:	differential encoder cable status
  56 */
  57struct quad8_reg {
  58	struct channel_reg channel[QUAD8_NUM_COUNTERS];
  59	u8 interrupt_status;
  60	u8 channel_oper;
  61	u8 index_interrupt;
  62	u8 reserved[3];
  63	u8 index_input_levels;
  64	u8 cable_status;
  65};
  66
  67/**
  68 * struct quad8 - device private data structure
  69 * @lock:		lock to prevent clobbering device states during R/W ops
  70 * @counter:		instance of the counter_device
  71 * @fck_prescaler:	array of filter clock prescaler configurations
  72 * @preset:		array of preset values
  73 * @count_mode:		array of count mode configurations
  74 * @quadrature_mode:	array of quadrature mode configurations
  75 * @quadrature_scale:	array of quadrature mode scale configurations
  76 * @ab_enable:		array of A and B inputs enable configurations
  77 * @preset_enable:	array of set_to_preset_on_index attribute configurations
  78 * @irq_trigger:	array of current IRQ trigger function configurations
  79 * @synchronous_mode:	array of index function synchronous mode configurations
  80 * @index_polarity:	array of index function polarity configurations
  81 * @cable_fault_enable:	differential encoder cable status enable configurations
  82 * @reg:		I/O address offset for the device registers
  83 */
  84struct quad8 {
  85	spinlock_t lock;
  86	unsigned int fck_prescaler[QUAD8_NUM_COUNTERS];
  87	unsigned int preset[QUAD8_NUM_COUNTERS];
  88	unsigned int count_mode[QUAD8_NUM_COUNTERS];
  89	unsigned int quadrature_mode[QUAD8_NUM_COUNTERS];
  90	unsigned int quadrature_scale[QUAD8_NUM_COUNTERS];
  91	unsigned int ab_enable[QUAD8_NUM_COUNTERS];
  92	unsigned int preset_enable[QUAD8_NUM_COUNTERS];
  93	unsigned int irq_trigger[QUAD8_NUM_COUNTERS];
  94	unsigned int synchronous_mode[QUAD8_NUM_COUNTERS];
  95	unsigned int index_polarity[QUAD8_NUM_COUNTERS];
  96	unsigned int cable_fault_enable;
  97	struct quad8_reg __iomem *reg;
  98};
  99
 100/* Borrow Toggle flip-flop */
 101#define QUAD8_FLAG_BT BIT(0)
 102/* Carry Toggle flip-flop */
 103#define QUAD8_FLAG_CT BIT(1)
 104/* Error flag */
 105#define QUAD8_FLAG_E BIT(4)
 106/* Up/Down flag */
 107#define QUAD8_FLAG_UD BIT(5)
 108/* Reset and Load Signal Decoders */
 109#define QUAD8_CTR_RLD 0x00
 110/* Counter Mode Register */
 111#define QUAD8_CTR_CMR 0x20
 112/* Input / Output Control Register */
 113#define QUAD8_CTR_IOR 0x40
 114/* Index Control Register */
 115#define QUAD8_CTR_IDR 0x60
 116/* Reset Byte Pointer (three byte data pointer) */
 117#define QUAD8_RLD_RESET_BP 0x01
 118/* Reset Counter */
 119#define QUAD8_RLD_RESET_CNTR 0x02
 120/* Reset Borrow Toggle, Carry Toggle, Compare Toggle, and Sign flags */
 121#define QUAD8_RLD_RESET_FLAGS 0x04
 122/* Reset Error flag */
 123#define QUAD8_RLD_RESET_E 0x06
 124/* Preset Register to Counter */
 125#define QUAD8_RLD_PRESET_CNTR 0x08
 126/* Transfer Counter to Output Latch */
 127#define QUAD8_RLD_CNTR_OUT 0x10
 128/* Transfer Preset Register LSB to FCK Prescaler */
 129#define QUAD8_RLD_PRESET_PSC 0x18
 130#define QUAD8_CHAN_OP_RESET_COUNTERS 0x01
 131#define QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC 0x04
 132#define QUAD8_CMR_QUADRATURE_X1 0x08
 133#define QUAD8_CMR_QUADRATURE_X2 0x10
 134#define QUAD8_CMR_QUADRATURE_X4 0x18
 135
 136static int quad8_signal_read(struct counter_device *counter,
 137			     struct counter_signal *signal,
 138			     enum counter_signal_level *level)
 139{
 140	const struct quad8 *const priv = counter_priv(counter);
 141	unsigned int state;
 142
 143	/* Only Index signal levels can be read */
 144	if (signal->id < 16)
 145		return -EINVAL;
 146
 147	state = ioread8(&priv->reg->index_input_levels) & BIT(signal->id - 16);
 148
 149	*level = (state) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
 150
 151	return 0;
 152}
 153
 154static int quad8_count_read(struct counter_device *counter,
 155			    struct counter_count *count, u64 *val)
 156{
 157	struct quad8 *const priv = counter_priv(counter);
 158	struct channel_reg __iomem *const chan = priv->reg->channel + count->id;
 159	unsigned int flags;
 160	unsigned int borrow;
 161	unsigned int carry;
 162	unsigned long irqflags;
 163	int i;
 164
 165	flags = ioread8(&chan->control);
 166	borrow = flags & QUAD8_FLAG_BT;
 167	carry = !!(flags & QUAD8_FLAG_CT);
 168
 169	/* Borrow XOR Carry effectively doubles count range */
 170	*val = (unsigned long)(borrow ^ carry) << 24;
 171
 172	spin_lock_irqsave(&priv->lock, irqflags);
 173
 174	/* Reset Byte Pointer; transfer Counter to Output Latch */
 175	iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
 176		 &chan->control);
 177
 178	for (i = 0; i < 3; i++)
 179		*val |= (unsigned long)ioread8(&chan->data) << (8 * i);
 180
 181	spin_unlock_irqrestore(&priv->lock, irqflags);
 182
 183	return 0;
 184}
 185
 186static int quad8_count_write(struct counter_device *counter,
 187			     struct counter_count *count, u64 val)
 188{
 189	struct quad8 *const priv = counter_priv(counter);
 190	struct channel_reg __iomem *const chan = priv->reg->channel + count->id;
 191	unsigned long irqflags;
 192	int i;
 193
 194	/* Only 24-bit values are supported */
 195	if (val > 0xFFFFFF)
 196		return -ERANGE;
 197
 198	spin_lock_irqsave(&priv->lock, irqflags);
 199
 200	/* Reset Byte Pointer */
 201	iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
 202
 203	/* Counter can only be set via Preset Register */
 204	for (i = 0; i < 3; i++)
 205		iowrite8(val >> (8 * i), &chan->data);
 206
 207	/* Transfer Preset Register to Counter */
 208	iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, &chan->control);
 209
 210	/* Reset Byte Pointer */
 211	iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
 212
 213	/* Set Preset Register back to original value */
 214	val = priv->preset[count->id];
 215	for (i = 0; i < 3; i++)
 216		iowrite8(val >> (8 * i), &chan->data);
 217
 218	/* Reset Borrow, Carry, Compare, and Sign flags */
 219	iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control);
 220	/* Reset Error flag */
 221	iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control);
 222
 223	spin_unlock_irqrestore(&priv->lock, irqflags);
 224
 225	return 0;
 226}
 227
 228static const enum counter_function quad8_count_functions_list[] = {
 229	COUNTER_FUNCTION_PULSE_DIRECTION,
 230	COUNTER_FUNCTION_QUADRATURE_X1_A,
 231	COUNTER_FUNCTION_QUADRATURE_X2_A,
 232	COUNTER_FUNCTION_QUADRATURE_X4,
 233};
 234
 235static int quad8_function_get(const struct quad8 *const priv, const size_t id,
 236			      enum counter_function *const function)
 237{
 238	if (!priv->quadrature_mode[id]) {
 239		*function = COUNTER_FUNCTION_PULSE_DIRECTION;
 240		return 0;
 241	}
 242
 243	switch (priv->quadrature_scale[id]) {
 244	case 0:
 245		*function = COUNTER_FUNCTION_QUADRATURE_X1_A;
 246		return 0;
 247	case 1:
 248		*function = COUNTER_FUNCTION_QUADRATURE_X2_A;
 249		return 0;
 250	case 2:
 251		*function = COUNTER_FUNCTION_QUADRATURE_X4;
 252		return 0;
 253	default:
 254		/* should never reach this path */
 255		return -EINVAL;
 256	}
 257}
 258
 259static int quad8_function_read(struct counter_device *counter,
 260			       struct counter_count *count,
 261			       enum counter_function *function)
 262{
 263	struct quad8 *const priv = counter_priv(counter);
 264	unsigned long irqflags;
 265	int retval;
 266
 267	spin_lock_irqsave(&priv->lock, irqflags);
 268
 269	retval = quad8_function_get(priv, count->id, function);
 270
 271	spin_unlock_irqrestore(&priv->lock, irqflags);
 272
 273	return retval;
 274}
 275
 276static int quad8_function_write(struct counter_device *counter,
 277				struct counter_count *count,
 278				enum counter_function function)
 279{
 280	struct quad8 *const priv = counter_priv(counter);
 281	const int id = count->id;
 282	unsigned int *const quadrature_mode = priv->quadrature_mode + id;
 283	unsigned int *const scale = priv->quadrature_scale + id;
 284	unsigned int *const synchronous_mode = priv->synchronous_mode + id;
 285	u8 __iomem *const control = &priv->reg->channel[id].control;
 286	unsigned long irqflags;
 287	unsigned int mode_cfg;
 288	unsigned int idr_cfg;
 289
 290	spin_lock_irqsave(&priv->lock, irqflags);
 291
 292	mode_cfg = priv->count_mode[id] << 1;
 293	idr_cfg = priv->index_polarity[id] << 1;
 294
 295	if (function == COUNTER_FUNCTION_PULSE_DIRECTION) {
 296		*quadrature_mode = 0;
 297
 298		/* Quadrature scaling only available in quadrature mode */
 299		*scale = 0;
 300
 301		/* Synchronous function not supported in non-quadrature mode */
 302		if (*synchronous_mode) {
 303			*synchronous_mode = 0;
 304			/* Disable synchronous function mode */
 305			iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
 306		}
 307	} else {
 308		*quadrature_mode = 1;
 309
 310		switch (function) {
 311		case COUNTER_FUNCTION_QUADRATURE_X1_A:
 312			*scale = 0;
 313			mode_cfg |= QUAD8_CMR_QUADRATURE_X1;
 314			break;
 315		case COUNTER_FUNCTION_QUADRATURE_X2_A:
 316			*scale = 1;
 317			mode_cfg |= QUAD8_CMR_QUADRATURE_X2;
 318			break;
 319		case COUNTER_FUNCTION_QUADRATURE_X4:
 320			*scale = 2;
 321			mode_cfg |= QUAD8_CMR_QUADRATURE_X4;
 322			break;
 323		default:
 324			/* should never reach this path */
 325			spin_unlock_irqrestore(&priv->lock, irqflags);
 326			return -EINVAL;
 327		}
 328	}
 329
 330	/* Load mode configuration to Counter Mode Register */
 331	iowrite8(QUAD8_CTR_CMR | mode_cfg, control);
 332
 333	spin_unlock_irqrestore(&priv->lock, irqflags);
 334
 335	return 0;
 336}
 337
 338static int quad8_direction_read(struct counter_device *counter,
 339				struct counter_count *count,
 340				enum counter_count_direction *direction)
 341{
 342	const struct quad8 *const priv = counter_priv(counter);
 343	unsigned int ud_flag;
 344	u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control;
 345
 346	/* U/D flag: nonzero = up, zero = down */
 347	ud_flag = ioread8(flag_addr) & QUAD8_FLAG_UD;
 348
 349	*direction = (ud_flag) ? COUNTER_COUNT_DIRECTION_FORWARD :
 350		COUNTER_COUNT_DIRECTION_BACKWARD;
 351
 352	return 0;
 353}
 354
 355static const enum counter_synapse_action quad8_index_actions_list[] = {
 356	COUNTER_SYNAPSE_ACTION_NONE,
 357	COUNTER_SYNAPSE_ACTION_RISING_EDGE,
 358};
 359
 360static const enum counter_synapse_action quad8_synapse_actions_list[] = {
 361	COUNTER_SYNAPSE_ACTION_NONE,
 362	COUNTER_SYNAPSE_ACTION_RISING_EDGE,
 363	COUNTER_SYNAPSE_ACTION_FALLING_EDGE,
 364	COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
 365};
 366
 367static int quad8_action_read(struct counter_device *counter,
 368			     struct counter_count *count,
 369			     struct counter_synapse *synapse,
 370			     enum counter_synapse_action *action)
 371{
 372	struct quad8 *const priv = counter_priv(counter);
 373	unsigned long irqflags;
 374	int err;
 375	enum counter_function function;
 376	const size_t signal_a_id = count->synapses[0].signal->id;
 377	enum counter_count_direction direction;
 378
 379	/* Handle Index signals */
 380	if (synapse->signal->id >= 16) {
 381		if (priv->preset_enable[count->id])
 382			*action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
 383		else
 384			*action = COUNTER_SYNAPSE_ACTION_NONE;
 385
 386		return 0;
 387	}
 388
 389	spin_lock_irqsave(&priv->lock, irqflags);
 390
 391	/* Get Count function and direction atomically */
 392	err = quad8_function_get(priv, count->id, &function);
 393	if (err) {
 394		spin_unlock_irqrestore(&priv->lock, irqflags);
 395		return err;
 396	}
 397	err = quad8_direction_read(counter, count, &direction);
 398	if (err) {
 399		spin_unlock_irqrestore(&priv->lock, irqflags);
 400		return err;
 401	}
 402
 403	spin_unlock_irqrestore(&priv->lock, irqflags);
 404
 405	/* Default action mode */
 406	*action = COUNTER_SYNAPSE_ACTION_NONE;
 407
 408	/* Determine action mode based on current count function mode */
 409	switch (function) {
 410	case COUNTER_FUNCTION_PULSE_DIRECTION:
 411		if (synapse->signal->id == signal_a_id)
 412			*action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
 413		return 0;
 414	case COUNTER_FUNCTION_QUADRATURE_X1_A:
 415		if (synapse->signal->id == signal_a_id) {
 416			if (direction == COUNTER_COUNT_DIRECTION_FORWARD)
 417				*action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
 418			else
 419				*action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE;
 420		}
 421		return 0;
 422	case COUNTER_FUNCTION_QUADRATURE_X2_A:
 423		if (synapse->signal->id == signal_a_id)
 424			*action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
 425		return 0;
 426	case COUNTER_FUNCTION_QUADRATURE_X4:
 427		*action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
 428		return 0;
 429	default:
 430		/* should never reach this path */
 431		return -EINVAL;
 432	}
 433}
 434
 435enum {
 436	QUAD8_EVENT_CARRY = 0,
 437	QUAD8_EVENT_COMPARE = 1,
 438	QUAD8_EVENT_CARRY_BORROW = 2,
 439	QUAD8_EVENT_INDEX = 3,
 440};
 441
 442static int quad8_events_configure(struct counter_device *counter)
 443{
 444	struct quad8 *const priv = counter_priv(counter);
 445	unsigned long irq_enabled = 0;
 446	unsigned long irqflags;
 447	struct counter_event_node *event_node;
 448	unsigned int next_irq_trigger;
 449	unsigned long ior_cfg;
 450
 451	spin_lock_irqsave(&priv->lock, irqflags);
 452
 453	list_for_each_entry(event_node, &counter->events_list, l) {
 454		switch (event_node->event) {
 455		case COUNTER_EVENT_OVERFLOW:
 456			next_irq_trigger = QUAD8_EVENT_CARRY;
 457			break;
 458		case COUNTER_EVENT_THRESHOLD:
 459			next_irq_trigger = QUAD8_EVENT_COMPARE;
 460			break;
 461		case COUNTER_EVENT_OVERFLOW_UNDERFLOW:
 462			next_irq_trigger = QUAD8_EVENT_CARRY_BORROW;
 463			break;
 464		case COUNTER_EVENT_INDEX:
 465			next_irq_trigger = QUAD8_EVENT_INDEX;
 466			break;
 467		default:
 468			/* should never reach this path */
 469			spin_unlock_irqrestore(&priv->lock, irqflags);
 470			return -EINVAL;
 471		}
 472
 473		/* Enable IRQ line */
 474		irq_enabled |= BIT(event_node->channel);
 475
 476		/* Skip configuration if it is the same as previously set */
 477		if (priv->irq_trigger[event_node->channel] == next_irq_trigger)
 478			continue;
 479
 480		/* Save new IRQ function configuration */
 481		priv->irq_trigger[event_node->channel] = next_irq_trigger;
 482
 483		/* Load configuration to I/O Control Register */
 484		ior_cfg = priv->ab_enable[event_node->channel] |
 485			  priv->preset_enable[event_node->channel] << 1 |
 486			  priv->irq_trigger[event_node->channel] << 3;
 487		iowrite8(QUAD8_CTR_IOR | ior_cfg,
 488			 &priv->reg->channel[event_node->channel].control);
 489	}
 490
 491	iowrite8(irq_enabled, &priv->reg->index_interrupt);
 492
 493	spin_unlock_irqrestore(&priv->lock, irqflags);
 494
 495	return 0;
 496}
 497
 498static int quad8_watch_validate(struct counter_device *counter,
 499				const struct counter_watch *watch)
 500{
 501	struct counter_event_node *event_node;
 502
 503	if (watch->channel > QUAD8_NUM_COUNTERS - 1)
 504		return -EINVAL;
 505
 506	switch (watch->event) {
 507	case COUNTER_EVENT_OVERFLOW:
 508	case COUNTER_EVENT_THRESHOLD:
 509	case COUNTER_EVENT_OVERFLOW_UNDERFLOW:
 510	case COUNTER_EVENT_INDEX:
 511		list_for_each_entry(event_node, &counter->next_events_list, l)
 512			if (watch->channel == event_node->channel &&
 513				watch->event != event_node->event)
 514				return -EINVAL;
 515		return 0;
 516	default:
 517		return -EINVAL;
 518	}
 519}
 520
 521static const struct counter_ops quad8_ops = {
 522	.signal_read = quad8_signal_read,
 523	.count_read = quad8_count_read,
 524	.count_write = quad8_count_write,
 525	.function_read = quad8_function_read,
 526	.function_write = quad8_function_write,
 527	.action_read = quad8_action_read,
 528	.events_configure = quad8_events_configure,
 529	.watch_validate = quad8_watch_validate,
 530};
 531
 532static const char *const quad8_index_polarity_modes[] = {
 533	"negative",
 534	"positive"
 535};
 536
 537static int quad8_index_polarity_get(struct counter_device *counter,
 538				    struct counter_signal *signal,
 539				    u32 *index_polarity)
 540{
 541	const struct quad8 *const priv = counter_priv(counter);
 542	const size_t channel_id = signal->id - 16;
 543
 544	*index_polarity = priv->index_polarity[channel_id];
 545
 546	return 0;
 547}
 548
 549static int quad8_index_polarity_set(struct counter_device *counter,
 550				    struct counter_signal *signal,
 551				    u32 index_polarity)
 552{
 553	struct quad8 *const priv = counter_priv(counter);
 554	const size_t channel_id = signal->id - 16;
 555	u8 __iomem *const control = &priv->reg->channel[channel_id].control;
 556	unsigned long irqflags;
 557	unsigned int idr_cfg = index_polarity << 1;
 558
 559	spin_lock_irqsave(&priv->lock, irqflags);
 560
 561	idr_cfg |= priv->synchronous_mode[channel_id];
 562
 563	priv->index_polarity[channel_id] = index_polarity;
 564
 565	/* Load Index Control configuration to Index Control Register */
 566	iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
 567
 568	spin_unlock_irqrestore(&priv->lock, irqflags);
 569
 570	return 0;
 571}
 572
 573static int quad8_polarity_read(struct counter_device *counter,
 574			       struct counter_signal *signal,
 575			       enum counter_signal_polarity *polarity)
 576{
 577	int err;
 578	u32 index_polarity;
 579
 580	err = quad8_index_polarity_get(counter, signal, &index_polarity);
 581	if (err)
 582		return err;
 583
 584	*polarity = (index_polarity) ? COUNTER_SIGNAL_POLARITY_POSITIVE :
 585		COUNTER_SIGNAL_POLARITY_NEGATIVE;
 586
 587	return 0;
 588}
 589
 590static int quad8_polarity_write(struct counter_device *counter,
 591				struct counter_signal *signal,
 592				enum counter_signal_polarity polarity)
 593{
 594	const u32 pol = (polarity == COUNTER_SIGNAL_POLARITY_POSITIVE) ? 1 : 0;
 595
 596	return quad8_index_polarity_set(counter, signal, pol);
 597}
 598
 599static const char *const quad8_synchronous_modes[] = {
 600	"non-synchronous",
 601	"synchronous"
 602};
 603
 604static int quad8_synchronous_mode_get(struct counter_device *counter,
 605				      struct counter_signal *signal,
 606				      u32 *synchronous_mode)
 607{
 608	const struct quad8 *const priv = counter_priv(counter);
 609	const size_t channel_id = signal->id - 16;
 610
 611	*synchronous_mode = priv->synchronous_mode[channel_id];
 612
 613	return 0;
 614}
 615
 616static int quad8_synchronous_mode_set(struct counter_device *counter,
 617				      struct counter_signal *signal,
 618				      u32 synchronous_mode)
 619{
 620	struct quad8 *const priv = counter_priv(counter);
 621	const size_t channel_id = signal->id - 16;
 622	u8 __iomem *const control = &priv->reg->channel[channel_id].control;
 623	unsigned long irqflags;
 624	unsigned int idr_cfg = synchronous_mode;
 625
 626	spin_lock_irqsave(&priv->lock, irqflags);
 627
 628	idr_cfg |= priv->index_polarity[channel_id] << 1;
 629
 630	/* Index function must be non-synchronous in non-quadrature mode */
 631	if (synchronous_mode && !priv->quadrature_mode[channel_id]) {
 632		spin_unlock_irqrestore(&priv->lock, irqflags);
 633		return -EINVAL;
 634	}
 635
 636	priv->synchronous_mode[channel_id] = synchronous_mode;
 637
 638	/* Load Index Control configuration to Index Control Register */
 639	iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
 640
 641	spin_unlock_irqrestore(&priv->lock, irqflags);
 642
 643	return 0;
 644}
 645
 646static int quad8_count_floor_read(struct counter_device *counter,
 647				  struct counter_count *count, u64 *floor)
 648{
 649	/* Only a floor of 0 is supported */
 650	*floor = 0;
 651
 652	return 0;
 653}
 654
 655static int quad8_count_mode_read(struct counter_device *counter,
 656				 struct counter_count *count,
 657				 enum counter_count_mode *cnt_mode)
 658{
 659	const struct quad8 *const priv = counter_priv(counter);
 660
 661	/* Map 104-QUAD-8 count mode to Generic Counter count mode */
 662	switch (priv->count_mode[count->id]) {
 663	case 0:
 664		*cnt_mode = COUNTER_COUNT_MODE_NORMAL;
 665		break;
 666	case 1:
 667		*cnt_mode = COUNTER_COUNT_MODE_RANGE_LIMIT;
 668		break;
 669	case 2:
 670		*cnt_mode = COUNTER_COUNT_MODE_NON_RECYCLE;
 671		break;
 672	case 3:
 673		*cnt_mode = COUNTER_COUNT_MODE_MODULO_N;
 674		break;
 675	}
 676
 677	return 0;
 678}
 679
 680static int quad8_count_mode_write(struct counter_device *counter,
 681				  struct counter_count *count,
 682				  enum counter_count_mode cnt_mode)
 683{
 684	struct quad8 *const priv = counter_priv(counter);
 685	unsigned int count_mode;
 686	unsigned int mode_cfg;
 687	u8 __iomem *const control = &priv->reg->channel[count->id].control;
 688	unsigned long irqflags;
 689
 690	/* Map Generic Counter count mode to 104-QUAD-8 count mode */
 691	switch (cnt_mode) {
 692	case COUNTER_COUNT_MODE_NORMAL:
 693		count_mode = 0;
 694		break;
 695	case COUNTER_COUNT_MODE_RANGE_LIMIT:
 696		count_mode = 1;
 697		break;
 698	case COUNTER_COUNT_MODE_NON_RECYCLE:
 699		count_mode = 2;
 700		break;
 701	case COUNTER_COUNT_MODE_MODULO_N:
 702		count_mode = 3;
 703		break;
 704	default:
 705		/* should never reach this path */
 706		return -EINVAL;
 707	}
 708
 709	spin_lock_irqsave(&priv->lock, irqflags);
 710
 711	priv->count_mode[count->id] = count_mode;
 712
 713	/* Set count mode configuration value */
 714	mode_cfg = count_mode << 1;
 715
 716	/* Add quadrature mode configuration */
 717	if (priv->quadrature_mode[count->id])
 718		mode_cfg |= (priv->quadrature_scale[count->id] + 1) << 3;
 719
 720	/* Load mode configuration to Counter Mode Register */
 721	iowrite8(QUAD8_CTR_CMR | mode_cfg, control);
 722
 723	spin_unlock_irqrestore(&priv->lock, irqflags);
 724
 725	return 0;
 726}
 727
 728static int quad8_count_enable_read(struct counter_device *counter,
 729				   struct counter_count *count, u8 *enable)
 730{
 731	const struct quad8 *const priv = counter_priv(counter);
 732
 733	*enable = priv->ab_enable[count->id];
 734
 735	return 0;
 736}
 737
 738static int quad8_count_enable_write(struct counter_device *counter,
 739				    struct counter_count *count, u8 enable)
 740{
 741	struct quad8 *const priv = counter_priv(counter);
 742	u8 __iomem *const control = &priv->reg->channel[count->id].control;
 743	unsigned long irqflags;
 744	unsigned int ior_cfg;
 745
 746	spin_lock_irqsave(&priv->lock, irqflags);
 747
 748	priv->ab_enable[count->id] = enable;
 749
 750	ior_cfg = enable | priv->preset_enable[count->id] << 1 |
 751		  priv->irq_trigger[count->id] << 3;
 752
 753	/* Load I/O control configuration */
 754	iowrite8(QUAD8_CTR_IOR | ior_cfg, control);
 755
 756	spin_unlock_irqrestore(&priv->lock, irqflags);
 757
 758	return 0;
 759}
 760
 761static const char *const quad8_noise_error_states[] = {
 762	"No excessive noise is present at the count inputs",
 763	"Excessive noise is present at the count inputs"
 764};
 765
 766static int quad8_error_noise_get(struct counter_device *counter,
 767				 struct counter_count *count, u32 *noise_error)
 768{
 769	const struct quad8 *const priv = counter_priv(counter);
 770	u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control;
 771
 772	*noise_error = !!(ioread8(flag_addr) & QUAD8_FLAG_E);
 773
 774	return 0;
 775}
 776
 777static int quad8_count_preset_read(struct counter_device *counter,
 778				   struct counter_count *count, u64 *preset)
 779{
 780	const struct quad8 *const priv = counter_priv(counter);
 781
 782	*preset = priv->preset[count->id];
 783
 784	return 0;
 785}
 786
 787static void quad8_preset_register_set(struct quad8 *const priv, const int id,
 788				      const unsigned int preset)
 789{
 790	struct channel_reg __iomem *const chan = priv->reg->channel + id;
 791	int i;
 792
 793	priv->preset[id] = preset;
 794
 795	/* Reset Byte Pointer */
 796	iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
 797
 798	/* Set Preset Register */
 799	for (i = 0; i < 3; i++)
 800		iowrite8(preset >> (8 * i), &chan->data);
 801}
 802
 803static int quad8_count_preset_write(struct counter_device *counter,
 804				    struct counter_count *count, u64 preset)
 805{
 806	struct quad8 *const priv = counter_priv(counter);
 807	unsigned long irqflags;
 808
 809	/* Only 24-bit values are supported */
 810	if (preset > 0xFFFFFF)
 811		return -ERANGE;
 812
 813	spin_lock_irqsave(&priv->lock, irqflags);
 814
 815	quad8_preset_register_set(priv, count->id, preset);
 816
 817	spin_unlock_irqrestore(&priv->lock, irqflags);
 818
 819	return 0;
 820}
 821
 822static int quad8_count_ceiling_read(struct counter_device *counter,
 823				    struct counter_count *count, u64 *ceiling)
 824{
 825	struct quad8 *const priv = counter_priv(counter);
 826	unsigned long irqflags;
 827
 828	spin_lock_irqsave(&priv->lock, irqflags);
 829
 830	/* Range Limit and Modulo-N count modes use preset value as ceiling */
 831	switch (priv->count_mode[count->id]) {
 832	case 1:
 833	case 3:
 834		*ceiling = priv->preset[count->id];
 835		break;
 836	default:
 837		/* By default 0x1FFFFFF (25 bits unsigned) is maximum count */
 838		*ceiling = 0x1FFFFFF;
 839		break;
 840	}
 841
 842	spin_unlock_irqrestore(&priv->lock, irqflags);
 843
 844	return 0;
 845}
 846
 847static int quad8_count_ceiling_write(struct counter_device *counter,
 848				     struct counter_count *count, u64 ceiling)
 849{
 850	struct quad8 *const priv = counter_priv(counter);
 851	unsigned long irqflags;
 852
 853	/* Only 24-bit values are supported */
 854	if (ceiling > 0xFFFFFF)
 855		return -ERANGE;
 856
 857	spin_lock_irqsave(&priv->lock, irqflags);
 858
 859	/* Range Limit and Modulo-N count modes use preset value as ceiling */
 860	switch (priv->count_mode[count->id]) {
 861	case 1:
 862	case 3:
 863		quad8_preset_register_set(priv, count->id, ceiling);
 864		spin_unlock_irqrestore(&priv->lock, irqflags);
 865		return 0;
 866	}
 867
 868	spin_unlock_irqrestore(&priv->lock, irqflags);
 869
 870	return -EINVAL;
 871}
 872
 873static int quad8_count_preset_enable_read(struct counter_device *counter,
 874					  struct counter_count *count,
 875					  u8 *preset_enable)
 876{
 877	const struct quad8 *const priv = counter_priv(counter);
 878
 879	*preset_enable = !priv->preset_enable[count->id];
 880
 881	return 0;
 882}
 883
 884static int quad8_count_preset_enable_write(struct counter_device *counter,
 885					   struct counter_count *count,
 886					   u8 preset_enable)
 887{
 888	struct quad8 *const priv = counter_priv(counter);
 889	u8 __iomem *const control = &priv->reg->channel[count->id].control;
 890	unsigned long irqflags;
 891	unsigned int ior_cfg;
 892
 893	/* Preset enable is active low in Input/Output Control register */
 894	preset_enable = !preset_enable;
 895
 896	spin_lock_irqsave(&priv->lock, irqflags);
 897
 898	priv->preset_enable[count->id] = preset_enable;
 899
 900	ior_cfg = priv->ab_enable[count->id] | preset_enable << 1 |
 901		  priv->irq_trigger[count->id] << 3;
 902
 903	/* Load I/O control configuration to Input / Output Control Register */
 904	iowrite8(QUAD8_CTR_IOR | ior_cfg, control);
 905
 906	spin_unlock_irqrestore(&priv->lock, irqflags);
 907
 908	return 0;
 909}
 910
 911static int quad8_signal_cable_fault_read(struct counter_device *counter,
 912					 struct counter_signal *signal,
 913					 u8 *cable_fault)
 914{
 915	struct quad8 *const priv = counter_priv(counter);
 916	const size_t channel_id = signal->id / 2;
 917	unsigned long irqflags;
 918	bool disabled;
 919	unsigned int status;
 920
 921	spin_lock_irqsave(&priv->lock, irqflags);
 922
 923	disabled = !(priv->cable_fault_enable & BIT(channel_id));
 924
 925	if (disabled) {
 926		spin_unlock_irqrestore(&priv->lock, irqflags);
 927		return -EINVAL;
 928	}
 929
 930	/* Logic 0 = cable fault */
 931	status = ioread8(&priv->reg->cable_status);
 932
 933	spin_unlock_irqrestore(&priv->lock, irqflags);
 934
 935	/* Mask respective channel and invert logic */
 936	*cable_fault = !(status & BIT(channel_id));
 937
 938	return 0;
 939}
 940
 941static int quad8_signal_cable_fault_enable_read(struct counter_device *counter,
 942						struct counter_signal *signal,
 943						u8 *enable)
 944{
 945	const struct quad8 *const priv = counter_priv(counter);
 946	const size_t channel_id = signal->id / 2;
 947
 948	*enable = !!(priv->cable_fault_enable & BIT(channel_id));
 949
 950	return 0;
 951}
 952
 953static int quad8_signal_cable_fault_enable_write(struct counter_device *counter,
 954						 struct counter_signal *signal,
 955						 u8 enable)
 956{
 957	struct quad8 *const priv = counter_priv(counter);
 958	const size_t channel_id = signal->id / 2;
 959	unsigned long irqflags;
 960	unsigned int cable_fault_enable;
 961
 962	spin_lock_irqsave(&priv->lock, irqflags);
 963
 964	if (enable)
 965		priv->cable_fault_enable |= BIT(channel_id);
 966	else
 967		priv->cable_fault_enable &= ~BIT(channel_id);
 968
 969	/* Enable is active low in Differential Encoder Cable Status register */
 970	cable_fault_enable = ~priv->cable_fault_enable;
 971
 972	iowrite8(cable_fault_enable, &priv->reg->cable_status);
 973
 974	spin_unlock_irqrestore(&priv->lock, irqflags);
 975
 976	return 0;
 977}
 978
 979static int quad8_signal_fck_prescaler_read(struct counter_device *counter,
 980					   struct counter_signal *signal,
 981					   u8 *prescaler)
 982{
 983	const struct quad8 *const priv = counter_priv(counter);
 984
 985	*prescaler = priv->fck_prescaler[signal->id / 2];
 986
 987	return 0;
 988}
 989
 990static int quad8_signal_fck_prescaler_write(struct counter_device *counter,
 991					    struct counter_signal *signal,
 992					    u8 prescaler)
 993{
 994	struct quad8 *const priv = counter_priv(counter);
 995	const size_t channel_id = signal->id / 2;
 996	struct channel_reg __iomem *const chan = priv->reg->channel + channel_id;
 997	unsigned long irqflags;
 998
 999	spin_lock_irqsave(&priv->lock, irqflags);
1000
1001	priv->fck_prescaler[channel_id] = prescaler;
1002
1003	/* Reset Byte Pointer */
1004	iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
1005
1006	/* Set filter clock factor */
1007	iowrite8(prescaler, &chan->data);
1008	iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
1009		 &chan->control);
1010
1011	spin_unlock_irqrestore(&priv->lock, irqflags);
1012
1013	return 0;
1014}
1015
1016static struct counter_comp quad8_signal_ext[] = {
1017	COUNTER_COMP_SIGNAL_BOOL("cable_fault", quad8_signal_cable_fault_read,
1018				 NULL),
1019	COUNTER_COMP_SIGNAL_BOOL("cable_fault_enable",
1020				 quad8_signal_cable_fault_enable_read,
1021				 quad8_signal_cable_fault_enable_write),
1022	COUNTER_COMP_SIGNAL_U8("filter_clock_prescaler",
1023			       quad8_signal_fck_prescaler_read,
1024			       quad8_signal_fck_prescaler_write)
1025};
1026
1027static const enum counter_signal_polarity quad8_polarities[] = {
1028	COUNTER_SIGNAL_POLARITY_POSITIVE,
1029	COUNTER_SIGNAL_POLARITY_NEGATIVE,
1030};
1031
1032static DEFINE_COUNTER_AVAILABLE(quad8_polarity_available, quad8_polarities);
1033
1034static DEFINE_COUNTER_ENUM(quad8_index_pol_enum, quad8_index_polarity_modes);
1035static DEFINE_COUNTER_ENUM(quad8_synch_mode_enum, quad8_synchronous_modes);
1036
1037static struct counter_comp quad8_index_ext[] = {
1038	COUNTER_COMP_SIGNAL_ENUM("index_polarity", quad8_index_polarity_get,
1039				 quad8_index_polarity_set,
1040				 quad8_index_pol_enum),
1041	COUNTER_COMP_POLARITY(quad8_polarity_read, quad8_polarity_write,
1042			      quad8_polarity_available),
1043	COUNTER_COMP_SIGNAL_ENUM("synchronous_mode", quad8_synchronous_mode_get,
1044				 quad8_synchronous_mode_set,
1045				 quad8_synch_mode_enum),
1046};
1047
1048#define QUAD8_QUAD_SIGNAL(_id, _name) {		\
1049	.id = (_id),				\
1050	.name = (_name),			\
1051	.ext = quad8_signal_ext,		\
1052	.num_ext = ARRAY_SIZE(quad8_signal_ext)	\
1053}
1054
1055#define	QUAD8_INDEX_SIGNAL(_id, _name) {	\
1056	.id = (_id),				\
1057	.name = (_name),			\
1058	.ext = quad8_index_ext,			\
1059	.num_ext = ARRAY_SIZE(quad8_index_ext)	\
1060}
1061
1062static struct counter_signal quad8_signals[] = {
1063	QUAD8_QUAD_SIGNAL(0, "Channel 1 Quadrature A"),
1064	QUAD8_QUAD_SIGNAL(1, "Channel 1 Quadrature B"),
1065	QUAD8_QUAD_SIGNAL(2, "Channel 2 Quadrature A"),
1066	QUAD8_QUAD_SIGNAL(3, "Channel 2 Quadrature B"),
1067	QUAD8_QUAD_SIGNAL(4, "Channel 3 Quadrature A"),
1068	QUAD8_QUAD_SIGNAL(5, "Channel 3 Quadrature B"),
1069	QUAD8_QUAD_SIGNAL(6, "Channel 4 Quadrature A"),
1070	QUAD8_QUAD_SIGNAL(7, "Channel 4 Quadrature B"),
1071	QUAD8_QUAD_SIGNAL(8, "Channel 5 Quadrature A"),
1072	QUAD8_QUAD_SIGNAL(9, "Channel 5 Quadrature B"),
1073	QUAD8_QUAD_SIGNAL(10, "Channel 6 Quadrature A"),
1074	QUAD8_QUAD_SIGNAL(11, "Channel 6 Quadrature B"),
1075	QUAD8_QUAD_SIGNAL(12, "Channel 7 Quadrature A"),
1076	QUAD8_QUAD_SIGNAL(13, "Channel 7 Quadrature B"),
1077	QUAD8_QUAD_SIGNAL(14, "Channel 8 Quadrature A"),
1078	QUAD8_QUAD_SIGNAL(15, "Channel 8 Quadrature B"),
1079	QUAD8_INDEX_SIGNAL(16, "Channel 1 Index"),
1080	QUAD8_INDEX_SIGNAL(17, "Channel 2 Index"),
1081	QUAD8_INDEX_SIGNAL(18, "Channel 3 Index"),
1082	QUAD8_INDEX_SIGNAL(19, "Channel 4 Index"),
1083	QUAD8_INDEX_SIGNAL(20, "Channel 5 Index"),
1084	QUAD8_INDEX_SIGNAL(21, "Channel 6 Index"),
1085	QUAD8_INDEX_SIGNAL(22, "Channel 7 Index"),
1086	QUAD8_INDEX_SIGNAL(23, "Channel 8 Index")
1087};
1088
1089#define QUAD8_COUNT_SYNAPSES(_id) {					\
1090	{								\
1091		.actions_list = quad8_synapse_actions_list,		\
1092		.num_actions = ARRAY_SIZE(quad8_synapse_actions_list),	\
1093		.signal = quad8_signals + 2 * (_id)			\
1094	},								\
1095	{								\
1096		.actions_list = quad8_synapse_actions_list,		\
1097		.num_actions = ARRAY_SIZE(quad8_synapse_actions_list),	\
1098		.signal = quad8_signals + 2 * (_id) + 1			\
1099	},								\
1100	{								\
1101		.actions_list = quad8_index_actions_list,		\
1102		.num_actions = ARRAY_SIZE(quad8_index_actions_list),	\
1103		.signal = quad8_signals + 2 * (_id) + 16		\
1104	}								\
1105}
1106
1107static struct counter_synapse quad8_count_synapses[][3] = {
1108	QUAD8_COUNT_SYNAPSES(0), QUAD8_COUNT_SYNAPSES(1),
1109	QUAD8_COUNT_SYNAPSES(2), QUAD8_COUNT_SYNAPSES(3),
1110	QUAD8_COUNT_SYNAPSES(4), QUAD8_COUNT_SYNAPSES(5),
1111	QUAD8_COUNT_SYNAPSES(6), QUAD8_COUNT_SYNAPSES(7)
1112};
1113
1114static const enum counter_count_mode quad8_cnt_modes[] = {
1115	COUNTER_COUNT_MODE_NORMAL,
1116	COUNTER_COUNT_MODE_RANGE_LIMIT,
1117	COUNTER_COUNT_MODE_NON_RECYCLE,
1118	COUNTER_COUNT_MODE_MODULO_N,
1119};
1120
1121static DEFINE_COUNTER_AVAILABLE(quad8_count_mode_available, quad8_cnt_modes);
1122
1123static DEFINE_COUNTER_ENUM(quad8_error_noise_enum, quad8_noise_error_states);
1124
1125static struct counter_comp quad8_count_ext[] = {
1126	COUNTER_COMP_CEILING(quad8_count_ceiling_read,
1127			     quad8_count_ceiling_write),
1128	COUNTER_COMP_FLOOR(quad8_count_floor_read, NULL),
1129	COUNTER_COMP_COUNT_MODE(quad8_count_mode_read, quad8_count_mode_write,
1130				quad8_count_mode_available),
1131	COUNTER_COMP_DIRECTION(quad8_direction_read),
1132	COUNTER_COMP_ENABLE(quad8_count_enable_read, quad8_count_enable_write),
1133	COUNTER_COMP_COUNT_ENUM("error_noise", quad8_error_noise_get, NULL,
1134				quad8_error_noise_enum),
1135	COUNTER_COMP_PRESET(quad8_count_preset_read, quad8_count_preset_write),
1136	COUNTER_COMP_PRESET_ENABLE(quad8_count_preset_enable_read,
1137				   quad8_count_preset_enable_write),
1138};
1139
1140#define QUAD8_COUNT(_id, _cntname) {					\
1141	.id = (_id),							\
1142	.name = (_cntname),						\
1143	.functions_list = quad8_count_functions_list,			\
1144	.num_functions = ARRAY_SIZE(quad8_count_functions_list),	\
1145	.synapses = quad8_count_synapses[(_id)],			\
1146	.num_synapses =	2,						\
1147	.ext = quad8_count_ext,						\
1148	.num_ext = ARRAY_SIZE(quad8_count_ext)				\
1149}
1150
1151static struct counter_count quad8_counts[] = {
1152	QUAD8_COUNT(0, "Channel 1 Count"),
1153	QUAD8_COUNT(1, "Channel 2 Count"),
1154	QUAD8_COUNT(2, "Channel 3 Count"),
1155	QUAD8_COUNT(3, "Channel 4 Count"),
1156	QUAD8_COUNT(4, "Channel 5 Count"),
1157	QUAD8_COUNT(5, "Channel 6 Count"),
1158	QUAD8_COUNT(6, "Channel 7 Count"),
1159	QUAD8_COUNT(7, "Channel 8 Count")
1160};
1161
1162static irqreturn_t quad8_irq_handler(int irq, void *private)
1163{
1164	struct counter_device *counter = private;
1165	struct quad8 *const priv = counter_priv(counter);
1166	unsigned long irq_status;
1167	unsigned long channel;
1168	u8 event;
1169
1170	irq_status = ioread8(&priv->reg->interrupt_status);
1171	if (!irq_status)
1172		return IRQ_NONE;
1173
1174	for_each_set_bit(channel, &irq_status, QUAD8_NUM_COUNTERS) {
1175		switch (priv->irq_trigger[channel]) {
1176		case QUAD8_EVENT_CARRY:
1177			event = COUNTER_EVENT_OVERFLOW;
1178				break;
1179		case QUAD8_EVENT_COMPARE:
1180			event = COUNTER_EVENT_THRESHOLD;
1181				break;
1182		case QUAD8_EVENT_CARRY_BORROW:
1183			event = COUNTER_EVENT_OVERFLOW_UNDERFLOW;
1184				break;
1185		case QUAD8_EVENT_INDEX:
1186			event = COUNTER_EVENT_INDEX;
1187				break;
1188		default:
1189			/* should never reach this path */
1190			WARN_ONCE(true, "invalid interrupt trigger function %u configured for channel %lu\n",
1191				  priv->irq_trigger[channel], channel);
1192			continue;
1193		}
1194
1195		counter_push_event(counter, event, channel);
1196	}
1197
1198	/* Clear pending interrupts on device */
1199	iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper);
1200
1201	return IRQ_HANDLED;
1202}
1203
1204static void quad8_init_counter(struct channel_reg __iomem *const chan)
1205{
1206	unsigned long i;
1207
1208	/* Reset Byte Pointer */
1209	iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
1210	/* Reset filter clock factor */
1211	iowrite8(0, &chan->data);
1212	iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
1213		 &chan->control);
1214	/* Reset Byte Pointer */
1215	iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
1216	/* Reset Preset Register */
1217	for (i = 0; i < 3; i++)
1218		iowrite8(0x00, &chan->data);
1219	/* Reset Borrow, Carry, Compare, and Sign flags */
1220	iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control);
1221	/* Reset Error flag */
1222	iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control);
1223	/* Binary encoding; Normal count; non-quadrature mode */
1224	iowrite8(QUAD8_CTR_CMR, &chan->control);
1225	/* Disable A and B inputs; preset on index; FLG1 as Carry */
1226	iowrite8(QUAD8_CTR_IOR, &chan->control);
1227	/* Disable index function; negative index polarity */
1228	iowrite8(QUAD8_CTR_IDR, &chan->control);
1229}
1230
1231static int quad8_probe(struct device *dev, unsigned int id)
1232{
1233	struct counter_device *counter;
1234	struct quad8 *priv;
1235	unsigned long i;
1236	int err;
1237
1238	if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) {
1239		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
1240			base[id], base[id] + QUAD8_EXTENT);
1241		return -EBUSY;
1242	}
1243
1244	counter = devm_counter_alloc(dev, sizeof(*priv));
1245	if (!counter)
1246		return -ENOMEM;
1247	priv = counter_priv(counter);
1248
1249	priv->reg = devm_ioport_map(dev, base[id], QUAD8_EXTENT);
1250	if (!priv->reg)
1251		return -ENOMEM;
1252
1253	/* Initialize Counter device and driver data */
1254	counter->name = dev_name(dev);
1255	counter->parent = dev;
1256	counter->ops = &quad8_ops;
1257	counter->counts = quad8_counts;
1258	counter->num_counts = ARRAY_SIZE(quad8_counts);
1259	counter->signals = quad8_signals;
1260	counter->num_signals = ARRAY_SIZE(quad8_signals);
1261
1262	spin_lock_init(&priv->lock);
1263
1264	/* Reset Index/Interrupt Register */
1265	iowrite8(0x00, &priv->reg->index_interrupt);
1266	/* Reset all counters and disable interrupt function */
1267	iowrite8(QUAD8_CHAN_OP_RESET_COUNTERS, &priv->reg->channel_oper);
1268	/* Set initial configuration for all counters */
1269	for (i = 0; i < QUAD8_NUM_COUNTERS; i++)
1270		quad8_init_counter(priv->reg->channel + i);
1271	/* Disable Differential Encoder Cable Status for all channels */
1272	iowrite8(0xFF, &priv->reg->cable_status);
1273	/* Enable all counters and enable interrupt function */
1274	iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper);
1275
1276	err = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler,
1277			       IRQF_SHARED, counter->name, counter);
1278	if (err)
1279		return err;
1280
1281	err = devm_counter_add(dev, counter);
1282	if (err < 0)
1283		return dev_err_probe(dev, err, "Failed to add counter\n");
1284
1285	return 0;
1286}
1287
1288static struct isa_driver quad8_driver = {
1289	.probe = quad8_probe,
1290	.driver = {
1291		.name = "104-quad-8"
1292	}
1293};
1294
1295module_isa_driver_with_irq(quad8_driver, num_quad8, num_irq);
1296
1297MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
1298MODULE_DESCRIPTION("ACCES 104-QUAD-8 driver");
1299MODULE_LICENSE("GPL v2");
1300MODULE_IMPORT_NS(COUNTER);