162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * ADIS16475 IMU driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2019 Analog Devices Inc. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#include <linux/bitfield.h> 862306a36Sopenharmony_ci#include <linux/bitops.h> 962306a36Sopenharmony_ci#include <linux/clk.h> 1062306a36Sopenharmony_ci#include <linux/debugfs.h> 1162306a36Sopenharmony_ci#include <linux/delay.h> 1262306a36Sopenharmony_ci#include <linux/device.h> 1362306a36Sopenharmony_ci#include <linux/kernel.h> 1462306a36Sopenharmony_ci#include <linux/iio/buffer.h> 1562306a36Sopenharmony_ci#include <linux/iio/iio.h> 1662306a36Sopenharmony_ci#include <linux/iio/imu/adis.h> 1762306a36Sopenharmony_ci#include <linux/iio/trigger_consumer.h> 1862306a36Sopenharmony_ci#include <linux/irq.h> 1962306a36Sopenharmony_ci#include <linux/lcm.h> 2062306a36Sopenharmony_ci#include <linux/math.h> 2162306a36Sopenharmony_ci#include <linux/module.h> 2262306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 2362306a36Sopenharmony_ci#include <linux/property.h> 2462306a36Sopenharmony_ci#include <linux/spi/spi.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define ADIS16475_REG_DIAG_STAT 0x02 2762306a36Sopenharmony_ci#define ADIS16475_REG_X_GYRO_L 0x04 2862306a36Sopenharmony_ci#define ADIS16475_REG_Y_GYRO_L 0x08 2962306a36Sopenharmony_ci#define ADIS16475_REG_Z_GYRO_L 0x0C 3062306a36Sopenharmony_ci#define ADIS16475_REG_X_ACCEL_L 0x10 3162306a36Sopenharmony_ci#define ADIS16475_REG_Y_ACCEL_L 0x14 3262306a36Sopenharmony_ci#define ADIS16475_REG_Z_ACCEL_L 0x18 3362306a36Sopenharmony_ci#define ADIS16475_REG_TEMP_OUT 0x1c 3462306a36Sopenharmony_ci#define ADIS16475_REG_X_GYRO_BIAS_L 0x40 3562306a36Sopenharmony_ci#define ADIS16475_REG_Y_GYRO_BIAS_L 0x44 3662306a36Sopenharmony_ci#define ADIS16475_REG_Z_GYRO_BIAS_L 0x48 3762306a36Sopenharmony_ci#define ADIS16475_REG_X_ACCEL_BIAS_L 0x4c 3862306a36Sopenharmony_ci#define ADIS16475_REG_Y_ACCEL_BIAS_L 0x50 3962306a36Sopenharmony_ci#define ADIS16475_REG_Z_ACCEL_BIAS_L 0x54 4062306a36Sopenharmony_ci#define ADIS16475_REG_FILT_CTRL 0x5c 4162306a36Sopenharmony_ci#define ADIS16475_FILT_CTRL_MASK GENMASK(2, 0) 4262306a36Sopenharmony_ci#define ADIS16475_FILT_CTRL(x) FIELD_PREP(ADIS16475_FILT_CTRL_MASK, x) 4362306a36Sopenharmony_ci#define ADIS16475_REG_MSG_CTRL 0x60 4462306a36Sopenharmony_ci#define ADIS16475_MSG_CTRL_DR_POL_MASK BIT(0) 4562306a36Sopenharmony_ci#define ADIS16475_MSG_CTRL_DR_POL(x) \ 4662306a36Sopenharmony_ci FIELD_PREP(ADIS16475_MSG_CTRL_DR_POL_MASK, x) 4762306a36Sopenharmony_ci#define ADIS16475_SYNC_MODE_MASK GENMASK(4, 2) 4862306a36Sopenharmony_ci#define ADIS16475_SYNC_MODE(x) FIELD_PREP(ADIS16475_SYNC_MODE_MASK, x) 4962306a36Sopenharmony_ci#define ADIS16475_REG_UP_SCALE 0x62 5062306a36Sopenharmony_ci#define ADIS16475_REG_DEC_RATE 0x64 5162306a36Sopenharmony_ci#define ADIS16475_REG_GLOB_CMD 0x68 5262306a36Sopenharmony_ci#define ADIS16475_REG_FIRM_REV 0x6c 5362306a36Sopenharmony_ci#define ADIS16475_REG_FIRM_DM 0x6e 5462306a36Sopenharmony_ci#define ADIS16475_REG_FIRM_Y 0x70 5562306a36Sopenharmony_ci#define ADIS16475_REG_PROD_ID 0x72 5662306a36Sopenharmony_ci#define ADIS16475_REG_SERIAL_NUM 0x74 5762306a36Sopenharmony_ci#define ADIS16475_REG_FLASH_CNT 0x7c 5862306a36Sopenharmony_ci#define ADIS16500_BURST32_MASK BIT(9) 5962306a36Sopenharmony_ci#define ADIS16500_BURST32(x) FIELD_PREP(ADIS16500_BURST32_MASK, x) 6062306a36Sopenharmony_ci/* number of data elements in burst mode */ 6162306a36Sopenharmony_ci#define ADIS16475_BURST32_MAX_DATA 32 6262306a36Sopenharmony_ci#define ADIS16475_BURST_MAX_DATA 20 6362306a36Sopenharmony_ci#define ADIS16475_MAX_SCAN_DATA 20 6462306a36Sopenharmony_ci/* spi max speed in brust mode */ 6562306a36Sopenharmony_ci#define ADIS16475_BURST_MAX_SPEED 1000000 6662306a36Sopenharmony_ci#define ADIS16475_LSB_DEC_MASK 0 6762306a36Sopenharmony_ci#define ADIS16475_LSB_FIR_MASK 1 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cienum { 7062306a36Sopenharmony_ci ADIS16475_SYNC_DIRECT = 1, 7162306a36Sopenharmony_ci ADIS16475_SYNC_SCALED, 7262306a36Sopenharmony_ci ADIS16475_SYNC_OUTPUT, 7362306a36Sopenharmony_ci ADIS16475_SYNC_PULSE = 5, 7462306a36Sopenharmony_ci}; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistruct adis16475_sync { 7762306a36Sopenharmony_ci u16 sync_mode; 7862306a36Sopenharmony_ci u16 min_rate; 7962306a36Sopenharmony_ci u16 max_rate; 8062306a36Sopenharmony_ci}; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistruct adis16475_chip_info { 8362306a36Sopenharmony_ci const struct iio_chan_spec *channels; 8462306a36Sopenharmony_ci const struct adis16475_sync *sync; 8562306a36Sopenharmony_ci const struct adis_data adis_data; 8662306a36Sopenharmony_ci const char *name; 8762306a36Sopenharmony_ci u32 num_channels; 8862306a36Sopenharmony_ci u32 gyro_max_val; 8962306a36Sopenharmony_ci u32 gyro_max_scale; 9062306a36Sopenharmony_ci u32 accel_max_val; 9162306a36Sopenharmony_ci u32 accel_max_scale; 9262306a36Sopenharmony_ci u32 temp_scale; 9362306a36Sopenharmony_ci u32 int_clk; 9462306a36Sopenharmony_ci u16 max_dec; 9562306a36Sopenharmony_ci u8 num_sync; 9662306a36Sopenharmony_ci bool has_burst32; 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistruct adis16475 { 10062306a36Sopenharmony_ci const struct adis16475_chip_info *info; 10162306a36Sopenharmony_ci struct adis adis; 10262306a36Sopenharmony_ci u32 clk_freq; 10362306a36Sopenharmony_ci bool burst32; 10462306a36Sopenharmony_ci unsigned long lsb_flag; 10562306a36Sopenharmony_ci u16 sync_mode; 10662306a36Sopenharmony_ci /* Alignment needed for the timestamp */ 10762306a36Sopenharmony_ci __be16 data[ADIS16475_MAX_SCAN_DATA] __aligned(8); 10862306a36Sopenharmony_ci}; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cienum { 11162306a36Sopenharmony_ci ADIS16475_SCAN_GYRO_X, 11262306a36Sopenharmony_ci ADIS16475_SCAN_GYRO_Y, 11362306a36Sopenharmony_ci ADIS16475_SCAN_GYRO_Z, 11462306a36Sopenharmony_ci ADIS16475_SCAN_ACCEL_X, 11562306a36Sopenharmony_ci ADIS16475_SCAN_ACCEL_Y, 11662306a36Sopenharmony_ci ADIS16475_SCAN_ACCEL_Z, 11762306a36Sopenharmony_ci ADIS16475_SCAN_TEMP, 11862306a36Sopenharmony_ci}; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic bool low_rate_allow; 12162306a36Sopenharmony_cimodule_param(low_rate_allow, bool, 0444); 12262306a36Sopenharmony_ciMODULE_PARM_DESC(low_rate_allow, 12362306a36Sopenharmony_ci "Allow IMU rates below the minimum advisable when external clk is used in SCALED mode (default: N)"); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 12662306a36Sopenharmony_cistatic ssize_t adis16475_show_firmware_revision(struct file *file, 12762306a36Sopenharmony_ci char __user *userbuf, 12862306a36Sopenharmony_ci size_t count, loff_t *ppos) 12962306a36Sopenharmony_ci{ 13062306a36Sopenharmony_ci struct adis16475 *st = file->private_data; 13162306a36Sopenharmony_ci char buf[7]; 13262306a36Sopenharmony_ci size_t len; 13362306a36Sopenharmony_ci u16 rev; 13462306a36Sopenharmony_ci int ret; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIRM_REV, &rev); 13762306a36Sopenharmony_ci if (ret) 13862306a36Sopenharmony_ci return ret; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci len = scnprintf(buf, sizeof(buf), "%x.%x\n", rev >> 8, rev & 0xff); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci return simple_read_from_buffer(userbuf, count, ppos, buf, len); 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cistatic const struct file_operations adis16475_firmware_revision_fops = { 14662306a36Sopenharmony_ci .open = simple_open, 14762306a36Sopenharmony_ci .read = adis16475_show_firmware_revision, 14862306a36Sopenharmony_ci .llseek = default_llseek, 14962306a36Sopenharmony_ci .owner = THIS_MODULE, 15062306a36Sopenharmony_ci}; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic ssize_t adis16475_show_firmware_date(struct file *file, 15362306a36Sopenharmony_ci char __user *userbuf, 15462306a36Sopenharmony_ci size_t count, loff_t *ppos) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci struct adis16475 *st = file->private_data; 15762306a36Sopenharmony_ci u16 md, year; 15862306a36Sopenharmony_ci char buf[12]; 15962306a36Sopenharmony_ci size_t len; 16062306a36Sopenharmony_ci int ret; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIRM_Y, &year); 16362306a36Sopenharmony_ci if (ret) 16462306a36Sopenharmony_ci return ret; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIRM_DM, &md); 16762306a36Sopenharmony_ci if (ret) 16862306a36Sopenharmony_ci return ret; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci len = snprintf(buf, sizeof(buf), "%.2x-%.2x-%.4x\n", md >> 8, md & 0xff, 17162306a36Sopenharmony_ci year); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci return simple_read_from_buffer(userbuf, count, ppos, buf, len); 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic const struct file_operations adis16475_firmware_date_fops = { 17762306a36Sopenharmony_ci .open = simple_open, 17862306a36Sopenharmony_ci .read = adis16475_show_firmware_date, 17962306a36Sopenharmony_ci .llseek = default_llseek, 18062306a36Sopenharmony_ci .owner = THIS_MODULE, 18162306a36Sopenharmony_ci}; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic int adis16475_show_serial_number(void *arg, u64 *val) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci struct adis16475 *st = arg; 18662306a36Sopenharmony_ci u16 serial; 18762306a36Sopenharmony_ci int ret; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci ret = adis_read_reg_16(&st->adis, ADIS16475_REG_SERIAL_NUM, &serial); 19062306a36Sopenharmony_ci if (ret) 19162306a36Sopenharmony_ci return ret; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci *val = serial; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci return 0; 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(adis16475_serial_number_fops, 19862306a36Sopenharmony_ci adis16475_show_serial_number, NULL, "0x%.4llx\n"); 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic int adis16475_show_product_id(void *arg, u64 *val) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci struct adis16475 *st = arg; 20362306a36Sopenharmony_ci u16 prod_id; 20462306a36Sopenharmony_ci int ret; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci ret = adis_read_reg_16(&st->adis, ADIS16475_REG_PROD_ID, &prod_id); 20762306a36Sopenharmony_ci if (ret) 20862306a36Sopenharmony_ci return ret; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci *val = prod_id; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci return 0; 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(adis16475_product_id_fops, 21562306a36Sopenharmony_ci adis16475_show_product_id, NULL, "%llu\n"); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_cistatic int adis16475_show_flash_count(void *arg, u64 *val) 21862306a36Sopenharmony_ci{ 21962306a36Sopenharmony_ci struct adis16475 *st = arg; 22062306a36Sopenharmony_ci u32 flash_count; 22162306a36Sopenharmony_ci int ret; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci ret = adis_read_reg_32(&st->adis, ADIS16475_REG_FLASH_CNT, 22462306a36Sopenharmony_ci &flash_count); 22562306a36Sopenharmony_ci if (ret) 22662306a36Sopenharmony_ci return ret; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci *val = flash_count; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci return 0; 23162306a36Sopenharmony_ci} 23262306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(adis16475_flash_count_fops, 23362306a36Sopenharmony_ci adis16475_show_flash_count, NULL, "%lld\n"); 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistatic void adis16475_debugfs_init(struct iio_dev *indio_dev) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci struct adis16475 *st = iio_priv(indio_dev); 23862306a36Sopenharmony_ci struct dentry *d = iio_get_debugfs_dentry(indio_dev); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci debugfs_create_file_unsafe("serial_number", 0400, 24162306a36Sopenharmony_ci d, st, &adis16475_serial_number_fops); 24262306a36Sopenharmony_ci debugfs_create_file_unsafe("product_id", 0400, 24362306a36Sopenharmony_ci d, st, &adis16475_product_id_fops); 24462306a36Sopenharmony_ci debugfs_create_file_unsafe("flash_count", 0400, 24562306a36Sopenharmony_ci d, st, &adis16475_flash_count_fops); 24662306a36Sopenharmony_ci debugfs_create_file("firmware_revision", 0400, 24762306a36Sopenharmony_ci d, st, &adis16475_firmware_revision_fops); 24862306a36Sopenharmony_ci debugfs_create_file("firmware_date", 0400, d, 24962306a36Sopenharmony_ci st, &adis16475_firmware_date_fops); 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci#else 25262306a36Sopenharmony_cistatic void adis16475_debugfs_init(struct iio_dev *indio_dev) 25362306a36Sopenharmony_ci{ 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci#endif 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_cistatic int adis16475_get_freq(struct adis16475 *st, u32 *freq) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci int ret; 26062306a36Sopenharmony_ci u16 dec; 26162306a36Sopenharmony_ci u32 sample_rate = st->clk_freq; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci adis_dev_lock(&st->adis); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci if (st->sync_mode == ADIS16475_SYNC_SCALED) { 26662306a36Sopenharmony_ci u16 sync_scale; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci ret = __adis_read_reg_16(&st->adis, ADIS16475_REG_UP_SCALE, &sync_scale); 26962306a36Sopenharmony_ci if (ret) 27062306a36Sopenharmony_ci goto error; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci sample_rate = st->clk_freq * sync_scale; 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci ret = __adis_read_reg_16(&st->adis, ADIS16475_REG_DEC_RATE, &dec); 27662306a36Sopenharmony_ci if (ret) 27762306a36Sopenharmony_ci goto error; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci adis_dev_unlock(&st->adis); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci *freq = DIV_ROUND_CLOSEST(sample_rate, dec + 1); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci return 0; 28462306a36Sopenharmony_cierror: 28562306a36Sopenharmony_ci adis_dev_unlock(&st->adis); 28662306a36Sopenharmony_ci return ret; 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic int adis16475_set_freq(struct adis16475 *st, const u32 freq) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci u16 dec; 29262306a36Sopenharmony_ci int ret; 29362306a36Sopenharmony_ci u32 sample_rate = st->clk_freq; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci if (!freq) 29662306a36Sopenharmony_ci return -EINVAL; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci adis_dev_lock(&st->adis); 29962306a36Sopenharmony_ci /* 30062306a36Sopenharmony_ci * When using sync scaled mode, the input clock needs to be scaled so that we have 30162306a36Sopenharmony_ci * an IMU sample rate between (optimally) 1900 and 2100. After this, we can use the 30262306a36Sopenharmony_ci * decimation filter to lower the sampling rate in order to get what the user wants. 30362306a36Sopenharmony_ci * Optimally, the user sample rate is a multiple of both the IMU sample rate and 30462306a36Sopenharmony_ci * the input clock. Hence, calculating the sync_scale dynamically gives us better 30562306a36Sopenharmony_ci * chances of achieving a perfect/integer value for DEC_RATE. The math here is: 30662306a36Sopenharmony_ci * 1. lcm of the input clock and the desired output rate. 30762306a36Sopenharmony_ci * 2. get the highest multiple of the previous result lower than the adis max rate. 30862306a36Sopenharmony_ci * 3. The last result becomes the IMU sample rate. Use that to calculate SYNC_SCALE 30962306a36Sopenharmony_ci * and DEC_RATE (to get the user output rate) 31062306a36Sopenharmony_ci */ 31162306a36Sopenharmony_ci if (st->sync_mode == ADIS16475_SYNC_SCALED) { 31262306a36Sopenharmony_ci unsigned long scaled_rate = lcm(st->clk_freq, freq); 31362306a36Sopenharmony_ci int sync_scale; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci /* 31662306a36Sopenharmony_ci * If lcm is bigger than the IMU maximum sampling rate there's no perfect 31762306a36Sopenharmony_ci * solution. In this case, we get the highest multiple of the input clock 31862306a36Sopenharmony_ci * lower than the IMU max sample rate. 31962306a36Sopenharmony_ci */ 32062306a36Sopenharmony_ci if (scaled_rate > 2100000) 32162306a36Sopenharmony_ci scaled_rate = 2100000 / st->clk_freq * st->clk_freq; 32262306a36Sopenharmony_ci else 32362306a36Sopenharmony_ci scaled_rate = 2100000 / scaled_rate * scaled_rate; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci /* 32662306a36Sopenharmony_ci * This is not an hard requirement but it's not advised to run the IMU 32762306a36Sopenharmony_ci * with a sample rate lower than 1900Hz due to possible undersampling 32862306a36Sopenharmony_ci * issues. However, there are users that might really want to take the risk. 32962306a36Sopenharmony_ci * Hence, we provide a module parameter for them. If set, we allow sample 33062306a36Sopenharmony_ci * rates lower than 1.9KHz. By default, we won't allow this and we just roundup 33162306a36Sopenharmony_ci * the rate to the next multiple of the input clock bigger than 1.9KHz. This 33262306a36Sopenharmony_ci * is done like this as in some cases (when DEC_RATE is 0) might give 33362306a36Sopenharmony_ci * us the closest value to the one desired by the user... 33462306a36Sopenharmony_ci */ 33562306a36Sopenharmony_ci if (scaled_rate < 1900000 && !low_rate_allow) 33662306a36Sopenharmony_ci scaled_rate = roundup(1900000, st->clk_freq); 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci sync_scale = scaled_rate / st->clk_freq; 33962306a36Sopenharmony_ci ret = __adis_write_reg_16(&st->adis, ADIS16475_REG_UP_SCALE, sync_scale); 34062306a36Sopenharmony_ci if (ret) 34162306a36Sopenharmony_ci goto error; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci sample_rate = scaled_rate; 34462306a36Sopenharmony_ci } 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci dec = DIV_ROUND_CLOSEST(sample_rate, freq); 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci if (dec) 34962306a36Sopenharmony_ci dec--; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci if (dec > st->info->max_dec) 35262306a36Sopenharmony_ci dec = st->info->max_dec; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci ret = __adis_write_reg_16(&st->adis, ADIS16475_REG_DEC_RATE, dec); 35562306a36Sopenharmony_ci if (ret) 35662306a36Sopenharmony_ci goto error; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci adis_dev_unlock(&st->adis); 35962306a36Sopenharmony_ci /* 36062306a36Sopenharmony_ci * If decimation is used, then gyro and accel data will have meaningful 36162306a36Sopenharmony_ci * bits on the LSB registers. This info is used on the trigger handler. 36262306a36Sopenharmony_ci */ 36362306a36Sopenharmony_ci assign_bit(ADIS16475_LSB_DEC_MASK, &st->lsb_flag, dec); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci return 0; 36662306a36Sopenharmony_cierror: 36762306a36Sopenharmony_ci adis_dev_unlock(&st->adis); 36862306a36Sopenharmony_ci return ret; 36962306a36Sopenharmony_ci} 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci/* The values are approximated. */ 37262306a36Sopenharmony_cistatic const u32 adis16475_3db_freqs[] = { 37362306a36Sopenharmony_ci [0] = 720, /* Filter disabled, full BW (~720Hz) */ 37462306a36Sopenharmony_ci [1] = 360, 37562306a36Sopenharmony_ci [2] = 164, 37662306a36Sopenharmony_ci [3] = 80, 37762306a36Sopenharmony_ci [4] = 40, 37862306a36Sopenharmony_ci [5] = 20, 37962306a36Sopenharmony_ci [6] = 10, 38062306a36Sopenharmony_ci}; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_cistatic int adis16475_get_filter(struct adis16475 *st, u32 *filter) 38362306a36Sopenharmony_ci{ 38462306a36Sopenharmony_ci u16 filter_sz; 38562306a36Sopenharmony_ci int ret; 38662306a36Sopenharmony_ci const int mask = ADIS16475_FILT_CTRL_MASK; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FILT_CTRL, &filter_sz); 38962306a36Sopenharmony_ci if (ret) 39062306a36Sopenharmony_ci return ret; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci *filter = adis16475_3db_freqs[filter_sz & mask]; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci return 0; 39562306a36Sopenharmony_ci} 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_cistatic int adis16475_set_filter(struct adis16475 *st, const u32 filter) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci int i = ARRAY_SIZE(adis16475_3db_freqs); 40062306a36Sopenharmony_ci int ret; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci while (--i) { 40362306a36Sopenharmony_ci if (adis16475_3db_freqs[i] >= filter) 40462306a36Sopenharmony_ci break; 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci ret = adis_write_reg_16(&st->adis, ADIS16475_REG_FILT_CTRL, 40862306a36Sopenharmony_ci ADIS16475_FILT_CTRL(i)); 40962306a36Sopenharmony_ci if (ret) 41062306a36Sopenharmony_ci return ret; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci /* 41362306a36Sopenharmony_ci * If FIR is used, then gyro and accel data will have meaningful 41462306a36Sopenharmony_ci * bits on the LSB registers. This info is used on the trigger handler. 41562306a36Sopenharmony_ci */ 41662306a36Sopenharmony_ci assign_bit(ADIS16475_LSB_FIR_MASK, &st->lsb_flag, i); 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci return 0; 41962306a36Sopenharmony_ci} 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_cistatic const u32 adis16475_calib_regs[] = { 42262306a36Sopenharmony_ci [ADIS16475_SCAN_GYRO_X] = ADIS16475_REG_X_GYRO_BIAS_L, 42362306a36Sopenharmony_ci [ADIS16475_SCAN_GYRO_Y] = ADIS16475_REG_Y_GYRO_BIAS_L, 42462306a36Sopenharmony_ci [ADIS16475_SCAN_GYRO_Z] = ADIS16475_REG_Z_GYRO_BIAS_L, 42562306a36Sopenharmony_ci [ADIS16475_SCAN_ACCEL_X] = ADIS16475_REG_X_ACCEL_BIAS_L, 42662306a36Sopenharmony_ci [ADIS16475_SCAN_ACCEL_Y] = ADIS16475_REG_Y_ACCEL_BIAS_L, 42762306a36Sopenharmony_ci [ADIS16475_SCAN_ACCEL_Z] = ADIS16475_REG_Z_ACCEL_BIAS_L, 42862306a36Sopenharmony_ci}; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_cistatic int adis16475_read_raw(struct iio_dev *indio_dev, 43162306a36Sopenharmony_ci const struct iio_chan_spec *chan, 43262306a36Sopenharmony_ci int *val, int *val2, long info) 43362306a36Sopenharmony_ci{ 43462306a36Sopenharmony_ci struct adis16475 *st = iio_priv(indio_dev); 43562306a36Sopenharmony_ci int ret; 43662306a36Sopenharmony_ci u32 tmp; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci switch (info) { 43962306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 44062306a36Sopenharmony_ci return adis_single_conversion(indio_dev, chan, 0, val); 44162306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 44262306a36Sopenharmony_ci switch (chan->type) { 44362306a36Sopenharmony_ci case IIO_ANGL_VEL: 44462306a36Sopenharmony_ci *val = st->info->gyro_max_val; 44562306a36Sopenharmony_ci *val2 = st->info->gyro_max_scale; 44662306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 44762306a36Sopenharmony_ci case IIO_ACCEL: 44862306a36Sopenharmony_ci *val = st->info->accel_max_val; 44962306a36Sopenharmony_ci *val2 = st->info->accel_max_scale; 45062306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 45162306a36Sopenharmony_ci case IIO_TEMP: 45262306a36Sopenharmony_ci *val = st->info->temp_scale; 45362306a36Sopenharmony_ci return IIO_VAL_INT; 45462306a36Sopenharmony_ci default: 45562306a36Sopenharmony_ci return -EINVAL; 45662306a36Sopenharmony_ci } 45762306a36Sopenharmony_ci case IIO_CHAN_INFO_CALIBBIAS: 45862306a36Sopenharmony_ci ret = adis_read_reg_32(&st->adis, 45962306a36Sopenharmony_ci adis16475_calib_regs[chan->scan_index], 46062306a36Sopenharmony_ci val); 46162306a36Sopenharmony_ci if (ret) 46262306a36Sopenharmony_ci return ret; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci return IIO_VAL_INT; 46562306a36Sopenharmony_ci case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 46662306a36Sopenharmony_ci ret = adis16475_get_filter(st, val); 46762306a36Sopenharmony_ci if (ret) 46862306a36Sopenharmony_ci return ret; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci return IIO_VAL_INT; 47162306a36Sopenharmony_ci case IIO_CHAN_INFO_SAMP_FREQ: 47262306a36Sopenharmony_ci ret = adis16475_get_freq(st, &tmp); 47362306a36Sopenharmony_ci if (ret) 47462306a36Sopenharmony_ci return ret; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci *val = tmp / 1000; 47762306a36Sopenharmony_ci *val2 = (tmp % 1000) * 1000; 47862306a36Sopenharmony_ci return IIO_VAL_INT_PLUS_MICRO; 47962306a36Sopenharmony_ci default: 48062306a36Sopenharmony_ci return -EINVAL; 48162306a36Sopenharmony_ci } 48262306a36Sopenharmony_ci} 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_cistatic int adis16475_write_raw(struct iio_dev *indio_dev, 48562306a36Sopenharmony_ci const struct iio_chan_spec *chan, 48662306a36Sopenharmony_ci int val, int val2, long info) 48762306a36Sopenharmony_ci{ 48862306a36Sopenharmony_ci struct adis16475 *st = iio_priv(indio_dev); 48962306a36Sopenharmony_ci u32 tmp; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci switch (info) { 49262306a36Sopenharmony_ci case IIO_CHAN_INFO_SAMP_FREQ: 49362306a36Sopenharmony_ci tmp = val * 1000 + val2 / 1000; 49462306a36Sopenharmony_ci return adis16475_set_freq(st, tmp); 49562306a36Sopenharmony_ci case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 49662306a36Sopenharmony_ci return adis16475_set_filter(st, val); 49762306a36Sopenharmony_ci case IIO_CHAN_INFO_CALIBBIAS: 49862306a36Sopenharmony_ci return adis_write_reg_32(&st->adis, 49962306a36Sopenharmony_ci adis16475_calib_regs[chan->scan_index], 50062306a36Sopenharmony_ci val); 50162306a36Sopenharmony_ci default: 50262306a36Sopenharmony_ci return -EINVAL; 50362306a36Sopenharmony_ci } 50462306a36Sopenharmony_ci} 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci#define ADIS16475_MOD_CHAN(_type, _mod, _address, _si, _r_bits, _s_bits) \ 50762306a36Sopenharmony_ci { \ 50862306a36Sopenharmony_ci .type = (_type), \ 50962306a36Sopenharmony_ci .modified = 1, \ 51062306a36Sopenharmony_ci .channel2 = (_mod), \ 51162306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 51262306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_CALIBBIAS), \ 51362306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 51462306a36Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ 51562306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ 51662306a36Sopenharmony_ci .address = (_address), \ 51762306a36Sopenharmony_ci .scan_index = (_si), \ 51862306a36Sopenharmony_ci .scan_type = { \ 51962306a36Sopenharmony_ci .sign = 's', \ 52062306a36Sopenharmony_ci .realbits = (_r_bits), \ 52162306a36Sopenharmony_ci .storagebits = (_s_bits), \ 52262306a36Sopenharmony_ci .endianness = IIO_BE, \ 52362306a36Sopenharmony_ci }, \ 52462306a36Sopenharmony_ci } 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci#define ADIS16475_GYRO_CHANNEL(_mod) \ 52762306a36Sopenharmony_ci ADIS16475_MOD_CHAN(IIO_ANGL_VEL, IIO_MOD_ ## _mod, \ 52862306a36Sopenharmony_ci ADIS16475_REG_ ## _mod ## _GYRO_L, \ 52962306a36Sopenharmony_ci ADIS16475_SCAN_GYRO_ ## _mod, 32, 32) 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci#define ADIS16475_ACCEL_CHANNEL(_mod) \ 53262306a36Sopenharmony_ci ADIS16475_MOD_CHAN(IIO_ACCEL, IIO_MOD_ ## _mod, \ 53362306a36Sopenharmony_ci ADIS16475_REG_ ## _mod ## _ACCEL_L, \ 53462306a36Sopenharmony_ci ADIS16475_SCAN_ACCEL_ ## _mod, 32, 32) 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci#define ADIS16475_TEMP_CHANNEL() { \ 53762306a36Sopenharmony_ci .type = IIO_TEMP, \ 53862306a36Sopenharmony_ci .indexed = 1, \ 53962306a36Sopenharmony_ci .channel = 0, \ 54062306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 54162306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), \ 54262306a36Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ 54362306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ 54462306a36Sopenharmony_ci .address = ADIS16475_REG_TEMP_OUT, \ 54562306a36Sopenharmony_ci .scan_index = ADIS16475_SCAN_TEMP, \ 54662306a36Sopenharmony_ci .scan_type = { \ 54762306a36Sopenharmony_ci .sign = 's', \ 54862306a36Sopenharmony_ci .realbits = 16, \ 54962306a36Sopenharmony_ci .storagebits = 16, \ 55062306a36Sopenharmony_ci .endianness = IIO_BE, \ 55162306a36Sopenharmony_ci }, \ 55262306a36Sopenharmony_ci } 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_cistatic const struct iio_chan_spec adis16475_channels[] = { 55562306a36Sopenharmony_ci ADIS16475_GYRO_CHANNEL(X), 55662306a36Sopenharmony_ci ADIS16475_GYRO_CHANNEL(Y), 55762306a36Sopenharmony_ci ADIS16475_GYRO_CHANNEL(Z), 55862306a36Sopenharmony_ci ADIS16475_ACCEL_CHANNEL(X), 55962306a36Sopenharmony_ci ADIS16475_ACCEL_CHANNEL(Y), 56062306a36Sopenharmony_ci ADIS16475_ACCEL_CHANNEL(Z), 56162306a36Sopenharmony_ci ADIS16475_TEMP_CHANNEL(), 56262306a36Sopenharmony_ci IIO_CHAN_SOFT_TIMESTAMP(7) 56362306a36Sopenharmony_ci}; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_cienum adis16475_variant { 56662306a36Sopenharmony_ci ADIS16470, 56762306a36Sopenharmony_ci ADIS16475_1, 56862306a36Sopenharmony_ci ADIS16475_2, 56962306a36Sopenharmony_ci ADIS16475_3, 57062306a36Sopenharmony_ci ADIS16477_1, 57162306a36Sopenharmony_ci ADIS16477_2, 57262306a36Sopenharmony_ci ADIS16477_3, 57362306a36Sopenharmony_ci ADIS16465_1, 57462306a36Sopenharmony_ci ADIS16465_2, 57562306a36Sopenharmony_ci ADIS16465_3, 57662306a36Sopenharmony_ci ADIS16467_1, 57762306a36Sopenharmony_ci ADIS16467_2, 57862306a36Sopenharmony_ci ADIS16467_3, 57962306a36Sopenharmony_ci ADIS16500, 58062306a36Sopenharmony_ci ADIS16505_1, 58162306a36Sopenharmony_ci ADIS16505_2, 58262306a36Sopenharmony_ci ADIS16505_3, 58362306a36Sopenharmony_ci ADIS16507_1, 58462306a36Sopenharmony_ci ADIS16507_2, 58562306a36Sopenharmony_ci ADIS16507_3, 58662306a36Sopenharmony_ci}; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_cienum { 58962306a36Sopenharmony_ci ADIS16475_DIAG_STAT_DATA_PATH = 1, 59062306a36Sopenharmony_ci ADIS16475_DIAG_STAT_FLASH_MEM, 59162306a36Sopenharmony_ci ADIS16475_DIAG_STAT_SPI, 59262306a36Sopenharmony_ci ADIS16475_DIAG_STAT_STANDBY, 59362306a36Sopenharmony_ci ADIS16475_DIAG_STAT_SENSOR, 59462306a36Sopenharmony_ci ADIS16475_DIAG_STAT_MEMORY, 59562306a36Sopenharmony_ci ADIS16475_DIAG_STAT_CLK, 59662306a36Sopenharmony_ci}; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_cistatic const char * const adis16475_status_error_msgs[] = { 59962306a36Sopenharmony_ci [ADIS16475_DIAG_STAT_DATA_PATH] = "Data Path Overrun", 60062306a36Sopenharmony_ci [ADIS16475_DIAG_STAT_FLASH_MEM] = "Flash memory update failure", 60162306a36Sopenharmony_ci [ADIS16475_DIAG_STAT_SPI] = "SPI communication error", 60262306a36Sopenharmony_ci [ADIS16475_DIAG_STAT_STANDBY] = "Standby mode", 60362306a36Sopenharmony_ci [ADIS16475_DIAG_STAT_SENSOR] = "Sensor failure", 60462306a36Sopenharmony_ci [ADIS16475_DIAG_STAT_MEMORY] = "Memory failure", 60562306a36Sopenharmony_ci [ADIS16475_DIAG_STAT_CLK] = "Clock error", 60662306a36Sopenharmony_ci}; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci#define ADIS16475_DATA(_prod_id, _timeouts) \ 60962306a36Sopenharmony_ci{ \ 61062306a36Sopenharmony_ci .msc_ctrl_reg = ADIS16475_REG_MSG_CTRL, \ 61162306a36Sopenharmony_ci .glob_cmd_reg = ADIS16475_REG_GLOB_CMD, \ 61262306a36Sopenharmony_ci .diag_stat_reg = ADIS16475_REG_DIAG_STAT, \ 61362306a36Sopenharmony_ci .prod_id_reg = ADIS16475_REG_PROD_ID, \ 61462306a36Sopenharmony_ci .prod_id = (_prod_id), \ 61562306a36Sopenharmony_ci .self_test_mask = BIT(2), \ 61662306a36Sopenharmony_ci .self_test_reg = ADIS16475_REG_GLOB_CMD, \ 61762306a36Sopenharmony_ci .cs_change_delay = 16, \ 61862306a36Sopenharmony_ci .read_delay = 5, \ 61962306a36Sopenharmony_ci .write_delay = 5, \ 62062306a36Sopenharmony_ci .status_error_msgs = adis16475_status_error_msgs, \ 62162306a36Sopenharmony_ci .status_error_mask = BIT(ADIS16475_DIAG_STAT_DATA_PATH) | \ 62262306a36Sopenharmony_ci BIT(ADIS16475_DIAG_STAT_FLASH_MEM) | \ 62362306a36Sopenharmony_ci BIT(ADIS16475_DIAG_STAT_SPI) | \ 62462306a36Sopenharmony_ci BIT(ADIS16475_DIAG_STAT_STANDBY) | \ 62562306a36Sopenharmony_ci BIT(ADIS16475_DIAG_STAT_SENSOR) | \ 62662306a36Sopenharmony_ci BIT(ADIS16475_DIAG_STAT_MEMORY) | \ 62762306a36Sopenharmony_ci BIT(ADIS16475_DIAG_STAT_CLK), \ 62862306a36Sopenharmony_ci .unmasked_drdy = true, \ 62962306a36Sopenharmony_ci .timeouts = (_timeouts), \ 63062306a36Sopenharmony_ci .burst_reg_cmd = ADIS16475_REG_GLOB_CMD, \ 63162306a36Sopenharmony_ci .burst_len = ADIS16475_BURST_MAX_DATA, \ 63262306a36Sopenharmony_ci .burst_max_len = ADIS16475_BURST32_MAX_DATA, \ 63362306a36Sopenharmony_ci .burst_max_speed_hz = ADIS16475_BURST_MAX_SPEED \ 63462306a36Sopenharmony_ci} 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_cistatic const struct adis16475_sync adis16475_sync_mode[] = { 63762306a36Sopenharmony_ci { ADIS16475_SYNC_OUTPUT }, 63862306a36Sopenharmony_ci { ADIS16475_SYNC_DIRECT, 1900, 2100 }, 63962306a36Sopenharmony_ci { ADIS16475_SYNC_SCALED, 1, 128 }, 64062306a36Sopenharmony_ci { ADIS16475_SYNC_PULSE, 1000, 2100 }, 64162306a36Sopenharmony_ci}; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_cistatic const struct adis_timeout adis16475_timeouts = { 64462306a36Sopenharmony_ci .reset_ms = 200, 64562306a36Sopenharmony_ci .sw_reset_ms = 200, 64662306a36Sopenharmony_ci .self_test_ms = 20, 64762306a36Sopenharmony_ci}; 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_cistatic const struct adis_timeout adis1650x_timeouts = { 65062306a36Sopenharmony_ci .reset_ms = 260, 65162306a36Sopenharmony_ci .sw_reset_ms = 260, 65262306a36Sopenharmony_ci .self_test_ms = 30, 65362306a36Sopenharmony_ci}; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_cistatic const struct adis16475_chip_info adis16475_chip_info[] = { 65662306a36Sopenharmony_ci [ADIS16470] = { 65762306a36Sopenharmony_ci .name = "adis16470", 65862306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 65962306a36Sopenharmony_ci .channels = adis16475_channels, 66062306a36Sopenharmony_ci .gyro_max_val = 1, 66162306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), 66262306a36Sopenharmony_ci .accel_max_val = 1, 66362306a36Sopenharmony_ci .accel_max_scale = IIO_M_S_2_TO_G(800 << 16), 66462306a36Sopenharmony_ci .temp_scale = 100, 66562306a36Sopenharmony_ci .int_clk = 2000, 66662306a36Sopenharmony_ci .max_dec = 1999, 66762306a36Sopenharmony_ci .sync = adis16475_sync_mode, 66862306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode), 66962306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16470, &adis16475_timeouts), 67062306a36Sopenharmony_ci }, 67162306a36Sopenharmony_ci [ADIS16475_1] = { 67262306a36Sopenharmony_ci .name = "adis16475-1", 67362306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 67462306a36Sopenharmony_ci .channels = adis16475_channels, 67562306a36Sopenharmony_ci .gyro_max_val = 1, 67662306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16), 67762306a36Sopenharmony_ci .accel_max_val = 1, 67862306a36Sopenharmony_ci .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16), 67962306a36Sopenharmony_ci .temp_scale = 100, 68062306a36Sopenharmony_ci .int_clk = 2000, 68162306a36Sopenharmony_ci .max_dec = 1999, 68262306a36Sopenharmony_ci .sync = adis16475_sync_mode, 68362306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode), 68462306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts), 68562306a36Sopenharmony_ci }, 68662306a36Sopenharmony_ci [ADIS16475_2] = { 68762306a36Sopenharmony_ci .name = "adis16475-2", 68862306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 68962306a36Sopenharmony_ci .channels = adis16475_channels, 69062306a36Sopenharmony_ci .gyro_max_val = 1, 69162306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16), 69262306a36Sopenharmony_ci .accel_max_val = 1, 69362306a36Sopenharmony_ci .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16), 69462306a36Sopenharmony_ci .temp_scale = 100, 69562306a36Sopenharmony_ci .int_clk = 2000, 69662306a36Sopenharmony_ci .max_dec = 1999, 69762306a36Sopenharmony_ci .sync = adis16475_sync_mode, 69862306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode), 69962306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts), 70062306a36Sopenharmony_ci }, 70162306a36Sopenharmony_ci [ADIS16475_3] = { 70262306a36Sopenharmony_ci .name = "adis16475-3", 70362306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 70462306a36Sopenharmony_ci .channels = adis16475_channels, 70562306a36Sopenharmony_ci .gyro_max_val = 1, 70662306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), 70762306a36Sopenharmony_ci .accel_max_val = 1, 70862306a36Sopenharmony_ci .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16), 70962306a36Sopenharmony_ci .temp_scale = 100, 71062306a36Sopenharmony_ci .int_clk = 2000, 71162306a36Sopenharmony_ci .max_dec = 1999, 71262306a36Sopenharmony_ci .sync = adis16475_sync_mode, 71362306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode), 71462306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts), 71562306a36Sopenharmony_ci }, 71662306a36Sopenharmony_ci [ADIS16477_1] = { 71762306a36Sopenharmony_ci .name = "adis16477-1", 71862306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 71962306a36Sopenharmony_ci .channels = adis16475_channels, 72062306a36Sopenharmony_ci .gyro_max_val = 1, 72162306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16), 72262306a36Sopenharmony_ci .accel_max_val = 1, 72362306a36Sopenharmony_ci .accel_max_scale = IIO_M_S_2_TO_G(800 << 16), 72462306a36Sopenharmony_ci .temp_scale = 100, 72562306a36Sopenharmony_ci .int_clk = 2000, 72662306a36Sopenharmony_ci .max_dec = 1999, 72762306a36Sopenharmony_ci .sync = adis16475_sync_mode, 72862306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode), 72962306a36Sopenharmony_ci .has_burst32 = true, 73062306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts), 73162306a36Sopenharmony_ci }, 73262306a36Sopenharmony_ci [ADIS16477_2] = { 73362306a36Sopenharmony_ci .name = "adis16477-2", 73462306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 73562306a36Sopenharmony_ci .channels = adis16475_channels, 73662306a36Sopenharmony_ci .gyro_max_val = 1, 73762306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16), 73862306a36Sopenharmony_ci .accel_max_val = 1, 73962306a36Sopenharmony_ci .accel_max_scale = IIO_M_S_2_TO_G(800 << 16), 74062306a36Sopenharmony_ci .temp_scale = 100, 74162306a36Sopenharmony_ci .int_clk = 2000, 74262306a36Sopenharmony_ci .max_dec = 1999, 74362306a36Sopenharmony_ci .sync = adis16475_sync_mode, 74462306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode), 74562306a36Sopenharmony_ci .has_burst32 = true, 74662306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts), 74762306a36Sopenharmony_ci }, 74862306a36Sopenharmony_ci [ADIS16477_3] = { 74962306a36Sopenharmony_ci .name = "adis16477-3", 75062306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 75162306a36Sopenharmony_ci .channels = adis16475_channels, 75262306a36Sopenharmony_ci .gyro_max_val = 1, 75362306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), 75462306a36Sopenharmony_ci .accel_max_val = 1, 75562306a36Sopenharmony_ci .accel_max_scale = IIO_M_S_2_TO_G(800 << 16), 75662306a36Sopenharmony_ci .temp_scale = 100, 75762306a36Sopenharmony_ci .int_clk = 2000, 75862306a36Sopenharmony_ci .max_dec = 1999, 75962306a36Sopenharmony_ci .sync = adis16475_sync_mode, 76062306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode), 76162306a36Sopenharmony_ci .has_burst32 = true, 76262306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts), 76362306a36Sopenharmony_ci }, 76462306a36Sopenharmony_ci [ADIS16465_1] = { 76562306a36Sopenharmony_ci .name = "adis16465-1", 76662306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 76762306a36Sopenharmony_ci .channels = adis16475_channels, 76862306a36Sopenharmony_ci .gyro_max_val = 1, 76962306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16), 77062306a36Sopenharmony_ci .accel_max_val = 1, 77162306a36Sopenharmony_ci .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16), 77262306a36Sopenharmony_ci .temp_scale = 100, 77362306a36Sopenharmony_ci .int_clk = 2000, 77462306a36Sopenharmony_ci .max_dec = 1999, 77562306a36Sopenharmony_ci .sync = adis16475_sync_mode, 77662306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode), 77762306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts), 77862306a36Sopenharmony_ci }, 77962306a36Sopenharmony_ci [ADIS16465_2] = { 78062306a36Sopenharmony_ci .name = "adis16465-2", 78162306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 78262306a36Sopenharmony_ci .channels = adis16475_channels, 78362306a36Sopenharmony_ci .gyro_max_val = 1, 78462306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16), 78562306a36Sopenharmony_ci .accel_max_val = 1, 78662306a36Sopenharmony_ci .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16), 78762306a36Sopenharmony_ci .temp_scale = 100, 78862306a36Sopenharmony_ci .int_clk = 2000, 78962306a36Sopenharmony_ci .max_dec = 1999, 79062306a36Sopenharmony_ci .sync = adis16475_sync_mode, 79162306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode), 79262306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts), 79362306a36Sopenharmony_ci }, 79462306a36Sopenharmony_ci [ADIS16465_3] = { 79562306a36Sopenharmony_ci .name = "adis16465-3", 79662306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 79762306a36Sopenharmony_ci .channels = adis16475_channels, 79862306a36Sopenharmony_ci .gyro_max_val = 1, 79962306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), 80062306a36Sopenharmony_ci .accel_max_val = 1, 80162306a36Sopenharmony_ci .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16), 80262306a36Sopenharmony_ci .temp_scale = 100, 80362306a36Sopenharmony_ci .int_clk = 2000, 80462306a36Sopenharmony_ci .max_dec = 1999, 80562306a36Sopenharmony_ci .sync = adis16475_sync_mode, 80662306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode), 80762306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts), 80862306a36Sopenharmony_ci }, 80962306a36Sopenharmony_ci [ADIS16467_1] = { 81062306a36Sopenharmony_ci .name = "adis16467-1", 81162306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 81262306a36Sopenharmony_ci .channels = adis16475_channels, 81362306a36Sopenharmony_ci .gyro_max_val = 1, 81462306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16), 81562306a36Sopenharmony_ci .accel_max_val = 1, 81662306a36Sopenharmony_ci .accel_max_scale = IIO_M_S_2_TO_G(800 << 16), 81762306a36Sopenharmony_ci .temp_scale = 100, 81862306a36Sopenharmony_ci .int_clk = 2000, 81962306a36Sopenharmony_ci .max_dec = 1999, 82062306a36Sopenharmony_ci .sync = adis16475_sync_mode, 82162306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode), 82262306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts), 82362306a36Sopenharmony_ci }, 82462306a36Sopenharmony_ci [ADIS16467_2] = { 82562306a36Sopenharmony_ci .name = "adis16467-2", 82662306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 82762306a36Sopenharmony_ci .channels = adis16475_channels, 82862306a36Sopenharmony_ci .gyro_max_val = 1, 82962306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16), 83062306a36Sopenharmony_ci .accel_max_val = 1, 83162306a36Sopenharmony_ci .accel_max_scale = IIO_M_S_2_TO_G(800 << 16), 83262306a36Sopenharmony_ci .temp_scale = 100, 83362306a36Sopenharmony_ci .int_clk = 2000, 83462306a36Sopenharmony_ci .max_dec = 1999, 83562306a36Sopenharmony_ci .sync = adis16475_sync_mode, 83662306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode), 83762306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts), 83862306a36Sopenharmony_ci }, 83962306a36Sopenharmony_ci [ADIS16467_3] = { 84062306a36Sopenharmony_ci .name = "adis16467-3", 84162306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 84262306a36Sopenharmony_ci .channels = adis16475_channels, 84362306a36Sopenharmony_ci .gyro_max_val = 1, 84462306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), 84562306a36Sopenharmony_ci .accel_max_val = 1, 84662306a36Sopenharmony_ci .accel_max_scale = IIO_M_S_2_TO_G(800 << 16), 84762306a36Sopenharmony_ci .temp_scale = 100, 84862306a36Sopenharmony_ci .int_clk = 2000, 84962306a36Sopenharmony_ci .max_dec = 1999, 85062306a36Sopenharmony_ci .sync = adis16475_sync_mode, 85162306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode), 85262306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts), 85362306a36Sopenharmony_ci }, 85462306a36Sopenharmony_ci [ADIS16500] = { 85562306a36Sopenharmony_ci .name = "adis16500", 85662306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 85762306a36Sopenharmony_ci .channels = adis16475_channels, 85862306a36Sopenharmony_ci .gyro_max_val = 1, 85962306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), 86062306a36Sopenharmony_ci .accel_max_val = 392, 86162306a36Sopenharmony_ci .accel_max_scale = 32000 << 16, 86262306a36Sopenharmony_ci .temp_scale = 100, 86362306a36Sopenharmony_ci .int_clk = 2000, 86462306a36Sopenharmony_ci .max_dec = 1999, 86562306a36Sopenharmony_ci .sync = adis16475_sync_mode, 86662306a36Sopenharmony_ci /* pulse sync not supported */ 86762306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, 86862306a36Sopenharmony_ci .has_burst32 = true, 86962306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16500, &adis1650x_timeouts), 87062306a36Sopenharmony_ci }, 87162306a36Sopenharmony_ci [ADIS16505_1] = { 87262306a36Sopenharmony_ci .name = "adis16505-1", 87362306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 87462306a36Sopenharmony_ci .channels = adis16475_channels, 87562306a36Sopenharmony_ci .gyro_max_val = 1, 87662306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16), 87762306a36Sopenharmony_ci .accel_max_val = 78, 87862306a36Sopenharmony_ci .accel_max_scale = 32000 << 16, 87962306a36Sopenharmony_ci .temp_scale = 100, 88062306a36Sopenharmony_ci .int_clk = 2000, 88162306a36Sopenharmony_ci .max_dec = 1999, 88262306a36Sopenharmony_ci .sync = adis16475_sync_mode, 88362306a36Sopenharmony_ci /* pulse sync not supported */ 88462306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, 88562306a36Sopenharmony_ci .has_burst32 = true, 88662306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts), 88762306a36Sopenharmony_ci }, 88862306a36Sopenharmony_ci [ADIS16505_2] = { 88962306a36Sopenharmony_ci .name = "adis16505-2", 89062306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 89162306a36Sopenharmony_ci .channels = adis16475_channels, 89262306a36Sopenharmony_ci .gyro_max_val = 1, 89362306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16), 89462306a36Sopenharmony_ci .accel_max_val = 78, 89562306a36Sopenharmony_ci .accel_max_scale = 32000 << 16, 89662306a36Sopenharmony_ci .temp_scale = 100, 89762306a36Sopenharmony_ci .int_clk = 2000, 89862306a36Sopenharmony_ci .max_dec = 1999, 89962306a36Sopenharmony_ci .sync = adis16475_sync_mode, 90062306a36Sopenharmony_ci /* pulse sync not supported */ 90162306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, 90262306a36Sopenharmony_ci .has_burst32 = true, 90362306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts), 90462306a36Sopenharmony_ci }, 90562306a36Sopenharmony_ci [ADIS16505_3] = { 90662306a36Sopenharmony_ci .name = "adis16505-3", 90762306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 90862306a36Sopenharmony_ci .channels = adis16475_channels, 90962306a36Sopenharmony_ci .gyro_max_val = 1, 91062306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), 91162306a36Sopenharmony_ci .accel_max_val = 78, 91262306a36Sopenharmony_ci .accel_max_scale = 32000 << 16, 91362306a36Sopenharmony_ci .temp_scale = 100, 91462306a36Sopenharmony_ci .int_clk = 2000, 91562306a36Sopenharmony_ci .max_dec = 1999, 91662306a36Sopenharmony_ci .sync = adis16475_sync_mode, 91762306a36Sopenharmony_ci /* pulse sync not supported */ 91862306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, 91962306a36Sopenharmony_ci .has_burst32 = true, 92062306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts), 92162306a36Sopenharmony_ci }, 92262306a36Sopenharmony_ci [ADIS16507_1] = { 92362306a36Sopenharmony_ci .name = "adis16507-1", 92462306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 92562306a36Sopenharmony_ci .channels = adis16475_channels, 92662306a36Sopenharmony_ci .gyro_max_val = 1, 92762306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16), 92862306a36Sopenharmony_ci .accel_max_val = 392, 92962306a36Sopenharmony_ci .accel_max_scale = 32000 << 16, 93062306a36Sopenharmony_ci .temp_scale = 100, 93162306a36Sopenharmony_ci .int_clk = 2000, 93262306a36Sopenharmony_ci .max_dec = 1999, 93362306a36Sopenharmony_ci .sync = adis16475_sync_mode, 93462306a36Sopenharmony_ci /* pulse sync not supported */ 93562306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, 93662306a36Sopenharmony_ci .has_burst32 = true, 93762306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts), 93862306a36Sopenharmony_ci }, 93962306a36Sopenharmony_ci [ADIS16507_2] = { 94062306a36Sopenharmony_ci .name = "adis16507-2", 94162306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 94262306a36Sopenharmony_ci .channels = adis16475_channels, 94362306a36Sopenharmony_ci .gyro_max_val = 1, 94462306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16), 94562306a36Sopenharmony_ci .accel_max_val = 392, 94662306a36Sopenharmony_ci .accel_max_scale = 32000 << 16, 94762306a36Sopenharmony_ci .temp_scale = 100, 94862306a36Sopenharmony_ci .int_clk = 2000, 94962306a36Sopenharmony_ci .max_dec = 1999, 95062306a36Sopenharmony_ci .sync = adis16475_sync_mode, 95162306a36Sopenharmony_ci /* pulse sync not supported */ 95262306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, 95362306a36Sopenharmony_ci .has_burst32 = true, 95462306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts), 95562306a36Sopenharmony_ci }, 95662306a36Sopenharmony_ci [ADIS16507_3] = { 95762306a36Sopenharmony_ci .name = "adis16507-3", 95862306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(adis16475_channels), 95962306a36Sopenharmony_ci .channels = adis16475_channels, 96062306a36Sopenharmony_ci .gyro_max_val = 1, 96162306a36Sopenharmony_ci .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16), 96262306a36Sopenharmony_ci .accel_max_val = 392, 96362306a36Sopenharmony_ci .accel_max_scale = 32000 << 16, 96462306a36Sopenharmony_ci .temp_scale = 100, 96562306a36Sopenharmony_ci .int_clk = 2000, 96662306a36Sopenharmony_ci .max_dec = 1999, 96762306a36Sopenharmony_ci .sync = adis16475_sync_mode, 96862306a36Sopenharmony_ci /* pulse sync not supported */ 96962306a36Sopenharmony_ci .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1, 97062306a36Sopenharmony_ci .has_burst32 = true, 97162306a36Sopenharmony_ci .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts), 97262306a36Sopenharmony_ci }, 97362306a36Sopenharmony_ci}; 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_cistatic const struct iio_info adis16475_info = { 97662306a36Sopenharmony_ci .read_raw = &adis16475_read_raw, 97762306a36Sopenharmony_ci .write_raw = &adis16475_write_raw, 97862306a36Sopenharmony_ci .update_scan_mode = adis_update_scan_mode, 97962306a36Sopenharmony_ci .debugfs_reg_access = adis_debugfs_reg_access, 98062306a36Sopenharmony_ci}; 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_cistatic bool adis16475_validate_crc(const u8 *buffer, u16 crc, 98362306a36Sopenharmony_ci const bool burst32) 98462306a36Sopenharmony_ci{ 98562306a36Sopenharmony_ci int i; 98662306a36Sopenharmony_ci /* extra 6 elements for low gyro and accel */ 98762306a36Sopenharmony_ci const u16 sz = burst32 ? ADIS16475_BURST32_MAX_DATA : 98862306a36Sopenharmony_ci ADIS16475_BURST_MAX_DATA; 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci for (i = 0; i < sz - 2; i++) 99162306a36Sopenharmony_ci crc -= buffer[i]; 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci return crc == 0; 99462306a36Sopenharmony_ci} 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_cistatic void adis16475_burst32_check(struct adis16475 *st) 99762306a36Sopenharmony_ci{ 99862306a36Sopenharmony_ci int ret; 99962306a36Sopenharmony_ci struct adis *adis = &st->adis; 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci if (!st->info->has_burst32) 100262306a36Sopenharmony_ci return; 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci if (st->lsb_flag && !st->burst32) { 100562306a36Sopenharmony_ci const u16 en = ADIS16500_BURST32(1); 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL, 100862306a36Sopenharmony_ci ADIS16500_BURST32_MASK, en); 100962306a36Sopenharmony_ci if (ret) 101062306a36Sopenharmony_ci return; 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci st->burst32 = true; 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci /* 101562306a36Sopenharmony_ci * In 32-bit mode we need extra 2 bytes for all gyro 101662306a36Sopenharmony_ci * and accel channels. 101762306a36Sopenharmony_ci */ 101862306a36Sopenharmony_ci adis->burst_extra_len = 6 * sizeof(u16); 101962306a36Sopenharmony_ci adis->xfer[1].len += 6 * sizeof(u16); 102062306a36Sopenharmony_ci dev_dbg(&adis->spi->dev, "Enable burst32 mode, xfer:%d", 102162306a36Sopenharmony_ci adis->xfer[1].len); 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci } else if (!st->lsb_flag && st->burst32) { 102462306a36Sopenharmony_ci const u16 en = ADIS16500_BURST32(0); 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL, 102762306a36Sopenharmony_ci ADIS16500_BURST32_MASK, en); 102862306a36Sopenharmony_ci if (ret) 102962306a36Sopenharmony_ci return; 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci st->burst32 = false; 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci /* Remove the extra bits */ 103462306a36Sopenharmony_ci adis->burst_extra_len = 0; 103562306a36Sopenharmony_ci adis->xfer[1].len -= 6 * sizeof(u16); 103662306a36Sopenharmony_ci dev_dbg(&adis->spi->dev, "Disable burst32 mode, xfer:%d\n", 103762306a36Sopenharmony_ci adis->xfer[1].len); 103862306a36Sopenharmony_ci } 103962306a36Sopenharmony_ci} 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_cistatic irqreturn_t adis16475_trigger_handler(int irq, void *p) 104262306a36Sopenharmony_ci{ 104362306a36Sopenharmony_ci struct iio_poll_func *pf = p; 104462306a36Sopenharmony_ci struct iio_dev *indio_dev = pf->indio_dev; 104562306a36Sopenharmony_ci struct adis16475 *st = iio_priv(indio_dev); 104662306a36Sopenharmony_ci struct adis *adis = &st->adis; 104762306a36Sopenharmony_ci int ret, bit, i = 0; 104862306a36Sopenharmony_ci __be16 *buffer; 104962306a36Sopenharmony_ci u16 crc; 105062306a36Sopenharmony_ci bool valid; 105162306a36Sopenharmony_ci /* offset until the first element after gyro and accel */ 105262306a36Sopenharmony_ci const u8 offset = st->burst32 ? 13 : 7; 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci ret = spi_sync(adis->spi, &adis->msg); 105562306a36Sopenharmony_ci if (ret) 105662306a36Sopenharmony_ci goto check_burst32; 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ci buffer = adis->buffer; 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci crc = be16_to_cpu(buffer[offset + 2]); 106162306a36Sopenharmony_ci valid = adis16475_validate_crc(adis->buffer, crc, st->burst32); 106262306a36Sopenharmony_ci if (!valid) { 106362306a36Sopenharmony_ci dev_err(&adis->spi->dev, "Invalid crc\n"); 106462306a36Sopenharmony_ci goto check_burst32; 106562306a36Sopenharmony_ci } 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci for_each_set_bit(bit, indio_dev->active_scan_mask, 106862306a36Sopenharmony_ci indio_dev->masklength) { 106962306a36Sopenharmony_ci /* 107062306a36Sopenharmony_ci * When burst mode is used, system flags is the first data 107162306a36Sopenharmony_ci * channel in the sequence, but the scan index is 7. 107262306a36Sopenharmony_ci */ 107362306a36Sopenharmony_ci switch (bit) { 107462306a36Sopenharmony_ci case ADIS16475_SCAN_TEMP: 107562306a36Sopenharmony_ci st->data[i++] = buffer[offset]; 107662306a36Sopenharmony_ci break; 107762306a36Sopenharmony_ci case ADIS16475_SCAN_GYRO_X ... ADIS16475_SCAN_ACCEL_Z: 107862306a36Sopenharmony_ci /* 107962306a36Sopenharmony_ci * The first 2 bytes on the received data are the 108062306a36Sopenharmony_ci * DIAG_STAT reg, hence the +1 offset here... 108162306a36Sopenharmony_ci */ 108262306a36Sopenharmony_ci if (st->burst32) { 108362306a36Sopenharmony_ci /* upper 16 */ 108462306a36Sopenharmony_ci st->data[i++] = buffer[bit * 2 + 2]; 108562306a36Sopenharmony_ci /* lower 16 */ 108662306a36Sopenharmony_ci st->data[i++] = buffer[bit * 2 + 1]; 108762306a36Sopenharmony_ci } else { 108862306a36Sopenharmony_ci st->data[i++] = buffer[bit + 1]; 108962306a36Sopenharmony_ci /* 109062306a36Sopenharmony_ci * Don't bother in doing the manual read if the 109162306a36Sopenharmony_ci * device supports burst32. burst32 will be 109262306a36Sopenharmony_ci * enabled in the next call to 109362306a36Sopenharmony_ci * adis16475_burst32_check()... 109462306a36Sopenharmony_ci */ 109562306a36Sopenharmony_ci if (st->lsb_flag && !st->info->has_burst32) { 109662306a36Sopenharmony_ci u16 val = 0; 109762306a36Sopenharmony_ci const u32 reg = ADIS16475_REG_X_GYRO_L + 109862306a36Sopenharmony_ci bit * 4; 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci adis_read_reg_16(adis, reg, &val); 110162306a36Sopenharmony_ci st->data[i++] = cpu_to_be16(val); 110262306a36Sopenharmony_ci } else { 110362306a36Sopenharmony_ci /* lower not used */ 110462306a36Sopenharmony_ci st->data[i++] = 0; 110562306a36Sopenharmony_ci } 110662306a36Sopenharmony_ci } 110762306a36Sopenharmony_ci break; 110862306a36Sopenharmony_ci } 110962306a36Sopenharmony_ci } 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci iio_push_to_buffers_with_timestamp(indio_dev, st->data, pf->timestamp); 111262306a36Sopenharmony_cicheck_burst32: 111362306a36Sopenharmony_ci /* 111462306a36Sopenharmony_ci * We only check the burst mode at the end of the current capture since 111562306a36Sopenharmony_ci * it takes a full data ready cycle for the device to update the burst 111662306a36Sopenharmony_ci * array. 111762306a36Sopenharmony_ci */ 111862306a36Sopenharmony_ci adis16475_burst32_check(st); 111962306a36Sopenharmony_ci iio_trigger_notify_done(indio_dev->trig); 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci return IRQ_HANDLED; 112262306a36Sopenharmony_ci} 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_cistatic int adis16475_config_sync_mode(struct adis16475 *st) 112562306a36Sopenharmony_ci{ 112662306a36Sopenharmony_ci int ret; 112762306a36Sopenharmony_ci struct device *dev = &st->adis.spi->dev; 112862306a36Sopenharmony_ci const struct adis16475_sync *sync; 112962306a36Sopenharmony_ci u32 sync_mode; 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci /* default to internal clk */ 113262306a36Sopenharmony_ci st->clk_freq = st->info->int_clk * 1000; 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci ret = device_property_read_u32(dev, "adi,sync-mode", &sync_mode); 113562306a36Sopenharmony_ci if (ret) 113662306a36Sopenharmony_ci return 0; 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci if (sync_mode >= st->info->num_sync) { 113962306a36Sopenharmony_ci dev_err(dev, "Invalid sync mode: %u for %s\n", sync_mode, 114062306a36Sopenharmony_ci st->info->name); 114162306a36Sopenharmony_ci return -EINVAL; 114262306a36Sopenharmony_ci } 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci sync = &st->info->sync[sync_mode]; 114562306a36Sopenharmony_ci st->sync_mode = sync->sync_mode; 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci /* All the other modes require external input signal */ 114862306a36Sopenharmony_ci if (sync->sync_mode != ADIS16475_SYNC_OUTPUT) { 114962306a36Sopenharmony_ci struct clk *clk = devm_clk_get_enabled(dev, NULL); 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci if (IS_ERR(clk)) 115262306a36Sopenharmony_ci return PTR_ERR(clk); 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci st->clk_freq = clk_get_rate(clk); 115562306a36Sopenharmony_ci if (st->clk_freq < sync->min_rate || 115662306a36Sopenharmony_ci st->clk_freq > sync->max_rate) { 115762306a36Sopenharmony_ci dev_err(dev, 115862306a36Sopenharmony_ci "Clk rate:%u not in a valid range:[%u %u]\n", 115962306a36Sopenharmony_ci st->clk_freq, sync->min_rate, sync->max_rate); 116062306a36Sopenharmony_ci return -EINVAL; 116162306a36Sopenharmony_ci } 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_ci if (sync->sync_mode == ADIS16475_SYNC_SCALED) { 116462306a36Sopenharmony_ci u16 up_scale; 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci /* 116762306a36Sopenharmony_ci * In sync scaled mode, the IMU sample rate is the clk_freq * sync_scale. 116862306a36Sopenharmony_ci * Hence, default the IMU sample rate to the highest multiple of the input 116962306a36Sopenharmony_ci * clock lower than the IMU max sample rate. The optimal range is 117062306a36Sopenharmony_ci * 1900-2100 sps... 117162306a36Sopenharmony_ci */ 117262306a36Sopenharmony_ci up_scale = 2100 / st->clk_freq; 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci ret = __adis_write_reg_16(&st->adis, 117562306a36Sopenharmony_ci ADIS16475_REG_UP_SCALE, 117662306a36Sopenharmony_ci up_scale); 117762306a36Sopenharmony_ci if (ret) 117862306a36Sopenharmony_ci return ret; 117962306a36Sopenharmony_ci } 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci st->clk_freq *= 1000; 118262306a36Sopenharmony_ci } 118362306a36Sopenharmony_ci /* 118462306a36Sopenharmony_ci * Keep in mind that the mask for the clk modes in adis1650* 118562306a36Sopenharmony_ci * chips is different (1100 instead of 11100). However, we 118662306a36Sopenharmony_ci * are not configuring BIT(4) in these chips and the default 118762306a36Sopenharmony_ci * value is 0, so we are fine in doing the below operations. 118862306a36Sopenharmony_ci * I'm keeping this for simplicity and avoiding extra variables 118962306a36Sopenharmony_ci * in chip_info. 119062306a36Sopenharmony_ci */ 119162306a36Sopenharmony_ci ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL, 119262306a36Sopenharmony_ci ADIS16475_SYNC_MODE_MASK, sync->sync_mode); 119362306a36Sopenharmony_ci if (ret) 119462306a36Sopenharmony_ci return ret; 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci usleep_range(250, 260); 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci return 0; 119962306a36Sopenharmony_ci} 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_cistatic int adis16475_config_irq_pin(struct adis16475 *st) 120262306a36Sopenharmony_ci{ 120362306a36Sopenharmony_ci int ret; 120462306a36Sopenharmony_ci struct irq_data *desc; 120562306a36Sopenharmony_ci u32 irq_type; 120662306a36Sopenharmony_ci u16 val = 0; 120762306a36Sopenharmony_ci u8 polarity; 120862306a36Sopenharmony_ci struct spi_device *spi = st->adis.spi; 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci desc = irq_get_irq_data(spi->irq); 121162306a36Sopenharmony_ci if (!desc) { 121262306a36Sopenharmony_ci dev_err(&spi->dev, "Could not find IRQ %d\n", spi->irq); 121362306a36Sopenharmony_ci return -EINVAL; 121462306a36Sopenharmony_ci } 121562306a36Sopenharmony_ci /* 121662306a36Sopenharmony_ci * It is possible to configure the data ready polarity. Furthermore, we 121762306a36Sopenharmony_ci * need to update the adis struct if we want data ready as active low. 121862306a36Sopenharmony_ci */ 121962306a36Sopenharmony_ci irq_type = irqd_get_trigger_type(desc); 122062306a36Sopenharmony_ci if (irq_type == IRQ_TYPE_EDGE_RISING) { 122162306a36Sopenharmony_ci polarity = 1; 122262306a36Sopenharmony_ci st->adis.irq_flag = IRQF_TRIGGER_RISING; 122362306a36Sopenharmony_ci } else if (irq_type == IRQ_TYPE_EDGE_FALLING) { 122462306a36Sopenharmony_ci polarity = 0; 122562306a36Sopenharmony_ci st->adis.irq_flag = IRQF_TRIGGER_FALLING; 122662306a36Sopenharmony_ci } else { 122762306a36Sopenharmony_ci dev_err(&spi->dev, "Invalid interrupt type 0x%x specified\n", 122862306a36Sopenharmony_ci irq_type); 122962306a36Sopenharmony_ci return -EINVAL; 123062306a36Sopenharmony_ci } 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci val = ADIS16475_MSG_CTRL_DR_POL(polarity); 123362306a36Sopenharmony_ci ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL, 123462306a36Sopenharmony_ci ADIS16475_MSG_CTRL_DR_POL_MASK, val); 123562306a36Sopenharmony_ci if (ret) 123662306a36Sopenharmony_ci return ret; 123762306a36Sopenharmony_ci /* 123862306a36Sopenharmony_ci * There is a delay writing to any bits written to the MSC_CTRL 123962306a36Sopenharmony_ci * register. It should not be bigger than 200us, so 250 should be more 124062306a36Sopenharmony_ci * than enough! 124162306a36Sopenharmony_ci */ 124262306a36Sopenharmony_ci usleep_range(250, 260); 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci return 0; 124562306a36Sopenharmony_ci} 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_cistatic int adis16475_probe(struct spi_device *spi) 124962306a36Sopenharmony_ci{ 125062306a36Sopenharmony_ci struct iio_dev *indio_dev; 125162306a36Sopenharmony_ci struct adis16475 *st; 125262306a36Sopenharmony_ci int ret; 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_ci indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 125562306a36Sopenharmony_ci if (!indio_dev) 125662306a36Sopenharmony_ci return -ENOMEM; 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci st = iio_priv(indio_dev); 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci st->info = spi_get_device_match_data(spi); 126162306a36Sopenharmony_ci if (!st->info) 126262306a36Sopenharmony_ci return -EINVAL; 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci ret = adis_init(&st->adis, indio_dev, spi, &st->info->adis_data); 126562306a36Sopenharmony_ci if (ret) 126662306a36Sopenharmony_ci return ret; 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci indio_dev->name = st->info->name; 126962306a36Sopenharmony_ci indio_dev->channels = st->info->channels; 127062306a36Sopenharmony_ci indio_dev->num_channels = st->info->num_channels; 127162306a36Sopenharmony_ci indio_dev->info = &adis16475_info; 127262306a36Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci ret = __adis_initial_startup(&st->adis); 127562306a36Sopenharmony_ci if (ret) 127662306a36Sopenharmony_ci return ret; 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_ci ret = adis16475_config_irq_pin(st); 127962306a36Sopenharmony_ci if (ret) 128062306a36Sopenharmony_ci return ret; 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_ci ret = adis16475_config_sync_mode(st); 128362306a36Sopenharmony_ci if (ret) 128462306a36Sopenharmony_ci return ret; 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_ci ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, 128762306a36Sopenharmony_ci adis16475_trigger_handler); 128862306a36Sopenharmony_ci if (ret) 128962306a36Sopenharmony_ci return ret; 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci ret = devm_iio_device_register(&spi->dev, indio_dev); 129262306a36Sopenharmony_ci if (ret) 129362306a36Sopenharmony_ci return ret; 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci adis16475_debugfs_init(indio_dev); 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ci return 0; 129862306a36Sopenharmony_ci} 129962306a36Sopenharmony_ci 130062306a36Sopenharmony_cistatic const struct of_device_id adis16475_of_match[] = { 130162306a36Sopenharmony_ci { .compatible = "adi,adis16470", 130262306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16470] }, 130362306a36Sopenharmony_ci { .compatible = "adi,adis16475-1", 130462306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16475_1] }, 130562306a36Sopenharmony_ci { .compatible = "adi,adis16475-2", 130662306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16475_2] }, 130762306a36Sopenharmony_ci { .compatible = "adi,adis16475-3", 130862306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16475_3] }, 130962306a36Sopenharmony_ci { .compatible = "adi,adis16477-1", 131062306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16477_1] }, 131162306a36Sopenharmony_ci { .compatible = "adi,adis16477-2", 131262306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16477_2] }, 131362306a36Sopenharmony_ci { .compatible = "adi,adis16477-3", 131462306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16477_3] }, 131562306a36Sopenharmony_ci { .compatible = "adi,adis16465-1", 131662306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16465_1] }, 131762306a36Sopenharmony_ci { .compatible = "adi,adis16465-2", 131862306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16465_2] }, 131962306a36Sopenharmony_ci { .compatible = "adi,adis16465-3", 132062306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16465_3] }, 132162306a36Sopenharmony_ci { .compatible = "adi,adis16467-1", 132262306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16467_1] }, 132362306a36Sopenharmony_ci { .compatible = "adi,adis16467-2", 132462306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16467_2] }, 132562306a36Sopenharmony_ci { .compatible = "adi,adis16467-3", 132662306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16467_3] }, 132762306a36Sopenharmony_ci { .compatible = "adi,adis16500", 132862306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16500] }, 132962306a36Sopenharmony_ci { .compatible = "adi,adis16505-1", 133062306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16505_1] }, 133162306a36Sopenharmony_ci { .compatible = "adi,adis16505-2", 133262306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16505_2] }, 133362306a36Sopenharmony_ci { .compatible = "adi,adis16505-3", 133462306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16505_3] }, 133562306a36Sopenharmony_ci { .compatible = "adi,adis16507-1", 133662306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16507_1] }, 133762306a36Sopenharmony_ci { .compatible = "adi,adis16507-2", 133862306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16507_2] }, 133962306a36Sopenharmony_ci { .compatible = "adi,adis16507-3", 134062306a36Sopenharmony_ci .data = &adis16475_chip_info[ADIS16507_3] }, 134162306a36Sopenharmony_ci { }, 134262306a36Sopenharmony_ci}; 134362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, adis16475_of_match); 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_cistatic const struct spi_device_id adis16475_ids[] = { 134662306a36Sopenharmony_ci { "adis16470", (kernel_ulong_t)&adis16475_chip_info[ADIS16470] }, 134762306a36Sopenharmony_ci { "adis16475-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16475_1] }, 134862306a36Sopenharmony_ci { "adis16475-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16475_2] }, 134962306a36Sopenharmony_ci { "adis16475-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16475_3] }, 135062306a36Sopenharmony_ci { "adis16477-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16477_1] }, 135162306a36Sopenharmony_ci { "adis16477-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16477_2] }, 135262306a36Sopenharmony_ci { "adis16477-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16477_3] }, 135362306a36Sopenharmony_ci { "adis16465-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16465_1] }, 135462306a36Sopenharmony_ci { "adis16465-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16465_2] }, 135562306a36Sopenharmony_ci { "adis16465-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16465_3] }, 135662306a36Sopenharmony_ci { "adis16467-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16467_1] }, 135762306a36Sopenharmony_ci { "adis16467-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16467_2] }, 135862306a36Sopenharmony_ci { "adis16467-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16467_3] }, 135962306a36Sopenharmony_ci { "adis16500", (kernel_ulong_t)&adis16475_chip_info[ADIS16500] }, 136062306a36Sopenharmony_ci { "adis16505-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16505_1] }, 136162306a36Sopenharmony_ci { "adis16505-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16505_2] }, 136262306a36Sopenharmony_ci { "adis16505-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16505_3] }, 136362306a36Sopenharmony_ci { "adis16507-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_1] }, 136462306a36Sopenharmony_ci { "adis16507-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_2] }, 136562306a36Sopenharmony_ci { "adis16507-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_3] }, 136662306a36Sopenharmony_ci { } 136762306a36Sopenharmony_ci}; 136862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, adis16475_ids); 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_cistatic struct spi_driver adis16475_driver = { 137162306a36Sopenharmony_ci .driver = { 137262306a36Sopenharmony_ci .name = "adis16475", 137362306a36Sopenharmony_ci .of_match_table = adis16475_of_match, 137462306a36Sopenharmony_ci }, 137562306a36Sopenharmony_ci .probe = adis16475_probe, 137662306a36Sopenharmony_ci .id_table = adis16475_ids, 137762306a36Sopenharmony_ci}; 137862306a36Sopenharmony_cimodule_spi_driver(adis16475_driver); 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ciMODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>"); 138162306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices ADIS16475 IMU driver"); 138262306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 138362306a36Sopenharmony_ciMODULE_IMPORT_NS(IIO_ADISLIB); 1384