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: add support for adis16545/7 families

The ADIS16545 and ADIS16547 are a complete inertial system that
includes a triaxis gyroscope and a triaxis accelerometer.
The serial peripheral interface (SPI) and register structure provide a
simple interface for data collection and configuration control.

These devices are similar to the ones already supported in the driver,
with changes in the scales, timings and the max spi speed in burst
mode.
Also, they support delta angle and delta velocity readings in burst
mode, for which support was added in the trigger handler.

Co-developed-by: Nuno Sá <nuno.sa@analog.com>
Signed-off-by: Ramona Gradinariu <ramona.gradinariu@analog.com>
Reviewed-by: Nuno Sa <nuno.sa@analog.com>
Link: https://lore.kernel.org/r/20240528142409.239187-5-ramona.gradinariu@analog.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Ramona Gradinariu and committed by
Jonathan Cameron
85b2aeaa 1c083963

+229 -8
+229 -8
drivers/iio/imu/adis16480.c
··· 104 104 */ 105 105 #define ADIS16495_REG_SYNC_SCALE ADIS16480_REG(0x03, 0x10) 106 106 #define ADIS16495_REG_BURST_CMD ADIS16480_REG(0x00, 0x7C) 107 - #define ADIS16495_BURST_ID 0xA5A5 107 + #define ADIS16495_GYRO_ACCEL_BURST_ID 0xA5A5 108 + #define ADIS16545_DELTA_ANG_VEL_BURST_ID 0xC3C3 108 109 /* total number of segments in burst */ 109 110 #define ADIS16495_BURST_MAX_DATA 20 110 111 ··· 133 132 #define ADIS16480_SYNC_MODE_MSK BIT(8) 134 133 #define ADIS16480_SYNC_MODE(x) FIELD_PREP(ADIS16480_SYNC_MODE_MSK, x) 135 134 135 + #define ADIS16545_BURST_DATA_SEL_0_CHN_MASK GENMASK(5, 0) 136 + #define ADIS16545_BURST_DATA_SEL_1_CHN_MASK GENMASK(16, 11) 137 + #define ADIS16545_BURST_DATA_SEL_MASK BIT(8) 138 + 136 139 struct adis16480_chip_info { 137 140 unsigned int num_channels; 138 141 const struct iio_chan_spec *channels; ··· 152 147 const unsigned int *filter_freqs; 153 148 bool has_pps_clk_mode; 154 149 bool has_sleep_cnt; 150 + bool has_burst_delta_data; 155 151 const struct adis_data adis_data; 156 152 }; 157 153 ··· 176 170 struct clk *ext_clk; 177 171 enum adis16480_clock_mode clk_mode; 178 172 unsigned int clk_freq; 173 + u16 burst_id; 179 174 /* Alignment needed for the timestamp */ 180 175 __be16 data[ADIS16495_BURST_MAX_DATA] __aligned(8); 181 176 }; ··· 883 876 ADIS16480_DELTVEL_CHANNEL_NO_SCAN(Z), 884 877 }; 885 878 879 + static const struct iio_chan_spec adis16545_channels[] = { 880 + ADIS16480_GYRO_CHANNEL(X), 881 + ADIS16480_GYRO_CHANNEL(Y), 882 + ADIS16480_GYRO_CHANNEL(Z), 883 + ADIS16480_ACCEL_CHANNEL(X), 884 + ADIS16480_ACCEL_CHANNEL(Y), 885 + ADIS16480_ACCEL_CHANNEL(Z), 886 + ADIS16480_TEMP_CHANNEL(), 887 + ADIS16480_DELTANG_CHANNEL(X), 888 + ADIS16480_DELTANG_CHANNEL(Y), 889 + ADIS16480_DELTANG_CHANNEL(Z), 890 + ADIS16480_DELTVEL_CHANNEL(X), 891 + ADIS16480_DELTVEL_CHANNEL(Y), 892 + ADIS16480_DELTVEL_CHANNEL(Z), 893 + IIO_CHAN_SOFT_TIMESTAMP(17), 894 + }; 895 + 886 896 enum adis16480_variant { 887 897 ADIS16375, 888 898 ADIS16480, ··· 912 888 ADIS16497_1, 913 889 ADIS16497_2, 914 890 ADIS16497_3, 891 + ADIS16545_1, 892 + ADIS16545_2, 893 + ADIS16545_3, 894 + ADIS16547_1, 895 + ADIS16547_2, 896 + ADIS16547_3 915 897 }; 916 898 917 899 #define ADIS16480_DIAG_STAT_XGYRO_FAIL 0 ··· 997 967 .reset_ms = 250, 998 968 .sw_reset_ms = 210, 999 969 .self_test_ms = 20, 970 + }; 971 + 972 + static const struct adis_timeout adis16545_timeouts = { 973 + .reset_ms = 315, 974 + .sw_reset_ms = 270, 975 + .self_test_ms = 35, 1000 976 }; 1001 977 1002 978 static const struct adis16480_chip_info adis16480_chip_info[] = { ··· 1206 1170 ADIS16495_BURST_MAX_DATA * 2, 1207 1171 6000000), 1208 1172 }, 1173 + [ADIS16545_1] = { 1174 + .channels = adis16545_channels, 1175 + .num_channels = ARRAY_SIZE(adis16545_channels), 1176 + .gyro_max_val = 20000 << 16, 1177 + .gyro_max_scale = IIO_DEGREE_TO_RAD(125), 1178 + .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), 1179 + .accel_max_scale = 8, 1180 + .temp_scale = 7000, /* 7 milli degree Celsius */ 1181 + .deltang_max_val = IIO_DEGREE_TO_RAD(360), 1182 + .deltvel_max_val = 100, 1183 + .int_clk = 4250000, 1184 + .max_dec_rate = 4250, 1185 + .filter_freqs = adis16495_def_filter_freqs, 1186 + .has_pps_clk_mode = true, 1187 + .has_burst_delta_data = true, 1188 + /* 20 elements of 16bits */ 1189 + .adis_data = ADIS16480_DATA(16545, &adis16545_timeouts, 1190 + ADIS16495_BURST_MAX_DATA * 2, 1191 + 6500000), 1192 + }, 1193 + [ADIS16545_2] = { 1194 + .channels = adis16545_channels, 1195 + .num_channels = ARRAY_SIZE(adis16545_channels), 1196 + .gyro_max_val = 18000 << 16, 1197 + .gyro_max_scale = IIO_DEGREE_TO_RAD(450), 1198 + .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), 1199 + .accel_max_scale = 8, 1200 + .temp_scale = 7000, /* 7 milli degree Celsius */ 1201 + .deltang_max_val = IIO_DEGREE_TO_RAD(720), 1202 + .deltvel_max_val = 100, 1203 + .int_clk = 4250000, 1204 + .max_dec_rate = 4250, 1205 + .filter_freqs = adis16495_def_filter_freqs, 1206 + .has_pps_clk_mode = true, 1207 + .has_burst_delta_data = true, 1208 + /* 20 elements of 16bits */ 1209 + .adis_data = ADIS16480_DATA(16545, &adis16545_timeouts, 1210 + ADIS16495_BURST_MAX_DATA * 2, 1211 + 6500000), 1212 + }, 1213 + [ADIS16545_3] = { 1214 + .channels = adis16545_channels, 1215 + .num_channels = ARRAY_SIZE(adis16545_channels), 1216 + .gyro_max_val = 20000 << 16, 1217 + .gyro_max_scale = IIO_DEGREE_TO_RAD(2000), 1218 + .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), 1219 + .accel_max_scale = 8, 1220 + .temp_scale = 7000, /* 7 milli degree Celsius */ 1221 + .deltang_max_val = IIO_DEGREE_TO_RAD(2160), 1222 + .deltvel_max_val = 100, 1223 + .int_clk = 4250000, 1224 + .max_dec_rate = 4250, 1225 + .filter_freqs = adis16495_def_filter_freqs, 1226 + .has_pps_clk_mode = true, 1227 + .has_burst_delta_data = true, 1228 + /* 20 elements of 16bits */ 1229 + .adis_data = ADIS16480_DATA(16545, &adis16545_timeouts, 1230 + ADIS16495_BURST_MAX_DATA * 2, 1231 + 6500000), 1232 + }, 1233 + [ADIS16547_1] = { 1234 + .channels = adis16545_channels, 1235 + .num_channels = ARRAY_SIZE(adis16545_channels), 1236 + .gyro_max_val = 20000 << 16, 1237 + .gyro_max_scale = IIO_DEGREE_TO_RAD(125), 1238 + .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), 1239 + .accel_max_scale = 40, 1240 + .temp_scale = 7000, /* 7 milli degree Celsius */ 1241 + .deltang_max_val = IIO_DEGREE_TO_RAD(360), 1242 + .deltvel_max_val = 400, 1243 + .int_clk = 4250000, 1244 + .max_dec_rate = 4250, 1245 + .filter_freqs = adis16495_def_filter_freqs, 1246 + .has_pps_clk_mode = true, 1247 + .has_burst_delta_data = true, 1248 + /* 20 elements of 16bits */ 1249 + .adis_data = ADIS16480_DATA(16547, &adis16545_timeouts, 1250 + ADIS16495_BURST_MAX_DATA * 2, 1251 + 6500000), 1252 + }, 1253 + [ADIS16547_2] = { 1254 + .channels = adis16545_channels, 1255 + .num_channels = ARRAY_SIZE(adis16545_channels), 1256 + .gyro_max_val = 18000 << 16, 1257 + .gyro_max_scale = IIO_DEGREE_TO_RAD(450), 1258 + .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), 1259 + .accel_max_scale = 40, 1260 + .temp_scale = 7000, /* 7 milli degree Celsius */ 1261 + .deltang_max_val = IIO_DEGREE_TO_RAD(720), 1262 + .deltvel_max_val = 400, 1263 + .int_clk = 4250000, 1264 + .max_dec_rate = 4250, 1265 + .filter_freqs = adis16495_def_filter_freqs, 1266 + .has_pps_clk_mode = true, 1267 + .has_burst_delta_data = true, 1268 + /* 20 elements of 16bits */ 1269 + .adis_data = ADIS16480_DATA(16547, &adis16545_timeouts, 1270 + ADIS16495_BURST_MAX_DATA * 2, 1271 + 6500000), 1272 + }, 1273 + [ADIS16547_3] = { 1274 + .channels = adis16545_channels, 1275 + .num_channels = ARRAY_SIZE(adis16545_channels), 1276 + .gyro_max_val = 20000 << 16, 1277 + .gyro_max_scale = IIO_DEGREE_TO_RAD(2000), 1278 + .accel_max_val = IIO_M_S_2_TO_G(32000 << 16), 1279 + .accel_max_scale = 40, 1280 + .temp_scale = 7000, /* 7 milli degree Celsius */ 1281 + .deltang_max_val = IIO_DEGREE_TO_RAD(2160), 1282 + .deltvel_max_val = 400, 1283 + .int_clk = 4250000, 1284 + .max_dec_rate = 4250, 1285 + .filter_freqs = adis16495_def_filter_freqs, 1286 + .has_pps_clk_mode = true, 1287 + .has_burst_delta_data = true, 1288 + /* 20 elements of 16bits */ 1289 + .adis_data = ADIS16480_DATA(16547, &adis16545_timeouts, 1290 + ADIS16495_BURST_MAX_DATA * 2, 1291 + 6500000), 1292 + }, 1209 1293 }; 1210 1294 1211 1295 static bool adis16480_validate_crc(const u16 *buf, const u8 n_elem, const u32 crc) ··· 1350 1194 struct adis16480 *st = iio_priv(indio_dev); 1351 1195 struct adis *adis = &st->adis; 1352 1196 struct device *dev = &adis->spi->dev; 1353 - int ret, bit, offset, i = 0; 1197 + int ret, bit, offset, i = 0, buff_offset = 0; 1354 1198 __be16 *buffer; 1355 1199 u32 crc; 1356 1200 bool valid; ··· 1383 1227 * 16-bit responses containing the BURST_ID depending on the sclk. If 1384 1228 * clk > 3.6MHz, then we will have two BURST_ID in a row. If clk < 3MHZ, 1385 1229 * we have only one. To manage that variation, we use the transition from the 1386 - * BURST_ID to the SYS_E_FLAG register, which will not be equal to 0xA5A5. If 1387 - * we not find this variation in the first 4 segments, then the data should 1230 + * BURST_ID to the SYS_E_FLAG register, which will not be equal to 0xA5A5/0xC3C3. 1231 + * If we not find this variation in the first 4 segments, then the data should 1388 1232 * not be valid. 1389 1233 */ 1390 1234 buffer = adis->buffer; ··· 1392 1236 u16 curr = be16_to_cpu(buffer[offset]); 1393 1237 u16 next = be16_to_cpu(buffer[offset + 1]); 1394 1238 1395 - if (curr == ADIS16495_BURST_ID && next != ADIS16495_BURST_ID) { 1239 + if (curr == st->burst_id && next != st->burst_id) { 1396 1240 offset++; 1397 1241 break; 1398 1242 } ··· 1419 1263 switch (bit) { 1420 1264 case ADIS16480_SCAN_TEMP: 1421 1265 st->data[i++] = buffer[offset + 1]; 1266 + /* 1267 + * The temperature channel has 16-bit storage size. 1268 + * We need to perform the padding to have the buffer 1269 + * elements naturally aligned in case there are any 1270 + * 32-bit storage size channels enabled which are added 1271 + * in the buffer after the temprature data. In case 1272 + * there is no data being added after the temperature 1273 + * data, the padding is harmless. 1274 + */ 1275 + st->data[i++] = 0; 1422 1276 break; 1277 + case ADIS16480_SCAN_DELTANG_X ... ADIS16480_SCAN_DELTVEL_Z: 1278 + buff_offset = ADIS16480_SCAN_DELTANG_X; 1279 + fallthrough; 1423 1280 case ADIS16480_SCAN_GYRO_X ... ADIS16480_SCAN_ACCEL_Z: 1424 1281 /* The lower register data is sequenced first */ 1425 - st->data[i++] = buffer[2 * bit + offset + 3]; 1426 - st->data[i++] = buffer[2 * bit + offset + 2]; 1282 + st->data[i++] = buffer[2 * (bit - buff_offset) + offset + 3]; 1283 + st->data[i++] = buffer[2 * (bit - buff_offset) + offset + 2]; 1427 1284 break; 1428 1285 } 1429 1286 } ··· 1448 1279 return IRQ_HANDLED; 1449 1280 } 1450 1281 1282 + static const unsigned long adis16545_channel_masks[] = { 1283 + ADIS16545_BURST_DATA_SEL_0_CHN_MASK | BIT(ADIS16480_SCAN_TEMP) | BIT(17), 1284 + ADIS16545_BURST_DATA_SEL_1_CHN_MASK | BIT(ADIS16480_SCAN_TEMP) | BIT(17), 1285 + 0, 1286 + }; 1287 + 1288 + static int adis16480_update_scan_mode(struct iio_dev *indio_dev, 1289 + const unsigned long *scan_mask) 1290 + { 1291 + u16 en; 1292 + int ret; 1293 + struct adis16480 *st = iio_priv(indio_dev); 1294 + 1295 + if (st->chip_info->has_burst_delta_data) { 1296 + if (*scan_mask & ADIS16545_BURST_DATA_SEL_0_CHN_MASK) { 1297 + en = FIELD_PREP(ADIS16545_BURST_DATA_SEL_MASK, 0); 1298 + st->burst_id = ADIS16495_GYRO_ACCEL_BURST_ID; 1299 + } else { 1300 + en = FIELD_PREP(ADIS16545_BURST_DATA_SEL_MASK, 1); 1301 + st->burst_id = ADIS16545_DELTA_ANG_VEL_BURST_ID; 1302 + } 1303 + 1304 + ret = __adis_update_bits(&st->adis, ADIS16480_REG_CONFIG, 1305 + ADIS16545_BURST_DATA_SEL_MASK, en); 1306 + if (ret) 1307 + return ret; 1308 + } 1309 + 1310 + return adis_update_scan_mode(indio_dev, scan_mask); 1311 + } 1312 + 1451 1313 static const struct iio_info adis16480_info = { 1452 1314 .read_raw = &adis16480_read_raw, 1453 1315 .write_raw = &adis16480_write_raw, 1454 - .update_scan_mode = adis_update_scan_mode, 1316 + .update_scan_mode = &adis16480_update_scan_mode, 1455 1317 .debugfs_reg_access = adis_debugfs_reg_access, 1456 1318 }; 1457 1319 ··· 1679 1479 indio_dev->name = spi_get_device_id(spi)->name; 1680 1480 indio_dev->channels = st->chip_info->channels; 1681 1481 indio_dev->num_channels = st->chip_info->num_channels; 1482 + if (st->chip_info->has_burst_delta_data) 1483 + indio_dev->available_scan_masks = adis16545_channel_masks; 1682 1484 indio_dev->info = &adis16480_info; 1683 1485 indio_dev->modes = INDIO_DIRECT_MODE; 1684 1486 ··· 1693 1491 ret = __adis_initial_startup(&st->adis); 1694 1492 if (ret) 1695 1493 return ret; 1494 + 1495 + /* 1496 + * By default, use burst id for gyroscope and accelerometer data. 1497 + * This is the only option for devices which do not offer delta angle 1498 + * and delta velocity burst readings. 1499 + */ 1500 + st->burst_id = ADIS16495_GYRO_ACCEL_BURST_ID; 1696 1501 1697 1502 if (st->chip_info->has_sleep_cnt) { 1698 1503 ret = devm_add_action_or_reset(dev, adis16480_stop, indio_dev); ··· 1774 1565 { "adis16497-1", ADIS16497_1 }, 1775 1566 { "adis16497-2", ADIS16497_2 }, 1776 1567 { "adis16497-3", ADIS16497_3 }, 1568 + { "adis16545-1", ADIS16545_1 }, 1569 + { "adis16545-2", ADIS16545_2 }, 1570 + { "adis16545-3", ADIS16545_3 }, 1571 + { "adis16547-1", ADIS16547_1 }, 1572 + { "adis16547-2", ADIS16547_2 }, 1573 + { "adis16547-3", ADIS16547_3 }, 1777 1574 { } 1778 1575 }; 1779 1576 MODULE_DEVICE_TABLE(spi, adis16480_ids); ··· 1796 1581 { .compatible = "adi,adis16497-1" }, 1797 1582 { .compatible = "adi,adis16497-2" }, 1798 1583 { .compatible = "adi,adis16497-3" }, 1584 + { .compatible = "adi,adis16545-1" }, 1585 + { .compatible = "adi,adis16545-2" }, 1586 + { .compatible = "adi,adis16545-3" }, 1587 + { .compatible = "adi,adis16547-1" }, 1588 + { .compatible = "adi,adis16547-2" }, 1589 + { .compatible = "adi,adis16547-3" }, 1799 1590 { }, 1800 1591 }; 1801 1592 MODULE_DEVICE_TABLE(of, adis16480_of_match);