162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * ADXRS450/ADXRS453 Digital Output Gyroscope Driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2011 Analog Devices Inc. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/interrupt.h> 962306a36Sopenharmony_ci#include <linux/irq.h> 1062306a36Sopenharmony_ci#include <linux/delay.h> 1162306a36Sopenharmony_ci#include <linux/mutex.h> 1262306a36Sopenharmony_ci#include <linux/device.h> 1362306a36Sopenharmony_ci#include <linux/kernel.h> 1462306a36Sopenharmony_ci#include <linux/spi/spi.h> 1562306a36Sopenharmony_ci#include <linux/slab.h> 1662306a36Sopenharmony_ci#include <linux/sysfs.h> 1762306a36Sopenharmony_ci#include <linux/list.h> 1862306a36Sopenharmony_ci#include <linux/module.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include <linux/iio/iio.h> 2162306a36Sopenharmony_ci#include <linux/iio/sysfs.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define ADXRS450_STARTUP_DELAY 50 /* ms */ 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* The MSB for the spi commands */ 2662306a36Sopenharmony_ci#define ADXRS450_SENSOR_DATA (0x20 << 24) 2762306a36Sopenharmony_ci#define ADXRS450_WRITE_DATA (0x40 << 24) 2862306a36Sopenharmony_ci#define ADXRS450_READ_DATA (0x80 << 24) 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define ADXRS450_RATE1 0x00 /* Rate Registers */ 3162306a36Sopenharmony_ci#define ADXRS450_TEMP1 0x02 /* Temperature Registers */ 3262306a36Sopenharmony_ci#define ADXRS450_LOCST1 0x04 /* Low CST Memory Registers */ 3362306a36Sopenharmony_ci#define ADXRS450_HICST1 0x06 /* High CST Memory Registers */ 3462306a36Sopenharmony_ci#define ADXRS450_QUAD1 0x08 /* Quad Memory Registers */ 3562306a36Sopenharmony_ci#define ADXRS450_FAULT1 0x0A /* Fault Registers */ 3662306a36Sopenharmony_ci#define ADXRS450_PID1 0x0C /* Part ID Register 1 */ 3762306a36Sopenharmony_ci#define ADXRS450_SNH 0x0E /* Serial Number Registers, 4 bytes */ 3862306a36Sopenharmony_ci#define ADXRS450_SNL 0x10 3962306a36Sopenharmony_ci#define ADXRS450_DNC1 0x12 /* Dynamic Null Correction Registers */ 4062306a36Sopenharmony_ci/* Check bits */ 4162306a36Sopenharmony_ci#define ADXRS450_P 0x01 4262306a36Sopenharmony_ci#define ADXRS450_CHK 0x02 4362306a36Sopenharmony_ci#define ADXRS450_CST 0x04 4462306a36Sopenharmony_ci#define ADXRS450_PWR 0x08 4562306a36Sopenharmony_ci#define ADXRS450_POR 0x10 4662306a36Sopenharmony_ci#define ADXRS450_NVM 0x20 4762306a36Sopenharmony_ci#define ADXRS450_Q 0x40 4862306a36Sopenharmony_ci#define ADXRS450_PLL 0x80 4962306a36Sopenharmony_ci#define ADXRS450_UV 0x100 5062306a36Sopenharmony_ci#define ADXRS450_OV 0x200 5162306a36Sopenharmony_ci#define ADXRS450_AMP 0x400 5262306a36Sopenharmony_ci#define ADXRS450_FAIL 0x800 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#define ADXRS450_WRERR_MASK (0x7 << 29) 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci#define ADXRS450_MAX_RX 4 5762306a36Sopenharmony_ci#define ADXRS450_MAX_TX 4 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#define ADXRS450_GET_ST(a) ((a >> 26) & 0x3) 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cienum { 6262306a36Sopenharmony_ci ID_ADXRS450, 6362306a36Sopenharmony_ci ID_ADXRS453, 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/** 6762306a36Sopenharmony_ci * struct adxrs450_state - device instance specific data 6862306a36Sopenharmony_ci * @us: actual spi_device 6962306a36Sopenharmony_ci * @buf_lock: mutex to protect tx and rx 7062306a36Sopenharmony_ci * @tx: transmit buffer 7162306a36Sopenharmony_ci * @rx: receive buffer 7262306a36Sopenharmony_ci **/ 7362306a36Sopenharmony_cistruct adxrs450_state { 7462306a36Sopenharmony_ci struct spi_device *us; 7562306a36Sopenharmony_ci struct mutex buf_lock; 7662306a36Sopenharmony_ci __be32 tx __aligned(IIO_DMA_MINALIGN); 7762306a36Sopenharmony_ci __be32 rx; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci}; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/** 8262306a36Sopenharmony_ci * adxrs450_spi_read_reg_16() - read 2 bytes from a register pair 8362306a36Sopenharmony_ci * @indio_dev: device associated with child of actual iio_dev 8462306a36Sopenharmony_ci * @reg_address: the address of the lower of the two registers, which should be 8562306a36Sopenharmony_ci * an even address, the second register's address is reg_address + 1. 8662306a36Sopenharmony_ci * @val: somewhere to pass back the value read 8762306a36Sopenharmony_ci **/ 8862306a36Sopenharmony_cistatic int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, 8962306a36Sopenharmony_ci u8 reg_address, 9062306a36Sopenharmony_ci u16 *val) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci struct adxrs450_state *st = iio_priv(indio_dev); 9362306a36Sopenharmony_ci u32 tx; 9462306a36Sopenharmony_ci int ret; 9562306a36Sopenharmony_ci struct spi_transfer xfers[] = { 9662306a36Sopenharmony_ci { 9762306a36Sopenharmony_ci .tx_buf = &st->tx, 9862306a36Sopenharmony_ci .bits_per_word = 8, 9962306a36Sopenharmony_ci .len = sizeof(st->tx), 10062306a36Sopenharmony_ci .cs_change = 1, 10162306a36Sopenharmony_ci }, { 10262306a36Sopenharmony_ci .rx_buf = &st->rx, 10362306a36Sopenharmony_ci .bits_per_word = 8, 10462306a36Sopenharmony_ci .len = sizeof(st->rx), 10562306a36Sopenharmony_ci }, 10662306a36Sopenharmony_ci }; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci mutex_lock(&st->buf_lock); 10962306a36Sopenharmony_ci tx = ADXRS450_READ_DATA | (reg_address << 17); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci if (!(hweight32(tx) & 1)) 11262306a36Sopenharmony_ci tx |= ADXRS450_P; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci st->tx = cpu_to_be32(tx); 11562306a36Sopenharmony_ci ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); 11662306a36Sopenharmony_ci if (ret) { 11762306a36Sopenharmony_ci dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n", 11862306a36Sopenharmony_ci reg_address); 11962306a36Sopenharmony_ci goto error_ret; 12062306a36Sopenharmony_ci } 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci *val = (be32_to_cpu(st->rx) >> 5) & 0xFFFF; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cierror_ret: 12562306a36Sopenharmony_ci mutex_unlock(&st->buf_lock); 12662306a36Sopenharmony_ci return ret; 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci/** 13062306a36Sopenharmony_ci * adxrs450_spi_write_reg_16() - write 2 bytes data to a register pair 13162306a36Sopenharmony_ci * @indio_dev: device associated with child of actual actual iio_dev 13262306a36Sopenharmony_ci * @reg_address: the address of the lower of the two registers,which should be 13362306a36Sopenharmony_ci * an even address, the second register's address is reg_address + 1. 13462306a36Sopenharmony_ci * @val: value to be written. 13562306a36Sopenharmony_ci **/ 13662306a36Sopenharmony_cistatic int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev, 13762306a36Sopenharmony_ci u8 reg_address, 13862306a36Sopenharmony_ci u16 val) 13962306a36Sopenharmony_ci{ 14062306a36Sopenharmony_ci struct adxrs450_state *st = iio_priv(indio_dev); 14162306a36Sopenharmony_ci u32 tx; 14262306a36Sopenharmony_ci int ret; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci mutex_lock(&st->buf_lock); 14562306a36Sopenharmony_ci tx = ADXRS450_WRITE_DATA | (reg_address << 17) | (val << 1); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci if (!(hweight32(tx) & 1)) 14862306a36Sopenharmony_ci tx |= ADXRS450_P; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci st->tx = cpu_to_be32(tx); 15162306a36Sopenharmony_ci ret = spi_write(st->us, &st->tx, sizeof(st->tx)); 15262306a36Sopenharmony_ci if (ret) 15362306a36Sopenharmony_ci dev_err(&st->us->dev, "problem while writing 16 bit register 0x%02x\n", 15462306a36Sopenharmony_ci reg_address); 15562306a36Sopenharmony_ci usleep_range(100, 1000); /* enforce sequential transfer delay 0.1ms */ 15662306a36Sopenharmony_ci mutex_unlock(&st->buf_lock); 15762306a36Sopenharmony_ci return ret; 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci/** 16162306a36Sopenharmony_ci * adxrs450_spi_sensor_data() - read 2 bytes sensor data 16262306a36Sopenharmony_ci * @indio_dev: device associated with child of actual iio_dev 16362306a36Sopenharmony_ci * @val: somewhere to pass back the value read 16462306a36Sopenharmony_ci **/ 16562306a36Sopenharmony_cistatic int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci struct adxrs450_state *st = iio_priv(indio_dev); 16862306a36Sopenharmony_ci int ret; 16962306a36Sopenharmony_ci struct spi_transfer xfers[] = { 17062306a36Sopenharmony_ci { 17162306a36Sopenharmony_ci .tx_buf = &st->tx, 17262306a36Sopenharmony_ci .bits_per_word = 8, 17362306a36Sopenharmony_ci .len = sizeof(st->tx), 17462306a36Sopenharmony_ci .cs_change = 1, 17562306a36Sopenharmony_ci }, { 17662306a36Sopenharmony_ci .rx_buf = &st->rx, 17762306a36Sopenharmony_ci .bits_per_word = 8, 17862306a36Sopenharmony_ci .len = sizeof(st->rx), 17962306a36Sopenharmony_ci }, 18062306a36Sopenharmony_ci }; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci mutex_lock(&st->buf_lock); 18362306a36Sopenharmony_ci st->tx = cpu_to_be32(ADXRS450_SENSOR_DATA); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); 18662306a36Sopenharmony_ci if (ret) { 18762306a36Sopenharmony_ci dev_err(&st->us->dev, "Problem while reading sensor data\n"); 18862306a36Sopenharmony_ci goto error_ret; 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci *val = (be32_to_cpu(st->rx) >> 10) & 0xFFFF; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_cierror_ret: 19462306a36Sopenharmony_ci mutex_unlock(&st->buf_lock); 19562306a36Sopenharmony_ci return ret; 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci/** 19962306a36Sopenharmony_ci * adxrs450_spi_initial() - use for initializing procedure. 20062306a36Sopenharmony_ci * @st: device instance specific data 20162306a36Sopenharmony_ci * @val: somewhere to pass back the value read 20262306a36Sopenharmony_ci * @chk: Whether to perform fault check 20362306a36Sopenharmony_ci **/ 20462306a36Sopenharmony_cistatic int adxrs450_spi_initial(struct adxrs450_state *st, 20562306a36Sopenharmony_ci u32 *val, char chk) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci int ret; 20862306a36Sopenharmony_ci u32 tx; 20962306a36Sopenharmony_ci struct spi_transfer xfers = { 21062306a36Sopenharmony_ci .tx_buf = &st->tx, 21162306a36Sopenharmony_ci .rx_buf = &st->rx, 21262306a36Sopenharmony_ci .bits_per_word = 8, 21362306a36Sopenharmony_ci .len = sizeof(st->tx), 21462306a36Sopenharmony_ci }; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci mutex_lock(&st->buf_lock); 21762306a36Sopenharmony_ci tx = ADXRS450_SENSOR_DATA; 21862306a36Sopenharmony_ci if (chk) 21962306a36Sopenharmony_ci tx |= (ADXRS450_CHK | ADXRS450_P); 22062306a36Sopenharmony_ci st->tx = cpu_to_be32(tx); 22162306a36Sopenharmony_ci ret = spi_sync_transfer(st->us, &xfers, 1); 22262306a36Sopenharmony_ci if (ret) { 22362306a36Sopenharmony_ci dev_err(&st->us->dev, "Problem while reading initializing data\n"); 22462306a36Sopenharmony_ci goto error_ret; 22562306a36Sopenharmony_ci } 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci *val = be32_to_cpu(st->rx); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_cierror_ret: 23062306a36Sopenharmony_ci mutex_unlock(&st->buf_lock); 23162306a36Sopenharmony_ci return ret; 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci/* Recommended Startup Sequence by spec */ 23562306a36Sopenharmony_cistatic int adxrs450_initial_setup(struct iio_dev *indio_dev) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci u32 t; 23862306a36Sopenharmony_ci u16 data; 23962306a36Sopenharmony_ci int ret; 24062306a36Sopenharmony_ci struct adxrs450_state *st = iio_priv(indio_dev); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci msleep(ADXRS450_STARTUP_DELAY*2); 24362306a36Sopenharmony_ci ret = adxrs450_spi_initial(st, &t, 1); 24462306a36Sopenharmony_ci if (ret) 24562306a36Sopenharmony_ci return ret; 24662306a36Sopenharmony_ci if (t != 0x01) 24762306a36Sopenharmony_ci dev_warn(&st->us->dev, "The initial power on response is not correct! Restart without reset?\n"); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci msleep(ADXRS450_STARTUP_DELAY); 25062306a36Sopenharmony_ci ret = adxrs450_spi_initial(st, &t, 0); 25162306a36Sopenharmony_ci if (ret) 25262306a36Sopenharmony_ci return ret; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci msleep(ADXRS450_STARTUP_DELAY); 25562306a36Sopenharmony_ci ret = adxrs450_spi_initial(st, &t, 0); 25662306a36Sopenharmony_ci if (ret) 25762306a36Sopenharmony_ci return ret; 25862306a36Sopenharmony_ci if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) { 25962306a36Sopenharmony_ci dev_err(&st->us->dev, "The second response is not correct!\n"); 26062306a36Sopenharmony_ci return -EIO; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci ret = adxrs450_spi_initial(st, &t, 0); 26462306a36Sopenharmony_ci if (ret) 26562306a36Sopenharmony_ci return ret; 26662306a36Sopenharmony_ci if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) { 26762306a36Sopenharmony_ci dev_err(&st->us->dev, "The third response is not correct!\n"); 26862306a36Sopenharmony_ci return -EIO; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci } 27162306a36Sopenharmony_ci ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_FAULT1, &data); 27262306a36Sopenharmony_ci if (ret) 27362306a36Sopenharmony_ci return ret; 27462306a36Sopenharmony_ci if (data & 0x0fff) { 27562306a36Sopenharmony_ci dev_err(&st->us->dev, "The device is not in normal status!\n"); 27662306a36Sopenharmony_ci return -EINVAL; 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci return 0; 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cistatic int adxrs450_write_raw(struct iio_dev *indio_dev, 28362306a36Sopenharmony_ci struct iio_chan_spec const *chan, 28462306a36Sopenharmony_ci int val, 28562306a36Sopenharmony_ci int val2, 28662306a36Sopenharmony_ci long mask) 28762306a36Sopenharmony_ci{ 28862306a36Sopenharmony_ci int ret; 28962306a36Sopenharmony_ci switch (mask) { 29062306a36Sopenharmony_ci case IIO_CHAN_INFO_CALIBBIAS: 29162306a36Sopenharmony_ci if (val < -0x400 || val >= 0x400) 29262306a36Sopenharmony_ci return -EINVAL; 29362306a36Sopenharmony_ci ret = adxrs450_spi_write_reg_16(indio_dev, 29462306a36Sopenharmony_ci ADXRS450_DNC1, val); 29562306a36Sopenharmony_ci break; 29662306a36Sopenharmony_ci default: 29762306a36Sopenharmony_ci ret = -EINVAL; 29862306a36Sopenharmony_ci break; 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci return ret; 30162306a36Sopenharmony_ci} 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_cistatic int adxrs450_read_raw(struct iio_dev *indio_dev, 30462306a36Sopenharmony_ci struct iio_chan_spec const *chan, 30562306a36Sopenharmony_ci int *val, 30662306a36Sopenharmony_ci int *val2, 30762306a36Sopenharmony_ci long mask) 30862306a36Sopenharmony_ci{ 30962306a36Sopenharmony_ci int ret; 31062306a36Sopenharmony_ci s16 t; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci switch (mask) { 31362306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 31462306a36Sopenharmony_ci switch (chan->type) { 31562306a36Sopenharmony_ci case IIO_ANGL_VEL: 31662306a36Sopenharmony_ci ret = adxrs450_spi_sensor_data(indio_dev, &t); 31762306a36Sopenharmony_ci if (ret) 31862306a36Sopenharmony_ci break; 31962306a36Sopenharmony_ci *val = t; 32062306a36Sopenharmony_ci ret = IIO_VAL_INT; 32162306a36Sopenharmony_ci break; 32262306a36Sopenharmony_ci case IIO_TEMP: 32362306a36Sopenharmony_ci ret = adxrs450_spi_read_reg_16(indio_dev, 32462306a36Sopenharmony_ci ADXRS450_TEMP1, &t); 32562306a36Sopenharmony_ci if (ret) 32662306a36Sopenharmony_ci break; 32762306a36Sopenharmony_ci *val = (t >> 6) + 225; 32862306a36Sopenharmony_ci ret = IIO_VAL_INT; 32962306a36Sopenharmony_ci break; 33062306a36Sopenharmony_ci default: 33162306a36Sopenharmony_ci ret = -EINVAL; 33262306a36Sopenharmony_ci break; 33362306a36Sopenharmony_ci } 33462306a36Sopenharmony_ci break; 33562306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 33662306a36Sopenharmony_ci switch (chan->type) { 33762306a36Sopenharmony_ci case IIO_ANGL_VEL: 33862306a36Sopenharmony_ci *val = 0; 33962306a36Sopenharmony_ci *val2 = 218166; 34062306a36Sopenharmony_ci return IIO_VAL_INT_PLUS_NANO; 34162306a36Sopenharmony_ci case IIO_TEMP: 34262306a36Sopenharmony_ci *val = 200; 34362306a36Sopenharmony_ci *val2 = 0; 34462306a36Sopenharmony_ci return IIO_VAL_INT; 34562306a36Sopenharmony_ci default: 34662306a36Sopenharmony_ci return -EINVAL; 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci case IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW: 34962306a36Sopenharmony_ci ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t); 35062306a36Sopenharmony_ci if (ret) 35162306a36Sopenharmony_ci break; 35262306a36Sopenharmony_ci *val = t; 35362306a36Sopenharmony_ci ret = IIO_VAL_INT; 35462306a36Sopenharmony_ci break; 35562306a36Sopenharmony_ci case IIO_CHAN_INFO_CALIBBIAS: 35662306a36Sopenharmony_ci ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_DNC1, &t); 35762306a36Sopenharmony_ci if (ret) 35862306a36Sopenharmony_ci break; 35962306a36Sopenharmony_ci *val = sign_extend32(t, 9); 36062306a36Sopenharmony_ci ret = IIO_VAL_INT; 36162306a36Sopenharmony_ci break; 36262306a36Sopenharmony_ci default: 36362306a36Sopenharmony_ci ret = -EINVAL; 36462306a36Sopenharmony_ci break; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci return ret; 36862306a36Sopenharmony_ci} 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_cistatic const struct iio_chan_spec adxrs450_channels[2][2] = { 37162306a36Sopenharmony_ci [ID_ADXRS450] = { 37262306a36Sopenharmony_ci { 37362306a36Sopenharmony_ci .type = IIO_ANGL_VEL, 37462306a36Sopenharmony_ci .modified = 1, 37562306a36Sopenharmony_ci .channel2 = IIO_MOD_Z, 37662306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 37762306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_CALIBBIAS) | 37862306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW) | 37962306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), 38062306a36Sopenharmony_ci }, { 38162306a36Sopenharmony_ci .type = IIO_TEMP, 38262306a36Sopenharmony_ci .indexed = 1, 38362306a36Sopenharmony_ci .channel = 0, 38462306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 38562306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), 38662306a36Sopenharmony_ci } 38762306a36Sopenharmony_ci }, 38862306a36Sopenharmony_ci [ID_ADXRS453] = { 38962306a36Sopenharmony_ci { 39062306a36Sopenharmony_ci .type = IIO_ANGL_VEL, 39162306a36Sopenharmony_ci .modified = 1, 39262306a36Sopenharmony_ci .channel2 = IIO_MOD_Z, 39362306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 39462306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE) | 39562306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW), 39662306a36Sopenharmony_ci }, { 39762306a36Sopenharmony_ci .type = IIO_TEMP, 39862306a36Sopenharmony_ci .indexed = 1, 39962306a36Sopenharmony_ci .channel = 0, 40062306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 40162306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci }, 40462306a36Sopenharmony_ci}; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_cistatic const struct iio_info adxrs450_info = { 40762306a36Sopenharmony_ci .read_raw = &adxrs450_read_raw, 40862306a36Sopenharmony_ci .write_raw = &adxrs450_write_raw, 40962306a36Sopenharmony_ci}; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_cistatic int adxrs450_probe(struct spi_device *spi) 41262306a36Sopenharmony_ci{ 41362306a36Sopenharmony_ci int ret; 41462306a36Sopenharmony_ci struct adxrs450_state *st; 41562306a36Sopenharmony_ci struct iio_dev *indio_dev; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci /* setup the industrialio driver allocated elements */ 41862306a36Sopenharmony_ci indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 41962306a36Sopenharmony_ci if (!indio_dev) 42062306a36Sopenharmony_ci return -ENOMEM; 42162306a36Sopenharmony_ci st = iio_priv(indio_dev); 42262306a36Sopenharmony_ci st->us = spi; 42362306a36Sopenharmony_ci mutex_init(&st->buf_lock); 42462306a36Sopenharmony_ci /* This is only used for removal purposes */ 42562306a36Sopenharmony_ci spi_set_drvdata(spi, indio_dev); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci indio_dev->info = &adxrs450_info; 42862306a36Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 42962306a36Sopenharmony_ci indio_dev->channels = 43062306a36Sopenharmony_ci adxrs450_channels[spi_get_device_id(spi)->driver_data]; 43162306a36Sopenharmony_ci indio_dev->num_channels = ARRAY_SIZE(adxrs450_channels); 43262306a36Sopenharmony_ci indio_dev->name = spi->dev.driver->name; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci ret = devm_iio_device_register(&spi->dev, indio_dev); 43562306a36Sopenharmony_ci if (ret) 43662306a36Sopenharmony_ci return ret; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci /* Get the device into a sane initial state */ 43962306a36Sopenharmony_ci ret = adxrs450_initial_setup(indio_dev); 44062306a36Sopenharmony_ci if (ret) 44162306a36Sopenharmony_ci return ret; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci return 0; 44462306a36Sopenharmony_ci} 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_cistatic const struct spi_device_id adxrs450_id[] = { 44762306a36Sopenharmony_ci {"adxrs450", ID_ADXRS450}, 44862306a36Sopenharmony_ci {"adxrs453", ID_ADXRS453}, 44962306a36Sopenharmony_ci {} 45062306a36Sopenharmony_ci}; 45162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, adxrs450_id); 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_cistatic struct spi_driver adxrs450_driver = { 45462306a36Sopenharmony_ci .driver = { 45562306a36Sopenharmony_ci .name = "adxrs450", 45662306a36Sopenharmony_ci }, 45762306a36Sopenharmony_ci .probe = adxrs450_probe, 45862306a36Sopenharmony_ci .id_table = adxrs450_id, 45962306a36Sopenharmony_ci}; 46062306a36Sopenharmony_cimodule_spi_driver(adxrs450_driver); 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ciMODULE_AUTHOR("Cliff Cai <cliff.cai@xxxxxxxxxx>"); 46362306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices ADXRS450/ADXRS453 Gyroscope SPI driver"); 46462306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 465