0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/bitops.h>
0009 #include <linux/counter.h>
0010 #include <linux/device.h>
0011 #include <linux/errno.h>
0012 #include <linux/io.h>
0013 #include <linux/ioport.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/isa.h>
0016 #include <linux/kernel.h>
0017 #include <linux/list.h>
0018 #include <linux/module.h>
0019 #include <linux/moduleparam.h>
0020 #include <linux/types.h>
0021 #include <linux/spinlock.h>
0022
0023 #define QUAD8_EXTENT 32
0024
0025 static unsigned int base[max_num_isa_dev(QUAD8_EXTENT)];
0026 static unsigned int num_quad8;
0027 module_param_hw_array(base, uint, ioport, &num_quad8, 0);
0028 MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");
0029
0030 static unsigned int irq[max_num_isa_dev(QUAD8_EXTENT)];
0031 module_param_hw_array(irq, uint, irq, NULL, 0);
0032 MODULE_PARM_DESC(irq, "ACCES 104-QUAD-8 interrupt line numbers");
0033
0034 #define QUAD8_NUM_COUNTERS 8
0035
0036
0037
0038
0039
0040
0041 struct channel_reg {
0042 u8 data;
0043 u8 control;
0044 };
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056 struct quad8_reg {
0057 struct channel_reg channel[QUAD8_NUM_COUNTERS];
0058 u8 interrupt_status;
0059 u8 channel_oper;
0060 u8 index_interrupt;
0061 u8 reserved[3];
0062 u8 index_input_levels;
0063 u8 cable_status;
0064 };
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083 struct quad8 {
0084 spinlock_t lock;
0085 unsigned int fck_prescaler[QUAD8_NUM_COUNTERS];
0086 unsigned int preset[QUAD8_NUM_COUNTERS];
0087 unsigned int count_mode[QUAD8_NUM_COUNTERS];
0088 unsigned int quadrature_mode[QUAD8_NUM_COUNTERS];
0089 unsigned int quadrature_scale[QUAD8_NUM_COUNTERS];
0090 unsigned int ab_enable[QUAD8_NUM_COUNTERS];
0091 unsigned int preset_enable[QUAD8_NUM_COUNTERS];
0092 unsigned int irq_trigger[QUAD8_NUM_COUNTERS];
0093 unsigned int synchronous_mode[QUAD8_NUM_COUNTERS];
0094 unsigned int index_polarity[QUAD8_NUM_COUNTERS];
0095 unsigned int cable_fault_enable;
0096 struct quad8_reg __iomem *reg;
0097 };
0098
0099
0100 #define QUAD8_FLAG_BT BIT(0)
0101
0102 #define QUAD8_FLAG_CT BIT(1)
0103
0104 #define QUAD8_FLAG_E BIT(4)
0105
0106 #define QUAD8_FLAG_UD BIT(5)
0107
0108 #define QUAD8_CTR_RLD 0x00
0109
0110 #define QUAD8_CTR_CMR 0x20
0111
0112 #define QUAD8_CTR_IOR 0x40
0113
0114 #define QUAD8_CTR_IDR 0x60
0115
0116 #define QUAD8_RLD_RESET_BP 0x01
0117
0118 #define QUAD8_RLD_RESET_CNTR 0x02
0119
0120 #define QUAD8_RLD_RESET_FLAGS 0x04
0121
0122 #define QUAD8_RLD_RESET_E 0x06
0123
0124 #define QUAD8_RLD_PRESET_CNTR 0x08
0125
0126 #define QUAD8_RLD_CNTR_OUT 0x10
0127
0128 #define QUAD8_RLD_PRESET_PSC 0x18
0129 #define QUAD8_CHAN_OP_RESET_COUNTERS 0x01
0130 #define QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC 0x04
0131 #define QUAD8_CMR_QUADRATURE_X1 0x08
0132 #define QUAD8_CMR_QUADRATURE_X2 0x10
0133 #define QUAD8_CMR_QUADRATURE_X4 0x18
0134
0135 static int quad8_signal_read(struct counter_device *counter,
0136 struct counter_signal *signal,
0137 enum counter_signal_level *level)
0138 {
0139 const struct quad8 *const priv = counter_priv(counter);
0140 unsigned int state;
0141
0142
0143 if (signal->id < 16)
0144 return -EINVAL;
0145
0146 state = ioread8(&priv->reg->index_input_levels) & BIT(signal->id - 16);
0147
0148 *level = (state) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
0149
0150 return 0;
0151 }
0152
0153 static int quad8_count_read(struct counter_device *counter,
0154 struct counter_count *count, u64 *val)
0155 {
0156 struct quad8 *const priv = counter_priv(counter);
0157 struct channel_reg __iomem *const chan = priv->reg->channel + count->id;
0158 unsigned int flags;
0159 unsigned int borrow;
0160 unsigned int carry;
0161 unsigned long irqflags;
0162 int i;
0163
0164 flags = ioread8(&chan->control);
0165 borrow = flags & QUAD8_FLAG_BT;
0166 carry = !!(flags & QUAD8_FLAG_CT);
0167
0168
0169 *val = (unsigned long)(borrow ^ carry) << 24;
0170
0171 spin_lock_irqsave(&priv->lock, irqflags);
0172
0173
0174 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
0175 &chan->control);
0176
0177 for (i = 0; i < 3; i++)
0178 *val |= (unsigned long)ioread8(&chan->data) << (8 * i);
0179
0180 spin_unlock_irqrestore(&priv->lock, irqflags);
0181
0182 return 0;
0183 }
0184
0185 static int quad8_count_write(struct counter_device *counter,
0186 struct counter_count *count, u64 val)
0187 {
0188 struct quad8 *const priv = counter_priv(counter);
0189 struct channel_reg __iomem *const chan = priv->reg->channel + count->id;
0190 unsigned long irqflags;
0191 int i;
0192
0193
0194 if (val > 0xFFFFFF)
0195 return -ERANGE;
0196
0197 spin_lock_irqsave(&priv->lock, irqflags);
0198
0199
0200 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
0201
0202
0203 for (i = 0; i < 3; i++)
0204 iowrite8(val >> (8 * i), &chan->data);
0205
0206
0207 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, &chan->control);
0208
0209
0210 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
0211
0212
0213 val = priv->preset[count->id];
0214 for (i = 0; i < 3; i++)
0215 iowrite8(val >> (8 * i), &chan->data);
0216
0217
0218 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control);
0219
0220 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control);
0221
0222 spin_unlock_irqrestore(&priv->lock, irqflags);
0223
0224 return 0;
0225 }
0226
0227 static const enum counter_function quad8_count_functions_list[] = {
0228 COUNTER_FUNCTION_PULSE_DIRECTION,
0229 COUNTER_FUNCTION_QUADRATURE_X1_A,
0230 COUNTER_FUNCTION_QUADRATURE_X2_A,
0231 COUNTER_FUNCTION_QUADRATURE_X4,
0232 };
0233
0234 static int quad8_function_read(struct counter_device *counter,
0235 struct counter_count *count,
0236 enum counter_function *function)
0237 {
0238 struct quad8 *const priv = counter_priv(counter);
0239 const int id = count->id;
0240 unsigned long irqflags;
0241
0242 spin_lock_irqsave(&priv->lock, irqflags);
0243
0244 if (priv->quadrature_mode[id])
0245 switch (priv->quadrature_scale[id]) {
0246 case 0:
0247 *function = COUNTER_FUNCTION_QUADRATURE_X1_A;
0248 break;
0249 case 1:
0250 *function = COUNTER_FUNCTION_QUADRATURE_X2_A;
0251 break;
0252 case 2:
0253 *function = COUNTER_FUNCTION_QUADRATURE_X4;
0254 break;
0255 }
0256 else
0257 *function = COUNTER_FUNCTION_PULSE_DIRECTION;
0258
0259 spin_unlock_irqrestore(&priv->lock, irqflags);
0260
0261 return 0;
0262 }
0263
0264 static int quad8_function_write(struct counter_device *counter,
0265 struct counter_count *count,
0266 enum counter_function function)
0267 {
0268 struct quad8 *const priv = counter_priv(counter);
0269 const int id = count->id;
0270 unsigned int *const quadrature_mode = priv->quadrature_mode + id;
0271 unsigned int *const scale = priv->quadrature_scale + id;
0272 unsigned int *const synchronous_mode = priv->synchronous_mode + id;
0273 u8 __iomem *const control = &priv->reg->channel[id].control;
0274 unsigned long irqflags;
0275 unsigned int mode_cfg;
0276 unsigned int idr_cfg;
0277
0278 spin_lock_irqsave(&priv->lock, irqflags);
0279
0280 mode_cfg = priv->count_mode[id] << 1;
0281 idr_cfg = priv->index_polarity[id] << 1;
0282
0283 if (function == COUNTER_FUNCTION_PULSE_DIRECTION) {
0284 *quadrature_mode = 0;
0285
0286
0287 *scale = 0;
0288
0289
0290 if (*synchronous_mode) {
0291 *synchronous_mode = 0;
0292
0293 iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
0294 }
0295 } else {
0296 *quadrature_mode = 1;
0297
0298 switch (function) {
0299 case COUNTER_FUNCTION_QUADRATURE_X1_A:
0300 *scale = 0;
0301 mode_cfg |= QUAD8_CMR_QUADRATURE_X1;
0302 break;
0303 case COUNTER_FUNCTION_QUADRATURE_X2_A:
0304 *scale = 1;
0305 mode_cfg |= QUAD8_CMR_QUADRATURE_X2;
0306 break;
0307 case COUNTER_FUNCTION_QUADRATURE_X4:
0308 *scale = 2;
0309 mode_cfg |= QUAD8_CMR_QUADRATURE_X4;
0310 break;
0311 default:
0312
0313 spin_unlock_irqrestore(&priv->lock, irqflags);
0314 return -EINVAL;
0315 }
0316 }
0317
0318
0319 iowrite8(QUAD8_CTR_CMR | mode_cfg, control);
0320
0321 spin_unlock_irqrestore(&priv->lock, irqflags);
0322
0323 return 0;
0324 }
0325
0326 static int quad8_direction_read(struct counter_device *counter,
0327 struct counter_count *count,
0328 enum counter_count_direction *direction)
0329 {
0330 const struct quad8 *const priv = counter_priv(counter);
0331 unsigned int ud_flag;
0332 u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control;
0333
0334
0335 ud_flag = ioread8(flag_addr) & QUAD8_FLAG_UD;
0336
0337 *direction = (ud_flag) ? COUNTER_COUNT_DIRECTION_FORWARD :
0338 COUNTER_COUNT_DIRECTION_BACKWARD;
0339
0340 return 0;
0341 }
0342
0343 static const enum counter_synapse_action quad8_index_actions_list[] = {
0344 COUNTER_SYNAPSE_ACTION_NONE,
0345 COUNTER_SYNAPSE_ACTION_RISING_EDGE,
0346 };
0347
0348 static const enum counter_synapse_action quad8_synapse_actions_list[] = {
0349 COUNTER_SYNAPSE_ACTION_NONE,
0350 COUNTER_SYNAPSE_ACTION_RISING_EDGE,
0351 COUNTER_SYNAPSE_ACTION_FALLING_EDGE,
0352 COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
0353 };
0354
0355 static int quad8_action_read(struct counter_device *counter,
0356 struct counter_count *count,
0357 struct counter_synapse *synapse,
0358 enum counter_synapse_action *action)
0359 {
0360 struct quad8 *const priv = counter_priv(counter);
0361 int err;
0362 enum counter_function function;
0363 const size_t signal_a_id = count->synapses[0].signal->id;
0364 enum counter_count_direction direction;
0365
0366
0367 if (synapse->signal->id >= 16) {
0368 if (priv->preset_enable[count->id])
0369 *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
0370 else
0371 *action = COUNTER_SYNAPSE_ACTION_NONE;
0372
0373 return 0;
0374 }
0375
0376 err = quad8_function_read(counter, count, &function);
0377 if (err)
0378 return err;
0379
0380
0381 *action = COUNTER_SYNAPSE_ACTION_NONE;
0382
0383
0384 switch (function) {
0385 case COUNTER_FUNCTION_PULSE_DIRECTION:
0386 if (synapse->signal->id == signal_a_id)
0387 *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
0388 return 0;
0389 case COUNTER_FUNCTION_QUADRATURE_X1_A:
0390 if (synapse->signal->id == signal_a_id) {
0391 err = quad8_direction_read(counter, count, &direction);
0392 if (err)
0393 return err;
0394
0395 if (direction == COUNTER_COUNT_DIRECTION_FORWARD)
0396 *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
0397 else
0398 *action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE;
0399 }
0400 return 0;
0401 case COUNTER_FUNCTION_QUADRATURE_X2_A:
0402 if (synapse->signal->id == signal_a_id)
0403 *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
0404 return 0;
0405 case COUNTER_FUNCTION_QUADRATURE_X4:
0406 *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
0407 return 0;
0408 default:
0409
0410 return -EINVAL;
0411 }
0412 }
0413
0414 enum {
0415 QUAD8_EVENT_CARRY = 0,
0416 QUAD8_EVENT_COMPARE = 1,
0417 QUAD8_EVENT_CARRY_BORROW = 2,
0418 QUAD8_EVENT_INDEX = 3,
0419 };
0420
0421 static int quad8_events_configure(struct counter_device *counter)
0422 {
0423 struct quad8 *const priv = counter_priv(counter);
0424 unsigned long irq_enabled = 0;
0425 unsigned long irqflags;
0426 struct counter_event_node *event_node;
0427 unsigned int next_irq_trigger;
0428 unsigned long ior_cfg;
0429
0430 spin_lock_irqsave(&priv->lock, irqflags);
0431
0432 list_for_each_entry(event_node, &counter->events_list, l) {
0433 switch (event_node->event) {
0434 case COUNTER_EVENT_OVERFLOW:
0435 next_irq_trigger = QUAD8_EVENT_CARRY;
0436 break;
0437 case COUNTER_EVENT_THRESHOLD:
0438 next_irq_trigger = QUAD8_EVENT_COMPARE;
0439 break;
0440 case COUNTER_EVENT_OVERFLOW_UNDERFLOW:
0441 next_irq_trigger = QUAD8_EVENT_CARRY_BORROW;
0442 break;
0443 case COUNTER_EVENT_INDEX:
0444 next_irq_trigger = QUAD8_EVENT_INDEX;
0445 break;
0446 default:
0447
0448 spin_unlock_irqrestore(&priv->lock, irqflags);
0449 return -EINVAL;
0450 }
0451
0452
0453 irq_enabled |= BIT(event_node->channel);
0454
0455
0456 if (priv->irq_trigger[event_node->channel] == next_irq_trigger)
0457 continue;
0458
0459
0460 priv->irq_trigger[event_node->channel] = next_irq_trigger;
0461
0462
0463 ior_cfg = priv->ab_enable[event_node->channel] |
0464 priv->preset_enable[event_node->channel] << 1 |
0465 priv->irq_trigger[event_node->channel] << 3;
0466 iowrite8(QUAD8_CTR_IOR | ior_cfg,
0467 &priv->reg->channel[event_node->channel].control);
0468 }
0469
0470 iowrite8(irq_enabled, &priv->reg->index_interrupt);
0471
0472 spin_unlock_irqrestore(&priv->lock, irqflags);
0473
0474 return 0;
0475 }
0476
0477 static int quad8_watch_validate(struct counter_device *counter,
0478 const struct counter_watch *watch)
0479 {
0480 struct counter_event_node *event_node;
0481
0482 if (watch->channel > QUAD8_NUM_COUNTERS - 1)
0483 return -EINVAL;
0484
0485 switch (watch->event) {
0486 case COUNTER_EVENT_OVERFLOW:
0487 case COUNTER_EVENT_THRESHOLD:
0488 case COUNTER_EVENT_OVERFLOW_UNDERFLOW:
0489 case COUNTER_EVENT_INDEX:
0490 list_for_each_entry(event_node, &counter->next_events_list, l)
0491 if (watch->channel == event_node->channel &&
0492 watch->event != event_node->event)
0493 return -EINVAL;
0494 return 0;
0495 default:
0496 return -EINVAL;
0497 }
0498 }
0499
0500 static const struct counter_ops quad8_ops = {
0501 .signal_read = quad8_signal_read,
0502 .count_read = quad8_count_read,
0503 .count_write = quad8_count_write,
0504 .function_read = quad8_function_read,
0505 .function_write = quad8_function_write,
0506 .action_read = quad8_action_read,
0507 .events_configure = quad8_events_configure,
0508 .watch_validate = quad8_watch_validate,
0509 };
0510
0511 static const char *const quad8_index_polarity_modes[] = {
0512 "negative",
0513 "positive"
0514 };
0515
0516 static int quad8_index_polarity_get(struct counter_device *counter,
0517 struct counter_signal *signal,
0518 u32 *index_polarity)
0519 {
0520 const struct quad8 *const priv = counter_priv(counter);
0521 const size_t channel_id = signal->id - 16;
0522
0523 *index_polarity = priv->index_polarity[channel_id];
0524
0525 return 0;
0526 }
0527
0528 static int quad8_index_polarity_set(struct counter_device *counter,
0529 struct counter_signal *signal,
0530 u32 index_polarity)
0531 {
0532 struct quad8 *const priv = counter_priv(counter);
0533 const size_t channel_id = signal->id - 16;
0534 u8 __iomem *const control = &priv->reg->channel[channel_id].control;
0535 unsigned long irqflags;
0536 unsigned int idr_cfg = index_polarity << 1;
0537
0538 spin_lock_irqsave(&priv->lock, irqflags);
0539
0540 idr_cfg |= priv->synchronous_mode[channel_id];
0541
0542 priv->index_polarity[channel_id] = index_polarity;
0543
0544
0545 iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
0546
0547 spin_unlock_irqrestore(&priv->lock, irqflags);
0548
0549 return 0;
0550 }
0551
0552 static const char *const quad8_synchronous_modes[] = {
0553 "non-synchronous",
0554 "synchronous"
0555 };
0556
0557 static int quad8_synchronous_mode_get(struct counter_device *counter,
0558 struct counter_signal *signal,
0559 u32 *synchronous_mode)
0560 {
0561 const struct quad8 *const priv = counter_priv(counter);
0562 const size_t channel_id = signal->id - 16;
0563
0564 *synchronous_mode = priv->synchronous_mode[channel_id];
0565
0566 return 0;
0567 }
0568
0569 static int quad8_synchronous_mode_set(struct counter_device *counter,
0570 struct counter_signal *signal,
0571 u32 synchronous_mode)
0572 {
0573 struct quad8 *const priv = counter_priv(counter);
0574 const size_t channel_id = signal->id - 16;
0575 u8 __iomem *const control = &priv->reg->channel[channel_id].control;
0576 unsigned long irqflags;
0577 unsigned int idr_cfg = synchronous_mode;
0578
0579 spin_lock_irqsave(&priv->lock, irqflags);
0580
0581 idr_cfg |= priv->index_polarity[channel_id] << 1;
0582
0583
0584 if (synchronous_mode && !priv->quadrature_mode[channel_id]) {
0585 spin_unlock_irqrestore(&priv->lock, irqflags);
0586 return -EINVAL;
0587 }
0588
0589 priv->synchronous_mode[channel_id] = synchronous_mode;
0590
0591
0592 iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
0593
0594 spin_unlock_irqrestore(&priv->lock, irqflags);
0595
0596 return 0;
0597 }
0598
0599 static int quad8_count_floor_read(struct counter_device *counter,
0600 struct counter_count *count, u64 *floor)
0601 {
0602
0603 *floor = 0;
0604
0605 return 0;
0606 }
0607
0608 static int quad8_count_mode_read(struct counter_device *counter,
0609 struct counter_count *count,
0610 enum counter_count_mode *cnt_mode)
0611 {
0612 const struct quad8 *const priv = counter_priv(counter);
0613
0614
0615 switch (priv->count_mode[count->id]) {
0616 case 0:
0617 *cnt_mode = COUNTER_COUNT_MODE_NORMAL;
0618 break;
0619 case 1:
0620 *cnt_mode = COUNTER_COUNT_MODE_RANGE_LIMIT;
0621 break;
0622 case 2:
0623 *cnt_mode = COUNTER_COUNT_MODE_NON_RECYCLE;
0624 break;
0625 case 3:
0626 *cnt_mode = COUNTER_COUNT_MODE_MODULO_N;
0627 break;
0628 }
0629
0630 return 0;
0631 }
0632
0633 static int quad8_count_mode_write(struct counter_device *counter,
0634 struct counter_count *count,
0635 enum counter_count_mode cnt_mode)
0636 {
0637 struct quad8 *const priv = counter_priv(counter);
0638 unsigned int count_mode;
0639 unsigned int mode_cfg;
0640 u8 __iomem *const control = &priv->reg->channel[count->id].control;
0641 unsigned long irqflags;
0642
0643
0644 switch (cnt_mode) {
0645 case COUNTER_COUNT_MODE_NORMAL:
0646 count_mode = 0;
0647 break;
0648 case COUNTER_COUNT_MODE_RANGE_LIMIT:
0649 count_mode = 1;
0650 break;
0651 case COUNTER_COUNT_MODE_NON_RECYCLE:
0652 count_mode = 2;
0653 break;
0654 case COUNTER_COUNT_MODE_MODULO_N:
0655 count_mode = 3;
0656 break;
0657 default:
0658
0659 return -EINVAL;
0660 }
0661
0662 spin_lock_irqsave(&priv->lock, irqflags);
0663
0664 priv->count_mode[count->id] = count_mode;
0665
0666
0667 mode_cfg = count_mode << 1;
0668
0669
0670 if (priv->quadrature_mode[count->id])
0671 mode_cfg |= (priv->quadrature_scale[count->id] + 1) << 3;
0672
0673
0674 iowrite8(QUAD8_CTR_CMR | mode_cfg, control);
0675
0676 spin_unlock_irqrestore(&priv->lock, irqflags);
0677
0678 return 0;
0679 }
0680
0681 static int quad8_count_enable_read(struct counter_device *counter,
0682 struct counter_count *count, u8 *enable)
0683 {
0684 const struct quad8 *const priv = counter_priv(counter);
0685
0686 *enable = priv->ab_enable[count->id];
0687
0688 return 0;
0689 }
0690
0691 static int quad8_count_enable_write(struct counter_device *counter,
0692 struct counter_count *count, u8 enable)
0693 {
0694 struct quad8 *const priv = counter_priv(counter);
0695 u8 __iomem *const control = &priv->reg->channel[count->id].control;
0696 unsigned long irqflags;
0697 unsigned int ior_cfg;
0698
0699 spin_lock_irqsave(&priv->lock, irqflags);
0700
0701 priv->ab_enable[count->id] = enable;
0702
0703 ior_cfg = enable | priv->preset_enable[count->id] << 1 |
0704 priv->irq_trigger[count->id] << 3;
0705
0706
0707 iowrite8(QUAD8_CTR_IOR | ior_cfg, control);
0708
0709 spin_unlock_irqrestore(&priv->lock, irqflags);
0710
0711 return 0;
0712 }
0713
0714 static const char *const quad8_noise_error_states[] = {
0715 "No excessive noise is present at the count inputs",
0716 "Excessive noise is present at the count inputs"
0717 };
0718
0719 static int quad8_error_noise_get(struct counter_device *counter,
0720 struct counter_count *count, u32 *noise_error)
0721 {
0722 const struct quad8 *const priv = counter_priv(counter);
0723 u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control;
0724
0725 *noise_error = !!(ioread8(flag_addr) & QUAD8_FLAG_E);
0726
0727 return 0;
0728 }
0729
0730 static int quad8_count_preset_read(struct counter_device *counter,
0731 struct counter_count *count, u64 *preset)
0732 {
0733 const struct quad8 *const priv = counter_priv(counter);
0734
0735 *preset = priv->preset[count->id];
0736
0737 return 0;
0738 }
0739
0740 static void quad8_preset_register_set(struct quad8 *const priv, const int id,
0741 const unsigned int preset)
0742 {
0743 struct channel_reg __iomem *const chan = priv->reg->channel + id;
0744 int i;
0745
0746 priv->preset[id] = preset;
0747
0748
0749 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
0750
0751
0752 for (i = 0; i < 3; i++)
0753 iowrite8(preset >> (8 * i), &chan->data);
0754 }
0755
0756 static int quad8_count_preset_write(struct counter_device *counter,
0757 struct counter_count *count, u64 preset)
0758 {
0759 struct quad8 *const priv = counter_priv(counter);
0760 unsigned long irqflags;
0761
0762
0763 if (preset > 0xFFFFFF)
0764 return -ERANGE;
0765
0766 spin_lock_irqsave(&priv->lock, irqflags);
0767
0768 quad8_preset_register_set(priv, count->id, preset);
0769
0770 spin_unlock_irqrestore(&priv->lock, irqflags);
0771
0772 return 0;
0773 }
0774
0775 static int quad8_count_ceiling_read(struct counter_device *counter,
0776 struct counter_count *count, u64 *ceiling)
0777 {
0778 struct quad8 *const priv = counter_priv(counter);
0779 unsigned long irqflags;
0780
0781 spin_lock_irqsave(&priv->lock, irqflags);
0782
0783
0784 switch (priv->count_mode[count->id]) {
0785 case 1:
0786 case 3:
0787 *ceiling = priv->preset[count->id];
0788 break;
0789 default:
0790
0791 *ceiling = 0x1FFFFFF;
0792 break;
0793 }
0794
0795 spin_unlock_irqrestore(&priv->lock, irqflags);
0796
0797 return 0;
0798 }
0799
0800 static int quad8_count_ceiling_write(struct counter_device *counter,
0801 struct counter_count *count, u64 ceiling)
0802 {
0803 struct quad8 *const priv = counter_priv(counter);
0804 unsigned long irqflags;
0805
0806
0807 if (ceiling > 0xFFFFFF)
0808 return -ERANGE;
0809
0810 spin_lock_irqsave(&priv->lock, irqflags);
0811
0812
0813 switch (priv->count_mode[count->id]) {
0814 case 1:
0815 case 3:
0816 quad8_preset_register_set(priv, count->id, ceiling);
0817 spin_unlock_irqrestore(&priv->lock, irqflags);
0818 return 0;
0819 }
0820
0821 spin_unlock_irqrestore(&priv->lock, irqflags);
0822
0823 return -EINVAL;
0824 }
0825
0826 static int quad8_count_preset_enable_read(struct counter_device *counter,
0827 struct counter_count *count,
0828 u8 *preset_enable)
0829 {
0830 const struct quad8 *const priv = counter_priv(counter);
0831
0832 *preset_enable = !priv->preset_enable[count->id];
0833
0834 return 0;
0835 }
0836
0837 static int quad8_count_preset_enable_write(struct counter_device *counter,
0838 struct counter_count *count,
0839 u8 preset_enable)
0840 {
0841 struct quad8 *const priv = counter_priv(counter);
0842 u8 __iomem *const control = &priv->reg->channel[count->id].control;
0843 unsigned long irqflags;
0844 unsigned int ior_cfg;
0845
0846
0847 preset_enable = !preset_enable;
0848
0849 spin_lock_irqsave(&priv->lock, irqflags);
0850
0851 priv->preset_enable[count->id] = preset_enable;
0852
0853 ior_cfg = priv->ab_enable[count->id] | preset_enable << 1 |
0854 priv->irq_trigger[count->id] << 3;
0855
0856
0857 iowrite8(QUAD8_CTR_IOR | ior_cfg, control);
0858
0859 spin_unlock_irqrestore(&priv->lock, irqflags);
0860
0861 return 0;
0862 }
0863
0864 static int quad8_signal_cable_fault_read(struct counter_device *counter,
0865 struct counter_signal *signal,
0866 u8 *cable_fault)
0867 {
0868 struct quad8 *const priv = counter_priv(counter);
0869 const size_t channel_id = signal->id / 2;
0870 unsigned long irqflags;
0871 bool disabled;
0872 unsigned int status;
0873
0874 spin_lock_irqsave(&priv->lock, irqflags);
0875
0876 disabled = !(priv->cable_fault_enable & BIT(channel_id));
0877
0878 if (disabled) {
0879 spin_unlock_irqrestore(&priv->lock, irqflags);
0880 return -EINVAL;
0881 }
0882
0883
0884 status = ioread8(&priv->reg->cable_status);
0885
0886 spin_unlock_irqrestore(&priv->lock, irqflags);
0887
0888
0889 *cable_fault = !(status & BIT(channel_id));
0890
0891 return 0;
0892 }
0893
0894 static int quad8_signal_cable_fault_enable_read(struct counter_device *counter,
0895 struct counter_signal *signal,
0896 u8 *enable)
0897 {
0898 const struct quad8 *const priv = counter_priv(counter);
0899 const size_t channel_id = signal->id / 2;
0900
0901 *enable = !!(priv->cable_fault_enable & BIT(channel_id));
0902
0903 return 0;
0904 }
0905
0906 static int quad8_signal_cable_fault_enable_write(struct counter_device *counter,
0907 struct counter_signal *signal,
0908 u8 enable)
0909 {
0910 struct quad8 *const priv = counter_priv(counter);
0911 const size_t channel_id = signal->id / 2;
0912 unsigned long irqflags;
0913 unsigned int cable_fault_enable;
0914
0915 spin_lock_irqsave(&priv->lock, irqflags);
0916
0917 if (enable)
0918 priv->cable_fault_enable |= BIT(channel_id);
0919 else
0920 priv->cable_fault_enable &= ~BIT(channel_id);
0921
0922
0923 cable_fault_enable = ~priv->cable_fault_enable;
0924
0925 iowrite8(cable_fault_enable, &priv->reg->cable_status);
0926
0927 spin_unlock_irqrestore(&priv->lock, irqflags);
0928
0929 return 0;
0930 }
0931
0932 static int quad8_signal_fck_prescaler_read(struct counter_device *counter,
0933 struct counter_signal *signal,
0934 u8 *prescaler)
0935 {
0936 const struct quad8 *const priv = counter_priv(counter);
0937
0938 *prescaler = priv->fck_prescaler[signal->id / 2];
0939
0940 return 0;
0941 }
0942
0943 static int quad8_signal_fck_prescaler_write(struct counter_device *counter,
0944 struct counter_signal *signal,
0945 u8 prescaler)
0946 {
0947 struct quad8 *const priv = counter_priv(counter);
0948 const size_t channel_id = signal->id / 2;
0949 struct channel_reg __iomem *const chan = priv->reg->channel + channel_id;
0950 unsigned long irqflags;
0951
0952 spin_lock_irqsave(&priv->lock, irqflags);
0953
0954 priv->fck_prescaler[channel_id] = prescaler;
0955
0956
0957 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
0958
0959
0960 iowrite8(prescaler, &chan->data);
0961 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
0962 &chan->control);
0963
0964 spin_unlock_irqrestore(&priv->lock, irqflags);
0965
0966 return 0;
0967 }
0968
0969 static struct counter_comp quad8_signal_ext[] = {
0970 COUNTER_COMP_SIGNAL_BOOL("cable_fault", quad8_signal_cable_fault_read,
0971 NULL),
0972 COUNTER_COMP_SIGNAL_BOOL("cable_fault_enable",
0973 quad8_signal_cable_fault_enable_read,
0974 quad8_signal_cable_fault_enable_write),
0975 COUNTER_COMP_SIGNAL_U8("filter_clock_prescaler",
0976 quad8_signal_fck_prescaler_read,
0977 quad8_signal_fck_prescaler_write)
0978 };
0979
0980 static DEFINE_COUNTER_ENUM(quad8_index_pol_enum, quad8_index_polarity_modes);
0981 static DEFINE_COUNTER_ENUM(quad8_synch_mode_enum, quad8_synchronous_modes);
0982
0983 static struct counter_comp quad8_index_ext[] = {
0984 COUNTER_COMP_SIGNAL_ENUM("index_polarity", quad8_index_polarity_get,
0985 quad8_index_polarity_set,
0986 quad8_index_pol_enum),
0987 COUNTER_COMP_SIGNAL_ENUM("synchronous_mode", quad8_synchronous_mode_get,
0988 quad8_synchronous_mode_set,
0989 quad8_synch_mode_enum),
0990 };
0991
0992 #define QUAD8_QUAD_SIGNAL(_id, _name) { \
0993 .id = (_id), \
0994 .name = (_name), \
0995 .ext = quad8_signal_ext, \
0996 .num_ext = ARRAY_SIZE(quad8_signal_ext) \
0997 }
0998
0999 #define QUAD8_INDEX_SIGNAL(_id, _name) { \
1000 .id = (_id), \
1001 .name = (_name), \
1002 .ext = quad8_index_ext, \
1003 .num_ext = ARRAY_SIZE(quad8_index_ext) \
1004 }
1005
1006 static struct counter_signal quad8_signals[] = {
1007 QUAD8_QUAD_SIGNAL(0, "Channel 1 Quadrature A"),
1008 QUAD8_QUAD_SIGNAL(1, "Channel 1 Quadrature B"),
1009 QUAD8_QUAD_SIGNAL(2, "Channel 2 Quadrature A"),
1010 QUAD8_QUAD_SIGNAL(3, "Channel 2 Quadrature B"),
1011 QUAD8_QUAD_SIGNAL(4, "Channel 3 Quadrature A"),
1012 QUAD8_QUAD_SIGNAL(5, "Channel 3 Quadrature B"),
1013 QUAD8_QUAD_SIGNAL(6, "Channel 4 Quadrature A"),
1014 QUAD8_QUAD_SIGNAL(7, "Channel 4 Quadrature B"),
1015 QUAD8_QUAD_SIGNAL(8, "Channel 5 Quadrature A"),
1016 QUAD8_QUAD_SIGNAL(9, "Channel 5 Quadrature B"),
1017 QUAD8_QUAD_SIGNAL(10, "Channel 6 Quadrature A"),
1018 QUAD8_QUAD_SIGNAL(11, "Channel 6 Quadrature B"),
1019 QUAD8_QUAD_SIGNAL(12, "Channel 7 Quadrature A"),
1020 QUAD8_QUAD_SIGNAL(13, "Channel 7 Quadrature B"),
1021 QUAD8_QUAD_SIGNAL(14, "Channel 8 Quadrature A"),
1022 QUAD8_QUAD_SIGNAL(15, "Channel 8 Quadrature B"),
1023 QUAD8_INDEX_SIGNAL(16, "Channel 1 Index"),
1024 QUAD8_INDEX_SIGNAL(17, "Channel 2 Index"),
1025 QUAD8_INDEX_SIGNAL(18, "Channel 3 Index"),
1026 QUAD8_INDEX_SIGNAL(19, "Channel 4 Index"),
1027 QUAD8_INDEX_SIGNAL(20, "Channel 5 Index"),
1028 QUAD8_INDEX_SIGNAL(21, "Channel 6 Index"),
1029 QUAD8_INDEX_SIGNAL(22, "Channel 7 Index"),
1030 QUAD8_INDEX_SIGNAL(23, "Channel 8 Index")
1031 };
1032
1033 #define QUAD8_COUNT_SYNAPSES(_id) { \
1034 { \
1035 .actions_list = quad8_synapse_actions_list, \
1036 .num_actions = ARRAY_SIZE(quad8_synapse_actions_list), \
1037 .signal = quad8_signals + 2 * (_id) \
1038 }, \
1039 { \
1040 .actions_list = quad8_synapse_actions_list, \
1041 .num_actions = ARRAY_SIZE(quad8_synapse_actions_list), \
1042 .signal = quad8_signals + 2 * (_id) + 1 \
1043 }, \
1044 { \
1045 .actions_list = quad8_index_actions_list, \
1046 .num_actions = ARRAY_SIZE(quad8_index_actions_list), \
1047 .signal = quad8_signals + 2 * (_id) + 16 \
1048 } \
1049 }
1050
1051 static struct counter_synapse quad8_count_synapses[][3] = {
1052 QUAD8_COUNT_SYNAPSES(0), QUAD8_COUNT_SYNAPSES(1),
1053 QUAD8_COUNT_SYNAPSES(2), QUAD8_COUNT_SYNAPSES(3),
1054 QUAD8_COUNT_SYNAPSES(4), QUAD8_COUNT_SYNAPSES(5),
1055 QUAD8_COUNT_SYNAPSES(6), QUAD8_COUNT_SYNAPSES(7)
1056 };
1057
1058 static const enum counter_count_mode quad8_cnt_modes[] = {
1059 COUNTER_COUNT_MODE_NORMAL,
1060 COUNTER_COUNT_MODE_RANGE_LIMIT,
1061 COUNTER_COUNT_MODE_NON_RECYCLE,
1062 COUNTER_COUNT_MODE_MODULO_N,
1063 };
1064
1065 static DEFINE_COUNTER_AVAILABLE(quad8_count_mode_available, quad8_cnt_modes);
1066
1067 static DEFINE_COUNTER_ENUM(quad8_error_noise_enum, quad8_noise_error_states);
1068
1069 static struct counter_comp quad8_count_ext[] = {
1070 COUNTER_COMP_CEILING(quad8_count_ceiling_read,
1071 quad8_count_ceiling_write),
1072 COUNTER_COMP_FLOOR(quad8_count_floor_read, NULL),
1073 COUNTER_COMP_COUNT_MODE(quad8_count_mode_read, quad8_count_mode_write,
1074 quad8_count_mode_available),
1075 COUNTER_COMP_DIRECTION(quad8_direction_read),
1076 COUNTER_COMP_ENABLE(quad8_count_enable_read, quad8_count_enable_write),
1077 COUNTER_COMP_COUNT_ENUM("error_noise", quad8_error_noise_get, NULL,
1078 quad8_error_noise_enum),
1079 COUNTER_COMP_PRESET(quad8_count_preset_read, quad8_count_preset_write),
1080 COUNTER_COMP_PRESET_ENABLE(quad8_count_preset_enable_read,
1081 quad8_count_preset_enable_write),
1082 };
1083
1084 #define QUAD8_COUNT(_id, _cntname) { \
1085 .id = (_id), \
1086 .name = (_cntname), \
1087 .functions_list = quad8_count_functions_list, \
1088 .num_functions = ARRAY_SIZE(quad8_count_functions_list), \
1089 .synapses = quad8_count_synapses[(_id)], \
1090 .num_synapses = 2, \
1091 .ext = quad8_count_ext, \
1092 .num_ext = ARRAY_SIZE(quad8_count_ext) \
1093 }
1094
1095 static struct counter_count quad8_counts[] = {
1096 QUAD8_COUNT(0, "Channel 1 Count"),
1097 QUAD8_COUNT(1, "Channel 2 Count"),
1098 QUAD8_COUNT(2, "Channel 3 Count"),
1099 QUAD8_COUNT(3, "Channel 4 Count"),
1100 QUAD8_COUNT(4, "Channel 5 Count"),
1101 QUAD8_COUNT(5, "Channel 6 Count"),
1102 QUAD8_COUNT(6, "Channel 7 Count"),
1103 QUAD8_COUNT(7, "Channel 8 Count")
1104 };
1105
1106 static irqreturn_t quad8_irq_handler(int irq, void *private)
1107 {
1108 struct counter_device *counter = private;
1109 struct quad8 *const priv = counter_priv(counter);
1110 unsigned long irq_status;
1111 unsigned long channel;
1112 u8 event;
1113
1114 irq_status = ioread8(&priv->reg->interrupt_status);
1115 if (!irq_status)
1116 return IRQ_NONE;
1117
1118 for_each_set_bit(channel, &irq_status, QUAD8_NUM_COUNTERS) {
1119 switch (priv->irq_trigger[channel]) {
1120 case QUAD8_EVENT_CARRY:
1121 event = COUNTER_EVENT_OVERFLOW;
1122 break;
1123 case QUAD8_EVENT_COMPARE:
1124 event = COUNTER_EVENT_THRESHOLD;
1125 break;
1126 case QUAD8_EVENT_CARRY_BORROW:
1127 event = COUNTER_EVENT_OVERFLOW_UNDERFLOW;
1128 break;
1129 case QUAD8_EVENT_INDEX:
1130 event = COUNTER_EVENT_INDEX;
1131 break;
1132 default:
1133
1134 WARN_ONCE(true, "invalid interrupt trigger function %u configured for channel %lu\n",
1135 priv->irq_trigger[channel], channel);
1136 continue;
1137 }
1138
1139 counter_push_event(counter, event, channel);
1140 }
1141
1142
1143 iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper);
1144
1145 return IRQ_HANDLED;
1146 }
1147
1148 static void quad8_init_counter(struct channel_reg __iomem *const chan)
1149 {
1150 unsigned long i;
1151
1152
1153 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
1154
1155 iowrite8(0, &chan->data);
1156 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
1157 &chan->control);
1158
1159 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
1160
1161 for (i = 0; i < 3; i++)
1162 iowrite8(0x00, &chan->data);
1163
1164 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control);
1165
1166 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control);
1167
1168 iowrite8(QUAD8_CTR_CMR, &chan->control);
1169
1170 iowrite8(QUAD8_CTR_IOR, &chan->control);
1171
1172 iowrite8(QUAD8_CTR_IDR, &chan->control);
1173 }
1174
1175 static int quad8_probe(struct device *dev, unsigned int id)
1176 {
1177 struct counter_device *counter;
1178 struct quad8 *priv;
1179 unsigned long i;
1180 int err;
1181
1182 if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) {
1183 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
1184 base[id], base[id] + QUAD8_EXTENT);
1185 return -EBUSY;
1186 }
1187
1188 counter = devm_counter_alloc(dev, sizeof(*priv));
1189 if (!counter)
1190 return -ENOMEM;
1191 priv = counter_priv(counter);
1192
1193 priv->reg = devm_ioport_map(dev, base[id], QUAD8_EXTENT);
1194 if (!priv->reg)
1195 return -ENOMEM;
1196
1197
1198 counter->name = dev_name(dev);
1199 counter->parent = dev;
1200 counter->ops = &quad8_ops;
1201 counter->counts = quad8_counts;
1202 counter->num_counts = ARRAY_SIZE(quad8_counts);
1203 counter->signals = quad8_signals;
1204 counter->num_signals = ARRAY_SIZE(quad8_signals);
1205
1206 spin_lock_init(&priv->lock);
1207
1208
1209 iowrite8(0x00, &priv->reg->index_interrupt);
1210
1211 iowrite8(QUAD8_CHAN_OP_RESET_COUNTERS, &priv->reg->channel_oper);
1212
1213 for (i = 0; i < QUAD8_NUM_COUNTERS; i++)
1214 quad8_init_counter(priv->reg->channel + i);
1215
1216 iowrite8(0xFF, &priv->reg->cable_status);
1217
1218 iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper);
1219
1220 err = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler,
1221 IRQF_SHARED, counter->name, counter);
1222 if (err)
1223 return err;
1224
1225 err = devm_counter_add(dev, counter);
1226 if (err < 0)
1227 return dev_err_probe(dev, err, "Failed to add counter\n");
1228
1229 return 0;
1230 }
1231
1232 static struct isa_driver quad8_driver = {
1233 .probe = quad8_probe,
1234 .driver = {
1235 .name = "104-quad-8"
1236 }
1237 };
1238
1239 module_isa_driver(quad8_driver, num_quad8);
1240
1241 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
1242 MODULE_DESCRIPTION("ACCES 104-QUAD-8 driver");
1243 MODULE_LICENSE("GPL v2");