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: adis16480: support burst read function

Some supported devices support burst read function. This provides a method
for reading a batch of data (status, temperature, gyroscopes,
accelerometers, time stamp/data counter, and CRC code), which does not
require a stall time between each 16-bit segment and only requires one
command on the DIN line to initiate. Devices supporting this mode
are:

* adis16495-1
* adis16495-2
* adis16495-3
* adis16497-1
* adis16497-2
* adis16497-3

Reviewed-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Nuno Sa <nuno.sa@analog.com>
Link: https://lore.kernel.org/r/20210422103735.136367-1-nuno.sa@analog.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Nuno Sa and committed by
Jonathan Cameron
941f1308 e50f8e04

+147 -13
+147 -13
drivers/iio/imu/adis16480.c
··· 19 19 #include <linux/sysfs.h> 20 20 #include <linux/module.h> 21 21 #include <linux/lcm.h> 22 + #include <linux/swab.h> 23 + #include <linux/crc32.h> 22 24 23 25 #include <linux/iio/iio.h> 24 26 #include <linux/iio/sysfs.h> 25 27 #include <linux/iio/buffer.h> 26 28 #include <linux/iio/imu/adis.h> 29 + #include <linux/iio/triggered_buffer.h> 30 + #include <linux/iio/trigger_consumer.h> 27 31 28 32 #include <linux/debugfs.h> 29 33 ··· 107 103 * Available only for ADIS1649x devices 108 104 */ 109 105 #define ADIS16495_REG_SYNC_SCALE ADIS16480_REG(0x03, 0x10) 106 + #define ADIS16495_REG_BURST_CMD ADIS16480_REG(0x00, 0x7C) 107 + #define ADIS16495_BURST_ID 0xA5A5 108 + /* total number of segments in burst */ 109 + #define ADIS16495_BURST_MAX_DATA 20 110 + /* spi max speed in burst mode */ 111 + #define ADIS16495_BURST_MAX_SPEED 6000000 110 112 111 113 #define ADIS16480_REG_SERIAL_NUM ADIS16480_REG(0x04, 0x20) 112 114 ··· 173 163 struct clk *ext_clk; 174 164 enum adis16480_clock_mode clk_mode; 175 165 unsigned int clk_freq; 166 + /* Alignment needed for the timestamp */ 167 + __be16 data[ADIS16495_BURST_MAX_DATA] __aligned(8); 176 168 }; 177 169 178 170 static const char * const adis16480_int_pin_names[4] = { ··· 875 863 876 864 static int adis16480_enable_irq(struct adis *adis, bool enable); 877 865 878 - #define ADIS16480_DATA(_prod_id, _timeouts) \ 866 + #define ADIS16480_DATA(_prod_id, _timeouts, _burst_len) \ 879 867 { \ 880 868 .diag_stat_reg = ADIS16480_REG_DIAG_STS, \ 881 869 .glob_cmd_reg = ADIS16480_REG_GLOB_CMD, \ ··· 899 887 BIT(ADIS16480_DIAG_STAT_BARO_FAIL), \ 900 888 .enable_irq = adis16480_enable_irq, \ 901 889 .timeouts = (_timeouts), \ 890 + .burst_reg_cmd = ADIS16495_REG_BURST_CMD, \ 891 + .burst_len = (_burst_len), \ 892 + .burst_max_speed_hz = ADIS16495_BURST_MAX_SPEED \ 902 893 } 903 894 904 895 static const struct adis_timeout adis16485_timeouts = { ··· 946 931 .int_clk = 2460000, 947 932 .max_dec_rate = 2048, 948 933 .filter_freqs = adis16480_def_filter_freqs, 949 - .adis_data = ADIS16480_DATA(16375, &adis16485_timeouts), 934 + .adis_data = ADIS16480_DATA(16375, &adis16485_timeouts, 0), 950 935 }, 951 936 [ADIS16480] = { 952 937 .channels = adis16480_channels, ··· 959 944 .int_clk = 2460000, 960 945 .max_dec_rate = 2048, 961 946 .filter_freqs = adis16480_def_filter_freqs, 962 - .adis_data = ADIS16480_DATA(16480, &adis16480_timeouts), 947 + .adis_data = ADIS16480_DATA(16480, &adis16480_timeouts, 0), 963 948 }, 964 949 [ADIS16485] = { 965 950 .channels = adis16485_channels, ··· 972 957 .int_clk = 2460000, 973 958 .max_dec_rate = 2048, 974 959 .filter_freqs = adis16480_def_filter_freqs, 975 - .adis_data = ADIS16480_DATA(16485, &adis16485_timeouts), 960 + .adis_data = ADIS16480_DATA(16485, &adis16485_timeouts, 0), 976 961 }, 977 962 [ADIS16488] = { 978 963 .channels = adis16480_channels, ··· 985 970 .int_clk = 2460000, 986 971 .max_dec_rate = 2048, 987 972 .filter_freqs = adis16480_def_filter_freqs, 988 - .adis_data = ADIS16480_DATA(16488, &adis16485_timeouts), 973 + .adis_data = ADIS16480_DATA(16488, &adis16485_timeouts, 0), 989 974 }, 990 975 [ADIS16490] = { 991 976 .channels = adis16485_channels, ··· 999 984 .max_dec_rate = 4250, 1000 985 .filter_freqs = adis16495_def_filter_freqs, 1001 986 .has_pps_clk_mode = true, 1002 - .adis_data = ADIS16480_DATA(16490, &adis16495_timeouts), 987 + .adis_data = ADIS16480_DATA(16490, &adis16495_timeouts, 0), 1003 988 }, 1004 989 [ADIS16495_1] = { 1005 990 .channels = adis16485_channels, ··· 1013 998 .max_dec_rate = 4250, 1014 999 .filter_freqs = adis16495_def_filter_freqs, 1015 1000 .has_pps_clk_mode = true, 1016 - .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts), 1001 + /* 20 elements of 16bits */ 1002 + .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts, 1003 + ADIS16495_BURST_MAX_DATA * 2), 1017 1004 }, 1018 1005 [ADIS16495_2] = { 1019 1006 .channels = adis16485_channels, ··· 1029 1012 .max_dec_rate = 4250, 1030 1013 .filter_freqs = adis16495_def_filter_freqs, 1031 1014 .has_pps_clk_mode = true, 1032 - .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts), 1015 + /* 20 elements of 16bits */ 1016 + .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts, 1017 + ADIS16495_BURST_MAX_DATA * 2), 1033 1018 }, 1034 1019 [ADIS16495_3] = { 1035 1020 .channels = adis16485_channels, ··· 1045 1026 .max_dec_rate = 4250, 1046 1027 .filter_freqs = adis16495_def_filter_freqs, 1047 1028 .has_pps_clk_mode = true, 1048 - .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts), 1029 + /* 20 elements of 16bits */ 1030 + .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts, 1031 + ADIS16495_BURST_MAX_DATA * 2), 1049 1032 }, 1050 1033 [ADIS16497_1] = { 1051 1034 .channels = adis16485_channels, ··· 1061 1040 .max_dec_rate = 4250, 1062 1041 .filter_freqs = adis16495_def_filter_freqs, 1063 1042 .has_pps_clk_mode = true, 1064 - .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts), 1043 + /* 20 elements of 16bits */ 1044 + .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts, 1045 + ADIS16495_BURST_MAX_DATA * 2), 1065 1046 }, 1066 1047 [ADIS16497_2] = { 1067 1048 .channels = adis16485_channels, ··· 1077 1054 .max_dec_rate = 4250, 1078 1055 .filter_freqs = adis16495_def_filter_freqs, 1079 1056 .has_pps_clk_mode = true, 1080 - .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts), 1057 + /* 20 elements of 16bits */ 1058 + .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts, 1059 + ADIS16495_BURST_MAX_DATA * 2), 1081 1060 }, 1082 1061 [ADIS16497_3] = { 1083 1062 .channels = adis16485_channels, ··· 1093 1068 .max_dec_rate = 4250, 1094 1069 .filter_freqs = adis16495_def_filter_freqs, 1095 1070 .has_pps_clk_mode = true, 1096 - .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts), 1071 + /* 20 elements of 16bits */ 1072 + .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts, 1073 + ADIS16495_BURST_MAX_DATA * 2), 1097 1074 }, 1098 1075 }; 1076 + 1077 + static bool adis16480_validate_crc(const u16 *buf, const u8 n_elem, const u32 crc) 1078 + { 1079 + u32 crc_calc; 1080 + u16 crc_buf[15]; 1081 + int j; 1082 + 1083 + for (j = 0; j < n_elem; j++) 1084 + crc_buf[j] = swab16(buf[j]); 1085 + 1086 + crc_calc = crc32(~0, crc_buf, n_elem * 2); 1087 + crc_calc ^= ~0; 1088 + 1089 + return (crc == crc_calc); 1090 + } 1091 + 1092 + static irqreturn_t adis16480_trigger_handler(int irq, void *p) 1093 + { 1094 + struct iio_poll_func *pf = p; 1095 + struct iio_dev *indio_dev = pf->indio_dev; 1096 + struct adis16480 *st = iio_priv(indio_dev); 1097 + struct adis *adis = &st->adis; 1098 + int ret, bit, offset, i = 0; 1099 + __be16 *buffer; 1100 + u32 crc; 1101 + bool valid; 1102 + 1103 + adis_dev_lock(adis); 1104 + if (adis->current_page != 0) { 1105 + adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); 1106 + adis->tx[1] = 0; 1107 + ret = spi_write(adis->spi, adis->tx, 2); 1108 + if (ret) { 1109 + dev_err(&adis->spi->dev, "Failed to change device page: %d\n", ret); 1110 + adis_dev_unlock(adis); 1111 + goto irq_done; 1112 + } 1113 + 1114 + adis->current_page = 0; 1115 + } 1116 + 1117 + ret = spi_sync(adis->spi, &adis->msg); 1118 + if (ret) { 1119 + dev_err(&adis->spi->dev, "Failed to read data: %d\n", ret); 1120 + adis_dev_unlock(adis); 1121 + goto irq_done; 1122 + } 1123 + 1124 + adis_dev_unlock(adis); 1125 + 1126 + /* 1127 + * After making the burst request, the response can have one or two 1128 + * 16-bit responses containing the BURST_ID depending on the sclk. If 1129 + * clk > 3.6MHz, then we will have two BURST_ID in a row. If clk < 3MHZ, 1130 + * we have only one. To manage that variation, we use the transition from the 1131 + * BURST_ID to the SYS_E_FLAG register, which will not be equal to 0xA5A5. If 1132 + * we not find this variation in the first 4 segments, then the data should 1133 + * not be valid. 1134 + */ 1135 + buffer = adis->buffer; 1136 + for (offset = 0; offset < 4; offset++) { 1137 + u16 curr = be16_to_cpu(buffer[offset]); 1138 + u16 next = be16_to_cpu(buffer[offset + 1]); 1139 + 1140 + if (curr == ADIS16495_BURST_ID && next != ADIS16495_BURST_ID) { 1141 + offset++; 1142 + break; 1143 + } 1144 + } 1145 + 1146 + if (offset == 4) { 1147 + dev_err(&adis->spi->dev, "Invalid burst data\n"); 1148 + goto irq_done; 1149 + } 1150 + 1151 + crc = be16_to_cpu(buffer[offset + 16]) << 16 | be16_to_cpu(buffer[offset + 15]); 1152 + valid = adis16480_validate_crc((u16 *)&buffer[offset], 15, crc); 1153 + if (!valid) { 1154 + dev_err(&adis->spi->dev, "Invalid crc\n"); 1155 + goto irq_done; 1156 + } 1157 + 1158 + for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength) { 1159 + /* 1160 + * When burst mode is used, temperature is the first data 1161 + * channel in the sequence, but the temperature scan index 1162 + * is 10. 1163 + */ 1164 + switch (bit) { 1165 + case ADIS16480_SCAN_TEMP: 1166 + st->data[i++] = buffer[offset + 1]; 1167 + break; 1168 + case ADIS16480_SCAN_GYRO_X ... ADIS16480_SCAN_ACCEL_Z: 1169 + /* The lower register data is sequenced first */ 1170 + st->data[i++] = buffer[2 * bit + offset + 3]; 1171 + st->data[i++] = buffer[2 * bit + offset + 2]; 1172 + break; 1173 + } 1174 + } 1175 + 1176 + iio_push_to_buffers_with_timestamp(indio_dev, st->data, pf->timestamp); 1177 + irq_done: 1178 + iio_trigger_notify_done(indio_dev->trig); 1179 + 1180 + return IRQ_HANDLED; 1181 + } 1099 1182 1100 1183 static const struct iio_info adis16480_info = { 1101 1184 .read_raw = &adis16480_read_raw, ··· 1474 1341 st->clk_freq = st->chip_info->int_clk; 1475 1342 } 1476 1343 1477 - ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL); 1344 + ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, 1345 + adis16480_trigger_handler); 1478 1346 if (ret) 1479 1347 return ret; 1480 1348