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