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