Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/counter/104-quad-8.c
26278 views
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/bitfield.h>
9
#include <linux/bits.h>
10
#include <linux/counter.h>
11
#include <linux/device.h>
12
#include <linux/err.h>
13
#include <linux/io.h>
14
#include <linux/ioport.h>
15
#include <linux/interrupt.h>
16
#include <linux/isa.h>
17
#include <linux/kernel.h>
18
#include <linux/list.h>
19
#include <linux/module.h>
20
#include <linux/moduleparam.h>
21
#include <linux/regmap.h>
22
#include <linux/spinlock.h>
23
#include <linux/types.h>
24
25
#include <linux/unaligned.h>
26
27
#define QUAD8_EXTENT 32
28
29
static unsigned int base[max_num_isa_dev(QUAD8_EXTENT)];
30
static unsigned int num_quad8;
31
module_param_hw_array(base, uint, ioport, &num_quad8, 0);
32
MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");
33
34
static unsigned int irq[max_num_isa_dev(QUAD8_EXTENT)];
35
static unsigned int num_irq;
36
module_param_hw_array(irq, uint, irq, &num_irq, 0);
37
MODULE_PARM_DESC(irq, "ACCES 104-QUAD-8 interrupt line numbers");
38
39
#define QUAD8_NUM_COUNTERS 8
40
41
#define QUAD8_DATA(_channel) ((_channel) * 2)
42
#define QUAD8_CONTROL(_channel) (QUAD8_DATA(_channel) + 1)
43
#define QUAD8_INTERRUPT_STATUS 0x10
44
#define QUAD8_CHANNEL_OPERATION 0x11
45
#define QUAD8_INDEX_INTERRUPT 0x12
46
#define QUAD8_INDEX_INPUT_LEVELS 0x16
47
#define QUAD8_CABLE_STATUS 0x17
48
49
/**
50
* struct quad8 - device private data structure
51
* @lock: lock to prevent clobbering device states during R/W ops
52
* @cmr: array of Counter Mode Register states
53
* @ior: array of Input / Output Control Register states
54
* @idr: array of Index Control Register states
55
* @fck_prescaler: array of filter clock prescaler configurations
56
* @preset: array of preset values
57
* @cable_fault_enable: differential encoder cable status enable configurations
58
* @map: regmap for the device
59
*/
60
struct quad8 {
61
spinlock_t lock;
62
u8 cmr[QUAD8_NUM_COUNTERS];
63
u8 ior[QUAD8_NUM_COUNTERS];
64
u8 idr[QUAD8_NUM_COUNTERS];
65
unsigned int fck_prescaler[QUAD8_NUM_COUNTERS];
66
unsigned int preset[QUAD8_NUM_COUNTERS];
67
unsigned int cable_fault_enable;
68
struct regmap *map;
69
};
70
71
static const struct regmap_range quad8_wr_ranges[] = {
72
regmap_reg_range(0x0, 0xF), regmap_reg_range(0x11, 0x12), regmap_reg_range(0x17, 0x17),
73
};
74
static const struct regmap_range quad8_rd_ranges[] = {
75
regmap_reg_range(0x0, 0x12), regmap_reg_range(0x16, 0x18),
76
};
77
static const struct regmap_access_table quad8_wr_table = {
78
.yes_ranges = quad8_wr_ranges,
79
.n_yes_ranges = ARRAY_SIZE(quad8_wr_ranges),
80
};
81
static const struct regmap_access_table quad8_rd_table = {
82
.yes_ranges = quad8_rd_ranges,
83
.n_yes_ranges = ARRAY_SIZE(quad8_rd_ranges),
84
};
85
static const struct regmap_config quad8_regmap_config = {
86
.reg_bits = 8,
87
.reg_stride = 1,
88
.val_bits = 8,
89
.io_port = true,
90
.wr_table = &quad8_wr_table,
91
.rd_table = &quad8_rd_table,
92
};
93
94
/* Error flag */
95
#define FLAG_E BIT(4)
96
/* Up/Down flag */
97
#define FLAG_UD BIT(5)
98
/* Counting up */
99
#define UP 0x1
100
101
#define REGISTER_SELECTION GENMASK(6, 5)
102
103
/* Reset and Load Signal Decoders */
104
#define SELECT_RLD u8_encode_bits(0x0, REGISTER_SELECTION)
105
/* Counter Mode Register */
106
#define SELECT_CMR u8_encode_bits(0x1, REGISTER_SELECTION)
107
/* Input / Output Control Register */
108
#define SELECT_IOR u8_encode_bits(0x2, REGISTER_SELECTION)
109
/* Index Control Register */
110
#define SELECT_IDR u8_encode_bits(0x3, REGISTER_SELECTION)
111
112
/*
113
* Reset and Load Signal Decoders
114
*/
115
#define RESETS GENMASK(2, 1)
116
#define LOADS GENMASK(4, 3)
117
/* Reset Byte Pointer (three byte data pointer) */
118
#define RESET_BP BIT(0)
119
/* Reset Borrow Toggle, Carry toggle, Compare toggle, Sign, and Index flags */
120
#define RESET_BT_CT_CPT_S_IDX u8_encode_bits(0x2, RESETS)
121
/* Reset Error flag */
122
#define RESET_E u8_encode_bits(0x3, RESETS)
123
/* Preset Register to Counter */
124
#define TRANSFER_PR_TO_CNTR u8_encode_bits(0x1, LOADS)
125
/* Transfer Counter to Output Latch */
126
#define TRANSFER_CNTR_TO_OL u8_encode_bits(0x2, LOADS)
127
/* Transfer Preset Register LSB to FCK Prescaler */
128
#define TRANSFER_PR0_TO_PSC u8_encode_bits(0x3, LOADS)
129
130
/*
131
* Counter Mode Registers
132
*/
133
#define COUNT_ENCODING BIT(0)
134
#define COUNT_MODE GENMASK(2, 1)
135
#define QUADRATURE_MODE GENMASK(4, 3)
136
/* Binary count */
137
#define BINARY u8_encode_bits(0x0, COUNT_ENCODING)
138
/* Normal count */
139
#define NORMAL_COUNT 0x0
140
/* Range Limit */
141
#define RANGE_LIMIT 0x1
142
/* Non-recycle count */
143
#define NON_RECYCLE_COUNT 0x2
144
/* Modulo-N */
145
#define MODULO_N 0x3
146
/* Non-quadrature */
147
#define NON_QUADRATURE 0x0
148
/* Quadrature X1 */
149
#define QUADRATURE_X1 0x1
150
/* Quadrature X2 */
151
#define QUADRATURE_X2 0x2
152
/* Quadrature X4 */
153
#define QUADRATURE_X4 0x3
154
155
/*
156
* Input/Output Control Register
157
*/
158
#define AB_GATE BIT(0)
159
#define LOAD_PIN BIT(1)
160
#define FLG_PINS GENMASK(4, 3)
161
/* Disable inputs A and B */
162
#define DISABLE_AB u8_encode_bits(0x0, AB_GATE)
163
/* Load Counter input */
164
#define LOAD_CNTR 0x0
165
/* FLG1 = CARRY(active low); FLG2 = BORROW(active low) */
166
#define FLG1_CARRY_FLG2_BORROW 0x0
167
/* FLG1 = COMPARE(active low); FLG2 = BORROW(active low) */
168
#define FLG1_COMPARE_FLG2_BORROW 0x1
169
/* FLG1 = Carry(active low)/Borrow(active low); FLG2 = U/D(active low) flag */
170
#define FLG1_CARRYBORROW_FLG2_UD 0x2
171
/* FLG1 = INDX (low pulse at INDEX pin active level); FLG2 = E flag */
172
#define FLG1_INDX_FLG2_E 0x3
173
174
/*
175
* INDEX CONTROL REGISTERS
176
*/
177
#define INDEX_MODE BIT(0)
178
#define INDEX_POLARITY BIT(1)
179
/* Disable Index mode */
180
#define DISABLE_INDEX_MODE 0x0
181
/* Enable Index mode */
182
#define ENABLE_INDEX_MODE 0x1
183
/* Negative Index Polarity */
184
#define NEGATIVE_INDEX_POLARITY 0x0
185
/* Positive Index Polarity */
186
#define POSITIVE_INDEX_POLARITY 0x1
187
188
/*
189
* Channel Operation Register
190
*/
191
#define COUNTERS_OPERATION BIT(0)
192
#define INTERRUPT_FUNCTION BIT(2)
193
/* Enable all Counters */
194
#define ENABLE_COUNTERS u8_encode_bits(0x0, COUNTERS_OPERATION)
195
/* Reset all Counters */
196
#define RESET_COUNTERS u8_encode_bits(0x1, COUNTERS_OPERATION)
197
/* Disable the interrupt function */
198
#define DISABLE_INTERRUPT_FUNCTION u8_encode_bits(0x0, INTERRUPT_FUNCTION)
199
/* Enable the interrupt function */
200
#define ENABLE_INTERRUPT_FUNCTION u8_encode_bits(0x1, INTERRUPT_FUNCTION)
201
/* Any write to the Channel Operation register clears any pending interrupts */
202
#define CLEAR_PENDING_INTERRUPTS (ENABLE_COUNTERS | ENABLE_INTERRUPT_FUNCTION)
203
204
/* Each Counter is 24 bits wide */
205
#define LS7267_CNTR_MAX GENMASK(23, 0)
206
207
static __always_inline int quad8_control_register_update(struct regmap *const map, u8 *const buf,
208
const size_t channel, const u8 val,
209
const u8 field)
210
{
211
u8p_replace_bits(&buf[channel], val, field);
212
return regmap_write(map, QUAD8_CONTROL(channel), buf[channel]);
213
}
214
215
static int quad8_signal_read(struct counter_device *counter,
216
struct counter_signal *signal,
217
enum counter_signal_level *level)
218
{
219
const struct quad8 *const priv = counter_priv(counter);
220
int ret;
221
222
/* Only Index signal levels can be read */
223
if (signal->id < 16)
224
return -EINVAL;
225
226
ret = regmap_test_bits(priv->map, QUAD8_INDEX_INPUT_LEVELS, BIT(signal->id - 16));
227
if (ret < 0)
228
return ret;
229
230
*level = (ret) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
231
232
return 0;
233
}
234
235
static int quad8_count_read(struct counter_device *counter,
236
struct counter_count *count, u64 *val)
237
{
238
struct quad8 *const priv = counter_priv(counter);
239
unsigned long irqflags;
240
u8 value[3];
241
int ret;
242
243
spin_lock_irqsave(&priv->lock, irqflags);
244
245
ret = regmap_write(priv->map, QUAD8_CONTROL(count->id),
246
SELECT_RLD | RESET_BP | TRANSFER_CNTR_TO_OL);
247
if (ret)
248
goto exit_unlock;
249
ret = regmap_noinc_read(priv->map, QUAD8_DATA(count->id), value, sizeof(value));
250
251
exit_unlock:
252
spin_unlock_irqrestore(&priv->lock, irqflags);
253
254
*val = get_unaligned_le24(value);
255
256
return ret;
257
}
258
259
static int quad8_preset_register_set(struct quad8 *const priv, const size_t id,
260
const unsigned long preset)
261
{
262
u8 value[3];
263
int ret;
264
265
put_unaligned_le24(preset, value);
266
267
ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BP);
268
if (ret)
269
return ret;
270
return regmap_noinc_write(priv->map, QUAD8_DATA(id), value, sizeof(value));
271
}
272
273
static int quad8_flag_register_reset(struct quad8 *const priv, const size_t id)
274
{
275
int ret;
276
277
ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BT_CT_CPT_S_IDX);
278
if (ret)
279
return ret;
280
return regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_E);
281
}
282
283
static int quad8_count_write(struct counter_device *counter,
284
struct counter_count *count, u64 val)
285
{
286
struct quad8 *const priv = counter_priv(counter);
287
unsigned long irqflags;
288
int ret;
289
290
if (val > LS7267_CNTR_MAX)
291
return -ERANGE;
292
293
spin_lock_irqsave(&priv->lock, irqflags);
294
295
/* Counter can only be set via Preset Register */
296
ret = quad8_preset_register_set(priv, count->id, val);
297
if (ret)
298
goto exit_unlock;
299
ret = regmap_write(priv->map, QUAD8_CONTROL(count->id), SELECT_RLD | TRANSFER_PR_TO_CNTR);
300
if (ret)
301
goto exit_unlock;
302
303
ret = quad8_flag_register_reset(priv, count->id);
304
if (ret)
305
goto exit_unlock;
306
307
/* Set Preset Register back to original value */
308
ret = quad8_preset_register_set(priv, count->id, priv->preset[count->id]);
309
310
exit_unlock:
311
spin_unlock_irqrestore(&priv->lock, irqflags);
312
313
return ret;
314
}
315
316
static const enum counter_function quad8_count_functions_list[] = {
317
COUNTER_FUNCTION_PULSE_DIRECTION,
318
COUNTER_FUNCTION_QUADRATURE_X1_A,
319
COUNTER_FUNCTION_QUADRATURE_X2_A,
320
COUNTER_FUNCTION_QUADRATURE_X4,
321
};
322
323
static int quad8_function_get(const struct quad8 *const priv, const size_t id,
324
enum counter_function *const function)
325
{
326
switch (u8_get_bits(priv->cmr[id], QUADRATURE_MODE)) {
327
case NON_QUADRATURE:
328
*function = COUNTER_FUNCTION_PULSE_DIRECTION;
329
return 0;
330
case QUADRATURE_X1:
331
*function = COUNTER_FUNCTION_QUADRATURE_X1_A;
332
return 0;
333
case QUADRATURE_X2:
334
*function = COUNTER_FUNCTION_QUADRATURE_X2_A;
335
return 0;
336
case QUADRATURE_X4:
337
*function = COUNTER_FUNCTION_QUADRATURE_X4;
338
return 0;
339
default:
340
/* should never reach this path */
341
return -EINVAL;
342
}
343
}
344
345
static int quad8_function_read(struct counter_device *counter,
346
struct counter_count *count,
347
enum counter_function *function)
348
{
349
struct quad8 *const priv = counter_priv(counter);
350
unsigned long irqflags;
351
int retval;
352
353
spin_lock_irqsave(&priv->lock, irqflags);
354
355
retval = quad8_function_get(priv, count->id, function);
356
357
spin_unlock_irqrestore(&priv->lock, irqflags);
358
359
return retval;
360
}
361
362
static int quad8_function_write(struct counter_device *counter,
363
struct counter_count *count,
364
enum counter_function function)
365
{
366
struct quad8 *const priv = counter_priv(counter);
367
const int id = count->id;
368
unsigned long irqflags;
369
unsigned int mode_cfg;
370
bool synchronous_mode;
371
int ret;
372
373
switch (function) {
374
case COUNTER_FUNCTION_PULSE_DIRECTION:
375
mode_cfg = NON_QUADRATURE;
376
break;
377
case COUNTER_FUNCTION_QUADRATURE_X1_A:
378
mode_cfg = QUADRATURE_X1;
379
break;
380
case COUNTER_FUNCTION_QUADRATURE_X2_A:
381
mode_cfg = QUADRATURE_X2;
382
break;
383
case COUNTER_FUNCTION_QUADRATURE_X4:
384
mode_cfg = QUADRATURE_X4;
385
break;
386
default:
387
/* should never reach this path */
388
return -EINVAL;
389
}
390
391
spin_lock_irqsave(&priv->lock, irqflags);
392
393
/* Synchronous function not supported in non-quadrature mode */
394
synchronous_mode = u8_get_bits(priv->idr[id], INDEX_MODE) == ENABLE_INDEX_MODE;
395
if (synchronous_mode && mode_cfg == NON_QUADRATURE) {
396
ret = quad8_control_register_update(priv->map, priv->idr, id, DISABLE_INDEX_MODE,
397
INDEX_MODE);
398
if (ret)
399
goto exit_unlock;
400
}
401
402
ret = quad8_control_register_update(priv->map, priv->cmr, id, mode_cfg, QUADRATURE_MODE);
403
404
exit_unlock:
405
spin_unlock_irqrestore(&priv->lock, irqflags);
406
407
return ret;
408
}
409
410
static int quad8_direction_read(struct counter_device *counter,
411
struct counter_count *count,
412
enum counter_count_direction *direction)
413
{
414
const struct quad8 *const priv = counter_priv(counter);
415
unsigned int flag;
416
int ret;
417
418
ret = regmap_read(priv->map, QUAD8_CONTROL(count->id), &flag);
419
if (ret)
420
return ret;
421
*direction = (u8_get_bits(flag, FLAG_UD) == UP) ? COUNTER_COUNT_DIRECTION_FORWARD :
422
COUNTER_COUNT_DIRECTION_BACKWARD;
423
424
return 0;
425
}
426
427
static const enum counter_synapse_action quad8_index_actions_list[] = {
428
COUNTER_SYNAPSE_ACTION_NONE,
429
COUNTER_SYNAPSE_ACTION_RISING_EDGE,
430
};
431
432
static const enum counter_synapse_action quad8_synapse_actions_list[] = {
433
COUNTER_SYNAPSE_ACTION_NONE,
434
COUNTER_SYNAPSE_ACTION_RISING_EDGE,
435
COUNTER_SYNAPSE_ACTION_FALLING_EDGE,
436
COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
437
};
438
439
static int quad8_action_read(struct counter_device *counter,
440
struct counter_count *count,
441
struct counter_synapse *synapse,
442
enum counter_synapse_action *action)
443
{
444
struct quad8 *const priv = counter_priv(counter);
445
unsigned long irqflags;
446
int err;
447
enum counter_function function;
448
const size_t signal_a_id = count->synapses[0].signal->id;
449
enum counter_count_direction direction;
450
451
/* Default action mode */
452
*action = COUNTER_SYNAPSE_ACTION_NONE;
453
454
/* Handle Index signals */
455
if (synapse->signal->id >= 16) {
456
if (u8_get_bits(priv->ior[count->id], LOAD_PIN) == LOAD_CNTR)
457
*action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
458
return 0;
459
}
460
461
spin_lock_irqsave(&priv->lock, irqflags);
462
463
/* Get Count function and direction atomically */
464
err = quad8_function_get(priv, count->id, &function);
465
if (err) {
466
spin_unlock_irqrestore(&priv->lock, irqflags);
467
return err;
468
}
469
err = quad8_direction_read(counter, count, &direction);
470
if (err) {
471
spin_unlock_irqrestore(&priv->lock, irqflags);
472
return err;
473
}
474
475
spin_unlock_irqrestore(&priv->lock, irqflags);
476
477
/* Determine action mode based on current count function mode */
478
switch (function) {
479
case COUNTER_FUNCTION_PULSE_DIRECTION:
480
if (synapse->signal->id == signal_a_id)
481
*action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
482
return 0;
483
case COUNTER_FUNCTION_QUADRATURE_X1_A:
484
if (synapse->signal->id == signal_a_id) {
485
if (direction == COUNTER_COUNT_DIRECTION_FORWARD)
486
*action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
487
else
488
*action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE;
489
}
490
return 0;
491
case COUNTER_FUNCTION_QUADRATURE_X2_A:
492
if (synapse->signal->id == signal_a_id)
493
*action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
494
return 0;
495
case COUNTER_FUNCTION_QUADRATURE_X4:
496
*action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
497
return 0;
498
default:
499
/* should never reach this path */
500
return -EINVAL;
501
}
502
}
503
504
static int quad8_events_configure(struct counter_device *counter)
505
{
506
struct quad8 *const priv = counter_priv(counter);
507
unsigned long irq_enabled = 0;
508
unsigned long irqflags;
509
struct counter_event_node *event_node;
510
u8 flg_pins;
511
int ret;
512
513
spin_lock_irqsave(&priv->lock, irqflags);
514
515
list_for_each_entry(event_node, &counter->events_list, l) {
516
switch (event_node->event) {
517
case COUNTER_EVENT_OVERFLOW:
518
flg_pins = FLG1_CARRY_FLG2_BORROW;
519
break;
520
case COUNTER_EVENT_THRESHOLD:
521
flg_pins = FLG1_COMPARE_FLG2_BORROW;
522
break;
523
case COUNTER_EVENT_OVERFLOW_UNDERFLOW:
524
flg_pins = FLG1_CARRYBORROW_FLG2_UD;
525
break;
526
case COUNTER_EVENT_INDEX:
527
flg_pins = FLG1_INDX_FLG2_E;
528
break;
529
default:
530
/* should never reach this path */
531
ret = -EINVAL;
532
goto exit_unlock;
533
}
534
535
/* Enable IRQ line */
536
irq_enabled |= BIT(event_node->channel);
537
538
/* Skip configuration if it is the same as previously set */
539
if (flg_pins == u8_get_bits(priv->ior[event_node->channel], FLG_PINS))
540
continue;
541
542
/* Save new IRQ function configuration */
543
ret = quad8_control_register_update(priv->map, priv->ior, event_node->channel,
544
flg_pins, FLG_PINS);
545
if (ret)
546
goto exit_unlock;
547
}
548
549
ret = regmap_write(priv->map, QUAD8_INDEX_INTERRUPT, irq_enabled);
550
551
exit_unlock:
552
spin_unlock_irqrestore(&priv->lock, irqflags);
553
554
return ret;
555
}
556
557
static int quad8_watch_validate(struct counter_device *counter,
558
const struct counter_watch *watch)
559
{
560
struct counter_event_node *event_node;
561
562
if (watch->channel > QUAD8_NUM_COUNTERS - 1)
563
return -EINVAL;
564
565
switch (watch->event) {
566
case COUNTER_EVENT_OVERFLOW:
567
case COUNTER_EVENT_THRESHOLD:
568
case COUNTER_EVENT_OVERFLOW_UNDERFLOW:
569
case COUNTER_EVENT_INDEX:
570
list_for_each_entry(event_node, &counter->next_events_list, l)
571
if (watch->channel == event_node->channel &&
572
watch->event != event_node->event)
573
return -EINVAL;
574
return 0;
575
default:
576
return -EINVAL;
577
}
578
}
579
580
static const struct counter_ops quad8_ops = {
581
.signal_read = quad8_signal_read,
582
.count_read = quad8_count_read,
583
.count_write = quad8_count_write,
584
.function_read = quad8_function_read,
585
.function_write = quad8_function_write,
586
.action_read = quad8_action_read,
587
.events_configure = quad8_events_configure,
588
.watch_validate = quad8_watch_validate,
589
};
590
591
static const char *const quad8_index_polarity_modes[] = {
592
"negative",
593
"positive"
594
};
595
596
static int quad8_index_polarity_get(struct counter_device *counter,
597
struct counter_signal *signal,
598
u32 *index_polarity)
599
{
600
const struct quad8 *const priv = counter_priv(counter);
601
const size_t channel_id = signal->id - 16;
602
603
*index_polarity = u8_get_bits(priv->idr[channel_id], INDEX_POLARITY);
604
605
return 0;
606
}
607
608
static int quad8_index_polarity_set(struct counter_device *counter,
609
struct counter_signal *signal,
610
u32 index_polarity)
611
{
612
struct quad8 *const priv = counter_priv(counter);
613
const size_t channel_id = signal->id - 16;
614
unsigned long irqflags;
615
int ret;
616
617
spin_lock_irqsave(&priv->lock, irqflags);
618
619
ret = quad8_control_register_update(priv->map, priv->idr, channel_id, index_polarity,
620
INDEX_POLARITY);
621
622
spin_unlock_irqrestore(&priv->lock, irqflags);
623
624
return ret;
625
}
626
627
static int quad8_polarity_read(struct counter_device *counter,
628
struct counter_signal *signal,
629
enum counter_signal_polarity *polarity)
630
{
631
int err;
632
u32 index_polarity;
633
634
err = quad8_index_polarity_get(counter, signal, &index_polarity);
635
if (err)
636
return err;
637
638
*polarity = (index_polarity == POSITIVE_INDEX_POLARITY) ? COUNTER_SIGNAL_POLARITY_POSITIVE :
639
COUNTER_SIGNAL_POLARITY_NEGATIVE;
640
641
return 0;
642
}
643
644
static int quad8_polarity_write(struct counter_device *counter,
645
struct counter_signal *signal,
646
enum counter_signal_polarity polarity)
647
{
648
const u32 pol = (polarity == COUNTER_SIGNAL_POLARITY_POSITIVE) ? POSITIVE_INDEX_POLARITY :
649
NEGATIVE_INDEX_POLARITY;
650
651
return quad8_index_polarity_set(counter, signal, pol);
652
}
653
654
static const char *const quad8_synchronous_modes[] = {
655
"non-synchronous",
656
"synchronous"
657
};
658
659
static int quad8_synchronous_mode_get(struct counter_device *counter,
660
struct counter_signal *signal,
661
u32 *synchronous_mode)
662
{
663
const struct quad8 *const priv = counter_priv(counter);
664
const size_t channel_id = signal->id - 16;
665
666
*synchronous_mode = u8_get_bits(priv->idr[channel_id], INDEX_MODE);
667
668
return 0;
669
}
670
671
static int quad8_synchronous_mode_set(struct counter_device *counter,
672
struct counter_signal *signal,
673
u32 synchronous_mode)
674
{
675
struct quad8 *const priv = counter_priv(counter);
676
const size_t channel_id = signal->id - 16;
677
u8 quadrature_mode;
678
unsigned long irqflags;
679
int ret;
680
681
spin_lock_irqsave(&priv->lock, irqflags);
682
683
/* Index function must be non-synchronous in non-quadrature mode */
684
quadrature_mode = u8_get_bits(priv->idr[channel_id], QUADRATURE_MODE);
685
if (synchronous_mode && quadrature_mode == NON_QUADRATURE) {
686
ret = -EINVAL;
687
goto exit_unlock;
688
}
689
690
ret = quad8_control_register_update(priv->map, priv->idr, channel_id, synchronous_mode,
691
INDEX_MODE);
692
693
exit_unlock:
694
spin_unlock_irqrestore(&priv->lock, irqflags);
695
696
return ret;
697
}
698
699
static int quad8_count_floor_read(struct counter_device *counter,
700
struct counter_count *count, u64 *floor)
701
{
702
/* Only a floor of 0 is supported */
703
*floor = 0;
704
705
return 0;
706
}
707
708
static int quad8_count_mode_read(struct counter_device *counter,
709
struct counter_count *count,
710
enum counter_count_mode *cnt_mode)
711
{
712
const struct quad8 *const priv = counter_priv(counter);
713
714
switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) {
715
case NORMAL_COUNT:
716
*cnt_mode = COUNTER_COUNT_MODE_NORMAL;
717
break;
718
case RANGE_LIMIT:
719
*cnt_mode = COUNTER_COUNT_MODE_RANGE_LIMIT;
720
break;
721
case NON_RECYCLE_COUNT:
722
*cnt_mode = COUNTER_COUNT_MODE_NON_RECYCLE;
723
break;
724
case MODULO_N:
725
*cnt_mode = COUNTER_COUNT_MODE_MODULO_N;
726
break;
727
}
728
729
return 0;
730
}
731
732
static int quad8_count_mode_write(struct counter_device *counter,
733
struct counter_count *count,
734
enum counter_count_mode cnt_mode)
735
{
736
struct quad8 *const priv = counter_priv(counter);
737
unsigned int count_mode;
738
unsigned long irqflags;
739
int ret;
740
741
switch (cnt_mode) {
742
case COUNTER_COUNT_MODE_NORMAL:
743
count_mode = NORMAL_COUNT;
744
break;
745
case COUNTER_COUNT_MODE_RANGE_LIMIT:
746
count_mode = RANGE_LIMIT;
747
break;
748
case COUNTER_COUNT_MODE_NON_RECYCLE:
749
count_mode = NON_RECYCLE_COUNT;
750
break;
751
case COUNTER_COUNT_MODE_MODULO_N:
752
count_mode = MODULO_N;
753
break;
754
default:
755
/* should never reach this path */
756
return -EINVAL;
757
}
758
759
spin_lock_irqsave(&priv->lock, irqflags);
760
761
ret = quad8_control_register_update(priv->map, priv->cmr, count->id, count_mode,
762
COUNT_MODE);
763
764
spin_unlock_irqrestore(&priv->lock, irqflags);
765
766
return ret;
767
}
768
769
static int quad8_count_enable_read(struct counter_device *counter,
770
struct counter_count *count, u8 *enable)
771
{
772
const struct quad8 *const priv = counter_priv(counter);
773
774
*enable = u8_get_bits(priv->ior[count->id], AB_GATE);
775
776
return 0;
777
}
778
779
static int quad8_count_enable_write(struct counter_device *counter,
780
struct counter_count *count, u8 enable)
781
{
782
struct quad8 *const priv = counter_priv(counter);
783
unsigned long irqflags;
784
int ret;
785
786
spin_lock_irqsave(&priv->lock, irqflags);
787
788
ret = quad8_control_register_update(priv->map, priv->ior, count->id, enable, AB_GATE);
789
790
spin_unlock_irqrestore(&priv->lock, irqflags);
791
792
return ret;
793
}
794
795
static const char *const quad8_noise_error_states[] = {
796
"No excessive noise is present at the count inputs",
797
"Excessive noise is present at the count inputs"
798
};
799
800
static int quad8_error_noise_get(struct counter_device *counter,
801
struct counter_count *count, u32 *noise_error)
802
{
803
const struct quad8 *const priv = counter_priv(counter);
804
unsigned int flag;
805
int ret;
806
807
ret = regmap_read(priv->map, QUAD8_CONTROL(count->id), &flag);
808
if (ret)
809
return ret;
810
*noise_error = u8_get_bits(flag, FLAG_E);
811
812
return 0;
813
}
814
815
static int quad8_count_preset_read(struct counter_device *counter,
816
struct counter_count *count, u64 *preset)
817
{
818
const struct quad8 *const priv = counter_priv(counter);
819
820
*preset = priv->preset[count->id];
821
822
return 0;
823
}
824
825
static int quad8_count_preset_write(struct counter_device *counter,
826
struct counter_count *count, u64 preset)
827
{
828
struct quad8 *const priv = counter_priv(counter);
829
unsigned long irqflags;
830
int ret;
831
832
if (preset > LS7267_CNTR_MAX)
833
return -ERANGE;
834
835
spin_lock_irqsave(&priv->lock, irqflags);
836
837
priv->preset[count->id] = preset;
838
ret = quad8_preset_register_set(priv, count->id, preset);
839
840
spin_unlock_irqrestore(&priv->lock, irqflags);
841
842
return ret;
843
}
844
845
static int quad8_count_ceiling_read(struct counter_device *counter,
846
struct counter_count *count, u64 *ceiling)
847
{
848
struct quad8 *const priv = counter_priv(counter);
849
unsigned long irqflags;
850
851
spin_lock_irqsave(&priv->lock, irqflags);
852
853
/* Range Limit and Modulo-N count modes use preset value as ceiling */
854
switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) {
855
case RANGE_LIMIT:
856
case MODULO_N:
857
*ceiling = priv->preset[count->id];
858
break;
859
default:
860
*ceiling = LS7267_CNTR_MAX;
861
break;
862
}
863
864
spin_unlock_irqrestore(&priv->lock, irqflags);
865
866
return 0;
867
}
868
869
static int quad8_count_ceiling_write(struct counter_device *counter,
870
struct counter_count *count, u64 ceiling)
871
{
872
struct quad8 *const priv = counter_priv(counter);
873
unsigned long irqflags;
874
int ret;
875
876
if (ceiling > LS7267_CNTR_MAX)
877
return -ERANGE;
878
879
spin_lock_irqsave(&priv->lock, irqflags);
880
881
/* Range Limit and Modulo-N count modes use preset value as ceiling */
882
switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) {
883
case RANGE_LIMIT:
884
case MODULO_N:
885
priv->preset[count->id] = ceiling;
886
ret = quad8_preset_register_set(priv, count->id, ceiling);
887
break;
888
default:
889
ret = -EINVAL;
890
break;
891
}
892
893
spin_unlock_irqrestore(&priv->lock, irqflags);
894
895
return ret;
896
}
897
898
static int quad8_count_preset_enable_read(struct counter_device *counter,
899
struct counter_count *count,
900
u8 *preset_enable)
901
{
902
const struct quad8 *const priv = counter_priv(counter);
903
904
/* Preset enable is active low in Input/Output Control register */
905
*preset_enable = !u8_get_bits(priv->ior[count->id], LOAD_PIN);
906
907
return 0;
908
}
909
910
static int quad8_count_preset_enable_write(struct counter_device *counter,
911
struct counter_count *count,
912
u8 preset_enable)
913
{
914
struct quad8 *const priv = counter_priv(counter);
915
unsigned long irqflags;
916
int ret;
917
918
spin_lock_irqsave(&priv->lock, irqflags);
919
920
/* Preset enable is active low in Input/Output Control register */
921
ret = quad8_control_register_update(priv->map, priv->ior, count->id, !preset_enable,
922
LOAD_PIN);
923
924
spin_unlock_irqrestore(&priv->lock, irqflags);
925
926
return ret;
927
}
928
929
static int quad8_signal_cable_fault_read(struct counter_device *counter,
930
struct counter_signal *signal,
931
u8 *cable_fault)
932
{
933
struct quad8 *const priv = counter_priv(counter);
934
const size_t channel_id = signal->id / 2;
935
unsigned long irqflags;
936
bool disabled;
937
int ret;
938
939
spin_lock_irqsave(&priv->lock, irqflags);
940
941
disabled = !(priv->cable_fault_enable & BIT(channel_id));
942
943
if (disabled) {
944
spin_unlock_irqrestore(&priv->lock, irqflags);
945
return -EINVAL;
946
}
947
948
ret = regmap_test_bits(priv->map, QUAD8_CABLE_STATUS, BIT(channel_id));
949
if (ret < 0) {
950
spin_unlock_irqrestore(&priv->lock, irqflags);
951
return ret;
952
}
953
954
spin_unlock_irqrestore(&priv->lock, irqflags);
955
956
/* Logic 0 = cable fault */
957
*cable_fault = !ret;
958
959
return 0;
960
}
961
962
static int quad8_signal_cable_fault_enable_read(struct counter_device *counter,
963
struct counter_signal *signal,
964
u8 *enable)
965
{
966
const struct quad8 *const priv = counter_priv(counter);
967
const size_t channel_id = signal->id / 2;
968
969
*enable = !!(priv->cable_fault_enable & BIT(channel_id));
970
971
return 0;
972
}
973
974
static int quad8_signal_cable_fault_enable_write(struct counter_device *counter,
975
struct counter_signal *signal,
976
u8 enable)
977
{
978
struct quad8 *const priv = counter_priv(counter);
979
const size_t channel_id = signal->id / 2;
980
unsigned long irqflags;
981
unsigned int cable_fault_enable;
982
int ret;
983
984
spin_lock_irqsave(&priv->lock, irqflags);
985
986
if (enable)
987
priv->cable_fault_enable |= BIT(channel_id);
988
else
989
priv->cable_fault_enable &= ~BIT(channel_id);
990
991
/* Enable is active low in Differential Encoder Cable Status register */
992
cable_fault_enable = ~priv->cable_fault_enable;
993
994
ret = regmap_write(priv->map, QUAD8_CABLE_STATUS, cable_fault_enable);
995
996
spin_unlock_irqrestore(&priv->lock, irqflags);
997
998
return ret;
999
}
1000
1001
static int quad8_signal_fck_prescaler_read(struct counter_device *counter,
1002
struct counter_signal *signal,
1003
u8 *prescaler)
1004
{
1005
const struct quad8 *const priv = counter_priv(counter);
1006
1007
*prescaler = priv->fck_prescaler[signal->id / 2];
1008
1009
return 0;
1010
}
1011
1012
static int quad8_filter_clock_prescaler_set(struct quad8 *const priv, const size_t id,
1013
const u8 prescaler)
1014
{
1015
int ret;
1016
1017
ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BP);
1018
if (ret)
1019
return ret;
1020
ret = regmap_write(priv->map, QUAD8_DATA(id), prescaler);
1021
if (ret)
1022
return ret;
1023
return regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | TRANSFER_PR0_TO_PSC);
1024
}
1025
1026
static int quad8_signal_fck_prescaler_write(struct counter_device *counter,
1027
struct counter_signal *signal,
1028
u8 prescaler)
1029
{
1030
struct quad8 *const priv = counter_priv(counter);
1031
const size_t channel_id = signal->id / 2;
1032
unsigned long irqflags;
1033
int ret;
1034
1035
spin_lock_irqsave(&priv->lock, irqflags);
1036
1037
priv->fck_prescaler[channel_id] = prescaler;
1038
ret = quad8_filter_clock_prescaler_set(priv, channel_id, prescaler);
1039
1040
spin_unlock_irqrestore(&priv->lock, irqflags);
1041
1042
return ret;
1043
}
1044
1045
static struct counter_comp quad8_signal_ext[] = {
1046
COUNTER_COMP_SIGNAL_BOOL("cable_fault", quad8_signal_cable_fault_read,
1047
NULL),
1048
COUNTER_COMP_SIGNAL_BOOL("cable_fault_enable",
1049
quad8_signal_cable_fault_enable_read,
1050
quad8_signal_cable_fault_enable_write),
1051
COUNTER_COMP_SIGNAL_U8("filter_clock_prescaler",
1052
quad8_signal_fck_prescaler_read,
1053
quad8_signal_fck_prescaler_write)
1054
};
1055
1056
static const enum counter_signal_polarity quad8_polarities[] = {
1057
COUNTER_SIGNAL_POLARITY_POSITIVE,
1058
COUNTER_SIGNAL_POLARITY_NEGATIVE,
1059
};
1060
1061
static DEFINE_COUNTER_AVAILABLE(quad8_polarity_available, quad8_polarities);
1062
1063
static DEFINE_COUNTER_ENUM(quad8_index_pol_enum, quad8_index_polarity_modes);
1064
static DEFINE_COUNTER_ENUM(quad8_synch_mode_enum, quad8_synchronous_modes);
1065
1066
static struct counter_comp quad8_index_ext[] = {
1067
COUNTER_COMP_SIGNAL_ENUM("index_polarity", quad8_index_polarity_get,
1068
quad8_index_polarity_set,
1069
quad8_index_pol_enum),
1070
COUNTER_COMP_POLARITY(quad8_polarity_read, quad8_polarity_write,
1071
quad8_polarity_available),
1072
COUNTER_COMP_SIGNAL_ENUM("synchronous_mode", quad8_synchronous_mode_get,
1073
quad8_synchronous_mode_set,
1074
quad8_synch_mode_enum),
1075
};
1076
1077
#define QUAD8_QUAD_SIGNAL(_id, _name) { \
1078
.id = (_id), \
1079
.name = (_name), \
1080
.ext = quad8_signal_ext, \
1081
.num_ext = ARRAY_SIZE(quad8_signal_ext) \
1082
}
1083
1084
#define QUAD8_INDEX_SIGNAL(_id, _name) { \
1085
.id = (_id), \
1086
.name = (_name), \
1087
.ext = quad8_index_ext, \
1088
.num_ext = ARRAY_SIZE(quad8_index_ext) \
1089
}
1090
1091
static struct counter_signal quad8_signals[] = {
1092
QUAD8_QUAD_SIGNAL(0, "Channel 1 Quadrature A"),
1093
QUAD8_QUAD_SIGNAL(1, "Channel 1 Quadrature B"),
1094
QUAD8_QUAD_SIGNAL(2, "Channel 2 Quadrature A"),
1095
QUAD8_QUAD_SIGNAL(3, "Channel 2 Quadrature B"),
1096
QUAD8_QUAD_SIGNAL(4, "Channel 3 Quadrature A"),
1097
QUAD8_QUAD_SIGNAL(5, "Channel 3 Quadrature B"),
1098
QUAD8_QUAD_SIGNAL(6, "Channel 4 Quadrature A"),
1099
QUAD8_QUAD_SIGNAL(7, "Channel 4 Quadrature B"),
1100
QUAD8_QUAD_SIGNAL(8, "Channel 5 Quadrature A"),
1101
QUAD8_QUAD_SIGNAL(9, "Channel 5 Quadrature B"),
1102
QUAD8_QUAD_SIGNAL(10, "Channel 6 Quadrature A"),
1103
QUAD8_QUAD_SIGNAL(11, "Channel 6 Quadrature B"),
1104
QUAD8_QUAD_SIGNAL(12, "Channel 7 Quadrature A"),
1105
QUAD8_QUAD_SIGNAL(13, "Channel 7 Quadrature B"),
1106
QUAD8_QUAD_SIGNAL(14, "Channel 8 Quadrature A"),
1107
QUAD8_QUAD_SIGNAL(15, "Channel 8 Quadrature B"),
1108
QUAD8_INDEX_SIGNAL(16, "Channel 1 Index"),
1109
QUAD8_INDEX_SIGNAL(17, "Channel 2 Index"),
1110
QUAD8_INDEX_SIGNAL(18, "Channel 3 Index"),
1111
QUAD8_INDEX_SIGNAL(19, "Channel 4 Index"),
1112
QUAD8_INDEX_SIGNAL(20, "Channel 5 Index"),
1113
QUAD8_INDEX_SIGNAL(21, "Channel 6 Index"),
1114
QUAD8_INDEX_SIGNAL(22, "Channel 7 Index"),
1115
QUAD8_INDEX_SIGNAL(23, "Channel 8 Index")
1116
};
1117
1118
#define QUAD8_COUNT_SYNAPSES(_id) { \
1119
{ \
1120
.actions_list = quad8_synapse_actions_list, \
1121
.num_actions = ARRAY_SIZE(quad8_synapse_actions_list), \
1122
.signal = quad8_signals + 2 * (_id) \
1123
}, \
1124
{ \
1125
.actions_list = quad8_synapse_actions_list, \
1126
.num_actions = ARRAY_SIZE(quad8_synapse_actions_list), \
1127
.signal = quad8_signals + 2 * (_id) + 1 \
1128
}, \
1129
{ \
1130
.actions_list = quad8_index_actions_list, \
1131
.num_actions = ARRAY_SIZE(quad8_index_actions_list), \
1132
.signal = quad8_signals + 2 * (_id) + 16 \
1133
} \
1134
}
1135
1136
static struct counter_synapse quad8_count_synapses[][3] = {
1137
QUAD8_COUNT_SYNAPSES(0), QUAD8_COUNT_SYNAPSES(1),
1138
QUAD8_COUNT_SYNAPSES(2), QUAD8_COUNT_SYNAPSES(3),
1139
QUAD8_COUNT_SYNAPSES(4), QUAD8_COUNT_SYNAPSES(5),
1140
QUAD8_COUNT_SYNAPSES(6), QUAD8_COUNT_SYNAPSES(7)
1141
};
1142
1143
static const enum counter_count_mode quad8_cnt_modes[] = {
1144
COUNTER_COUNT_MODE_NORMAL,
1145
COUNTER_COUNT_MODE_RANGE_LIMIT,
1146
COUNTER_COUNT_MODE_NON_RECYCLE,
1147
COUNTER_COUNT_MODE_MODULO_N,
1148
};
1149
1150
static DEFINE_COUNTER_AVAILABLE(quad8_count_mode_available, quad8_cnt_modes);
1151
1152
static DEFINE_COUNTER_ENUM(quad8_error_noise_enum, quad8_noise_error_states);
1153
1154
static struct counter_comp quad8_count_ext[] = {
1155
COUNTER_COMP_CEILING(quad8_count_ceiling_read,
1156
quad8_count_ceiling_write),
1157
COUNTER_COMP_FLOOR(quad8_count_floor_read, NULL),
1158
COUNTER_COMP_COUNT_MODE(quad8_count_mode_read, quad8_count_mode_write,
1159
quad8_count_mode_available),
1160
COUNTER_COMP_DIRECTION(quad8_direction_read),
1161
COUNTER_COMP_ENABLE(quad8_count_enable_read, quad8_count_enable_write),
1162
COUNTER_COMP_COUNT_ENUM("error_noise", quad8_error_noise_get, NULL,
1163
quad8_error_noise_enum),
1164
COUNTER_COMP_PRESET(quad8_count_preset_read, quad8_count_preset_write),
1165
COUNTER_COMP_PRESET_ENABLE(quad8_count_preset_enable_read,
1166
quad8_count_preset_enable_write),
1167
};
1168
1169
#define QUAD8_COUNT(_id, _cntname) { \
1170
.id = (_id), \
1171
.name = (_cntname), \
1172
.functions_list = quad8_count_functions_list, \
1173
.num_functions = ARRAY_SIZE(quad8_count_functions_list), \
1174
.synapses = quad8_count_synapses[(_id)], \
1175
.num_synapses = 2, \
1176
.ext = quad8_count_ext, \
1177
.num_ext = ARRAY_SIZE(quad8_count_ext) \
1178
}
1179
1180
static struct counter_count quad8_counts[] = {
1181
QUAD8_COUNT(0, "Channel 1 Count"),
1182
QUAD8_COUNT(1, "Channel 2 Count"),
1183
QUAD8_COUNT(2, "Channel 3 Count"),
1184
QUAD8_COUNT(3, "Channel 4 Count"),
1185
QUAD8_COUNT(4, "Channel 5 Count"),
1186
QUAD8_COUNT(5, "Channel 6 Count"),
1187
QUAD8_COUNT(6, "Channel 7 Count"),
1188
QUAD8_COUNT(7, "Channel 8 Count")
1189
};
1190
1191
static irqreturn_t quad8_irq_handler(int irq, void *private)
1192
{
1193
struct counter_device *counter = private;
1194
struct quad8 *const priv = counter_priv(counter);
1195
unsigned int status;
1196
unsigned long irq_status;
1197
unsigned long channel;
1198
unsigned int flg_pins;
1199
u8 event;
1200
int ret;
1201
1202
ret = regmap_read(priv->map, QUAD8_INTERRUPT_STATUS, &status);
1203
if (ret)
1204
return ret;
1205
if (!status)
1206
return IRQ_NONE;
1207
1208
irq_status = status;
1209
for_each_set_bit(channel, &irq_status, QUAD8_NUM_COUNTERS) {
1210
flg_pins = u8_get_bits(priv->ior[channel], FLG_PINS);
1211
switch (flg_pins) {
1212
case FLG1_CARRY_FLG2_BORROW:
1213
event = COUNTER_EVENT_OVERFLOW;
1214
break;
1215
case FLG1_COMPARE_FLG2_BORROW:
1216
event = COUNTER_EVENT_THRESHOLD;
1217
break;
1218
case FLG1_CARRYBORROW_FLG2_UD:
1219
event = COUNTER_EVENT_OVERFLOW_UNDERFLOW;
1220
break;
1221
case FLG1_INDX_FLG2_E:
1222
event = COUNTER_EVENT_INDEX;
1223
break;
1224
default:
1225
/* should never reach this path */
1226
WARN_ONCE(true, "invalid interrupt trigger function %u configured for channel %lu\n",
1227
flg_pins, channel);
1228
continue;
1229
}
1230
1231
counter_push_event(counter, event, channel);
1232
}
1233
1234
ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION, CLEAR_PENDING_INTERRUPTS);
1235
if (ret)
1236
return ret;
1237
1238
return IRQ_HANDLED;
1239
}
1240
1241
static int quad8_init_counter(struct quad8 *const priv, const size_t channel)
1242
{
1243
int ret;
1244
1245
ret = quad8_filter_clock_prescaler_set(priv, channel, 0);
1246
if (ret)
1247
return ret;
1248
ret = quad8_preset_register_set(priv, channel, 0);
1249
if (ret)
1250
return ret;
1251
ret = quad8_flag_register_reset(priv, channel);
1252
if (ret)
1253
return ret;
1254
1255
/* Binary encoding; Normal count; non-quadrature mode */
1256
priv->cmr[channel] = SELECT_CMR | BINARY | u8_encode_bits(NORMAL_COUNT, COUNT_MODE) |
1257
u8_encode_bits(NON_QUADRATURE, QUADRATURE_MODE);
1258
ret = regmap_write(priv->map, QUAD8_CONTROL(channel), priv->cmr[channel]);
1259
if (ret)
1260
return ret;
1261
1262
/* Disable A and B inputs; preset on index; FLG1 as Carry */
1263
priv->ior[channel] = SELECT_IOR | DISABLE_AB | u8_encode_bits(LOAD_CNTR, LOAD_PIN) |
1264
u8_encode_bits(FLG1_CARRY_FLG2_BORROW, FLG_PINS);
1265
ret = regmap_write(priv->map, QUAD8_CONTROL(channel), priv->ior[channel]);
1266
if (ret)
1267
return ret;
1268
1269
/* Disable index function; negative index polarity */
1270
priv->idr[channel] = SELECT_IDR | u8_encode_bits(DISABLE_INDEX_MODE, INDEX_MODE) |
1271
u8_encode_bits(NEGATIVE_INDEX_POLARITY, INDEX_POLARITY);
1272
return regmap_write(priv->map, QUAD8_CONTROL(channel), priv->idr[channel]);
1273
}
1274
1275
static int quad8_probe(struct device *dev, unsigned int id)
1276
{
1277
struct counter_device *counter;
1278
struct quad8 *priv;
1279
void __iomem *regs;
1280
unsigned long i;
1281
int ret;
1282
1283
if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) {
1284
dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
1285
base[id], base[id] + QUAD8_EXTENT);
1286
return -EBUSY;
1287
}
1288
1289
counter = devm_counter_alloc(dev, sizeof(*priv));
1290
if (!counter)
1291
return -ENOMEM;
1292
priv = counter_priv(counter);
1293
1294
regs = devm_ioport_map(dev, base[id], QUAD8_EXTENT);
1295
if (!regs)
1296
return -ENOMEM;
1297
1298
priv->map = devm_regmap_init_mmio(dev, regs, &quad8_regmap_config);
1299
if (IS_ERR(priv->map))
1300
return dev_err_probe(dev, PTR_ERR(priv->map),
1301
"Unable to initialize register map\n");
1302
1303
/* Initialize Counter device and driver data */
1304
counter->name = dev_name(dev);
1305
counter->parent = dev;
1306
counter->ops = &quad8_ops;
1307
counter->counts = quad8_counts;
1308
counter->num_counts = ARRAY_SIZE(quad8_counts);
1309
counter->signals = quad8_signals;
1310
counter->num_signals = ARRAY_SIZE(quad8_signals);
1311
1312
spin_lock_init(&priv->lock);
1313
1314
/* Reset Index/Interrupt Register */
1315
ret = regmap_write(priv->map, QUAD8_INDEX_INTERRUPT, 0x00);
1316
if (ret)
1317
return ret;
1318
/* Reset all counters and disable interrupt function */
1319
ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION,
1320
RESET_COUNTERS | DISABLE_INTERRUPT_FUNCTION);
1321
if (ret)
1322
return ret;
1323
/* Set initial configuration for all counters */
1324
for (i = 0; i < QUAD8_NUM_COUNTERS; i++) {
1325
ret = quad8_init_counter(priv, i);
1326
if (ret)
1327
return ret;
1328
}
1329
/* Disable Differential Encoder Cable Status for all channels */
1330
ret = regmap_write(priv->map, QUAD8_CABLE_STATUS, GENMASK(7, 0));
1331
if (ret)
1332
return ret;
1333
/* Enable all counters and enable interrupt function */
1334
ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION,
1335
ENABLE_COUNTERS | ENABLE_INTERRUPT_FUNCTION);
1336
if (ret)
1337
return ret;
1338
1339
ret = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler,
1340
IRQF_SHARED, counter->name, counter);
1341
if (ret)
1342
return ret;
1343
1344
ret = devm_counter_add(dev, counter);
1345
if (ret < 0)
1346
return dev_err_probe(dev, ret, "Failed to add counter\n");
1347
1348
return 0;
1349
}
1350
1351
static struct isa_driver quad8_driver = {
1352
.probe = quad8_probe,
1353
.driver = {
1354
.name = "104-quad-8"
1355
}
1356
};
1357
1358
module_isa_driver_with_irq(quad8_driver, num_quad8, num_irq);
1359
1360
MODULE_AUTHOR("William Breathitt Gray <[email protected]>");
1361
MODULE_DESCRIPTION("ACCES 104-QUAD-8 driver");
1362
MODULE_LICENSE("GPL v2");
1363
MODULE_IMPORT_NS("COUNTER");
1364
1365