6
6
* Copyright 2021 Analog Devices Inc.
7
7
*/
8
8
#include <linux/unaligned.h>
9
+ #include <linux/bitfield.h>
9
10
#include <linux/device.h>
10
11
#include <linux/iio/triggered_buffer.h>
11
12
#include <linux/iio/trigger_consumer.h>
@@ -210,46 +211,6 @@ static const s32 gains_scaling_table[] = {
210
211
[AD3552R_CH_GAIN_SCALING_0_125 ] = 125
211
212
};
212
213
213
- enum ad3552r_dev_attributes {
214
- /* - Direct register values */
215
- /* From 0-3 */
216
- AD3552R_SDO_DRIVE_STRENGTH ,
217
- /*
218
- * 0 -> Internal Vref, vref_io pin floating (default)
219
- * 1 -> Internal Vref, vref_io driven by internal vref
220
- * 2 or 3 -> External Vref
221
- */
222
- AD3552R_VREF_SELECT ,
223
- /* Read registers in ascending order if set. Else descending */
224
- AD3552R_ADDR_ASCENSION ,
225
- };
226
-
227
- enum ad3552r_ch_attributes {
228
- /* DAC powerdown */
229
- AD3552R_CH_DAC_POWERDOWN ,
230
- /* DAC amplifier powerdown */
231
- AD3552R_CH_AMPLIFIER_POWERDOWN ,
232
- /* Select the output range. Select from enum ad3552r_ch_output_range */
233
- AD3552R_CH_OUTPUT_RANGE_SEL ,
234
- /*
235
- * Over-rider the range selector in order to manually set the output
236
- * voltage range
237
- */
238
- AD3552R_CH_RANGE_OVERRIDE ,
239
- /* Manually set the offset voltage */
240
- AD3552R_CH_GAIN_OFFSET ,
241
- /* Sets the polarity of the offset. */
242
- AD3552R_CH_GAIN_OFFSET_POLARITY ,
243
- /* PDAC gain scaling */
244
- AD3552R_CH_GAIN_SCALING_P ,
245
- /* NDAC gain scaling */
246
- AD3552R_CH_GAIN_SCALING_N ,
247
- /* Rfb value */
248
- AD3552R_CH_RFB ,
249
- /* Channel select. When set allow Input -> DAC and Mask -> DAC */
250
- AD3552R_CH_SELECT ,
251
- };
252
-
253
214
struct ad3552r_ch_data {
254
215
s32 scale_int ;
255
216
s32 scale_dec ;
@@ -285,45 +246,6 @@ struct ad3552r_desc {
285
246
unsigned int num_ch ;
286
247
};
287
248
288
- static const u16 addr_mask_map [][2 ] = {
289
- [AD3552R_ADDR_ASCENSION ] = {
290
- AD3552R_REG_ADDR_INTERFACE_CONFIG_A ,
291
- AD3552R_MASK_ADDR_ASCENSION
292
- },
293
- [AD3552R_SDO_DRIVE_STRENGTH ] = {
294
- AD3552R_REG_ADDR_INTERFACE_CONFIG_D ,
295
- AD3552R_MASK_SDO_DRIVE_STRENGTH
296
- },
297
- [AD3552R_VREF_SELECT ] = {
298
- AD3552R_REG_ADDR_SH_REFERENCE_CONFIG ,
299
- AD3552R_MASK_REFERENCE_VOLTAGE_SEL
300
- },
301
- };
302
-
303
- /* 0 -> reg addr, 1->ch0 mask, 2->ch1 mask */
304
- static const u16 addr_mask_map_ch [][3 ] = {
305
- [AD3552R_CH_DAC_POWERDOWN ] = {
306
- AD3552R_REG_ADDR_POWERDOWN_CONFIG ,
307
- AD3552R_MASK_CH_DAC_POWERDOWN (0 ),
308
- AD3552R_MASK_CH_DAC_POWERDOWN (1 )
309
- },
310
- [AD3552R_CH_AMPLIFIER_POWERDOWN ] = {
311
- AD3552R_REG_ADDR_POWERDOWN_CONFIG ,
312
- AD3552R_MASK_CH_AMPLIFIER_POWERDOWN (0 ),
313
- AD3552R_MASK_CH_AMPLIFIER_POWERDOWN (1 )
314
- },
315
- [AD3552R_CH_OUTPUT_RANGE_SEL ] = {
316
- AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE ,
317
- AD3552R_MASK_CH_OUTPUT_RANGE_SEL (0 ),
318
- AD3552R_MASK_CH_OUTPUT_RANGE_SEL (1 )
319
- },
320
- [AD3552R_CH_SELECT ] = {
321
- AD3552R_REG_ADDR_CH_SELECT_16B ,
322
- AD3552R_MASK_CH (0 ),
323
- AD3552R_MASK_CH (1 )
324
- }
325
- };
326
-
327
249
static u8 _ad3552r_reg_len (u8 addr )
328
250
{
329
251
switch (addr ) {
@@ -399,11 +321,6 @@ static int ad3552r_read_reg(struct ad3552r_desc *dac, u8 addr, u16 *val)
399
321
return 0 ;
400
322
}
401
323
402
- static u16 ad3552r_field_prep (u16 val , u16 mask )
403
- {
404
- return (val << __ffs (mask )) & mask ;
405
- }
406
-
407
324
/* Update field of a register, shift val if needed */
408
325
static int ad3552r_update_reg_field (struct ad3552r_desc * dac , u8 addr , u16 mask ,
409
326
u16 val )
@@ -416,21 +333,11 @@ static int ad3552r_update_reg_field(struct ad3552r_desc *dac, u8 addr, u16 mask,
416
333
return ret ;
417
334
418
335
reg &= ~mask ;
419
- reg |= ad3552r_field_prep ( val , mask ) ;
336
+ reg |= val ;
420
337
421
338
return ad3552r_write_reg (dac , addr , reg );
422
339
}
423
340
424
- static int ad3552r_set_ch_value (struct ad3552r_desc * dac ,
425
- enum ad3552r_ch_attributes attr ,
426
- u8 ch ,
427
- u16 val )
428
- {
429
- /* Update register related to attributes in chip */
430
- return ad3552r_update_reg_field (dac , addr_mask_map_ch [attr ][0 ],
431
- addr_mask_map_ch [attr ][ch + 1 ], val );
432
- }
433
-
434
341
#define AD3552R_CH_DAC (_idx ) ((struct iio_chan_spec) { \
435
342
.type = IIO_VOLTAGE, \
436
343
.output = true, \
@@ -510,8 +417,14 @@ static int ad3552r_write_raw(struct iio_dev *indio_dev,
510
417
val );
511
418
break ;
512
419
case IIO_CHAN_INFO_ENABLE :
513
- err = ad3552r_set_ch_value (dac , AD3552R_CH_DAC_POWERDOWN ,
514
- chan -> channel , !val );
420
+ if (chan -> channel == 0 )
421
+ val = FIELD_PREP (AD3552R_MASK_CH_DAC_POWERDOWN (0 ), !val );
422
+ else
423
+ val = FIELD_PREP (AD3552R_MASK_CH_DAC_POWERDOWN (1 ), !val );
424
+
425
+ err = ad3552r_update_reg_field (dac , AD3552R_REG_ADDR_POWERDOWN_CONFIG ,
426
+ AD3552R_MASK_CH_DAC_POWERDOWN (chan -> channel ),
427
+ val );
515
428
break ;
516
429
default :
517
430
err = - EINVAL ;
@@ -721,9 +634,9 @@ static int ad3552r_reset(struct ad3552r_desc *dac)
721
634
return ret ;
722
635
723
636
return ad3552r_update_reg_field (dac ,
724
- addr_mask_map [ AD3552R_ADDR_ASCENSION ][ 0 ] ,
725
- addr_mask_map [ AD3552R_ADDR_ASCENSION ][ 1 ] ,
726
- val );
637
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_A ,
638
+ AD3552R_MASK_ADDR_ASCENSION ,
639
+ FIELD_PREP ( AD3552R_MASK_ADDR_ASCENSION , val ) );
727
640
}
728
641
729
642
static void ad3552r_get_custom_range (struct ad3552r_desc * dac , s32 i , s32 * v_min ,
@@ -818,20 +731,20 @@ static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac,
818
731
"mandatory custom-output-range-config property missing\n" );
819
732
820
733
dac -> ch_data [ch ].range_override = 1 ;
821
- reg |= ad3552r_field_prep ( 1 , AD3552R_MASK_CH_RANGE_OVERRIDE );
734
+ reg |= FIELD_PREP ( AD3552R_MASK_CH_RANGE_OVERRIDE , 1 );
822
735
823
736
err = fwnode_property_read_u32 (gain_child , "adi,gain-scaling-p" , & val );
824
737
if (err )
825
738
return dev_err_probe (dev , err ,
826
739
"mandatory adi,gain-scaling-p property missing\n" );
827
- reg |= ad3552r_field_prep ( val , AD3552R_MASK_CH_GAIN_SCALING_P );
740
+ reg |= FIELD_PREP ( AD3552R_MASK_CH_GAIN_SCALING_P , val );
828
741
dac -> ch_data [ch ].p = val ;
829
742
830
743
err = fwnode_property_read_u32 (gain_child , "adi,gain-scaling-n" , & val );
831
744
if (err )
832
745
return dev_err_probe (dev , err ,
833
746
"mandatory adi,gain-scaling-n property missing\n" );
834
- reg |= ad3552r_field_prep ( val , AD3552R_MASK_CH_GAIN_SCALING_N );
747
+ reg |= FIELD_PREP ( AD3552R_MASK_CH_GAIN_SCALING_N , val );
835
748
dac -> ch_data [ch ].n = val ;
836
749
837
750
err = fwnode_property_read_u32 (gain_child , "adi,rfb-ohms" , & val );
@@ -847,9 +760,9 @@ static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac,
847
760
dac -> ch_data [ch ].gain_offset = val ;
848
761
849
762
offset = abs ((s32 )val );
850
- reg |= ad3552r_field_prep ( (offset >> 8 ), AD3552R_MASK_CH_OFFSET_BIT_8 );
763
+ reg |= FIELD_PREP ( AD3552R_MASK_CH_OFFSET_BIT_8 , (offset >> 8 ));
851
764
852
- reg |= ad3552r_field_prep ( (s32 )val < 0 , AD3552R_MASK_CH_OFFSET_POLARITY );
765
+ reg |= FIELD_PREP ( AD3552R_MASK_CH_OFFSET_POLARITY , (s32 )val < 0 );
853
766
addr = AD3552R_REG_ADDR_CH_GAIN (ch );
854
767
err = ad3552r_write_reg (dac , addr ,
855
768
offset & AD3552R_MASK_CH_OFFSET_BITS_0_7 );
@@ -892,9 +805,9 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
892
805
}
893
806
894
807
err = ad3552r_update_reg_field (dac ,
895
- addr_mask_map [ AD3552R_VREF_SELECT ][ 0 ] ,
896
- addr_mask_map [ AD3552R_VREF_SELECT ][ 1 ] ,
897
- val );
808
+ AD3552R_REG_ADDR_SH_REFERENCE_CONFIG ,
809
+ AD3552R_MASK_REFERENCE_VOLTAGE_SEL ,
810
+ FIELD_PREP ( AD3552R_MASK_REFERENCE_VOLTAGE_SEL , val ) );
898
811
if (err )
899
812
return err ;
900
813
@@ -906,9 +819,9 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
906
819
}
907
820
908
821
err = ad3552r_update_reg_field (dac ,
909
- addr_mask_map [ AD3552R_SDO_DRIVE_STRENGTH ][ 0 ] ,
910
- addr_mask_map [ AD3552R_SDO_DRIVE_STRENGTH ][ 1 ] ,
911
- val );
822
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D ,
823
+ AD3552R_MASK_SDO_DRIVE_STRENGTH ,
824
+ FIELD_PREP ( AD3552R_MASK_SDO_DRIVE_STRENGTH , val ) );
912
825
if (err )
913
826
return err ;
914
827
}
@@ -944,9 +857,15 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
944
857
"Invalid adi,output-range-microvolt value\n" );
945
858
946
859
val = err ;
947
- err = ad3552r_set_ch_value (dac ,
948
- AD3552R_CH_OUTPUT_RANGE_SEL ,
949
- ch , val );
860
+ if (ch == 0 )
861
+ val = FIELD_PREP (AD3552R_MASK_CH_OUTPUT_RANGE_SEL (0 ), val );
862
+ else
863
+ val = FIELD_PREP (AD3552R_MASK_CH_OUTPUT_RANGE_SEL (1 ), val );
864
+
865
+ err = ad3552r_update_reg_field (dac ,
866
+ AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE ,
867
+ AD3552R_MASK_CH_OUTPUT_RANGE_SEL (ch ),
868
+ val );
950
869
if (err )
951
870
return err ;
952
871
@@ -964,7 +883,14 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
964
883
ad3552r_calc_gain_and_offset (dac , ch );
965
884
dac -> enabled_ch |= BIT (ch );
966
885
967
- err = ad3552r_set_ch_value (dac , AD3552R_CH_SELECT , ch , 1 );
886
+ if (ch == 0 )
887
+ val = FIELD_PREP (AD3552R_MASK_CH (0 ), 1 );
888
+ else
889
+ val = FIELD_PREP (AD3552R_MASK_CH (1 ), 1 );
890
+
891
+ err = ad3552r_update_reg_field (dac ,
892
+ AD3552R_REG_ADDR_CH_SELECT_16B ,
893
+ AD3552R_MASK_CH (ch ), val );
968
894
if (err < 0 )
969
895
return err ;
970
896
@@ -976,8 +902,15 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
976
902
/* Disable unused channels */
977
903
for_each_clear_bit (ch , & dac -> enabled_ch ,
978
904
dac -> model_data -> num_hw_channels ) {
979
- err = ad3552r_set_ch_value (dac , AD3552R_CH_AMPLIFIER_POWERDOWN ,
980
- ch , 1 );
905
+ if (ch == 0 )
906
+ val = FIELD_PREP (AD3552R_MASK_CH_AMPLIFIER_POWERDOWN (0 ), 1 );
907
+ else
908
+ val = FIELD_PREP (AD3552R_MASK_CH_AMPLIFIER_POWERDOWN (1 ), 1 );
909
+
910
+ err = ad3552r_update_reg_field (dac ,
911
+ AD3552R_REG_ADDR_POWERDOWN_CONFIG ,
912
+ AD3552R_MASK_CH_AMPLIFIER_POWERDOWN (ch ),
913
+ val );
981
914
if (err )
982
915
return err ;
983
916
}
0 commit comments