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: ad7124: add filter support

Add support to the ad7124 driver for selecting the filter type.

The filter type has an influence on the effective sampling frequency of
each channel. For sinc3+pf{1,2,3,4}, the sampling frequency is fixed.
For sinc{3,4} (without post filter), there is a factor of 3 or 4
depending on the filter type. For the extra +sinc1, there is an extra
averaging factor that depends on the power mode.

In order to select the closest sampling frequency for each filter type,
we keep a copy of the requested sampling frequency. This way, if the
user sets the sampling frequency first and then selects the filter type,
the sampling frequency will still be as close as possible to the
requested value.

Since we always either have the SINGLE_CYCLE bit set or have more than
one channel enabled, the sampling frequency is always using the
"zero-latency" calculation from the data sheet. This is only documented
for the basic sinc{3,4} filters, so the other filter types had to be
inferred and confirmed through testing.

Since the flat filter type list consists of multiple register fields,
the struct ad7124_channel_config::filter_type field is changed to the
enum ad7124_filter_type type to avoid nested switch statements in a
lot of places.

Signed-off-by: David Lechner <dlechner@baylibre.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

David Lechner and committed by
Jonathan Cameron
f1496949 b2dbba2b

+230 -32
+230 -32
drivers/iio/adc/ad7124.c
··· 3 3 * AD7124 SPI ADC driver 4 4 * 5 5 * Copyright 2018 Analog Devices Inc. 6 + * Copyright 2025 BayLibre, SAS 6 7 */ 7 8 #include <linux/bitfield.h> 8 9 #include <linux/bitops.h> ··· 98 97 #define AD7124_FILTER_FILTER GENMASK(23, 21) 99 98 #define AD7124_FILTER_FILTER_SINC4 0 100 99 #define AD7124_FILTER_FILTER_SINC3 2 100 + #define AD7124_FILTER_FILTER_SINC4_SINC1 4 101 + #define AD7124_FILTER_FILTER_SINC3_SINC1 5 102 + #define AD7124_FILTER_FILTER_SINC3_PF 7 103 + #define AD7124_FILTER_REJ60 BIT(20) 104 + #define AD7124_FILTER_POST_FILTER GENMASK(19, 17) 105 + #define AD7124_FILTER_POST_FILTER_47dB 2 106 + #define AD7124_FILTER_POST_FILTER_62dB 3 107 + #define AD7124_FILTER_POST_FILTER_86dB 5 108 + #define AD7124_FILTER_POST_FILTER_92dB 6 101 109 #define AD7124_FILTER_SINGLE_CYCLE BIT(16) 102 110 #define AD7124_FILTER_FS GENMASK(10, 0) 103 111 ··· 161 151 unsigned int num_inputs; 162 152 }; 163 153 154 + enum ad7124_filter_type { 155 + AD7124_FILTER_TYPE_SINC3, 156 + AD7124_FILTER_TYPE_SINC3_PF1, 157 + AD7124_FILTER_TYPE_SINC3_PF2, 158 + AD7124_FILTER_TYPE_SINC3_PF3, 159 + AD7124_FILTER_TYPE_SINC3_PF4, 160 + AD7124_FILTER_TYPE_SINC3_REJ60, 161 + AD7124_FILTER_TYPE_SINC3_SINC1, 162 + AD7124_FILTER_TYPE_SINC4, 163 + AD7124_FILTER_TYPE_SINC4_REJ60, 164 + AD7124_FILTER_TYPE_SINC4_SINC1, 165 + }; 166 + 164 167 struct ad7124_channel_config { 165 168 bool live; 166 169 unsigned int cfg_slot; 170 + unsigned int requested_odr; 171 + unsigned int requested_odr_micro; 167 172 /* 168 173 * Following fields are used to compare for equality. If you 169 174 * make adaptations in it, you most likely also have to adapt ··· 192 167 unsigned int vref_mv; 193 168 unsigned int pga_bits; 194 169 unsigned int odr_sel_bits; 195 - unsigned int filter_type; 170 + enum ad7124_filter_type filter_type; 196 171 unsigned int calibration_offset; 197 172 unsigned int calibration_gain; 198 173 ); ··· 309 284 return fclk_hz; 310 285 } 311 286 287 + static u32 ad7124_get_fs_factor(struct ad7124_state *st, unsigned int channel) 288 + { 289 + enum ad7124_power_mode power_mode = 290 + FIELD_GET(AD7124_ADC_CONTROL_POWER_MODE, st->adc_control); 291 + u32 avg = power_mode == AD7124_LOW_POWER ? 8 : 16; 292 + 293 + /* 294 + * These are the "zero-latency" factors from the data sheet. For the 295 + * sinc1 filters, these aren't documented, but derived by taking the 296 + * single-channel formula from the sinc1 section of the data sheet and 297 + * multiplying that by the sinc3/4 factor from the corresponding zero- 298 + * latency sections. 299 + */ 300 + switch (st->channels[channel].cfg.filter_type) { 301 + case AD7124_FILTER_TYPE_SINC4: 302 + case AD7124_FILTER_TYPE_SINC4_REJ60: 303 + return 4 * 32; 304 + case AD7124_FILTER_TYPE_SINC4_SINC1: 305 + return 4 * avg * 32; 306 + case AD7124_FILTER_TYPE_SINC3_SINC1: 307 + return 3 * avg * 32; 308 + default: 309 + return 3 * 32; 310 + } 311 + } 312 + 312 313 static u32 ad7124_get_fadc_divisor(struct ad7124_state *st, unsigned int channel) 313 314 { 315 + u32 factor = ad7124_get_fs_factor(st, channel); 316 + 314 317 /* 315 318 * The output data rate (f_ADC) is f_CLK / divisor. We are returning 316 319 * the divisor. 317 320 */ 318 - return st->channels[channel].cfg.odr_sel_bits * 32 * 4; 321 + return st->channels[channel].cfg.odr_sel_bits * factor; 319 322 } 320 323 321 - static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel, 322 - unsigned int odr, unsigned int odr_micro) 324 + static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel) 323 325 { 324 - unsigned int fclk, factor, odr_sel_bits; 326 + struct ad7124_channel_config *cfg = &st->channels[channel].cfg; 327 + unsigned int fclk, factor, divisor, odr_sel_bits; 325 328 326 329 fclk = ad7124_get_fclk_hz(st); 330 + factor = ad7124_get_fs_factor(st, channel); 327 331 328 332 /* 329 333 * FS[10:0] = fCLK / (fADC x 32 * N) where: ··· 362 308 * FS[10:0] are the bits in the filter register 363 309 * FS[10:0] can have a value from 1 to 2047 364 310 */ 365 - factor = 32 * 4; /* N = 4 for default sinc4 filter. */ 366 - odr_sel_bits = DIV_ROUND_CLOSEST(fclk, odr * factor + 367 - odr_micro * factor / MICRO); 368 - odr_sel_bits = clamp(odr_sel_bits, 1, 2047); 311 + divisor = cfg->requested_odr * factor + 312 + cfg->requested_odr_micro * factor / MICRO; 313 + odr_sel_bits = clamp(DIV_ROUND_CLOSEST(fclk, divisor), 1, 2047); 369 314 370 315 if (odr_sel_bits != st->channels[channel].cfg.odr_sel_bits) 371 316 st->channels[channel].cfg.live = false; ··· 375 322 static int ad7124_get_3db_filter_factor(struct ad7124_state *st, 376 323 unsigned int channel) 377 324 { 325 + struct ad7124_channel_config *cfg = &st->channels[channel].cfg; 326 + 378 327 /* 379 328 * 3dB point is the f_CLK rate times some factor. This functions returns 380 329 * the factor times 1000. 381 330 */ 382 - switch (st->channels[channel].cfg.filter_type) { 383 - case AD7124_FILTER_FILTER_SINC3: 331 + switch (cfg->filter_type) { 332 + case AD7124_FILTER_TYPE_SINC3: 333 + case AD7124_FILTER_TYPE_SINC3_REJ60: 334 + case AD7124_FILTER_TYPE_SINC3_SINC1: 384 335 return 272; 385 - case AD7124_FILTER_FILTER_SINC4: 336 + case AD7124_FILTER_TYPE_SINC4: 337 + case AD7124_FILTER_TYPE_SINC4_REJ60: 338 + case AD7124_FILTER_TYPE_SINC4_SINC1: 386 339 return 230; 340 + case AD7124_FILTER_TYPE_SINC3_PF1: 341 + return 633; 342 + case AD7124_FILTER_TYPE_SINC3_PF2: 343 + return 605; 344 + case AD7124_FILTER_TYPE_SINC3_PF3: 345 + return 669; 346 + case AD7124_FILTER_TYPE_SINC3_PF4: 347 + return 759; 387 348 default: 388 349 return -EINVAL; 389 350 } ··· 422 355 unsigned int vref_mv; 423 356 unsigned int pga_bits; 424 357 unsigned int odr_sel_bits; 425 - unsigned int filter_type; 358 + enum ad7124_filter_type filter_type; 426 359 unsigned int calibration_offset; 427 360 unsigned int calibration_gain; 428 361 })); ··· 489 422 static int ad7124_write_config(struct ad7124_state *st, struct ad7124_channel_config *cfg, 490 423 unsigned int cfg_slot) 491 424 { 492 - unsigned int tmp; 493 - unsigned int val; 425 + unsigned int val, filter; 426 + unsigned int rej60 = 0; 427 + unsigned int post = 0; 494 428 int ret; 495 429 496 430 cfg->cfg_slot = cfg_slot; ··· 514 446 if (ret < 0) 515 447 return ret; 516 448 449 + switch (cfg->filter_type) { 450 + case AD7124_FILTER_TYPE_SINC3: 451 + filter = AD7124_FILTER_FILTER_SINC3; 452 + break; 453 + case AD7124_FILTER_TYPE_SINC3_PF1: 454 + filter = AD7124_FILTER_FILTER_SINC3_PF; 455 + post = AD7124_FILTER_POST_FILTER_47dB; 456 + break; 457 + case AD7124_FILTER_TYPE_SINC3_PF2: 458 + filter = AD7124_FILTER_FILTER_SINC3_PF; 459 + post = AD7124_FILTER_POST_FILTER_62dB; 460 + break; 461 + case AD7124_FILTER_TYPE_SINC3_PF3: 462 + filter = AD7124_FILTER_FILTER_SINC3_PF; 463 + post = AD7124_FILTER_POST_FILTER_86dB; 464 + break; 465 + case AD7124_FILTER_TYPE_SINC3_PF4: 466 + filter = AD7124_FILTER_FILTER_SINC3_PF; 467 + post = AD7124_FILTER_POST_FILTER_92dB; 468 + break; 469 + case AD7124_FILTER_TYPE_SINC3_REJ60: 470 + filter = AD7124_FILTER_FILTER_SINC3; 471 + rej60 = 1; 472 + break; 473 + case AD7124_FILTER_TYPE_SINC3_SINC1: 474 + filter = AD7124_FILTER_FILTER_SINC3_SINC1; 475 + break; 476 + case AD7124_FILTER_TYPE_SINC4: 477 + filter = AD7124_FILTER_FILTER_SINC4; 478 + break; 479 + case AD7124_FILTER_TYPE_SINC4_REJ60: 480 + filter = AD7124_FILTER_FILTER_SINC4; 481 + rej60 = 1; 482 + break; 483 + case AD7124_FILTER_TYPE_SINC4_SINC1: 484 + filter = AD7124_FILTER_FILTER_SINC4_SINC1; 485 + break; 486 + default: 487 + return -EINVAL; 488 + } 489 + 517 490 /* 518 491 * NB: AD7124_FILTER_SINGLE_CYCLE is always set so that we get the same 519 492 * sampling frequency even when only one channel is enabled in a ··· 562 453 * would be 1 and we would get a faster sampling frequency than what 563 454 * was requested. 564 455 */ 565 - tmp = FIELD_PREP(AD7124_FILTER_FILTER, cfg->filter_type) | 566 - AD7124_FILTER_SINGLE_CYCLE | 567 - FIELD_PREP(AD7124_FILTER_FS, cfg->odr_sel_bits); 568 - return ad7124_spi_write_mask(st, AD7124_FILTER(cfg->cfg_slot), 569 - AD7124_FILTER_FILTER | 570 - AD7124_FILTER_SINGLE_CYCLE | 571 - AD7124_FILTER_FS, 572 - tmp, 3); 456 + return ad_sd_write_reg(&st->sd, AD7124_FILTER(cfg->cfg_slot), 3, 457 + FIELD_PREP(AD7124_FILTER_FILTER, filter) | 458 + FIELD_PREP(AD7124_FILTER_REJ60, rej60) | 459 + FIELD_PREP(AD7124_FILTER_POST_FILTER, post) | 460 + AD7124_FILTER_SINGLE_CYCLE | 461 + FIELD_PREP(AD7124_FILTER_FS, cfg->odr_sel_bits)); 573 462 } 574 463 575 464 static struct ad7124_channel_config *ad7124_pop_config(struct ad7124_state *st) ··· 829 722 return -EINVAL; 830 723 } 831 724 832 - case IIO_CHAN_INFO_SAMP_FREQ: 833 - mutex_lock(&st->cfgs_lock); 834 - *val = ad7124_get_fclk_hz(st); 835 - *val2 = ad7124_get_fadc_divisor(st, chan->address); 836 - mutex_unlock(&st->cfgs_lock); 725 + case IIO_CHAN_INFO_SAMP_FREQ: { 726 + struct ad7124_channel_config *cfg = &st->channels[chan->address].cfg; 837 727 838 - return IIO_VAL_FRACTIONAL; 728 + guard(mutex)(&st->cfgs_lock); 729 + 730 + switch (cfg->filter_type) { 731 + case AD7124_FILTER_TYPE_SINC3: 732 + case AD7124_FILTER_TYPE_SINC3_REJ60: 733 + case AD7124_FILTER_TYPE_SINC3_SINC1: 734 + case AD7124_FILTER_TYPE_SINC4: 735 + case AD7124_FILTER_TYPE_SINC4_REJ60: 736 + case AD7124_FILTER_TYPE_SINC4_SINC1: 737 + *val = ad7124_get_fclk_hz(st); 738 + *val2 = ad7124_get_fadc_divisor(st, chan->address); 739 + return IIO_VAL_FRACTIONAL; 740 + /* 741 + * Post filters force the chip to a fixed rate. These are the 742 + * single-channel rates from the data sheet divided by 3 for 743 + * the multi-channel case (data sheet doesn't explicitly state 744 + * this but confirmed through testing). 745 + */ 746 + case AD7124_FILTER_TYPE_SINC3_PF1: 747 + *val = 300; 748 + *val2 = 33; 749 + return IIO_VAL_FRACTIONAL; 750 + case AD7124_FILTER_TYPE_SINC3_PF2: 751 + *val = 25; 752 + *val2 = 3; 753 + return IIO_VAL_FRACTIONAL; 754 + case AD7124_FILTER_TYPE_SINC3_PF3: 755 + *val = 20; 756 + *val2 = 3; 757 + return IIO_VAL_FRACTIONAL; 758 + case AD7124_FILTER_TYPE_SINC3_PF4: 759 + *val = 50; 760 + *val2 = 9; 761 + return IIO_VAL_FRACTIONAL; 762 + default: 763 + return -EINVAL; 764 + } 765 + } 839 766 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: { 840 767 guard(mutex)(&st->cfgs_lock); 841 768 ··· 892 751 int val, int val2, long info) 893 752 { 894 753 struct ad7124_state *st = iio_priv(indio_dev); 754 + struct ad7124_channel_config *cfg = &st->channels[chan->address].cfg; 895 755 unsigned int res, gain, full_scale, vref; 896 756 897 757 guard(mutex)(&st->cfgs_lock); ··· 902 760 if (val2 < 0 || val < 0 || (val2 == 0 && val == 0)) 903 761 return -EINVAL; 904 762 905 - ad7124_set_channel_odr(st, chan->address, val, val2); 763 + cfg->requested_odr = val; 764 + cfg->requested_odr_micro = val2; 765 + ad7124_set_channel_odr(st, chan->address); 906 766 907 767 return 0; 908 768 case IIO_CHAN_INFO_SCALE: ··· 1150 1006 .get = ad7124_get_syscalib_mode 1151 1007 }; 1152 1008 1009 + static const char * const ad7124_filter_types[] = { 1010 + [AD7124_FILTER_TYPE_SINC3] = "sinc3", 1011 + [AD7124_FILTER_TYPE_SINC3_PF1] = "sinc3+pf1", 1012 + [AD7124_FILTER_TYPE_SINC3_PF2] = "sinc3+pf2", 1013 + [AD7124_FILTER_TYPE_SINC3_PF3] = "sinc3+pf3", 1014 + [AD7124_FILTER_TYPE_SINC3_PF4] = "sinc3+pf4", 1015 + [AD7124_FILTER_TYPE_SINC3_REJ60] = "sinc3+rej60", 1016 + [AD7124_FILTER_TYPE_SINC3_SINC1] = "sinc3+sinc1", 1017 + [AD7124_FILTER_TYPE_SINC4] = "sinc4", 1018 + [AD7124_FILTER_TYPE_SINC4_REJ60] = "sinc4+rej60", 1019 + [AD7124_FILTER_TYPE_SINC4_SINC1] = "sinc4+sinc1", 1020 + }; 1021 + 1022 + static int ad7124_set_filter_type_attr(struct iio_dev *dev, 1023 + const struct iio_chan_spec *chan, 1024 + unsigned int value) 1025 + { 1026 + struct ad7124_state *st = iio_priv(dev); 1027 + struct ad7124_channel_config *cfg = &st->channels[chan->address].cfg; 1028 + 1029 + guard(mutex)(&st->cfgs_lock); 1030 + 1031 + cfg->live = false; 1032 + cfg->filter_type = value; 1033 + ad7124_set_channel_odr(st, chan->address); 1034 + 1035 + return 0; 1036 + } 1037 + 1038 + static int ad7124_get_filter_type_attr(struct iio_dev *dev, 1039 + const struct iio_chan_spec *chan) 1040 + { 1041 + struct ad7124_state *st = iio_priv(dev); 1042 + 1043 + guard(mutex)(&st->cfgs_lock); 1044 + 1045 + return st->channels[chan->address].cfg.filter_type; 1046 + } 1047 + 1048 + static const struct iio_enum ad7124_filter_type_enum = { 1049 + .items = ad7124_filter_types, 1050 + .num_items = ARRAY_SIZE(ad7124_filter_types), 1051 + .set = ad7124_set_filter_type_attr, 1052 + .get = ad7124_get_filter_type_attr, 1053 + }; 1054 + 1153 1055 static const struct iio_chan_spec_ext_info ad7124_calibsys_ext_info[] = { 1154 1056 { 1155 1057 .name = "sys_calibration", ··· 1206 1016 &ad7124_syscalib_mode_enum), 1207 1017 IIO_ENUM_AVAILABLE("sys_calibration_mode", IIO_SHARED_BY_TYPE, 1208 1018 &ad7124_syscalib_mode_enum), 1019 + IIO_ENUM("filter_type", IIO_SEPARATE, &ad7124_filter_type_enum), 1020 + IIO_ENUM_AVAILABLE("filter_type", IIO_SHARED_BY_TYPE, 1021 + &ad7124_filter_type_enum), 1209 1022 { } 1210 1023 }; 1211 1024 ··· 1492 1299 mutex_init(&st->cfgs_lock); 1493 1300 INIT_KFIFO(st->live_cfgs_fifo); 1494 1301 for (i = 0; i < st->num_channels; i++) { 1302 + struct ad7124_channel_config *cfg = &st->channels[i].cfg; 1495 1303 1496 - ret = ad7124_init_config_vref(st, &st->channels[i].cfg); 1304 + ret = ad7124_init_config_vref(st, cfg); 1497 1305 if (ret < 0) 1498 1306 return ret; 1307 + 1308 + /* Default filter type on the ADC after reset. */ 1309 + cfg->filter_type = AD7124_FILTER_TYPE_SINC4; 1499 1310 1500 1311 /* 1501 1312 * 9.38 SPS is the minimum output data rate supported 1502 1313 * regardless of the selected power mode. Round it up to 10 and 1503 1314 * set all channels to this default value. 1504 1315 */ 1505 - ad7124_set_channel_odr(st, i, 10, 0); 1316 + cfg->requested_odr = 10; 1317 + ad7124_set_channel_odr(st, i); 1506 1318 } 1507 1319 1508 1320 ad7124_disable_all(&st->sd);