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