18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * adis16400.c support Analog Devices ADIS16400/5 48c2ecf20Sopenharmony_ci * 3d 2g Linear Accelerometers, 58c2ecf20Sopenharmony_ci * 3d Gyroscopes, 68c2ecf20Sopenharmony_ci * 3d Magnetometers via SPI 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Copyright (c) 2009 Manuel Stahl <manuel.stahl@iis.fraunhofer.de> 98c2ecf20Sopenharmony_ci * Copyright (c) 2007 Jonathan Cameron <jic23@kernel.org> 108c2ecf20Sopenharmony_ci * Copyright (c) 2011 Analog Devices Inc. 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 148c2ecf20Sopenharmony_ci#include <linux/irq.h> 158c2ecf20Sopenharmony_ci#include <linux/delay.h> 168c2ecf20Sopenharmony_ci#include <linux/mutex.h> 178c2ecf20Sopenharmony_ci#include <linux/device.h> 188c2ecf20Sopenharmony_ci#include <linux/kernel.h> 198c2ecf20Sopenharmony_ci#include <linux/spi/spi.h> 208c2ecf20Sopenharmony_ci#include <linux/slab.h> 218c2ecf20Sopenharmony_ci#include <linux/sysfs.h> 228c2ecf20Sopenharmony_ci#include <linux/list.h> 238c2ecf20Sopenharmony_ci#include <linux/module.h> 248c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 258c2ecf20Sopenharmony_ci#include <linux/bitops.h> 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#include <linux/iio/iio.h> 288c2ecf20Sopenharmony_ci#include <linux/iio/sysfs.h> 298c2ecf20Sopenharmony_ci#include <linux/iio/buffer.h> 308c2ecf20Sopenharmony_ci#include <linux/iio/trigger_consumer.h> 318c2ecf20Sopenharmony_ci#include <linux/iio/imu/adis.h> 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define ADIS16400_STARTUP_DELAY 290 /* ms */ 348c2ecf20Sopenharmony_ci#define ADIS16400_MTEST_DELAY 90 /* ms */ 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#define ADIS16400_FLASH_CNT 0x00 /* Flash memory write count */ 378c2ecf20Sopenharmony_ci#define ADIS16400_SUPPLY_OUT 0x02 /* Power supply measurement */ 388c2ecf20Sopenharmony_ci#define ADIS16400_XGYRO_OUT 0x04 /* X-axis gyroscope output */ 398c2ecf20Sopenharmony_ci#define ADIS16400_YGYRO_OUT 0x06 /* Y-axis gyroscope output */ 408c2ecf20Sopenharmony_ci#define ADIS16400_ZGYRO_OUT 0x08 /* Z-axis gyroscope output */ 418c2ecf20Sopenharmony_ci#define ADIS16400_XACCL_OUT 0x0A /* X-axis accelerometer output */ 428c2ecf20Sopenharmony_ci#define ADIS16400_YACCL_OUT 0x0C /* Y-axis accelerometer output */ 438c2ecf20Sopenharmony_ci#define ADIS16400_ZACCL_OUT 0x0E /* Z-axis accelerometer output */ 448c2ecf20Sopenharmony_ci#define ADIS16400_XMAGN_OUT 0x10 /* X-axis magnetometer measurement */ 458c2ecf20Sopenharmony_ci#define ADIS16400_YMAGN_OUT 0x12 /* Y-axis magnetometer measurement */ 468c2ecf20Sopenharmony_ci#define ADIS16400_ZMAGN_OUT 0x14 /* Z-axis magnetometer measurement */ 478c2ecf20Sopenharmony_ci#define ADIS16400_TEMP_OUT 0x16 /* Temperature output */ 488c2ecf20Sopenharmony_ci#define ADIS16400_AUX_ADC 0x18 /* Auxiliary ADC measurement */ 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#define ADIS16350_XTEMP_OUT 0x10 /* X-axis gyroscope temperature measurement */ 518c2ecf20Sopenharmony_ci#define ADIS16350_YTEMP_OUT 0x12 /* Y-axis gyroscope temperature measurement */ 528c2ecf20Sopenharmony_ci#define ADIS16350_ZTEMP_OUT 0x14 /* Z-axis gyroscope temperature measurement */ 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#define ADIS16300_PITCH_OUT 0x12 /* X axis inclinometer output measurement */ 558c2ecf20Sopenharmony_ci#define ADIS16300_ROLL_OUT 0x14 /* Y axis inclinometer output measurement */ 568c2ecf20Sopenharmony_ci#define ADIS16300_AUX_ADC 0x16 /* Auxiliary ADC measurement */ 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci#define ADIS16448_BARO_OUT 0x16 /* Barometric pressure output */ 598c2ecf20Sopenharmony_ci#define ADIS16448_TEMP_OUT 0x18 /* Temperature output */ 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/* Calibration parameters */ 628c2ecf20Sopenharmony_ci#define ADIS16400_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */ 638c2ecf20Sopenharmony_ci#define ADIS16400_YGYRO_OFF 0x1C /* Y-axis gyroscope bias offset factor */ 648c2ecf20Sopenharmony_ci#define ADIS16400_ZGYRO_OFF 0x1E /* Z-axis gyroscope bias offset factor */ 658c2ecf20Sopenharmony_ci#define ADIS16400_XACCL_OFF 0x20 /* X-axis acceleration bias offset factor */ 668c2ecf20Sopenharmony_ci#define ADIS16400_YACCL_OFF 0x22 /* Y-axis acceleration bias offset factor */ 678c2ecf20Sopenharmony_ci#define ADIS16400_ZACCL_OFF 0x24 /* Z-axis acceleration bias offset factor */ 688c2ecf20Sopenharmony_ci#define ADIS16400_XMAGN_HIF 0x26 /* X-axis magnetometer, hard-iron factor */ 698c2ecf20Sopenharmony_ci#define ADIS16400_YMAGN_HIF 0x28 /* Y-axis magnetometer, hard-iron factor */ 708c2ecf20Sopenharmony_ci#define ADIS16400_ZMAGN_HIF 0x2A /* Z-axis magnetometer, hard-iron factor */ 718c2ecf20Sopenharmony_ci#define ADIS16400_XMAGN_SIF 0x2C /* X-axis magnetometer, soft-iron factor */ 728c2ecf20Sopenharmony_ci#define ADIS16400_YMAGN_SIF 0x2E /* Y-axis magnetometer, soft-iron factor */ 738c2ecf20Sopenharmony_ci#define ADIS16400_ZMAGN_SIF 0x30 /* Z-axis magnetometer, soft-iron factor */ 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci#define ADIS16400_GPIO_CTRL 0x32 /* Auxiliary digital input/output control */ 768c2ecf20Sopenharmony_ci#define ADIS16400_MSC_CTRL 0x34 /* Miscellaneous control */ 778c2ecf20Sopenharmony_ci#define ADIS16400_SMPL_PRD 0x36 /* Internal sample period (rate) control */ 788c2ecf20Sopenharmony_ci#define ADIS16400_SENS_AVG 0x38 /* Dynamic range and digital filter control */ 798c2ecf20Sopenharmony_ci#define ADIS16400_SLP_CNT 0x3A /* Sleep mode control */ 808c2ecf20Sopenharmony_ci#define ADIS16400_DIAG_STAT 0x3C /* System status */ 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci/* Alarm functions */ 838c2ecf20Sopenharmony_ci#define ADIS16400_GLOB_CMD 0x3E /* System command */ 848c2ecf20Sopenharmony_ci#define ADIS16400_ALM_MAG1 0x40 /* Alarm 1 amplitude threshold */ 858c2ecf20Sopenharmony_ci#define ADIS16400_ALM_MAG2 0x42 /* Alarm 2 amplitude threshold */ 868c2ecf20Sopenharmony_ci#define ADIS16400_ALM_SMPL1 0x44 /* Alarm 1 sample size */ 878c2ecf20Sopenharmony_ci#define ADIS16400_ALM_SMPL2 0x46 /* Alarm 2 sample size */ 888c2ecf20Sopenharmony_ci#define ADIS16400_ALM_CTRL 0x48 /* Alarm control */ 898c2ecf20Sopenharmony_ci#define ADIS16400_AUX_DAC 0x4A /* Auxiliary DAC data */ 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci#define ADIS16334_LOT_ID1 0x52 /* Lot identification code 1 */ 928c2ecf20Sopenharmony_ci#define ADIS16334_LOT_ID2 0x54 /* Lot identification code 2 */ 938c2ecf20Sopenharmony_ci#define ADIS16400_PRODUCT_ID 0x56 /* Product identifier */ 948c2ecf20Sopenharmony_ci#define ADIS16334_SERIAL_NUMBER 0x58 /* Serial number, lot specific */ 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci#define ADIS16400_ERROR_ACTIVE (1<<14) 978c2ecf20Sopenharmony_ci#define ADIS16400_NEW_DATA (1<<14) 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci/* MSC_CTRL */ 1008c2ecf20Sopenharmony_ci#define ADIS16400_MSC_CTRL_MEM_TEST (1<<11) 1018c2ecf20Sopenharmony_ci#define ADIS16400_MSC_CTRL_INT_SELF_TEST (1<<10) 1028c2ecf20Sopenharmony_ci#define ADIS16400_MSC_CTRL_NEG_SELF_TEST (1<<9) 1038c2ecf20Sopenharmony_ci#define ADIS16400_MSC_CTRL_POS_SELF_TEST (1<<8) 1048c2ecf20Sopenharmony_ci#define ADIS16400_MSC_CTRL_GYRO_BIAS (1<<7) 1058c2ecf20Sopenharmony_ci#define ADIS16400_MSC_CTRL_ACCL_ALIGN (1<<6) 1068c2ecf20Sopenharmony_ci#define ADIS16400_MSC_CTRL_DATA_RDY_EN (1<<2) 1078c2ecf20Sopenharmony_ci#define ADIS16400_MSC_CTRL_DATA_RDY_POL_HIGH (1<<1) 1088c2ecf20Sopenharmony_ci#define ADIS16400_MSC_CTRL_DATA_RDY_DIO2 (1<<0) 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci/* SMPL_PRD */ 1118c2ecf20Sopenharmony_ci#define ADIS16400_SMPL_PRD_TIME_BASE (1<<7) 1128c2ecf20Sopenharmony_ci#define ADIS16400_SMPL_PRD_DIV_MASK 0x7F 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci/* DIAG_STAT */ 1158c2ecf20Sopenharmony_ci#define ADIS16400_DIAG_STAT_ZACCL_FAIL 15 1168c2ecf20Sopenharmony_ci#define ADIS16400_DIAG_STAT_YACCL_FAIL 14 1178c2ecf20Sopenharmony_ci#define ADIS16400_DIAG_STAT_XACCL_FAIL 13 1188c2ecf20Sopenharmony_ci#define ADIS16400_DIAG_STAT_XGYRO_FAIL 12 1198c2ecf20Sopenharmony_ci#define ADIS16400_DIAG_STAT_YGYRO_FAIL 11 1208c2ecf20Sopenharmony_ci#define ADIS16400_DIAG_STAT_ZGYRO_FAIL 10 1218c2ecf20Sopenharmony_ci#define ADIS16400_DIAG_STAT_ALARM2 9 1228c2ecf20Sopenharmony_ci#define ADIS16400_DIAG_STAT_ALARM1 8 1238c2ecf20Sopenharmony_ci#define ADIS16400_DIAG_STAT_FLASH_CHK 6 1248c2ecf20Sopenharmony_ci#define ADIS16400_DIAG_STAT_SELF_TEST 5 1258c2ecf20Sopenharmony_ci#define ADIS16400_DIAG_STAT_OVERFLOW 4 1268c2ecf20Sopenharmony_ci#define ADIS16400_DIAG_STAT_SPI_FAIL 3 1278c2ecf20Sopenharmony_ci#define ADIS16400_DIAG_STAT_FLASH_UPT 2 1288c2ecf20Sopenharmony_ci#define ADIS16400_DIAG_STAT_POWER_HIGH 1 1298c2ecf20Sopenharmony_ci#define ADIS16400_DIAG_STAT_POWER_LOW 0 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci/* GLOB_CMD */ 1328c2ecf20Sopenharmony_ci#define ADIS16400_GLOB_CMD_SW_RESET (1<<7) 1338c2ecf20Sopenharmony_ci#define ADIS16400_GLOB_CMD_P_AUTO_NULL (1<<4) 1348c2ecf20Sopenharmony_ci#define ADIS16400_GLOB_CMD_FLASH_UPD (1<<3) 1358c2ecf20Sopenharmony_ci#define ADIS16400_GLOB_CMD_DAC_LATCH (1<<2) 1368c2ecf20Sopenharmony_ci#define ADIS16400_GLOB_CMD_FAC_CALIB (1<<1) 1378c2ecf20Sopenharmony_ci#define ADIS16400_GLOB_CMD_AUTO_NULL (1<<0) 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci/* SLP_CNT */ 1408c2ecf20Sopenharmony_ci#define ADIS16400_SLP_CNT_POWER_OFF (1<<8) 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci#define ADIS16334_RATE_DIV_SHIFT 8 1438c2ecf20Sopenharmony_ci#define ADIS16334_RATE_INT_CLK BIT(0) 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci#define ADIS16400_SPI_SLOW (u32)(300 * 1000) 1468c2ecf20Sopenharmony_ci#define ADIS16400_SPI_BURST (u32)(1000 * 1000) 1478c2ecf20Sopenharmony_ci#define ADIS16400_SPI_FAST (u32)(2000 * 1000) 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci#define ADIS16400_HAS_PROD_ID BIT(0) 1508c2ecf20Sopenharmony_ci#define ADIS16400_NO_BURST BIT(1) 1518c2ecf20Sopenharmony_ci#define ADIS16400_HAS_SLOW_MODE BIT(2) 1528c2ecf20Sopenharmony_ci#define ADIS16400_HAS_SERIAL_NUMBER BIT(3) 1538c2ecf20Sopenharmony_ci#define ADIS16400_BURST_DIAG_STAT BIT(4) 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistruct adis16400_state; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistruct adis16400_chip_info { 1588c2ecf20Sopenharmony_ci const struct iio_chan_spec *channels; 1598c2ecf20Sopenharmony_ci const struct adis_data adis_data; 1608c2ecf20Sopenharmony_ci const int num_channels; 1618c2ecf20Sopenharmony_ci const long flags; 1628c2ecf20Sopenharmony_ci unsigned int gyro_scale_micro; 1638c2ecf20Sopenharmony_ci unsigned int accel_scale_micro; 1648c2ecf20Sopenharmony_ci int temp_scale_nano; 1658c2ecf20Sopenharmony_ci int temp_offset; 1668c2ecf20Sopenharmony_ci /* set_freq() & get_freq() need to avoid using ADIS lib's state lock */ 1678c2ecf20Sopenharmony_ci int (*set_freq)(struct adis16400_state *st, unsigned int freq); 1688c2ecf20Sopenharmony_ci int (*get_freq)(struct adis16400_state *st); 1698c2ecf20Sopenharmony_ci}; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci/** 1728c2ecf20Sopenharmony_ci * struct adis16400_state - device instance specific data 1738c2ecf20Sopenharmony_ci * @variant: chip variant info 1748c2ecf20Sopenharmony_ci * @filt_int: integer part of requested filter frequency 1758c2ecf20Sopenharmony_ci * @adis: adis device 1768c2ecf20Sopenharmony_ci * @avail_scan_mask: NULL terminated array of bitmaps of channels 1778c2ecf20Sopenharmony_ci * that must be enabled together 1788c2ecf20Sopenharmony_ci **/ 1798c2ecf20Sopenharmony_cistruct adis16400_state { 1808c2ecf20Sopenharmony_ci struct adis16400_chip_info *variant; 1818c2ecf20Sopenharmony_ci int filt_int; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci struct adis adis; 1848c2ecf20Sopenharmony_ci unsigned long avail_scan_mask[2]; 1858c2ecf20Sopenharmony_ci}; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci/* At the moment triggers are only used for ring buffer 1888c2ecf20Sopenharmony_ci * filling. This may change! 1898c2ecf20Sopenharmony_ci */ 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_cienum { 1928c2ecf20Sopenharmony_ci ADIS16400_SCAN_SUPPLY, 1938c2ecf20Sopenharmony_ci ADIS16400_SCAN_GYRO_X, 1948c2ecf20Sopenharmony_ci ADIS16400_SCAN_GYRO_Y, 1958c2ecf20Sopenharmony_ci ADIS16400_SCAN_GYRO_Z, 1968c2ecf20Sopenharmony_ci ADIS16400_SCAN_ACC_X, 1978c2ecf20Sopenharmony_ci ADIS16400_SCAN_ACC_Y, 1988c2ecf20Sopenharmony_ci ADIS16400_SCAN_ACC_Z, 1998c2ecf20Sopenharmony_ci ADIS16400_SCAN_MAGN_X, 2008c2ecf20Sopenharmony_ci ADIS16400_SCAN_MAGN_Y, 2018c2ecf20Sopenharmony_ci ADIS16400_SCAN_MAGN_Z, 2028c2ecf20Sopenharmony_ci ADIS16400_SCAN_BARO, 2038c2ecf20Sopenharmony_ci ADIS16350_SCAN_TEMP_X, 2048c2ecf20Sopenharmony_ci ADIS16350_SCAN_TEMP_Y, 2058c2ecf20Sopenharmony_ci ADIS16350_SCAN_TEMP_Z, 2068c2ecf20Sopenharmony_ci ADIS16300_SCAN_INCLI_X, 2078c2ecf20Sopenharmony_ci ADIS16300_SCAN_INCLI_Y, 2088c2ecf20Sopenharmony_ci ADIS16400_SCAN_ADC, 2098c2ecf20Sopenharmony_ci ADIS16400_SCAN_TIMESTAMP, 2108c2ecf20Sopenharmony_ci}; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cistatic ssize_t adis16400_show_serial_number(struct file *file, 2158c2ecf20Sopenharmony_ci char __user *userbuf, size_t count, loff_t *ppos) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci struct adis16400_state *st = file->private_data; 2188c2ecf20Sopenharmony_ci u16 lot1, lot2, serial_number; 2198c2ecf20Sopenharmony_ci char buf[16]; 2208c2ecf20Sopenharmony_ci size_t len; 2218c2ecf20Sopenharmony_ci int ret; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci ret = adis_read_reg_16(&st->adis, ADIS16334_LOT_ID1, &lot1); 2248c2ecf20Sopenharmony_ci if (ret) 2258c2ecf20Sopenharmony_ci return ret; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci ret = adis_read_reg_16(&st->adis, ADIS16334_LOT_ID2, &lot2); 2288c2ecf20Sopenharmony_ci if (ret) 2298c2ecf20Sopenharmony_ci return ret; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci ret = adis_read_reg_16(&st->adis, ADIS16334_SERIAL_NUMBER, 2328c2ecf20Sopenharmony_ci &serial_number); 2338c2ecf20Sopenharmony_ci if (ret) 2348c2ecf20Sopenharmony_ci return ret; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci len = snprintf(buf, sizeof(buf), "%.4x-%.4x-%.4x\n", lot1, lot2, 2378c2ecf20Sopenharmony_ci serial_number); 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci return simple_read_from_buffer(userbuf, count, ppos, buf, len); 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_cistatic const struct file_operations adis16400_serial_number_fops = { 2438c2ecf20Sopenharmony_ci .open = simple_open, 2448c2ecf20Sopenharmony_ci .read = adis16400_show_serial_number, 2458c2ecf20Sopenharmony_ci .llseek = default_llseek, 2468c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 2478c2ecf20Sopenharmony_ci}; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic int adis16400_show_product_id(void *arg, u64 *val) 2508c2ecf20Sopenharmony_ci{ 2518c2ecf20Sopenharmony_ci struct adis16400_state *st = arg; 2528c2ecf20Sopenharmony_ci uint16_t prod_id; 2538c2ecf20Sopenharmony_ci int ret; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci ret = adis_read_reg_16(&st->adis, ADIS16400_PRODUCT_ID, &prod_id); 2568c2ecf20Sopenharmony_ci if (ret) 2578c2ecf20Sopenharmony_ci return ret; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci *val = prod_id; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci return 0; 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(adis16400_product_id_fops, 2648c2ecf20Sopenharmony_ci adis16400_show_product_id, NULL, "%lld\n"); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistatic int adis16400_show_flash_count(void *arg, u64 *val) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci struct adis16400_state *st = arg; 2698c2ecf20Sopenharmony_ci uint16_t flash_count; 2708c2ecf20Sopenharmony_ci int ret; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci ret = adis_read_reg_16(&st->adis, ADIS16400_FLASH_CNT, &flash_count); 2738c2ecf20Sopenharmony_ci if (ret) 2748c2ecf20Sopenharmony_ci return ret; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci *val = flash_count; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci return 0; 2798c2ecf20Sopenharmony_ci} 2808c2ecf20Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(adis16400_flash_count_fops, 2818c2ecf20Sopenharmony_ci adis16400_show_flash_count, NULL, "%lld\n"); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistatic int adis16400_debugfs_init(struct iio_dev *indio_dev) 2848c2ecf20Sopenharmony_ci{ 2858c2ecf20Sopenharmony_ci struct adis16400_state *st = iio_priv(indio_dev); 2868c2ecf20Sopenharmony_ci struct dentry *d = iio_get_debugfs_dentry(indio_dev); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci if (st->variant->flags & ADIS16400_HAS_SERIAL_NUMBER) 2898c2ecf20Sopenharmony_ci debugfs_create_file_unsafe("serial_number", 0400, 2908c2ecf20Sopenharmony_ci d, st, &adis16400_serial_number_fops); 2918c2ecf20Sopenharmony_ci if (st->variant->flags & ADIS16400_HAS_PROD_ID) 2928c2ecf20Sopenharmony_ci debugfs_create_file_unsafe("product_id", 0400, 2938c2ecf20Sopenharmony_ci d, st, &adis16400_product_id_fops); 2948c2ecf20Sopenharmony_ci debugfs_create_file_unsafe("flash_count", 0400, 2958c2ecf20Sopenharmony_ci d, st, &adis16400_flash_count_fops); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci return 0; 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci#else 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic int adis16400_debugfs_init(struct iio_dev *indio_dev) 3038c2ecf20Sopenharmony_ci{ 3048c2ecf20Sopenharmony_ci return 0; 3058c2ecf20Sopenharmony_ci} 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci#endif 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_cienum adis16400_chip_variant { 3108c2ecf20Sopenharmony_ci ADIS16300, 3118c2ecf20Sopenharmony_ci ADIS16334, 3128c2ecf20Sopenharmony_ci ADIS16350, 3138c2ecf20Sopenharmony_ci ADIS16360, 3148c2ecf20Sopenharmony_ci ADIS16362, 3158c2ecf20Sopenharmony_ci ADIS16364, 3168c2ecf20Sopenharmony_ci ADIS16367, 3178c2ecf20Sopenharmony_ci ADIS16400, 3188c2ecf20Sopenharmony_ci ADIS16445, 3198c2ecf20Sopenharmony_ci ADIS16448, 3208c2ecf20Sopenharmony_ci}; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_cistatic int adis16334_get_freq(struct adis16400_state *st) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci int ret; 3258c2ecf20Sopenharmony_ci uint16_t t; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci ret = __adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); 3288c2ecf20Sopenharmony_ci if (ret) 3298c2ecf20Sopenharmony_ci return ret; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci t >>= ADIS16334_RATE_DIV_SHIFT; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci return 819200 >> t; 3348c2ecf20Sopenharmony_ci} 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_cistatic int adis16334_set_freq(struct adis16400_state *st, unsigned int freq) 3378c2ecf20Sopenharmony_ci{ 3388c2ecf20Sopenharmony_ci unsigned int t; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci if (freq < 819200) 3418c2ecf20Sopenharmony_ci t = ilog2(819200 / freq); 3428c2ecf20Sopenharmony_ci else 3438c2ecf20Sopenharmony_ci t = 0; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci if (t > 0x31) 3468c2ecf20Sopenharmony_ci t = 0x31; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci t <<= ADIS16334_RATE_DIV_SHIFT; 3498c2ecf20Sopenharmony_ci t |= ADIS16334_RATE_INT_CLK; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci return __adis_write_reg_16(&st->adis, ADIS16400_SMPL_PRD, t); 3528c2ecf20Sopenharmony_ci} 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_cistatic int adis16400_get_freq(struct adis16400_state *st) 3558c2ecf20Sopenharmony_ci{ 3568c2ecf20Sopenharmony_ci int sps, ret; 3578c2ecf20Sopenharmony_ci uint16_t t; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci ret = __adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); 3608c2ecf20Sopenharmony_ci if (ret) 3618c2ecf20Sopenharmony_ci return ret; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci sps = (t & ADIS16400_SMPL_PRD_TIME_BASE) ? 52851 : 1638404; 3648c2ecf20Sopenharmony_ci sps /= (t & ADIS16400_SMPL_PRD_DIV_MASK) + 1; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci return sps; 3678c2ecf20Sopenharmony_ci} 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_cistatic int adis16400_set_freq(struct adis16400_state *st, unsigned int freq) 3708c2ecf20Sopenharmony_ci{ 3718c2ecf20Sopenharmony_ci unsigned int t; 3728c2ecf20Sopenharmony_ci uint8_t val = 0; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci t = 1638404 / freq; 3758c2ecf20Sopenharmony_ci if (t >= 128) { 3768c2ecf20Sopenharmony_ci val |= ADIS16400_SMPL_PRD_TIME_BASE; 3778c2ecf20Sopenharmony_ci t = 52851 / freq; 3788c2ecf20Sopenharmony_ci if (t >= 128) 3798c2ecf20Sopenharmony_ci t = 127; 3808c2ecf20Sopenharmony_ci } else if (t != 0) { 3818c2ecf20Sopenharmony_ci t--; 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci val |= t; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci if (t >= 0x0A || (val & ADIS16400_SMPL_PRD_TIME_BASE)) 3878c2ecf20Sopenharmony_ci st->adis.spi->max_speed_hz = ADIS16400_SPI_SLOW; 3888c2ecf20Sopenharmony_ci else 3898c2ecf20Sopenharmony_ci st->adis.spi->max_speed_hz = ADIS16400_SPI_FAST; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci return __adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val); 3928c2ecf20Sopenharmony_ci} 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_cistatic const unsigned int adis16400_3db_divisors[] = { 3958c2ecf20Sopenharmony_ci [0] = 2, /* Special case */ 3968c2ecf20Sopenharmony_ci [1] = 6, 3978c2ecf20Sopenharmony_ci [2] = 12, 3988c2ecf20Sopenharmony_ci [3] = 25, 3998c2ecf20Sopenharmony_ci [4] = 50, 4008c2ecf20Sopenharmony_ci [5] = 100, 4018c2ecf20Sopenharmony_ci [6] = 200, 4028c2ecf20Sopenharmony_ci [7] = 200, /* Not a valid setting */ 4038c2ecf20Sopenharmony_ci}; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_cistatic int __adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val) 4068c2ecf20Sopenharmony_ci{ 4078c2ecf20Sopenharmony_ci struct adis16400_state *st = iio_priv(indio_dev); 4088c2ecf20Sopenharmony_ci uint16_t val16; 4098c2ecf20Sopenharmony_ci int i, ret; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci for (i = ARRAY_SIZE(adis16400_3db_divisors) - 1; i >= 1; i--) { 4128c2ecf20Sopenharmony_ci if (sps / adis16400_3db_divisors[i] >= val) 4138c2ecf20Sopenharmony_ci break; 4148c2ecf20Sopenharmony_ci } 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci ret = __adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, &val16); 4178c2ecf20Sopenharmony_ci if (ret) 4188c2ecf20Sopenharmony_ci return ret; 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci ret = __adis_write_reg_16(&st->adis, ADIS16400_SENS_AVG, 4218c2ecf20Sopenharmony_ci (val16 & ~0x07) | i); 4228c2ecf20Sopenharmony_ci return ret; 4238c2ecf20Sopenharmony_ci} 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci/* Power down the device */ 4268c2ecf20Sopenharmony_cistatic int adis16400_stop_device(struct iio_dev *indio_dev) 4278c2ecf20Sopenharmony_ci{ 4288c2ecf20Sopenharmony_ci struct adis16400_state *st = iio_priv(indio_dev); 4298c2ecf20Sopenharmony_ci int ret; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci ret = adis_write_reg_16(&st->adis, ADIS16400_SLP_CNT, 4328c2ecf20Sopenharmony_ci ADIS16400_SLP_CNT_POWER_OFF); 4338c2ecf20Sopenharmony_ci if (ret) 4348c2ecf20Sopenharmony_ci dev_err(&indio_dev->dev, 4358c2ecf20Sopenharmony_ci "problem with turning device off: SLP_CNT"); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci return ret; 4388c2ecf20Sopenharmony_ci} 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_cistatic int adis16400_initial_setup(struct iio_dev *indio_dev) 4418c2ecf20Sopenharmony_ci{ 4428c2ecf20Sopenharmony_ci struct adis16400_state *st = iio_priv(indio_dev); 4438c2ecf20Sopenharmony_ci uint16_t prod_id, smp_prd; 4448c2ecf20Sopenharmony_ci unsigned int device_id; 4458c2ecf20Sopenharmony_ci int ret; 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci /* use low spi speed for init if the device has a slow mode */ 4488c2ecf20Sopenharmony_ci if (st->variant->flags & ADIS16400_HAS_SLOW_MODE) 4498c2ecf20Sopenharmony_ci st->adis.spi->max_speed_hz = ADIS16400_SPI_SLOW; 4508c2ecf20Sopenharmony_ci else 4518c2ecf20Sopenharmony_ci st->adis.spi->max_speed_hz = ADIS16400_SPI_FAST; 4528c2ecf20Sopenharmony_ci st->adis.spi->mode = SPI_MODE_3; 4538c2ecf20Sopenharmony_ci spi_setup(st->adis.spi); 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci ret = adis_initial_startup(&st->adis); 4568c2ecf20Sopenharmony_ci if (ret) 4578c2ecf20Sopenharmony_ci return ret; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci if (st->variant->flags & ADIS16400_HAS_PROD_ID) { 4608c2ecf20Sopenharmony_ci ret = adis_read_reg_16(&st->adis, 4618c2ecf20Sopenharmony_ci ADIS16400_PRODUCT_ID, &prod_id); 4628c2ecf20Sopenharmony_ci if (ret) 4638c2ecf20Sopenharmony_ci goto err_ret; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci if (sscanf(indio_dev->name, "adis%u\n", &device_id) != 1) { 4668c2ecf20Sopenharmony_ci ret = -EINVAL; 4678c2ecf20Sopenharmony_ci goto err_ret; 4688c2ecf20Sopenharmony_ci } 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci if (prod_id != device_id) 4718c2ecf20Sopenharmony_ci dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.", 4728c2ecf20Sopenharmony_ci device_id, prod_id); 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci dev_info(&indio_dev->dev, "%s: prod_id 0x%04x at CS%d (irq %d)\n", 4758c2ecf20Sopenharmony_ci indio_dev->name, prod_id, 4768c2ecf20Sopenharmony_ci st->adis.spi->chip_select, st->adis.spi->irq); 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci /* use high spi speed if possible */ 4798c2ecf20Sopenharmony_ci if (st->variant->flags & ADIS16400_HAS_SLOW_MODE) { 4808c2ecf20Sopenharmony_ci ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &smp_prd); 4818c2ecf20Sopenharmony_ci if (ret) 4828c2ecf20Sopenharmony_ci goto err_ret; 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci if ((smp_prd & ADIS16400_SMPL_PRD_DIV_MASK) < 0x0A) { 4858c2ecf20Sopenharmony_ci st->adis.spi->max_speed_hz = ADIS16400_SPI_FAST; 4868c2ecf20Sopenharmony_ci spi_setup(st->adis.spi); 4878c2ecf20Sopenharmony_ci } 4888c2ecf20Sopenharmony_ci } 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_cierr_ret: 4918c2ecf20Sopenharmony_ci return ret; 4928c2ecf20Sopenharmony_ci} 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_cistatic const uint8_t adis16400_addresses[] = { 4958c2ecf20Sopenharmony_ci [ADIS16400_SCAN_GYRO_X] = ADIS16400_XGYRO_OFF, 4968c2ecf20Sopenharmony_ci [ADIS16400_SCAN_GYRO_Y] = ADIS16400_YGYRO_OFF, 4978c2ecf20Sopenharmony_ci [ADIS16400_SCAN_GYRO_Z] = ADIS16400_ZGYRO_OFF, 4988c2ecf20Sopenharmony_ci [ADIS16400_SCAN_ACC_X] = ADIS16400_XACCL_OFF, 4998c2ecf20Sopenharmony_ci [ADIS16400_SCAN_ACC_Y] = ADIS16400_YACCL_OFF, 5008c2ecf20Sopenharmony_ci [ADIS16400_SCAN_ACC_Z] = ADIS16400_ZACCL_OFF, 5018c2ecf20Sopenharmony_ci}; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_cistatic int adis16400_write_raw(struct iio_dev *indio_dev, 5048c2ecf20Sopenharmony_ci struct iio_chan_spec const *chan, int val, int val2, long info) 5058c2ecf20Sopenharmony_ci{ 5068c2ecf20Sopenharmony_ci struct adis16400_state *st = iio_priv(indio_dev); 5078c2ecf20Sopenharmony_ci struct mutex *slock = &st->adis.state_lock; 5088c2ecf20Sopenharmony_ci int ret, sps; 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci switch (info) { 5118c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_CALIBBIAS: 5128c2ecf20Sopenharmony_ci ret = adis_write_reg_16(&st->adis, 5138c2ecf20Sopenharmony_ci adis16400_addresses[chan->scan_index], val); 5148c2ecf20Sopenharmony_ci return ret; 5158c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 5168c2ecf20Sopenharmony_ci /* 5178c2ecf20Sopenharmony_ci * Need to cache values so we can update if the frequency 5188c2ecf20Sopenharmony_ci * changes. 5198c2ecf20Sopenharmony_ci */ 5208c2ecf20Sopenharmony_ci mutex_lock(slock); 5218c2ecf20Sopenharmony_ci st->filt_int = val; 5228c2ecf20Sopenharmony_ci /* Work out update to current value */ 5238c2ecf20Sopenharmony_ci sps = st->variant->get_freq(st); 5248c2ecf20Sopenharmony_ci if (sps < 0) { 5258c2ecf20Sopenharmony_ci mutex_unlock(slock); 5268c2ecf20Sopenharmony_ci return sps; 5278c2ecf20Sopenharmony_ci } 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci ret = __adis16400_set_filter(indio_dev, sps, 5308c2ecf20Sopenharmony_ci val * 1000 + val2 / 1000); 5318c2ecf20Sopenharmony_ci mutex_unlock(slock); 5328c2ecf20Sopenharmony_ci return ret; 5338c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_SAMP_FREQ: 5348c2ecf20Sopenharmony_ci sps = val * 1000 + val2 / 1000; 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci if (sps <= 0) 5378c2ecf20Sopenharmony_ci return -EINVAL; 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci mutex_lock(slock); 5408c2ecf20Sopenharmony_ci ret = st->variant->set_freq(st, sps); 5418c2ecf20Sopenharmony_ci mutex_unlock(slock); 5428c2ecf20Sopenharmony_ci return ret; 5438c2ecf20Sopenharmony_ci default: 5448c2ecf20Sopenharmony_ci return -EINVAL; 5458c2ecf20Sopenharmony_ci } 5468c2ecf20Sopenharmony_ci} 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_cistatic int adis16400_read_raw(struct iio_dev *indio_dev, 5498c2ecf20Sopenharmony_ci struct iio_chan_spec const *chan, int *val, int *val2, long info) 5508c2ecf20Sopenharmony_ci{ 5518c2ecf20Sopenharmony_ci struct adis16400_state *st = iio_priv(indio_dev); 5528c2ecf20Sopenharmony_ci struct mutex *slock = &st->adis.state_lock; 5538c2ecf20Sopenharmony_ci int16_t val16; 5548c2ecf20Sopenharmony_ci int ret; 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci switch (info) { 5578c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_RAW: 5588c2ecf20Sopenharmony_ci return adis_single_conversion(indio_dev, chan, 0, val); 5598c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 5608c2ecf20Sopenharmony_ci switch (chan->type) { 5618c2ecf20Sopenharmony_ci case IIO_ANGL_VEL: 5628c2ecf20Sopenharmony_ci *val = 0; 5638c2ecf20Sopenharmony_ci *val2 = st->variant->gyro_scale_micro; 5648c2ecf20Sopenharmony_ci return IIO_VAL_INT_PLUS_MICRO; 5658c2ecf20Sopenharmony_ci case IIO_VOLTAGE: 5668c2ecf20Sopenharmony_ci *val = 0; 5678c2ecf20Sopenharmony_ci if (chan->channel == 0) { 5688c2ecf20Sopenharmony_ci *val = 2; 5698c2ecf20Sopenharmony_ci *val2 = 418000; /* 2.418 mV */ 5708c2ecf20Sopenharmony_ci } else { 5718c2ecf20Sopenharmony_ci *val = 0; 5728c2ecf20Sopenharmony_ci *val2 = 805800; /* 805.8 uV */ 5738c2ecf20Sopenharmony_ci } 5748c2ecf20Sopenharmony_ci return IIO_VAL_INT_PLUS_MICRO; 5758c2ecf20Sopenharmony_ci case IIO_ACCEL: 5768c2ecf20Sopenharmony_ci *val = 0; 5778c2ecf20Sopenharmony_ci *val2 = st->variant->accel_scale_micro; 5788c2ecf20Sopenharmony_ci return IIO_VAL_INT_PLUS_MICRO; 5798c2ecf20Sopenharmony_ci case IIO_MAGN: 5808c2ecf20Sopenharmony_ci *val = 0; 5818c2ecf20Sopenharmony_ci *val2 = 500; /* 0.5 mgauss */ 5828c2ecf20Sopenharmony_ci return IIO_VAL_INT_PLUS_MICRO; 5838c2ecf20Sopenharmony_ci case IIO_TEMP: 5848c2ecf20Sopenharmony_ci *val = st->variant->temp_scale_nano / 1000000; 5858c2ecf20Sopenharmony_ci *val2 = (st->variant->temp_scale_nano % 1000000); 5868c2ecf20Sopenharmony_ci return IIO_VAL_INT_PLUS_MICRO; 5878c2ecf20Sopenharmony_ci case IIO_PRESSURE: 5888c2ecf20Sopenharmony_ci /* 20 uBar = 0.002kPascal */ 5898c2ecf20Sopenharmony_ci *val = 0; 5908c2ecf20Sopenharmony_ci *val2 = 2000; 5918c2ecf20Sopenharmony_ci return IIO_VAL_INT_PLUS_MICRO; 5928c2ecf20Sopenharmony_ci default: 5938c2ecf20Sopenharmony_ci return -EINVAL; 5948c2ecf20Sopenharmony_ci } 5958c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_CALIBBIAS: 5968c2ecf20Sopenharmony_ci ret = adis_read_reg_16(&st->adis, 5978c2ecf20Sopenharmony_ci adis16400_addresses[chan->scan_index], &val16); 5988c2ecf20Sopenharmony_ci if (ret) 5998c2ecf20Sopenharmony_ci return ret; 6008c2ecf20Sopenharmony_ci val16 = sign_extend32(val16, 11); 6018c2ecf20Sopenharmony_ci *val = val16; 6028c2ecf20Sopenharmony_ci return IIO_VAL_INT; 6038c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_OFFSET: 6048c2ecf20Sopenharmony_ci /* currently only temperature */ 6058c2ecf20Sopenharmony_ci *val = st->variant->temp_offset; 6068c2ecf20Sopenharmony_ci return IIO_VAL_INT; 6078c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 6088c2ecf20Sopenharmony_ci mutex_lock(slock); 6098c2ecf20Sopenharmony_ci /* Need both the number of taps and the sampling frequency */ 6108c2ecf20Sopenharmony_ci ret = __adis_read_reg_16(&st->adis, 6118c2ecf20Sopenharmony_ci ADIS16400_SENS_AVG, 6128c2ecf20Sopenharmony_ci &val16); 6138c2ecf20Sopenharmony_ci if (ret) { 6148c2ecf20Sopenharmony_ci mutex_unlock(slock); 6158c2ecf20Sopenharmony_ci return ret; 6168c2ecf20Sopenharmony_ci } 6178c2ecf20Sopenharmony_ci ret = st->variant->get_freq(st); 6188c2ecf20Sopenharmony_ci mutex_unlock(slock); 6198c2ecf20Sopenharmony_ci if (ret) 6208c2ecf20Sopenharmony_ci return ret; 6218c2ecf20Sopenharmony_ci ret /= adis16400_3db_divisors[val16 & 0x07]; 6228c2ecf20Sopenharmony_ci *val = ret / 1000; 6238c2ecf20Sopenharmony_ci *val2 = (ret % 1000) * 1000; 6248c2ecf20Sopenharmony_ci return IIO_VAL_INT_PLUS_MICRO; 6258c2ecf20Sopenharmony_ci case IIO_CHAN_INFO_SAMP_FREQ: 6268c2ecf20Sopenharmony_ci mutex_lock(slock); 6278c2ecf20Sopenharmony_ci ret = st->variant->get_freq(st); 6288c2ecf20Sopenharmony_ci mutex_unlock(slock); 6298c2ecf20Sopenharmony_ci if (ret) 6308c2ecf20Sopenharmony_ci return ret; 6318c2ecf20Sopenharmony_ci *val = ret / 1000; 6328c2ecf20Sopenharmony_ci *val2 = (ret % 1000) * 1000; 6338c2ecf20Sopenharmony_ci return IIO_VAL_INT_PLUS_MICRO; 6348c2ecf20Sopenharmony_ci default: 6358c2ecf20Sopenharmony_ci return -EINVAL; 6368c2ecf20Sopenharmony_ci } 6378c2ecf20Sopenharmony_ci} 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_IIO_BUFFER) 6408c2ecf20Sopenharmony_cistatic irqreturn_t adis16400_trigger_handler(int irq, void *p) 6418c2ecf20Sopenharmony_ci{ 6428c2ecf20Sopenharmony_ci struct iio_poll_func *pf = p; 6438c2ecf20Sopenharmony_ci struct iio_dev *indio_dev = pf->indio_dev; 6448c2ecf20Sopenharmony_ci struct adis16400_state *st = iio_priv(indio_dev); 6458c2ecf20Sopenharmony_ci struct adis *adis = &st->adis; 6468c2ecf20Sopenharmony_ci u32 old_speed_hz = st->adis.spi->max_speed_hz; 6478c2ecf20Sopenharmony_ci void *buffer; 6488c2ecf20Sopenharmony_ci int ret; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci if (!(st->variant->flags & ADIS16400_NO_BURST) && 6518c2ecf20Sopenharmony_ci st->adis.spi->max_speed_hz > ADIS16400_SPI_BURST) { 6528c2ecf20Sopenharmony_ci st->adis.spi->max_speed_hz = ADIS16400_SPI_BURST; 6538c2ecf20Sopenharmony_ci spi_setup(st->adis.spi); 6548c2ecf20Sopenharmony_ci } 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci ret = spi_sync(adis->spi, &adis->msg); 6578c2ecf20Sopenharmony_ci if (ret) 6588c2ecf20Sopenharmony_ci dev_err(&adis->spi->dev, "Failed to read data: %d\n", ret); 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci if (!(st->variant->flags & ADIS16400_NO_BURST)) { 6618c2ecf20Sopenharmony_ci st->adis.spi->max_speed_hz = old_speed_hz; 6628c2ecf20Sopenharmony_ci spi_setup(st->adis.spi); 6638c2ecf20Sopenharmony_ci } 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) 6668c2ecf20Sopenharmony_ci buffer = adis->buffer + sizeof(u16); 6678c2ecf20Sopenharmony_ci else 6688c2ecf20Sopenharmony_ci buffer = adis->buffer; 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci iio_push_to_buffers_with_timestamp(indio_dev, buffer, 6718c2ecf20Sopenharmony_ci pf->timestamp); 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci iio_trigger_notify_done(indio_dev->trig); 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci return IRQ_HANDLED; 6768c2ecf20Sopenharmony_ci} 6778c2ecf20Sopenharmony_ci#else 6788c2ecf20Sopenharmony_ci#define adis16400_trigger_handler NULL 6798c2ecf20Sopenharmony_ci#endif /* IS_ENABLED(CONFIG_IIO_BUFFER) */ 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci#define ADIS16400_VOLTAGE_CHAN(addr, bits, name, si, chn) { \ 6828c2ecf20Sopenharmony_ci .type = IIO_VOLTAGE, \ 6838c2ecf20Sopenharmony_ci .indexed = 1, \ 6848c2ecf20Sopenharmony_ci .channel = chn, \ 6858c2ecf20Sopenharmony_ci .extend_name = name, \ 6868c2ecf20Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 6878c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), \ 6888c2ecf20Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 6898c2ecf20Sopenharmony_ci .address = (addr), \ 6908c2ecf20Sopenharmony_ci .scan_index = (si), \ 6918c2ecf20Sopenharmony_ci .scan_type = { \ 6928c2ecf20Sopenharmony_ci .sign = 'u', \ 6938c2ecf20Sopenharmony_ci .realbits = (bits), \ 6948c2ecf20Sopenharmony_ci .storagebits = 16, \ 6958c2ecf20Sopenharmony_ci .shift = 0, \ 6968c2ecf20Sopenharmony_ci .endianness = IIO_BE, \ 6978c2ecf20Sopenharmony_ci }, \ 6988c2ecf20Sopenharmony_ci} 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci#define ADIS16400_SUPPLY_CHAN(addr, bits) \ 7018c2ecf20Sopenharmony_ci ADIS16400_VOLTAGE_CHAN(addr, bits, "supply", ADIS16400_SCAN_SUPPLY, 0) 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci#define ADIS16400_AUX_ADC_CHAN(addr, bits) \ 7048c2ecf20Sopenharmony_ci ADIS16400_VOLTAGE_CHAN(addr, bits, NULL, ADIS16400_SCAN_ADC, 1) 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci#define ADIS16400_GYRO_CHAN(mod, addr, bits) { \ 7078c2ecf20Sopenharmony_ci .type = IIO_ANGL_VEL, \ 7088c2ecf20Sopenharmony_ci .modified = 1, \ 7098c2ecf20Sopenharmony_ci .channel2 = IIO_MOD_ ## mod, \ 7108c2ecf20Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 7118c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_CALIBBIAS), \ 7128c2ecf20Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 7138c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ 7148c2ecf20Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 7158c2ecf20Sopenharmony_ci .address = addr, \ 7168c2ecf20Sopenharmony_ci .scan_index = ADIS16400_SCAN_GYRO_ ## mod, \ 7178c2ecf20Sopenharmony_ci .scan_type = { \ 7188c2ecf20Sopenharmony_ci .sign = 's', \ 7198c2ecf20Sopenharmony_ci .realbits = (bits), \ 7208c2ecf20Sopenharmony_ci .storagebits = 16, \ 7218c2ecf20Sopenharmony_ci .shift = 0, \ 7228c2ecf20Sopenharmony_ci .endianness = IIO_BE, \ 7238c2ecf20Sopenharmony_ci }, \ 7248c2ecf20Sopenharmony_ci} 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci#define ADIS16400_ACCEL_CHAN(mod, addr, bits) { \ 7278c2ecf20Sopenharmony_ci .type = IIO_ACCEL, \ 7288c2ecf20Sopenharmony_ci .modified = 1, \ 7298c2ecf20Sopenharmony_ci .channel2 = IIO_MOD_ ## mod, \ 7308c2ecf20Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 7318c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_CALIBBIAS), \ 7328c2ecf20Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 7338c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ 7348c2ecf20Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 7358c2ecf20Sopenharmony_ci .address = (addr), \ 7368c2ecf20Sopenharmony_ci .scan_index = ADIS16400_SCAN_ACC_ ## mod, \ 7378c2ecf20Sopenharmony_ci .scan_type = { \ 7388c2ecf20Sopenharmony_ci .sign = 's', \ 7398c2ecf20Sopenharmony_ci .realbits = (bits), \ 7408c2ecf20Sopenharmony_ci .storagebits = 16, \ 7418c2ecf20Sopenharmony_ci .shift = 0, \ 7428c2ecf20Sopenharmony_ci .endianness = IIO_BE, \ 7438c2ecf20Sopenharmony_ci }, \ 7448c2ecf20Sopenharmony_ci} 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci#define ADIS16400_MAGN_CHAN(mod, addr, bits) { \ 7478c2ecf20Sopenharmony_ci .type = IIO_MAGN, \ 7488c2ecf20Sopenharmony_ci .modified = 1, \ 7498c2ecf20Sopenharmony_ci .channel2 = IIO_MOD_ ## mod, \ 7508c2ecf20Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 7518c2ecf20Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 7528c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ 7538c2ecf20Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 7548c2ecf20Sopenharmony_ci .address = (addr), \ 7558c2ecf20Sopenharmony_ci .scan_index = ADIS16400_SCAN_MAGN_ ## mod, \ 7568c2ecf20Sopenharmony_ci .scan_type = { \ 7578c2ecf20Sopenharmony_ci .sign = 's', \ 7588c2ecf20Sopenharmony_ci .realbits = (bits), \ 7598c2ecf20Sopenharmony_ci .storagebits = 16, \ 7608c2ecf20Sopenharmony_ci .shift = 0, \ 7618c2ecf20Sopenharmony_ci .endianness = IIO_BE, \ 7628c2ecf20Sopenharmony_ci }, \ 7638c2ecf20Sopenharmony_ci} 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci#define ADIS16400_MOD_TEMP_NAME_X "x" 7668c2ecf20Sopenharmony_ci#define ADIS16400_MOD_TEMP_NAME_Y "y" 7678c2ecf20Sopenharmony_ci#define ADIS16400_MOD_TEMP_NAME_Z "z" 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci#define ADIS16400_MOD_TEMP_CHAN(mod, addr, bits) { \ 7708c2ecf20Sopenharmony_ci .type = IIO_TEMP, \ 7718c2ecf20Sopenharmony_ci .indexed = 1, \ 7728c2ecf20Sopenharmony_ci .channel = 0, \ 7738c2ecf20Sopenharmony_ci .extend_name = ADIS16400_MOD_TEMP_NAME_ ## mod, \ 7748c2ecf20Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 7758c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_OFFSET) | \ 7768c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), \ 7778c2ecf20Sopenharmony_ci .info_mask_shared_by_type = \ 7788c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ 7798c2ecf20Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 7808c2ecf20Sopenharmony_ci .address = (addr), \ 7818c2ecf20Sopenharmony_ci .scan_index = ADIS16350_SCAN_TEMP_ ## mod, \ 7828c2ecf20Sopenharmony_ci .scan_type = { \ 7838c2ecf20Sopenharmony_ci .sign = 's', \ 7848c2ecf20Sopenharmony_ci .realbits = (bits), \ 7858c2ecf20Sopenharmony_ci .storagebits = 16, \ 7868c2ecf20Sopenharmony_ci .shift = 0, \ 7878c2ecf20Sopenharmony_ci .endianness = IIO_BE, \ 7888c2ecf20Sopenharmony_ci }, \ 7898c2ecf20Sopenharmony_ci} 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci#define ADIS16400_TEMP_CHAN(addr, bits) { \ 7928c2ecf20Sopenharmony_ci .type = IIO_TEMP, \ 7938c2ecf20Sopenharmony_ci .indexed = 1, \ 7948c2ecf20Sopenharmony_ci .channel = 0, \ 7958c2ecf20Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 7968c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_OFFSET) | \ 7978c2ecf20Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), \ 7988c2ecf20Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 7998c2ecf20Sopenharmony_ci .address = (addr), \ 8008c2ecf20Sopenharmony_ci .scan_index = ADIS16350_SCAN_TEMP_X, \ 8018c2ecf20Sopenharmony_ci .scan_type = { \ 8028c2ecf20Sopenharmony_ci .sign = 's', \ 8038c2ecf20Sopenharmony_ci .realbits = (bits), \ 8048c2ecf20Sopenharmony_ci .storagebits = 16, \ 8058c2ecf20Sopenharmony_ci .shift = 0, \ 8068c2ecf20Sopenharmony_ci .endianness = IIO_BE, \ 8078c2ecf20Sopenharmony_ci }, \ 8088c2ecf20Sopenharmony_ci} 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci#define ADIS16400_INCLI_CHAN(mod, addr, bits) { \ 8118c2ecf20Sopenharmony_ci .type = IIO_INCLI, \ 8128c2ecf20Sopenharmony_ci .modified = 1, \ 8138c2ecf20Sopenharmony_ci .channel2 = IIO_MOD_ ## mod, \ 8148c2ecf20Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 8158c2ecf20Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 8168c2ecf20Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 8178c2ecf20Sopenharmony_ci .address = (addr), \ 8188c2ecf20Sopenharmony_ci .scan_index = ADIS16300_SCAN_INCLI_ ## mod, \ 8198c2ecf20Sopenharmony_ci .scan_type = { \ 8208c2ecf20Sopenharmony_ci .sign = 's', \ 8218c2ecf20Sopenharmony_ci .realbits = (bits), \ 8228c2ecf20Sopenharmony_ci .storagebits = 16, \ 8238c2ecf20Sopenharmony_ci .shift = 0, \ 8248c2ecf20Sopenharmony_ci .endianness = IIO_BE, \ 8258c2ecf20Sopenharmony_ci }, \ 8268c2ecf20Sopenharmony_ci} 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_cistatic const struct iio_chan_spec adis16400_channels[] = { 8298c2ecf20Sopenharmony_ci ADIS16400_SUPPLY_CHAN(ADIS16400_SUPPLY_OUT, 14), 8308c2ecf20Sopenharmony_ci ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 14), 8318c2ecf20Sopenharmony_ci ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 14), 8328c2ecf20Sopenharmony_ci ADIS16400_GYRO_CHAN(Z, ADIS16400_ZGYRO_OUT, 14), 8338c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 14), 8348c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 14), 8358c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 14), 8368c2ecf20Sopenharmony_ci ADIS16400_MAGN_CHAN(X, ADIS16400_XMAGN_OUT, 14), 8378c2ecf20Sopenharmony_ci ADIS16400_MAGN_CHAN(Y, ADIS16400_YMAGN_OUT, 14), 8388c2ecf20Sopenharmony_ci ADIS16400_MAGN_CHAN(Z, ADIS16400_ZMAGN_OUT, 14), 8398c2ecf20Sopenharmony_ci ADIS16400_TEMP_CHAN(ADIS16400_TEMP_OUT, 12), 8408c2ecf20Sopenharmony_ci ADIS16400_AUX_ADC_CHAN(ADIS16400_AUX_ADC, 12), 8418c2ecf20Sopenharmony_ci IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP), 8428c2ecf20Sopenharmony_ci}; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_cistatic const struct iio_chan_spec adis16445_channels[] = { 8458c2ecf20Sopenharmony_ci ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 16), 8468c2ecf20Sopenharmony_ci ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 16), 8478c2ecf20Sopenharmony_ci ADIS16400_GYRO_CHAN(Z, ADIS16400_ZGYRO_OUT, 16), 8488c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 16), 8498c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 16), 8508c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 16), 8518c2ecf20Sopenharmony_ci ADIS16400_TEMP_CHAN(ADIS16448_TEMP_OUT, 12), 8528c2ecf20Sopenharmony_ci IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP), 8538c2ecf20Sopenharmony_ci}; 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_cistatic const struct iio_chan_spec adis16448_channels[] = { 8568c2ecf20Sopenharmony_ci ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 16), 8578c2ecf20Sopenharmony_ci ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 16), 8588c2ecf20Sopenharmony_ci ADIS16400_GYRO_CHAN(Z, ADIS16400_ZGYRO_OUT, 16), 8598c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 16), 8608c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 16), 8618c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 16), 8628c2ecf20Sopenharmony_ci ADIS16400_MAGN_CHAN(X, ADIS16400_XMAGN_OUT, 16), 8638c2ecf20Sopenharmony_ci ADIS16400_MAGN_CHAN(Y, ADIS16400_YMAGN_OUT, 16), 8648c2ecf20Sopenharmony_ci ADIS16400_MAGN_CHAN(Z, ADIS16400_ZMAGN_OUT, 16), 8658c2ecf20Sopenharmony_ci { 8668c2ecf20Sopenharmony_ci .type = IIO_PRESSURE, 8678c2ecf20Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 8688c2ecf20Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), 8698c2ecf20Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), 8708c2ecf20Sopenharmony_ci .address = ADIS16448_BARO_OUT, 8718c2ecf20Sopenharmony_ci .scan_index = ADIS16400_SCAN_BARO, 8728c2ecf20Sopenharmony_ci .scan_type = { 8738c2ecf20Sopenharmony_ci .sign = 's', 8748c2ecf20Sopenharmony_ci .realbits = 16, 8758c2ecf20Sopenharmony_ci .storagebits = 16, 8768c2ecf20Sopenharmony_ci .endianness = IIO_BE, 8778c2ecf20Sopenharmony_ci }, 8788c2ecf20Sopenharmony_ci }, 8798c2ecf20Sopenharmony_ci ADIS16400_TEMP_CHAN(ADIS16448_TEMP_OUT, 12), 8808c2ecf20Sopenharmony_ci IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP), 8818c2ecf20Sopenharmony_ci}; 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_cistatic const struct iio_chan_spec adis16350_channels[] = { 8848c2ecf20Sopenharmony_ci ADIS16400_SUPPLY_CHAN(ADIS16400_SUPPLY_OUT, 12), 8858c2ecf20Sopenharmony_ci ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 14), 8868c2ecf20Sopenharmony_ci ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 14), 8878c2ecf20Sopenharmony_ci ADIS16400_GYRO_CHAN(Z, ADIS16400_ZGYRO_OUT, 14), 8888c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 14), 8898c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 14), 8908c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 14), 8918c2ecf20Sopenharmony_ci ADIS16400_MAGN_CHAN(X, ADIS16400_XMAGN_OUT, 14), 8928c2ecf20Sopenharmony_ci ADIS16400_MAGN_CHAN(Y, ADIS16400_YMAGN_OUT, 14), 8938c2ecf20Sopenharmony_ci ADIS16400_MAGN_CHAN(Z, ADIS16400_ZMAGN_OUT, 14), 8948c2ecf20Sopenharmony_ci ADIS16400_AUX_ADC_CHAN(ADIS16300_AUX_ADC, 12), 8958c2ecf20Sopenharmony_ci ADIS16400_MOD_TEMP_CHAN(X, ADIS16350_XTEMP_OUT, 12), 8968c2ecf20Sopenharmony_ci ADIS16400_MOD_TEMP_CHAN(Y, ADIS16350_YTEMP_OUT, 12), 8978c2ecf20Sopenharmony_ci ADIS16400_MOD_TEMP_CHAN(Z, ADIS16350_ZTEMP_OUT, 12), 8988c2ecf20Sopenharmony_ci IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP), 8998c2ecf20Sopenharmony_ci}; 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_cistatic const struct iio_chan_spec adis16300_channels[] = { 9028c2ecf20Sopenharmony_ci ADIS16400_SUPPLY_CHAN(ADIS16400_SUPPLY_OUT, 12), 9038c2ecf20Sopenharmony_ci ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 14), 9048c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 14), 9058c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 14), 9068c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 14), 9078c2ecf20Sopenharmony_ci ADIS16400_TEMP_CHAN(ADIS16350_XTEMP_OUT, 12), 9088c2ecf20Sopenharmony_ci ADIS16400_AUX_ADC_CHAN(ADIS16300_AUX_ADC, 12), 9098c2ecf20Sopenharmony_ci ADIS16400_INCLI_CHAN(X, ADIS16300_PITCH_OUT, 13), 9108c2ecf20Sopenharmony_ci ADIS16400_INCLI_CHAN(Y, ADIS16300_ROLL_OUT, 13), 9118c2ecf20Sopenharmony_ci IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP), 9128c2ecf20Sopenharmony_ci}; 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_cistatic const struct iio_chan_spec adis16334_channels[] = { 9158c2ecf20Sopenharmony_ci ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 14), 9168c2ecf20Sopenharmony_ci ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 14), 9178c2ecf20Sopenharmony_ci ADIS16400_GYRO_CHAN(Z, ADIS16400_ZGYRO_OUT, 14), 9188c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 14), 9198c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 14), 9208c2ecf20Sopenharmony_ci ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 14), 9218c2ecf20Sopenharmony_ci ADIS16400_TEMP_CHAN(ADIS16350_XTEMP_OUT, 12), 9228c2ecf20Sopenharmony_ci IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP), 9238c2ecf20Sopenharmony_ci}; 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_cistatic const char * const adis16400_status_error_msgs[] = { 9268c2ecf20Sopenharmony_ci [ADIS16400_DIAG_STAT_ZACCL_FAIL] = "Z-axis accelerometer self-test failure", 9278c2ecf20Sopenharmony_ci [ADIS16400_DIAG_STAT_YACCL_FAIL] = "Y-axis accelerometer self-test failure", 9288c2ecf20Sopenharmony_ci [ADIS16400_DIAG_STAT_XACCL_FAIL] = "X-axis accelerometer self-test failure", 9298c2ecf20Sopenharmony_ci [ADIS16400_DIAG_STAT_XGYRO_FAIL] = "X-axis gyroscope self-test failure", 9308c2ecf20Sopenharmony_ci [ADIS16400_DIAG_STAT_YGYRO_FAIL] = "Y-axis gyroscope self-test failure", 9318c2ecf20Sopenharmony_ci [ADIS16400_DIAG_STAT_ZGYRO_FAIL] = "Z-axis gyroscope self-test failure", 9328c2ecf20Sopenharmony_ci [ADIS16400_DIAG_STAT_ALARM2] = "Alarm 2 active", 9338c2ecf20Sopenharmony_ci [ADIS16400_DIAG_STAT_ALARM1] = "Alarm 1 active", 9348c2ecf20Sopenharmony_ci [ADIS16400_DIAG_STAT_FLASH_CHK] = "Flash checksum error", 9358c2ecf20Sopenharmony_ci [ADIS16400_DIAG_STAT_SELF_TEST] = "Self test error", 9368c2ecf20Sopenharmony_ci [ADIS16400_DIAG_STAT_OVERFLOW] = "Sensor overrange", 9378c2ecf20Sopenharmony_ci [ADIS16400_DIAG_STAT_SPI_FAIL] = "SPI failure", 9388c2ecf20Sopenharmony_ci [ADIS16400_DIAG_STAT_FLASH_UPT] = "Flash update failed", 9398c2ecf20Sopenharmony_ci [ADIS16400_DIAG_STAT_POWER_HIGH] = "Power supply above 5.25V", 9408c2ecf20Sopenharmony_ci [ADIS16400_DIAG_STAT_POWER_LOW] = "Power supply below 4.75V", 9418c2ecf20Sopenharmony_ci}; 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci#define ADIS16400_DATA(_timeouts, _burst_len) \ 9448c2ecf20Sopenharmony_ci{ \ 9458c2ecf20Sopenharmony_ci .msc_ctrl_reg = ADIS16400_MSC_CTRL, \ 9468c2ecf20Sopenharmony_ci .glob_cmd_reg = ADIS16400_GLOB_CMD, \ 9478c2ecf20Sopenharmony_ci .diag_stat_reg = ADIS16400_DIAG_STAT, \ 9488c2ecf20Sopenharmony_ci .read_delay = 50, \ 9498c2ecf20Sopenharmony_ci .write_delay = 50, \ 9508c2ecf20Sopenharmony_ci .self_test_mask = ADIS16400_MSC_CTRL_MEM_TEST, \ 9518c2ecf20Sopenharmony_ci .self_test_reg = ADIS16400_MSC_CTRL, \ 9528c2ecf20Sopenharmony_ci .status_error_msgs = adis16400_status_error_msgs, \ 9538c2ecf20Sopenharmony_ci .status_error_mask = BIT(ADIS16400_DIAG_STAT_ZACCL_FAIL) | \ 9548c2ecf20Sopenharmony_ci BIT(ADIS16400_DIAG_STAT_YACCL_FAIL) | \ 9558c2ecf20Sopenharmony_ci BIT(ADIS16400_DIAG_STAT_XACCL_FAIL) | \ 9568c2ecf20Sopenharmony_ci BIT(ADIS16400_DIAG_STAT_XGYRO_FAIL) | \ 9578c2ecf20Sopenharmony_ci BIT(ADIS16400_DIAG_STAT_YGYRO_FAIL) | \ 9588c2ecf20Sopenharmony_ci BIT(ADIS16400_DIAG_STAT_ZGYRO_FAIL) | \ 9598c2ecf20Sopenharmony_ci BIT(ADIS16400_DIAG_STAT_ALARM2) | \ 9608c2ecf20Sopenharmony_ci BIT(ADIS16400_DIAG_STAT_ALARM1) | \ 9618c2ecf20Sopenharmony_ci BIT(ADIS16400_DIAG_STAT_FLASH_CHK) | \ 9628c2ecf20Sopenharmony_ci BIT(ADIS16400_DIAG_STAT_SELF_TEST) | \ 9638c2ecf20Sopenharmony_ci BIT(ADIS16400_DIAG_STAT_OVERFLOW) | \ 9648c2ecf20Sopenharmony_ci BIT(ADIS16400_DIAG_STAT_SPI_FAIL) | \ 9658c2ecf20Sopenharmony_ci BIT(ADIS16400_DIAG_STAT_FLASH_UPT) | \ 9668c2ecf20Sopenharmony_ci BIT(ADIS16400_DIAG_STAT_POWER_HIGH) | \ 9678c2ecf20Sopenharmony_ci BIT(ADIS16400_DIAG_STAT_POWER_LOW), \ 9688c2ecf20Sopenharmony_ci .timeouts = (_timeouts), \ 9698c2ecf20Sopenharmony_ci .burst_reg_cmd = ADIS16400_GLOB_CMD, \ 9708c2ecf20Sopenharmony_ci .burst_len = (_burst_len) \ 9718c2ecf20Sopenharmony_ci} 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_cistatic const struct adis_timeout adis16300_timeouts = { 9748c2ecf20Sopenharmony_ci .reset_ms = ADIS16400_STARTUP_DELAY, 9758c2ecf20Sopenharmony_ci .sw_reset_ms = ADIS16400_STARTUP_DELAY, 9768c2ecf20Sopenharmony_ci .self_test_ms = ADIS16400_STARTUP_DELAY, 9778c2ecf20Sopenharmony_ci}; 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_cistatic const struct adis_timeout adis16334_timeouts = { 9808c2ecf20Sopenharmony_ci .reset_ms = 60, 9818c2ecf20Sopenharmony_ci .sw_reset_ms = 60, 9828c2ecf20Sopenharmony_ci .self_test_ms = 14, 9838c2ecf20Sopenharmony_ci}; 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_cistatic const struct adis_timeout adis16362_timeouts = { 9868c2ecf20Sopenharmony_ci .reset_ms = 130, 9878c2ecf20Sopenharmony_ci .sw_reset_ms = 130, 9888c2ecf20Sopenharmony_ci .self_test_ms = 12, 9898c2ecf20Sopenharmony_ci}; 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_cistatic const struct adis_timeout adis16400_timeouts = { 9928c2ecf20Sopenharmony_ci .reset_ms = 170, 9938c2ecf20Sopenharmony_ci .sw_reset_ms = 170, 9948c2ecf20Sopenharmony_ci .self_test_ms = 12, 9958c2ecf20Sopenharmony_ci}; 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_cistatic const struct adis_timeout adis16445_timeouts = { 9988c2ecf20Sopenharmony_ci .reset_ms = 55, 9998c2ecf20Sopenharmony_ci .sw_reset_ms = 55, 10008c2ecf20Sopenharmony_ci .self_test_ms = 16, 10018c2ecf20Sopenharmony_ci}; 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_cistatic const struct adis_timeout adis16448_timeouts = { 10048c2ecf20Sopenharmony_ci .reset_ms = 90, 10058c2ecf20Sopenharmony_ci .sw_reset_ms = 90, 10068c2ecf20Sopenharmony_ci .self_test_ms = 45, 10078c2ecf20Sopenharmony_ci}; 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_cistatic struct adis16400_chip_info adis16400_chips[] = { 10108c2ecf20Sopenharmony_ci [ADIS16300] = { 10118c2ecf20Sopenharmony_ci .channels = adis16300_channels, 10128c2ecf20Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16300_channels), 10138c2ecf20Sopenharmony_ci .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE | 10148c2ecf20Sopenharmony_ci ADIS16400_HAS_SERIAL_NUMBER, 10158c2ecf20Sopenharmony_ci .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ 10168c2ecf20Sopenharmony_ci .accel_scale_micro = 5884, 10178c2ecf20Sopenharmony_ci .temp_scale_nano = 140000000, /* 0.14 C */ 10188c2ecf20Sopenharmony_ci .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ 10198c2ecf20Sopenharmony_ci .set_freq = adis16400_set_freq, 10208c2ecf20Sopenharmony_ci .get_freq = adis16400_get_freq, 10218c2ecf20Sopenharmony_ci .adis_data = ADIS16400_DATA(&adis16300_timeouts, 18), 10228c2ecf20Sopenharmony_ci }, 10238c2ecf20Sopenharmony_ci [ADIS16334] = { 10248c2ecf20Sopenharmony_ci .channels = adis16334_channels, 10258c2ecf20Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16334_channels), 10268c2ecf20Sopenharmony_ci .flags = ADIS16400_HAS_PROD_ID | ADIS16400_NO_BURST | 10278c2ecf20Sopenharmony_ci ADIS16400_HAS_SERIAL_NUMBER, 10288c2ecf20Sopenharmony_ci .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ 10298c2ecf20Sopenharmony_ci .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ 10308c2ecf20Sopenharmony_ci .temp_scale_nano = 67850000, /* 0.06785 C */ 10318c2ecf20Sopenharmony_ci .temp_offset = 25000000 / 67850, /* 25 C = 0x00 */ 10328c2ecf20Sopenharmony_ci .set_freq = adis16334_set_freq, 10338c2ecf20Sopenharmony_ci .get_freq = adis16334_get_freq, 10348c2ecf20Sopenharmony_ci .adis_data = ADIS16400_DATA(&adis16334_timeouts, 0), 10358c2ecf20Sopenharmony_ci }, 10368c2ecf20Sopenharmony_ci [ADIS16350] = { 10378c2ecf20Sopenharmony_ci .channels = adis16350_channels, 10388c2ecf20Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16350_channels), 10398c2ecf20Sopenharmony_ci .gyro_scale_micro = IIO_DEGREE_TO_RAD(73260), /* 0.07326 deg/s */ 10408c2ecf20Sopenharmony_ci .accel_scale_micro = IIO_G_TO_M_S_2(2522), /* 0.002522 g */ 10418c2ecf20Sopenharmony_ci .temp_scale_nano = 145300000, /* 0.1453 C */ 10428c2ecf20Sopenharmony_ci .temp_offset = 25000000 / 145300, /* 25 C = 0x00 */ 10438c2ecf20Sopenharmony_ci .flags = ADIS16400_NO_BURST | ADIS16400_HAS_SLOW_MODE, 10448c2ecf20Sopenharmony_ci .set_freq = adis16400_set_freq, 10458c2ecf20Sopenharmony_ci .get_freq = adis16400_get_freq, 10468c2ecf20Sopenharmony_ci .adis_data = ADIS16400_DATA(&adis16300_timeouts, 0), 10478c2ecf20Sopenharmony_ci }, 10488c2ecf20Sopenharmony_ci [ADIS16360] = { 10498c2ecf20Sopenharmony_ci .channels = adis16350_channels, 10508c2ecf20Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16350_channels), 10518c2ecf20Sopenharmony_ci .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE | 10528c2ecf20Sopenharmony_ci ADIS16400_HAS_SERIAL_NUMBER, 10538c2ecf20Sopenharmony_ci .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ 10548c2ecf20Sopenharmony_ci .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */ 10558c2ecf20Sopenharmony_ci .temp_scale_nano = 136000000, /* 0.136 C */ 10568c2ecf20Sopenharmony_ci .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ 10578c2ecf20Sopenharmony_ci .set_freq = adis16400_set_freq, 10588c2ecf20Sopenharmony_ci .get_freq = adis16400_get_freq, 10598c2ecf20Sopenharmony_ci .adis_data = ADIS16400_DATA(&adis16300_timeouts, 28), 10608c2ecf20Sopenharmony_ci }, 10618c2ecf20Sopenharmony_ci [ADIS16362] = { 10628c2ecf20Sopenharmony_ci .channels = adis16350_channels, 10638c2ecf20Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16350_channels), 10648c2ecf20Sopenharmony_ci .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE | 10658c2ecf20Sopenharmony_ci ADIS16400_HAS_SERIAL_NUMBER, 10668c2ecf20Sopenharmony_ci .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ 10678c2ecf20Sopenharmony_ci .accel_scale_micro = IIO_G_TO_M_S_2(333), /* 0.333 mg */ 10688c2ecf20Sopenharmony_ci .temp_scale_nano = 136000000, /* 0.136 C */ 10698c2ecf20Sopenharmony_ci .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ 10708c2ecf20Sopenharmony_ci .set_freq = adis16400_set_freq, 10718c2ecf20Sopenharmony_ci .get_freq = adis16400_get_freq, 10728c2ecf20Sopenharmony_ci .adis_data = ADIS16400_DATA(&adis16362_timeouts, 28), 10738c2ecf20Sopenharmony_ci }, 10748c2ecf20Sopenharmony_ci [ADIS16364] = { 10758c2ecf20Sopenharmony_ci .channels = adis16350_channels, 10768c2ecf20Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16350_channels), 10778c2ecf20Sopenharmony_ci .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE | 10788c2ecf20Sopenharmony_ci ADIS16400_HAS_SERIAL_NUMBER, 10798c2ecf20Sopenharmony_ci .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ 10808c2ecf20Sopenharmony_ci .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ 10818c2ecf20Sopenharmony_ci .temp_scale_nano = 136000000, /* 0.136 C */ 10828c2ecf20Sopenharmony_ci .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ 10838c2ecf20Sopenharmony_ci .set_freq = adis16400_set_freq, 10848c2ecf20Sopenharmony_ci .get_freq = adis16400_get_freq, 10858c2ecf20Sopenharmony_ci .adis_data = ADIS16400_DATA(&adis16362_timeouts, 28), 10868c2ecf20Sopenharmony_ci }, 10878c2ecf20Sopenharmony_ci [ADIS16367] = { 10888c2ecf20Sopenharmony_ci .channels = adis16350_channels, 10898c2ecf20Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16350_channels), 10908c2ecf20Sopenharmony_ci .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE | 10918c2ecf20Sopenharmony_ci ADIS16400_HAS_SERIAL_NUMBER, 10928c2ecf20Sopenharmony_ci .gyro_scale_micro = IIO_DEGREE_TO_RAD(2000), /* 0.2 deg/s */ 10938c2ecf20Sopenharmony_ci .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */ 10948c2ecf20Sopenharmony_ci .temp_scale_nano = 136000000, /* 0.136 C */ 10958c2ecf20Sopenharmony_ci .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ 10968c2ecf20Sopenharmony_ci .set_freq = adis16400_set_freq, 10978c2ecf20Sopenharmony_ci .get_freq = adis16400_get_freq, 10988c2ecf20Sopenharmony_ci .adis_data = ADIS16400_DATA(&adis16300_timeouts, 28), 10998c2ecf20Sopenharmony_ci }, 11008c2ecf20Sopenharmony_ci [ADIS16400] = { 11018c2ecf20Sopenharmony_ci .channels = adis16400_channels, 11028c2ecf20Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16400_channels), 11038c2ecf20Sopenharmony_ci .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE, 11048c2ecf20Sopenharmony_ci .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ 11058c2ecf20Sopenharmony_ci .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */ 11068c2ecf20Sopenharmony_ci .temp_scale_nano = 140000000, /* 0.14 C */ 11078c2ecf20Sopenharmony_ci .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ 11088c2ecf20Sopenharmony_ci .set_freq = adis16400_set_freq, 11098c2ecf20Sopenharmony_ci .get_freq = adis16400_get_freq, 11108c2ecf20Sopenharmony_ci .adis_data = ADIS16400_DATA(&adis16400_timeouts, 24), 11118c2ecf20Sopenharmony_ci }, 11128c2ecf20Sopenharmony_ci [ADIS16445] = { 11138c2ecf20Sopenharmony_ci .channels = adis16445_channels, 11148c2ecf20Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16445_channels), 11158c2ecf20Sopenharmony_ci .flags = ADIS16400_HAS_PROD_ID | 11168c2ecf20Sopenharmony_ci ADIS16400_HAS_SERIAL_NUMBER | 11178c2ecf20Sopenharmony_ci ADIS16400_BURST_DIAG_STAT, 11188c2ecf20Sopenharmony_ci .gyro_scale_micro = IIO_DEGREE_TO_RAD(10000), /* 0.01 deg/s */ 11198c2ecf20Sopenharmony_ci .accel_scale_micro = IIO_G_TO_M_S_2(250), /* 1/4000 g */ 11208c2ecf20Sopenharmony_ci .temp_scale_nano = 73860000, /* 0.07386 C */ 11218c2ecf20Sopenharmony_ci .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */ 11228c2ecf20Sopenharmony_ci .set_freq = adis16334_set_freq, 11238c2ecf20Sopenharmony_ci .get_freq = adis16334_get_freq, 11248c2ecf20Sopenharmony_ci .adis_data = ADIS16400_DATA(&adis16445_timeouts, 16), 11258c2ecf20Sopenharmony_ci }, 11268c2ecf20Sopenharmony_ci [ADIS16448] = { 11278c2ecf20Sopenharmony_ci .channels = adis16448_channels, 11288c2ecf20Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16448_channels), 11298c2ecf20Sopenharmony_ci .flags = ADIS16400_HAS_PROD_ID | 11308c2ecf20Sopenharmony_ci ADIS16400_HAS_SERIAL_NUMBER | 11318c2ecf20Sopenharmony_ci ADIS16400_BURST_DIAG_STAT, 11328c2ecf20Sopenharmony_ci .gyro_scale_micro = IIO_DEGREE_TO_RAD(40000), /* 0.04 deg/s */ 11338c2ecf20Sopenharmony_ci .accel_scale_micro = IIO_G_TO_M_S_2(833), /* 1/1200 g */ 11348c2ecf20Sopenharmony_ci .temp_scale_nano = 73860000, /* 0.07386 C */ 11358c2ecf20Sopenharmony_ci .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */ 11368c2ecf20Sopenharmony_ci .set_freq = adis16334_set_freq, 11378c2ecf20Sopenharmony_ci .get_freq = adis16334_get_freq, 11388c2ecf20Sopenharmony_ci .adis_data = ADIS16400_DATA(&adis16448_timeouts, 24), 11398c2ecf20Sopenharmony_ci } 11408c2ecf20Sopenharmony_ci}; 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_cistatic const struct iio_info adis16400_info = { 11438c2ecf20Sopenharmony_ci .read_raw = &adis16400_read_raw, 11448c2ecf20Sopenharmony_ci .write_raw = &adis16400_write_raw, 11458c2ecf20Sopenharmony_ci .update_scan_mode = adis_update_scan_mode, 11468c2ecf20Sopenharmony_ci .debugfs_reg_access = adis_debugfs_reg_access, 11478c2ecf20Sopenharmony_ci}; 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_cistatic void adis16400_setup_chan_mask(struct adis16400_state *st) 11508c2ecf20Sopenharmony_ci{ 11518c2ecf20Sopenharmony_ci const struct adis16400_chip_info *chip_info = st->variant; 11528c2ecf20Sopenharmony_ci unsigned int i; 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci for (i = 0; i < chip_info->num_channels; i++) { 11558c2ecf20Sopenharmony_ci const struct iio_chan_spec *ch = &chip_info->channels[i]; 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci if (ch->scan_index >= 0 && 11588c2ecf20Sopenharmony_ci ch->scan_index != ADIS16400_SCAN_TIMESTAMP) 11598c2ecf20Sopenharmony_ci st->avail_scan_mask[0] |= BIT(ch->scan_index); 11608c2ecf20Sopenharmony_ci } 11618c2ecf20Sopenharmony_ci} 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_cistatic void adis16400_stop(void *data) 11648c2ecf20Sopenharmony_ci{ 11658c2ecf20Sopenharmony_ci adis16400_stop_device(data); 11668c2ecf20Sopenharmony_ci} 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_cistatic int adis16400_probe(struct spi_device *spi) 11698c2ecf20Sopenharmony_ci{ 11708c2ecf20Sopenharmony_ci struct adis16400_state *st; 11718c2ecf20Sopenharmony_ci struct iio_dev *indio_dev; 11728c2ecf20Sopenharmony_ci int ret; 11738c2ecf20Sopenharmony_ci const struct adis_data *adis16400_data; 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 11768c2ecf20Sopenharmony_ci if (indio_dev == NULL) 11778c2ecf20Sopenharmony_ci return -ENOMEM; 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci st = iio_priv(indio_dev); 11808c2ecf20Sopenharmony_ci /* this is only used for removal purposes */ 11818c2ecf20Sopenharmony_ci spi_set_drvdata(spi, indio_dev); 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci /* setup the industrialio driver allocated elements */ 11848c2ecf20Sopenharmony_ci st->variant = &adis16400_chips[spi_get_device_id(spi)->driver_data]; 11858c2ecf20Sopenharmony_ci indio_dev->name = spi_get_device_id(spi)->name; 11868c2ecf20Sopenharmony_ci indio_dev->channels = st->variant->channels; 11878c2ecf20Sopenharmony_ci indio_dev->num_channels = st->variant->num_channels; 11888c2ecf20Sopenharmony_ci indio_dev->info = &adis16400_info; 11898c2ecf20Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ci if (!(st->variant->flags & ADIS16400_NO_BURST)) { 11928c2ecf20Sopenharmony_ci adis16400_setup_chan_mask(st); 11938c2ecf20Sopenharmony_ci indio_dev->available_scan_masks = st->avail_scan_mask; 11948c2ecf20Sopenharmony_ci } 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci adis16400_data = &st->variant->adis_data; 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ci ret = adis_init(&st->adis, indio_dev, spi, adis16400_data); 11998c2ecf20Sopenharmony_ci if (ret) 12008c2ecf20Sopenharmony_ci return ret; 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, adis16400_trigger_handler); 12038c2ecf20Sopenharmony_ci if (ret) 12048c2ecf20Sopenharmony_ci return ret; 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci /* Get the device into a sane initial state */ 12078c2ecf20Sopenharmony_ci ret = adis16400_initial_setup(indio_dev); 12088c2ecf20Sopenharmony_ci if (ret) 12098c2ecf20Sopenharmony_ci return ret; 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci ret = devm_add_action_or_reset(&spi->dev, adis16400_stop, indio_dev); 12128c2ecf20Sopenharmony_ci if (ret) 12138c2ecf20Sopenharmony_ci return ret; 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci ret = devm_iio_device_register(&spi->dev, indio_dev); 12168c2ecf20Sopenharmony_ci if (ret) 12178c2ecf20Sopenharmony_ci return ret; 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_ci adis16400_debugfs_init(indio_dev); 12208c2ecf20Sopenharmony_ci return 0; 12218c2ecf20Sopenharmony_ci} 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_cistatic const struct spi_device_id adis16400_id[] = { 12248c2ecf20Sopenharmony_ci {"adis16300", ADIS16300}, 12258c2ecf20Sopenharmony_ci {"adis16305", ADIS16300}, 12268c2ecf20Sopenharmony_ci {"adis16334", ADIS16334}, 12278c2ecf20Sopenharmony_ci {"adis16350", ADIS16350}, 12288c2ecf20Sopenharmony_ci {"adis16354", ADIS16350}, 12298c2ecf20Sopenharmony_ci {"adis16355", ADIS16350}, 12308c2ecf20Sopenharmony_ci {"adis16360", ADIS16360}, 12318c2ecf20Sopenharmony_ci {"adis16362", ADIS16362}, 12328c2ecf20Sopenharmony_ci {"adis16364", ADIS16364}, 12338c2ecf20Sopenharmony_ci {"adis16365", ADIS16360}, 12348c2ecf20Sopenharmony_ci {"adis16367", ADIS16367}, 12358c2ecf20Sopenharmony_ci {"adis16400", ADIS16400}, 12368c2ecf20Sopenharmony_ci {"adis16405", ADIS16400}, 12378c2ecf20Sopenharmony_ci {"adis16445", ADIS16445}, 12388c2ecf20Sopenharmony_ci {"adis16448", ADIS16448}, 12398c2ecf20Sopenharmony_ci {} 12408c2ecf20Sopenharmony_ci}; 12418c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(spi, adis16400_id); 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_cistatic struct spi_driver adis16400_driver = { 12448c2ecf20Sopenharmony_ci .driver = { 12458c2ecf20Sopenharmony_ci .name = "adis16400", 12468c2ecf20Sopenharmony_ci }, 12478c2ecf20Sopenharmony_ci .id_table = adis16400_id, 12488c2ecf20Sopenharmony_ci .probe = adis16400_probe, 12498c2ecf20Sopenharmony_ci}; 12508c2ecf20Sopenharmony_cimodule_spi_driver(adis16400_driver); 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ciMODULE_AUTHOR("Manuel Stahl <manuel.stahl@iis.fraunhofer.de>"); 12538c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices ADIS16400/5 IMU SPI driver"); 12548c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 12558c2ecf20Sopenharmony_ciMODULE_IMPORT_NS(IIO_ADISLIB); 1256