434 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * ADIS16260/ADIS16265 Programmable Digital Gyroscope Sensor Driver4 *5 * Copyright 2010 Analog Devices Inc.6 */7 8#include <linux/device.h>9#include <linux/kernel.h>10#include <linux/spi/spi.h>11#include <linux/module.h>12 13#include <linux/iio/iio.h>14#include <linux/iio/imu/adis.h>15 16#define ADIS16260_STARTUP_DELAY 220 /* ms */17 18#define ADIS16260_FLASH_CNT 0x00 /* Flash memory write count */19#define ADIS16260_SUPPLY_OUT 0x02 /* Power supply measurement */20#define ADIS16260_GYRO_OUT 0x04 /* X-axis gyroscope output */21#define ADIS16260_AUX_ADC 0x0A /* analog input channel measurement */22#define ADIS16260_TEMP_OUT 0x0C /* internal temperature measurement */23#define ADIS16260_ANGL_OUT 0x0E /* angle displacement */24#define ADIS16260_GYRO_OFF 0x14 /* Calibration, offset/bias adjustment */25#define ADIS16260_GYRO_SCALE 0x16 /* Calibration, scale adjustment */26#define ADIS16260_ALM_MAG1 0x20 /* Alarm 1 magnitude/polarity setting */27#define ADIS16260_ALM_MAG2 0x22 /* Alarm 2 magnitude/polarity setting */28#define ADIS16260_ALM_SMPL1 0x24 /* Alarm 1 dynamic rate of change setting */29#define ADIS16260_ALM_SMPL2 0x26 /* Alarm 2 dynamic rate of change setting */30#define ADIS16260_ALM_CTRL 0x28 /* Alarm control */31#define ADIS16260_AUX_DAC 0x30 /* Auxiliary DAC data */32#define ADIS16260_GPIO_CTRL 0x32 /* Control, digital I/O line */33#define ADIS16260_MSC_CTRL 0x34 /* Control, data ready, self-test settings */34#define ADIS16260_SMPL_PRD 0x36 /* Control, internal sample rate */35#define ADIS16260_SENS_AVG 0x38 /* Control, dynamic range, filtering */36#define ADIS16260_SLP_CNT 0x3A /* Control, sleep mode initiation */37#define ADIS16260_DIAG_STAT 0x3C /* Diagnostic, error flags */38#define ADIS16260_GLOB_CMD 0x3E /* Control, global commands */39#define ADIS16260_LOT_ID1 0x52 /* Lot Identification Code 1 */40#define ADIS16260_LOT_ID2 0x54 /* Lot Identification Code 2 */41#define ADIS16260_PROD_ID 0x56 /* Product identifier;42 * convert to decimal = 16,265/16,260 */43#define ADIS16260_SERIAL_NUM 0x58 /* Serial number */44 45#define ADIS16260_ERROR_ACTIVE (1<<14)46#define ADIS16260_NEW_DATA (1<<15)47 48/* MSC_CTRL */49#define ADIS16260_MSC_CTRL_MEM_TEST (1<<11)50/* Internal self-test enable */51#define ADIS16260_MSC_CTRL_INT_SELF_TEST (1<<10)52#define ADIS16260_MSC_CTRL_NEG_SELF_TEST (1<<9)53#define ADIS16260_MSC_CTRL_POS_SELF_TEST (1<<8)54#define ADIS16260_MSC_CTRL_DATA_RDY_EN (1<<2)55#define ADIS16260_MSC_CTRL_DATA_RDY_POL_HIGH (1<<1)56#define ADIS16260_MSC_CTRL_DATA_RDY_DIO2 (1<<0)57 58/* SMPL_PRD */59/* Time base (tB): 0 = 1.953 ms, 1 = 60.54 ms */60#define ADIS16260_SMPL_PRD_TIME_BASE (1<<7)61#define ADIS16260_SMPL_PRD_DIV_MASK 0x7F62 63/* SLP_CNT */64#define ADIS16260_SLP_CNT_POWER_OFF 0x8065 66/* DIAG_STAT */67#define ADIS16260_DIAG_STAT_ALARM2 (1<<9)68#define ADIS16260_DIAG_STAT_ALARM1 (1<<8)69#define ADIS16260_DIAG_STAT_FLASH_CHK_BIT 670#define ADIS16260_DIAG_STAT_SELF_TEST_BIT 571#define ADIS16260_DIAG_STAT_OVERFLOW_BIT 472#define ADIS16260_DIAG_STAT_SPI_FAIL_BIT 373#define ADIS16260_DIAG_STAT_FLASH_UPT_BIT 274#define ADIS16260_DIAG_STAT_POWER_HIGH_BIT 175#define ADIS16260_DIAG_STAT_POWER_LOW_BIT 076 77/* GLOB_CMD */78#define ADIS16260_GLOB_CMD_SW_RESET (1<<7)79#define ADIS16260_GLOB_CMD_FLASH_UPD (1<<3)80#define ADIS16260_GLOB_CMD_DAC_LATCH (1<<2)81#define ADIS16260_GLOB_CMD_FAC_CALIB (1<<1)82#define ADIS16260_GLOB_CMD_AUTO_NULL (1<<0)83 84#define ADIS16260_SPI_SLOW (u32)(300 * 1000)85#define ADIS16260_SPI_BURST (u32)(1000 * 1000)86#define ADIS16260_SPI_FAST (u32)(2000 * 1000)87 88/* At the moment triggers are only used for ring buffer89 * filling. This may change!90 */91 92#define ADIS16260_SCAN_GYRO 093#define ADIS16260_SCAN_SUPPLY 194#define ADIS16260_SCAN_AUX_ADC 295#define ADIS16260_SCAN_TEMP 396#define ADIS16260_SCAN_ANGL 497 98struct adis16260_chip_info {99 unsigned int gyro_max_val;100 unsigned int gyro_max_scale;101 const struct iio_chan_spec *channels;102 unsigned int num_channels;103};104 105struct adis16260 {106 const struct adis16260_chip_info *info;107 108 struct adis adis;109};110 111enum adis16260_type {112 ADIS16251,113 ADIS16260,114 ADIS16266,115};116 117static const struct iio_chan_spec adis16260_channels[] = {118 ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,119 BIT(IIO_CHAN_INFO_CALIBBIAS) |120 BIT(IIO_CHAN_INFO_CALIBSCALE),121 BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),122 ADIS_INCLI_CHAN(X, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0,123 BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),124 ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP,125 BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),126 ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY,127 BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),128 ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC,129 BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),130 IIO_CHAN_SOFT_TIMESTAMP(5),131};132 133static const struct iio_chan_spec adis16266_channels[] = {134 ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,135 BIT(IIO_CHAN_INFO_CALIBBIAS) |136 BIT(IIO_CHAN_INFO_CALIBSCALE),137 BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),138 ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP,139 BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),140 ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY,141 BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),142 ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC,143 BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),144 IIO_CHAN_SOFT_TIMESTAMP(4),145};146 147static const struct adis16260_chip_info adis16260_chip_info_table[] = {148 [ADIS16251] = {149 .gyro_max_scale = 80,150 .gyro_max_val = IIO_RAD_TO_DEGREE(4368),151 .channels = adis16260_channels,152 .num_channels = ARRAY_SIZE(adis16260_channels),153 },154 [ADIS16260] = {155 .gyro_max_scale = 320,156 .gyro_max_val = IIO_RAD_TO_DEGREE(4368),157 .channels = adis16260_channels,158 .num_channels = ARRAY_SIZE(adis16260_channels),159 },160 [ADIS16266] = {161 .gyro_max_scale = 14000,162 .gyro_max_val = IIO_RAD_TO_DEGREE(3357),163 .channels = adis16266_channels,164 .num_channels = ARRAY_SIZE(adis16266_channels),165 },166};167 168/* Power down the device */169static int adis16260_stop_device(struct iio_dev *indio_dev)170{171 struct adis16260 *adis16260 = iio_priv(indio_dev);172 int ret;173 u16 val = ADIS16260_SLP_CNT_POWER_OFF;174 175 ret = adis_write_reg_16(&adis16260->adis, ADIS16260_SLP_CNT, val);176 if (ret)177 dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");178 179 return ret;180}181 182static const u8 adis16260_addresses[][2] = {183 [ADIS16260_SCAN_GYRO] = { ADIS16260_GYRO_OFF, ADIS16260_GYRO_SCALE },184};185 186static int adis16260_read_raw(struct iio_dev *indio_dev,187 struct iio_chan_spec const *chan,188 int *val, int *val2,189 long mask)190{191 struct adis16260 *adis16260 = iio_priv(indio_dev);192 const struct adis16260_chip_info *info = adis16260->info;193 struct adis *adis = &adis16260->adis;194 int ret;195 u8 addr;196 s16 val16;197 198 switch (mask) {199 case IIO_CHAN_INFO_RAW:200 return adis_single_conversion(indio_dev, chan,201 ADIS16260_ERROR_ACTIVE, val);202 case IIO_CHAN_INFO_SCALE:203 switch (chan->type) {204 case IIO_ANGL_VEL:205 *val = info->gyro_max_scale;206 *val2 = info->gyro_max_val;207 return IIO_VAL_FRACTIONAL;208 case IIO_INCLI:209 *val = 0;210 *val2 = IIO_DEGREE_TO_RAD(36630);211 return IIO_VAL_INT_PLUS_MICRO;212 case IIO_VOLTAGE:213 if (chan->channel == 0) {214 *val = 1;215 *val2 = 831500; /* 1.8315 mV */216 } else {217 *val = 0;218 *val2 = 610500; /* 610.5 uV */219 }220 return IIO_VAL_INT_PLUS_MICRO;221 case IIO_TEMP:222 *val = 145;223 *val2 = 300000; /* 0.1453 C */224 return IIO_VAL_INT_PLUS_MICRO;225 default:226 return -EINVAL;227 }228 case IIO_CHAN_INFO_OFFSET:229 *val = 250000 / 1453; /* 25 C = 0x00 */230 return IIO_VAL_INT;231 case IIO_CHAN_INFO_CALIBBIAS:232 addr = adis16260_addresses[chan->scan_index][0];233 ret = adis_read_reg_16(adis, addr, &val16);234 if (ret)235 return ret;236 237 *val = sign_extend32(val16, 11);238 return IIO_VAL_INT;239 case IIO_CHAN_INFO_CALIBSCALE:240 addr = adis16260_addresses[chan->scan_index][1];241 ret = adis_read_reg_16(adis, addr, &val16);242 if (ret)243 return ret;244 245 *val = val16;246 return IIO_VAL_INT;247 case IIO_CHAN_INFO_SAMP_FREQ:248 ret = adis_read_reg_16(adis, ADIS16260_SMPL_PRD, &val16);249 if (ret)250 return ret;251 252 if (spi_get_device_id(adis->spi)->driver_data)253 /* If an adis16251 */254 *val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ?255 8 : 256;256 else257 *val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ?258 66 : 2048;259 *val /= (val16 & ADIS16260_SMPL_PRD_DIV_MASK) + 1;260 return IIO_VAL_INT;261 }262 return -EINVAL;263}264 265static int adis16260_write_raw(struct iio_dev *indio_dev,266 struct iio_chan_spec const *chan,267 int val,268 int val2,269 long mask)270{271 struct adis16260 *adis16260 = iio_priv(indio_dev);272 struct adis *adis = &adis16260->adis;273 u8 addr;274 u8 t;275 276 switch (mask) {277 case IIO_CHAN_INFO_CALIBBIAS:278 if (val < -2048 || val >= 2048)279 return -EINVAL;280 281 addr = adis16260_addresses[chan->scan_index][0];282 return adis_write_reg_16(adis, addr, val);283 case IIO_CHAN_INFO_CALIBSCALE:284 if (val < 0 || val >= 4096)285 return -EINVAL;286 287 addr = adis16260_addresses[chan->scan_index][1];288 return adis_write_reg_16(adis, addr, val);289 case IIO_CHAN_INFO_SAMP_FREQ:290 if (spi_get_device_id(adis->spi)->driver_data)291 t = 256 / val;292 else293 t = 2048 / val;294 295 if (t > ADIS16260_SMPL_PRD_DIV_MASK)296 t = ADIS16260_SMPL_PRD_DIV_MASK;297 else if (t > 0)298 t--;299 adis_dev_auto_scoped_lock(adis) {300 if (t >= 0x0A)301 adis->spi->max_speed_hz = ADIS16260_SPI_SLOW;302 else303 adis->spi->max_speed_hz = ADIS16260_SPI_FAST;304 return __adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t);305 }306 unreachable();307 }308 return -EINVAL;309}310 311static const struct iio_info adis16260_info = {312 .read_raw = &adis16260_read_raw,313 .write_raw = &adis16260_write_raw,314 .update_scan_mode = adis_update_scan_mode,315};316 317static const char * const adis1620_status_error_msgs[] = {318 [ADIS16260_DIAG_STAT_FLASH_CHK_BIT] = "Flash checksum error",319 [ADIS16260_DIAG_STAT_SELF_TEST_BIT] = "Self test error",320 [ADIS16260_DIAG_STAT_OVERFLOW_BIT] = "Sensor overrange",321 [ADIS16260_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",322 [ADIS16260_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",323 [ADIS16260_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 5.25",324 [ADIS16260_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 4.75",325};326 327static const struct adis_timeout adis16260_timeouts = {328 .reset_ms = ADIS16260_STARTUP_DELAY,329 .sw_reset_ms = ADIS16260_STARTUP_DELAY,330 .self_test_ms = ADIS16260_STARTUP_DELAY,331};332 333static const struct adis_data adis16260_data = {334 .write_delay = 30,335 .read_delay = 30,336 .msc_ctrl_reg = ADIS16260_MSC_CTRL,337 .glob_cmd_reg = ADIS16260_GLOB_CMD,338 .diag_stat_reg = ADIS16260_DIAG_STAT,339 340 .self_test_mask = ADIS16260_MSC_CTRL_MEM_TEST,341 .self_test_reg = ADIS16260_MSC_CTRL,342 .timeouts = &adis16260_timeouts,343 344 .status_error_msgs = adis1620_status_error_msgs,345 .status_error_mask = BIT(ADIS16260_DIAG_STAT_FLASH_CHK_BIT) |346 BIT(ADIS16260_DIAG_STAT_SELF_TEST_BIT) |347 BIT(ADIS16260_DIAG_STAT_OVERFLOW_BIT) |348 BIT(ADIS16260_DIAG_STAT_SPI_FAIL_BIT) |349 BIT(ADIS16260_DIAG_STAT_FLASH_UPT_BIT) |350 BIT(ADIS16260_DIAG_STAT_POWER_HIGH_BIT) |351 BIT(ADIS16260_DIAG_STAT_POWER_LOW_BIT),352};353 354static void adis16260_stop(void *data)355{356 adis16260_stop_device(data);357}358 359static int adis16260_probe(struct spi_device *spi)360{361 const struct spi_device_id *id;362 struct adis16260 *adis16260;363 struct iio_dev *indio_dev;364 int ret;365 366 id = spi_get_device_id(spi);367 if (!id)368 return -ENODEV;369 370 /* setup the industrialio driver allocated elements */371 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis16260));372 if (!indio_dev)373 return -ENOMEM;374 adis16260 = iio_priv(indio_dev);375 /* this is only used for removal purposes */376 spi_set_drvdata(spi, indio_dev);377 378 adis16260->info = &adis16260_chip_info_table[id->driver_data];379 380 indio_dev->name = id->name;381 indio_dev->info = &adis16260_info;382 indio_dev->channels = adis16260->info->channels;383 indio_dev->num_channels = adis16260->info->num_channels;384 indio_dev->modes = INDIO_DIRECT_MODE;385 386 ret = adis_init(&adis16260->adis, indio_dev, spi, &adis16260_data);387 if (ret)388 return ret;389 390 ret = devm_adis_setup_buffer_and_trigger(&adis16260->adis, indio_dev, NULL);391 if (ret)392 return ret;393 394 /* Get the device into a sane initial state */395 ret = __adis_initial_startup(&adis16260->adis);396 if (ret)397 return ret;398 399 ret = devm_add_action_or_reset(&spi->dev, adis16260_stop, indio_dev);400 if (ret)401 return ret;402 403 return devm_iio_device_register(&spi->dev, indio_dev);404}405 406/*407 * These parts do not need to be differentiated until someone adds408 * support for the on chip filtering.409 */410static const struct spi_device_id adis16260_id[] = {411 {"adis16260", ADIS16260},412 {"adis16265", ADIS16260},413 {"adis16266", ADIS16266},414 {"adis16250", ADIS16260},415 {"adis16255", ADIS16260},416 {"adis16251", ADIS16251},417 {}418};419MODULE_DEVICE_TABLE(spi, adis16260_id);420 421static struct spi_driver adis16260_driver = {422 .driver = {423 .name = "adis16260",424 },425 .probe = adis16260_probe,426 .id_table = adis16260_id,427};428module_spi_driver(adis16260_driver);429 430MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");431MODULE_DESCRIPTION("Analog Devices ADIS16260/5 Digital Gyroscope Sensor");432MODULE_LICENSE("GPL v2");433MODULE_IMPORT_NS(IIO_ADISLIB);434