cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

104-quad-8.c (34871B)


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