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/io.h> 13 #include <linux/ioport.h> 14 #include <linux/interrupt.h> 15 #include <linux/isa.h> 16 #include <linux/kernel.h> 17 #include <linux/module.h> 18 #include <linux/moduleparam.h> 19 #include <linux/types.h> 20 #include <linux/spinlock.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_hw_array(base, uint, ioport, &num_quad8, 0); 27 MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses"); 28 29 static unsigned int irq[max_num_isa_dev(QUAD8_EXTENT)]; 30 module_param_hw_array(irq, uint, irq, NULL, 0); 31 MODULE_PARM_DESC(irq, "ACCES 104-QUAD-8 interrupt line numbers"); 32 33 #define QUAD8_NUM_COUNTERS 8 34 35 /** 36 * struct quad8 - device private data structure 37 * @lock: lock to prevent clobbering device states during R/W ops 38 * @counter: instance of the counter_device 39 * @fck_prescaler: array of filter clock prescaler configurations 40 * @preset: array of preset values 41 * @count_mode: array of count mode configurations 42 * @quadrature_mode: array of quadrature mode configurations 43 * @quadrature_scale: array of quadrature mode scale configurations 44 * @ab_enable: array of A and B inputs enable configurations 45 * @preset_enable: array of set_to_preset_on_index attribute configurations 46 * @irq_trigger: array of current IRQ trigger function configurations 47 * @next_irq_trigger: array of next IRQ trigger function configurations 48 * @synchronous_mode: array of index function synchronous mode configurations 49 * @index_polarity: array of index function polarity configurations 50 * @cable_fault_enable: differential encoder cable status enable configurations 51 * @base: base port address of the device 52 */ 53 struct quad8 { 54 spinlock_t lock; 55 struct counter_device counter; 56 unsigned int fck_prescaler[QUAD8_NUM_COUNTERS]; 57 unsigned int preset[QUAD8_NUM_COUNTERS]; 58 unsigned int count_mode[QUAD8_NUM_COUNTERS]; 59 unsigned int quadrature_mode[QUAD8_NUM_COUNTERS]; 60 unsigned int quadrature_scale[QUAD8_NUM_COUNTERS]; 61 unsigned int ab_enable[QUAD8_NUM_COUNTERS]; 62 unsigned int preset_enable[QUAD8_NUM_COUNTERS]; 63 unsigned int irq_trigger[QUAD8_NUM_COUNTERS]; 64 unsigned int next_irq_trigger[QUAD8_NUM_COUNTERS]; 65 unsigned int synchronous_mode[QUAD8_NUM_COUNTERS]; 66 unsigned int index_polarity[QUAD8_NUM_COUNTERS]; 67 unsigned int cable_fault_enable; 68 unsigned int base; 69 }; 70 71 #define QUAD8_REG_INTERRUPT_STATUS 0x10 72 #define QUAD8_REG_CHAN_OP 0x11 73 #define QUAD8_REG_INDEX_INTERRUPT 0x12 74 #define QUAD8_REG_INDEX_INPUT_LEVELS 0x16 75 #define QUAD8_DIFF_ENCODER_CABLE_STATUS 0x17 76 /* Borrow Toggle flip-flop */ 77 #define QUAD8_FLAG_BT BIT(0) 78 /* Carry Toggle flip-flop */ 79 #define QUAD8_FLAG_CT BIT(1) 80 /* Error flag */ 81 #define QUAD8_FLAG_E BIT(4) 82 /* Up/Down flag */ 83 #define QUAD8_FLAG_UD BIT(5) 84 /* Reset and Load Signal Decoders */ 85 #define QUAD8_CTR_RLD 0x00 86 /* Counter Mode Register */ 87 #define QUAD8_CTR_CMR 0x20 88 /* Input / Output Control Register */ 89 #define QUAD8_CTR_IOR 0x40 90 /* Index Control Register */ 91 #define QUAD8_CTR_IDR 0x60 92 /* Reset Byte Pointer (three byte data pointer) */ 93 #define QUAD8_RLD_RESET_BP 0x01 94 /* Reset Counter */ 95 #define QUAD8_RLD_RESET_CNTR 0x02 96 /* Reset Borrow Toggle, Carry Toggle, Compare Toggle, and Sign flags */ 97 #define QUAD8_RLD_RESET_FLAGS 0x04 98 /* Reset Error flag */ 99 #define QUAD8_RLD_RESET_E 0x06 100 /* Preset Register to Counter */ 101 #define QUAD8_RLD_PRESET_CNTR 0x08 102 /* Transfer Counter to Output Latch */ 103 #define QUAD8_RLD_CNTR_OUT 0x10 104 /* Transfer Preset Register LSB to FCK Prescaler */ 105 #define QUAD8_RLD_PRESET_PSC 0x18 106 #define QUAD8_CHAN_OP_RESET_COUNTERS 0x01 107 #define QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC 0x04 108 #define QUAD8_CMR_QUADRATURE_X1 0x08 109 #define QUAD8_CMR_QUADRATURE_X2 0x10 110 #define QUAD8_CMR_QUADRATURE_X4 0x18 111 112 static int quad8_signal_read(struct counter_device *counter, 113 struct counter_signal *signal, 114 enum counter_signal_level *level) 115 { 116 const struct quad8 *const priv = counter->priv; 117 unsigned int state; 118 119 /* Only Index signal levels can be read */ 120 if (signal->id < 16) 121 return -EINVAL; 122 123 state = inb(priv->base + QUAD8_REG_INDEX_INPUT_LEVELS) 124 & BIT(signal->id - 16); 125 126 *level = (state) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW; 127 128 return 0; 129 } 130 131 static int quad8_count_read(struct counter_device *counter, 132 struct counter_count *count, u64 *val) 133 { 134 struct quad8 *const priv = counter->priv; 135 const int base_offset = priv->base + 2 * count->id; 136 unsigned int flags; 137 unsigned int borrow; 138 unsigned int carry; 139 unsigned long irqflags; 140 int i; 141 142 flags = inb(base_offset + 1); 143 borrow = flags & QUAD8_FLAG_BT; 144 carry = !!(flags & QUAD8_FLAG_CT); 145 146 /* Borrow XOR Carry effectively doubles count range */ 147 *val = (unsigned long)(borrow ^ carry) << 24; 148 149 spin_lock_irqsave(&priv->lock, irqflags); 150 151 /* Reset Byte Pointer; transfer Counter to Output Latch */ 152 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT, 153 base_offset + 1); 154 155 for (i = 0; i < 3; i++) 156 *val |= (unsigned long)inb(base_offset) << (8 * i); 157 158 spin_unlock_irqrestore(&priv->lock, irqflags); 159 160 return 0; 161 } 162 163 static int quad8_count_write(struct counter_device *counter, 164 struct counter_count *count, u64 val) 165 { 166 struct quad8 *const priv = counter->priv; 167 const int base_offset = priv->base + 2 * count->id; 168 unsigned long irqflags; 169 int i; 170 171 /* Only 24-bit values are supported */ 172 if (val > 0xFFFFFF) 173 return -ERANGE; 174 175 spin_lock_irqsave(&priv->lock, irqflags); 176 177 /* Reset Byte Pointer */ 178 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); 179 180 /* Counter can only be set via Preset Register */ 181 for (i = 0; i < 3; i++) 182 outb(val >> (8 * i), base_offset); 183 184 /* Transfer Preset Register to Counter */ 185 outb(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, base_offset + 1); 186 187 /* Reset Byte Pointer */ 188 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); 189 190 /* Set Preset Register back to original value */ 191 val = priv->preset[count->id]; 192 for (i = 0; i < 3; i++) 193 outb(val >> (8 * i), base_offset); 194 195 /* Reset Borrow, Carry, Compare, and Sign flags */ 196 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1); 197 /* Reset Error flag */ 198 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1); 199 200 spin_unlock_irqrestore(&priv->lock, irqflags); 201 202 return 0; 203 } 204 205 static const enum counter_function quad8_count_functions_list[] = { 206 COUNTER_FUNCTION_PULSE_DIRECTION, 207 COUNTER_FUNCTION_QUADRATURE_X1_A, 208 COUNTER_FUNCTION_QUADRATURE_X2_A, 209 COUNTER_FUNCTION_QUADRATURE_X4, 210 }; 211 212 static int quad8_function_read(struct counter_device *counter, 213 struct counter_count *count, 214 enum counter_function *function) 215 { 216 struct quad8 *const priv = counter->priv; 217 const int id = count->id; 218 unsigned long irqflags; 219 220 spin_lock_irqsave(&priv->lock, irqflags); 221 222 if (priv->quadrature_mode[id]) 223 switch (priv->quadrature_scale[id]) { 224 case 0: 225 *function = COUNTER_FUNCTION_QUADRATURE_X1_A; 226 break; 227 case 1: 228 *function = COUNTER_FUNCTION_QUADRATURE_X2_A; 229 break; 230 case 2: 231 *function = COUNTER_FUNCTION_QUADRATURE_X4; 232 break; 233 } 234 else 235 *function = COUNTER_FUNCTION_PULSE_DIRECTION; 236 237 spin_unlock_irqrestore(&priv->lock, irqflags); 238 239 return 0; 240 } 241 242 static int quad8_function_write(struct counter_device *counter, 243 struct counter_count *count, 244 enum counter_function function) 245 { 246 struct quad8 *const priv = counter->priv; 247 const int id = count->id; 248 unsigned int *const quadrature_mode = priv->quadrature_mode + id; 249 unsigned int *const scale = priv->quadrature_scale + id; 250 unsigned int *const synchronous_mode = priv->synchronous_mode + id; 251 const int base_offset = priv->base + 2 * id + 1; 252 unsigned long irqflags; 253 unsigned int mode_cfg; 254 unsigned int idr_cfg; 255 256 spin_lock_irqsave(&priv->lock, irqflags); 257 258 mode_cfg = priv->count_mode[id] << 1; 259 idr_cfg = priv->index_polarity[id] << 1; 260 261 if (function == COUNTER_FUNCTION_PULSE_DIRECTION) { 262 *quadrature_mode = 0; 263 264 /* Quadrature scaling only available in quadrature mode */ 265 *scale = 0; 266 267 /* Synchronous function not supported in non-quadrature mode */ 268 if (*synchronous_mode) { 269 *synchronous_mode = 0; 270 /* Disable synchronous function mode */ 271 outb(QUAD8_CTR_IDR | idr_cfg, base_offset); 272 } 273 } else { 274 *quadrature_mode = 1; 275 276 switch (function) { 277 case COUNTER_FUNCTION_QUADRATURE_X1_A: 278 *scale = 0; 279 mode_cfg |= QUAD8_CMR_QUADRATURE_X1; 280 break; 281 case COUNTER_FUNCTION_QUADRATURE_X2_A: 282 *scale = 1; 283 mode_cfg |= QUAD8_CMR_QUADRATURE_X2; 284 break; 285 case COUNTER_FUNCTION_QUADRATURE_X4: 286 *scale = 2; 287 mode_cfg |= QUAD8_CMR_QUADRATURE_X4; 288 break; 289 default: 290 /* should never reach this path */ 291 spin_unlock_irqrestore(&priv->lock, irqflags); 292 return -EINVAL; 293 } 294 } 295 296 /* Load mode configuration to Counter Mode Register */ 297 outb(QUAD8_CTR_CMR | mode_cfg, base_offset); 298 299 spin_unlock_irqrestore(&priv->lock, irqflags); 300 301 return 0; 302 } 303 304 static int quad8_direction_read(struct counter_device *counter, 305 struct counter_count *count, 306 enum counter_count_direction *direction) 307 { 308 const struct quad8 *const priv = counter->priv; 309 unsigned int ud_flag; 310 const unsigned int flag_addr = priv->base + 2 * count->id + 1; 311 312 /* U/D flag: nonzero = up, zero = down */ 313 ud_flag = inb(flag_addr) & QUAD8_FLAG_UD; 314 315 *direction = (ud_flag) ? COUNTER_COUNT_DIRECTION_FORWARD : 316 COUNTER_COUNT_DIRECTION_BACKWARD; 317 318 return 0; 319 } 320 321 static const enum counter_synapse_action quad8_index_actions_list[] = { 322 COUNTER_SYNAPSE_ACTION_NONE, 323 COUNTER_SYNAPSE_ACTION_RISING_EDGE, 324 }; 325 326 static const enum counter_synapse_action quad8_synapse_actions_list[] = { 327 COUNTER_SYNAPSE_ACTION_NONE, 328 COUNTER_SYNAPSE_ACTION_RISING_EDGE, 329 COUNTER_SYNAPSE_ACTION_FALLING_EDGE, 330 COUNTER_SYNAPSE_ACTION_BOTH_EDGES, 331 }; 332 333 static int quad8_action_read(struct counter_device *counter, 334 struct counter_count *count, 335 struct counter_synapse *synapse, 336 enum counter_synapse_action *action) 337 { 338 struct quad8 *const priv = counter->priv; 339 int err; 340 enum counter_function function; 341 const size_t signal_a_id = count->synapses[0].signal->id; 342 enum counter_count_direction direction; 343 344 /* Handle Index signals */ 345 if (synapse->signal->id >= 16) { 346 if (priv->preset_enable[count->id]) 347 *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; 348 else 349 *action = COUNTER_SYNAPSE_ACTION_NONE; 350 351 return 0; 352 } 353 354 err = quad8_function_read(counter, count, &function); 355 if (err) 356 return err; 357 358 /* Default action mode */ 359 *action = COUNTER_SYNAPSE_ACTION_NONE; 360 361 /* Determine action mode based on current count function mode */ 362 switch (function) { 363 case COUNTER_FUNCTION_PULSE_DIRECTION: 364 if (synapse->signal->id == signal_a_id) 365 *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; 366 return 0; 367 case COUNTER_FUNCTION_QUADRATURE_X1_A: 368 if (synapse->signal->id == signal_a_id) { 369 err = quad8_direction_read(counter, count, &direction); 370 if (err) 371 return err; 372 373 if (direction == COUNTER_COUNT_DIRECTION_FORWARD) 374 *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; 375 else 376 *action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE; 377 } 378 return 0; 379 case COUNTER_FUNCTION_QUADRATURE_X2_A: 380 if (synapse->signal->id == signal_a_id) 381 *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 382 return 0; 383 case COUNTER_FUNCTION_QUADRATURE_X4: 384 *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 385 return 0; 386 default: 387 /* should never reach this path */ 388 return -EINVAL; 389 } 390 } 391 392 enum { 393 QUAD8_EVENT_NONE = -1, 394 QUAD8_EVENT_CARRY = 0, 395 QUAD8_EVENT_COMPARE = 1, 396 QUAD8_EVENT_CARRY_BORROW = 2, 397 QUAD8_EVENT_INDEX = 3, 398 }; 399 400 static int quad8_events_configure(struct counter_device *counter) 401 { 402 struct quad8 *const priv = counter->priv; 403 unsigned long irq_enabled = 0; 404 unsigned long irqflags; 405 size_t channel; 406 unsigned long ior_cfg; 407 unsigned long base_offset; 408 409 spin_lock_irqsave(&priv->lock, irqflags); 410 411 /* Enable interrupts for the requested channels, disable for the rest */ 412 for (channel = 0; channel < QUAD8_NUM_COUNTERS; channel++) { 413 if (priv->next_irq_trigger[channel] == QUAD8_EVENT_NONE) 414 continue; 415 416 if (priv->irq_trigger[channel] != priv->next_irq_trigger[channel]) { 417 /* Save new IRQ function configuration */ 418 priv->irq_trigger[channel] = priv->next_irq_trigger[channel]; 419 420 /* Load configuration to I/O Control Register */ 421 ior_cfg = priv->ab_enable[channel] | 422 priv->preset_enable[channel] << 1 | 423 priv->irq_trigger[channel] << 3; 424 base_offset = priv->base + 2 * channel + 1; 425 outb(QUAD8_CTR_IOR | ior_cfg, base_offset); 426 } 427 428 /* Reset next IRQ trigger function configuration */ 429 priv->next_irq_trigger[channel] = QUAD8_EVENT_NONE; 430 431 /* Enable IRQ line */ 432 irq_enabled |= BIT(channel); 433 } 434 435 outb(irq_enabled, priv->base + QUAD8_REG_INDEX_INTERRUPT); 436 437 spin_unlock_irqrestore(&priv->lock, irqflags); 438 439 return 0; 440 } 441 442 static int quad8_watch_validate(struct counter_device *counter, 443 const struct counter_watch *watch) 444 { 445 struct quad8 *const priv = counter->priv; 446 447 if (watch->channel > QUAD8_NUM_COUNTERS - 1) 448 return -EINVAL; 449 450 switch (watch->event) { 451 case COUNTER_EVENT_OVERFLOW: 452 if (priv->next_irq_trigger[watch->channel] == QUAD8_EVENT_NONE) 453 priv->next_irq_trigger[watch->channel] = QUAD8_EVENT_CARRY; 454 else if (priv->next_irq_trigger[watch->channel] != QUAD8_EVENT_CARRY) 455 return -EINVAL; 456 return 0; 457 case COUNTER_EVENT_THRESHOLD: 458 if (priv->next_irq_trigger[watch->channel] == QUAD8_EVENT_NONE) 459 priv->next_irq_trigger[watch->channel] = QUAD8_EVENT_COMPARE; 460 else if (priv->next_irq_trigger[watch->channel] != QUAD8_EVENT_COMPARE) 461 return -EINVAL; 462 return 0; 463 case COUNTER_EVENT_OVERFLOW_UNDERFLOW: 464 if (priv->next_irq_trigger[watch->channel] == QUAD8_EVENT_NONE) 465 priv->next_irq_trigger[watch->channel] = QUAD8_EVENT_CARRY_BORROW; 466 else if (priv->next_irq_trigger[watch->channel] != QUAD8_EVENT_CARRY_BORROW) 467 return -EINVAL; 468 return 0; 469 case COUNTER_EVENT_INDEX: 470 if (priv->next_irq_trigger[watch->channel] == QUAD8_EVENT_NONE) 471 priv->next_irq_trigger[watch->channel] = QUAD8_EVENT_INDEX; 472 else if (priv->next_irq_trigger[watch->channel] != QUAD8_EVENT_INDEX) 473 return -EINVAL; 474 return 0; 475 default: 476 return -EINVAL; 477 } 478 } 479 480 static const struct counter_ops quad8_ops = { 481 .signal_read = quad8_signal_read, 482 .count_read = quad8_count_read, 483 .count_write = quad8_count_write, 484 .function_read = quad8_function_read, 485 .function_write = quad8_function_write, 486 .action_read = quad8_action_read, 487 .events_configure = quad8_events_configure, 488 .watch_validate = quad8_watch_validate, 489 }; 490 491 static const char *const quad8_index_polarity_modes[] = { 492 "negative", 493 "positive" 494 }; 495 496 static int quad8_index_polarity_get(struct counter_device *counter, 497 struct counter_signal *signal, 498 u32 *index_polarity) 499 { 500 const struct quad8 *const priv = counter->priv; 501 const size_t channel_id = signal->id - 16; 502 503 *index_polarity = priv->index_polarity[channel_id]; 504 505 return 0; 506 } 507 508 static int quad8_index_polarity_set(struct counter_device *counter, 509 struct counter_signal *signal, 510 u32 index_polarity) 511 { 512 struct quad8 *const priv = counter->priv; 513 const size_t channel_id = signal->id - 16; 514 const int base_offset = priv->base + 2 * channel_id + 1; 515 unsigned long irqflags; 516 unsigned int idr_cfg = index_polarity << 1; 517 518 spin_lock_irqsave(&priv->lock, irqflags); 519 520 idr_cfg |= priv->synchronous_mode[channel_id]; 521 522 priv->index_polarity[channel_id] = index_polarity; 523 524 /* Load Index Control configuration to Index Control Register */ 525 outb(QUAD8_CTR_IDR | idr_cfg, base_offset); 526 527 spin_unlock_irqrestore(&priv->lock, irqflags); 528 529 return 0; 530 } 531 532 static const char *const quad8_synchronous_modes[] = { 533 "non-synchronous", 534 "synchronous" 535 }; 536 537 static int quad8_synchronous_mode_get(struct counter_device *counter, 538 struct counter_signal *signal, 539 u32 *synchronous_mode) 540 { 541 const struct quad8 *const priv = counter->priv; 542 const size_t channel_id = signal->id - 16; 543 544 *synchronous_mode = priv->synchronous_mode[channel_id]; 545 546 return 0; 547 } 548 549 static int quad8_synchronous_mode_set(struct counter_device *counter, 550 struct counter_signal *signal, 551 u32 synchronous_mode) 552 { 553 struct quad8 *const priv = counter->priv; 554 const size_t channel_id = signal->id - 16; 555 const int base_offset = priv->base + 2 * channel_id + 1; 556 unsigned long irqflags; 557 unsigned int idr_cfg = synchronous_mode; 558 559 spin_lock_irqsave(&priv->lock, irqflags); 560 561 idr_cfg |= priv->index_polarity[channel_id] << 1; 562 563 /* Index function must be non-synchronous in non-quadrature mode */ 564 if (synchronous_mode && !priv->quadrature_mode[channel_id]) { 565 spin_unlock_irqrestore(&priv->lock, irqflags); 566 return -EINVAL; 567 } 568 569 priv->synchronous_mode[channel_id] = synchronous_mode; 570 571 /* Load Index Control configuration to Index Control Register */ 572 outb(QUAD8_CTR_IDR | idr_cfg, base_offset); 573 574 spin_unlock_irqrestore(&priv->lock, irqflags); 575 576 return 0; 577 } 578 579 static int quad8_count_floor_read(struct counter_device *counter, 580 struct counter_count *count, u64 *floor) 581 { 582 /* Only a floor of 0 is supported */ 583 *floor = 0; 584 585 return 0; 586 } 587 588 static int quad8_count_mode_read(struct counter_device *counter, 589 struct counter_count *count, 590 enum counter_count_mode *cnt_mode) 591 { 592 const struct quad8 *const priv = counter->priv; 593 594 /* Map 104-QUAD-8 count mode to Generic Counter count mode */ 595 switch (priv->count_mode[count->id]) { 596 case 0: 597 *cnt_mode = COUNTER_COUNT_MODE_NORMAL; 598 break; 599 case 1: 600 *cnt_mode = COUNTER_COUNT_MODE_RANGE_LIMIT; 601 break; 602 case 2: 603 *cnt_mode = COUNTER_COUNT_MODE_NON_RECYCLE; 604 break; 605 case 3: 606 *cnt_mode = COUNTER_COUNT_MODE_MODULO_N; 607 break; 608 } 609 610 return 0; 611 } 612 613 static int quad8_count_mode_write(struct counter_device *counter, 614 struct counter_count *count, 615 enum counter_count_mode cnt_mode) 616 { 617 struct quad8 *const priv = counter->priv; 618 unsigned int count_mode; 619 unsigned int mode_cfg; 620 const int base_offset = priv->base + 2 * count->id + 1; 621 unsigned long irqflags; 622 623 /* Map Generic Counter count mode to 104-QUAD-8 count mode */ 624 switch (cnt_mode) { 625 case COUNTER_COUNT_MODE_NORMAL: 626 count_mode = 0; 627 break; 628 case COUNTER_COUNT_MODE_RANGE_LIMIT: 629 count_mode = 1; 630 break; 631 case COUNTER_COUNT_MODE_NON_RECYCLE: 632 count_mode = 2; 633 break; 634 case COUNTER_COUNT_MODE_MODULO_N: 635 count_mode = 3; 636 break; 637 default: 638 /* should never reach this path */ 639 return -EINVAL; 640 } 641 642 spin_lock_irqsave(&priv->lock, irqflags); 643 644 priv->count_mode[count->id] = count_mode; 645 646 /* Set count mode configuration value */ 647 mode_cfg = count_mode << 1; 648 649 /* Add quadrature mode configuration */ 650 if (priv->quadrature_mode[count->id]) 651 mode_cfg |= (priv->quadrature_scale[count->id] + 1) << 3; 652 653 /* Load mode configuration to Counter Mode Register */ 654 outb(QUAD8_CTR_CMR | mode_cfg, base_offset); 655 656 spin_unlock_irqrestore(&priv->lock, irqflags); 657 658 return 0; 659 } 660 661 static int quad8_count_enable_read(struct counter_device *counter, 662 struct counter_count *count, u8 *enable) 663 { 664 const struct quad8 *const priv = counter->priv; 665 666 *enable = priv->ab_enable[count->id]; 667 668 return 0; 669 } 670 671 static int quad8_count_enable_write(struct counter_device *counter, 672 struct counter_count *count, u8 enable) 673 { 674 struct quad8 *const priv = counter->priv; 675 const int base_offset = priv->base + 2 * count->id; 676 unsigned long irqflags; 677 unsigned int ior_cfg; 678 679 spin_lock_irqsave(&priv->lock, irqflags); 680 681 priv->ab_enable[count->id] = enable; 682 683 ior_cfg = enable | priv->preset_enable[count->id] << 1 | 684 priv->irq_trigger[count->id] << 3; 685 686 /* Load I/O control configuration */ 687 outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1); 688 689 spin_unlock_irqrestore(&priv->lock, irqflags); 690 691 return 0; 692 } 693 694 static const char *const quad8_noise_error_states[] = { 695 "No excessive noise is present at the count inputs", 696 "Excessive noise is present at the count inputs" 697 }; 698 699 static int quad8_error_noise_get(struct counter_device *counter, 700 struct counter_count *count, u32 *noise_error) 701 { 702 const struct quad8 *const priv = counter->priv; 703 const int base_offset = priv->base + 2 * count->id + 1; 704 705 *noise_error = !!(inb(base_offset) & QUAD8_FLAG_E); 706 707 return 0; 708 } 709 710 static int quad8_count_preset_read(struct counter_device *counter, 711 struct counter_count *count, u64 *preset) 712 { 713 const struct quad8 *const priv = counter->priv; 714 715 *preset = priv->preset[count->id]; 716 717 return 0; 718 } 719 720 static void quad8_preset_register_set(struct quad8 *const priv, const int id, 721 const unsigned int preset) 722 { 723 const unsigned int base_offset = priv->base + 2 * id; 724 int i; 725 726 priv->preset[id] = preset; 727 728 /* Reset Byte Pointer */ 729 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); 730 731 /* Set Preset Register */ 732 for (i = 0; i < 3; i++) 733 outb(preset >> (8 * i), base_offset); 734 } 735 736 static int quad8_count_preset_write(struct counter_device *counter, 737 struct counter_count *count, u64 preset) 738 { 739 struct quad8 *const priv = counter->priv; 740 unsigned long irqflags; 741 742 /* Only 24-bit values are supported */ 743 if (preset > 0xFFFFFF) 744 return -ERANGE; 745 746 spin_lock_irqsave(&priv->lock, irqflags); 747 748 quad8_preset_register_set(priv, count->id, preset); 749 750 spin_unlock_irqrestore(&priv->lock, irqflags); 751 752 return 0; 753 } 754 755 static int quad8_count_ceiling_read(struct counter_device *counter, 756 struct counter_count *count, u64 *ceiling) 757 { 758 struct quad8 *const priv = counter->priv; 759 unsigned long irqflags; 760 761 spin_lock_irqsave(&priv->lock, irqflags); 762 763 /* Range Limit and Modulo-N count modes use preset value as ceiling */ 764 switch (priv->count_mode[count->id]) { 765 case 1: 766 case 3: 767 *ceiling = priv->preset[count->id]; 768 break; 769 default: 770 /* By default 0x1FFFFFF (25 bits unsigned) is maximum count */ 771 *ceiling = 0x1FFFFFF; 772 break; 773 } 774 775 spin_unlock_irqrestore(&priv->lock, irqflags); 776 777 return 0; 778 } 779 780 static int quad8_count_ceiling_write(struct counter_device *counter, 781 struct counter_count *count, u64 ceiling) 782 { 783 struct quad8 *const priv = counter->priv; 784 unsigned long irqflags; 785 786 /* Only 24-bit values are supported */ 787 if (ceiling > 0xFFFFFF) 788 return -ERANGE; 789 790 spin_lock_irqsave(&priv->lock, irqflags); 791 792 /* Range Limit and Modulo-N count modes use preset value as ceiling */ 793 switch (priv->count_mode[count->id]) { 794 case 1: 795 case 3: 796 quad8_preset_register_set(priv, count->id, ceiling); 797 spin_unlock_irqrestore(&priv->lock, irqflags); 798 return 0; 799 } 800 801 spin_unlock_irqrestore(&priv->lock, irqflags); 802 803 return -EINVAL; 804 } 805 806 static int quad8_count_preset_enable_read(struct counter_device *counter, 807 struct counter_count *count, 808 u8 *preset_enable) 809 { 810 const struct quad8 *const priv = counter->priv; 811 812 *preset_enable = !priv->preset_enable[count->id]; 813 814 return 0; 815 } 816 817 static int quad8_count_preset_enable_write(struct counter_device *counter, 818 struct counter_count *count, 819 u8 preset_enable) 820 { 821 struct quad8 *const priv = counter->priv; 822 const int base_offset = priv->base + 2 * count->id + 1; 823 unsigned long irqflags; 824 unsigned int ior_cfg; 825 826 /* Preset enable is active low in Input/Output Control register */ 827 preset_enable = !preset_enable; 828 829 spin_lock_irqsave(&priv->lock, irqflags); 830 831 priv->preset_enable[count->id] = preset_enable; 832 833 ior_cfg = priv->ab_enable[count->id] | preset_enable << 1 | 834 priv->irq_trigger[count->id] << 3; 835 836 /* Load I/O control configuration to Input / Output Control Register */ 837 outb(QUAD8_CTR_IOR | ior_cfg, base_offset); 838 839 spin_unlock_irqrestore(&priv->lock, irqflags); 840 841 return 0; 842 } 843 844 static int quad8_signal_cable_fault_read(struct counter_device *counter, 845 struct counter_signal *signal, 846 u8 *cable_fault) 847 { 848 struct quad8 *const priv = counter->priv; 849 const size_t channel_id = signal->id / 2; 850 unsigned long irqflags; 851 bool disabled; 852 unsigned int status; 853 854 spin_lock_irqsave(&priv->lock, irqflags); 855 856 disabled = !(priv->cable_fault_enable & BIT(channel_id)); 857 858 if (disabled) { 859 spin_unlock_irqrestore(&priv->lock, irqflags); 860 return -EINVAL; 861 } 862 863 /* Logic 0 = cable fault */ 864 status = inb(priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS); 865 866 spin_unlock_irqrestore(&priv->lock, irqflags); 867 868 /* Mask respective channel and invert logic */ 869 *cable_fault = !(status & BIT(channel_id)); 870 871 return 0; 872 } 873 874 static int quad8_signal_cable_fault_enable_read(struct counter_device *counter, 875 struct counter_signal *signal, 876 u8 *enable) 877 { 878 const struct quad8 *const priv = counter->priv; 879 const size_t channel_id = signal->id / 2; 880 881 *enable = !!(priv->cable_fault_enable & BIT(channel_id)); 882 883 return 0; 884 } 885 886 static int quad8_signal_cable_fault_enable_write(struct counter_device *counter, 887 struct counter_signal *signal, 888 u8 enable) 889 { 890 struct quad8 *const priv = counter->priv; 891 const size_t channel_id = signal->id / 2; 892 unsigned long irqflags; 893 unsigned int cable_fault_enable; 894 895 spin_lock_irqsave(&priv->lock, irqflags); 896 897 if (enable) 898 priv->cable_fault_enable |= BIT(channel_id); 899 else 900 priv->cable_fault_enable &= ~BIT(channel_id); 901 902 /* Enable is active low in Differential Encoder Cable Status register */ 903 cable_fault_enable = ~priv->cable_fault_enable; 904 905 outb(cable_fault_enable, priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS); 906 907 spin_unlock_irqrestore(&priv->lock, irqflags); 908 909 return 0; 910 } 911 912 static int quad8_signal_fck_prescaler_read(struct counter_device *counter, 913 struct counter_signal *signal, 914 u8 *prescaler) 915 { 916 const struct quad8 *const priv = counter->priv; 917 918 *prescaler = priv->fck_prescaler[signal->id / 2]; 919 920 return 0; 921 } 922 923 static int quad8_signal_fck_prescaler_write(struct counter_device *counter, 924 struct counter_signal *signal, 925 u8 prescaler) 926 { 927 struct quad8 *const priv = counter->priv; 928 const size_t channel_id = signal->id / 2; 929 const int base_offset = priv->base + 2 * channel_id; 930 unsigned long irqflags; 931 932 spin_lock_irqsave(&priv->lock, irqflags); 933 934 priv->fck_prescaler[channel_id] = prescaler; 935 936 /* Reset Byte Pointer */ 937 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); 938 939 /* Set filter clock factor */ 940 outb(prescaler, base_offset); 941 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, 942 base_offset + 1); 943 944 spin_unlock_irqrestore(&priv->lock, irqflags); 945 946 return 0; 947 } 948 949 static struct counter_comp quad8_signal_ext[] = { 950 COUNTER_COMP_SIGNAL_BOOL("cable_fault", quad8_signal_cable_fault_read, 951 NULL), 952 COUNTER_COMP_SIGNAL_BOOL("cable_fault_enable", 953 quad8_signal_cable_fault_enable_read, 954 quad8_signal_cable_fault_enable_write), 955 COUNTER_COMP_SIGNAL_U8("filter_clock_prescaler", 956 quad8_signal_fck_prescaler_read, 957 quad8_signal_fck_prescaler_write) 958 }; 959 960 static DEFINE_COUNTER_ENUM(quad8_index_pol_enum, quad8_index_polarity_modes); 961 static DEFINE_COUNTER_ENUM(quad8_synch_mode_enum, quad8_synchronous_modes); 962 963 static struct counter_comp quad8_index_ext[] = { 964 COUNTER_COMP_SIGNAL_ENUM("index_polarity", quad8_index_polarity_get, 965 quad8_index_polarity_set, 966 quad8_index_pol_enum), 967 COUNTER_COMP_SIGNAL_ENUM("synchronous_mode", quad8_synchronous_mode_get, 968 quad8_synchronous_mode_set, 969 quad8_synch_mode_enum), 970 }; 971 972 #define QUAD8_QUAD_SIGNAL(_id, _name) { \ 973 .id = (_id), \ 974 .name = (_name), \ 975 .ext = quad8_signal_ext, \ 976 .num_ext = ARRAY_SIZE(quad8_signal_ext) \ 977 } 978 979 #define QUAD8_INDEX_SIGNAL(_id, _name) { \ 980 .id = (_id), \ 981 .name = (_name), \ 982 .ext = quad8_index_ext, \ 983 .num_ext = ARRAY_SIZE(quad8_index_ext) \ 984 } 985 986 static struct counter_signal quad8_signals[] = { 987 QUAD8_QUAD_SIGNAL(0, "Channel 1 Quadrature A"), 988 QUAD8_QUAD_SIGNAL(1, "Channel 1 Quadrature B"), 989 QUAD8_QUAD_SIGNAL(2, "Channel 2 Quadrature A"), 990 QUAD8_QUAD_SIGNAL(3, "Channel 2 Quadrature B"), 991 QUAD8_QUAD_SIGNAL(4, "Channel 3 Quadrature A"), 992 QUAD8_QUAD_SIGNAL(5, "Channel 3 Quadrature B"), 993 QUAD8_QUAD_SIGNAL(6, "Channel 4 Quadrature A"), 994 QUAD8_QUAD_SIGNAL(7, "Channel 4 Quadrature B"), 995 QUAD8_QUAD_SIGNAL(8, "Channel 5 Quadrature A"), 996 QUAD8_QUAD_SIGNAL(9, "Channel 5 Quadrature B"), 997 QUAD8_QUAD_SIGNAL(10, "Channel 6 Quadrature A"), 998 QUAD8_QUAD_SIGNAL(11, "Channel 6 Quadrature B"), 999 QUAD8_QUAD_SIGNAL(12, "Channel 7 Quadrature A"), 1000 QUAD8_QUAD_SIGNAL(13, "Channel 7 Quadrature B"), 1001 QUAD8_QUAD_SIGNAL(14, "Channel 8 Quadrature A"), 1002 QUAD8_QUAD_SIGNAL(15, "Channel 8 Quadrature B"), 1003 QUAD8_INDEX_SIGNAL(16, "Channel 1 Index"), 1004 QUAD8_INDEX_SIGNAL(17, "Channel 2 Index"), 1005 QUAD8_INDEX_SIGNAL(18, "Channel 3 Index"), 1006 QUAD8_INDEX_SIGNAL(19, "Channel 4 Index"), 1007 QUAD8_INDEX_SIGNAL(20, "Channel 5 Index"), 1008 QUAD8_INDEX_SIGNAL(21, "Channel 6 Index"), 1009 QUAD8_INDEX_SIGNAL(22, "Channel 7 Index"), 1010 QUAD8_INDEX_SIGNAL(23, "Channel 8 Index") 1011 }; 1012 1013 #define QUAD8_COUNT_SYNAPSES(_id) { \ 1014 { \ 1015 .actions_list = quad8_synapse_actions_list, \ 1016 .num_actions = ARRAY_SIZE(quad8_synapse_actions_list), \ 1017 .signal = quad8_signals + 2 * (_id) \ 1018 }, \ 1019 { \ 1020 .actions_list = quad8_synapse_actions_list, \ 1021 .num_actions = ARRAY_SIZE(quad8_synapse_actions_list), \ 1022 .signal = quad8_signals + 2 * (_id) + 1 \ 1023 }, \ 1024 { \ 1025 .actions_list = quad8_index_actions_list, \ 1026 .num_actions = ARRAY_SIZE(quad8_index_actions_list), \ 1027 .signal = quad8_signals + 2 * (_id) + 16 \ 1028 } \ 1029 } 1030 1031 static struct counter_synapse quad8_count_synapses[][3] = { 1032 QUAD8_COUNT_SYNAPSES(0), QUAD8_COUNT_SYNAPSES(1), 1033 QUAD8_COUNT_SYNAPSES(2), QUAD8_COUNT_SYNAPSES(3), 1034 QUAD8_COUNT_SYNAPSES(4), QUAD8_COUNT_SYNAPSES(5), 1035 QUAD8_COUNT_SYNAPSES(6), QUAD8_COUNT_SYNAPSES(7) 1036 }; 1037 1038 static const enum counter_count_mode quad8_cnt_modes[] = { 1039 COUNTER_COUNT_MODE_NORMAL, 1040 COUNTER_COUNT_MODE_RANGE_LIMIT, 1041 COUNTER_COUNT_MODE_NON_RECYCLE, 1042 COUNTER_COUNT_MODE_MODULO_N, 1043 }; 1044 1045 static DEFINE_COUNTER_AVAILABLE(quad8_count_mode_available, quad8_cnt_modes); 1046 1047 static DEFINE_COUNTER_ENUM(quad8_error_noise_enum, quad8_noise_error_states); 1048 1049 static struct counter_comp quad8_count_ext[] = { 1050 COUNTER_COMP_CEILING(quad8_count_ceiling_read, 1051 quad8_count_ceiling_write), 1052 COUNTER_COMP_FLOOR(quad8_count_floor_read, NULL), 1053 COUNTER_COMP_COUNT_MODE(quad8_count_mode_read, quad8_count_mode_write, 1054 quad8_count_mode_available), 1055 COUNTER_COMP_DIRECTION(quad8_direction_read), 1056 COUNTER_COMP_ENABLE(quad8_count_enable_read, quad8_count_enable_write), 1057 COUNTER_COMP_COUNT_ENUM("error_noise", quad8_error_noise_get, NULL, 1058 quad8_error_noise_enum), 1059 COUNTER_COMP_PRESET(quad8_count_preset_read, quad8_count_preset_write), 1060 COUNTER_COMP_PRESET_ENABLE(quad8_count_preset_enable_read, 1061 quad8_count_preset_enable_write), 1062 }; 1063 1064 #define QUAD8_COUNT(_id, _cntname) { \ 1065 .id = (_id), \ 1066 .name = (_cntname), \ 1067 .functions_list = quad8_count_functions_list, \ 1068 .num_functions = ARRAY_SIZE(quad8_count_functions_list), \ 1069 .synapses = quad8_count_synapses[(_id)], \ 1070 .num_synapses = 2, \ 1071 .ext = quad8_count_ext, \ 1072 .num_ext = ARRAY_SIZE(quad8_count_ext) \ 1073 } 1074 1075 static struct counter_count quad8_counts[] = { 1076 QUAD8_COUNT(0, "Channel 1 Count"), 1077 QUAD8_COUNT(1, "Channel 2 Count"), 1078 QUAD8_COUNT(2, "Channel 3 Count"), 1079 QUAD8_COUNT(3, "Channel 4 Count"), 1080 QUAD8_COUNT(4, "Channel 5 Count"), 1081 QUAD8_COUNT(5, "Channel 6 Count"), 1082 QUAD8_COUNT(6, "Channel 7 Count"), 1083 QUAD8_COUNT(7, "Channel 8 Count") 1084 }; 1085 1086 static irqreturn_t quad8_irq_handler(int irq, void *private) 1087 { 1088 struct quad8 *const priv = private; 1089 const unsigned long base = priv->base; 1090 unsigned long irq_status; 1091 unsigned long channel; 1092 u8 event; 1093 1094 irq_status = inb(base + QUAD8_REG_INTERRUPT_STATUS); 1095 if (!irq_status) 1096 return IRQ_NONE; 1097 1098 for_each_set_bit(channel, &irq_status, QUAD8_NUM_COUNTERS) { 1099 switch (priv->irq_trigger[channel]) { 1100 case QUAD8_EVENT_CARRY: 1101 event = COUNTER_EVENT_OVERFLOW; 1102 break; 1103 case QUAD8_EVENT_COMPARE: 1104 event = COUNTER_EVENT_THRESHOLD; 1105 break; 1106 case QUAD8_EVENT_CARRY_BORROW: 1107 event = COUNTER_EVENT_OVERFLOW_UNDERFLOW; 1108 break; 1109 case QUAD8_EVENT_INDEX: 1110 event = COUNTER_EVENT_INDEX; 1111 break; 1112 default: 1113 /* should never reach this path */ 1114 WARN_ONCE(true, "invalid interrupt trigger function %u configured for channel %lu\n", 1115 priv->irq_trigger[channel], channel); 1116 continue; 1117 } 1118 1119 counter_push_event(&priv->counter, event, channel); 1120 } 1121 1122 /* Clear pending interrupts on device */ 1123 outb(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, base + QUAD8_REG_CHAN_OP); 1124 1125 return IRQ_HANDLED; 1126 } 1127 1128 static int quad8_probe(struct device *dev, unsigned int id) 1129 { 1130 struct quad8 *priv; 1131 int i, j; 1132 unsigned int base_offset; 1133 int err; 1134 1135 if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) { 1136 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", 1137 base[id], base[id] + QUAD8_EXTENT); 1138 return -EBUSY; 1139 } 1140 1141 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 1142 if (!priv) 1143 return -ENOMEM; 1144 1145 /* Initialize Counter device and driver data */ 1146 priv->counter.name = dev_name(dev); 1147 priv->counter.parent = dev; 1148 priv->counter.ops = &quad8_ops; 1149 priv->counter.counts = quad8_counts; 1150 priv->counter.num_counts = ARRAY_SIZE(quad8_counts); 1151 priv->counter.signals = quad8_signals; 1152 priv->counter.num_signals = ARRAY_SIZE(quad8_signals); 1153 priv->counter.priv = priv; 1154 priv->base = base[id]; 1155 1156 spin_lock_init(&priv->lock); 1157 1158 /* Reset Index/Interrupt Register */ 1159 outb(0x00, base[id] + QUAD8_REG_INDEX_INTERRUPT); 1160 /* Reset all counters and disable interrupt function */ 1161 outb(QUAD8_CHAN_OP_RESET_COUNTERS, base[id] + QUAD8_REG_CHAN_OP); 1162 /* Set initial configuration for all counters */ 1163 for (i = 0; i < QUAD8_NUM_COUNTERS; i++) { 1164 base_offset = base[id] + 2 * i; 1165 /* Reset Byte Pointer */ 1166 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); 1167 /* Reset filter clock factor */ 1168 outb(0, base_offset); 1169 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, 1170 base_offset + 1); 1171 /* Reset Byte Pointer */ 1172 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); 1173 /* Reset Preset Register */ 1174 for (j = 0; j < 3; j++) 1175 outb(0x00, base_offset); 1176 /* Reset Borrow, Carry, Compare, and Sign flags */ 1177 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1); 1178 /* Reset Error flag */ 1179 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1); 1180 /* Binary encoding; Normal count; non-quadrature mode */ 1181 outb(QUAD8_CTR_CMR, base_offset + 1); 1182 /* Disable A and B inputs; preset on index; FLG1 as Carry */ 1183 outb(QUAD8_CTR_IOR, base_offset + 1); 1184 /* Disable index function; negative index polarity */ 1185 outb(QUAD8_CTR_IDR, base_offset + 1); 1186 /* Initialize next IRQ trigger function configuration */ 1187 priv->next_irq_trigger[i] = QUAD8_EVENT_NONE; 1188 } 1189 /* Disable Differential Encoder Cable Status for all channels */ 1190 outb(0xFF, base[id] + QUAD8_DIFF_ENCODER_CABLE_STATUS); 1191 /* Enable all counters and enable interrupt function */ 1192 outb(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, base[id] + QUAD8_REG_CHAN_OP); 1193 1194 err = devm_request_irq(dev, irq[id], quad8_irq_handler, IRQF_SHARED, 1195 priv->counter.name, priv); 1196 if (err) 1197 return err; 1198 1199 return devm_counter_register(dev, &priv->counter); 1200 } 1201 1202 static struct isa_driver quad8_driver = { 1203 .probe = quad8_probe, 1204 .driver = { 1205 .name = "104-quad-8" 1206 } 1207 }; 1208 1209 module_isa_driver(quad8_driver, num_quad8); 1210 1211 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); 1212 MODULE_DESCRIPTION("ACCES 104-QUAD-8 driver"); 1213 MODULE_LICENSE("GPL v2"); 1214