13
13
* ad7381-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7381-4.pdf
14
14
* ad7383/4-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7383-4-ad7384-4.pdf
15
15
* 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
16
18
*/
17
19
18
20
#include <linux/align.h>
22
24
#include <linux/device.h>
23
25
#include <linux/err.h>
24
26
#include <linux/kernel.h>
27
+ #include <linux/math.h>
25
28
#include <linux/module.h>
26
29
#include <linux/regmap.h>
27
30
#include <linux/regulator/consumer.h>
28
31
#include <linux/slab.h>
29
32
#include <linux/spi/spi.h>
33
+ #include <linux/units.h>
34
+ #include <linux/util_macros.h>
30
35
31
36
#include <linux/iio/buffer.h>
32
37
#include <linux/iio/iio.h>
36
41
#define MAX_NUM_CHANNELS 8
37
42
/* 2.5V internal reference voltage */
38
43
#define AD7380_INTERNAL_REF_MV 2500
44
+ /* 3.3V internal reference voltage for ADAQ */
45
+ #define ADAQ4380_INTERNAL_REF_MV 3300
39
46
40
47
/* reading and writing registers is more reliable at lower than max speed */
41
48
#define AD7380_REG_WR_SPEED_HZ 10000000
82
89
* supports only 1 SDO line (standard SPI transaction)
83
90
*/
84
91
#define AD7380_NUM_SDO_LINES 1
92
+ #define AD7380_DEFAULT_GAIN_MILLI 1000
85
93
86
94
struct ad7380_timing_specs {
87
95
const unsigned int t_csh_ns ; /* CS minimum high time */
@@ -92,10 +100,12 @@ struct ad7380_chip_info {
92
100
const struct iio_chan_spec * channels ;
93
101
unsigned int num_channels ;
94
102
unsigned int num_simult_channels ;
103
+ bool has_hardware_gain ;
95
104
bool has_mux ;
96
105
const char * const * supplies ;
97
106
unsigned int num_supplies ;
98
107
bool external_ref_only ;
108
+ bool adaq_internal_ref_only ;
99
109
const char * const * vcm_supplies ;
100
110
unsigned int num_vcm_supplies ;
101
111
const unsigned long * available_scan_masks ;
@@ -187,11 +197,12 @@ static const struct iio_scan_type ad7380_scan_type_16_u[] = {
187
197
},
188
198
};
189
199
190
- #define AD7380_CHANNEL (index , bits , diff , sign ) { \
200
+ #define _AD7380_CHANNEL (index , bits , diff , sign , gain ) { \
191
201
.type = IIO_VOLTAGE, \
192
202
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
203
+ ((gain) ? BIT(IIO_CHAN_INFO_SCALE) : 0) | \
193
204
((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)) | \
195
206
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
196
207
.info_mask_shared_by_type_available = \
197
208
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
@@ -205,6 +216,12 @@ static const struct iio_scan_type ad7380_scan_type_16_u[] = {
205
216
.num_ext_scan_type = ARRAY_SIZE(ad7380_scan_type_##bits##_##sign), \
206
217
}
207
218
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
+
208
225
#define DEFINE_AD7380_2_CHANNEL (name , bits , diff , sign ) \
209
226
static const struct iio_chan_spec name[] = { \
210
227
AD7380_CHANNEL(0, bits, diff, sign), \
@@ -221,6 +238,15 @@ static const struct iio_chan_spec name[] = { \
221
238
IIO_CHAN_SOFT_TIMESTAMP(4), \
222
239
}
223
240
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
+
224
250
#define DEFINE_AD7380_8_CHANNEL (name , bits , diff , sign ) \
225
251
static const struct iio_chan_spec name[] = { \
226
252
AD7380_CHANNEL(0, bits, diff, sign), \
@@ -239,6 +265,7 @@ DEFINE_AD7380_2_CHANNEL(ad7380_channels, 16, 1, s);
239
265
DEFINE_AD7380_2_CHANNEL (ad7381_channels , 14 , 1 , s );
240
266
DEFINE_AD7380_4_CHANNEL (ad7380_4_channels , 16 , 1 , s );
241
267
DEFINE_AD7380_4_CHANNEL (ad7381_4_channels , 14 , 1 , s );
268
+ DEFINE_ADAQ4380_4_CHANNEL (adaq4380_4_channels , 16 , 1 , s );
242
269
/* pseudo differential */
243
270
DEFINE_AD7380_2_CHANNEL (ad7383_channels , 16 , 0 , s );
244
271
DEFINE_AD7380_2_CHANNEL (ad7384_channels , 14 , 0 , s );
@@ -257,6 +284,10 @@ static const char * const ad7380_supplies[] = {
257
284
"vcc" , "vlogic" ,
258
285
};
259
286
287
+ static const char * const adaq4380_supplies [] = {
288
+ "ldo" , "vcc" , "vlogic" , "vs-p" , "vs-n" , "refin" ,
289
+ };
290
+
260
291
static const char * const ad7380_2_channel_vcm_supplies [] = {
261
292
"aina" , "ainb" ,
262
293
};
@@ -347,6 +378,11 @@ static const int ad7380_oversampling_ratios[] = {
347
378
1 , 2 , 4 , 8 , 16 , 32 ,
348
379
};
349
380
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
+
350
386
static const struct ad7380_chip_info ad7380_chip_info = {
351
387
.name = "ad7380" ,
352
388
.channels = ad7380_channels ,
@@ -516,6 +552,32 @@ static const struct ad7380_chip_info ad7388_4_chip_info = {
516
552
.timing_specs = & ad7380_4_timing ,
517
553
};
518
554
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
+
519
581
struct ad7380_state {
520
582
const struct ad7380_chip_info * chip_info ;
521
583
struct spi_device * spi ;
@@ -526,6 +588,7 @@ struct ad7380_state {
526
588
bool seq ;
527
589
unsigned int vref_mv ;
528
590
unsigned int vcm_mv [MAX_NUM_CHANNELS ];
591
+ unsigned int gain_milli [MAX_NUM_CHANNELS ];
529
592
/* xfers, message an buffer for reading sample data */
530
593
struct spi_transfer normal_xfer [2 ];
531
594
struct spi_message normal_msg ;
@@ -876,8 +939,15 @@ static int ad7380_read_raw(struct iio_dev *indio_dev,
876
939
* * (2 × VREF) / 2^N, for differential chips
877
940
* * VREF / 2^N, for pseudo-differential chips
878
941
* 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.
879
945
*/
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 ;
881
951
* val2 = scan_type -> realbits - chan -> differential ;
882
952
883
953
return IIO_VAL_FRACTIONAL_LOG2 ;
@@ -1059,7 +1129,19 @@ static int ad7380_probe(struct spi_device *spi)
1059
1129
"Failed to enable power supplies\n" );
1060
1130
fsleep (T_POWERUP_US );
1061
1131
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 ) {
1063
1145
ret = devm_regulator_get_enable_read_voltage (dev , "refin" );
1064
1146
if (ret < 0 )
1065
1147
return dev_err_probe (dev , ret ,
@@ -1103,6 +1185,42 @@ static int ad7380_probe(struct spi_device *spi)
1103
1185
st -> vcm_mv [i ] = ret / 1000 ;
1104
1186
}
1105
1187
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
+
1106
1224
st -> regmap = devm_regmap_init (dev , NULL , st , & ad7380_regmap_config );
1107
1225
if (IS_ERR (st -> regmap ))
1108
1226
return dev_err_probe (dev , PTR_ERR (st -> regmap ),
@@ -1185,6 +1303,8 @@ static const struct of_device_id ad7380_of_match_table[] = {
1185
1303
{ .compatible = "adi,ad7386-4" , .data = & ad7386_4_chip_info },
1186
1304
{ .compatible = "adi,ad7387-4" , .data = & ad7387_4_chip_info },
1187
1305
{ .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 },
1188
1308
{ }
1189
1309
};
1190
1310
@@ -1203,6 +1323,8 @@ static const struct spi_device_id ad7380_id_table[] = {
1203
1323
{ "ad7386-4" , (kernel_ulong_t )& ad7386_4_chip_info },
1204
1324
{ "ad7387-4" , (kernel_ulong_t )& ad7387_4_chip_info },
1205
1325
{ "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 },
1206
1328
{ }
1207
1329
};
1208
1330
MODULE_DEVICE_TABLE (spi , ad7380_id_table );
0 commit comments