88 * AD7175-8/AD7176-2/AD7177-2
99 *
1010 * Copyright (C) 2015, 2024 Analog Devices, Inc.
11+ * Copyright (C) 2025 BayLibre, SAS
1112 */
1213
1314#include <linux/array_size.h>
149150 (pin2) < st->info->num_voltage_in && \
150151 (pin2) >= st->info->num_voltage_in_div)
151152
152- #define AD7173_FILTER_ODR0_MASK GENMASK(5, 0)
153+ #define AD7173_FILTER_SINC3_MAP BIT(15)
154+ #define AD7173_FILTER_SINC3_MAP_DIV GENMASK(14, 0)
155+ #define AD7173_FILTER_ENHFILTEN BIT(11)
156+ #define AD7173_FILTER_ENHFILT_MASK GENMASK(10, 8)
157+ #define AD7173_FILTER_ORDER BIT(6)
158+ #define AD7173_FILTER_ODR_MASK GENMASK(5, 0)
153159#define AD7173_MAX_CONFIGS 8
154160#define AD4111_OW_DET_THRSH_MV 300
155161
@@ -190,6 +196,15 @@ struct ad7173_device_info {
190196 u8 num_gpios ;
191197};
192198
199+ enum ad7173_filter_type {
200+ AD7173_FILTER_SINC3 ,
201+ AD7173_FILTER_SINC5_SINC1 ,
202+ AD7173_FILTER_SINC5_SINC1_PF1 ,
203+ AD7173_FILTER_SINC5_SINC1_PF2 ,
204+ AD7173_FILTER_SINC5_SINC1_PF3 ,
205+ AD7173_FILTER_SINC5_SINC1_PF4 ,
206+ };
207+
193208struct ad7173_channel_config {
194209 /* Openwire detection threshold */
195210 unsigned int openwire_thrsh_raw ;
@@ -205,8 +220,10 @@ struct ad7173_channel_config {
205220 struct_group (config_props ,
206221 bool bipolar ;
207222 bool input_buf ;
223+ u16 sinc3_odr_div ;
208224 u8 sinc5_odr_index ;
209225 u8 ref_sel ;
226+ enum ad7173_filter_type filter_type ;
210227 );
211228};
212229
@@ -266,6 +283,24 @@ static const unsigned int ad7175_sinc5_data_rates[] = {
266283 5000 , /* 20 */
267284};
268285
286+ /**
287+ * ad7173_sinc3_odr_div_from_odr() - Convert ODR to divider value
288+ * @odr_millihz: ODR (sampling_frequency) in milliHz
289+ * Returns: Divider value for SINC3 filter to pass.
290+ */
291+ static u16 ad7173_sinc3_odr_div_from_odr (u32 odr_millihz )
292+ {
293+ /*
294+ * Divider is f_MOD (1 MHz) / 32 / ODR. ODR freq is in milliHz, so
295+ * we need to convert f_MOD to the same units. When SING_CYC=1 or
296+ * multiple channels are enabled (currently always the case), there
297+ * is an additional factor of 3.
298+ */
299+ u32 div = DIV_ROUND_CLOSEST (MEGA * MILLI , odr_millihz * 32 * 3 );
300+ /* Avoid divide by 0 and limit to register field size. */
301+ return clamp (div , 1U , AD7173_FILTER_SINC3_MAP_DIV );
302+ }
303+
269304static unsigned int ad4111_current_channel_config [] = {
270305 /* Ain sel: pos neg */
271306 0x1E8 , /* 15:IIN0+ 8:IIN0− */
@@ -369,6 +404,47 @@ static const struct iio_enum ad7173_syscalib_mode_enum = {
369404 .get = ad7173_get_syscalib_mode
370405};
371406
407+ static const char * const ad7173_filter_types_str [] = {
408+ [AD7173_FILTER_SINC3 ] = "sinc3" ,
409+ [AD7173_FILTER_SINC5_SINC1 ] = "sinc5+sinc1" ,
410+ [AD7173_FILTER_SINC5_SINC1_PF1 ] = "sinc5+sinc1+pf1" ,
411+ [AD7173_FILTER_SINC5_SINC1_PF2 ] = "sinc5+sinc1+pf2" ,
412+ [AD7173_FILTER_SINC5_SINC1_PF3 ] = "sinc5+sinc1+pf3" ,
413+ [AD7173_FILTER_SINC5_SINC1_PF4 ] = "sinc5+sinc1+pf4" ,
414+ };
415+
416+ static int ad7173_set_filter_type (struct iio_dev * indio_dev ,
417+ const struct iio_chan_spec * chan ,
418+ unsigned int val )
419+ {
420+ struct ad7173_state * st = iio_priv (indio_dev );
421+
422+ if (!iio_device_claim_direct (indio_dev ))
423+ return - EBUSY ;
424+
425+ st -> channels [chan -> address ].cfg .filter_type = val ;
426+ st -> channels [chan -> address ].cfg .live = false;
427+
428+ iio_device_release_direct (indio_dev );
429+
430+ return 0 ;
431+ }
432+
433+ static int ad7173_get_filter_type (struct iio_dev * indio_dev ,
434+ const struct iio_chan_spec * chan )
435+ {
436+ struct ad7173_state * st = iio_priv (indio_dev );
437+
438+ return st -> channels [chan -> address ].cfg .filter_type ;
439+ }
440+
441+ static const struct iio_enum ad7173_filter_type_enum = {
442+ .items = ad7173_filter_types_str ,
443+ .num_items = ARRAY_SIZE (ad7173_filter_types_str ),
444+ .set = ad7173_set_filter_type ,
445+ .get = ad7173_get_filter_type ,
446+ };
447+
372448static const struct iio_chan_spec_ext_info ad7173_chan_spec_ext_info [] = {
373449 {
374450 .name = "sys_calibration" ,
@@ -379,6 +455,16 @@ static const struct iio_chan_spec_ext_info ad7173_chan_spec_ext_info[] = {
379455 & ad7173_syscalib_mode_enum ),
380456 IIO_ENUM_AVAILABLE ("sys_calibration_mode" , IIO_SHARED_BY_TYPE ,
381457 & ad7173_syscalib_mode_enum ),
458+ IIO_ENUM ("filter_type" , IIO_SEPARATE , & ad7173_filter_type_enum ),
459+ IIO_ENUM_AVAILABLE ("filter_type" , IIO_SHARED_BY_TYPE ,
460+ & ad7173_filter_type_enum ),
461+ { }
462+ };
463+
464+ static const struct iio_chan_spec_ext_info ad7173_temp_chan_spec_ext_info [] = {
465+ IIO_ENUM ("filter_type" , IIO_SEPARATE , & ad7173_filter_type_enum ),
466+ IIO_ENUM_AVAILABLE ("filter_type" , IIO_SHARED_BY_TYPE ,
467+ & ad7173_filter_type_enum ),
382468 { }
383469};
384470
@@ -582,14 +668,18 @@ static bool ad7173_is_setup_equal(const struct ad7173_channel_config *cfg1,
582668 sizeof (struct {
583669 bool bipolar ;
584670 bool input_buf ;
671+ u16 sinc3_odr_div ;
585672 u8 sinc5_odr_index ;
586673 u8 ref_sel ;
674+ enum ad7173_filter_type filter_type ;
587675 }));
588676
589677 return cfg1 -> bipolar == cfg2 -> bipolar &&
590678 cfg1 -> input_buf == cfg2 -> input_buf &&
679+ cfg1 -> sinc3_odr_div == cfg2 -> sinc3_odr_div &&
591680 cfg1 -> sinc5_odr_index == cfg2 -> sinc5_odr_index &&
592- cfg1 -> ref_sel == cfg2 -> ref_sel ;
681+ cfg1 -> ref_sel == cfg2 -> ref_sel &&
682+ cfg1 -> filter_type == cfg2 -> filter_type ;
593683}
594684
595685static struct ad7173_channel_config *
@@ -630,6 +720,7 @@ static int ad7173_load_config(struct ad7173_state *st,
630720{
631721 unsigned int config ;
632722 int free_cfg_slot , ret ;
723+ u8 post_filter_enable , post_filter_select ;
633724
634725 free_cfg_slot = ida_alloc_range (& st -> cfg_slots_status , 0 ,
635726 st -> info -> num_configs - 1 , GFP_KERNEL );
@@ -649,8 +740,49 @@ static int ad7173_load_config(struct ad7173_state *st,
649740 if (ret )
650741 return ret ;
651742
743+ /*
744+ * When SINC3_MAP flag is enabled, the rest of the register has a
745+ * different meaning. We are using this option to allow the most
746+ * possible sampling frequencies with SINC3 filter.
747+ */
748+ if (cfg -> filter_type == AD7173_FILTER_SINC3 )
749+ return ad_sd_write_reg (& st -> sd , AD7173_REG_FILTER (free_cfg_slot ), 2 ,
750+ FIELD_PREP (AD7173_FILTER_SINC3_MAP , 1 ) |
751+ FIELD_PREP (AD7173_FILTER_SINC3_MAP_DIV ,
752+ cfg -> sinc3_odr_div ));
753+
754+ switch (cfg -> filter_type ) {
755+ case AD7173_FILTER_SINC5_SINC1_PF1 :
756+ post_filter_enable = 1 ;
757+ post_filter_select = 2 ;
758+ break ;
759+ case AD7173_FILTER_SINC5_SINC1_PF2 :
760+ post_filter_enable = 1 ;
761+ post_filter_select = 3 ;
762+ break ;
763+ case AD7173_FILTER_SINC5_SINC1_PF3 :
764+ post_filter_enable = 1 ;
765+ post_filter_select = 5 ;
766+ break ;
767+ case AD7173_FILTER_SINC5_SINC1_PF4 :
768+ post_filter_enable = 1 ;
769+ post_filter_select = 6 ;
770+ break ;
771+ default :
772+ post_filter_enable = 0 ;
773+ post_filter_select = 0 ;
774+ break ;
775+ }
776+
652777 return ad_sd_write_reg (& st -> sd , AD7173_REG_FILTER (free_cfg_slot ), 2 ,
653- AD7173_FILTER_ODR0_MASK & cfg -> sinc5_odr_index );
778+ FIELD_PREP (AD7173_FILTER_SINC3_MAP , 0 ) |
779+ FIELD_PREP (AD7173_FILTER_ENHFILT_MASK ,
780+ post_filter_enable ) |
781+ FIELD_PREP (AD7173_FILTER_ENHFILTEN ,
782+ post_filter_select ) |
783+ FIELD_PREP (AD7173_FILTER_ORDER , 0 ) |
784+ FIELD_PREP (AD7173_FILTER_ODR_MASK ,
785+ cfg -> sinc5_odr_index ));
654786}
655787
656788static int ad7173_config_channel (struct ad7173_state * st , int addr )
@@ -1183,6 +1315,13 @@ static int ad7173_read_raw(struct iio_dev *indio_dev,
11831315 return - EINVAL ;
11841316 }
11851317 case IIO_CHAN_INFO_SAMP_FREQ :
1318+ if (st -> channels [chan -> address ].cfg .filter_type == AD7173_FILTER_SINC3 ) {
1319+ /* Inverse operation of ad7173_sinc3_odr_div_from_odr() */
1320+ * val = MEGA ;
1321+ * val2 = 3 * 32 * st -> channels [chan -> address ].cfg .sinc3_odr_div ;
1322+ return IIO_VAL_FRACTIONAL ;
1323+ }
1324+
11861325 reg = st -> channels [chan -> address ].cfg .sinc5_odr_index ;
11871326
11881327 * val = st -> info -> sinc5_data_rates [reg ] / MILLI ;
@@ -1221,6 +1360,10 @@ static int ad7173_write_raw(struct iio_dev *indio_dev,
12211360 *
12221361 * This will cause the reading of CH1 to be actually done once every
12231362 * 200.16ms, an effective rate of 4.99sps.
1363+ *
1364+ * Both the sinc5 and sinc3 rates are set here so that if the filter
1365+ * type is changed, the requested rate will still be set (aside from
1366+ * rounding differences).
12241367 */
12251368 case IIO_CHAN_INFO_SAMP_FREQ :
12261369 freq = val * MILLI + val2 / MILLI ;
@@ -1230,6 +1373,7 @@ static int ad7173_write_raw(struct iio_dev *indio_dev,
12301373
12311374 cfg = & st -> channels [chan -> address ].cfg ;
12321375 cfg -> sinc5_odr_index = i ;
1376+ cfg -> sinc3_odr_div = ad7173_sinc3_odr_div_from_odr (freq );
12331377 cfg -> live = false;
12341378 break ;
12351379
@@ -1246,17 +1390,40 @@ static int ad7173_update_scan_mode(struct iio_dev *indio_dev,
12461390 const unsigned long * scan_mask )
12471391{
12481392 struct ad7173_state * st = iio_priv (indio_dev );
1393+ u16 sinc3_count = 0 ;
1394+ u16 sinc3_div = 0 ;
12491395 int i , j , k , ret ;
12501396
12511397 for (i = 0 ; i < indio_dev -> num_channels ; i ++ ) {
1252- if (test_bit (i , scan_mask ))
1398+ const struct ad7173_channel_config * cfg = & st -> channels [i ].cfg ;
1399+
1400+ if (test_bit (i , scan_mask )) {
1401+ if (cfg -> filter_type == AD7173_FILTER_SINC3 ) {
1402+ sinc3_count ++ ;
1403+
1404+ if (sinc3_div == 0 ) {
1405+ sinc3_div = cfg -> sinc3_odr_div ;
1406+ } else if (sinc3_div != cfg -> sinc3_odr_div ) {
1407+ dev_err (& st -> sd .spi -> dev ,
1408+ "All enabled channels must have the same sampling_frequency for sinc3 filter_type\n" );
1409+ return - EINVAL ;
1410+ }
1411+ }
1412+
12531413 ret = ad7173_set_channel (& st -> sd , i );
1254- else
1414+ } else {
12551415 ret = ad_sd_write_reg (& st -> sd , AD7173_REG_CH (i ), 2 , 0 );
1416+ }
12561417 if (ret < 0 )
12571418 return ret ;
12581419 }
12591420
1421+ if (sinc3_count && sinc3_count < bitmap_weight (scan_mask , indio_dev -> num_channels )) {
1422+ dev_err (& st -> sd .spi -> dev ,
1423+ "All enabled channels must have sinc3 filter_type\n" );
1424+ return - EINVAL ;
1425+ }
1426+
12601427 /*
12611428 * On some chips, there are more channels that setups, so if there were
12621429 * more unique setups requested than the number of available slots,
@@ -1415,6 +1582,7 @@ static const struct iio_chan_spec ad7173_temp_iio_channel_template = {
14151582 .storagebits = 32 ,
14161583 .endianness = IIO_BE ,
14171584 },
1585+ .ext_info = ad7173_temp_chan_spec_ext_info ,
14181586};
14191587
14201588static void ad7173_disable_regulators (void * data )
@@ -1655,7 +1823,11 @@ static int ad7173_fw_parse_channel_config(struct iio_dev *indio_dev)
16551823 chan_st_priv -> cfg .bipolar = false;
16561824 chan_st_priv -> cfg .input_buf = st -> info -> has_input_buf ;
16571825 chan_st_priv -> cfg .ref_sel = AD7173_SETUP_REF_SEL_INT_REF ;
1826+ chan_st_priv -> cfg .sinc3_odr_div = ad7173_sinc3_odr_div_from_odr (
1827+ st -> info -> sinc5_data_rates [st -> info -> odr_start_value ]
1828+ );
16581829 chan_st_priv -> cfg .sinc5_odr_index = st -> info -> odr_start_value ;
1830+ chan_st_priv -> cfg .filter_type = AD7173_FILTER_SINC5_SINC1 ;
16591831 chan_st_priv -> cfg .openwire_comp_chan = -1 ;
16601832 st -> adc_mode |= AD7173_ADC_MODE_REF_EN ;
16611833 if (st -> info -> data_reg_only_16bit )
@@ -1727,7 +1899,11 @@ static int ad7173_fw_parse_channel_config(struct iio_dev *indio_dev)
17271899 chan -> scan_index = chan_index ;
17281900 chan -> channel = ain [0 ];
17291901 chan_st_priv -> cfg .input_buf = st -> info -> has_input_buf ;
1902+ chan_st_priv -> cfg .sinc3_odr_div = ad7173_sinc3_odr_div_from_odr (
1903+ st -> info -> sinc5_data_rates [st -> info -> odr_start_value ]
1904+ );
17301905 chan_st_priv -> cfg .sinc5_odr_index = st -> info -> odr_start_value ;
1906+ chan_st_priv -> cfg .filter_type = AD7173_FILTER_SINC5_SINC1 ;
17311907 chan_st_priv -> cfg .openwire_comp_chan = -1 ;
17321908
17331909 chan_st_priv -> cfg .bipolar = fwnode_property_read_bool (child , "bipolar" );
0 commit comments