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