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 struct quad8_iio *const priv = counter->priv; 1278 const size_t channel_id = signal->id / 2; 1279 bool disabled; 1280 unsigned int status; 1281 unsigned int fault; 1282 1283 mutex_lock(&priv->lock); 1284 1285 disabled = !(priv->cable_fault_enable & BIT(channel_id)); 1286 1287 if (disabled) { 1288 mutex_unlock(&priv->lock); 1289 return -EINVAL; 1290 } 1291 1292 /* Logic 0 = cable fault */ 1293 status = inb(priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS); 1294 1295 mutex_unlock(&priv->lock); 1296 1297 /* Mask respective channel and invert logic */ 1298 fault = !(status & BIT(channel_id)); 1299 1300 return sprintf(buf, "%u\n", fault); 1301 } 1302 1303 static ssize_t quad8_signal_cable_fault_enable_read( 1304 struct counter_device *counter, struct counter_signal *signal, 1305 void *private, char *buf) 1306 { 1307 const struct quad8_iio *const priv = counter->priv; 1308 const size_t channel_id = signal->id / 2; 1309 const unsigned int enb = !!(priv->cable_fault_enable & BIT(channel_id)); 1310 1311 return sprintf(buf, "%u\n", enb); 1312 } 1313 1314 static ssize_t quad8_signal_cable_fault_enable_write( 1315 struct counter_device *counter, struct counter_signal *signal, 1316 void *private, const char *buf, size_t len) 1317 { 1318 struct quad8_iio *const priv = counter->priv; 1319 const size_t channel_id = signal->id / 2; 1320 bool enable; 1321 int ret; 1322 unsigned int cable_fault_enable; 1323 1324 ret = kstrtobool(buf, &enable); 1325 if (ret) 1326 return ret; 1327 1328 mutex_lock(&priv->lock); 1329 1330 if (enable) 1331 priv->cable_fault_enable |= BIT(channel_id); 1332 else 1333 priv->cable_fault_enable &= ~BIT(channel_id); 1334 1335 /* Enable is active low in Differential Encoder Cable Status register */ 1336 cable_fault_enable = ~priv->cable_fault_enable; 1337 1338 outb(cable_fault_enable, priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS); 1339 1340 mutex_unlock(&priv->lock); 1341 1342 return len; 1343 } 1344 1345 static ssize_t quad8_signal_fck_prescaler_read(struct counter_device *counter, 1346 struct counter_signal *signal, void *private, char *buf) 1347 { 1348 const struct quad8_iio *const priv = counter->priv; 1349 const size_t channel_id = signal->id / 2; 1350 1351 return sprintf(buf, "%u\n", priv->fck_prescaler[channel_id]); 1352 } 1353 1354 static ssize_t quad8_signal_fck_prescaler_write(struct counter_device *counter, 1355 struct counter_signal *signal, void *private, const char *buf, 1356 size_t len) 1357 { 1358 struct quad8_iio *const priv = counter->priv; 1359 const size_t channel_id = signal->id / 2; 1360 const int base_offset = priv->base + 2 * channel_id; 1361 u8 prescaler; 1362 int ret; 1363 1364 ret = kstrtou8(buf, 0, &prescaler); 1365 if (ret) 1366 return ret; 1367 1368 mutex_lock(&priv->lock); 1369 1370 priv->fck_prescaler[channel_id] = prescaler; 1371 1372 /* Reset Byte Pointer */ 1373 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); 1374 1375 /* Set filter clock factor */ 1376 outb(prescaler, base_offset); 1377 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, 1378 base_offset + 1); 1379 1380 mutex_unlock(&priv->lock); 1381 1382 return len; 1383 } 1384 1385 static const struct counter_signal_ext quad8_signal_ext[] = { 1386 { 1387 .name = "cable_fault", 1388 .read = quad8_signal_cable_fault_read 1389 }, 1390 { 1391 .name = "cable_fault_enable", 1392 .read = quad8_signal_cable_fault_enable_read, 1393 .write = quad8_signal_cable_fault_enable_write 1394 }, 1395 { 1396 .name = "filter_clock_prescaler", 1397 .read = quad8_signal_fck_prescaler_read, 1398 .write = quad8_signal_fck_prescaler_write 1399 } 1400 }; 1401 1402 static const struct counter_signal_ext quad8_index_ext[] = { 1403 COUNTER_SIGNAL_ENUM("index_polarity", &quad8_index_pol_enum), 1404 COUNTER_SIGNAL_ENUM_AVAILABLE("index_polarity", &quad8_index_pol_enum), 1405 COUNTER_SIGNAL_ENUM("synchronous_mode", &quad8_syn_mode_enum), 1406 COUNTER_SIGNAL_ENUM_AVAILABLE("synchronous_mode", &quad8_syn_mode_enum) 1407 }; 1408 1409 #define QUAD8_QUAD_SIGNAL(_id, _name) { \ 1410 .id = (_id), \ 1411 .name = (_name), \ 1412 .ext = quad8_signal_ext, \ 1413 .num_ext = ARRAY_SIZE(quad8_signal_ext) \ 1414 } 1415 1416 #define QUAD8_INDEX_SIGNAL(_id, _name) { \ 1417 .id = (_id), \ 1418 .name = (_name), \ 1419 .ext = quad8_index_ext, \ 1420 .num_ext = ARRAY_SIZE(quad8_index_ext) \ 1421 } 1422 1423 static struct counter_signal quad8_signals[] = { 1424 QUAD8_QUAD_SIGNAL(0, "Channel 1 Quadrature A"), 1425 QUAD8_QUAD_SIGNAL(1, "Channel 1 Quadrature B"), 1426 QUAD8_QUAD_SIGNAL(2, "Channel 2 Quadrature A"), 1427 QUAD8_QUAD_SIGNAL(3, "Channel 2 Quadrature B"), 1428 QUAD8_QUAD_SIGNAL(4, "Channel 3 Quadrature A"), 1429 QUAD8_QUAD_SIGNAL(5, "Channel 3 Quadrature B"), 1430 QUAD8_QUAD_SIGNAL(6, "Channel 4 Quadrature A"), 1431 QUAD8_QUAD_SIGNAL(7, "Channel 4 Quadrature B"), 1432 QUAD8_QUAD_SIGNAL(8, "Channel 5 Quadrature A"), 1433 QUAD8_QUAD_SIGNAL(9, "Channel 5 Quadrature B"), 1434 QUAD8_QUAD_SIGNAL(10, "Channel 6 Quadrature A"), 1435 QUAD8_QUAD_SIGNAL(11, "Channel 6 Quadrature B"), 1436 QUAD8_QUAD_SIGNAL(12, "Channel 7 Quadrature A"), 1437 QUAD8_QUAD_SIGNAL(13, "Channel 7 Quadrature B"), 1438 QUAD8_QUAD_SIGNAL(14, "Channel 8 Quadrature A"), 1439 QUAD8_QUAD_SIGNAL(15, "Channel 8 Quadrature B"), 1440 QUAD8_INDEX_SIGNAL(16, "Channel 1 Index"), 1441 QUAD8_INDEX_SIGNAL(17, "Channel 2 Index"), 1442 QUAD8_INDEX_SIGNAL(18, "Channel 3 Index"), 1443 QUAD8_INDEX_SIGNAL(19, "Channel 4 Index"), 1444 QUAD8_INDEX_SIGNAL(20, "Channel 5 Index"), 1445 QUAD8_INDEX_SIGNAL(21, "Channel 6 Index"), 1446 QUAD8_INDEX_SIGNAL(22, "Channel 7 Index"), 1447 QUAD8_INDEX_SIGNAL(23, "Channel 8 Index") 1448 }; 1449 1450 #define QUAD8_COUNT_SYNAPSES(_id) { \ 1451 { \ 1452 .actions_list = quad8_synapse_actions_list, \ 1453 .num_actions = ARRAY_SIZE(quad8_synapse_actions_list), \ 1454 .signal = quad8_signals + 2 * (_id) \ 1455 }, \ 1456 { \ 1457 .actions_list = quad8_synapse_actions_list, \ 1458 .num_actions = ARRAY_SIZE(quad8_synapse_actions_list), \ 1459 .signal = quad8_signals + 2 * (_id) + 1 \ 1460 }, \ 1461 { \ 1462 .actions_list = quad8_index_actions_list, \ 1463 .num_actions = ARRAY_SIZE(quad8_index_actions_list), \ 1464 .signal = quad8_signals + 2 * (_id) + 16 \ 1465 } \ 1466 } 1467 1468 static struct counter_synapse quad8_count_synapses[][3] = { 1469 QUAD8_COUNT_SYNAPSES(0), QUAD8_COUNT_SYNAPSES(1), 1470 QUAD8_COUNT_SYNAPSES(2), QUAD8_COUNT_SYNAPSES(3), 1471 QUAD8_COUNT_SYNAPSES(4), QUAD8_COUNT_SYNAPSES(5), 1472 QUAD8_COUNT_SYNAPSES(6), QUAD8_COUNT_SYNAPSES(7) 1473 }; 1474 1475 static const struct counter_count_ext quad8_count_ext[] = { 1476 { 1477 .name = "ceiling", 1478 .read = quad8_count_ceiling_read, 1479 .write = quad8_count_ceiling_write 1480 }, 1481 { 1482 .name = "floor", 1483 .read = quad8_count_floor_read 1484 }, 1485 COUNTER_COUNT_ENUM("count_mode", &quad8_cnt_mode_enum), 1486 COUNTER_COUNT_ENUM_AVAILABLE("count_mode", &quad8_cnt_mode_enum), 1487 { 1488 .name = "direction", 1489 .read = quad8_count_direction_read 1490 }, 1491 { 1492 .name = "enable", 1493 .read = quad8_count_enable_read, 1494 .write = quad8_count_enable_write 1495 }, 1496 COUNTER_COUNT_ENUM("error_noise", &quad8_error_noise_enum), 1497 COUNTER_COUNT_ENUM_AVAILABLE("error_noise", &quad8_error_noise_enum), 1498 { 1499 .name = "preset", 1500 .read = quad8_count_preset_read, 1501 .write = quad8_count_preset_write 1502 }, 1503 { 1504 .name = "preset_enable", 1505 .read = quad8_count_preset_enable_read, 1506 .write = quad8_count_preset_enable_write 1507 } 1508 }; 1509 1510 #define QUAD8_COUNT(_id, _cntname) { \ 1511 .id = (_id), \ 1512 .name = (_cntname), \ 1513 .functions_list = quad8_count_functions_list, \ 1514 .num_functions = ARRAY_SIZE(quad8_count_functions_list), \ 1515 .synapses = quad8_count_synapses[(_id)], \ 1516 .num_synapses = 2, \ 1517 .ext = quad8_count_ext, \ 1518 .num_ext = ARRAY_SIZE(quad8_count_ext) \ 1519 } 1520 1521 static struct counter_count quad8_counts[] = { 1522 QUAD8_COUNT(0, "Channel 1 Count"), 1523 QUAD8_COUNT(1, "Channel 2 Count"), 1524 QUAD8_COUNT(2, "Channel 3 Count"), 1525 QUAD8_COUNT(3, "Channel 4 Count"), 1526 QUAD8_COUNT(4, "Channel 5 Count"), 1527 QUAD8_COUNT(5, "Channel 6 Count"), 1528 QUAD8_COUNT(6, "Channel 7 Count"), 1529 QUAD8_COUNT(7, "Channel 8 Count") 1530 }; 1531 1532 static int quad8_probe(struct device *dev, unsigned int id) 1533 { 1534 struct iio_dev *indio_dev; 1535 struct quad8_iio *quad8iio; 1536 int i, j; 1537 unsigned int base_offset; 1538 int err; 1539 1540 if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) { 1541 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", 1542 base[id], base[id] + QUAD8_EXTENT); 1543 return -EBUSY; 1544 } 1545 1546 /* Allocate IIO device; this also allocates driver data structure */ 1547 indio_dev = devm_iio_device_alloc(dev, sizeof(*quad8iio)); 1548 if (!indio_dev) 1549 return -ENOMEM; 1550 1551 /* Initialize IIO device */ 1552 indio_dev->info = &quad8_info; 1553 indio_dev->modes = INDIO_DIRECT_MODE; 1554 indio_dev->num_channels = ARRAY_SIZE(quad8_channels); 1555 indio_dev->channels = quad8_channels; 1556 indio_dev->name = dev_name(dev); 1557 1558 /* Initialize Counter device and driver data */ 1559 quad8iio = iio_priv(indio_dev); 1560 quad8iio->counter.name = dev_name(dev); 1561 quad8iio->counter.parent = dev; 1562 quad8iio->counter.ops = &quad8_ops; 1563 quad8iio->counter.counts = quad8_counts; 1564 quad8iio->counter.num_counts = ARRAY_SIZE(quad8_counts); 1565 quad8iio->counter.signals = quad8_signals; 1566 quad8iio->counter.num_signals = ARRAY_SIZE(quad8_signals); 1567 quad8iio->counter.priv = quad8iio; 1568 quad8iio->base = base[id]; 1569 1570 /* Initialize mutex */ 1571 mutex_init(&quad8iio->lock); 1572 1573 /* Reset all counters and disable interrupt function */ 1574 outb(QUAD8_CHAN_OP_RESET_COUNTERS, base[id] + QUAD8_REG_CHAN_OP); 1575 /* Set initial configuration for all counters */ 1576 for (i = 0; i < QUAD8_NUM_COUNTERS; i++) { 1577 base_offset = base[id] + 2 * i; 1578 /* Reset Byte Pointer */ 1579 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); 1580 /* Reset filter clock factor */ 1581 outb(0, base_offset); 1582 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, 1583 base_offset + 1); 1584 /* Reset Byte Pointer */ 1585 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); 1586 /* Reset Preset Register */ 1587 for (j = 0; j < 3; j++) 1588 outb(0x00, base_offset); 1589 /* Reset Borrow, Carry, Compare, and Sign flags */ 1590 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1); 1591 /* Reset Error flag */ 1592 outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1); 1593 /* Binary encoding; Normal count; non-quadrature mode */ 1594 outb(QUAD8_CTR_CMR, base_offset + 1); 1595 /* Disable A and B inputs; preset on index; FLG1 as Carry */ 1596 outb(QUAD8_CTR_IOR, base_offset + 1); 1597 /* Disable index function; negative index polarity */ 1598 outb(QUAD8_CTR_IDR, base_offset + 1); 1599 } 1600 /* Disable Differential Encoder Cable Status for all channels */ 1601 outb(0xFF, base[id] + QUAD8_DIFF_ENCODER_CABLE_STATUS); 1602 /* Enable all counters */ 1603 outb(QUAD8_CHAN_OP_ENABLE_COUNTERS, base[id] + QUAD8_REG_CHAN_OP); 1604 1605 /* Register IIO device */ 1606 err = devm_iio_device_register(dev, indio_dev); 1607 if (err) 1608 return err; 1609 1610 /* Register Counter device */ 1611 return devm_counter_register(dev, &quad8iio->counter); 1612 } 1613 1614 static struct isa_driver quad8_driver = { 1615 .probe = quad8_probe, 1616 .driver = { 1617 .name = "104-quad-8" 1618 } 1619 }; 1620 1621 module_isa_driver(quad8_driver, num_quad8); 1622 1623 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); 1624 MODULE_DESCRIPTION("ACCES 104-QUAD-8 IIO driver"); 1625 MODULE_LICENSE("GPL v2"); 1626