162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * ADIS16260/ADIS16265 Programmable Digital Gyroscope Sensor Driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2010 Analog Devices Inc.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/device.h>
962306a36Sopenharmony_ci#include <linux/kernel.h>
1062306a36Sopenharmony_ci#include <linux/spi/spi.h>
1162306a36Sopenharmony_ci#include <linux/module.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/iio/iio.h>
1462306a36Sopenharmony_ci#include <linux/iio/imu/adis.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define ADIS16260_STARTUP_DELAY	220 /* ms */
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#define ADIS16260_FLASH_CNT  0x00 /* Flash memory write count */
1962306a36Sopenharmony_ci#define ADIS16260_SUPPLY_OUT 0x02 /* Power supply measurement */
2062306a36Sopenharmony_ci#define ADIS16260_GYRO_OUT   0x04 /* X-axis gyroscope output */
2162306a36Sopenharmony_ci#define ADIS16260_AUX_ADC    0x0A /* analog input channel measurement */
2262306a36Sopenharmony_ci#define ADIS16260_TEMP_OUT   0x0C /* internal temperature measurement */
2362306a36Sopenharmony_ci#define ADIS16260_ANGL_OUT   0x0E /* angle displacement */
2462306a36Sopenharmony_ci#define ADIS16260_GYRO_OFF   0x14 /* Calibration, offset/bias adjustment */
2562306a36Sopenharmony_ci#define ADIS16260_GYRO_SCALE 0x16 /* Calibration, scale adjustment */
2662306a36Sopenharmony_ci#define ADIS16260_ALM_MAG1   0x20 /* Alarm 1 magnitude/polarity setting */
2762306a36Sopenharmony_ci#define ADIS16260_ALM_MAG2   0x22 /* Alarm 2 magnitude/polarity setting */
2862306a36Sopenharmony_ci#define ADIS16260_ALM_SMPL1  0x24 /* Alarm 1 dynamic rate of change setting */
2962306a36Sopenharmony_ci#define ADIS16260_ALM_SMPL2  0x26 /* Alarm 2 dynamic rate of change setting */
3062306a36Sopenharmony_ci#define ADIS16260_ALM_CTRL   0x28 /* Alarm control */
3162306a36Sopenharmony_ci#define ADIS16260_AUX_DAC    0x30 /* Auxiliary DAC data */
3262306a36Sopenharmony_ci#define ADIS16260_GPIO_CTRL  0x32 /* Control, digital I/O line */
3362306a36Sopenharmony_ci#define ADIS16260_MSC_CTRL   0x34 /* Control, data ready, self-test settings */
3462306a36Sopenharmony_ci#define ADIS16260_SMPL_PRD   0x36 /* Control, internal sample rate */
3562306a36Sopenharmony_ci#define ADIS16260_SENS_AVG   0x38 /* Control, dynamic range, filtering */
3662306a36Sopenharmony_ci#define ADIS16260_SLP_CNT    0x3A /* Control, sleep mode initiation */
3762306a36Sopenharmony_ci#define ADIS16260_DIAG_STAT  0x3C /* Diagnostic, error flags */
3862306a36Sopenharmony_ci#define ADIS16260_GLOB_CMD   0x3E /* Control, global commands */
3962306a36Sopenharmony_ci#define ADIS16260_LOT_ID1    0x52 /* Lot Identification Code 1 */
4062306a36Sopenharmony_ci#define ADIS16260_LOT_ID2    0x54 /* Lot Identification Code 2 */
4162306a36Sopenharmony_ci#define ADIS16260_PROD_ID    0x56 /* Product identifier;
4262306a36Sopenharmony_ci				   * convert to decimal = 16,265/16,260 */
4362306a36Sopenharmony_ci#define ADIS16260_SERIAL_NUM 0x58 /* Serial number */
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#define ADIS16260_ERROR_ACTIVE			(1<<14)
4662306a36Sopenharmony_ci#define ADIS16260_NEW_DATA			(1<<15)
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci/* MSC_CTRL */
4962306a36Sopenharmony_ci#define ADIS16260_MSC_CTRL_MEM_TEST		(1<<11)
5062306a36Sopenharmony_ci/* Internal self-test enable */
5162306a36Sopenharmony_ci#define ADIS16260_MSC_CTRL_INT_SELF_TEST	(1<<10)
5262306a36Sopenharmony_ci#define ADIS16260_MSC_CTRL_NEG_SELF_TEST	(1<<9)
5362306a36Sopenharmony_ci#define ADIS16260_MSC_CTRL_POS_SELF_TEST	(1<<8)
5462306a36Sopenharmony_ci#define ADIS16260_MSC_CTRL_DATA_RDY_EN		(1<<2)
5562306a36Sopenharmony_ci#define ADIS16260_MSC_CTRL_DATA_RDY_POL_HIGH	(1<<1)
5662306a36Sopenharmony_ci#define ADIS16260_MSC_CTRL_DATA_RDY_DIO2	(1<<0)
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci/* SMPL_PRD */
5962306a36Sopenharmony_ci/* Time base (tB): 0 = 1.953 ms, 1 = 60.54 ms */
6062306a36Sopenharmony_ci#define ADIS16260_SMPL_PRD_TIME_BASE	(1<<7)
6162306a36Sopenharmony_ci#define ADIS16260_SMPL_PRD_DIV_MASK	0x7F
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci/* SLP_CNT */
6462306a36Sopenharmony_ci#define ADIS16260_SLP_CNT_POWER_OFF     0x80
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci/* DIAG_STAT */
6762306a36Sopenharmony_ci#define ADIS16260_DIAG_STAT_ALARM2	(1<<9)
6862306a36Sopenharmony_ci#define ADIS16260_DIAG_STAT_ALARM1	(1<<8)
6962306a36Sopenharmony_ci#define ADIS16260_DIAG_STAT_FLASH_CHK_BIT	6
7062306a36Sopenharmony_ci#define ADIS16260_DIAG_STAT_SELF_TEST_BIT	5
7162306a36Sopenharmony_ci#define ADIS16260_DIAG_STAT_OVERFLOW_BIT	4
7262306a36Sopenharmony_ci#define ADIS16260_DIAG_STAT_SPI_FAIL_BIT	3
7362306a36Sopenharmony_ci#define ADIS16260_DIAG_STAT_FLASH_UPT_BIT	2
7462306a36Sopenharmony_ci#define ADIS16260_DIAG_STAT_POWER_HIGH_BIT	1
7562306a36Sopenharmony_ci#define ADIS16260_DIAG_STAT_POWER_LOW_BIT	0
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci/* GLOB_CMD */
7862306a36Sopenharmony_ci#define ADIS16260_GLOB_CMD_SW_RESET	(1<<7)
7962306a36Sopenharmony_ci#define ADIS16260_GLOB_CMD_FLASH_UPD	(1<<3)
8062306a36Sopenharmony_ci#define ADIS16260_GLOB_CMD_DAC_LATCH	(1<<2)
8162306a36Sopenharmony_ci#define ADIS16260_GLOB_CMD_FAC_CALIB	(1<<1)
8262306a36Sopenharmony_ci#define ADIS16260_GLOB_CMD_AUTO_NULL	(1<<0)
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci#define ADIS16260_SPI_SLOW	(u32)(300 * 1000)
8562306a36Sopenharmony_ci#define ADIS16260_SPI_BURST	(u32)(1000 * 1000)
8662306a36Sopenharmony_ci#define ADIS16260_SPI_FAST	(u32)(2000 * 1000)
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci/* At the moment triggers are only used for ring buffer
8962306a36Sopenharmony_ci * filling. This may change!
9062306a36Sopenharmony_ci */
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci#define ADIS16260_SCAN_GYRO	0
9362306a36Sopenharmony_ci#define ADIS16260_SCAN_SUPPLY	1
9462306a36Sopenharmony_ci#define ADIS16260_SCAN_AUX_ADC	2
9562306a36Sopenharmony_ci#define ADIS16260_SCAN_TEMP	3
9662306a36Sopenharmony_ci#define ADIS16260_SCAN_ANGL	4
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistruct adis16260_chip_info {
9962306a36Sopenharmony_ci	unsigned int gyro_max_val;
10062306a36Sopenharmony_ci	unsigned int gyro_max_scale;
10162306a36Sopenharmony_ci	const struct iio_chan_spec *channels;
10262306a36Sopenharmony_ci	unsigned int num_channels;
10362306a36Sopenharmony_ci};
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistruct adis16260 {
10662306a36Sopenharmony_ci	const struct adis16260_chip_info *info;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	struct adis adis;
10962306a36Sopenharmony_ci};
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cienum adis16260_type {
11262306a36Sopenharmony_ci	ADIS16251,
11362306a36Sopenharmony_ci	ADIS16260,
11462306a36Sopenharmony_ci	ADIS16266,
11562306a36Sopenharmony_ci};
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic const struct iio_chan_spec adis16260_channels[] = {
11862306a36Sopenharmony_ci	ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
11962306a36Sopenharmony_ci		BIT(IIO_CHAN_INFO_CALIBBIAS) |
12062306a36Sopenharmony_ci		BIT(IIO_CHAN_INFO_CALIBSCALE),
12162306a36Sopenharmony_ci		BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
12262306a36Sopenharmony_ci	ADIS_INCLI_CHAN(X, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0,
12362306a36Sopenharmony_ci		BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
12462306a36Sopenharmony_ci	ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP,
12562306a36Sopenharmony_ci		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
12662306a36Sopenharmony_ci	ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY,
12762306a36Sopenharmony_ci		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
12862306a36Sopenharmony_ci	ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC,
12962306a36Sopenharmony_ci		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
13062306a36Sopenharmony_ci	IIO_CHAN_SOFT_TIMESTAMP(5),
13162306a36Sopenharmony_ci};
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cistatic const struct iio_chan_spec adis16266_channels[] = {
13462306a36Sopenharmony_ci	ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
13562306a36Sopenharmony_ci		BIT(IIO_CHAN_INFO_CALIBBIAS) |
13662306a36Sopenharmony_ci		BIT(IIO_CHAN_INFO_CALIBSCALE),
13762306a36Sopenharmony_ci		BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
13862306a36Sopenharmony_ci	ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP,
13962306a36Sopenharmony_ci		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
14062306a36Sopenharmony_ci	ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY,
14162306a36Sopenharmony_ci		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
14262306a36Sopenharmony_ci	ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC,
14362306a36Sopenharmony_ci		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
14462306a36Sopenharmony_ci	IIO_CHAN_SOFT_TIMESTAMP(4),
14562306a36Sopenharmony_ci};
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cistatic const struct adis16260_chip_info adis16260_chip_info_table[] = {
14862306a36Sopenharmony_ci	[ADIS16251] = {
14962306a36Sopenharmony_ci		.gyro_max_scale = 80,
15062306a36Sopenharmony_ci		.gyro_max_val = IIO_RAD_TO_DEGREE(4368),
15162306a36Sopenharmony_ci		.channels = adis16260_channels,
15262306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(adis16260_channels),
15362306a36Sopenharmony_ci	},
15462306a36Sopenharmony_ci	[ADIS16260] = {
15562306a36Sopenharmony_ci		.gyro_max_scale = 320,
15662306a36Sopenharmony_ci		.gyro_max_val = IIO_RAD_TO_DEGREE(4368),
15762306a36Sopenharmony_ci		.channels = adis16260_channels,
15862306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(adis16260_channels),
15962306a36Sopenharmony_ci	},
16062306a36Sopenharmony_ci	[ADIS16266] = {
16162306a36Sopenharmony_ci		.gyro_max_scale = 14000,
16262306a36Sopenharmony_ci		.gyro_max_val = IIO_RAD_TO_DEGREE(3357),
16362306a36Sopenharmony_ci		.channels = adis16266_channels,
16462306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(adis16266_channels),
16562306a36Sopenharmony_ci	},
16662306a36Sopenharmony_ci};
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci/* Power down the device */
16962306a36Sopenharmony_cistatic int adis16260_stop_device(struct iio_dev *indio_dev)
17062306a36Sopenharmony_ci{
17162306a36Sopenharmony_ci	struct adis16260 *adis16260 = iio_priv(indio_dev);
17262306a36Sopenharmony_ci	int ret;
17362306a36Sopenharmony_ci	u16 val = ADIS16260_SLP_CNT_POWER_OFF;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	ret = adis_write_reg_16(&adis16260->adis, ADIS16260_SLP_CNT, val);
17662306a36Sopenharmony_ci	if (ret)
17762306a36Sopenharmony_ci		dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	return ret;
18062306a36Sopenharmony_ci}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_cistatic const u8 adis16260_addresses[][2] = {
18362306a36Sopenharmony_ci	[ADIS16260_SCAN_GYRO] = { ADIS16260_GYRO_OFF, ADIS16260_GYRO_SCALE },
18462306a36Sopenharmony_ci};
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_cistatic int adis16260_read_raw(struct iio_dev *indio_dev,
18762306a36Sopenharmony_ci			      struct iio_chan_spec const *chan,
18862306a36Sopenharmony_ci			      int *val, int *val2,
18962306a36Sopenharmony_ci			      long mask)
19062306a36Sopenharmony_ci{
19162306a36Sopenharmony_ci	struct adis16260 *adis16260 = iio_priv(indio_dev);
19262306a36Sopenharmony_ci	const struct adis16260_chip_info *info = adis16260->info;
19362306a36Sopenharmony_ci	struct adis *adis = &adis16260->adis;
19462306a36Sopenharmony_ci	int ret;
19562306a36Sopenharmony_ci	u8 addr;
19662306a36Sopenharmony_ci	s16 val16;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	switch (mask) {
19962306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
20062306a36Sopenharmony_ci		return adis_single_conversion(indio_dev, chan,
20162306a36Sopenharmony_ci				ADIS16260_ERROR_ACTIVE, val);
20262306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
20362306a36Sopenharmony_ci		switch (chan->type) {
20462306a36Sopenharmony_ci		case IIO_ANGL_VEL:
20562306a36Sopenharmony_ci			*val = info->gyro_max_scale;
20662306a36Sopenharmony_ci			*val2 = info->gyro_max_val;
20762306a36Sopenharmony_ci			return IIO_VAL_FRACTIONAL;
20862306a36Sopenharmony_ci		case IIO_INCLI:
20962306a36Sopenharmony_ci			*val = 0;
21062306a36Sopenharmony_ci			*val2 = IIO_DEGREE_TO_RAD(36630);
21162306a36Sopenharmony_ci			return IIO_VAL_INT_PLUS_MICRO;
21262306a36Sopenharmony_ci		case IIO_VOLTAGE:
21362306a36Sopenharmony_ci			if (chan->channel == 0) {
21462306a36Sopenharmony_ci				*val = 1;
21562306a36Sopenharmony_ci				*val2 = 831500; /* 1.8315 mV */
21662306a36Sopenharmony_ci			} else {
21762306a36Sopenharmony_ci				*val = 0;
21862306a36Sopenharmony_ci				*val2 = 610500; /* 610.5 uV */
21962306a36Sopenharmony_ci			}
22062306a36Sopenharmony_ci			return IIO_VAL_INT_PLUS_MICRO;
22162306a36Sopenharmony_ci		case IIO_TEMP:
22262306a36Sopenharmony_ci			*val = 145;
22362306a36Sopenharmony_ci			*val2 = 300000; /* 0.1453 C */
22462306a36Sopenharmony_ci			return IIO_VAL_INT_PLUS_MICRO;
22562306a36Sopenharmony_ci		default:
22662306a36Sopenharmony_ci			return -EINVAL;
22762306a36Sopenharmony_ci		}
22862306a36Sopenharmony_ci	case IIO_CHAN_INFO_OFFSET:
22962306a36Sopenharmony_ci		*val = 250000 / 1453; /* 25 C = 0x00 */
23062306a36Sopenharmony_ci		return IIO_VAL_INT;
23162306a36Sopenharmony_ci	case IIO_CHAN_INFO_CALIBBIAS:
23262306a36Sopenharmony_ci		addr = adis16260_addresses[chan->scan_index][0];
23362306a36Sopenharmony_ci		ret = adis_read_reg_16(adis, addr, &val16);
23462306a36Sopenharmony_ci		if (ret)
23562306a36Sopenharmony_ci			return ret;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci		*val = sign_extend32(val16, 11);
23862306a36Sopenharmony_ci		return IIO_VAL_INT;
23962306a36Sopenharmony_ci	case IIO_CHAN_INFO_CALIBSCALE:
24062306a36Sopenharmony_ci		addr = adis16260_addresses[chan->scan_index][1];
24162306a36Sopenharmony_ci		ret = adis_read_reg_16(adis, addr, &val16);
24262306a36Sopenharmony_ci		if (ret)
24362306a36Sopenharmony_ci			return ret;
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci		*val = val16;
24662306a36Sopenharmony_ci		return IIO_VAL_INT;
24762306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
24862306a36Sopenharmony_ci		ret = adis_read_reg_16(adis, ADIS16260_SMPL_PRD, &val16);
24962306a36Sopenharmony_ci		if (ret)
25062306a36Sopenharmony_ci			return ret;
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci		if (spi_get_device_id(adis->spi)->driver_data)
25362306a36Sopenharmony_ci		/* If an adis16251 */
25462306a36Sopenharmony_ci			*val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ?
25562306a36Sopenharmony_ci				8 : 256;
25662306a36Sopenharmony_ci		else
25762306a36Sopenharmony_ci			*val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ?
25862306a36Sopenharmony_ci				66 : 2048;
25962306a36Sopenharmony_ci		*val /= (val16 & ADIS16260_SMPL_PRD_DIV_MASK) + 1;
26062306a36Sopenharmony_ci		return IIO_VAL_INT;
26162306a36Sopenharmony_ci	}
26262306a36Sopenharmony_ci	return -EINVAL;
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_cistatic int adis16260_write_raw(struct iio_dev *indio_dev,
26662306a36Sopenharmony_ci			       struct iio_chan_spec const *chan,
26762306a36Sopenharmony_ci			       int val,
26862306a36Sopenharmony_ci			       int val2,
26962306a36Sopenharmony_ci			       long mask)
27062306a36Sopenharmony_ci{
27162306a36Sopenharmony_ci	struct adis16260 *adis16260 = iio_priv(indio_dev);
27262306a36Sopenharmony_ci	struct adis *adis = &adis16260->adis;
27362306a36Sopenharmony_ci	int ret;
27462306a36Sopenharmony_ci	u8 addr;
27562306a36Sopenharmony_ci	u8 t;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	switch (mask) {
27862306a36Sopenharmony_ci	case IIO_CHAN_INFO_CALIBBIAS:
27962306a36Sopenharmony_ci		if (val < -2048 || val >= 2048)
28062306a36Sopenharmony_ci			return -EINVAL;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci		addr = adis16260_addresses[chan->scan_index][0];
28362306a36Sopenharmony_ci		return adis_write_reg_16(adis, addr, val);
28462306a36Sopenharmony_ci	case IIO_CHAN_INFO_CALIBSCALE:
28562306a36Sopenharmony_ci		if (val < 0 || val >= 4096)
28662306a36Sopenharmony_ci			return -EINVAL;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci		addr = adis16260_addresses[chan->scan_index][1];
28962306a36Sopenharmony_ci		return adis_write_reg_16(adis, addr, val);
29062306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
29162306a36Sopenharmony_ci		adis_dev_lock(adis);
29262306a36Sopenharmony_ci		if (spi_get_device_id(adis->spi)->driver_data)
29362306a36Sopenharmony_ci			t = 256 / val;
29462306a36Sopenharmony_ci		else
29562306a36Sopenharmony_ci			t = 2048 / val;
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci		if (t > ADIS16260_SMPL_PRD_DIV_MASK)
29862306a36Sopenharmony_ci			t = ADIS16260_SMPL_PRD_DIV_MASK;
29962306a36Sopenharmony_ci		else if (t > 0)
30062306a36Sopenharmony_ci			t--;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci		if (t >= 0x0A)
30362306a36Sopenharmony_ci			adis->spi->max_speed_hz = ADIS16260_SPI_SLOW;
30462306a36Sopenharmony_ci		else
30562306a36Sopenharmony_ci			adis->spi->max_speed_hz = ADIS16260_SPI_FAST;
30662306a36Sopenharmony_ci		ret = __adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci		adis_dev_unlock(adis);
30962306a36Sopenharmony_ci		return ret;
31062306a36Sopenharmony_ci	}
31162306a36Sopenharmony_ci	return -EINVAL;
31262306a36Sopenharmony_ci}
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_cistatic const struct iio_info adis16260_info = {
31562306a36Sopenharmony_ci	.read_raw = &adis16260_read_raw,
31662306a36Sopenharmony_ci	.write_raw = &adis16260_write_raw,
31762306a36Sopenharmony_ci	.update_scan_mode = adis_update_scan_mode,
31862306a36Sopenharmony_ci};
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_cistatic const char * const adis1620_status_error_msgs[] = {
32162306a36Sopenharmony_ci	[ADIS16260_DIAG_STAT_FLASH_CHK_BIT] = "Flash checksum error",
32262306a36Sopenharmony_ci	[ADIS16260_DIAG_STAT_SELF_TEST_BIT] = "Self test error",
32362306a36Sopenharmony_ci	[ADIS16260_DIAG_STAT_OVERFLOW_BIT] = "Sensor overrange",
32462306a36Sopenharmony_ci	[ADIS16260_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
32562306a36Sopenharmony_ci	[ADIS16260_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
32662306a36Sopenharmony_ci	[ADIS16260_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 5.25",
32762306a36Sopenharmony_ci	[ADIS16260_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 4.75",
32862306a36Sopenharmony_ci};
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_cistatic const struct adis_timeout adis16260_timeouts = {
33162306a36Sopenharmony_ci	.reset_ms = ADIS16260_STARTUP_DELAY,
33262306a36Sopenharmony_ci	.sw_reset_ms = ADIS16260_STARTUP_DELAY,
33362306a36Sopenharmony_ci	.self_test_ms = ADIS16260_STARTUP_DELAY,
33462306a36Sopenharmony_ci};
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_cistatic const struct adis_data adis16260_data = {
33762306a36Sopenharmony_ci	.write_delay = 30,
33862306a36Sopenharmony_ci	.read_delay = 30,
33962306a36Sopenharmony_ci	.msc_ctrl_reg = ADIS16260_MSC_CTRL,
34062306a36Sopenharmony_ci	.glob_cmd_reg = ADIS16260_GLOB_CMD,
34162306a36Sopenharmony_ci	.diag_stat_reg = ADIS16260_DIAG_STAT,
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	.self_test_mask = ADIS16260_MSC_CTRL_MEM_TEST,
34462306a36Sopenharmony_ci	.self_test_reg = ADIS16260_MSC_CTRL,
34562306a36Sopenharmony_ci	.timeouts = &adis16260_timeouts,
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	.status_error_msgs = adis1620_status_error_msgs,
34862306a36Sopenharmony_ci	.status_error_mask = BIT(ADIS16260_DIAG_STAT_FLASH_CHK_BIT) |
34962306a36Sopenharmony_ci		BIT(ADIS16260_DIAG_STAT_SELF_TEST_BIT) |
35062306a36Sopenharmony_ci		BIT(ADIS16260_DIAG_STAT_OVERFLOW_BIT) |
35162306a36Sopenharmony_ci		BIT(ADIS16260_DIAG_STAT_SPI_FAIL_BIT) |
35262306a36Sopenharmony_ci		BIT(ADIS16260_DIAG_STAT_FLASH_UPT_BIT) |
35362306a36Sopenharmony_ci		BIT(ADIS16260_DIAG_STAT_POWER_HIGH_BIT) |
35462306a36Sopenharmony_ci		BIT(ADIS16260_DIAG_STAT_POWER_LOW_BIT),
35562306a36Sopenharmony_ci};
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_cistatic void adis16260_stop(void *data)
35862306a36Sopenharmony_ci{
35962306a36Sopenharmony_ci	adis16260_stop_device(data);
36062306a36Sopenharmony_ci}
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_cistatic int adis16260_probe(struct spi_device *spi)
36362306a36Sopenharmony_ci{
36462306a36Sopenharmony_ci	const struct spi_device_id *id;
36562306a36Sopenharmony_ci	struct adis16260 *adis16260;
36662306a36Sopenharmony_ci	struct iio_dev *indio_dev;
36762306a36Sopenharmony_ci	int ret;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	id = spi_get_device_id(spi);
37062306a36Sopenharmony_ci	if (!id)
37162306a36Sopenharmony_ci		return -ENODEV;
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	/* setup the industrialio driver allocated elements */
37462306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis16260));
37562306a36Sopenharmony_ci	if (!indio_dev)
37662306a36Sopenharmony_ci		return -ENOMEM;
37762306a36Sopenharmony_ci	adis16260 = iio_priv(indio_dev);
37862306a36Sopenharmony_ci	/* this is only used for removal purposes */
37962306a36Sopenharmony_ci	spi_set_drvdata(spi, indio_dev);
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	adis16260->info = &adis16260_chip_info_table[id->driver_data];
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	indio_dev->name = id->name;
38462306a36Sopenharmony_ci	indio_dev->info = &adis16260_info;
38562306a36Sopenharmony_ci	indio_dev->channels = adis16260->info->channels;
38662306a36Sopenharmony_ci	indio_dev->num_channels = adis16260->info->num_channels;
38762306a36Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	ret = adis_init(&adis16260->adis, indio_dev, spi, &adis16260_data);
39062306a36Sopenharmony_ci	if (ret)
39162306a36Sopenharmony_ci		return ret;
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	ret = devm_adis_setup_buffer_and_trigger(&adis16260->adis, indio_dev, NULL);
39462306a36Sopenharmony_ci	if (ret)
39562306a36Sopenharmony_ci		return ret;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	/* Get the device into a sane initial state */
39862306a36Sopenharmony_ci	ret = __adis_initial_startup(&adis16260->adis);
39962306a36Sopenharmony_ci	if (ret)
40062306a36Sopenharmony_ci		return ret;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	ret = devm_add_action_or_reset(&spi->dev, adis16260_stop, indio_dev);
40362306a36Sopenharmony_ci	if (ret)
40462306a36Sopenharmony_ci		return ret;
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	return devm_iio_device_register(&spi->dev, indio_dev);
40762306a36Sopenharmony_ci}
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci/*
41062306a36Sopenharmony_ci * These parts do not need to be differentiated until someone adds
41162306a36Sopenharmony_ci * support for the on chip filtering.
41262306a36Sopenharmony_ci */
41362306a36Sopenharmony_cistatic const struct spi_device_id adis16260_id[] = {
41462306a36Sopenharmony_ci	{"adis16260", ADIS16260},
41562306a36Sopenharmony_ci	{"adis16265", ADIS16260},
41662306a36Sopenharmony_ci	{"adis16266", ADIS16266},
41762306a36Sopenharmony_ci	{"adis16250", ADIS16260},
41862306a36Sopenharmony_ci	{"adis16255", ADIS16260},
41962306a36Sopenharmony_ci	{"adis16251", ADIS16251},
42062306a36Sopenharmony_ci	{}
42162306a36Sopenharmony_ci};
42262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, adis16260_id);
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_cistatic struct spi_driver adis16260_driver = {
42562306a36Sopenharmony_ci	.driver = {
42662306a36Sopenharmony_ci		.name = "adis16260",
42762306a36Sopenharmony_ci	},
42862306a36Sopenharmony_ci	.probe = adis16260_probe,
42962306a36Sopenharmony_ci	.id_table = adis16260_id,
43062306a36Sopenharmony_ci};
43162306a36Sopenharmony_cimodule_spi_driver(adis16260_driver);
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ciMODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
43462306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices ADIS16260/5 Digital Gyroscope Sensor");
43562306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
43662306a36Sopenharmony_ciMODULE_IMPORT_NS(IIO_ADISLIB);
437