Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

iio: adc: ad4030: add averaging support

This add support for the averaging mode of AD4030 using oversampling IIO
attribute

Signed-off-by: Esteban Blanc <eblanc@baylibre.com>
Link: https://patch.msgid.link/20250214-eblanc-ad4630_v1-v4-3-135dd66cab6a@baylibre.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Esteban Blanc and committed by
Jonathan Cameron
949abd1c 0cb8b324

+119 -17
+119 -17
drivers/iio/adc/ad4030.c
··· 112 112 AD4030_OUT_DATA_MD_32_PATTERN, 113 113 }; 114 114 115 + enum { 116 + AD4030_SCAN_TYPE_NORMAL, 117 + AD4030_SCAN_TYPE_AVG, 118 + }; 119 + 115 120 struct ad4030_chip_info { 116 121 const char *name; 117 122 const unsigned long *available_masks; ··· 132 127 struct spi_device *spi; 133 128 struct regmap *regmap; 134 129 const struct ad4030_chip_info *chip; 130 + const struct iio_scan_type *current_scan_type; 135 131 struct gpio_desc *cnv_gpio; 136 132 int vref_uv; 137 133 int vio_uv; 138 134 int offset_avail[3]; 135 + unsigned int avg_log2; 139 136 enum ad4030_out_mode mode; 140 137 141 138 /* ··· 191 184 * - voltage0-voltage1 192 185 * - voltage2-voltage3 193 186 */ 194 - #define AD4030_CHAN_DIFF(_idx, _storage, _real, _shift) { \ 187 + #define AD4030_CHAN_DIFF(_idx, _scan_type) { \ 188 + .info_mask_shared_by_all = \ 189 + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 190 + .info_mask_shared_by_all_available = \ 191 + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 195 192 .info_mask_separate = BIT(IIO_CHAN_INFO_SCALE) | \ 196 193 BIT(IIO_CHAN_INFO_CALIBSCALE) | \ 197 194 BIT(IIO_CHAN_INFO_CALIBBIAS) | \ ··· 209 198 .channel2 = (_idx) * 2 + 1, \ 210 199 .scan_index = (_idx), \ 211 200 .differential = true, \ 212 - .scan_type = { \ 213 - .sign = 's', \ 214 - .storagebits = _storage, \ 215 - .realbits = _real, \ 216 - .shift = _shift, \ 217 - .endianness = IIO_BE, \ 218 - }, \ 201 + .has_ext_scan_type = 1, \ 202 + .ext_scan_type = _scan_type, \ 203 + .num_ext_scan_type = ARRAY_SIZE(_scan_type), \ 219 204 } 205 + 206 + static const int ad4030_average_modes[] = { 207 + 1, 2, 4, 8, 16, 32, 64, 128, 208 + 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 209 + 65536, 210 + }; 220 211 221 212 static int ad4030_enter_config_mode(struct ad4030_state *st) 222 213 { ··· 369 356 int *val2) 370 357 { 371 358 struct ad4030_state *st = iio_priv(indio_dev); 359 + const struct iio_scan_type *scan_type; 372 360 373 361 if (chan->differential) { 362 + scan_type = iio_get_current_scan_type(indio_dev, 363 + st->chip->channels); 374 364 *val = (st->vref_uv * 2) / MILLI; 375 - *val2 = chan->scan_type.realbits; 365 + *val2 = scan_type->realbits; 376 366 return IIO_VAL_FRACTIONAL_LOG2; 377 367 } 378 368 ··· 490 474 st->tx_data, AD4030_REG_OFFSET_BYTES_NB); 491 475 } 492 476 477 + static int ad4030_set_avg_frame_len(struct iio_dev *dev, int avg_val) 478 + { 479 + struct ad4030_state *st = iio_priv(dev); 480 + unsigned int avg_log2 = ilog2(avg_val); 481 + unsigned int last_avg_idx = ARRAY_SIZE(ad4030_average_modes) - 1; 482 + int ret; 483 + 484 + if (avg_val < 0 || avg_val > ad4030_average_modes[last_avg_idx]) 485 + return -EINVAL; 486 + 487 + ret = regmap_write(st->regmap, AD4030_REG_AVG, 488 + AD4030_REG_AVG_MASK_AVG_SYNC | 489 + FIELD_PREP(AD4030_REG_AVG_MASK_AVG_VAL, avg_log2)); 490 + if (ret) 491 + return ret; 492 + 493 + st->avg_log2 = avg_log2; 494 + 495 + return 0; 496 + } 497 + 493 498 static bool ad4030_is_common_byte_asked(struct ad4030_state *st, 494 499 unsigned int mask) 495 500 { ··· 521 484 { 522 485 struct ad4030_state *st = iio_priv(indio_dev); 523 486 524 - if (ad4030_is_common_byte_asked(st, mask)) 487 + if (st->avg_log2 > 0) 488 + st->mode = AD4030_OUT_DATA_MD_30_AVERAGED_DIFF; 489 + else if (ad4030_is_common_byte_asked(st, mask)) 525 490 st->mode = AD4030_OUT_DATA_MD_24_DIFF_8_COM; 526 491 else 527 492 st->mode = AD4030_OUT_DATA_MD_DIFF; 493 + 494 + st->current_scan_type = iio_get_current_scan_type(indio_dev, 495 + st->chip->channels); 496 + if (IS_ERR(st->current_scan_type)) 497 + return PTR_ERR(st->current_scan_type); 528 498 529 499 return regmap_update_bits(st->regmap, AD4030_REG_MODES, 530 500 AD4030_REG_MODES_MASK_OUT_DATA_MODE, ··· 541 497 static int ad4030_conversion(struct iio_dev *indio_dev) 542 498 { 543 499 struct ad4030_state *st = iio_priv(indio_dev); 544 - const struct iio_scan_type scan_type = indio_dev->channels->scan_type; 545 - unsigned char diff_realbytes = BITS_TO_BYTES(scan_type.realbits); 500 + unsigned char diff_realbytes = 501 + BITS_TO_BYTES(st->current_scan_type->realbits); 546 502 unsigned int bytes_to_read; 503 + unsigned long cnv_nb = BIT(st->avg_log2); 504 + unsigned int i; 547 505 int ret; 548 506 549 507 /* Number of bytes for one differential channel */ ··· 556 510 /* Mulitiply by the number of hardware channels */ 557 511 bytes_to_read *= st->chip->num_voltage_inputs; 558 512 559 - gpiod_set_value_cansleep(st->cnv_gpio, 1); 560 - ndelay(AD4030_TCNVH_NS); 561 - gpiod_set_value_cansleep(st->cnv_gpio, 0); 562 - ndelay(st->chip->tcyc_ns); 513 + for (i = 0; i < cnv_nb; i++) { 514 + gpiod_set_value_cansleep(st->cnv_gpio, 1); 515 + ndelay(AD4030_TCNVH_NS); 516 + gpiod_set_value_cansleep(st->cnv_gpio, 0); 517 + ndelay(st->chip->tcyc_ns); 518 + } 563 519 564 520 ret = spi_read(st->spi, st->rx_data.raw, bytes_to_read); 565 521 if (ret) ··· 641 593 *type = IIO_VAL_INT_PLUS_NANO; 642 594 return IIO_AVAIL_RANGE; 643 595 596 + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 597 + *vals = ad4030_average_modes; 598 + *type = IIO_VAL_INT; 599 + *length = ARRAY_SIZE(ad4030_average_modes); 600 + return IIO_AVAIL_LIST; 601 + 644 602 default: 645 603 return -EINVAL; 646 604 } ··· 656 602 struct iio_chan_spec const *chan, int *val, 657 603 int *val2, long info) 658 604 { 605 + struct ad4030_state *st = iio_priv(indio_dev); 606 + 659 607 switch (info) { 660 608 case IIO_CHAN_INFO_RAW: 661 609 return ad4030_single_conversion(indio_dev, chan, val); ··· 667 611 668 612 case IIO_CHAN_INFO_CALIBBIAS: 669 613 return ad4030_get_chan_calibbias(indio_dev, chan, val); 614 + 615 + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 616 + *val = BIT(st->avg_log2); 617 + return IIO_VAL_INT; 670 618 671 619 default: 672 620 return -EINVAL; ··· 709 649 if (val2 != 0) 710 650 return -EINVAL; 711 651 return ad4030_set_chan_calibbias(indio_dev, chan, val); 652 + 653 + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 654 + return ad4030_set_avg_frame_len(indio_dev, val); 712 655 713 656 default: 714 657 return -EINVAL; ··· 764 701 return sprintf(label, "common-mode%lu\n", chan->address); 765 702 } 766 703 704 + static int ad4030_get_current_scan_type(const struct iio_dev *indio_dev, 705 + const struct iio_chan_spec *chan) 706 + { 707 + struct ad4030_state *st = iio_priv(indio_dev); 708 + 709 + return st->avg_log2 ? AD4030_SCAN_TYPE_AVG : AD4030_SCAN_TYPE_NORMAL; 710 + } 711 + 767 712 static const struct iio_info ad4030_iio_info = { 768 713 .read_avail = ad4030_read_avail, 769 714 .read_raw = ad4030_read_raw, 770 715 .write_raw = ad4030_write_raw, 771 716 .debugfs_reg_access = ad4030_reg_access, 772 717 .read_label = ad4030_read_label, 718 + .get_current_scan_type = ad4030_get_current_scan_type, 773 719 }; 774 720 775 721 static int ad4030_buffer_preenable(struct iio_dev *indio_dev) ··· 786 714 return ad4030_set_mode(indio_dev, *indio_dev->active_scan_mask); 787 715 } 788 716 717 + static bool ad4030_validate_scan_mask(struct iio_dev *indio_dev, 718 + const unsigned long *scan_mask) 719 + { 720 + struct ad4030_state *st = iio_priv(indio_dev); 721 + 722 + /* Asking for both common channels and averaging */ 723 + if (st->avg_log2 && ad4030_is_common_byte_asked(st, *scan_mask)) 724 + return false; 725 + 726 + return true; 727 + } 728 + 789 729 static const struct iio_buffer_setup_ops ad4030_buffer_setup_ops = { 790 730 .preenable = ad4030_buffer_preenable, 731 + .validate_scan_mask = ad4030_validate_scan_mask, 791 732 }; 792 733 793 734 static int ad4030_regulators_get(struct ad4030_state *st) ··· 966 881 0, 967 882 }; 968 883 884 + static const struct iio_scan_type ad4030_24_scan_types[] = { 885 + [AD4030_SCAN_TYPE_NORMAL] = { 886 + .sign = 's', 887 + .storagebits = 32, 888 + .realbits = 24, 889 + .shift = 8, 890 + .endianness = IIO_BE, 891 + }, 892 + [AD4030_SCAN_TYPE_AVG] = { 893 + .sign = 's', 894 + .storagebits = 32, 895 + .realbits = 30, 896 + .shift = 2, 897 + .endianness = IIO_BE, 898 + }, 899 + }; 900 + 969 901 static const struct ad4030_chip_info ad4030_24_chip_info = { 970 902 .name = "ad4030-24", 971 903 .available_masks = ad4030_channel_masks, 972 904 .channels = { 973 - AD4030_CHAN_DIFF(0, 32, 24, 8), 905 + AD4030_CHAN_DIFF(0, ad4030_24_scan_types), 974 906 AD4030_CHAN_CMO(1, 0), 975 907 IIO_CHAN_SOFT_TIMESTAMP(2), 976 908 },