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