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

iio: adc: ad7192: Add fast settling support

Add fast settling mode support for AD7193.

Add two new device specific attributes: oversampling_ratio and
oversampling_ratio_available.

For AD7193 the user can set the average factor by writing to
oversampling_ratio. The possible values are exposed when reading
oversampling_ratio_available.

Signed-off-by: Alisa-Dariana Roman <alisa.roman@analog.com>
Link: https://lore.kernel.org/r/20231010124927.143343-4-alisadariana@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Alisa-Dariana Roman and committed by
Jonathan Cameron
db7fe1f6 15f3b487

+82 -27
+82 -27
drivers/iio/adc/ad7192.c
··· 60 60 #define AD7192_MODE_SEL_MASK GENMASK(23, 21) /* Operation Mode Select Mask */ 61 61 #define AD7192_MODE_STA_MASK BIT(20) /* Status Register transmission Mask */ 62 62 #define AD7192_MODE_CLKSRC_MASK GENMASK(19, 18) /* Clock Source Select Mask */ 63 + #define AD7192_MODE_AVG_MASK GENMASK(17, 16) 64 + /* Fast Settling Filter Average Select Mask (AD7193 only) */ 63 65 #define AD7192_MODE_SINC3 BIT(15) /* SINC3 Filter Select */ 64 66 #define AD7192_MODE_ENPAR BIT(13) /* Parity Enable */ 65 67 #define AD7192_MODE_CLKDIV BIT(12) /* Clock divide by 2 (AD7190/2 only)*/ ··· 187 185 u32 mode; 188 186 u32 conf; 189 187 u32 scale_avail[8][2]; 188 + u32 oversampling_ratio_avail[4]; 190 189 u8 gpocon; 191 190 u8 clock_sel; 192 191 struct mutex lock; /* protect sensor state */ ··· 465 462 st->scale_avail[i][0] = scale_uv; 466 463 } 467 464 465 + st->oversampling_ratio_avail[0] = 1; 466 + st->oversampling_ratio_avail[1] = 2; 467 + st->oversampling_ratio_avail[2] = 8; 468 + st->oversampling_ratio_avail[3] = 16; 469 + 468 470 return 0; 469 471 } 470 472 ··· 539 531 return ret ? ret : len; 540 532 } 541 533 542 - static int ad7192_compute_f_order(bool sinc3_en, bool chop_en) 534 + static int ad7192_compute_f_order(struct ad7192_state *st, bool sinc3_en, bool chop_en) 543 535 { 544 - if (!chop_en) 536 + u8 avg_factor_selected, oversampling_ratio; 537 + 538 + avg_factor_selected = FIELD_GET(AD7192_MODE_AVG_MASK, st->mode); 539 + 540 + if (!avg_factor_selected && !chop_en) 545 541 return 1; 546 542 547 - if (sinc3_en) 548 - return AD7192_SYNC3_FILTER; 543 + oversampling_ratio = st->oversampling_ratio_avail[avg_factor_selected]; 549 544 550 - return AD7192_SYNC4_FILTER; 545 + if (sinc3_en) 546 + return AD7192_SYNC3_FILTER + oversampling_ratio - 1; 547 + 548 + return AD7192_SYNC4_FILTER + oversampling_ratio - 1; 551 549 } 552 550 553 551 static int ad7192_get_f_order(struct ad7192_state *st) ··· 563 549 sinc3_en = FIELD_GET(AD7192_MODE_SINC3, st->mode); 564 550 chop_en = FIELD_GET(AD7192_CONF_CHOP, st->conf); 565 551 566 - return ad7192_compute_f_order(sinc3_en, chop_en); 552 + return ad7192_compute_f_order(st, sinc3_en, chop_en); 567 553 } 568 554 569 555 static int ad7192_compute_f_adc(struct ad7192_state *st, bool sinc3_en, 570 556 bool chop_en) 571 557 { 572 - unsigned int f_order = ad7192_compute_f_order(sinc3_en, chop_en); 558 + unsigned int f_order = ad7192_compute_f_order(st, sinc3_en, chop_en); 573 559 574 560 return DIV_ROUND_CLOSEST(st->fclk, 575 561 f_order * FIELD_GET(AD7192_MODE_RATE_MASK, st->mode)); ··· 767 753 *val = ad7192_get_3db_filter_freq(st); 768 754 *val2 = 1000; 769 755 return IIO_VAL_FRACTIONAL; 756 + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 757 + *val = st->oversampling_ratio_avail[FIELD_GET(AD7192_MODE_AVG_MASK, st->mode)]; 758 + return IIO_VAL_INT; 770 759 } 771 760 772 761 return -EINVAL; ··· 827 810 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 828 811 ret = ad7192_set_3db_filter_freq(st, val, val2 / 1000); 829 812 break; 813 + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 814 + ret = -EINVAL; 815 + mutex_lock(&st->lock); 816 + for (i = 0; i < ARRAY_SIZE(st->oversampling_ratio_avail); i++) 817 + if (val == st->oversampling_ratio_avail[i]) { 818 + ret = 0; 819 + tmp = st->mode; 820 + st->mode &= ~AD7192_MODE_AVG_MASK; 821 + st->mode |= FIELD_PREP(AD7192_MODE_AVG_MASK, i); 822 + if (tmp == st->mode) 823 + break; 824 + ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 825 + 3, st->mode); 826 + break; 827 + } 828 + mutex_unlock(&st->lock); 829 + break; 830 830 default: 831 831 ret = -EINVAL; 832 832 } ··· 864 830 return IIO_VAL_INT; 865 831 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 866 832 return IIO_VAL_INT_PLUS_MICRO; 833 + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 834 + return IIO_VAL_INT; 867 835 default: 868 836 return -EINVAL; 869 837 } ··· 884 848 *type = IIO_VAL_INT_PLUS_NANO; 885 849 /* Values are stored in a 2D matrix */ 886 850 *length = ARRAY_SIZE(st->scale_avail) * 2; 851 + 852 + return IIO_AVAIL_LIST; 853 + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 854 + *vals = (int *)st->oversampling_ratio_avail; 855 + *type = IIO_VAL_INT; 856 + *length = ARRAY_SIZE(st->oversampling_ratio_avail); 887 857 888 858 return IIO_AVAIL_LIST; 889 859 } ··· 938 896 }; 939 897 940 898 #define __AD719x_CHANNEL(_si, _channel1, _channel2, _address, _type, \ 941 - _mask_type_av, _ext_info) \ 899 + _mask_all, _mask_type_av, _mask_all_av, _ext_info) \ 942 900 { \ 943 901 .type = (_type), \ 944 902 .differential = ((_channel2) == -1 ? 0 : 1), \ ··· 950 908 BIT(IIO_CHAN_INFO_OFFSET), \ 951 909 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 952 910 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ 953 - BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ 911 + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \ 912 + (_mask_all), \ 954 913 .info_mask_shared_by_type_available = (_mask_type_av), \ 914 + .info_mask_shared_by_all_available = (_mask_all_av), \ 955 915 .ext_info = (_ext_info), \ 956 916 .scan_index = (_si), \ 957 917 .scan_type = { \ ··· 965 921 } 966 922 967 923 #define AD719x_DIFF_CHANNEL(_si, _channel1, _channel2, _address) \ 968 - __AD719x_CHANNEL(_si, _channel1, _channel2, _address, IIO_VOLTAGE, \ 969 - BIT(IIO_CHAN_INFO_SCALE), ad7192_calibsys_ext_info) 924 + __AD719x_CHANNEL(_si, _channel1, _channel2, _address, IIO_VOLTAGE, 0, \ 925 + BIT(IIO_CHAN_INFO_SCALE), 0, ad7192_calibsys_ext_info) 970 926 971 927 #define AD719x_CHANNEL(_si, _channel1, _address) \ 972 - __AD719x_CHANNEL(_si, _channel1, -1, _address, IIO_VOLTAGE, \ 973 - BIT(IIO_CHAN_INFO_SCALE), ad7192_calibsys_ext_info) 928 + __AD719x_CHANNEL(_si, _channel1, -1, _address, IIO_VOLTAGE, 0, \ 929 + BIT(IIO_CHAN_INFO_SCALE), 0, ad7192_calibsys_ext_info) 974 930 975 931 #define AD719x_TEMP_CHANNEL(_si, _address) \ 976 - __AD719x_CHANNEL(_si, 0, -1, _address, IIO_TEMP, 0, NULL) 932 + __AD719x_CHANNEL(_si, 0, -1, _address, IIO_TEMP, 0, 0, 0, NULL) 933 + 934 + #define AD7193_DIFF_CHANNEL(_si, _channel1, _channel2, _address) \ 935 + __AD719x_CHANNEL(_si, _channel1, _channel2, _address, \ 936 + IIO_VOLTAGE, \ 937 + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 938 + BIT(IIO_CHAN_INFO_SCALE), \ 939 + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 940 + ad7192_calibsys_ext_info) 941 + 942 + #define AD7193_CHANNEL(_si, _channel1, _address) \ 943 + AD7193_DIFF_CHANNEL(_si, _channel1, -1, _address) 977 944 978 945 static const struct iio_chan_spec ad7192_channels[] = { 979 946 AD719x_DIFF_CHANNEL(0, 1, 2, AD7192_CH_AIN1P_AIN2M), ··· 999 944 }; 1000 945 1001 946 static const struct iio_chan_spec ad7193_channels[] = { 1002 - AD719x_DIFF_CHANNEL(0, 1, 2, AD7193_CH_AIN1P_AIN2M), 1003 - AD719x_DIFF_CHANNEL(1, 3, 4, AD7193_CH_AIN3P_AIN4M), 1004 - AD719x_DIFF_CHANNEL(2, 5, 6, AD7193_CH_AIN5P_AIN6M), 1005 - AD719x_DIFF_CHANNEL(3, 7, 8, AD7193_CH_AIN7P_AIN8M), 947 + AD7193_DIFF_CHANNEL(0, 1, 2, AD7193_CH_AIN1P_AIN2M), 948 + AD7193_DIFF_CHANNEL(1, 3, 4, AD7193_CH_AIN3P_AIN4M), 949 + AD7193_DIFF_CHANNEL(2, 5, 6, AD7193_CH_AIN5P_AIN6M), 950 + AD7193_DIFF_CHANNEL(3, 7, 8, AD7193_CH_AIN7P_AIN8M), 1006 951 AD719x_TEMP_CHANNEL(4, AD7193_CH_TEMP), 1007 - AD719x_DIFF_CHANNEL(5, 2, 2, AD7193_CH_AIN2P_AIN2M), 1008 - AD719x_CHANNEL(6, 1, AD7193_CH_AIN1), 1009 - AD719x_CHANNEL(7, 2, AD7193_CH_AIN2), 1010 - AD719x_CHANNEL(8, 3, AD7193_CH_AIN3), 1011 - AD719x_CHANNEL(9, 4, AD7193_CH_AIN4), 1012 - AD719x_CHANNEL(10, 5, AD7193_CH_AIN5), 1013 - AD719x_CHANNEL(11, 6, AD7193_CH_AIN6), 1014 - AD719x_CHANNEL(12, 7, AD7193_CH_AIN7), 1015 - AD719x_CHANNEL(13, 8, AD7193_CH_AIN8), 952 + AD7193_DIFF_CHANNEL(5, 2, 2, AD7193_CH_AIN2P_AIN2M), 953 + AD7193_CHANNEL(6, 1, AD7193_CH_AIN1), 954 + AD7193_CHANNEL(7, 2, AD7193_CH_AIN2), 955 + AD7193_CHANNEL(8, 3, AD7193_CH_AIN3), 956 + AD7193_CHANNEL(9, 4, AD7193_CH_AIN4), 957 + AD7193_CHANNEL(10, 5, AD7193_CH_AIN5), 958 + AD7193_CHANNEL(11, 6, AD7193_CH_AIN6), 959 + AD7193_CHANNEL(12, 7, AD7193_CH_AIN7), 960 + AD7193_CHANNEL(13, 8, AD7193_CH_AIN8), 1016 961 IIO_CHAN_SOFT_TIMESTAMP(14), 1017 962 }; 1018 963