Merge tag 'gfs2-for-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux...
[linux-2.6-microblaze.git] / drivers / counter / 104-quad-8.c
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         struct quad8_iio *const priv = counter->priv;
1278         const size_t channel_id = signal->id / 2;
1279         bool disabled;
1280         unsigned int status;
1281         unsigned int fault;
1282
1283         mutex_lock(&priv->lock);
1284
1285         disabled = !(priv->cable_fault_enable & BIT(channel_id));
1286
1287         if (disabled) {
1288                 mutex_unlock(&priv->lock);
1289                 return -EINVAL;
1290         }
1291
1292         /* Logic 0 = cable fault */
1293         status = inb(priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
1294
1295         mutex_unlock(&priv->lock);
1296
1297         /* Mask respective channel and invert logic */
1298         fault = !(status & BIT(channel_id));
1299
1300         return sprintf(buf, "%u\n", fault);
1301 }
1302
1303 static ssize_t quad8_signal_cable_fault_enable_read(
1304         struct counter_device *counter, struct counter_signal *signal,
1305         void *private, char *buf)
1306 {
1307         const struct quad8_iio *const priv = counter->priv;
1308         const size_t channel_id = signal->id / 2;
1309         const unsigned int enb = !!(priv->cable_fault_enable & BIT(channel_id));
1310
1311         return sprintf(buf, "%u\n", enb);
1312 }
1313
1314 static ssize_t quad8_signal_cable_fault_enable_write(
1315         struct counter_device *counter, struct counter_signal *signal,
1316         void *private, const char *buf, size_t len)
1317 {
1318         struct quad8_iio *const priv = counter->priv;
1319         const size_t channel_id = signal->id / 2;
1320         bool enable;
1321         int ret;
1322         unsigned int cable_fault_enable;
1323
1324         ret = kstrtobool(buf, &enable);
1325         if (ret)
1326                 return ret;
1327
1328         mutex_lock(&priv->lock);
1329
1330         if (enable)
1331                 priv->cable_fault_enable |= BIT(channel_id);
1332         else
1333                 priv->cable_fault_enable &= ~BIT(channel_id);
1334
1335         /* Enable is active low in Differential Encoder Cable Status register */
1336         cable_fault_enable = ~priv->cable_fault_enable;
1337
1338         outb(cable_fault_enable, priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
1339
1340         mutex_unlock(&priv->lock);
1341
1342         return len;
1343 }
1344
1345 static ssize_t quad8_signal_fck_prescaler_read(struct counter_device *counter,
1346         struct counter_signal *signal, void *private, char *buf)
1347 {
1348         const struct quad8_iio *const priv = counter->priv;
1349         const size_t channel_id = signal->id / 2;
1350
1351         return sprintf(buf, "%u\n", priv->fck_prescaler[channel_id]);
1352 }
1353
1354 static ssize_t quad8_signal_fck_prescaler_write(struct counter_device *counter,
1355         struct counter_signal *signal, void *private, const char *buf,
1356         size_t len)
1357 {
1358         struct quad8_iio *const priv = counter->priv;
1359         const size_t channel_id = signal->id / 2;
1360         const int base_offset = priv->base + 2 * channel_id;
1361         u8 prescaler;
1362         int ret;
1363
1364         ret = kstrtou8(buf, 0, &prescaler);
1365         if (ret)
1366                 return ret;
1367
1368         mutex_lock(&priv->lock);
1369
1370         priv->fck_prescaler[channel_id] = prescaler;
1371
1372         /* Reset Byte Pointer */
1373         outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
1374
1375         /* Set filter clock factor */
1376         outb(prescaler, base_offset);
1377         outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
1378              base_offset + 1);
1379
1380         mutex_unlock(&priv->lock);
1381
1382         return len;
1383 }
1384
1385 static const struct counter_signal_ext quad8_signal_ext[] = {
1386         {
1387                 .name = "cable_fault",
1388                 .read = quad8_signal_cable_fault_read
1389         },
1390         {
1391                 .name = "cable_fault_enable",
1392                 .read = quad8_signal_cable_fault_enable_read,
1393                 .write = quad8_signal_cable_fault_enable_write
1394         },
1395         {
1396                 .name = "filter_clock_prescaler",
1397                 .read = quad8_signal_fck_prescaler_read,
1398                 .write = quad8_signal_fck_prescaler_write
1399         }
1400 };
1401
1402 static const struct counter_signal_ext quad8_index_ext[] = {
1403         COUNTER_SIGNAL_ENUM("index_polarity", &quad8_index_pol_enum),
1404         COUNTER_SIGNAL_ENUM_AVAILABLE("index_polarity", &quad8_index_pol_enum),
1405         COUNTER_SIGNAL_ENUM("synchronous_mode", &quad8_syn_mode_enum),
1406         COUNTER_SIGNAL_ENUM_AVAILABLE("synchronous_mode", &quad8_syn_mode_enum)
1407 };
1408
1409 #define QUAD8_QUAD_SIGNAL(_id, _name) {         \
1410         .id = (_id),                            \
1411         .name = (_name),                        \
1412         .ext = quad8_signal_ext,                \
1413         .num_ext = ARRAY_SIZE(quad8_signal_ext) \
1414 }
1415
1416 #define QUAD8_INDEX_SIGNAL(_id, _name) {        \
1417         .id = (_id),                            \
1418         .name = (_name),                        \
1419         .ext = quad8_index_ext,                 \
1420         .num_ext = ARRAY_SIZE(quad8_index_ext)  \
1421 }
1422
1423 static struct counter_signal quad8_signals[] = {
1424         QUAD8_QUAD_SIGNAL(0, "Channel 1 Quadrature A"),
1425         QUAD8_QUAD_SIGNAL(1, "Channel 1 Quadrature B"),
1426         QUAD8_QUAD_SIGNAL(2, "Channel 2 Quadrature A"),
1427         QUAD8_QUAD_SIGNAL(3, "Channel 2 Quadrature B"),
1428         QUAD8_QUAD_SIGNAL(4, "Channel 3 Quadrature A"),
1429         QUAD8_QUAD_SIGNAL(5, "Channel 3 Quadrature B"),
1430         QUAD8_QUAD_SIGNAL(6, "Channel 4 Quadrature A"),
1431         QUAD8_QUAD_SIGNAL(7, "Channel 4 Quadrature B"),
1432         QUAD8_QUAD_SIGNAL(8, "Channel 5 Quadrature A"),
1433         QUAD8_QUAD_SIGNAL(9, "Channel 5 Quadrature B"),
1434         QUAD8_QUAD_SIGNAL(10, "Channel 6 Quadrature A"),
1435         QUAD8_QUAD_SIGNAL(11, "Channel 6 Quadrature B"),
1436         QUAD8_QUAD_SIGNAL(12, "Channel 7 Quadrature A"),
1437         QUAD8_QUAD_SIGNAL(13, "Channel 7 Quadrature B"),
1438         QUAD8_QUAD_SIGNAL(14, "Channel 8 Quadrature A"),
1439         QUAD8_QUAD_SIGNAL(15, "Channel 8 Quadrature B"),
1440         QUAD8_INDEX_SIGNAL(16, "Channel 1 Index"),
1441         QUAD8_INDEX_SIGNAL(17, "Channel 2 Index"),
1442         QUAD8_INDEX_SIGNAL(18, "Channel 3 Index"),
1443         QUAD8_INDEX_SIGNAL(19, "Channel 4 Index"),
1444         QUAD8_INDEX_SIGNAL(20, "Channel 5 Index"),
1445         QUAD8_INDEX_SIGNAL(21, "Channel 6 Index"),
1446         QUAD8_INDEX_SIGNAL(22, "Channel 7 Index"),
1447         QUAD8_INDEX_SIGNAL(23, "Channel 8 Index")
1448 };
1449
1450 #define QUAD8_COUNT_SYNAPSES(_id) {                                     \
1451         {                                                               \
1452                 .actions_list = quad8_synapse_actions_list,             \
1453                 .num_actions = ARRAY_SIZE(quad8_synapse_actions_list),  \
1454                 .signal = quad8_signals + 2 * (_id)                     \
1455         },                                                              \
1456         {                                                               \
1457                 .actions_list = quad8_synapse_actions_list,             \
1458                 .num_actions = ARRAY_SIZE(quad8_synapse_actions_list),  \
1459                 .signal = quad8_signals + 2 * (_id) + 1                 \
1460         },                                                              \
1461         {                                                               \
1462                 .actions_list = quad8_index_actions_list,               \
1463                 .num_actions = ARRAY_SIZE(quad8_index_actions_list),    \
1464                 .signal = quad8_signals + 2 * (_id) + 16                \
1465         }                                                               \
1466 }
1467
1468 static struct counter_synapse quad8_count_synapses[][3] = {
1469         QUAD8_COUNT_SYNAPSES(0), QUAD8_COUNT_SYNAPSES(1),
1470         QUAD8_COUNT_SYNAPSES(2), QUAD8_COUNT_SYNAPSES(3),
1471         QUAD8_COUNT_SYNAPSES(4), QUAD8_COUNT_SYNAPSES(5),
1472         QUAD8_COUNT_SYNAPSES(6), QUAD8_COUNT_SYNAPSES(7)
1473 };
1474
1475 static const struct counter_count_ext quad8_count_ext[] = {
1476         {
1477                 .name = "ceiling",
1478                 .read = quad8_count_ceiling_read,
1479                 .write = quad8_count_ceiling_write
1480         },
1481         {
1482                 .name = "floor",
1483                 .read = quad8_count_floor_read
1484         },
1485         COUNTER_COUNT_ENUM("count_mode", &quad8_cnt_mode_enum),
1486         COUNTER_COUNT_ENUM_AVAILABLE("count_mode", &quad8_cnt_mode_enum),
1487         {
1488                 .name = "direction",
1489                 .read = quad8_count_direction_read
1490         },
1491         {
1492                 .name = "enable",
1493                 .read = quad8_count_enable_read,
1494                 .write = quad8_count_enable_write
1495         },
1496         COUNTER_COUNT_ENUM("error_noise", &quad8_error_noise_enum),
1497         COUNTER_COUNT_ENUM_AVAILABLE("error_noise", &quad8_error_noise_enum),
1498         {
1499                 .name = "preset",
1500                 .read = quad8_count_preset_read,
1501                 .write = quad8_count_preset_write
1502         },
1503         {
1504                 .name = "preset_enable",
1505                 .read = quad8_count_preset_enable_read,
1506                 .write = quad8_count_preset_enable_write
1507         }
1508 };
1509
1510 #define QUAD8_COUNT(_id, _cntname) {                                    \
1511         .id = (_id),                                                    \
1512         .name = (_cntname),                                             \
1513         .functions_list = quad8_count_functions_list,                   \
1514         .num_functions = ARRAY_SIZE(quad8_count_functions_list),        \
1515         .synapses = quad8_count_synapses[(_id)],                        \
1516         .num_synapses = 2,                                              \
1517         .ext = quad8_count_ext,                                         \
1518         .num_ext = ARRAY_SIZE(quad8_count_ext)                          \
1519 }
1520
1521 static struct counter_count quad8_counts[] = {
1522         QUAD8_COUNT(0, "Channel 1 Count"),
1523         QUAD8_COUNT(1, "Channel 2 Count"),
1524         QUAD8_COUNT(2, "Channel 3 Count"),
1525         QUAD8_COUNT(3, "Channel 4 Count"),
1526         QUAD8_COUNT(4, "Channel 5 Count"),
1527         QUAD8_COUNT(5, "Channel 6 Count"),
1528         QUAD8_COUNT(6, "Channel 7 Count"),
1529         QUAD8_COUNT(7, "Channel 8 Count")
1530 };
1531
1532 static int quad8_probe(struct device *dev, unsigned int id)
1533 {
1534         struct iio_dev *indio_dev;
1535         struct quad8_iio *quad8iio;
1536         int i, j;
1537         unsigned int base_offset;
1538         int err;
1539
1540         if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) {
1541                 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
1542                         base[id], base[id] + QUAD8_EXTENT);
1543                 return -EBUSY;
1544         }
1545
1546         /* Allocate IIO device; this also allocates driver data structure */
1547         indio_dev = devm_iio_device_alloc(dev, sizeof(*quad8iio));
1548         if (!indio_dev)
1549                 return -ENOMEM;
1550
1551         /* Initialize IIO device */
1552         indio_dev->info = &quad8_info;
1553         indio_dev->modes = INDIO_DIRECT_MODE;
1554         indio_dev->num_channels = ARRAY_SIZE(quad8_channels);
1555         indio_dev->channels = quad8_channels;
1556         indio_dev->name = dev_name(dev);
1557
1558         /* Initialize Counter device and driver data */
1559         quad8iio = iio_priv(indio_dev);
1560         quad8iio->counter.name = dev_name(dev);
1561         quad8iio->counter.parent = dev;
1562         quad8iio->counter.ops = &quad8_ops;
1563         quad8iio->counter.counts = quad8_counts;
1564         quad8iio->counter.num_counts = ARRAY_SIZE(quad8_counts);
1565         quad8iio->counter.signals = quad8_signals;
1566         quad8iio->counter.num_signals = ARRAY_SIZE(quad8_signals);
1567         quad8iio->counter.priv = quad8iio;
1568         quad8iio->base = base[id];
1569
1570         /* Initialize mutex */
1571         mutex_init(&quad8iio->lock);
1572
1573         /* Reset all counters and disable interrupt function */
1574         outb(QUAD8_CHAN_OP_RESET_COUNTERS, base[id] + QUAD8_REG_CHAN_OP);
1575         /* Set initial configuration for all counters */
1576         for (i = 0; i < QUAD8_NUM_COUNTERS; i++) {
1577                 base_offset = base[id] + 2 * i;
1578                 /* Reset Byte Pointer */
1579                 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
1580                 /* Reset filter clock factor */
1581                 outb(0, base_offset);
1582                 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
1583                      base_offset + 1);
1584                 /* Reset Byte Pointer */
1585                 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
1586                 /* Reset Preset Register */
1587                 for (j = 0; j < 3; j++)
1588                         outb(0x00, base_offset);
1589                 /* Reset Borrow, Carry, Compare, and Sign flags */
1590                 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1);
1591                 /* Reset Error flag */
1592                 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
1593                 /* Binary encoding; Normal count; non-quadrature mode */
1594                 outb(QUAD8_CTR_CMR, base_offset + 1);
1595                 /* Disable A and B inputs; preset on index; FLG1 as Carry */
1596                 outb(QUAD8_CTR_IOR, base_offset + 1);
1597                 /* Disable index function; negative index polarity */
1598                 outb(QUAD8_CTR_IDR, base_offset + 1);
1599         }
1600         /* Disable Differential Encoder Cable Status for all channels */
1601         outb(0xFF, base[id] + QUAD8_DIFF_ENCODER_CABLE_STATUS);
1602         /* Enable all counters */
1603         outb(QUAD8_CHAN_OP_ENABLE_COUNTERS, base[id] + QUAD8_REG_CHAN_OP);
1604
1605         /* Register IIO device */
1606         err = devm_iio_device_register(dev, indio_dev);
1607         if (err)
1608                 return err;
1609
1610         /* Register Counter device */
1611         return devm_counter_register(dev, &quad8iio->counter);
1612 }
1613
1614 static struct isa_driver quad8_driver = {
1615         .probe = quad8_probe,
1616         .driver = {
1617                 .name = "104-quad-8"
1618         }
1619 };
1620
1621 module_isa_driver(quad8_driver, num_quad8);
1622
1623 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
1624 MODULE_DESCRIPTION("ACCES 104-QUAD-8 IIO driver");
1625 MODULE_LICENSE("GPL v2");