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: ad4030: add support for ad4630-24 and ad4630-16

AD4630-24 and AD4630-16 are 2 channels ADCs. Both channels are
interleaved bit per bit on SDO line.

Signed-off-by: Esteban Blanc <eblanc@baylibre.com>
Link: https://patch.msgid.link/20250214-eblanc-ad4630_v1-v4-4-135dd66cab6a@baylibre.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Esteban Blanc and committed by
Jonathan Cameron
c8ed843c 949abd1c

+178 -10
+178 -10
drivers/iio/adc/ad4030.c
··· 33 33 #define AD4030_REG_PRODUCT_ID_H 0x05 34 34 #define AD4030_REG_CHIP_GRADE 0x06 35 35 #define AD4030_REG_CHIP_GRADE_AD4030_24_GRADE 0x10 36 + #define AD4030_REG_CHIP_GRADE_AD4630_16_GRADE 0x03 37 + #define AD4030_REG_CHIP_GRADE_AD4630_24_GRADE 0x00 36 38 #define AD4030_REG_CHIP_GRADE_MASK_CHIP_GRADE GENMASK(7, 3) 37 39 #define AD4030_REG_SCRATCH_PAD 0x0A 38 40 #define AD4030_REG_SPI_REVISION 0x0B ··· 85 83 #define AD4030_MAX_HARDWARE_CHANNEL_NB 2 86 84 #define AD4030_MAX_IIO_CHANNEL_NB 5 87 85 #define AD4030_SINGLE_COMMON_BYTE_CHANNELS_MASK 0b10 86 + #define AD4030_DUAL_COMMON_BYTE_CHANNELS_MASK 0b1100 88 87 #define AD4030_GAIN_MIDLE_POINT 0x8000 89 88 /* 90 89 * This accounts for 1 sample per channel plus one s64 for the timestamp, ··· 113 110 AD4030_OUT_DATA_MD_24_DIFF_8_COM, 114 111 AD4030_OUT_DATA_MD_30_AVERAGED_DIFF, 115 112 AD4030_OUT_DATA_MD_32_PATTERN, 113 + }; 114 + 115 + enum { 116 + AD4030_LANE_MD_1_PER_CH, 117 + AD4030_LANE_MD_2_PER_CH, 118 + AD4030_LANE_MD_4_PER_CH, 119 + AD4030_LANE_MD_INTERLEAVED, 116 120 }; 117 121 118 122 enum { ··· 160 150 struct { 161 151 s32 diff; 162 152 u8 common; 163 - }; 153 + } single; 154 + struct { 155 + s32 diff[2]; 156 + u8 common[2]; 157 + } dual; 164 158 } rx_data; 165 159 }; 166 160 ··· 528 514 static bool ad4030_is_common_byte_asked(struct ad4030_state *st, 529 515 unsigned int mask) 530 516 { 531 - return mask & AD4030_SINGLE_COMMON_BYTE_CHANNELS_MASK; 517 + return mask & (st->chip->num_voltage_inputs == 1 ? 518 + AD4030_SINGLE_COMMON_BYTE_CHANNELS_MASK : 519 + AD4030_DUAL_COMMON_BYTE_CHANNELS_MASK); 532 520 } 533 521 534 522 static int ad4030_set_mode(struct iio_dev *indio_dev, unsigned long mask) 535 523 { 536 524 struct ad4030_state *st = iio_priv(indio_dev); 537 525 538 - if (st->avg_log2 > 0) 526 + if (st->avg_log2 > 0) { 539 527 st->mode = AD4030_OUT_DATA_MD_30_AVERAGED_DIFF; 540 - else if (ad4030_is_common_byte_asked(st, mask)) 541 - st->mode = AD4030_OUT_DATA_MD_24_DIFF_8_COM; 542 - else 528 + } else if (ad4030_is_common_byte_asked(st, mask)) { 529 + switch (st->chip->precision_bits) { 530 + case 16: 531 + st->mode = AD4030_OUT_DATA_MD_16_DIFF_8_COM; 532 + break; 533 + 534 + case 24: 535 + st->mode = AD4030_OUT_DATA_MD_24_DIFF_8_COM; 536 + break; 537 + 538 + default: 539 + return -EINVAL; 540 + } 541 + } else { 543 542 st->mode = AD4030_OUT_DATA_MD_DIFF; 543 + } 544 544 545 545 st->current_scan_type = iio_get_current_scan_type(indio_dev, 546 546 st->chip->channels); ··· 566 538 st->mode); 567 539 } 568 540 541 + /* 542 + * Descramble 2 32bits numbers out of a 64bits. The bits are interleaved: 543 + * 1 bit for first number, 1 bit for the second, and so on... 544 + */ 545 + static void ad4030_extract_interleaved(u8 *src, u32 *ch0, u32 *ch1) 546 + { 547 + u8 h0, h1, l0, l1; 548 + u32 out0, out1; 549 + u8 *out0_raw = (u8 *)&out0; 550 + u8 *out1_raw = (u8 *)&out1; 551 + 552 + for (int i = 0; i < 4; i++) { 553 + h0 = src[i * 2]; 554 + l1 = src[i * 2 + 1]; 555 + h1 = h0 << 1; 556 + l0 = l1 >> 1; 557 + 558 + h0 &= 0xAA; 559 + l0 &= 0x55; 560 + h1 &= 0xAA; 561 + l1 &= 0x55; 562 + 563 + h0 = (h0 | h0 << 001) & 0xCC; 564 + h1 = (h1 | h1 << 001) & 0xCC; 565 + l0 = (l0 | l0 >> 001) & 0x33; 566 + l1 = (l1 | l1 >> 001) & 0x33; 567 + h0 = (h0 | h0 << 002) & 0xF0; 568 + h1 = (h1 | h1 << 002) & 0xF0; 569 + l0 = (l0 | l0 >> 002) & 0x0F; 570 + l1 = (l1 | l1 >> 002) & 0x0F; 571 + 572 + out0_raw[i] = h0 | l0; 573 + out1_raw[i] = h1 | l1; 574 + } 575 + 576 + *ch0 = out0; 577 + *ch1 = out1; 578 + } 579 + 569 580 static int ad4030_conversion(struct iio_dev *indio_dev) 570 581 { 571 582 struct ad4030_state *st = iio_priv(indio_dev); 572 583 unsigned char diff_realbytes = 573 584 BITS_TO_BYTES(st->current_scan_type->realbits); 585 + unsigned char diff_storagebytes = 586 + BITS_TO_BYTES(st->current_scan_type->storagebits); 574 587 unsigned int bytes_to_read; 575 588 unsigned long cnv_nb = BIT(st->avg_log2); 576 589 unsigned int i; ··· 636 567 if (ret) 637 568 return ret; 638 569 639 - if (st->mode != AD4030_OUT_DATA_MD_24_DIFF_8_COM) 570 + if (st->chip->num_voltage_inputs == 2) 571 + ad4030_extract_interleaved(st->rx_data.raw, 572 + &st->rx_data.dual.diff[0], 573 + &st->rx_data.dual.diff[1]); 574 + 575 + if (st->mode != AD4030_OUT_DATA_MD_16_DIFF_8_COM && 576 + st->mode != AD4030_OUT_DATA_MD_24_DIFF_8_COM) 640 577 return 0; 641 578 642 - st->rx_data.common = st->rx_data.raw[diff_realbytes]; 579 + if (st->chip->num_voltage_inputs == 1) { 580 + st->rx_data.single.common = st->rx_data.raw[diff_realbytes]; 581 + return 0; 582 + } 583 + 584 + for (i = 0; i < st->chip->num_voltage_inputs; i++) 585 + st->rx_data.dual.common[i] = 586 + st->rx_data.raw[diff_storagebytes * i + diff_realbytes]; 643 587 644 588 return 0; 645 589 } ··· 667 585 if (ret) 668 586 return ret; 669 587 588 + st->current_scan_type = iio_get_current_scan_type(indio_dev, 589 + st->chip->channels); 590 + if (IS_ERR(st->current_scan_type)) 591 + return PTR_ERR(st->current_scan_type); 592 + 670 593 ret = ad4030_conversion(indio_dev); 671 594 if (ret) 672 595 return ret; 673 596 674 597 if (chan->differential) 675 - *val = st->rx_data.diff; 598 + if (st->chip->num_voltage_inputs == 1) 599 + *val = st->rx_data.single.diff; 600 + else 601 + *val = st->rx_data.dual.diff[chan->address]; 676 602 else 677 - *val = st->rx_data.common; 603 + if (st->chip->num_voltage_inputs == 1) 604 + *val = st->rx_data.single.common; 605 + else 606 + *val = st->rx_data.dual.common[chan->address]; 678 607 679 608 return IIO_VAL_INT; 680 609 } ··· 967 874 968 875 static int ad4030_config(struct ad4030_state *st) 969 876 { 877 + int ret; 878 + u8 reg_modes; 879 + 970 880 st->offset_avail[0] = (int)BIT(st->chip->precision_bits - 1) * -1; 971 881 st->offset_avail[1] = 1; 972 882 st->offset_avail[2] = BIT(st->chip->precision_bits - 1) - 1; 883 + 884 + if (st->chip->num_voltage_inputs > 1) 885 + reg_modes = FIELD_PREP(AD4030_REG_MODES_MASK_LANE_MODE, 886 + AD4030_LANE_MD_INTERLEAVED); 887 + else 888 + reg_modes = FIELD_PREP(AD4030_REG_MODES_MASK_LANE_MODE, 889 + AD4030_LANE_MD_1_PER_CH); 890 + 891 + ret = regmap_write(st->regmap, AD4030_REG_MODES, reg_modes); 892 + if (ret) 893 + return ret; 973 894 974 895 if (st->vio_uv < AD4030_VIO_THRESHOLD_UV) 975 896 return regmap_write(st->regmap, AD4030_REG_IO, ··· 1073 966 0, 1074 967 }; 1075 968 969 + static const unsigned long ad4630_channel_masks[] = { 970 + /* Differential only */ 971 + BIT(1) | BIT(0), 972 + /* Differential with common byte */ 973 + GENMASK(3, 0), 974 + 0, 975 + }; 976 + 1076 977 static const struct iio_scan_type ad4030_24_scan_types[] = { 1077 978 [AD4030_SCAN_TYPE_NORMAL] = { 1078 979 .sign = 's', ··· 1098 983 }, 1099 984 }; 1100 985 986 + static const struct iio_scan_type ad4030_16_scan_types[] = { 987 + [AD4030_SCAN_TYPE_NORMAL] = { 988 + .sign = 's', 989 + .storagebits = 32, 990 + .realbits = 16, 991 + .shift = 16, 992 + .endianness = IIO_BE, 993 + }, 994 + [AD4030_SCAN_TYPE_AVG] = { 995 + .sign = 's', 996 + .storagebits = 32, 997 + .realbits = 30, 998 + .shift = 2, 999 + .endianness = IIO_BE, 1000 + } 1001 + }; 1002 + 1101 1003 static const struct ad4030_chip_info ad4030_24_chip_info = { 1102 1004 .name = "ad4030-24", 1103 1005 .available_masks = ad4030_channel_masks, ··· 1129 997 .tcyc_ns = AD4030_TCYC_ADJUSTED_NS, 1130 998 }; 1131 999 1000 + static const struct ad4030_chip_info ad4630_16_chip_info = { 1001 + .name = "ad4630-16", 1002 + .available_masks = ad4630_channel_masks, 1003 + .channels = { 1004 + AD4030_CHAN_DIFF(0, ad4030_16_scan_types), 1005 + AD4030_CHAN_DIFF(1, ad4030_16_scan_types), 1006 + AD4030_CHAN_CMO(2, 0), 1007 + AD4030_CHAN_CMO(3, 1), 1008 + IIO_CHAN_SOFT_TIMESTAMP(4), 1009 + }, 1010 + .grade = AD4030_REG_CHIP_GRADE_AD4630_16_GRADE, 1011 + .precision_bits = 16, 1012 + .num_voltage_inputs = 2, 1013 + .tcyc_ns = AD4030_TCYC_ADJUSTED_NS, 1014 + }; 1015 + 1016 + static const struct ad4030_chip_info ad4630_24_chip_info = { 1017 + .name = "ad4630-24", 1018 + .available_masks = ad4630_channel_masks, 1019 + .channels = { 1020 + AD4030_CHAN_DIFF(0, ad4030_24_scan_types), 1021 + AD4030_CHAN_DIFF(1, ad4030_24_scan_types), 1022 + AD4030_CHAN_CMO(2, 0), 1023 + AD4030_CHAN_CMO(3, 1), 1024 + IIO_CHAN_SOFT_TIMESTAMP(4), 1025 + }, 1026 + .grade = AD4030_REG_CHIP_GRADE_AD4630_24_GRADE, 1027 + .precision_bits = 24, 1028 + .num_voltage_inputs = 2, 1029 + .tcyc_ns = AD4030_TCYC_ADJUSTED_NS, 1030 + }; 1031 + 1132 1032 static const struct spi_device_id ad4030_id_table[] = { 1133 1033 { "ad4030-24", (kernel_ulong_t)&ad4030_24_chip_info }, 1034 + { "ad4630-16", (kernel_ulong_t)&ad4630_16_chip_info }, 1035 + { "ad4630-24", (kernel_ulong_t)&ad4630_24_chip_info }, 1134 1036 { } 1135 1037 }; 1136 1038 MODULE_DEVICE_TABLE(spi, ad4030_id_table); 1137 1039 1138 1040 static const struct of_device_id ad4030_of_match[] = { 1139 1041 { .compatible = "adi,ad4030-24", .data = &ad4030_24_chip_info }, 1042 + { .compatible = "adi,ad4630-16", .data = &ad4630_16_chip_info }, 1043 + { .compatible = "adi,ad4630-24", .data = &ad4630_24_chip_info }, 1140 1044 { } 1141 1045 }; 1142 1046 MODULE_DEVICE_TABLE(of, ad4030_of_match);