xref: /openbmc/linux/drivers/iio/imu/adis16400.c (revision 0183f81f)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
25447e3f1SAlexandru Ardelean /*
35447e3f1SAlexandru Ardelean  * adis16400.c	support Analog Devices ADIS16400/5
45447e3f1SAlexandru Ardelean  *		3d 2g Linear Accelerometers,
55447e3f1SAlexandru Ardelean  *		3d Gyroscopes,
65447e3f1SAlexandru Ardelean  *		3d Magnetometers via SPI
75447e3f1SAlexandru Ardelean  *
85447e3f1SAlexandru Ardelean  * Copyright (c) 2009 Manuel Stahl <manuel.stahl@iis.fraunhofer.de>
95447e3f1SAlexandru Ardelean  * Copyright (c) 2007 Jonathan Cameron <jic23@kernel.org>
105447e3f1SAlexandru Ardelean  * Copyright (c) 2011 Analog Devices Inc.
115447e3f1SAlexandru Ardelean  */
125447e3f1SAlexandru Ardelean 
135447e3f1SAlexandru Ardelean #include <linux/irq.h>
145447e3f1SAlexandru Ardelean #include <linux/device.h>
155447e3f1SAlexandru Ardelean #include <linux/kernel.h>
165447e3f1SAlexandru Ardelean #include <linux/spi/spi.h>
175447e3f1SAlexandru Ardelean #include <linux/module.h>
185447e3f1SAlexandru Ardelean #include <linux/debugfs.h>
195447e3f1SAlexandru Ardelean #include <linux/bitops.h>
205447e3f1SAlexandru Ardelean 
215447e3f1SAlexandru Ardelean #include <linux/iio/iio.h>
225447e3f1SAlexandru Ardelean #include <linux/iio/buffer.h>
235447e3f1SAlexandru Ardelean #include <linux/iio/trigger_consumer.h>
243cb51613SAlexandru Ardelean #include <linux/iio/imu/adis.h>
255447e3f1SAlexandru Ardelean 
263cb51613SAlexandru Ardelean #define ADIS16400_STARTUP_DELAY	290 /* ms */
273cb51613SAlexandru Ardelean #define ADIS16400_MTEST_DELAY 90 /* ms */
283cb51613SAlexandru Ardelean 
293cb51613SAlexandru Ardelean #define ADIS16400_FLASH_CNT  0x00 /* Flash memory write count */
303cb51613SAlexandru Ardelean #define ADIS16400_SUPPLY_OUT 0x02 /* Power supply measurement */
313cb51613SAlexandru Ardelean #define ADIS16400_XGYRO_OUT 0x04 /* X-axis gyroscope output */
323cb51613SAlexandru Ardelean #define ADIS16400_YGYRO_OUT 0x06 /* Y-axis gyroscope output */
333cb51613SAlexandru Ardelean #define ADIS16400_ZGYRO_OUT 0x08 /* Z-axis gyroscope output */
343cb51613SAlexandru Ardelean #define ADIS16400_XACCL_OUT 0x0A /* X-axis accelerometer output */
353cb51613SAlexandru Ardelean #define ADIS16400_YACCL_OUT 0x0C /* Y-axis accelerometer output */
363cb51613SAlexandru Ardelean #define ADIS16400_ZACCL_OUT 0x0E /* Z-axis accelerometer output */
373cb51613SAlexandru Ardelean #define ADIS16400_XMAGN_OUT 0x10 /* X-axis magnetometer measurement */
383cb51613SAlexandru Ardelean #define ADIS16400_YMAGN_OUT 0x12 /* Y-axis magnetometer measurement */
393cb51613SAlexandru Ardelean #define ADIS16400_ZMAGN_OUT 0x14 /* Z-axis magnetometer measurement */
403cb51613SAlexandru Ardelean #define ADIS16400_TEMP_OUT  0x16 /* Temperature output */
413cb51613SAlexandru Ardelean #define ADIS16400_AUX_ADC   0x18 /* Auxiliary ADC measurement */
423cb51613SAlexandru Ardelean 
433cb51613SAlexandru Ardelean #define ADIS16350_XTEMP_OUT 0x10 /* X-axis gyroscope temperature measurement */
443cb51613SAlexandru Ardelean #define ADIS16350_YTEMP_OUT 0x12 /* Y-axis gyroscope temperature measurement */
453cb51613SAlexandru Ardelean #define ADIS16350_ZTEMP_OUT 0x14 /* Z-axis gyroscope temperature measurement */
463cb51613SAlexandru Ardelean 
473cb51613SAlexandru Ardelean #define ADIS16300_PITCH_OUT 0x12 /* X axis inclinometer output measurement */
483cb51613SAlexandru Ardelean #define ADIS16300_ROLL_OUT  0x14 /* Y axis inclinometer output measurement */
493cb51613SAlexandru Ardelean #define ADIS16300_AUX_ADC   0x16 /* Auxiliary ADC measurement */
503cb51613SAlexandru Ardelean 
513cb51613SAlexandru Ardelean #define ADIS16448_BARO_OUT	0x16 /* Barometric pressure output */
523cb51613SAlexandru Ardelean #define ADIS16448_TEMP_OUT  0x18 /* Temperature output */
533cb51613SAlexandru Ardelean 
543cb51613SAlexandru Ardelean /* Calibration parameters */
553cb51613SAlexandru Ardelean #define ADIS16400_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */
563cb51613SAlexandru Ardelean #define ADIS16400_YGYRO_OFF 0x1C /* Y-axis gyroscope bias offset factor */
573cb51613SAlexandru Ardelean #define ADIS16400_ZGYRO_OFF 0x1E /* Z-axis gyroscope bias offset factor */
583cb51613SAlexandru Ardelean #define ADIS16400_XACCL_OFF 0x20 /* X-axis acceleration bias offset factor */
593cb51613SAlexandru Ardelean #define ADIS16400_YACCL_OFF 0x22 /* Y-axis acceleration bias offset factor */
603cb51613SAlexandru Ardelean #define ADIS16400_ZACCL_OFF 0x24 /* Z-axis acceleration bias offset factor */
613cb51613SAlexandru Ardelean #define ADIS16400_XMAGN_HIF 0x26 /* X-axis magnetometer, hard-iron factor */
623cb51613SAlexandru Ardelean #define ADIS16400_YMAGN_HIF 0x28 /* Y-axis magnetometer, hard-iron factor */
633cb51613SAlexandru Ardelean #define ADIS16400_ZMAGN_HIF 0x2A /* Z-axis magnetometer, hard-iron factor */
643cb51613SAlexandru Ardelean #define ADIS16400_XMAGN_SIF 0x2C /* X-axis magnetometer, soft-iron factor */
653cb51613SAlexandru Ardelean #define ADIS16400_YMAGN_SIF 0x2E /* Y-axis magnetometer, soft-iron factor */
663cb51613SAlexandru Ardelean #define ADIS16400_ZMAGN_SIF 0x30 /* Z-axis magnetometer, soft-iron factor */
673cb51613SAlexandru Ardelean 
683cb51613SAlexandru Ardelean #define ADIS16400_GPIO_CTRL 0x32 /* Auxiliary digital input/output control */
693cb51613SAlexandru Ardelean #define ADIS16400_MSC_CTRL  0x34 /* Miscellaneous control */
703cb51613SAlexandru Ardelean #define ADIS16400_SMPL_PRD  0x36 /* Internal sample period (rate) control */
713cb51613SAlexandru Ardelean #define ADIS16400_SENS_AVG  0x38 /* Dynamic range and digital filter control */
723cb51613SAlexandru Ardelean #define ADIS16400_SLP_CNT   0x3A /* Sleep mode control */
733cb51613SAlexandru Ardelean #define ADIS16400_DIAG_STAT 0x3C /* System status */
743cb51613SAlexandru Ardelean 
753cb51613SAlexandru Ardelean /* Alarm functions */
763cb51613SAlexandru Ardelean #define ADIS16400_GLOB_CMD  0x3E /* System command */
773cb51613SAlexandru Ardelean #define ADIS16400_ALM_MAG1  0x40 /* Alarm 1 amplitude threshold */
783cb51613SAlexandru Ardelean #define ADIS16400_ALM_MAG2  0x42 /* Alarm 2 amplitude threshold */
793cb51613SAlexandru Ardelean #define ADIS16400_ALM_SMPL1 0x44 /* Alarm 1 sample size */
803cb51613SAlexandru Ardelean #define ADIS16400_ALM_SMPL2 0x46 /* Alarm 2 sample size */
813cb51613SAlexandru Ardelean #define ADIS16400_ALM_CTRL  0x48 /* Alarm control */
823cb51613SAlexandru Ardelean #define ADIS16400_AUX_DAC   0x4A /* Auxiliary DAC data */
833cb51613SAlexandru Ardelean 
843cb51613SAlexandru Ardelean #define ADIS16334_LOT_ID1   0x52 /* Lot identification code 1 */
853cb51613SAlexandru Ardelean #define ADIS16334_LOT_ID2   0x54 /* Lot identification code 2 */
863cb51613SAlexandru Ardelean #define ADIS16400_PRODUCT_ID 0x56 /* Product identifier */
873cb51613SAlexandru Ardelean #define ADIS16334_SERIAL_NUMBER 0x58 /* Serial number, lot specific */
883cb51613SAlexandru Ardelean 
893cb51613SAlexandru Ardelean #define ADIS16400_ERROR_ACTIVE			(1<<14)
903cb51613SAlexandru Ardelean #define ADIS16400_NEW_DATA			(1<<14)
913cb51613SAlexandru Ardelean 
923cb51613SAlexandru Ardelean /* MSC_CTRL */
933cb51613SAlexandru Ardelean #define ADIS16400_MSC_CTRL_MEM_TEST		(1<<11)
943cb51613SAlexandru Ardelean #define ADIS16400_MSC_CTRL_INT_SELF_TEST	(1<<10)
953cb51613SAlexandru Ardelean #define ADIS16400_MSC_CTRL_NEG_SELF_TEST	(1<<9)
963cb51613SAlexandru Ardelean #define ADIS16400_MSC_CTRL_POS_SELF_TEST	(1<<8)
973cb51613SAlexandru Ardelean #define ADIS16400_MSC_CTRL_GYRO_BIAS		(1<<7)
983cb51613SAlexandru Ardelean #define ADIS16400_MSC_CTRL_ACCL_ALIGN		(1<<6)
993cb51613SAlexandru Ardelean #define ADIS16400_MSC_CTRL_DATA_RDY_EN		(1<<2)
1003cb51613SAlexandru Ardelean #define ADIS16400_MSC_CTRL_DATA_RDY_POL_HIGH	(1<<1)
1013cb51613SAlexandru Ardelean #define ADIS16400_MSC_CTRL_DATA_RDY_DIO2	(1<<0)
1023cb51613SAlexandru Ardelean 
1033cb51613SAlexandru Ardelean /* SMPL_PRD */
1043cb51613SAlexandru Ardelean #define ADIS16400_SMPL_PRD_TIME_BASE	(1<<7)
1053cb51613SAlexandru Ardelean #define ADIS16400_SMPL_PRD_DIV_MASK	0x7F
1063cb51613SAlexandru Ardelean 
1073cb51613SAlexandru Ardelean /* DIAG_STAT */
1083cb51613SAlexandru Ardelean #define ADIS16400_DIAG_STAT_ZACCL_FAIL	15
1093cb51613SAlexandru Ardelean #define ADIS16400_DIAG_STAT_YACCL_FAIL	14
1103cb51613SAlexandru Ardelean #define ADIS16400_DIAG_STAT_XACCL_FAIL	13
1113cb51613SAlexandru Ardelean #define ADIS16400_DIAG_STAT_XGYRO_FAIL	12
1123cb51613SAlexandru Ardelean #define ADIS16400_DIAG_STAT_YGYRO_FAIL	11
1133cb51613SAlexandru Ardelean #define ADIS16400_DIAG_STAT_ZGYRO_FAIL	10
1143cb51613SAlexandru Ardelean #define ADIS16400_DIAG_STAT_ALARM2	9
1153cb51613SAlexandru Ardelean #define ADIS16400_DIAG_STAT_ALARM1	8
1163cb51613SAlexandru Ardelean #define ADIS16400_DIAG_STAT_FLASH_CHK	6
1173cb51613SAlexandru Ardelean #define ADIS16400_DIAG_STAT_SELF_TEST	5
1183cb51613SAlexandru Ardelean #define ADIS16400_DIAG_STAT_OVERFLOW	4
1193cb51613SAlexandru Ardelean #define ADIS16400_DIAG_STAT_SPI_FAIL	3
1203cb51613SAlexandru Ardelean #define ADIS16400_DIAG_STAT_FLASH_UPT	2
1213cb51613SAlexandru Ardelean #define ADIS16400_DIAG_STAT_POWER_HIGH	1
1223cb51613SAlexandru Ardelean #define ADIS16400_DIAG_STAT_POWER_LOW	0
1233cb51613SAlexandru Ardelean 
1243cb51613SAlexandru Ardelean /* GLOB_CMD */
1253cb51613SAlexandru Ardelean #define ADIS16400_GLOB_CMD_SW_RESET	(1<<7)
1263cb51613SAlexandru Ardelean #define ADIS16400_GLOB_CMD_P_AUTO_NULL	(1<<4)
1273cb51613SAlexandru Ardelean #define ADIS16400_GLOB_CMD_FLASH_UPD	(1<<3)
1283cb51613SAlexandru Ardelean #define ADIS16400_GLOB_CMD_DAC_LATCH	(1<<2)
1293cb51613SAlexandru Ardelean #define ADIS16400_GLOB_CMD_FAC_CALIB	(1<<1)
1303cb51613SAlexandru Ardelean #define ADIS16400_GLOB_CMD_AUTO_NULL	(1<<0)
1313cb51613SAlexandru Ardelean 
1323cb51613SAlexandru Ardelean /* SLP_CNT */
1333cb51613SAlexandru Ardelean #define ADIS16400_SLP_CNT_POWER_OFF	(1<<8)
1343cb51613SAlexandru Ardelean 
1353cb51613SAlexandru Ardelean #define ADIS16334_RATE_DIV_SHIFT 8
1363cb51613SAlexandru Ardelean #define ADIS16334_RATE_INT_CLK BIT(0)
1373cb51613SAlexandru Ardelean 
1383cb51613SAlexandru Ardelean #define ADIS16400_SPI_SLOW	(u32)(300 * 1000)
1393cb51613SAlexandru Ardelean #define ADIS16400_SPI_BURST	(u32)(1000 * 1000)
1403cb51613SAlexandru Ardelean #define ADIS16400_SPI_FAST	(u32)(2000 * 1000)
1413cb51613SAlexandru Ardelean 
1423cb51613SAlexandru Ardelean #define ADIS16400_HAS_PROD_ID		BIT(0)
1433cb51613SAlexandru Ardelean #define ADIS16400_NO_BURST		BIT(1)
1443cb51613SAlexandru Ardelean #define ADIS16400_HAS_SLOW_MODE		BIT(2)
1453cb51613SAlexandru Ardelean #define ADIS16400_HAS_SERIAL_NUMBER	BIT(3)
1463cb51613SAlexandru Ardelean #define ADIS16400_BURST_DIAG_STAT	BIT(4)
1473cb51613SAlexandru Ardelean 
1483cb51613SAlexandru Ardelean struct adis16400_state;
1493cb51613SAlexandru Ardelean 
1503cb51613SAlexandru Ardelean struct adis16400_chip_info {
1513cb51613SAlexandru Ardelean 	const struct iio_chan_spec *channels;
15299460853SAlexandru Ardelean 	const struct adis_data adis_data;
1533cb51613SAlexandru Ardelean 	const int num_channels;
1543cb51613SAlexandru Ardelean 	const long flags;
1553cb51613SAlexandru Ardelean 	unsigned int gyro_scale_micro;
1563cb51613SAlexandru Ardelean 	unsigned int accel_scale_micro;
1573cb51613SAlexandru Ardelean 	int temp_scale_nano;
1583cb51613SAlexandru Ardelean 	int temp_offset;
159ce476cd1SAlexandru Ardelean 	/* set_freq() & get_freq() need to avoid using ADIS lib's state lock */
1603cb51613SAlexandru Ardelean 	int (*set_freq)(struct adis16400_state *st, unsigned int freq);
1613cb51613SAlexandru Ardelean 	int (*get_freq)(struct adis16400_state *st);
1623cb51613SAlexandru Ardelean };
1633cb51613SAlexandru Ardelean 
1643cb51613SAlexandru Ardelean /**
1653cb51613SAlexandru Ardelean  * struct adis16400_state - device instance specific data
1663cb51613SAlexandru Ardelean  * @variant:	chip variant info
1673cb51613SAlexandru Ardelean  * @filt_int:	integer part of requested filter frequency
1683cb51613SAlexandru Ardelean  * @adis:	adis device
169d563d4d8SJonathan Cameron  * @avail_scan_mask:	NULL terminated array of bitmaps of channels
170d563d4d8SJonathan Cameron  *			that must be enabled together
1713cb51613SAlexandru Ardelean  **/
1723cb51613SAlexandru Ardelean struct adis16400_state {
1733cb51613SAlexandru Ardelean 	struct adis16400_chip_info	*variant;
1743cb51613SAlexandru Ardelean 	int				filt_int;
1753cb51613SAlexandru Ardelean 
1763cb51613SAlexandru Ardelean 	struct adis adis;
1773cb51613SAlexandru Ardelean 	unsigned long avail_scan_mask[2];
1783cb51613SAlexandru Ardelean };
1793cb51613SAlexandru Ardelean 
1803cb51613SAlexandru Ardelean /* At the moment triggers are only used for ring buffer
1813cb51613SAlexandru Ardelean  * filling. This may change!
1823cb51613SAlexandru Ardelean  */
1833cb51613SAlexandru Ardelean 
1843cb51613SAlexandru Ardelean enum {
1853cb51613SAlexandru Ardelean 	ADIS16400_SCAN_SUPPLY,
1863cb51613SAlexandru Ardelean 	ADIS16400_SCAN_GYRO_X,
1873cb51613SAlexandru Ardelean 	ADIS16400_SCAN_GYRO_Y,
1883cb51613SAlexandru Ardelean 	ADIS16400_SCAN_GYRO_Z,
1893cb51613SAlexandru Ardelean 	ADIS16400_SCAN_ACC_X,
1903cb51613SAlexandru Ardelean 	ADIS16400_SCAN_ACC_Y,
1913cb51613SAlexandru Ardelean 	ADIS16400_SCAN_ACC_Z,
1923cb51613SAlexandru Ardelean 	ADIS16400_SCAN_MAGN_X,
1933cb51613SAlexandru Ardelean 	ADIS16400_SCAN_MAGN_Y,
1943cb51613SAlexandru Ardelean 	ADIS16400_SCAN_MAGN_Z,
1953cb51613SAlexandru Ardelean 	ADIS16400_SCAN_BARO,
1963cb51613SAlexandru Ardelean 	ADIS16350_SCAN_TEMP_X,
1973cb51613SAlexandru Ardelean 	ADIS16350_SCAN_TEMP_Y,
1983cb51613SAlexandru Ardelean 	ADIS16350_SCAN_TEMP_Z,
1993cb51613SAlexandru Ardelean 	ADIS16300_SCAN_INCLI_X,
2003cb51613SAlexandru Ardelean 	ADIS16300_SCAN_INCLI_Y,
2013cb51613SAlexandru Ardelean 	ADIS16400_SCAN_ADC,
2023cb51613SAlexandru Ardelean 	ADIS16400_SCAN_TIMESTAMP,
2033cb51613SAlexandru Ardelean };
2045447e3f1SAlexandru Ardelean 
2055447e3f1SAlexandru Ardelean #ifdef CONFIG_DEBUG_FS
2065447e3f1SAlexandru Ardelean 
adis16400_show_serial_number(struct file * file,char __user * userbuf,size_t count,loff_t * ppos)2075447e3f1SAlexandru Ardelean static ssize_t adis16400_show_serial_number(struct file *file,
2085447e3f1SAlexandru Ardelean 		char __user *userbuf, size_t count, loff_t *ppos)
2095447e3f1SAlexandru Ardelean {
2105447e3f1SAlexandru Ardelean 	struct adis16400_state *st = file->private_data;
2115447e3f1SAlexandru Ardelean 	u16 lot1, lot2, serial_number;
2125447e3f1SAlexandru Ardelean 	char buf[16];
2135447e3f1SAlexandru Ardelean 	size_t len;
2145447e3f1SAlexandru Ardelean 	int ret;
2155447e3f1SAlexandru Ardelean 
2165447e3f1SAlexandru Ardelean 	ret = adis_read_reg_16(&st->adis, ADIS16334_LOT_ID1, &lot1);
217fe4b7f91SAlexandru Ardelean 	if (ret)
2185447e3f1SAlexandru Ardelean 		return ret;
2195447e3f1SAlexandru Ardelean 
2205447e3f1SAlexandru Ardelean 	ret = adis_read_reg_16(&st->adis, ADIS16334_LOT_ID2, &lot2);
221fe4b7f91SAlexandru Ardelean 	if (ret)
2225447e3f1SAlexandru Ardelean 		return ret;
2235447e3f1SAlexandru Ardelean 
2245447e3f1SAlexandru Ardelean 	ret = adis_read_reg_16(&st->adis, ADIS16334_SERIAL_NUMBER,
2255447e3f1SAlexandru Ardelean 			&serial_number);
226fe4b7f91SAlexandru Ardelean 	if (ret)
2275447e3f1SAlexandru Ardelean 		return ret;
2285447e3f1SAlexandru Ardelean 
2295447e3f1SAlexandru Ardelean 	len = snprintf(buf, sizeof(buf), "%.4x-%.4x-%.4x\n", lot1, lot2,
2305447e3f1SAlexandru Ardelean 			serial_number);
2315447e3f1SAlexandru Ardelean 
2325447e3f1SAlexandru Ardelean 	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
2335447e3f1SAlexandru Ardelean }
2345447e3f1SAlexandru Ardelean 
2355447e3f1SAlexandru Ardelean static const struct file_operations adis16400_serial_number_fops = {
2365447e3f1SAlexandru Ardelean 	.open = simple_open,
2375447e3f1SAlexandru Ardelean 	.read = adis16400_show_serial_number,
2385447e3f1SAlexandru Ardelean 	.llseek = default_llseek,
2395447e3f1SAlexandru Ardelean 	.owner = THIS_MODULE,
2405447e3f1SAlexandru Ardelean };
2415447e3f1SAlexandru Ardelean 
adis16400_show_product_id(void * arg,u64 * val)2425447e3f1SAlexandru Ardelean static int adis16400_show_product_id(void *arg, u64 *val)
2435447e3f1SAlexandru Ardelean {
2445447e3f1SAlexandru Ardelean 	struct adis16400_state *st = arg;
2455447e3f1SAlexandru Ardelean 	uint16_t prod_id;
2465447e3f1SAlexandru Ardelean 	int ret;
2475447e3f1SAlexandru Ardelean 
2485447e3f1SAlexandru Ardelean 	ret = adis_read_reg_16(&st->adis, ADIS16400_PRODUCT_ID, &prod_id);
249fe4b7f91SAlexandru Ardelean 	if (ret)
2505447e3f1SAlexandru Ardelean 		return ret;
2515447e3f1SAlexandru Ardelean 
2525447e3f1SAlexandru Ardelean 	*val = prod_id;
2535447e3f1SAlexandru Ardelean 
2545447e3f1SAlexandru Ardelean 	return 0;
2555447e3f1SAlexandru Ardelean }
256ae1d37a9SRohit Sarkar DEFINE_DEBUGFS_ATTRIBUTE(adis16400_product_id_fops,
2575447e3f1SAlexandru Ardelean 	adis16400_show_product_id, NULL, "%lld\n");
2585447e3f1SAlexandru Ardelean 
adis16400_show_flash_count(void * arg,u64 * val)2595447e3f1SAlexandru Ardelean static int adis16400_show_flash_count(void *arg, u64 *val)
2605447e3f1SAlexandru Ardelean {
2615447e3f1SAlexandru Ardelean 	struct adis16400_state *st = arg;
2625447e3f1SAlexandru Ardelean 	uint16_t flash_count;
2635447e3f1SAlexandru Ardelean 	int ret;
2645447e3f1SAlexandru Ardelean 
2655447e3f1SAlexandru Ardelean 	ret = adis_read_reg_16(&st->adis, ADIS16400_FLASH_CNT, &flash_count);
266fe4b7f91SAlexandru Ardelean 	if (ret)
2675447e3f1SAlexandru Ardelean 		return ret;
2685447e3f1SAlexandru Ardelean 
2695447e3f1SAlexandru Ardelean 	*val = flash_count;
2705447e3f1SAlexandru Ardelean 
2715447e3f1SAlexandru Ardelean 	return 0;
2725447e3f1SAlexandru Ardelean }
273ae1d37a9SRohit Sarkar DEFINE_DEBUGFS_ATTRIBUTE(adis16400_flash_count_fops,
2745447e3f1SAlexandru Ardelean 	adis16400_show_flash_count, NULL, "%lld\n");
2755447e3f1SAlexandru Ardelean 
adis16400_debugfs_init(struct iio_dev * indio_dev)2765447e3f1SAlexandru Ardelean static int adis16400_debugfs_init(struct iio_dev *indio_dev)
2775447e3f1SAlexandru Ardelean {
2785447e3f1SAlexandru Ardelean 	struct adis16400_state *st = iio_priv(indio_dev);
279b7190859SAlexandru Ardelean 	struct dentry *d = iio_get_debugfs_dentry(indio_dev);
2805447e3f1SAlexandru Ardelean 
2815447e3f1SAlexandru Ardelean 	if (st->variant->flags & ADIS16400_HAS_SERIAL_NUMBER)
282ae1d37a9SRohit Sarkar 		debugfs_create_file_unsafe("serial_number", 0400,
283b7190859SAlexandru Ardelean 				d, st, &adis16400_serial_number_fops);
2845447e3f1SAlexandru Ardelean 	if (st->variant->flags & ADIS16400_HAS_PROD_ID)
285ae1d37a9SRohit Sarkar 		debugfs_create_file_unsafe("product_id", 0400,
286b7190859SAlexandru Ardelean 				d, st, &adis16400_product_id_fops);
287ae1d37a9SRohit Sarkar 	debugfs_create_file_unsafe("flash_count", 0400,
288b7190859SAlexandru Ardelean 			d, st, &adis16400_flash_count_fops);
2895447e3f1SAlexandru Ardelean 
2905447e3f1SAlexandru Ardelean 	return 0;
2915447e3f1SAlexandru Ardelean }
2925447e3f1SAlexandru Ardelean 
2935447e3f1SAlexandru Ardelean #else
2945447e3f1SAlexandru Ardelean 
adis16400_debugfs_init(struct iio_dev * indio_dev)2955447e3f1SAlexandru Ardelean static int adis16400_debugfs_init(struct iio_dev *indio_dev)
2965447e3f1SAlexandru Ardelean {
2975447e3f1SAlexandru Ardelean 	return 0;
2985447e3f1SAlexandru Ardelean }
2995447e3f1SAlexandru Ardelean 
3005447e3f1SAlexandru Ardelean #endif
3015447e3f1SAlexandru Ardelean 
3025447e3f1SAlexandru Ardelean enum adis16400_chip_variant {
3035447e3f1SAlexandru Ardelean 	ADIS16300,
3045447e3f1SAlexandru Ardelean 	ADIS16334,
3055447e3f1SAlexandru Ardelean 	ADIS16350,
3065447e3f1SAlexandru Ardelean 	ADIS16360,
3075447e3f1SAlexandru Ardelean 	ADIS16362,
3085447e3f1SAlexandru Ardelean 	ADIS16364,
3095447e3f1SAlexandru Ardelean 	ADIS16367,
3105447e3f1SAlexandru Ardelean 	ADIS16400,
3115447e3f1SAlexandru Ardelean 	ADIS16445,
3125447e3f1SAlexandru Ardelean 	ADIS16448,
3135447e3f1SAlexandru Ardelean };
3145447e3f1SAlexandru Ardelean 
adis16334_get_freq(struct adis16400_state * st)3155447e3f1SAlexandru Ardelean static int adis16334_get_freq(struct adis16400_state *st)
3165447e3f1SAlexandru Ardelean {
3175447e3f1SAlexandru Ardelean 	int ret;
3185447e3f1SAlexandru Ardelean 	uint16_t t;
3195447e3f1SAlexandru Ardelean 
320ce476cd1SAlexandru Ardelean 	ret = __adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t);
321fe4b7f91SAlexandru Ardelean 	if (ret)
3225447e3f1SAlexandru Ardelean 		return ret;
3235447e3f1SAlexandru Ardelean 
3245447e3f1SAlexandru Ardelean 	t >>= ADIS16334_RATE_DIV_SHIFT;
3255447e3f1SAlexandru Ardelean 
3265447e3f1SAlexandru Ardelean 	return 819200 >> t;
3275447e3f1SAlexandru Ardelean }
3285447e3f1SAlexandru Ardelean 
adis16334_set_freq(struct adis16400_state * st,unsigned int freq)3295447e3f1SAlexandru Ardelean static int adis16334_set_freq(struct adis16400_state *st, unsigned int freq)
3305447e3f1SAlexandru Ardelean {
3315447e3f1SAlexandru Ardelean 	unsigned int t;
3325447e3f1SAlexandru Ardelean 
3335447e3f1SAlexandru Ardelean 	if (freq < 819200)
3345447e3f1SAlexandru Ardelean 		t = ilog2(819200 / freq);
3355447e3f1SAlexandru Ardelean 	else
3365447e3f1SAlexandru Ardelean 		t = 0;
3375447e3f1SAlexandru Ardelean 
3385447e3f1SAlexandru Ardelean 	if (t > 0x31)
3395447e3f1SAlexandru Ardelean 		t = 0x31;
3405447e3f1SAlexandru Ardelean 
3415447e3f1SAlexandru Ardelean 	t <<= ADIS16334_RATE_DIV_SHIFT;
3425447e3f1SAlexandru Ardelean 	t |= ADIS16334_RATE_INT_CLK;
3435447e3f1SAlexandru Ardelean 
344ce476cd1SAlexandru Ardelean 	return __adis_write_reg_16(&st->adis, ADIS16400_SMPL_PRD, t);
3455447e3f1SAlexandru Ardelean }
3465447e3f1SAlexandru Ardelean 
adis16400_get_freq(struct adis16400_state * st)3475447e3f1SAlexandru Ardelean static int adis16400_get_freq(struct adis16400_state *st)
3485447e3f1SAlexandru Ardelean {
3495447e3f1SAlexandru Ardelean 	int sps, ret;
3505447e3f1SAlexandru Ardelean 	uint16_t t;
3515447e3f1SAlexandru Ardelean 
352ce476cd1SAlexandru Ardelean 	ret = __adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t);
353fe4b7f91SAlexandru Ardelean 	if (ret)
3545447e3f1SAlexandru Ardelean 		return ret;
3555447e3f1SAlexandru Ardelean 
3565447e3f1SAlexandru Ardelean 	sps = (t & ADIS16400_SMPL_PRD_TIME_BASE) ? 52851 : 1638404;
3575447e3f1SAlexandru Ardelean 	sps /= (t & ADIS16400_SMPL_PRD_DIV_MASK) + 1;
3585447e3f1SAlexandru Ardelean 
3595447e3f1SAlexandru Ardelean 	return sps;
3605447e3f1SAlexandru Ardelean }
3615447e3f1SAlexandru Ardelean 
adis16400_set_freq(struct adis16400_state * st,unsigned int freq)3625447e3f1SAlexandru Ardelean static int adis16400_set_freq(struct adis16400_state *st, unsigned int freq)
3635447e3f1SAlexandru Ardelean {
3645447e3f1SAlexandru Ardelean 	unsigned int t;
3655447e3f1SAlexandru Ardelean 	uint8_t val = 0;
3665447e3f1SAlexandru Ardelean 
3675447e3f1SAlexandru Ardelean 	t = 1638404 / freq;
3685447e3f1SAlexandru Ardelean 	if (t >= 128) {
3695447e3f1SAlexandru Ardelean 		val |= ADIS16400_SMPL_PRD_TIME_BASE;
3705447e3f1SAlexandru Ardelean 		t = 52851 / freq;
3715447e3f1SAlexandru Ardelean 		if (t >= 128)
3725447e3f1SAlexandru Ardelean 			t = 127;
3735447e3f1SAlexandru Ardelean 	} else if (t != 0) {
3745447e3f1SAlexandru Ardelean 		t--;
3755447e3f1SAlexandru Ardelean 	}
3765447e3f1SAlexandru Ardelean 
3775447e3f1SAlexandru Ardelean 	val |= t;
3785447e3f1SAlexandru Ardelean 
3795447e3f1SAlexandru Ardelean 	if (t >= 0x0A || (val & ADIS16400_SMPL_PRD_TIME_BASE))
3805447e3f1SAlexandru Ardelean 		st->adis.spi->max_speed_hz = ADIS16400_SPI_SLOW;
3815447e3f1SAlexandru Ardelean 	else
3825447e3f1SAlexandru Ardelean 		st->adis.spi->max_speed_hz = ADIS16400_SPI_FAST;
3835447e3f1SAlexandru Ardelean 
384ce476cd1SAlexandru Ardelean 	return __adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val);
3855447e3f1SAlexandru Ardelean }
3865447e3f1SAlexandru Ardelean 
3875447e3f1SAlexandru Ardelean static const unsigned int adis16400_3db_divisors[] = {
3885447e3f1SAlexandru Ardelean 	[0] = 2, /* Special case */
3895447e3f1SAlexandru Ardelean 	[1] = 6,
3905447e3f1SAlexandru Ardelean 	[2] = 12,
3915447e3f1SAlexandru Ardelean 	[3] = 25,
3925447e3f1SAlexandru Ardelean 	[4] = 50,
3935447e3f1SAlexandru Ardelean 	[5] = 100,
3945447e3f1SAlexandru Ardelean 	[6] = 200,
3955447e3f1SAlexandru Ardelean 	[7] = 200, /* Not a valid setting */
3965447e3f1SAlexandru Ardelean };
3975447e3f1SAlexandru Ardelean 
__adis16400_set_filter(struct iio_dev * indio_dev,int sps,int val)398ce476cd1SAlexandru Ardelean static int __adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val)
3995447e3f1SAlexandru Ardelean {
4005447e3f1SAlexandru Ardelean 	struct adis16400_state *st = iio_priv(indio_dev);
4015447e3f1SAlexandru Ardelean 	uint16_t val16;
4025447e3f1SAlexandru Ardelean 	int i, ret;
4035447e3f1SAlexandru Ardelean 
4045447e3f1SAlexandru Ardelean 	for (i = ARRAY_SIZE(adis16400_3db_divisors) - 1; i >= 1; i--) {
4055447e3f1SAlexandru Ardelean 		if (sps / adis16400_3db_divisors[i] >= val)
4065447e3f1SAlexandru Ardelean 			break;
4075447e3f1SAlexandru Ardelean 	}
4085447e3f1SAlexandru Ardelean 
409ce476cd1SAlexandru Ardelean 	ret = __adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, &val16);
410fe4b7f91SAlexandru Ardelean 	if (ret)
4115447e3f1SAlexandru Ardelean 		return ret;
4125447e3f1SAlexandru Ardelean 
413ce476cd1SAlexandru Ardelean 	ret = __adis_write_reg_16(&st->adis, ADIS16400_SENS_AVG,
4145447e3f1SAlexandru Ardelean 					 (val16 & ~0x07) | i);
4155447e3f1SAlexandru Ardelean 	return ret;
4165447e3f1SAlexandru Ardelean }
4175447e3f1SAlexandru Ardelean 
4185447e3f1SAlexandru Ardelean /* Power down the device */
adis16400_stop_device(struct iio_dev * indio_dev)4195447e3f1SAlexandru Ardelean static int adis16400_stop_device(struct iio_dev *indio_dev)
4205447e3f1SAlexandru Ardelean {
4215447e3f1SAlexandru Ardelean 	struct adis16400_state *st = iio_priv(indio_dev);
4225447e3f1SAlexandru Ardelean 	int ret;
4235447e3f1SAlexandru Ardelean 
4245447e3f1SAlexandru Ardelean 	ret = adis_write_reg_16(&st->adis, ADIS16400_SLP_CNT,
4255447e3f1SAlexandru Ardelean 			ADIS16400_SLP_CNT_POWER_OFF);
4265447e3f1SAlexandru Ardelean 	if (ret)
4275447e3f1SAlexandru Ardelean 		dev_err(&indio_dev->dev,
4285447e3f1SAlexandru Ardelean 			"problem with turning device off: SLP_CNT");
4295447e3f1SAlexandru Ardelean 
4305447e3f1SAlexandru Ardelean 	return ret;
4315447e3f1SAlexandru Ardelean }
4325447e3f1SAlexandru Ardelean 
adis16400_initial_setup(struct iio_dev * indio_dev)4335447e3f1SAlexandru Ardelean static int adis16400_initial_setup(struct iio_dev *indio_dev)
4345447e3f1SAlexandru Ardelean {
4355447e3f1SAlexandru Ardelean 	struct adis16400_state *st = iio_priv(indio_dev);
4365447e3f1SAlexandru Ardelean 	uint16_t prod_id, smp_prd;
4375447e3f1SAlexandru Ardelean 	unsigned int device_id;
4385447e3f1SAlexandru Ardelean 	int ret;
4395447e3f1SAlexandru Ardelean 
4405447e3f1SAlexandru Ardelean 	/* use low spi speed for init if the device has a slow mode */
4415447e3f1SAlexandru Ardelean 	if (st->variant->flags & ADIS16400_HAS_SLOW_MODE)
4425447e3f1SAlexandru Ardelean 		st->adis.spi->max_speed_hz = ADIS16400_SPI_SLOW;
4435447e3f1SAlexandru Ardelean 	else
4445447e3f1SAlexandru Ardelean 		st->adis.spi->max_speed_hz = ADIS16400_SPI_FAST;
4455447e3f1SAlexandru Ardelean 	st->adis.spi->mode = SPI_MODE_3;
4465447e3f1SAlexandru Ardelean 	spi_setup(st->adis.spi);
4475447e3f1SAlexandru Ardelean 
44840fd61b0SRamona Bolboaca 	ret = __adis_initial_startup(&st->adis);
4495447e3f1SAlexandru Ardelean 	if (ret)
4505447e3f1SAlexandru Ardelean 		return ret;
4515447e3f1SAlexandru Ardelean 
4525447e3f1SAlexandru Ardelean 	if (st->variant->flags & ADIS16400_HAS_PROD_ID) {
4535447e3f1SAlexandru Ardelean 		ret = adis_read_reg_16(&st->adis,
4545447e3f1SAlexandru Ardelean 						ADIS16400_PRODUCT_ID, &prod_id);
4555447e3f1SAlexandru Ardelean 		if (ret)
4565447e3f1SAlexandru Ardelean 			goto err_ret;
4575447e3f1SAlexandru Ardelean 
458a71266e4SDan Carpenter 		if (sscanf(indio_dev->name, "adis%u\n", &device_id) != 1) {
4595447e3f1SAlexandru Ardelean 			ret = -EINVAL;
4605447e3f1SAlexandru Ardelean 			goto err_ret;
4615447e3f1SAlexandru Ardelean 		}
4625447e3f1SAlexandru Ardelean 
4635447e3f1SAlexandru Ardelean 		if (prod_id != device_id)
4645447e3f1SAlexandru Ardelean 			dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.",
4655447e3f1SAlexandru Ardelean 					device_id, prod_id);
4665447e3f1SAlexandru Ardelean 
4675447e3f1SAlexandru Ardelean 		dev_info(&indio_dev->dev, "%s: prod_id 0x%04x at CS%d (irq %d)\n",
4685447e3f1SAlexandru Ardelean 			indio_dev->name, prod_id,
469*0183f81fSAmit Kumar Mahapatra 			spi_get_chipselect(st->adis.spi, 0), st->adis.spi->irq);
4705447e3f1SAlexandru Ardelean 	}
4715447e3f1SAlexandru Ardelean 	/* use high spi speed if possible */
4725447e3f1SAlexandru Ardelean 	if (st->variant->flags & ADIS16400_HAS_SLOW_MODE) {
4735447e3f1SAlexandru Ardelean 		ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &smp_prd);
4745447e3f1SAlexandru Ardelean 		if (ret)
4755447e3f1SAlexandru Ardelean 			goto err_ret;
4765447e3f1SAlexandru Ardelean 
4775447e3f1SAlexandru Ardelean 		if ((smp_prd & ADIS16400_SMPL_PRD_DIV_MASK) < 0x0A) {
4785447e3f1SAlexandru Ardelean 			st->adis.spi->max_speed_hz = ADIS16400_SPI_FAST;
4795447e3f1SAlexandru Ardelean 			spi_setup(st->adis.spi);
4805447e3f1SAlexandru Ardelean 		}
4815447e3f1SAlexandru Ardelean 	}
4825447e3f1SAlexandru Ardelean 
4835447e3f1SAlexandru Ardelean err_ret:
4845447e3f1SAlexandru Ardelean 	return ret;
4855447e3f1SAlexandru Ardelean }
4865447e3f1SAlexandru Ardelean 
4875447e3f1SAlexandru Ardelean static const uint8_t adis16400_addresses[] = {
4885447e3f1SAlexandru Ardelean 	[ADIS16400_SCAN_GYRO_X] = ADIS16400_XGYRO_OFF,
4895447e3f1SAlexandru Ardelean 	[ADIS16400_SCAN_GYRO_Y] = ADIS16400_YGYRO_OFF,
4905447e3f1SAlexandru Ardelean 	[ADIS16400_SCAN_GYRO_Z] = ADIS16400_ZGYRO_OFF,
4915447e3f1SAlexandru Ardelean 	[ADIS16400_SCAN_ACC_X] = ADIS16400_XACCL_OFF,
4925447e3f1SAlexandru Ardelean 	[ADIS16400_SCAN_ACC_Y] = ADIS16400_YACCL_OFF,
4935447e3f1SAlexandru Ardelean 	[ADIS16400_SCAN_ACC_Z] = ADIS16400_ZACCL_OFF,
4945447e3f1SAlexandru Ardelean };
4955447e3f1SAlexandru Ardelean 
adis16400_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long info)4965447e3f1SAlexandru Ardelean static int adis16400_write_raw(struct iio_dev *indio_dev,
4975447e3f1SAlexandru Ardelean 	struct iio_chan_spec const *chan, int val, int val2, long info)
4985447e3f1SAlexandru Ardelean {
4995447e3f1SAlexandru Ardelean 	struct adis16400_state *st = iio_priv(indio_dev);
5005447e3f1SAlexandru Ardelean 	int ret, sps;
5015447e3f1SAlexandru Ardelean 
5025447e3f1SAlexandru Ardelean 	switch (info) {
5035447e3f1SAlexandru Ardelean 	case IIO_CHAN_INFO_CALIBBIAS:
5045447e3f1SAlexandru Ardelean 		ret = adis_write_reg_16(&st->adis,
5055447e3f1SAlexandru Ardelean 				adis16400_addresses[chan->scan_index], val);
5065447e3f1SAlexandru Ardelean 		return ret;
5075447e3f1SAlexandru Ardelean 	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
5085447e3f1SAlexandru Ardelean 		/*
5095447e3f1SAlexandru Ardelean 		 * Need to cache values so we can update if the frequency
5105447e3f1SAlexandru Ardelean 		 * changes.
5115447e3f1SAlexandru Ardelean 		 */
51215aacc98SNuno Sa 		adis_dev_lock(&st->adis);
5135447e3f1SAlexandru Ardelean 		st->filt_int = val;
5145447e3f1SAlexandru Ardelean 		/* Work out update to current value */
5155447e3f1SAlexandru Ardelean 		sps = st->variant->get_freq(st);
5165447e3f1SAlexandru Ardelean 		if (sps < 0) {
51715aacc98SNuno Sa 			adis_dev_unlock(&st->adis);
5185447e3f1SAlexandru Ardelean 			return sps;
5195447e3f1SAlexandru Ardelean 		}
5205447e3f1SAlexandru Ardelean 
521ce476cd1SAlexandru Ardelean 		ret = __adis16400_set_filter(indio_dev, sps,
5225447e3f1SAlexandru Ardelean 			val * 1000 + val2 / 1000);
52315aacc98SNuno Sa 		adis_dev_unlock(&st->adis);
5245447e3f1SAlexandru Ardelean 		return ret;
5255447e3f1SAlexandru Ardelean 	case IIO_CHAN_INFO_SAMP_FREQ:
5265447e3f1SAlexandru Ardelean 		sps = val * 1000 + val2 / 1000;
5275447e3f1SAlexandru Ardelean 
5285447e3f1SAlexandru Ardelean 		if (sps <= 0)
5295447e3f1SAlexandru Ardelean 			return -EINVAL;
5305447e3f1SAlexandru Ardelean 
53115aacc98SNuno Sa 		adis_dev_lock(&st->adis);
5325447e3f1SAlexandru Ardelean 		ret = st->variant->set_freq(st, sps);
53315aacc98SNuno Sa 		adis_dev_unlock(&st->adis);
5345447e3f1SAlexandru Ardelean 		return ret;
5355447e3f1SAlexandru Ardelean 	default:
5365447e3f1SAlexandru Ardelean 		return -EINVAL;
5375447e3f1SAlexandru Ardelean 	}
5385447e3f1SAlexandru Ardelean }
5395447e3f1SAlexandru Ardelean 
adis16400_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long info)5405447e3f1SAlexandru Ardelean static int adis16400_read_raw(struct iio_dev *indio_dev,
5415447e3f1SAlexandru Ardelean 	struct iio_chan_spec const *chan, int *val, int *val2, long info)
5425447e3f1SAlexandru Ardelean {
5435447e3f1SAlexandru Ardelean 	struct adis16400_state *st = iio_priv(indio_dev);
5445447e3f1SAlexandru Ardelean 	int16_t val16;
5455447e3f1SAlexandru Ardelean 	int ret;
5465447e3f1SAlexandru Ardelean 
5475447e3f1SAlexandru Ardelean 	switch (info) {
5485447e3f1SAlexandru Ardelean 	case IIO_CHAN_INFO_RAW:
5495447e3f1SAlexandru Ardelean 		return adis_single_conversion(indio_dev, chan, 0, val);
5505447e3f1SAlexandru Ardelean 	case IIO_CHAN_INFO_SCALE:
5515447e3f1SAlexandru Ardelean 		switch (chan->type) {
5525447e3f1SAlexandru Ardelean 		case IIO_ANGL_VEL:
5535447e3f1SAlexandru Ardelean 			*val = 0;
5545447e3f1SAlexandru Ardelean 			*val2 = st->variant->gyro_scale_micro;
5555447e3f1SAlexandru Ardelean 			return IIO_VAL_INT_PLUS_MICRO;
5565447e3f1SAlexandru Ardelean 		case IIO_VOLTAGE:
5575447e3f1SAlexandru Ardelean 			*val = 0;
5585447e3f1SAlexandru Ardelean 			if (chan->channel == 0) {
5595447e3f1SAlexandru Ardelean 				*val = 2;
5605447e3f1SAlexandru Ardelean 				*val2 = 418000; /* 2.418 mV */
5615447e3f1SAlexandru Ardelean 			} else {
5625447e3f1SAlexandru Ardelean 				*val = 0;
5635447e3f1SAlexandru Ardelean 				*val2 = 805800; /* 805.8 uV */
5645447e3f1SAlexandru Ardelean 			}
5655447e3f1SAlexandru Ardelean 			return IIO_VAL_INT_PLUS_MICRO;
5665447e3f1SAlexandru Ardelean 		case IIO_ACCEL:
5675447e3f1SAlexandru Ardelean 			*val = 0;
5685447e3f1SAlexandru Ardelean 			*val2 = st->variant->accel_scale_micro;
5695447e3f1SAlexandru Ardelean 			return IIO_VAL_INT_PLUS_MICRO;
5705447e3f1SAlexandru Ardelean 		case IIO_MAGN:
5715447e3f1SAlexandru Ardelean 			*val = 0;
5725447e3f1SAlexandru Ardelean 			*val2 = 500; /* 0.5 mgauss */
5735447e3f1SAlexandru Ardelean 			return IIO_VAL_INT_PLUS_MICRO;
5745447e3f1SAlexandru Ardelean 		case IIO_TEMP:
5755447e3f1SAlexandru Ardelean 			*val = st->variant->temp_scale_nano / 1000000;
5765447e3f1SAlexandru Ardelean 			*val2 = (st->variant->temp_scale_nano % 1000000);
5775447e3f1SAlexandru Ardelean 			return IIO_VAL_INT_PLUS_MICRO;
5785447e3f1SAlexandru Ardelean 		case IIO_PRESSURE:
5795447e3f1SAlexandru Ardelean 			/* 20 uBar = 0.002kPascal */
5805447e3f1SAlexandru Ardelean 			*val = 0;
5815447e3f1SAlexandru Ardelean 			*val2 = 2000;
5825447e3f1SAlexandru Ardelean 			return IIO_VAL_INT_PLUS_MICRO;
5835447e3f1SAlexandru Ardelean 		default:
5845447e3f1SAlexandru Ardelean 			return -EINVAL;
5855447e3f1SAlexandru Ardelean 		}
5865447e3f1SAlexandru Ardelean 	case IIO_CHAN_INFO_CALIBBIAS:
5875447e3f1SAlexandru Ardelean 		ret = adis_read_reg_16(&st->adis,
5885447e3f1SAlexandru Ardelean 				adis16400_addresses[chan->scan_index], &val16);
5895447e3f1SAlexandru Ardelean 		if (ret)
5905447e3f1SAlexandru Ardelean 			return ret;
5915447e3f1SAlexandru Ardelean 		val16 = sign_extend32(val16, 11);
5925447e3f1SAlexandru Ardelean 		*val = val16;
5935447e3f1SAlexandru Ardelean 		return IIO_VAL_INT;
5945447e3f1SAlexandru Ardelean 	case IIO_CHAN_INFO_OFFSET:
5955447e3f1SAlexandru Ardelean 		/* currently only temperature */
5965447e3f1SAlexandru Ardelean 		*val = st->variant->temp_offset;
5975447e3f1SAlexandru Ardelean 		return IIO_VAL_INT;
5985447e3f1SAlexandru Ardelean 	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
59915aacc98SNuno Sa 		adis_dev_lock(&st->adis);
6005447e3f1SAlexandru Ardelean 		/* Need both the number of taps and the sampling frequency */
601ce476cd1SAlexandru Ardelean 		ret = __adis_read_reg_16(&st->adis,
6025447e3f1SAlexandru Ardelean 						ADIS16400_SENS_AVG,
6035447e3f1SAlexandru Ardelean 						&val16);
604fe4b7f91SAlexandru Ardelean 		if (ret) {
60515aacc98SNuno Sa 			adis_dev_unlock(&st->adis);
6065447e3f1SAlexandru Ardelean 			return ret;
6075447e3f1SAlexandru Ardelean 		}
6085447e3f1SAlexandru Ardelean 		ret = st->variant->get_freq(st);
60915aacc98SNuno Sa 		adis_dev_unlock(&st->adis);
610ce476cd1SAlexandru Ardelean 		if (ret)
611ce476cd1SAlexandru Ardelean 			return ret;
6125447e3f1SAlexandru Ardelean 		ret /= adis16400_3db_divisors[val16 & 0x07];
6135447e3f1SAlexandru Ardelean 		*val = ret / 1000;
6145447e3f1SAlexandru Ardelean 		*val2 = (ret % 1000) * 1000;
6155447e3f1SAlexandru Ardelean 		return IIO_VAL_INT_PLUS_MICRO;
6165447e3f1SAlexandru Ardelean 	case IIO_CHAN_INFO_SAMP_FREQ:
61715aacc98SNuno Sa 		adis_dev_lock(&st->adis);
6185447e3f1SAlexandru Ardelean 		ret = st->variant->get_freq(st);
61915aacc98SNuno Sa 		adis_dev_unlock(&st->adis);
620fe4b7f91SAlexandru Ardelean 		if (ret)
6215447e3f1SAlexandru Ardelean 			return ret;
6225447e3f1SAlexandru Ardelean 		*val = ret / 1000;
6235447e3f1SAlexandru Ardelean 		*val2 = (ret % 1000) * 1000;
6245447e3f1SAlexandru Ardelean 		return IIO_VAL_INT_PLUS_MICRO;
6255447e3f1SAlexandru Ardelean 	default:
6265447e3f1SAlexandru Ardelean 		return -EINVAL;
6275447e3f1SAlexandru Ardelean 	}
6285447e3f1SAlexandru Ardelean }
6295447e3f1SAlexandru Ardelean 
6305447e3f1SAlexandru Ardelean #if IS_ENABLED(CONFIG_IIO_BUFFER)
adis16400_trigger_handler(int irq,void * p)6315447e3f1SAlexandru Ardelean static irqreturn_t adis16400_trigger_handler(int irq, void *p)
6325447e3f1SAlexandru Ardelean {
6335447e3f1SAlexandru Ardelean 	struct iio_poll_func *pf = p;
6345447e3f1SAlexandru Ardelean 	struct iio_dev *indio_dev = pf->indio_dev;
6355447e3f1SAlexandru Ardelean 	struct adis16400_state *st = iio_priv(indio_dev);
6365447e3f1SAlexandru Ardelean 	struct adis *adis = &st->adis;
6375447e3f1SAlexandru Ardelean 	void *buffer;
6385447e3f1SAlexandru Ardelean 	int ret;
6395447e3f1SAlexandru Ardelean 
6405447e3f1SAlexandru Ardelean 	ret = spi_sync(adis->spi, &adis->msg);
6415447e3f1SAlexandru Ardelean 	if (ret)
6425447e3f1SAlexandru Ardelean 		dev_err(&adis->spi->dev, "Failed to read data: %d\n", ret);
6435447e3f1SAlexandru Ardelean 
644d7a83bc3SJonathan Cameron 	if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) {
6455447e3f1SAlexandru Ardelean 		buffer = adis->buffer + sizeof(u16);
646d7a83bc3SJonathan Cameron 		/*
647d7a83bc3SJonathan Cameron 		 * The size here is always larger than, or equal to the true
648d7a83bc3SJonathan Cameron 		 * size of the channel data. This may result in a larger copy
649d7a83bc3SJonathan Cameron 		 * than necessary, but as the target buffer will be
650d7a83bc3SJonathan Cameron 		 * buffer->scan_bytes this will be safe.
651d7a83bc3SJonathan Cameron 		 */
652d7a83bc3SJonathan Cameron 		iio_push_to_buffers_with_ts_unaligned(indio_dev, buffer,
653d7a83bc3SJonathan Cameron 						      indio_dev->scan_bytes - sizeof(pf->timestamp),
6545447e3f1SAlexandru Ardelean 						      pf->timestamp);
655d7a83bc3SJonathan Cameron 	} else {
656d7a83bc3SJonathan Cameron 		iio_push_to_buffers_with_timestamp(indio_dev,
657d7a83bc3SJonathan Cameron 						   adis->buffer,
658d7a83bc3SJonathan Cameron 						   pf->timestamp);
659d7a83bc3SJonathan Cameron 	}
660d7a83bc3SJonathan Cameron 
6615447e3f1SAlexandru Ardelean 
6625447e3f1SAlexandru Ardelean 	iio_trigger_notify_done(indio_dev->trig);
6635447e3f1SAlexandru Ardelean 
6645447e3f1SAlexandru Ardelean 	return IRQ_HANDLED;
6655447e3f1SAlexandru Ardelean }
6665447e3f1SAlexandru Ardelean #else
6675447e3f1SAlexandru Ardelean #define adis16400_trigger_handler	NULL
6685447e3f1SAlexandru Ardelean #endif /* IS_ENABLED(CONFIG_IIO_BUFFER) */
6695447e3f1SAlexandru Ardelean 
6705447e3f1SAlexandru Ardelean #define ADIS16400_VOLTAGE_CHAN(addr, bits, name, si, chn) { \
6715447e3f1SAlexandru Ardelean 	.type = IIO_VOLTAGE, \
6725447e3f1SAlexandru Ardelean 	.indexed = 1, \
6735447e3f1SAlexandru Ardelean 	.channel = chn, \
6745447e3f1SAlexandru Ardelean 	.extend_name = name, \
6755447e3f1SAlexandru Ardelean 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
6765447e3f1SAlexandru Ardelean 		BIT(IIO_CHAN_INFO_SCALE), \
6775447e3f1SAlexandru Ardelean 	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
6785447e3f1SAlexandru Ardelean 	.address = (addr), \
6795447e3f1SAlexandru Ardelean 	.scan_index = (si), \
6805447e3f1SAlexandru Ardelean 	.scan_type = { \
6815447e3f1SAlexandru Ardelean 		.sign = 'u', \
6825447e3f1SAlexandru Ardelean 		.realbits = (bits), \
6835447e3f1SAlexandru Ardelean 		.storagebits = 16, \
6845447e3f1SAlexandru Ardelean 		.shift = 0, \
6855447e3f1SAlexandru Ardelean 		.endianness = IIO_BE, \
6865447e3f1SAlexandru Ardelean 	}, \
6875447e3f1SAlexandru Ardelean }
6885447e3f1SAlexandru Ardelean 
6895447e3f1SAlexandru Ardelean #define ADIS16400_SUPPLY_CHAN(addr, bits) \
6905447e3f1SAlexandru Ardelean 	ADIS16400_VOLTAGE_CHAN(addr, bits, "supply", ADIS16400_SCAN_SUPPLY, 0)
6915447e3f1SAlexandru Ardelean 
6925447e3f1SAlexandru Ardelean #define ADIS16400_AUX_ADC_CHAN(addr, bits) \
6935447e3f1SAlexandru Ardelean 	ADIS16400_VOLTAGE_CHAN(addr, bits, NULL, ADIS16400_SCAN_ADC, 1)
6945447e3f1SAlexandru Ardelean 
6955447e3f1SAlexandru Ardelean #define ADIS16400_GYRO_CHAN(mod, addr, bits) { \
6965447e3f1SAlexandru Ardelean 	.type = IIO_ANGL_VEL, \
6975447e3f1SAlexandru Ardelean 	.modified = 1, \
6985447e3f1SAlexandru Ardelean 	.channel2 = IIO_MOD_ ## mod, \
6995447e3f1SAlexandru Ardelean 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
7005447e3f1SAlexandru Ardelean 		BIT(IIO_CHAN_INFO_CALIBBIAS),		  \
7015447e3f1SAlexandru Ardelean 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
7025447e3f1SAlexandru Ardelean 		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
7035447e3f1SAlexandru Ardelean 	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
7045447e3f1SAlexandru Ardelean 	.address = addr, \
7055447e3f1SAlexandru Ardelean 	.scan_index = ADIS16400_SCAN_GYRO_ ## mod, \
7065447e3f1SAlexandru Ardelean 	.scan_type = { \
7075447e3f1SAlexandru Ardelean 		.sign = 's', \
7085447e3f1SAlexandru Ardelean 		.realbits = (bits), \
7095447e3f1SAlexandru Ardelean 		.storagebits = 16, \
7105447e3f1SAlexandru Ardelean 		.shift = 0, \
7115447e3f1SAlexandru Ardelean 		.endianness = IIO_BE, \
7125447e3f1SAlexandru Ardelean 	}, \
7135447e3f1SAlexandru Ardelean }
7145447e3f1SAlexandru Ardelean 
7155447e3f1SAlexandru Ardelean #define ADIS16400_ACCEL_CHAN(mod, addr, bits) { \
7165447e3f1SAlexandru Ardelean 	.type = IIO_ACCEL, \
7175447e3f1SAlexandru Ardelean 	.modified = 1, \
7185447e3f1SAlexandru Ardelean 	.channel2 = IIO_MOD_ ## mod, \
7195447e3f1SAlexandru Ardelean 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
7205447e3f1SAlexandru Ardelean 		BIT(IIO_CHAN_INFO_CALIBBIAS), \
7215447e3f1SAlexandru Ardelean 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
7225447e3f1SAlexandru Ardelean 		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
7235447e3f1SAlexandru Ardelean 	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
7245447e3f1SAlexandru Ardelean 	.address = (addr), \
7255447e3f1SAlexandru Ardelean 	.scan_index = ADIS16400_SCAN_ACC_ ## mod, \
7265447e3f1SAlexandru Ardelean 	.scan_type = { \
7275447e3f1SAlexandru Ardelean 		.sign = 's', \
7285447e3f1SAlexandru Ardelean 		.realbits = (bits), \
7295447e3f1SAlexandru Ardelean 		.storagebits = 16, \
7305447e3f1SAlexandru Ardelean 		.shift = 0, \
7315447e3f1SAlexandru Ardelean 		.endianness = IIO_BE, \
7325447e3f1SAlexandru Ardelean 	}, \
7335447e3f1SAlexandru Ardelean }
7345447e3f1SAlexandru Ardelean 
7355447e3f1SAlexandru Ardelean #define ADIS16400_MAGN_CHAN(mod, addr, bits) { \
7365447e3f1SAlexandru Ardelean 	.type = IIO_MAGN, \
7375447e3f1SAlexandru Ardelean 	.modified = 1, \
7385447e3f1SAlexandru Ardelean 	.channel2 = IIO_MOD_ ## mod, \
7395447e3f1SAlexandru Ardelean 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
7405447e3f1SAlexandru Ardelean 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
7415447e3f1SAlexandru Ardelean 		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
7425447e3f1SAlexandru Ardelean 	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
7435447e3f1SAlexandru Ardelean 	.address = (addr), \
7445447e3f1SAlexandru Ardelean 	.scan_index = ADIS16400_SCAN_MAGN_ ## mod, \
7455447e3f1SAlexandru Ardelean 	.scan_type = { \
7465447e3f1SAlexandru Ardelean 		.sign = 's', \
7475447e3f1SAlexandru Ardelean 		.realbits = (bits), \
7485447e3f1SAlexandru Ardelean 		.storagebits = 16, \
7495447e3f1SAlexandru Ardelean 		.shift = 0, \
7505447e3f1SAlexandru Ardelean 		.endianness = IIO_BE, \
7515447e3f1SAlexandru Ardelean 	}, \
7525447e3f1SAlexandru Ardelean }
7535447e3f1SAlexandru Ardelean 
7545447e3f1SAlexandru Ardelean #define ADIS16400_MOD_TEMP_NAME_X "x"
7555447e3f1SAlexandru Ardelean #define ADIS16400_MOD_TEMP_NAME_Y "y"
7565447e3f1SAlexandru Ardelean #define ADIS16400_MOD_TEMP_NAME_Z "z"
7575447e3f1SAlexandru Ardelean 
7585447e3f1SAlexandru Ardelean #define ADIS16400_MOD_TEMP_CHAN(mod, addr, bits) { \
7595447e3f1SAlexandru Ardelean 	.type = IIO_TEMP, \
7605447e3f1SAlexandru Ardelean 	.indexed = 1, \
7615447e3f1SAlexandru Ardelean 	.channel = 0, \
7625447e3f1SAlexandru Ardelean 	.extend_name = ADIS16400_MOD_TEMP_NAME_ ## mod, \
7635447e3f1SAlexandru Ardelean 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
7645447e3f1SAlexandru Ardelean 		BIT(IIO_CHAN_INFO_OFFSET) | \
7655447e3f1SAlexandru Ardelean 		BIT(IIO_CHAN_INFO_SCALE), \
7665447e3f1SAlexandru Ardelean 	.info_mask_shared_by_type = \
7675447e3f1SAlexandru Ardelean 		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
7685447e3f1SAlexandru Ardelean 	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
7695447e3f1SAlexandru Ardelean 	.address = (addr), \
7705447e3f1SAlexandru Ardelean 	.scan_index = ADIS16350_SCAN_TEMP_ ## mod, \
7715447e3f1SAlexandru Ardelean 	.scan_type = { \
7725447e3f1SAlexandru Ardelean 		.sign = 's', \
7735447e3f1SAlexandru Ardelean 		.realbits = (bits), \
7745447e3f1SAlexandru Ardelean 		.storagebits = 16, \
7755447e3f1SAlexandru Ardelean 		.shift = 0, \
7765447e3f1SAlexandru Ardelean 		.endianness = IIO_BE, \
7775447e3f1SAlexandru Ardelean 	}, \
7785447e3f1SAlexandru Ardelean }
7795447e3f1SAlexandru Ardelean 
7805447e3f1SAlexandru Ardelean #define ADIS16400_TEMP_CHAN(addr, bits) { \
7815447e3f1SAlexandru Ardelean 	.type = IIO_TEMP, \
7825447e3f1SAlexandru Ardelean 	.indexed = 1, \
7835447e3f1SAlexandru Ardelean 	.channel = 0, \
7845447e3f1SAlexandru Ardelean 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
7855447e3f1SAlexandru Ardelean 		BIT(IIO_CHAN_INFO_OFFSET) | \
7865447e3f1SAlexandru Ardelean 		BIT(IIO_CHAN_INFO_SCALE), \
7875447e3f1SAlexandru Ardelean 	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
7885447e3f1SAlexandru Ardelean 	.address = (addr), \
7895447e3f1SAlexandru Ardelean 	.scan_index = ADIS16350_SCAN_TEMP_X, \
7905447e3f1SAlexandru Ardelean 	.scan_type = { \
7915447e3f1SAlexandru Ardelean 		.sign = 's', \
7925447e3f1SAlexandru Ardelean 		.realbits = (bits), \
7935447e3f1SAlexandru Ardelean 		.storagebits = 16, \
7945447e3f1SAlexandru Ardelean 		.shift = 0, \
7955447e3f1SAlexandru Ardelean 		.endianness = IIO_BE, \
7965447e3f1SAlexandru Ardelean 	}, \
7975447e3f1SAlexandru Ardelean }
7985447e3f1SAlexandru Ardelean 
7995447e3f1SAlexandru Ardelean #define ADIS16400_INCLI_CHAN(mod, addr, bits) { \
8005447e3f1SAlexandru Ardelean 	.type = IIO_INCLI, \
8015447e3f1SAlexandru Ardelean 	.modified = 1, \
8025447e3f1SAlexandru Ardelean 	.channel2 = IIO_MOD_ ## mod, \
8035447e3f1SAlexandru Ardelean 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
8045447e3f1SAlexandru Ardelean 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
8055447e3f1SAlexandru Ardelean 	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
8065447e3f1SAlexandru Ardelean 	.address = (addr), \
8075447e3f1SAlexandru Ardelean 	.scan_index = ADIS16300_SCAN_INCLI_ ## mod, \
8085447e3f1SAlexandru Ardelean 	.scan_type = { \
8095447e3f1SAlexandru Ardelean 		.sign = 's', \
8105447e3f1SAlexandru Ardelean 		.realbits = (bits), \
8115447e3f1SAlexandru Ardelean 		.storagebits = 16, \
8125447e3f1SAlexandru Ardelean 		.shift = 0, \
8135447e3f1SAlexandru Ardelean 		.endianness = IIO_BE, \
8145447e3f1SAlexandru Ardelean 	}, \
8155447e3f1SAlexandru Ardelean }
8165447e3f1SAlexandru Ardelean 
8175447e3f1SAlexandru Ardelean static const struct iio_chan_spec adis16400_channels[] = {
8185447e3f1SAlexandru Ardelean 	ADIS16400_SUPPLY_CHAN(ADIS16400_SUPPLY_OUT, 14),
8195447e3f1SAlexandru Ardelean 	ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 14),
8205447e3f1SAlexandru Ardelean 	ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 14),
8215447e3f1SAlexandru Ardelean 	ADIS16400_GYRO_CHAN(Z, ADIS16400_ZGYRO_OUT, 14),
8225447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 14),
8235447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 14),
8245447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 14),
8255447e3f1SAlexandru Ardelean 	ADIS16400_MAGN_CHAN(X, ADIS16400_XMAGN_OUT, 14),
8265447e3f1SAlexandru Ardelean 	ADIS16400_MAGN_CHAN(Y, ADIS16400_YMAGN_OUT, 14),
8275447e3f1SAlexandru Ardelean 	ADIS16400_MAGN_CHAN(Z, ADIS16400_ZMAGN_OUT, 14),
8285447e3f1SAlexandru Ardelean 	ADIS16400_TEMP_CHAN(ADIS16400_TEMP_OUT, 12),
8295447e3f1SAlexandru Ardelean 	ADIS16400_AUX_ADC_CHAN(ADIS16400_AUX_ADC, 12),
8305447e3f1SAlexandru Ardelean 	IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
8315447e3f1SAlexandru Ardelean };
8325447e3f1SAlexandru Ardelean 
8335447e3f1SAlexandru Ardelean static const struct iio_chan_spec adis16445_channels[] = {
8345447e3f1SAlexandru Ardelean 	ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 16),
8355447e3f1SAlexandru Ardelean 	ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 16),
8365447e3f1SAlexandru Ardelean 	ADIS16400_GYRO_CHAN(Z, ADIS16400_ZGYRO_OUT, 16),
8375447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 16),
8385447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 16),
8395447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 16),
8405447e3f1SAlexandru Ardelean 	ADIS16400_TEMP_CHAN(ADIS16448_TEMP_OUT, 12),
8415447e3f1SAlexandru Ardelean 	IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
8425447e3f1SAlexandru Ardelean };
8435447e3f1SAlexandru Ardelean 
8445447e3f1SAlexandru Ardelean static const struct iio_chan_spec adis16448_channels[] = {
8455447e3f1SAlexandru Ardelean 	ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 16),
8465447e3f1SAlexandru Ardelean 	ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 16),
8475447e3f1SAlexandru Ardelean 	ADIS16400_GYRO_CHAN(Z, ADIS16400_ZGYRO_OUT, 16),
8485447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 16),
8495447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 16),
8505447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 16),
8515447e3f1SAlexandru Ardelean 	ADIS16400_MAGN_CHAN(X, ADIS16400_XMAGN_OUT, 16),
8525447e3f1SAlexandru Ardelean 	ADIS16400_MAGN_CHAN(Y, ADIS16400_YMAGN_OUT, 16),
8535447e3f1SAlexandru Ardelean 	ADIS16400_MAGN_CHAN(Z, ADIS16400_ZMAGN_OUT, 16),
8545447e3f1SAlexandru Ardelean 	{
8555447e3f1SAlexandru Ardelean 		.type = IIO_PRESSURE,
8565447e3f1SAlexandru Ardelean 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
8575447e3f1SAlexandru Ardelean 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
8585447e3f1SAlexandru Ardelean 		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
8595447e3f1SAlexandru Ardelean 		.address = ADIS16448_BARO_OUT,
8605447e3f1SAlexandru Ardelean 		.scan_index = ADIS16400_SCAN_BARO,
8615447e3f1SAlexandru Ardelean 		.scan_type = {
8625447e3f1SAlexandru Ardelean 			.sign = 's',
8635447e3f1SAlexandru Ardelean 			.realbits = 16,
8645447e3f1SAlexandru Ardelean 			.storagebits = 16,
8655447e3f1SAlexandru Ardelean 			.endianness = IIO_BE,
8665447e3f1SAlexandru Ardelean 		},
8675447e3f1SAlexandru Ardelean 	},
8685447e3f1SAlexandru Ardelean 	ADIS16400_TEMP_CHAN(ADIS16448_TEMP_OUT, 12),
8695447e3f1SAlexandru Ardelean 	IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
8705447e3f1SAlexandru Ardelean };
8715447e3f1SAlexandru Ardelean 
8725447e3f1SAlexandru Ardelean static const struct iio_chan_spec adis16350_channels[] = {
8735447e3f1SAlexandru Ardelean 	ADIS16400_SUPPLY_CHAN(ADIS16400_SUPPLY_OUT, 12),
8745447e3f1SAlexandru Ardelean 	ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 14),
8755447e3f1SAlexandru Ardelean 	ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 14),
8765447e3f1SAlexandru Ardelean 	ADIS16400_GYRO_CHAN(Z, ADIS16400_ZGYRO_OUT, 14),
8775447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 14),
8785447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 14),
8795447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 14),
8805447e3f1SAlexandru Ardelean 	ADIS16400_MAGN_CHAN(X, ADIS16400_XMAGN_OUT, 14),
8815447e3f1SAlexandru Ardelean 	ADIS16400_MAGN_CHAN(Y, ADIS16400_YMAGN_OUT, 14),
8825447e3f1SAlexandru Ardelean 	ADIS16400_MAGN_CHAN(Z, ADIS16400_ZMAGN_OUT, 14),
8835447e3f1SAlexandru Ardelean 	ADIS16400_AUX_ADC_CHAN(ADIS16300_AUX_ADC, 12),
8845447e3f1SAlexandru Ardelean 	ADIS16400_MOD_TEMP_CHAN(X, ADIS16350_XTEMP_OUT, 12),
8855447e3f1SAlexandru Ardelean 	ADIS16400_MOD_TEMP_CHAN(Y, ADIS16350_YTEMP_OUT, 12),
8865447e3f1SAlexandru Ardelean 	ADIS16400_MOD_TEMP_CHAN(Z, ADIS16350_ZTEMP_OUT, 12),
8875447e3f1SAlexandru Ardelean 	IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
8885447e3f1SAlexandru Ardelean };
8895447e3f1SAlexandru Ardelean 
8905447e3f1SAlexandru Ardelean static const struct iio_chan_spec adis16300_channels[] = {
8915447e3f1SAlexandru Ardelean 	ADIS16400_SUPPLY_CHAN(ADIS16400_SUPPLY_OUT, 12),
8925447e3f1SAlexandru Ardelean 	ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 14),
8935447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 14),
8945447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 14),
8955447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 14),
8965447e3f1SAlexandru Ardelean 	ADIS16400_TEMP_CHAN(ADIS16350_XTEMP_OUT, 12),
8975447e3f1SAlexandru Ardelean 	ADIS16400_AUX_ADC_CHAN(ADIS16300_AUX_ADC, 12),
8985447e3f1SAlexandru Ardelean 	ADIS16400_INCLI_CHAN(X, ADIS16300_PITCH_OUT, 13),
8995447e3f1SAlexandru Ardelean 	ADIS16400_INCLI_CHAN(Y, ADIS16300_ROLL_OUT, 13),
9005447e3f1SAlexandru Ardelean 	IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
9015447e3f1SAlexandru Ardelean };
9025447e3f1SAlexandru Ardelean 
9035447e3f1SAlexandru Ardelean static const struct iio_chan_spec adis16334_channels[] = {
9045447e3f1SAlexandru Ardelean 	ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 14),
9055447e3f1SAlexandru Ardelean 	ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 14),
9065447e3f1SAlexandru Ardelean 	ADIS16400_GYRO_CHAN(Z, ADIS16400_ZGYRO_OUT, 14),
9075447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 14),
9085447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 14),
9095447e3f1SAlexandru Ardelean 	ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 14),
9105447e3f1SAlexandru Ardelean 	ADIS16400_TEMP_CHAN(ADIS16350_XTEMP_OUT, 12),
9115447e3f1SAlexandru Ardelean 	IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
9125447e3f1SAlexandru Ardelean };
9135447e3f1SAlexandru Ardelean 
91499460853SAlexandru Ardelean static const char * const adis16400_status_error_msgs[] = {
91599460853SAlexandru Ardelean 	[ADIS16400_DIAG_STAT_ZACCL_FAIL] = "Z-axis accelerometer self-test failure",
91699460853SAlexandru Ardelean 	[ADIS16400_DIAG_STAT_YACCL_FAIL] = "Y-axis accelerometer self-test failure",
91799460853SAlexandru Ardelean 	[ADIS16400_DIAG_STAT_XACCL_FAIL] = "X-axis accelerometer self-test failure",
91899460853SAlexandru Ardelean 	[ADIS16400_DIAG_STAT_XGYRO_FAIL] = "X-axis gyroscope self-test failure",
91999460853SAlexandru Ardelean 	[ADIS16400_DIAG_STAT_YGYRO_FAIL] = "Y-axis gyroscope self-test failure",
92099460853SAlexandru Ardelean 	[ADIS16400_DIAG_STAT_ZGYRO_FAIL] = "Z-axis gyroscope self-test failure",
92199460853SAlexandru Ardelean 	[ADIS16400_DIAG_STAT_ALARM2] = "Alarm 2 active",
92299460853SAlexandru Ardelean 	[ADIS16400_DIAG_STAT_ALARM1] = "Alarm 1 active",
92399460853SAlexandru Ardelean 	[ADIS16400_DIAG_STAT_FLASH_CHK] = "Flash checksum error",
92499460853SAlexandru Ardelean 	[ADIS16400_DIAG_STAT_SELF_TEST] = "Self test error",
92599460853SAlexandru Ardelean 	[ADIS16400_DIAG_STAT_OVERFLOW] = "Sensor overrange",
92699460853SAlexandru Ardelean 	[ADIS16400_DIAG_STAT_SPI_FAIL] = "SPI failure",
92799460853SAlexandru Ardelean 	[ADIS16400_DIAG_STAT_FLASH_UPT] = "Flash update failed",
92899460853SAlexandru Ardelean 	[ADIS16400_DIAG_STAT_POWER_HIGH] = "Power supply above 5.25V",
92999460853SAlexandru Ardelean 	[ADIS16400_DIAG_STAT_POWER_LOW] = "Power supply below 4.75V",
93099460853SAlexandru Ardelean };
93199460853SAlexandru Ardelean 
932f81d053bSNuno Sá #define ADIS16400_DATA(_timeouts, _burst_len)				\
93399460853SAlexandru Ardelean {									\
93499460853SAlexandru Ardelean 	.msc_ctrl_reg = ADIS16400_MSC_CTRL,				\
93599460853SAlexandru Ardelean 	.glob_cmd_reg = ADIS16400_GLOB_CMD,				\
93699460853SAlexandru Ardelean 	.diag_stat_reg = ADIS16400_DIAG_STAT,				\
93799460853SAlexandru Ardelean 	.read_delay = 50,						\
93899460853SAlexandru Ardelean 	.write_delay = 50,						\
93999460853SAlexandru Ardelean 	.self_test_mask = ADIS16400_MSC_CTRL_MEM_TEST,			\
940fdcf6bbbSNuno Sá 	.self_test_reg = ADIS16400_MSC_CTRL,				\
94199460853SAlexandru Ardelean 	.status_error_msgs = adis16400_status_error_msgs,		\
94299460853SAlexandru Ardelean 	.status_error_mask = BIT(ADIS16400_DIAG_STAT_ZACCL_FAIL) |	\
94399460853SAlexandru Ardelean 		BIT(ADIS16400_DIAG_STAT_YACCL_FAIL) |			\
94499460853SAlexandru Ardelean 		BIT(ADIS16400_DIAG_STAT_XACCL_FAIL) |			\
94599460853SAlexandru Ardelean 		BIT(ADIS16400_DIAG_STAT_XGYRO_FAIL) |			\
94699460853SAlexandru Ardelean 		BIT(ADIS16400_DIAG_STAT_YGYRO_FAIL) |			\
94799460853SAlexandru Ardelean 		BIT(ADIS16400_DIAG_STAT_ZGYRO_FAIL) |			\
94899460853SAlexandru Ardelean 		BIT(ADIS16400_DIAG_STAT_ALARM2) |			\
94999460853SAlexandru Ardelean 		BIT(ADIS16400_DIAG_STAT_ALARM1) |			\
95099460853SAlexandru Ardelean 		BIT(ADIS16400_DIAG_STAT_FLASH_CHK) |			\
95199460853SAlexandru Ardelean 		BIT(ADIS16400_DIAG_STAT_SELF_TEST) |			\
95299460853SAlexandru Ardelean 		BIT(ADIS16400_DIAG_STAT_OVERFLOW) |			\
95399460853SAlexandru Ardelean 		BIT(ADIS16400_DIAG_STAT_SPI_FAIL) |			\
95499460853SAlexandru Ardelean 		BIT(ADIS16400_DIAG_STAT_FLASH_UPT) |			\
95599460853SAlexandru Ardelean 		BIT(ADIS16400_DIAG_STAT_POWER_HIGH) |			\
95699460853SAlexandru Ardelean 		BIT(ADIS16400_DIAG_STAT_POWER_LOW),			\
95799460853SAlexandru Ardelean 	.timeouts = (_timeouts),					\
958f81d053bSNuno Sá 	.burst_reg_cmd = ADIS16400_GLOB_CMD,				\
959b27e1970SNuno Sa 	.burst_len = (_burst_len),					\
960b27e1970SNuno Sa 	.burst_max_speed_hz = ADIS16400_SPI_BURST			\
96199460853SAlexandru Ardelean }
96299460853SAlexandru Ardelean 
963380b107bSNuno Sá static const struct adis_timeout adis16300_timeouts = {
964380b107bSNuno Sá 	.reset_ms = ADIS16400_STARTUP_DELAY,
965380b107bSNuno Sá 	.sw_reset_ms = ADIS16400_STARTUP_DELAY,
966380b107bSNuno Sá 	.self_test_ms = ADIS16400_STARTUP_DELAY,
967380b107bSNuno Sá };
968380b107bSNuno Sá 
96999460853SAlexandru Ardelean static const struct adis_timeout adis16334_timeouts = {
97099460853SAlexandru Ardelean 	.reset_ms = 60,
97199460853SAlexandru Ardelean 	.sw_reset_ms = 60,
97299460853SAlexandru Ardelean 	.self_test_ms = 14,
97399460853SAlexandru Ardelean };
97499460853SAlexandru Ardelean 
975380b107bSNuno Sá static const struct adis_timeout adis16362_timeouts = {
976380b107bSNuno Sá 	.reset_ms = 130,
977380b107bSNuno Sá 	.sw_reset_ms = 130,
978380b107bSNuno Sá 	.self_test_ms = 12,
979380b107bSNuno Sá };
980380b107bSNuno Sá 
981380b107bSNuno Sá static const struct adis_timeout adis16400_timeouts = {
982380b107bSNuno Sá 	.reset_ms = 170,
983380b107bSNuno Sá 	.sw_reset_ms = 170,
984380b107bSNuno Sá 	.self_test_ms = 12,
985380b107bSNuno Sá };
986380b107bSNuno Sá 
987380b107bSNuno Sá static const struct adis_timeout adis16445_timeouts = {
988380b107bSNuno Sá 	.reset_ms = 55,
989380b107bSNuno Sá 	.sw_reset_ms = 55,
990380b107bSNuno Sá 	.self_test_ms = 16,
991380b107bSNuno Sá };
992380b107bSNuno Sá 
993380b107bSNuno Sá static const struct adis_timeout adis16448_timeouts = {
994380b107bSNuno Sá 	.reset_ms = 90,
995380b107bSNuno Sá 	.sw_reset_ms = 90,
996380b107bSNuno Sá 	.self_test_ms = 45,
997380b107bSNuno Sá };
998380b107bSNuno Sá 
9995447e3f1SAlexandru Ardelean static struct adis16400_chip_info adis16400_chips[] = {
10005447e3f1SAlexandru Ardelean 	[ADIS16300] = {
10015447e3f1SAlexandru Ardelean 		.channels = adis16300_channels,
10025447e3f1SAlexandru Ardelean 		.num_channels = ARRAY_SIZE(adis16300_channels),
10035447e3f1SAlexandru Ardelean 		.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE |
10045447e3f1SAlexandru Ardelean 				ADIS16400_HAS_SERIAL_NUMBER,
10055447e3f1SAlexandru Ardelean 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
10065447e3f1SAlexandru Ardelean 		.accel_scale_micro = 5884,
10075447e3f1SAlexandru Ardelean 		.temp_scale_nano = 140000000, /* 0.14 C */
10085447e3f1SAlexandru Ardelean 		.temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
10095447e3f1SAlexandru Ardelean 		.set_freq = adis16400_set_freq,
10105447e3f1SAlexandru Ardelean 		.get_freq = adis16400_get_freq,
1011f81d053bSNuno Sá 		.adis_data = ADIS16400_DATA(&adis16300_timeouts, 18),
10125447e3f1SAlexandru Ardelean 	},
10135447e3f1SAlexandru Ardelean 	[ADIS16334] = {
10145447e3f1SAlexandru Ardelean 		.channels = adis16334_channels,
10155447e3f1SAlexandru Ardelean 		.num_channels = ARRAY_SIZE(adis16334_channels),
10165447e3f1SAlexandru Ardelean 		.flags = ADIS16400_HAS_PROD_ID | ADIS16400_NO_BURST |
10175447e3f1SAlexandru Ardelean 				ADIS16400_HAS_SERIAL_NUMBER,
10185447e3f1SAlexandru Ardelean 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
10195447e3f1SAlexandru Ardelean 		.accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
10205447e3f1SAlexandru Ardelean 		.temp_scale_nano = 67850000, /* 0.06785 C */
10215447e3f1SAlexandru Ardelean 		.temp_offset = 25000000 / 67850, /* 25 C = 0x00 */
10225447e3f1SAlexandru Ardelean 		.set_freq = adis16334_set_freq,
10235447e3f1SAlexandru Ardelean 		.get_freq = adis16334_get_freq,
1024f81d053bSNuno Sá 		.adis_data = ADIS16400_DATA(&adis16334_timeouts, 0),
10255447e3f1SAlexandru Ardelean 	},
10265447e3f1SAlexandru Ardelean 	[ADIS16350] = {
10275447e3f1SAlexandru Ardelean 		.channels = adis16350_channels,
10285447e3f1SAlexandru Ardelean 		.num_channels = ARRAY_SIZE(adis16350_channels),
10295447e3f1SAlexandru Ardelean 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(73260), /* 0.07326 deg/s */
10305447e3f1SAlexandru Ardelean 		.accel_scale_micro = IIO_G_TO_M_S_2(2522), /* 0.002522 g */
10315447e3f1SAlexandru Ardelean 		.temp_scale_nano = 145300000, /* 0.1453 C */
10325447e3f1SAlexandru Ardelean 		.temp_offset = 25000000 / 145300, /* 25 C = 0x00 */
10335447e3f1SAlexandru Ardelean 		.flags = ADIS16400_NO_BURST | ADIS16400_HAS_SLOW_MODE,
10345447e3f1SAlexandru Ardelean 		.set_freq = adis16400_set_freq,
10355447e3f1SAlexandru Ardelean 		.get_freq = adis16400_get_freq,
1036f81d053bSNuno Sá 		.adis_data = ADIS16400_DATA(&adis16300_timeouts, 0),
10375447e3f1SAlexandru Ardelean 	},
10385447e3f1SAlexandru Ardelean 	[ADIS16360] = {
10395447e3f1SAlexandru Ardelean 		.channels = adis16350_channels,
10405447e3f1SAlexandru Ardelean 		.num_channels = ARRAY_SIZE(adis16350_channels),
10415447e3f1SAlexandru Ardelean 		.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE |
10425447e3f1SAlexandru Ardelean 				ADIS16400_HAS_SERIAL_NUMBER,
10435447e3f1SAlexandru Ardelean 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
10445447e3f1SAlexandru Ardelean 		.accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
10455447e3f1SAlexandru Ardelean 		.temp_scale_nano = 136000000, /* 0.136 C */
10465447e3f1SAlexandru Ardelean 		.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
10475447e3f1SAlexandru Ardelean 		.set_freq = adis16400_set_freq,
10485447e3f1SAlexandru Ardelean 		.get_freq = adis16400_get_freq,
1049f81d053bSNuno Sá 		.adis_data = ADIS16400_DATA(&adis16300_timeouts, 28),
10505447e3f1SAlexandru Ardelean 	},
10515447e3f1SAlexandru Ardelean 	[ADIS16362] = {
10525447e3f1SAlexandru Ardelean 		.channels = adis16350_channels,
10535447e3f1SAlexandru Ardelean 		.num_channels = ARRAY_SIZE(adis16350_channels),
10545447e3f1SAlexandru Ardelean 		.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE |
10555447e3f1SAlexandru Ardelean 				ADIS16400_HAS_SERIAL_NUMBER,
10565447e3f1SAlexandru Ardelean 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
10575447e3f1SAlexandru Ardelean 		.accel_scale_micro = IIO_G_TO_M_S_2(333), /* 0.333 mg */
10585447e3f1SAlexandru Ardelean 		.temp_scale_nano = 136000000, /* 0.136 C */
10595447e3f1SAlexandru Ardelean 		.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
10605447e3f1SAlexandru Ardelean 		.set_freq = adis16400_set_freq,
10615447e3f1SAlexandru Ardelean 		.get_freq = adis16400_get_freq,
1062f81d053bSNuno Sá 		.adis_data = ADIS16400_DATA(&adis16362_timeouts, 28),
10635447e3f1SAlexandru Ardelean 	},
10645447e3f1SAlexandru Ardelean 	[ADIS16364] = {
10655447e3f1SAlexandru Ardelean 		.channels = adis16350_channels,
10665447e3f1SAlexandru Ardelean 		.num_channels = ARRAY_SIZE(adis16350_channels),
10675447e3f1SAlexandru Ardelean 		.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE |
10685447e3f1SAlexandru Ardelean 				ADIS16400_HAS_SERIAL_NUMBER,
10695447e3f1SAlexandru Ardelean 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
10705447e3f1SAlexandru Ardelean 		.accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
10715447e3f1SAlexandru Ardelean 		.temp_scale_nano = 136000000, /* 0.136 C */
10725447e3f1SAlexandru Ardelean 		.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
10735447e3f1SAlexandru Ardelean 		.set_freq = adis16400_set_freq,
10745447e3f1SAlexandru Ardelean 		.get_freq = adis16400_get_freq,
1075f81d053bSNuno Sá 		.adis_data = ADIS16400_DATA(&adis16362_timeouts, 28),
10765447e3f1SAlexandru Ardelean 	},
10775447e3f1SAlexandru Ardelean 	[ADIS16367] = {
10785447e3f1SAlexandru Ardelean 		.channels = adis16350_channels,
10795447e3f1SAlexandru Ardelean 		.num_channels = ARRAY_SIZE(adis16350_channels),
10805447e3f1SAlexandru Ardelean 		.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE |
10815447e3f1SAlexandru Ardelean 				ADIS16400_HAS_SERIAL_NUMBER,
10825447e3f1SAlexandru Ardelean 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(2000), /* 0.2 deg/s */
10835447e3f1SAlexandru Ardelean 		.accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
10845447e3f1SAlexandru Ardelean 		.temp_scale_nano = 136000000, /* 0.136 C */
10855447e3f1SAlexandru Ardelean 		.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
10865447e3f1SAlexandru Ardelean 		.set_freq = adis16400_set_freq,
10875447e3f1SAlexandru Ardelean 		.get_freq = adis16400_get_freq,
1088f81d053bSNuno Sá 		.adis_data = ADIS16400_DATA(&adis16300_timeouts, 28),
10895447e3f1SAlexandru Ardelean 	},
10905447e3f1SAlexandru Ardelean 	[ADIS16400] = {
10915447e3f1SAlexandru Ardelean 		.channels = adis16400_channels,
10925447e3f1SAlexandru Ardelean 		.num_channels = ARRAY_SIZE(adis16400_channels),
10935447e3f1SAlexandru Ardelean 		.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
10945447e3f1SAlexandru Ardelean 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
10955447e3f1SAlexandru Ardelean 		.accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
10965447e3f1SAlexandru Ardelean 		.temp_scale_nano = 140000000, /* 0.14 C */
10975447e3f1SAlexandru Ardelean 		.temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
10985447e3f1SAlexandru Ardelean 		.set_freq = adis16400_set_freq,
10995447e3f1SAlexandru Ardelean 		.get_freq = adis16400_get_freq,
1100f81d053bSNuno Sá 		.adis_data = ADIS16400_DATA(&adis16400_timeouts, 24),
11015447e3f1SAlexandru Ardelean 	},
11025447e3f1SAlexandru Ardelean 	[ADIS16445] = {
11035447e3f1SAlexandru Ardelean 		.channels = adis16445_channels,
11045447e3f1SAlexandru Ardelean 		.num_channels = ARRAY_SIZE(adis16445_channels),
11055447e3f1SAlexandru Ardelean 		.flags = ADIS16400_HAS_PROD_ID |
11065447e3f1SAlexandru Ardelean 				ADIS16400_HAS_SERIAL_NUMBER |
11075447e3f1SAlexandru Ardelean 				ADIS16400_BURST_DIAG_STAT,
11085447e3f1SAlexandru Ardelean 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(10000), /* 0.01 deg/s */
11095447e3f1SAlexandru Ardelean 		.accel_scale_micro = IIO_G_TO_M_S_2(250), /* 1/4000 g */
11105447e3f1SAlexandru Ardelean 		.temp_scale_nano = 73860000, /* 0.07386 C */
11115447e3f1SAlexandru Ardelean 		.temp_offset = 31000000 / 73860, /* 31 C = 0x00 */
11125447e3f1SAlexandru Ardelean 		.set_freq = adis16334_set_freq,
11135447e3f1SAlexandru Ardelean 		.get_freq = adis16334_get_freq,
1114f81d053bSNuno Sá 		.adis_data = ADIS16400_DATA(&adis16445_timeouts, 16),
11155447e3f1SAlexandru Ardelean 	},
11165447e3f1SAlexandru Ardelean 	[ADIS16448] = {
11175447e3f1SAlexandru Ardelean 		.channels = adis16448_channels,
11185447e3f1SAlexandru Ardelean 		.num_channels = ARRAY_SIZE(adis16448_channels),
11195447e3f1SAlexandru Ardelean 		.flags = ADIS16400_HAS_PROD_ID |
11205447e3f1SAlexandru Ardelean 				ADIS16400_HAS_SERIAL_NUMBER |
11215447e3f1SAlexandru Ardelean 				ADIS16400_BURST_DIAG_STAT,
11225447e3f1SAlexandru Ardelean 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(40000), /* 0.04 deg/s */
11235447e3f1SAlexandru Ardelean 		.accel_scale_micro = IIO_G_TO_M_S_2(833), /* 1/1200 g */
11245447e3f1SAlexandru Ardelean 		.temp_scale_nano = 73860000, /* 0.07386 C */
11255447e3f1SAlexandru Ardelean 		.temp_offset = 31000000 / 73860, /* 31 C = 0x00 */
11265447e3f1SAlexandru Ardelean 		.set_freq = adis16334_set_freq,
11275447e3f1SAlexandru Ardelean 		.get_freq = adis16334_get_freq,
1128f81d053bSNuno Sá 		.adis_data = ADIS16400_DATA(&adis16448_timeouts, 24),
11295447e3f1SAlexandru Ardelean 	}
11305447e3f1SAlexandru Ardelean };
11315447e3f1SAlexandru Ardelean 
11325447e3f1SAlexandru Ardelean static const struct iio_info adis16400_info = {
11335447e3f1SAlexandru Ardelean 	.read_raw = &adis16400_read_raw,
11345447e3f1SAlexandru Ardelean 	.write_raw = &adis16400_write_raw,
11355447e3f1SAlexandru Ardelean 	.update_scan_mode = adis_update_scan_mode,
11365447e3f1SAlexandru Ardelean 	.debugfs_reg_access = adis_debugfs_reg_access,
11375447e3f1SAlexandru Ardelean };
11385447e3f1SAlexandru Ardelean 
adis16400_setup_chan_mask(struct adis16400_state * st)11395447e3f1SAlexandru Ardelean static void adis16400_setup_chan_mask(struct adis16400_state *st)
11405447e3f1SAlexandru Ardelean {
11415447e3f1SAlexandru Ardelean 	const struct adis16400_chip_info *chip_info = st->variant;
11425447e3f1SAlexandru Ardelean 	unsigned int i;
11435447e3f1SAlexandru Ardelean 
11445447e3f1SAlexandru Ardelean 	for (i = 0; i < chip_info->num_channels; i++) {
11455447e3f1SAlexandru Ardelean 		const struct iio_chan_spec *ch = &chip_info->channels[i];
11465447e3f1SAlexandru Ardelean 
11475447e3f1SAlexandru Ardelean 		if (ch->scan_index >= 0 &&
11485447e3f1SAlexandru Ardelean 		    ch->scan_index != ADIS16400_SCAN_TIMESTAMP)
11495447e3f1SAlexandru Ardelean 			st->avail_scan_mask[0] |= BIT(ch->scan_index);
11505447e3f1SAlexandru Ardelean 	}
11515447e3f1SAlexandru Ardelean }
1152f13aa064SNuno Sá 
adis16400_stop(void * data)1153f13aa064SNuno Sá static void adis16400_stop(void *data)
1154f13aa064SNuno Sá {
1155f13aa064SNuno Sá 	adis16400_stop_device(data);
1156f13aa064SNuno Sá }
1157f13aa064SNuno Sá 
adis16400_probe(struct spi_device * spi)11585447e3f1SAlexandru Ardelean static int adis16400_probe(struct spi_device *spi)
11595447e3f1SAlexandru Ardelean {
11605447e3f1SAlexandru Ardelean 	struct adis16400_state *st;
11615447e3f1SAlexandru Ardelean 	struct iio_dev *indio_dev;
11625447e3f1SAlexandru Ardelean 	int ret;
1163380b107bSNuno Sá 	const struct adis_data *adis16400_data;
11645447e3f1SAlexandru Ardelean 
11655447e3f1SAlexandru Ardelean 	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
11665447e3f1SAlexandru Ardelean 	if (indio_dev == NULL)
11675447e3f1SAlexandru Ardelean 		return -ENOMEM;
11685447e3f1SAlexandru Ardelean 
11695447e3f1SAlexandru Ardelean 	st = iio_priv(indio_dev);
11705447e3f1SAlexandru Ardelean 
11715447e3f1SAlexandru Ardelean 	/* setup the industrialio driver allocated elements */
11725447e3f1SAlexandru Ardelean 	st->variant = &adis16400_chips[spi_get_device_id(spi)->driver_data];
11735447e3f1SAlexandru Ardelean 	indio_dev->name = spi_get_device_id(spi)->name;
11745447e3f1SAlexandru Ardelean 	indio_dev->channels = st->variant->channels;
11755447e3f1SAlexandru Ardelean 	indio_dev->num_channels = st->variant->num_channels;
11765447e3f1SAlexandru Ardelean 	indio_dev->info = &adis16400_info;
11775447e3f1SAlexandru Ardelean 	indio_dev->modes = INDIO_DIRECT_MODE;
11785447e3f1SAlexandru Ardelean 
11795447e3f1SAlexandru Ardelean 	if (!(st->variant->flags & ADIS16400_NO_BURST)) {
11805447e3f1SAlexandru Ardelean 		adis16400_setup_chan_mask(st);
11815447e3f1SAlexandru Ardelean 		indio_dev->available_scan_masks = st->avail_scan_mask;
11825447e3f1SAlexandru Ardelean 	}
11835447e3f1SAlexandru Ardelean 
118499460853SAlexandru Ardelean 	adis16400_data = &st->variant->adis_data;
1185380b107bSNuno Sá 
1186380b107bSNuno Sá 	ret = adis_init(&st->adis, indio_dev, spi, adis16400_data);
11875447e3f1SAlexandru Ardelean 	if (ret)
11885447e3f1SAlexandru Ardelean 		return ret;
11895447e3f1SAlexandru Ardelean 
1190f13aa064SNuno Sá 	ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, adis16400_trigger_handler);
11915447e3f1SAlexandru Ardelean 	if (ret)
11925447e3f1SAlexandru Ardelean 		return ret;
11935447e3f1SAlexandru Ardelean 
11945447e3f1SAlexandru Ardelean 	/* Get the device into a sane initial state */
11955447e3f1SAlexandru Ardelean 	ret = adis16400_initial_setup(indio_dev);
11965447e3f1SAlexandru Ardelean 	if (ret)
1197f13aa064SNuno Sá 		return ret;
1198f13aa064SNuno Sá 
1199f13aa064SNuno Sá 	ret = devm_add_action_or_reset(&spi->dev, adis16400_stop, indio_dev);
12005447e3f1SAlexandru Ardelean 	if (ret)
1201f13aa064SNuno Sá 		return ret;
1202f13aa064SNuno Sá 
1203f13aa064SNuno Sá 	ret = devm_iio_device_register(&spi->dev, indio_dev);
1204f13aa064SNuno Sá 	if (ret)
1205f13aa064SNuno Sá 		return ret;
12065447e3f1SAlexandru Ardelean 
12075447e3f1SAlexandru Ardelean 	adis16400_debugfs_init(indio_dev);
12085447e3f1SAlexandru Ardelean 	return 0;
12095447e3f1SAlexandru Ardelean }
12105447e3f1SAlexandru Ardelean 
12115447e3f1SAlexandru Ardelean static const struct spi_device_id adis16400_id[] = {
12125447e3f1SAlexandru Ardelean 	{"adis16300", ADIS16300},
12135447e3f1SAlexandru Ardelean 	{"adis16305", ADIS16300},
12145447e3f1SAlexandru Ardelean 	{"adis16334", ADIS16334},
12155447e3f1SAlexandru Ardelean 	{"adis16350", ADIS16350},
12165447e3f1SAlexandru Ardelean 	{"adis16354", ADIS16350},
12175447e3f1SAlexandru Ardelean 	{"adis16355", ADIS16350},
12185447e3f1SAlexandru Ardelean 	{"adis16360", ADIS16360},
12195447e3f1SAlexandru Ardelean 	{"adis16362", ADIS16362},
12205447e3f1SAlexandru Ardelean 	{"adis16364", ADIS16364},
12215447e3f1SAlexandru Ardelean 	{"adis16365", ADIS16360},
12225447e3f1SAlexandru Ardelean 	{"adis16367", ADIS16367},
12235447e3f1SAlexandru Ardelean 	{"adis16400", ADIS16400},
12245447e3f1SAlexandru Ardelean 	{"adis16405", ADIS16400},
12255447e3f1SAlexandru Ardelean 	{"adis16445", ADIS16445},
12265447e3f1SAlexandru Ardelean 	{"adis16448", ADIS16448},
12275447e3f1SAlexandru Ardelean 	{}
12285447e3f1SAlexandru Ardelean };
12295447e3f1SAlexandru Ardelean MODULE_DEVICE_TABLE(spi, adis16400_id);
12305447e3f1SAlexandru Ardelean 
12315447e3f1SAlexandru Ardelean static struct spi_driver adis16400_driver = {
12325447e3f1SAlexandru Ardelean 	.driver = {
12335447e3f1SAlexandru Ardelean 		.name = "adis16400",
12345447e3f1SAlexandru Ardelean 	},
12355447e3f1SAlexandru Ardelean 	.id_table = adis16400_id,
12365447e3f1SAlexandru Ardelean 	.probe = adis16400_probe,
12375447e3f1SAlexandru Ardelean };
12385447e3f1SAlexandru Ardelean module_spi_driver(adis16400_driver);
12395447e3f1SAlexandru Ardelean 
12405447e3f1SAlexandru Ardelean MODULE_AUTHOR("Manuel Stahl <manuel.stahl@iis.fraunhofer.de>");
12415447e3f1SAlexandru Ardelean MODULE_DESCRIPTION("Analog Devices ADIS16400/5 IMU SPI driver");
12425447e3f1SAlexandru Ardelean MODULE_LICENSE("GPL v2");
12436c9304d6SJonathan Cameron MODULE_IMPORT_NS(IIO_ADISLIB);
1244