1313 * ad7381-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7381-4.pdf
1414 * ad7383/4-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7383-4-ad7384-4.pdf
1515 * ad7386/7/8-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7386-4-7387-4-7388-4.pdf
16+ * adaq4370-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4370-4.pdf
17+ * adaq4380-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4380-4.pdf
1618 */
1719
1820#include <linux/align.h>
2224#include <linux/device.h>
2325#include <linux/err.h>
2426#include <linux/kernel.h>
27+ #include <linux/math.h>
2528#include <linux/module.h>
2629#include <linux/regmap.h>
2730#include <linux/regulator/consumer.h>
2831#include <linux/slab.h>
2932#include <linux/spi/spi.h>
33+ #include <linux/units.h>
34+ #include <linux/util_macros.h>
3035
3136#include <linux/iio/buffer.h>
3237#include <linux/iio/iio.h>
3641#define MAX_NUM_CHANNELS 8
3742/* 2.5V internal reference voltage */
3843#define AD7380_INTERNAL_REF_MV 2500
44+ /* 3.3V internal reference voltage for ADAQ */
45+ #define ADAQ4380_INTERNAL_REF_MV 3300
3946
4047/* reading and writing registers is more reliable at lower than max speed */
4148#define AD7380_REG_WR_SPEED_HZ 10000000
8289 * supports only 1 SDO line (standard SPI transaction)
8390 */
8491#define AD7380_NUM_SDO_LINES 1
92+ #define AD7380_DEFAULT_GAIN_MILLI 1000
8593
8694struct ad7380_timing_specs {
8795 const unsigned int t_csh_ns ; /* CS minimum high time */
@@ -92,10 +100,12 @@ struct ad7380_chip_info {
92100 const struct iio_chan_spec * channels ;
93101 unsigned int num_channels ;
94102 unsigned int num_simult_channels ;
103+ bool has_hardware_gain ;
95104 bool has_mux ;
96105 const char * const * supplies ;
97106 unsigned int num_supplies ;
98107 bool external_ref_only ;
108+ bool adaq_internal_ref_only ;
99109 const char * const * vcm_supplies ;
100110 unsigned int num_vcm_supplies ;
101111 const unsigned long * available_scan_masks ;
@@ -187,11 +197,12 @@ static const struct iio_scan_type ad7380_scan_type_16_u[] = {
187197 },
188198};
189199
190- #define AD7380_CHANNEL (index , bits , diff , sign ) { \
200+ #define _AD7380_CHANNEL (index , bits , diff , sign , gain ) { \
191201 .type = IIO_VOLTAGE, \
192202 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
203+ ((gain) ? BIT(IIO_CHAN_INFO_SCALE) : 0) | \
193204 ((diff) ? 0 : BIT(IIO_CHAN_INFO_OFFSET)), \
194- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
205+ .info_mask_shared_by_type = ((gain) ? 0 : BIT(IIO_CHAN_INFO_SCALE)) | \
195206 BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
196207 .info_mask_shared_by_type_available = \
197208 BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
@@ -205,6 +216,12 @@ static const struct iio_scan_type ad7380_scan_type_16_u[] = {
205216 .num_ext_scan_type = ARRAY_SIZE(ad7380_scan_type_##bits##_##sign), \
206217}
207218
219+ #define AD7380_CHANNEL (index , bits , diff , sign ) \
220+ _AD7380_CHANNEL(index, bits, diff, sign, false)
221+
222+ #define ADAQ4380_CHANNEL (index , bits , diff , sign ) \
223+ _AD7380_CHANNEL(index, bits, diff, sign, true)
224+
208225#define DEFINE_AD7380_2_CHANNEL (name , bits , diff , sign ) \
209226static const struct iio_chan_spec name[] = { \
210227 AD7380_CHANNEL(0, bits, diff, sign), \
@@ -221,6 +238,15 @@ static const struct iio_chan_spec name[] = { \
221238 IIO_CHAN_SOFT_TIMESTAMP(4), \
222239}
223240
241+ #define DEFINE_ADAQ4380_4_CHANNEL (name , bits , diff , sign ) \
242+ static const struct iio_chan_spec name[] = { \
243+ ADAQ4380_CHANNEL(0, bits, diff, sign), \
244+ ADAQ4380_CHANNEL(1, bits, diff, sign), \
245+ ADAQ4380_CHANNEL(2, bits, diff, sign), \
246+ ADAQ4380_CHANNEL(3, bits, diff, sign), \
247+ IIO_CHAN_SOFT_TIMESTAMP(4), \
248+ }
249+
224250#define DEFINE_AD7380_8_CHANNEL (name , bits , diff , sign ) \
225251static const struct iio_chan_spec name[] = { \
226252 AD7380_CHANNEL(0, bits, diff, sign), \
@@ -239,6 +265,7 @@ DEFINE_AD7380_2_CHANNEL(ad7380_channels, 16, 1, s);
239265DEFINE_AD7380_2_CHANNEL (ad7381_channels , 14 , 1 , s );
240266DEFINE_AD7380_4_CHANNEL (ad7380_4_channels , 16 , 1 , s );
241267DEFINE_AD7380_4_CHANNEL (ad7381_4_channels , 14 , 1 , s );
268+ DEFINE_ADAQ4380_4_CHANNEL (adaq4380_4_channels , 16 , 1 , s );
242269/* pseudo differential */
243270DEFINE_AD7380_2_CHANNEL (ad7383_channels , 16 , 0 , s );
244271DEFINE_AD7380_2_CHANNEL (ad7384_channels , 14 , 0 , s );
@@ -257,6 +284,10 @@ static const char * const ad7380_supplies[] = {
257284 "vcc" , "vlogic" ,
258285};
259286
287+ static const char * const adaq4380_supplies [] = {
288+ "ldo" , "vcc" , "vlogic" , "vs-p" , "vs-n" , "refin" ,
289+ };
290+
260291static const char * const ad7380_2_channel_vcm_supplies [] = {
261292 "aina" , "ainb" ,
262293};
@@ -347,6 +378,11 @@ static const int ad7380_oversampling_ratios[] = {
347378 1 , 2 , 4 , 8 , 16 , 32 ,
348379};
349380
381+ /* Gains stored as fractions of 1000 so they can be expressed by integers. */
382+ static const int ad7380_gains [] = {
383+ 300 , 600 , 1000 , 1600 ,
384+ };
385+
350386static const struct ad7380_chip_info ad7380_chip_info = {
351387 .name = "ad7380" ,
352388 .channels = ad7380_channels ,
@@ -516,6 +552,32 @@ static const struct ad7380_chip_info ad7388_4_chip_info = {
516552 .timing_specs = & ad7380_4_timing ,
517553};
518554
555+ static const struct ad7380_chip_info adaq4370_4_chip_info = {
556+ .name = "adaq4370-4" ,
557+ .channels = adaq4380_4_channels ,
558+ .num_channels = ARRAY_SIZE (adaq4380_4_channels ),
559+ .num_simult_channels = 4 ,
560+ .supplies = adaq4380_supplies ,
561+ .num_supplies = ARRAY_SIZE (adaq4380_supplies ),
562+ .adaq_internal_ref_only = true,
563+ .has_hardware_gain = true,
564+ .available_scan_masks = ad7380_4_channel_scan_masks ,
565+ .timing_specs = & ad7380_4_timing ,
566+ };
567+
568+ static const struct ad7380_chip_info adaq4380_4_chip_info = {
569+ .name = "adaq4380-4" ,
570+ .channels = adaq4380_4_channels ,
571+ .num_channels = ARRAY_SIZE (adaq4380_4_channels ),
572+ .num_simult_channels = 4 ,
573+ .supplies = adaq4380_supplies ,
574+ .num_supplies = ARRAY_SIZE (adaq4380_supplies ),
575+ .adaq_internal_ref_only = true,
576+ .has_hardware_gain = true,
577+ .available_scan_masks = ad7380_4_channel_scan_masks ,
578+ .timing_specs = & ad7380_4_timing ,
579+ };
580+
519581struct ad7380_state {
520582 const struct ad7380_chip_info * chip_info ;
521583 struct spi_device * spi ;
@@ -526,6 +588,7 @@ struct ad7380_state {
526588 bool seq ;
527589 unsigned int vref_mv ;
528590 unsigned int vcm_mv [MAX_NUM_CHANNELS ];
591+ unsigned int gain_milli [MAX_NUM_CHANNELS ];
529592 /* xfers, message an buffer for reading sample data */
530593 struct spi_transfer normal_xfer [2 ];
531594 struct spi_message normal_msg ;
@@ -876,8 +939,15 @@ static int ad7380_read_raw(struct iio_dev *indio_dev,
876939 * * (2 × VREF) / 2^N, for differential chips
877940 * * VREF / 2^N, for pseudo-differential chips
878941 * where N is the ADC resolution (i.e realbits)
942+ *
943+ * The gain is stored as a fraction of 1000 and, as we need to
944+ * divide vref_mv by the gain, we invert the gain/1000 fraction.
879945 */
880- * val = st -> vref_mv ;
946+ if (st -> chip_info -> has_hardware_gain )
947+ * val = mult_frac (st -> vref_mv , MILLI ,
948+ st -> gain_milli [chan -> scan_index ]);
949+ else
950+ * val = st -> vref_mv ;
881951 * val2 = scan_type -> realbits - chan -> differential ;
882952
883953 return IIO_VAL_FRACTIONAL_LOG2 ;
@@ -1059,7 +1129,19 @@ static int ad7380_probe(struct spi_device *spi)
10591129 "Failed to enable power supplies\n" );
10601130 fsleep (T_POWERUP_US );
10611131
1062- if (st -> chip_info -> external_ref_only ) {
1132+ if (st -> chip_info -> adaq_internal_ref_only ) {
1133+ /*
1134+ * ADAQ chips use fixed internal reference but still
1135+ * require a specific reference supply to power it.
1136+ * "refin" is already enabled with other power supplies
1137+ * in bulk_get_enable().
1138+ */
1139+
1140+ st -> vref_mv = ADAQ4380_INTERNAL_REF_MV ;
1141+
1142+ /* these chips don't have a register bit for this */
1143+ external_ref_en = false;
1144+ } else if (st -> chip_info -> external_ref_only ) {
10631145 ret = devm_regulator_get_enable_read_voltage (dev , "refin" );
10641146 if (ret < 0 )
10651147 return dev_err_probe (dev , ret ,
@@ -1103,6 +1185,42 @@ static int ad7380_probe(struct spi_device *spi)
11031185 st -> vcm_mv [i ] = ret / 1000 ;
11041186 }
11051187
1188+ for (i = 0 ; i < MAX_NUM_CHANNELS ; i ++ )
1189+ st -> gain_milli [i ] = AD7380_DEFAULT_GAIN_MILLI ;
1190+
1191+ if (st -> chip_info -> has_hardware_gain ) {
1192+ device_for_each_child_node_scoped (dev , node ) {
1193+ unsigned int channel , gain ;
1194+ int gain_idx ;
1195+
1196+ ret = fwnode_property_read_u32 (node , "reg" , & channel );
1197+ if (ret )
1198+ return dev_err_probe (dev , ret ,
1199+ "Failed to read reg property\n" );
1200+
1201+ if (channel >= st -> chip_info -> num_channels - 1 )
1202+ return dev_err_probe (dev , - EINVAL ,
1203+ "Invalid channel number %i\n" ,
1204+ channel );
1205+
1206+ ret = fwnode_property_read_u32 (node , "adi,gain-milli" ,
1207+ & gain );
1208+ if (ret && ret != - EINVAL )
1209+ return dev_err_probe (dev , ret ,
1210+ "Failed to read gain for channel %i\n" ,
1211+ channel );
1212+ if (ret != - EINVAL ) {
1213+ /*
1214+ * Match gain value from dt to one of supported
1215+ * gains
1216+ */
1217+ gain_idx = find_closest (gain , ad7380_gains ,
1218+ ARRAY_SIZE (ad7380_gains ));
1219+ st -> gain_milli [channel ] = ad7380_gains [gain_idx ];
1220+ }
1221+ }
1222+ }
1223+
11061224 st -> regmap = devm_regmap_init (dev , NULL , st , & ad7380_regmap_config );
11071225 if (IS_ERR (st -> regmap ))
11081226 return dev_err_probe (dev , PTR_ERR (st -> regmap ),
@@ -1185,6 +1303,8 @@ static const struct of_device_id ad7380_of_match_table[] = {
11851303 { .compatible = "adi,ad7386-4" , .data = & ad7386_4_chip_info },
11861304 { .compatible = "adi,ad7387-4" , .data = & ad7387_4_chip_info },
11871305 { .compatible = "adi,ad7388-4" , .data = & ad7388_4_chip_info },
1306+ { .compatible = "adi,adaq4370-4" , .data = & adaq4370_4_chip_info },
1307+ { .compatible = "adi,adaq4380-4" , .data = & adaq4380_4_chip_info },
11881308 { }
11891309};
11901310
@@ -1203,6 +1323,8 @@ static const struct spi_device_id ad7380_id_table[] = {
12031323 { "ad7386-4" , (kernel_ulong_t )& ad7386_4_chip_info },
12041324 { "ad7387-4" , (kernel_ulong_t )& ad7387_4_chip_info },
12051325 { "ad7388-4" , (kernel_ulong_t )& ad7388_4_chip_info },
1326+ { "adaq4370-4" , (kernel_ulong_t )& adaq4370_4_chip_info },
1327+ { "adaq4380-4" , (kernel_ulong_t )& adaq4380_4_chip_info },
12061328 { }
12071329};
12081330MODULE_DEVICE_TABLE (spi , ad7380_id_table );
0 commit comments