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