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