xref: /openbmc/linux/drivers/counter/104-quad-8.c (revision 8f92f680)
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/iio/iio.h>
13 #include <linux/iio/types.h>
14 #include <linux/io.h>
15 #include <linux/ioport.h>
16 #include <linux/isa.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/moduleparam.h>
20 #include <linux/types.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_array(base, uint, &num_quad8, 0);
27 MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");
28 
29 #define QUAD8_NUM_COUNTERS 8
30 
31 /**
32  * struct quad8_iio - IIO device private data structure
33  * @counter:		instance of the counter_device
34  * @fck_prescaler:	array of filter clock prescaler configurations
35  * @preset:		array of preset values
36  * @count_mode:		array of count mode configurations
37  * @quadrature_mode:	array of quadrature mode configurations
38  * @quadrature_scale:	array of quadrature mode scale configurations
39  * @ab_enable:		array of A and B inputs enable configurations
40  * @preset_enable:	array of set_to_preset_on_index attribute configurations
41  * @synchronous_mode:	array of index function synchronous mode configurations
42  * @index_polarity:	array of index function polarity configurations
43  * @cable_fault_enable:	differential encoder cable status enable configurations
44  * @base:		base port address of the IIO device
45  */
46 struct quad8_iio {
47 	struct mutex lock;
48 	struct counter_device counter;
49 	unsigned int fck_prescaler[QUAD8_NUM_COUNTERS];
50 	unsigned int preset[QUAD8_NUM_COUNTERS];
51 	unsigned int count_mode[QUAD8_NUM_COUNTERS];
52 	unsigned int quadrature_mode[QUAD8_NUM_COUNTERS];
53 	unsigned int quadrature_scale[QUAD8_NUM_COUNTERS];
54 	unsigned int ab_enable[QUAD8_NUM_COUNTERS];
55 	unsigned int preset_enable[QUAD8_NUM_COUNTERS];
56 	unsigned int synchronous_mode[QUAD8_NUM_COUNTERS];
57 	unsigned int index_polarity[QUAD8_NUM_COUNTERS];
58 	unsigned int cable_fault_enable;
59 	unsigned int base;
60 };
61 
62 #define QUAD8_REG_CHAN_OP 0x11
63 #define QUAD8_REG_INDEX_INPUT_LEVELS 0x16
64 #define QUAD8_DIFF_ENCODER_CABLE_STATUS 0x17
65 /* Borrow Toggle flip-flop */
66 #define QUAD8_FLAG_BT BIT(0)
67 /* Carry Toggle flip-flop */
68 #define QUAD8_FLAG_CT BIT(1)
69 /* Error flag */
70 #define QUAD8_FLAG_E BIT(4)
71 /* Up/Down flag */
72 #define QUAD8_FLAG_UD BIT(5)
73 /* Reset and Load Signal Decoders */
74 #define QUAD8_CTR_RLD 0x00
75 /* Counter Mode Register */
76 #define QUAD8_CTR_CMR 0x20
77 /* Input / Output Control Register */
78 #define QUAD8_CTR_IOR 0x40
79 /* Index Control Register */
80 #define QUAD8_CTR_IDR 0x60
81 /* Reset Byte Pointer (three byte data pointer) */
82 #define QUAD8_RLD_RESET_BP 0x01
83 /* Reset Counter */
84 #define QUAD8_RLD_RESET_CNTR 0x02
85 /* Reset Borrow Toggle, Carry Toggle, Compare Toggle, and Sign flags */
86 #define QUAD8_RLD_RESET_FLAGS 0x04
87 /* Reset Error flag */
88 #define QUAD8_RLD_RESET_E 0x06
89 /* Preset Register to Counter */
90 #define QUAD8_RLD_PRESET_CNTR 0x08
91 /* Transfer Counter to Output Latch */
92 #define QUAD8_RLD_CNTR_OUT 0x10
93 /* Transfer Preset Register LSB to FCK Prescaler */
94 #define QUAD8_RLD_PRESET_PSC 0x18
95 #define QUAD8_CHAN_OP_ENABLE_COUNTERS 0x00
96 #define QUAD8_CHAN_OP_RESET_COUNTERS 0x01
97 #define QUAD8_CMR_QUADRATURE_X1 0x08
98 #define QUAD8_CMR_QUADRATURE_X2 0x10
99 #define QUAD8_CMR_QUADRATURE_X4 0x18
100 
101 
102 static int quad8_read_raw(struct iio_dev *indio_dev,
103 	struct iio_chan_spec const *chan, int *val, int *val2, long mask)
104 {
105 	struct quad8_iio *const priv = iio_priv(indio_dev);
106 	const int base_offset = priv->base + 2 * chan->channel;
107 	unsigned int flags;
108 	unsigned int borrow;
109 	unsigned int carry;
110 	int i;
111 
112 	switch (mask) {
113 	case IIO_CHAN_INFO_RAW:
114 		if (chan->type == IIO_INDEX) {
115 			*val = !!(inb(priv->base + QUAD8_REG_INDEX_INPUT_LEVELS)
116 				& BIT(chan->channel));
117 			return IIO_VAL_INT;
118 		}
119 
120 		flags = inb(base_offset + 1);
121 		borrow = flags & QUAD8_FLAG_BT;
122 		carry = !!(flags & QUAD8_FLAG_CT);
123 
124 		/* Borrow XOR Carry effectively doubles count range */
125 		*val = (borrow ^ carry) << 24;
126 
127 		mutex_lock(&priv->lock);
128 
129 		/* Reset Byte Pointer; transfer Counter to Output Latch */
130 		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
131 		     base_offset + 1);
132 
133 		for (i = 0; i < 3; i++)
134 			*val |= (unsigned int)inb(base_offset) << (8 * i);
135 
136 		mutex_unlock(&priv->lock);
137 
138 		return IIO_VAL_INT;
139 	case IIO_CHAN_INFO_ENABLE:
140 		*val = priv->ab_enable[chan->channel];
141 		return IIO_VAL_INT;
142 	case IIO_CHAN_INFO_SCALE:
143 		*val = 1;
144 		*val2 = priv->quadrature_scale[chan->channel];
145 		return IIO_VAL_FRACTIONAL_LOG2;
146 	}
147 
148 	return -EINVAL;
149 }
150 
151 static int quad8_write_raw(struct iio_dev *indio_dev,
152 	struct iio_chan_spec const *chan, int val, int val2, long mask)
153 {
154 	struct quad8_iio *const priv = iio_priv(indio_dev);
155 	const int base_offset = priv->base + 2 * chan->channel;
156 	int i;
157 	unsigned int ior_cfg;
158 
159 	switch (mask) {
160 	case IIO_CHAN_INFO_RAW:
161 		if (chan->type == IIO_INDEX)
162 			return -EINVAL;
163 
164 		/* Only 24-bit values are supported */
165 		if ((unsigned int)val > 0xFFFFFF)
166 			return -EINVAL;
167 
168 		mutex_lock(&priv->lock);
169 
170 		/* Reset Byte Pointer */
171 		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
172 
173 		/* Counter can only be set via Preset Register */
174 		for (i = 0; i < 3; i++)
175 			outb(val >> (8 * i), base_offset);
176 
177 		/* Transfer Preset Register to Counter */
178 		outb(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, base_offset + 1);
179 
180 		/* Reset Byte Pointer */
181 		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
182 
183 		/* Set Preset Register back to original value */
184 		val = priv->preset[chan->channel];
185 		for (i = 0; i < 3; i++)
186 			outb(val >> (8 * i), base_offset);
187 
188 		/* Reset Borrow, Carry, Compare, and Sign flags */
189 		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1);
190 		/* Reset Error flag */
191 		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
192 
193 		mutex_unlock(&priv->lock);
194 
195 		return 0;
196 	case IIO_CHAN_INFO_ENABLE:
197 		/* only boolean values accepted */
198 		if (val < 0 || val > 1)
199 			return -EINVAL;
200 
201 		mutex_lock(&priv->lock);
202 
203 		priv->ab_enable[chan->channel] = val;
204 
205 		ior_cfg = val | priv->preset_enable[chan->channel] << 1;
206 
207 		/* Load I/O control configuration */
208 		outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1);
209 
210 		mutex_unlock(&priv->lock);
211 
212 		return 0;
213 	case IIO_CHAN_INFO_SCALE:
214 		mutex_lock(&priv->lock);
215 
216 		/* Quadrature scaling only available in quadrature mode */
217 		if (!priv->quadrature_mode[chan->channel] &&
218 				(val2 || val != 1)) {
219 			mutex_unlock(&priv->lock);
220 			return -EINVAL;
221 		}
222 
223 		/* Only three gain states (1, 0.5, 0.25) */
224 		if (val == 1 && !val2)
225 			priv->quadrature_scale[chan->channel] = 0;
226 		else if (!val)
227 			switch (val2) {
228 			case 500000:
229 				priv->quadrature_scale[chan->channel] = 1;
230 				break;
231 			case 250000:
232 				priv->quadrature_scale[chan->channel] = 2;
233 				break;
234 			default:
235 				mutex_unlock(&priv->lock);
236 				return -EINVAL;
237 			}
238 		else {
239 			mutex_unlock(&priv->lock);
240 			return -EINVAL;
241 		}
242 
243 		mutex_unlock(&priv->lock);
244 		return 0;
245 	}
246 
247 	return -EINVAL;
248 }
249 
250 static const struct iio_info quad8_info = {
251 	.read_raw = quad8_read_raw,
252 	.write_raw = quad8_write_raw
253 };
254 
255 static ssize_t quad8_read_preset(struct iio_dev *indio_dev, uintptr_t private,
256 	const struct iio_chan_spec *chan, char *buf)
257 {
258 	const struct quad8_iio *const priv = iio_priv(indio_dev);
259 
260 	return snprintf(buf, PAGE_SIZE, "%u\n", priv->preset[chan->channel]);
261 }
262 
263 static ssize_t quad8_write_preset(struct iio_dev *indio_dev, uintptr_t private,
264 	const struct iio_chan_spec *chan, const char *buf, size_t len)
265 {
266 	struct quad8_iio *const priv = iio_priv(indio_dev);
267 	const int base_offset = priv->base + 2 * chan->channel;
268 	unsigned int preset;
269 	int ret;
270 	int i;
271 
272 	ret = kstrtouint(buf, 0, &preset);
273 	if (ret)
274 		return ret;
275 
276 	/* Only 24-bit values are supported */
277 	if (preset > 0xFFFFFF)
278 		return -EINVAL;
279 
280 	mutex_lock(&priv->lock);
281 
282 	priv->preset[chan->channel] = preset;
283 
284 	/* Reset Byte Pointer */
285 	outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
286 
287 	/* Set Preset Register */
288 	for (i = 0; i < 3; i++)
289 		outb(preset >> (8 * i), base_offset);
290 
291 	mutex_unlock(&priv->lock);
292 
293 	return len;
294 }
295 
296 static ssize_t quad8_read_set_to_preset_on_index(struct iio_dev *indio_dev,
297 	uintptr_t private, const struct iio_chan_spec *chan, char *buf)
298 {
299 	const struct quad8_iio *const priv = iio_priv(indio_dev);
300 
301 	return snprintf(buf, PAGE_SIZE, "%u\n",
302 		!priv->preset_enable[chan->channel]);
303 }
304 
305 static ssize_t quad8_write_set_to_preset_on_index(struct iio_dev *indio_dev,
306 	uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
307 	size_t len)
308 {
309 	struct quad8_iio *const priv = iio_priv(indio_dev);
310 	const int base_offset = priv->base + 2 * chan->channel + 1;
311 	bool preset_enable;
312 	int ret;
313 	unsigned int ior_cfg;
314 
315 	ret = kstrtobool(buf, &preset_enable);
316 	if (ret)
317 		return ret;
318 
319 	/* Preset enable is active low in Input/Output Control register */
320 	preset_enable = !preset_enable;
321 
322 	mutex_lock(&priv->lock);
323 
324 	priv->preset_enable[chan->channel] = preset_enable;
325 
326 	ior_cfg = priv->ab_enable[chan->channel] |
327 		(unsigned int)preset_enable << 1;
328 
329 	/* Load I/O control configuration to Input / Output Control Register */
330 	outb(QUAD8_CTR_IOR | ior_cfg, base_offset);
331 
332 	mutex_unlock(&priv->lock);
333 
334 	return len;
335 }
336 
337 static const char *const quad8_noise_error_states[] = {
338 	"No excessive noise is present at the count inputs",
339 	"Excessive noise is present at the count inputs"
340 };
341 
342 static int quad8_get_noise_error(struct iio_dev *indio_dev,
343 	const struct iio_chan_spec *chan)
344 {
345 	struct quad8_iio *const priv = iio_priv(indio_dev);
346 	const int base_offset = priv->base + 2 * chan->channel + 1;
347 
348 	return !!(inb(base_offset) & QUAD8_FLAG_E);
349 }
350 
351 static const struct iio_enum quad8_noise_error_enum = {
352 	.items = quad8_noise_error_states,
353 	.num_items = ARRAY_SIZE(quad8_noise_error_states),
354 	.get = quad8_get_noise_error
355 };
356 
357 static const char *const quad8_count_direction_states[] = {
358 	"down",
359 	"up"
360 };
361 
362 static int quad8_get_count_direction(struct iio_dev *indio_dev,
363 	const struct iio_chan_spec *chan)
364 {
365 	struct quad8_iio *const priv = iio_priv(indio_dev);
366 	const int base_offset = priv->base + 2 * chan->channel + 1;
367 
368 	return !!(inb(base_offset) & QUAD8_FLAG_UD);
369 }
370 
371 static const struct iio_enum quad8_count_direction_enum = {
372 	.items = quad8_count_direction_states,
373 	.num_items = ARRAY_SIZE(quad8_count_direction_states),
374 	.get = quad8_get_count_direction
375 };
376 
377 static const char *const quad8_count_modes[] = {
378 	"normal",
379 	"range limit",
380 	"non-recycle",
381 	"modulo-n"
382 };
383 
384 static int quad8_set_count_mode(struct iio_dev *indio_dev,
385 	const struct iio_chan_spec *chan, unsigned int cnt_mode)
386 {
387 	struct quad8_iio *const priv = iio_priv(indio_dev);
388 	unsigned int mode_cfg = cnt_mode << 1;
389 	const int base_offset = priv->base + 2 * chan->channel + 1;
390 
391 	mutex_lock(&priv->lock);
392 
393 	priv->count_mode[chan->channel] = cnt_mode;
394 
395 	/* Add quadrature mode configuration */
396 	if (priv->quadrature_mode[chan->channel])
397 		mode_cfg |= (priv->quadrature_scale[chan->channel] + 1) << 3;
398 
399 	/* Load mode configuration to Counter Mode Register */
400 	outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
401 
402 	mutex_unlock(&priv->lock);
403 
404 	return 0;
405 }
406 
407 static int quad8_get_count_mode(struct iio_dev *indio_dev,
408 	const struct iio_chan_spec *chan)
409 {
410 	const struct quad8_iio *const priv = iio_priv(indio_dev);
411 
412 	return priv->count_mode[chan->channel];
413 }
414 
415 static const struct iio_enum quad8_count_mode_enum = {
416 	.items = quad8_count_modes,
417 	.num_items = ARRAY_SIZE(quad8_count_modes),
418 	.set = quad8_set_count_mode,
419 	.get = quad8_get_count_mode
420 };
421 
422 static const char *const quad8_synchronous_modes[] = {
423 	"non-synchronous",
424 	"synchronous"
425 };
426 
427 static int quad8_set_synchronous_mode(struct iio_dev *indio_dev,
428 	const struct iio_chan_spec *chan, unsigned int synchronous_mode)
429 {
430 	struct quad8_iio *const priv = iio_priv(indio_dev);
431 	const int base_offset = priv->base + 2 * chan->channel + 1;
432 	unsigned int idr_cfg = synchronous_mode;
433 
434 	mutex_lock(&priv->lock);
435 
436 	idr_cfg |= priv->index_polarity[chan->channel] << 1;
437 
438 	/* Index function must be non-synchronous in non-quadrature mode */
439 	if (synchronous_mode && !priv->quadrature_mode[chan->channel]) {
440 		mutex_unlock(&priv->lock);
441 		return -EINVAL;
442 	}
443 
444 	priv->synchronous_mode[chan->channel] = synchronous_mode;
445 
446 	/* Load Index Control configuration to Index Control Register */
447 	outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
448 
449 	mutex_unlock(&priv->lock);
450 
451 	return 0;
452 }
453 
454 static int quad8_get_synchronous_mode(struct iio_dev *indio_dev,
455 	const struct iio_chan_spec *chan)
456 {
457 	const struct quad8_iio *const priv = iio_priv(indio_dev);
458 
459 	return priv->synchronous_mode[chan->channel];
460 }
461 
462 static const struct iio_enum quad8_synchronous_mode_enum = {
463 	.items = quad8_synchronous_modes,
464 	.num_items = ARRAY_SIZE(quad8_synchronous_modes),
465 	.set = quad8_set_synchronous_mode,
466 	.get = quad8_get_synchronous_mode
467 };
468 
469 static const char *const quad8_quadrature_modes[] = {
470 	"non-quadrature",
471 	"quadrature"
472 };
473 
474 static int quad8_set_quadrature_mode(struct iio_dev *indio_dev,
475 	const struct iio_chan_spec *chan, unsigned int quadrature_mode)
476 {
477 	struct quad8_iio *const priv = iio_priv(indio_dev);
478 	const int base_offset = priv->base + 2 * chan->channel + 1;
479 	unsigned int mode_cfg;
480 
481 	mutex_lock(&priv->lock);
482 
483 	mode_cfg = priv->count_mode[chan->channel] << 1;
484 
485 	if (quadrature_mode)
486 		mode_cfg |= (priv->quadrature_scale[chan->channel] + 1) << 3;
487 	else {
488 		/* Quadrature scaling only available in quadrature mode */
489 		priv->quadrature_scale[chan->channel] = 0;
490 
491 		/* Synchronous function not supported in non-quadrature mode */
492 		if (priv->synchronous_mode[chan->channel])
493 			quad8_set_synchronous_mode(indio_dev, chan, 0);
494 	}
495 
496 	priv->quadrature_mode[chan->channel] = quadrature_mode;
497 
498 	/* Load mode configuration to Counter Mode Register */
499 	outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
500 
501 	mutex_unlock(&priv->lock);
502 
503 	return 0;
504 }
505 
506 static int quad8_get_quadrature_mode(struct iio_dev *indio_dev,
507 	const struct iio_chan_spec *chan)
508 {
509 	const struct quad8_iio *const priv = iio_priv(indio_dev);
510 
511 	return priv->quadrature_mode[chan->channel];
512 }
513 
514 static const struct iio_enum quad8_quadrature_mode_enum = {
515 	.items = quad8_quadrature_modes,
516 	.num_items = ARRAY_SIZE(quad8_quadrature_modes),
517 	.set = quad8_set_quadrature_mode,
518 	.get = quad8_get_quadrature_mode
519 };
520 
521 static const char *const quad8_index_polarity_modes[] = {
522 	"negative",
523 	"positive"
524 };
525 
526 static int quad8_set_index_polarity(struct iio_dev *indio_dev,
527 	const struct iio_chan_spec *chan, unsigned int index_polarity)
528 {
529 	struct quad8_iio *const priv = iio_priv(indio_dev);
530 	const int base_offset = priv->base + 2 * chan->channel + 1;
531 	unsigned int idr_cfg = index_polarity << 1;
532 
533 	mutex_lock(&priv->lock);
534 
535 	idr_cfg |= priv->synchronous_mode[chan->channel];
536 
537 	priv->index_polarity[chan->channel] = index_polarity;
538 
539 	/* Load Index Control configuration to Index Control Register */
540 	outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
541 
542 	mutex_unlock(&priv->lock);
543 
544 	return 0;
545 }
546 
547 static int quad8_get_index_polarity(struct iio_dev *indio_dev,
548 	const struct iio_chan_spec *chan)
549 {
550 	const struct quad8_iio *const priv = iio_priv(indio_dev);
551 
552 	return priv->index_polarity[chan->channel];
553 }
554 
555 static const struct iio_enum quad8_index_polarity_enum = {
556 	.items = quad8_index_polarity_modes,
557 	.num_items = ARRAY_SIZE(quad8_index_polarity_modes),
558 	.set = quad8_set_index_polarity,
559 	.get = quad8_get_index_polarity
560 };
561 
562 static const struct iio_chan_spec_ext_info quad8_count_ext_info[] = {
563 	{
564 		.name = "preset",
565 		.shared = IIO_SEPARATE,
566 		.read = quad8_read_preset,
567 		.write = quad8_write_preset
568 	},
569 	{
570 		.name = "set_to_preset_on_index",
571 		.shared = IIO_SEPARATE,
572 		.read = quad8_read_set_to_preset_on_index,
573 		.write = quad8_write_set_to_preset_on_index
574 	},
575 	IIO_ENUM("noise_error", IIO_SEPARATE, &quad8_noise_error_enum),
576 	IIO_ENUM_AVAILABLE("noise_error", &quad8_noise_error_enum),
577 	IIO_ENUM("count_direction", IIO_SEPARATE, &quad8_count_direction_enum),
578 	IIO_ENUM_AVAILABLE("count_direction", &quad8_count_direction_enum),
579 	IIO_ENUM("count_mode", IIO_SEPARATE, &quad8_count_mode_enum),
580 	IIO_ENUM_AVAILABLE("count_mode", &quad8_count_mode_enum),
581 	IIO_ENUM("quadrature_mode", IIO_SEPARATE, &quad8_quadrature_mode_enum),
582 	IIO_ENUM_AVAILABLE("quadrature_mode", &quad8_quadrature_mode_enum),
583 	{}
584 };
585 
586 static const struct iio_chan_spec_ext_info quad8_index_ext_info[] = {
587 	IIO_ENUM("synchronous_mode", IIO_SEPARATE,
588 		&quad8_synchronous_mode_enum),
589 	IIO_ENUM_AVAILABLE("synchronous_mode", &quad8_synchronous_mode_enum),
590 	IIO_ENUM("index_polarity", IIO_SEPARATE, &quad8_index_polarity_enum),
591 	IIO_ENUM_AVAILABLE("index_polarity", &quad8_index_polarity_enum),
592 	{}
593 };
594 
595 #define QUAD8_COUNT_CHAN(_chan) {					\
596 	.type = IIO_COUNT,						\
597 	.channel = (_chan),						\
598 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |			\
599 		BIT(IIO_CHAN_INFO_ENABLE) | BIT(IIO_CHAN_INFO_SCALE),	\
600 	.ext_info = quad8_count_ext_info,				\
601 	.indexed = 1							\
602 }
603 
604 #define QUAD8_INDEX_CHAN(_chan) {			\
605 	.type = IIO_INDEX,				\
606 	.channel = (_chan),				\
607 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
608 	.ext_info = quad8_index_ext_info,		\
609 	.indexed = 1					\
610 }
611 
612 static const struct iio_chan_spec quad8_channels[] = {
613 	QUAD8_COUNT_CHAN(0), QUAD8_INDEX_CHAN(0),
614 	QUAD8_COUNT_CHAN(1), QUAD8_INDEX_CHAN(1),
615 	QUAD8_COUNT_CHAN(2), QUAD8_INDEX_CHAN(2),
616 	QUAD8_COUNT_CHAN(3), QUAD8_INDEX_CHAN(3),
617 	QUAD8_COUNT_CHAN(4), QUAD8_INDEX_CHAN(4),
618 	QUAD8_COUNT_CHAN(5), QUAD8_INDEX_CHAN(5),
619 	QUAD8_COUNT_CHAN(6), QUAD8_INDEX_CHAN(6),
620 	QUAD8_COUNT_CHAN(7), QUAD8_INDEX_CHAN(7)
621 };
622 
623 static int quad8_signal_read(struct counter_device *counter,
624 	struct counter_signal *signal, enum counter_signal_value *val)
625 {
626 	const struct quad8_iio *const priv = counter->priv;
627 	unsigned int state;
628 
629 	/* Only Index signal levels can be read */
630 	if (signal->id < 16)
631 		return -EINVAL;
632 
633 	state = inb(priv->base + QUAD8_REG_INDEX_INPUT_LEVELS)
634 		& BIT(signal->id - 16);
635 
636 	*val = (state) ? COUNTER_SIGNAL_HIGH : COUNTER_SIGNAL_LOW;
637 
638 	return 0;
639 }
640 
641 static int quad8_count_read(struct counter_device *counter,
642 	struct counter_count *count, unsigned long *val)
643 {
644 	struct quad8_iio *const priv = counter->priv;
645 	const int base_offset = priv->base + 2 * count->id;
646 	unsigned int flags;
647 	unsigned int borrow;
648 	unsigned int carry;
649 	int i;
650 
651 	flags = inb(base_offset + 1);
652 	borrow = flags & QUAD8_FLAG_BT;
653 	carry = !!(flags & QUAD8_FLAG_CT);
654 
655 	/* Borrow XOR Carry effectively doubles count range */
656 	*val = (unsigned long)(borrow ^ carry) << 24;
657 
658 	mutex_lock(&priv->lock);
659 
660 	/* Reset Byte Pointer; transfer Counter to Output Latch */
661 	outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
662 	     base_offset + 1);
663 
664 	for (i = 0; i < 3; i++)
665 		*val |= (unsigned long)inb(base_offset) << (8 * i);
666 
667 	mutex_unlock(&priv->lock);
668 
669 	return 0;
670 }
671 
672 static int quad8_count_write(struct counter_device *counter,
673 	struct counter_count *count, unsigned long val)
674 {
675 	struct quad8_iio *const priv = counter->priv;
676 	const int base_offset = priv->base + 2 * count->id;
677 	int i;
678 
679 	/* Only 24-bit values are supported */
680 	if (val > 0xFFFFFF)
681 		return -EINVAL;
682 
683 	mutex_lock(&priv->lock);
684 
685 	/* Reset Byte Pointer */
686 	outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
687 
688 	/* Counter can only be set via Preset Register */
689 	for (i = 0; i < 3; i++)
690 		outb(val >> (8 * i), base_offset);
691 
692 	/* Transfer Preset Register to Counter */
693 	outb(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, base_offset + 1);
694 
695 	/* Reset Byte Pointer */
696 	outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
697 
698 	/* Set Preset Register back to original value */
699 	val = priv->preset[count->id];
700 	for (i = 0; i < 3; i++)
701 		outb(val >> (8 * i), base_offset);
702 
703 	/* Reset Borrow, Carry, Compare, and Sign flags */
704 	outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1);
705 	/* Reset Error flag */
706 	outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
707 
708 	mutex_unlock(&priv->lock);
709 
710 	return 0;
711 }
712 
713 enum quad8_count_function {
714 	QUAD8_COUNT_FUNCTION_PULSE_DIRECTION = 0,
715 	QUAD8_COUNT_FUNCTION_QUADRATURE_X1,
716 	QUAD8_COUNT_FUNCTION_QUADRATURE_X2,
717 	QUAD8_COUNT_FUNCTION_QUADRATURE_X4
718 };
719 
720 static enum counter_count_function quad8_count_functions_list[] = {
721 	[QUAD8_COUNT_FUNCTION_PULSE_DIRECTION] = COUNTER_COUNT_FUNCTION_PULSE_DIRECTION,
722 	[QUAD8_COUNT_FUNCTION_QUADRATURE_X1] = COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A,
723 	[QUAD8_COUNT_FUNCTION_QUADRATURE_X2] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A,
724 	[QUAD8_COUNT_FUNCTION_QUADRATURE_X4] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4
725 };
726 
727 static int quad8_function_get(struct counter_device *counter,
728 	struct counter_count *count, size_t *function)
729 {
730 	struct quad8_iio *const priv = counter->priv;
731 	const int id = count->id;
732 
733 	mutex_lock(&priv->lock);
734 
735 	if (priv->quadrature_mode[id])
736 		switch (priv->quadrature_scale[id]) {
737 		case 0:
738 			*function = QUAD8_COUNT_FUNCTION_QUADRATURE_X1;
739 			break;
740 		case 1:
741 			*function = QUAD8_COUNT_FUNCTION_QUADRATURE_X2;
742 			break;
743 		case 2:
744 			*function = QUAD8_COUNT_FUNCTION_QUADRATURE_X4;
745 			break;
746 		}
747 	else
748 		*function = QUAD8_COUNT_FUNCTION_PULSE_DIRECTION;
749 
750 	mutex_unlock(&priv->lock);
751 
752 	return 0;
753 }
754 
755 static int quad8_function_set(struct counter_device *counter,
756 	struct counter_count *count, size_t function)
757 {
758 	struct quad8_iio *const priv = counter->priv;
759 	const int id = count->id;
760 	unsigned int *const quadrature_mode = priv->quadrature_mode + id;
761 	unsigned int *const scale = priv->quadrature_scale + id;
762 	unsigned int *const synchronous_mode = priv->synchronous_mode + id;
763 	const int base_offset = priv->base + 2 * id + 1;
764 	unsigned int mode_cfg;
765 	unsigned int idr_cfg;
766 
767 	mutex_lock(&priv->lock);
768 
769 	mode_cfg = priv->count_mode[id] << 1;
770 	idr_cfg = priv->index_polarity[id] << 1;
771 
772 	if (function == QUAD8_COUNT_FUNCTION_PULSE_DIRECTION) {
773 		*quadrature_mode = 0;
774 
775 		/* Quadrature scaling only available in quadrature mode */
776 		*scale = 0;
777 
778 		/* Synchronous function not supported in non-quadrature mode */
779 		if (*synchronous_mode) {
780 			*synchronous_mode = 0;
781 			/* Disable synchronous function mode */
782 			outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
783 		}
784 	} else {
785 		*quadrature_mode = 1;
786 
787 		switch (function) {
788 		case QUAD8_COUNT_FUNCTION_QUADRATURE_X1:
789 			*scale = 0;
790 			mode_cfg |= QUAD8_CMR_QUADRATURE_X1;
791 			break;
792 		case QUAD8_COUNT_FUNCTION_QUADRATURE_X2:
793 			*scale = 1;
794 			mode_cfg |= QUAD8_CMR_QUADRATURE_X2;
795 			break;
796 		case QUAD8_COUNT_FUNCTION_QUADRATURE_X4:
797 			*scale = 2;
798 			mode_cfg |= QUAD8_CMR_QUADRATURE_X4;
799 			break;
800 		}
801 	}
802 
803 	/* Load mode configuration to Counter Mode Register */
804 	outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
805 
806 	mutex_unlock(&priv->lock);
807 
808 	return 0;
809 }
810 
811 static void quad8_direction_get(struct counter_device *counter,
812 	struct counter_count *count, enum counter_count_direction *direction)
813 {
814 	const struct quad8_iio *const priv = counter->priv;
815 	unsigned int ud_flag;
816 	const unsigned int flag_addr = priv->base + 2 * count->id + 1;
817 
818 	/* U/D flag: nonzero = up, zero = down */
819 	ud_flag = inb(flag_addr) & QUAD8_FLAG_UD;
820 
821 	*direction = (ud_flag) ? COUNTER_COUNT_DIRECTION_FORWARD :
822 		COUNTER_COUNT_DIRECTION_BACKWARD;
823 }
824 
825 enum quad8_synapse_action {
826 	QUAD8_SYNAPSE_ACTION_NONE = 0,
827 	QUAD8_SYNAPSE_ACTION_RISING_EDGE,
828 	QUAD8_SYNAPSE_ACTION_FALLING_EDGE,
829 	QUAD8_SYNAPSE_ACTION_BOTH_EDGES
830 };
831 
832 static enum counter_synapse_action quad8_index_actions_list[] = {
833 	[QUAD8_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE,
834 	[QUAD8_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE
835 };
836 
837 static enum counter_synapse_action quad8_synapse_actions_list[] = {
838 	[QUAD8_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE,
839 	[QUAD8_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE,
840 	[QUAD8_SYNAPSE_ACTION_FALLING_EDGE] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE,
841 	[QUAD8_SYNAPSE_ACTION_BOTH_EDGES] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES
842 };
843 
844 static int quad8_action_get(struct counter_device *counter,
845 	struct counter_count *count, struct counter_synapse *synapse,
846 	size_t *action)
847 {
848 	struct quad8_iio *const priv = counter->priv;
849 	int err;
850 	size_t function = 0;
851 	const size_t signal_a_id = count->synapses[0].signal->id;
852 	enum counter_count_direction direction;
853 
854 	/* Handle Index signals */
855 	if (synapse->signal->id >= 16) {
856 		if (priv->preset_enable[count->id])
857 			*action = QUAD8_SYNAPSE_ACTION_RISING_EDGE;
858 		else
859 			*action = QUAD8_SYNAPSE_ACTION_NONE;
860 
861 		return 0;
862 	}
863 
864 	err = quad8_function_get(counter, count, &function);
865 	if (err)
866 		return err;
867 
868 	/* Default action mode */
869 	*action = QUAD8_SYNAPSE_ACTION_NONE;
870 
871 	/* Determine action mode based on current count function mode */
872 	switch (function) {
873 	case QUAD8_COUNT_FUNCTION_PULSE_DIRECTION:
874 		if (synapse->signal->id == signal_a_id)
875 			*action = QUAD8_SYNAPSE_ACTION_RISING_EDGE;
876 		break;
877 	case QUAD8_COUNT_FUNCTION_QUADRATURE_X1:
878 		if (synapse->signal->id == signal_a_id) {
879 			quad8_direction_get(counter, count, &direction);
880 
881 			if (direction == COUNTER_COUNT_DIRECTION_FORWARD)
882 				*action = QUAD8_SYNAPSE_ACTION_RISING_EDGE;
883 			else
884 				*action = QUAD8_SYNAPSE_ACTION_FALLING_EDGE;
885 		}
886 		break;
887 	case QUAD8_COUNT_FUNCTION_QUADRATURE_X2:
888 		if (synapse->signal->id == signal_a_id)
889 			*action = QUAD8_SYNAPSE_ACTION_BOTH_EDGES;
890 		break;
891 	case QUAD8_COUNT_FUNCTION_QUADRATURE_X4:
892 		*action = QUAD8_SYNAPSE_ACTION_BOTH_EDGES;
893 		break;
894 	}
895 
896 	return 0;
897 }
898 
899 static const struct counter_ops quad8_ops = {
900 	.signal_read = quad8_signal_read,
901 	.count_read = quad8_count_read,
902 	.count_write = quad8_count_write,
903 	.function_get = quad8_function_get,
904 	.function_set = quad8_function_set,
905 	.action_get = quad8_action_get
906 };
907 
908 static int quad8_index_polarity_get(struct counter_device *counter,
909 	struct counter_signal *signal, size_t *index_polarity)
910 {
911 	const struct quad8_iio *const priv = counter->priv;
912 	const size_t channel_id = signal->id - 16;
913 
914 	*index_polarity = priv->index_polarity[channel_id];
915 
916 	return 0;
917 }
918 
919 static int quad8_index_polarity_set(struct counter_device *counter,
920 	struct counter_signal *signal, size_t index_polarity)
921 {
922 	struct quad8_iio *const priv = counter->priv;
923 	const size_t channel_id = signal->id - 16;
924 	const int base_offset = priv->base + 2 * channel_id + 1;
925 	unsigned int idr_cfg = index_polarity << 1;
926 
927 	mutex_lock(&priv->lock);
928 
929 	idr_cfg |= priv->synchronous_mode[channel_id];
930 
931 	priv->index_polarity[channel_id] = index_polarity;
932 
933 	/* Load Index Control configuration to Index Control Register */
934 	outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
935 
936 	mutex_unlock(&priv->lock);
937 
938 	return 0;
939 }
940 
941 static struct counter_signal_enum_ext quad8_index_pol_enum = {
942 	.items = quad8_index_polarity_modes,
943 	.num_items = ARRAY_SIZE(quad8_index_polarity_modes),
944 	.get = quad8_index_polarity_get,
945 	.set = quad8_index_polarity_set
946 };
947 
948 static int quad8_synchronous_mode_get(struct counter_device *counter,
949 	struct counter_signal *signal, size_t *synchronous_mode)
950 {
951 	const struct quad8_iio *const priv = counter->priv;
952 	const size_t channel_id = signal->id - 16;
953 
954 	*synchronous_mode = priv->synchronous_mode[channel_id];
955 
956 	return 0;
957 }
958 
959 static int quad8_synchronous_mode_set(struct counter_device *counter,
960 	struct counter_signal *signal, size_t synchronous_mode)
961 {
962 	struct quad8_iio *const priv = counter->priv;
963 	const size_t channel_id = signal->id - 16;
964 	const int base_offset = priv->base + 2 * channel_id + 1;
965 	unsigned int idr_cfg = synchronous_mode;
966 
967 	mutex_lock(&priv->lock);
968 
969 	idr_cfg |= priv->index_polarity[channel_id] << 1;
970 
971 	/* Index function must be non-synchronous in non-quadrature mode */
972 	if (synchronous_mode && !priv->quadrature_mode[channel_id]) {
973 		mutex_unlock(&priv->lock);
974 		return -EINVAL;
975 	}
976 
977 	priv->synchronous_mode[channel_id] = synchronous_mode;
978 
979 	/* Load Index Control configuration to Index Control Register */
980 	outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
981 
982 	mutex_unlock(&priv->lock);
983 
984 	return 0;
985 }
986 
987 static struct counter_signal_enum_ext quad8_syn_mode_enum = {
988 	.items = quad8_synchronous_modes,
989 	.num_items = ARRAY_SIZE(quad8_synchronous_modes),
990 	.get = quad8_synchronous_mode_get,
991 	.set = quad8_synchronous_mode_set
992 };
993 
994 static ssize_t quad8_count_floor_read(struct counter_device *counter,
995 	struct counter_count *count, void *private, char *buf)
996 {
997 	/* Only a floor of 0 is supported */
998 	return sprintf(buf, "0\n");
999 }
1000 
1001 static int quad8_count_mode_get(struct counter_device *counter,
1002 	struct counter_count *count, size_t *cnt_mode)
1003 {
1004 	const struct quad8_iio *const priv = counter->priv;
1005 
1006 	/* Map 104-QUAD-8 count mode to Generic Counter count mode */
1007 	switch (priv->count_mode[count->id]) {
1008 	case 0:
1009 		*cnt_mode = COUNTER_COUNT_MODE_NORMAL;
1010 		break;
1011 	case 1:
1012 		*cnt_mode = COUNTER_COUNT_MODE_RANGE_LIMIT;
1013 		break;
1014 	case 2:
1015 		*cnt_mode = COUNTER_COUNT_MODE_NON_RECYCLE;
1016 		break;
1017 	case 3:
1018 		*cnt_mode = COUNTER_COUNT_MODE_MODULO_N;
1019 		break;
1020 	}
1021 
1022 	return 0;
1023 }
1024 
1025 static int quad8_count_mode_set(struct counter_device *counter,
1026 	struct counter_count *count, size_t cnt_mode)
1027 {
1028 	struct quad8_iio *const priv = counter->priv;
1029 	unsigned int mode_cfg;
1030 	const int base_offset = priv->base + 2 * count->id + 1;
1031 
1032 	/* Map Generic Counter count mode to 104-QUAD-8 count mode */
1033 	switch (cnt_mode) {
1034 	case COUNTER_COUNT_MODE_NORMAL:
1035 		cnt_mode = 0;
1036 		break;
1037 	case COUNTER_COUNT_MODE_RANGE_LIMIT:
1038 		cnt_mode = 1;
1039 		break;
1040 	case COUNTER_COUNT_MODE_NON_RECYCLE:
1041 		cnt_mode = 2;
1042 		break;
1043 	case COUNTER_COUNT_MODE_MODULO_N:
1044 		cnt_mode = 3;
1045 		break;
1046 	}
1047 
1048 	mutex_lock(&priv->lock);
1049 
1050 	priv->count_mode[count->id] = cnt_mode;
1051 
1052 	/* Set count mode configuration value */
1053 	mode_cfg = cnt_mode << 1;
1054 
1055 	/* Add quadrature mode configuration */
1056 	if (priv->quadrature_mode[count->id])
1057 		mode_cfg |= (priv->quadrature_scale[count->id] + 1) << 3;
1058 
1059 	/* Load mode configuration to Counter Mode Register */
1060 	outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
1061 
1062 	mutex_unlock(&priv->lock);
1063 
1064 	return 0;
1065 }
1066 
1067 static struct counter_count_enum_ext quad8_cnt_mode_enum = {
1068 	.items = counter_count_mode_str,
1069 	.num_items = ARRAY_SIZE(counter_count_mode_str),
1070 	.get = quad8_count_mode_get,
1071 	.set = quad8_count_mode_set
1072 };
1073 
1074 static ssize_t quad8_count_direction_read(struct counter_device *counter,
1075 	struct counter_count *count, void *priv, char *buf)
1076 {
1077 	enum counter_count_direction dir;
1078 
1079 	quad8_direction_get(counter, count, &dir);
1080 
1081 	return sprintf(buf, "%s\n", counter_count_direction_str[dir]);
1082 }
1083 
1084 static ssize_t quad8_count_enable_read(struct counter_device *counter,
1085 	struct counter_count *count, void *private, char *buf)
1086 {
1087 	const struct quad8_iio *const priv = counter->priv;
1088 
1089 	return sprintf(buf, "%u\n", priv->ab_enable[count->id]);
1090 }
1091 
1092 static ssize_t quad8_count_enable_write(struct counter_device *counter,
1093 	struct counter_count *count, void *private, const char *buf, size_t len)
1094 {
1095 	struct quad8_iio *const priv = counter->priv;
1096 	const int base_offset = priv->base + 2 * count->id;
1097 	int err;
1098 	bool ab_enable;
1099 	unsigned int ior_cfg;
1100 
1101 	err = kstrtobool(buf, &ab_enable);
1102 	if (err)
1103 		return err;
1104 
1105 	mutex_lock(&priv->lock);
1106 
1107 	priv->ab_enable[count->id] = ab_enable;
1108 
1109 	ior_cfg = ab_enable | priv->preset_enable[count->id] << 1;
1110 
1111 	/* Load I/O control configuration */
1112 	outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1);
1113 
1114 	mutex_unlock(&priv->lock);
1115 
1116 	return len;
1117 }
1118 
1119 static int quad8_error_noise_get(struct counter_device *counter,
1120 	struct counter_count *count, size_t *noise_error)
1121 {
1122 	const struct quad8_iio *const priv = counter->priv;
1123 	const int base_offset = priv->base + 2 * count->id + 1;
1124 
1125 	*noise_error = !!(inb(base_offset) & QUAD8_FLAG_E);
1126 
1127 	return 0;
1128 }
1129 
1130 static struct counter_count_enum_ext quad8_error_noise_enum = {
1131 	.items = quad8_noise_error_states,
1132 	.num_items = ARRAY_SIZE(quad8_noise_error_states),
1133 	.get = quad8_error_noise_get
1134 };
1135 
1136 static ssize_t quad8_count_preset_read(struct counter_device *counter,
1137 	struct counter_count *count, void *private, char *buf)
1138 {
1139 	const struct quad8_iio *const priv = counter->priv;
1140 
1141 	return sprintf(buf, "%u\n", priv->preset[count->id]);
1142 }
1143 
1144 static void quad8_preset_register_set(struct quad8_iio *quad8iio, int id,
1145 		unsigned int preset)
1146 {
1147 	const unsigned int base_offset = quad8iio->base + 2 * id;
1148 	int i;
1149 
1150 	quad8iio->preset[id] = preset;
1151 
1152 	/* Reset Byte Pointer */
1153 	outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
1154 
1155 	/* Set Preset Register */
1156 	for (i = 0; i < 3; i++)
1157 		outb(preset >> (8 * i), base_offset);
1158 }
1159 
1160 static ssize_t quad8_count_preset_write(struct counter_device *counter,
1161 	struct counter_count *count, void *private, const char *buf, size_t len)
1162 {
1163 	struct quad8_iio *const priv = counter->priv;
1164 	unsigned int preset;
1165 	int ret;
1166 
1167 	ret = kstrtouint(buf, 0, &preset);
1168 	if (ret)
1169 		return ret;
1170 
1171 	/* Only 24-bit values are supported */
1172 	if (preset > 0xFFFFFF)
1173 		return -EINVAL;
1174 
1175 	mutex_lock(&priv->lock);
1176 
1177 	quad8_preset_register_set(priv, count->id, preset);
1178 
1179 	mutex_unlock(&priv->lock);
1180 
1181 	return len;
1182 }
1183 
1184 static ssize_t quad8_count_ceiling_read(struct counter_device *counter,
1185 	struct counter_count *count, void *private, char *buf)
1186 {
1187 	struct quad8_iio *const priv = counter->priv;
1188 
1189 	mutex_lock(&priv->lock);
1190 
1191 	/* Range Limit and Modulo-N count modes use preset value as ceiling */
1192 	switch (priv->count_mode[count->id]) {
1193 	case 1:
1194 	case 3:
1195 		mutex_unlock(&priv->lock);
1196 		return sprintf(buf, "%u\n", priv->preset[count->id]);
1197 	}
1198 
1199 	mutex_unlock(&priv->lock);
1200 
1201 	/* By default 0x1FFFFFF (25 bits unsigned) is maximum count */
1202 	return sprintf(buf, "33554431\n");
1203 }
1204 
1205 static ssize_t quad8_count_ceiling_write(struct counter_device *counter,
1206 	struct counter_count *count, void *private, const char *buf, size_t len)
1207 {
1208 	struct quad8_iio *const priv = counter->priv;
1209 	unsigned int ceiling;
1210 	int ret;
1211 
1212 	ret = kstrtouint(buf, 0, &ceiling);
1213 	if (ret)
1214 		return ret;
1215 
1216 	/* Only 24-bit values are supported */
1217 	if (ceiling > 0xFFFFFF)
1218 		return -EINVAL;
1219 
1220 	mutex_lock(&priv->lock);
1221 
1222 	/* Range Limit and Modulo-N count modes use preset value as ceiling */
1223 	switch (priv->count_mode[count->id]) {
1224 	case 1:
1225 	case 3:
1226 		quad8_preset_register_set(priv, count->id, ceiling);
1227 		break;
1228 	}
1229 
1230 	mutex_unlock(&priv->lock);
1231 
1232 	return len;
1233 }
1234 
1235 static ssize_t quad8_count_preset_enable_read(struct counter_device *counter,
1236 	struct counter_count *count, void *private, char *buf)
1237 {
1238 	const struct quad8_iio *const priv = counter->priv;
1239 
1240 	return sprintf(buf, "%u\n", !priv->preset_enable[count->id]);
1241 }
1242 
1243 static ssize_t quad8_count_preset_enable_write(struct counter_device *counter,
1244 	struct counter_count *count, void *private, const char *buf, size_t len)
1245 {
1246 	struct quad8_iio *const priv = counter->priv;
1247 	const int base_offset = priv->base + 2 * count->id + 1;
1248 	bool preset_enable;
1249 	int ret;
1250 	unsigned int ior_cfg;
1251 
1252 	ret = kstrtobool(buf, &preset_enable);
1253 	if (ret)
1254 		return ret;
1255 
1256 	/* Preset enable is active low in Input/Output Control register */
1257 	preset_enable = !preset_enable;
1258 
1259 	mutex_lock(&priv->lock);
1260 
1261 	priv->preset_enable[count->id] = preset_enable;
1262 
1263 	ior_cfg = priv->ab_enable[count->id] | (unsigned int)preset_enable << 1;
1264 
1265 	/* Load I/O control configuration to Input / Output Control Register */
1266 	outb(QUAD8_CTR_IOR | ior_cfg, base_offset);
1267 
1268 	mutex_unlock(&priv->lock);
1269 
1270 	return len;
1271 }
1272 
1273 static ssize_t quad8_signal_cable_fault_read(struct counter_device *counter,
1274 					     struct counter_signal *signal,
1275 					     void *private, char *buf)
1276 {
1277 	const struct quad8_iio *const priv = counter->priv;
1278 	const size_t channel_id = signal->id / 2;
1279 	const bool disabled = !(priv->cable_fault_enable & BIT(channel_id));
1280 	unsigned int status;
1281 	unsigned int fault;
1282 
1283 	if (disabled)
1284 		return -EINVAL;
1285 
1286 	/* Logic 0 = cable fault */
1287 	status = inb(priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
1288 
1289 	/* Mask respective channel and invert logic */
1290 	fault = !(status & BIT(channel_id));
1291 
1292 	return sprintf(buf, "%u\n", fault);
1293 }
1294 
1295 static ssize_t quad8_signal_cable_fault_enable_read(
1296 	struct counter_device *counter, struct counter_signal *signal,
1297 	void *private, char *buf)
1298 {
1299 	const struct quad8_iio *const priv = counter->priv;
1300 	const size_t channel_id = signal->id / 2;
1301 	const unsigned int enb = !!(priv->cable_fault_enable & BIT(channel_id));
1302 
1303 	return sprintf(buf, "%u\n", enb);
1304 }
1305 
1306 static ssize_t quad8_signal_cable_fault_enable_write(
1307 	struct counter_device *counter, struct counter_signal *signal,
1308 	void *private, const char *buf, size_t len)
1309 {
1310 	struct quad8_iio *const priv = counter->priv;
1311 	const size_t channel_id = signal->id / 2;
1312 	bool enable;
1313 	int ret;
1314 	unsigned int cable_fault_enable;
1315 
1316 	ret = kstrtobool(buf, &enable);
1317 	if (ret)
1318 		return ret;
1319 
1320 	if (enable)
1321 		priv->cable_fault_enable |= BIT(channel_id);
1322 	else
1323 		priv->cable_fault_enable &= ~BIT(channel_id);
1324 
1325 	/* Enable is active low in Differential Encoder Cable Status register */
1326 	cable_fault_enable = ~priv->cable_fault_enable;
1327 
1328 	outb(cable_fault_enable, priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
1329 
1330 	return len;
1331 }
1332 
1333 static ssize_t quad8_signal_fck_prescaler_read(struct counter_device *counter,
1334 	struct counter_signal *signal, void *private, char *buf)
1335 {
1336 	const struct quad8_iio *const priv = counter->priv;
1337 	const size_t channel_id = signal->id / 2;
1338 
1339 	return sprintf(buf, "%u\n", priv->fck_prescaler[channel_id]);
1340 }
1341 
1342 static ssize_t quad8_signal_fck_prescaler_write(struct counter_device *counter,
1343 	struct counter_signal *signal, void *private, const char *buf,
1344 	size_t len)
1345 {
1346 	struct quad8_iio *const priv = counter->priv;
1347 	const size_t channel_id = signal->id / 2;
1348 	const int base_offset = priv->base + 2 * channel_id;
1349 	u8 prescaler;
1350 	int ret;
1351 
1352 	ret = kstrtou8(buf, 0, &prescaler);
1353 	if (ret)
1354 		return ret;
1355 
1356 	priv->fck_prescaler[channel_id] = prescaler;
1357 
1358 	/* Reset Byte Pointer */
1359 	outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
1360 
1361 	/* Set filter clock factor */
1362 	outb(prescaler, base_offset);
1363 	outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
1364 	     base_offset + 1);
1365 
1366 	return len;
1367 }
1368 
1369 static const struct counter_signal_ext quad8_signal_ext[] = {
1370 	{
1371 		.name = "cable_fault",
1372 		.read = quad8_signal_cable_fault_read
1373 	},
1374 	{
1375 		.name = "cable_fault_enable",
1376 		.read = quad8_signal_cable_fault_enable_read,
1377 		.write = quad8_signal_cable_fault_enable_write
1378 	},
1379 	{
1380 		.name = "filter_clock_prescaler",
1381 		.read = quad8_signal_fck_prescaler_read,
1382 		.write = quad8_signal_fck_prescaler_write
1383 	}
1384 };
1385 
1386 static const struct counter_signal_ext quad8_index_ext[] = {
1387 	COUNTER_SIGNAL_ENUM("index_polarity", &quad8_index_pol_enum),
1388 	COUNTER_SIGNAL_ENUM_AVAILABLE("index_polarity",	&quad8_index_pol_enum),
1389 	COUNTER_SIGNAL_ENUM("synchronous_mode", &quad8_syn_mode_enum),
1390 	COUNTER_SIGNAL_ENUM_AVAILABLE("synchronous_mode", &quad8_syn_mode_enum)
1391 };
1392 
1393 #define QUAD8_QUAD_SIGNAL(_id, _name) {		\
1394 	.id = (_id),				\
1395 	.name = (_name),			\
1396 	.ext = quad8_signal_ext,		\
1397 	.num_ext = ARRAY_SIZE(quad8_signal_ext)	\
1398 }
1399 
1400 #define	QUAD8_INDEX_SIGNAL(_id, _name) {	\
1401 	.id = (_id),				\
1402 	.name = (_name),			\
1403 	.ext = quad8_index_ext,			\
1404 	.num_ext = ARRAY_SIZE(quad8_index_ext)	\
1405 }
1406 
1407 static struct counter_signal quad8_signals[] = {
1408 	QUAD8_QUAD_SIGNAL(0, "Channel 1 Quadrature A"),
1409 	QUAD8_QUAD_SIGNAL(1, "Channel 1 Quadrature B"),
1410 	QUAD8_QUAD_SIGNAL(2, "Channel 2 Quadrature A"),
1411 	QUAD8_QUAD_SIGNAL(3, "Channel 2 Quadrature B"),
1412 	QUAD8_QUAD_SIGNAL(4, "Channel 3 Quadrature A"),
1413 	QUAD8_QUAD_SIGNAL(5, "Channel 3 Quadrature B"),
1414 	QUAD8_QUAD_SIGNAL(6, "Channel 4 Quadrature A"),
1415 	QUAD8_QUAD_SIGNAL(7, "Channel 4 Quadrature B"),
1416 	QUAD8_QUAD_SIGNAL(8, "Channel 5 Quadrature A"),
1417 	QUAD8_QUAD_SIGNAL(9, "Channel 5 Quadrature B"),
1418 	QUAD8_QUAD_SIGNAL(10, "Channel 6 Quadrature A"),
1419 	QUAD8_QUAD_SIGNAL(11, "Channel 6 Quadrature B"),
1420 	QUAD8_QUAD_SIGNAL(12, "Channel 7 Quadrature A"),
1421 	QUAD8_QUAD_SIGNAL(13, "Channel 7 Quadrature B"),
1422 	QUAD8_QUAD_SIGNAL(14, "Channel 8 Quadrature A"),
1423 	QUAD8_QUAD_SIGNAL(15, "Channel 8 Quadrature B"),
1424 	QUAD8_INDEX_SIGNAL(16, "Channel 1 Index"),
1425 	QUAD8_INDEX_SIGNAL(17, "Channel 2 Index"),
1426 	QUAD8_INDEX_SIGNAL(18, "Channel 3 Index"),
1427 	QUAD8_INDEX_SIGNAL(19, "Channel 4 Index"),
1428 	QUAD8_INDEX_SIGNAL(20, "Channel 5 Index"),
1429 	QUAD8_INDEX_SIGNAL(21, "Channel 6 Index"),
1430 	QUAD8_INDEX_SIGNAL(22, "Channel 7 Index"),
1431 	QUAD8_INDEX_SIGNAL(23, "Channel 8 Index")
1432 };
1433 
1434 #define QUAD8_COUNT_SYNAPSES(_id) {					\
1435 	{								\
1436 		.actions_list = quad8_synapse_actions_list,		\
1437 		.num_actions = ARRAY_SIZE(quad8_synapse_actions_list),	\
1438 		.signal = quad8_signals + 2 * (_id)			\
1439 	},								\
1440 	{								\
1441 		.actions_list = quad8_synapse_actions_list,		\
1442 		.num_actions = ARRAY_SIZE(quad8_synapse_actions_list),	\
1443 		.signal = quad8_signals + 2 * (_id) + 1			\
1444 	},								\
1445 	{								\
1446 		.actions_list = quad8_index_actions_list,		\
1447 		.num_actions = ARRAY_SIZE(quad8_index_actions_list),	\
1448 		.signal = quad8_signals + 2 * (_id) + 16		\
1449 	}								\
1450 }
1451 
1452 static struct counter_synapse quad8_count_synapses[][3] = {
1453 	QUAD8_COUNT_SYNAPSES(0), QUAD8_COUNT_SYNAPSES(1),
1454 	QUAD8_COUNT_SYNAPSES(2), QUAD8_COUNT_SYNAPSES(3),
1455 	QUAD8_COUNT_SYNAPSES(4), QUAD8_COUNT_SYNAPSES(5),
1456 	QUAD8_COUNT_SYNAPSES(6), QUAD8_COUNT_SYNAPSES(7)
1457 };
1458 
1459 static const struct counter_count_ext quad8_count_ext[] = {
1460 	{
1461 		.name = "ceiling",
1462 		.read = quad8_count_ceiling_read,
1463 		.write = quad8_count_ceiling_write
1464 	},
1465 	{
1466 		.name = "floor",
1467 		.read = quad8_count_floor_read
1468 	},
1469 	COUNTER_COUNT_ENUM("count_mode", &quad8_cnt_mode_enum),
1470 	COUNTER_COUNT_ENUM_AVAILABLE("count_mode", &quad8_cnt_mode_enum),
1471 	{
1472 		.name = "direction",
1473 		.read = quad8_count_direction_read
1474 	},
1475 	{
1476 		.name = "enable",
1477 		.read = quad8_count_enable_read,
1478 		.write = quad8_count_enable_write
1479 	},
1480 	COUNTER_COUNT_ENUM("error_noise", &quad8_error_noise_enum),
1481 	COUNTER_COUNT_ENUM_AVAILABLE("error_noise", &quad8_error_noise_enum),
1482 	{
1483 		.name = "preset",
1484 		.read = quad8_count_preset_read,
1485 		.write = quad8_count_preset_write
1486 	},
1487 	{
1488 		.name = "preset_enable",
1489 		.read = quad8_count_preset_enable_read,
1490 		.write = quad8_count_preset_enable_write
1491 	}
1492 };
1493 
1494 #define QUAD8_COUNT(_id, _cntname) {					\
1495 	.id = (_id),							\
1496 	.name = (_cntname),						\
1497 	.functions_list = quad8_count_functions_list,			\
1498 	.num_functions = ARRAY_SIZE(quad8_count_functions_list),	\
1499 	.synapses = quad8_count_synapses[(_id)],			\
1500 	.num_synapses =	2,						\
1501 	.ext = quad8_count_ext,						\
1502 	.num_ext = ARRAY_SIZE(quad8_count_ext)				\
1503 }
1504 
1505 static struct counter_count quad8_counts[] = {
1506 	QUAD8_COUNT(0, "Channel 1 Count"),
1507 	QUAD8_COUNT(1, "Channel 2 Count"),
1508 	QUAD8_COUNT(2, "Channel 3 Count"),
1509 	QUAD8_COUNT(3, "Channel 4 Count"),
1510 	QUAD8_COUNT(4, "Channel 5 Count"),
1511 	QUAD8_COUNT(5, "Channel 6 Count"),
1512 	QUAD8_COUNT(6, "Channel 7 Count"),
1513 	QUAD8_COUNT(7, "Channel 8 Count")
1514 };
1515 
1516 static int quad8_probe(struct device *dev, unsigned int id)
1517 {
1518 	struct iio_dev *indio_dev;
1519 	struct quad8_iio *quad8iio;
1520 	int i, j;
1521 	unsigned int base_offset;
1522 	int err;
1523 
1524 	if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) {
1525 		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
1526 			base[id], base[id] + QUAD8_EXTENT);
1527 		return -EBUSY;
1528 	}
1529 
1530 	/* Allocate IIO device; this also allocates driver data structure */
1531 	indio_dev = devm_iio_device_alloc(dev, sizeof(*quad8iio));
1532 	if (!indio_dev)
1533 		return -ENOMEM;
1534 
1535 	/* Initialize IIO device */
1536 	indio_dev->info = &quad8_info;
1537 	indio_dev->modes = INDIO_DIRECT_MODE;
1538 	indio_dev->num_channels = ARRAY_SIZE(quad8_channels);
1539 	indio_dev->channels = quad8_channels;
1540 	indio_dev->name = dev_name(dev);
1541 	indio_dev->dev.parent = dev;
1542 
1543 	/* Initialize Counter device and driver data */
1544 	quad8iio = iio_priv(indio_dev);
1545 	quad8iio->counter.name = dev_name(dev);
1546 	quad8iio->counter.parent = dev;
1547 	quad8iio->counter.ops = &quad8_ops;
1548 	quad8iio->counter.counts = quad8_counts;
1549 	quad8iio->counter.num_counts = ARRAY_SIZE(quad8_counts);
1550 	quad8iio->counter.signals = quad8_signals;
1551 	quad8iio->counter.num_signals = ARRAY_SIZE(quad8_signals);
1552 	quad8iio->counter.priv = quad8iio;
1553 	quad8iio->base = base[id];
1554 
1555 	/* Initialize mutex */
1556 	mutex_init(&quad8iio->lock);
1557 
1558 	/* Reset all counters and disable interrupt function */
1559 	outb(QUAD8_CHAN_OP_RESET_COUNTERS, base[id] + QUAD8_REG_CHAN_OP);
1560 	/* Set initial configuration for all counters */
1561 	for (i = 0; i < QUAD8_NUM_COUNTERS; i++) {
1562 		base_offset = base[id] + 2 * i;
1563 		/* Reset Byte Pointer */
1564 		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
1565 		/* Reset filter clock factor */
1566 		outb(0, base_offset);
1567 		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
1568 		     base_offset + 1);
1569 		/* Reset Byte Pointer */
1570 		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
1571 		/* Reset Preset Register */
1572 		for (j = 0; j < 3; j++)
1573 			outb(0x00, base_offset);
1574 		/* Reset Borrow, Carry, Compare, and Sign flags */
1575 		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1);
1576 		/* Reset Error flag */
1577 		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
1578 		/* Binary encoding; Normal count; non-quadrature mode */
1579 		outb(QUAD8_CTR_CMR, base_offset + 1);
1580 		/* Disable A and B inputs; preset on index; FLG1 as Carry */
1581 		outb(QUAD8_CTR_IOR, base_offset + 1);
1582 		/* Disable index function; negative index polarity */
1583 		outb(QUAD8_CTR_IDR, base_offset + 1);
1584 	}
1585 	/* Disable Differential Encoder Cable Status for all channels */
1586 	outb(0xFF, base[id] + QUAD8_DIFF_ENCODER_CABLE_STATUS);
1587 	/* Enable all counters */
1588 	outb(QUAD8_CHAN_OP_ENABLE_COUNTERS, base[id] + QUAD8_REG_CHAN_OP);
1589 
1590 	/* Register IIO device */
1591 	err = devm_iio_device_register(dev, indio_dev);
1592 	if (err)
1593 		return err;
1594 
1595 	/* Register Counter device */
1596 	return devm_counter_register(dev, &quad8iio->counter);
1597 }
1598 
1599 static struct isa_driver quad8_driver = {
1600 	.probe = quad8_probe,
1601 	.driver = {
1602 		.name = "104-quad-8"
1603 	}
1604 };
1605 
1606 module_isa_driver(quad8_driver, num_quad8);
1607 
1608 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
1609 MODULE_DESCRIPTION("ACCES 104-QUAD-8 IIO driver");
1610 MODULE_LICENSE("GPL v2");
1611