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