summaryrefslogtreecommitdiff
path: root/drivers/iio/imu
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-05-15 16:03:28 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-05-15 16:03:28 +0200
commitcef077e6aa4c7dbe2f23e1201cf705f9540ec467 (patch)
treed955418799ae8d491a648e07a44425bb06d957bb /drivers/iio/imu
parentc336c022503d1be719ca06f2526c211709e3d2d3 (diff)
parent6b46ddb51eab245c64b6b9c55c189e45967d213f (diff)
Merge tag 'iio-for-5.8b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
Jonathan writes: Second set of new device support, cleanups and features for IIO in the 5.8 cycle Usual mixed back but with a few subsystem wide or device type wide cleanups. New device support * adis16475 - New driver supporting adis16470, adis16475, adis16477, adis16465, adis16467, adis16500, adis16505 and adis16507. Includes some rework of the adis library to simplify using it for this new driver. * ak8974 - Add support for Alps hscdt008a. ID only. Related patches add support for scale. * atlas-sensor - Add support for RTD-SM OEM temperature sensor. * cm32181 - Add support for CM3218 including support for SMBUS alert via ACPI resources. * ltc2632 - Add support for ltc2634-12/10/8 DACS including handling per device type numbers of channels. Major Features * cm32181 - ACPI bindings including parsing CPM0 and CPM1 custom ACPI tables. Includes minor tidy ups and fixes. * vcnl4000 - Add event support - Add buffered data capture support - Add control of sampling frequency Cleanups and minor fixes. * core - Trivial rework of iio_device_alloc to use an early return and improve readability. - Precursors to addition of multiple buffer support. So far minor refactoring. * subsystem wide - Use get_unaligned_be24 slightly improve readability over open coding it. * adis drivers - Use iio_get_debugfs_dentry access function. * bh1780, cm32181, cm3232, gp2ap02a00f, opt3001, st_uvis25, vl6180, dmard06, kxsd9 - Drop use of of_match_ptr to allow ACPI based probing via PRP0001. Part of clear out of this to avoid cut and paste into new drivers. * ad5592r, ad5593r - Fix typos * ad5933 - Use managed interfaces to automate error handling and remove. * ak8974 - Fix wrong number of 'real bits' for buffered data. - Refactor to pull measurement code out as separate function. bmp280 - Fix lack of clamp on range during data capture. * at91-sama5d2_adc - Handle unfinished conversions correctly. - Allow use of triggers other than it's own. - Reorganize buffer setup and tear down as part of long running subsystem wide rework. * ccs811 - Add DT binding docs and match table. - Support external reset and wakeup pins. * hid-sensors - Reorganize buffer setup and tear down as part of long running subsystem wide rework. * ltr501 - Constify some structs. * vcnl4000 - Fix an endian issue by using explicit byte swapped i2c accessors. * tag 'iio-for-5.8b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (74 commits) iio: light: ltr501: Constify structs staging: iio: ad5933: attach life-cycle of kfifo buffer to parent device and use managed calls throughout iio: bmp280: fix compensation of humidity iio: light: cm32181: Fix integartion time typo iio: light: cm32181: Add support for parsing CPM0 and CPM1 ACPI tables iio: light: cm32181: Make lux_per_bit and lux_per_bit_base_it runtime settings iio: light: cm32181: Use units of 1/100000th for calibscale and lux_per_bit iio: light: cm32181: Change reg_init to use a bitmap of which registers to init iio: light: cm32181: Handle CM3218 ACPI devices with 2 I2C resources iio: light: cm32181: Clean up the probe function a bit iio: light: cm32181: Add support for the CM3218 iio: light: cm32181: Add some extra register defines iio: light: cm32181: Add support for ACPI enumeration iio: light: cm32181: Switch to new style i2c-driver probe function iio: hid-sensors: move triggered buffer setup into hid_sensor_setup_trigger iio: vcnl4000: Add buffer support for VCNL4010/20. iio: vcnl4000: Add sampling frequency support for VCNL4010/20. iio: vcnl4000: Add event support for VCNL4010/20. iio: vcnl4000: Factorize data reading and writing. iio: vcnl4000: Fix i2c swapped word reading. ...
Diffstat (limited to 'drivers/iio/imu')
-rw-r--r--drivers/iio/imu/Kconfig13
-rw-r--r--drivers/iio/imu/Makefile1
-rw-r--r--drivers/iio/imu/adis.c25
-rw-r--r--drivers/iio/imu/adis16400.c12
-rw-r--r--drivers/iio/imu/adis16460.c10
-rw-r--r--drivers/iio/imu/adis16475.c1338
-rw-r--r--drivers/iio/imu/adis16480.c16
-rw-r--r--drivers/iio/imu/adis_buffer.c58
-rw-r--r--drivers/iio/imu/adis_trigger.c72
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c21
10 files changed, 1528 insertions, 38 deletions
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index 60bb1029e759..fc4123d518bc 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -29,6 +29,19 @@ config ADIS16460
To compile this driver as a module, choose M here: the module will be
called adis16460.
+config ADIS16475
+ tristate "Analog Devices ADIS16475 and similar IMU driver"
+ depends on SPI
+ select IIO_ADIS_LIB
+ select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
+ help
+ Say yes here to build support for Analog Devices ADIS16470, ADIS16475,
+ ADIS16477, ADIS16465, ADIS16467, ADIS16500, ADIS16505, ADIS16507 inertial
+ sensors.
+
+ To compile this driver as a module, choose M here: the module will be
+ called adis16475.
+
config ADIS16480
tristate "Analog Devices ADIS16480 and similar IMU driver"
depends on SPI
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
index 5237fd4bc384..88b2c4555230 100644
--- a/drivers/iio/imu/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -6,6 +6,7 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ADIS16400) += adis16400.o
obj-$(CONFIG_ADIS16460) += adis16460.o
+obj-$(CONFIG_ADIS16475) += adis16475.o
obj-$(CONFIG_ADIS16480) += adis16480.o
adis_lib-y += adis.o
diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c
index 2e7d0d337f8f..c539dfa3b8d3 100644
--- a/drivers/iio/imu/adis.c
+++ b/drivers/iio/imu/adis.c
@@ -223,6 +223,31 @@ int __adis_read_reg(struct adis *adis, unsigned int reg,
return ret;
}
EXPORT_SYMBOL_GPL(__adis_read_reg);
+/**
+ * __adis_update_bits_base() - ADIS Update bits function - Unlocked version
+ * @adis: The adis device
+ * @reg: The address of the lower of the two registers
+ * @mask: Bitmask to change
+ * @val: Value to be written
+ * @size: Size of the register to update
+ *
+ * Updates the desired bits of @reg in accordance with @mask and @val.
+ */
+int __adis_update_bits_base(struct adis *adis, unsigned int reg, const u32 mask,
+ const u32 val, u8 size)
+{
+ int ret;
+ u32 __val;
+
+ ret = __adis_read_reg(adis, reg, &__val, size);
+ if (ret)
+ return ret;
+
+ __val = (__val & ~mask) | (val & mask);
+
+ return __adis_write_reg(adis, reg, __val, size);
+}
+EXPORT_SYMBOL_GPL(__adis_update_bits_base);
#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c
index 4445c242709c..229f2ff98469 100644
--- a/drivers/iio/imu/adis16400.c
+++ b/drivers/iio/imu/adis16400.c
@@ -281,18 +281,16 @@ DEFINE_DEBUGFS_ATTRIBUTE(adis16400_flash_count_fops,
static int adis16400_debugfs_init(struct iio_dev *indio_dev)
{
struct adis16400_state *st = iio_priv(indio_dev);
+ struct dentry *d = iio_get_debugfs_dentry(indio_dev);
if (st->variant->flags & ADIS16400_HAS_SERIAL_NUMBER)
debugfs_create_file_unsafe("serial_number", 0400,
- indio_dev->debugfs_dentry, st,
- &adis16400_serial_number_fops);
+ d, st, &adis16400_serial_number_fops);
if (st->variant->flags & ADIS16400_HAS_PROD_ID)
debugfs_create_file_unsafe("product_id", 0400,
- indio_dev->debugfs_dentry, st,
- &adis16400_product_id_fops);
+ d, st, &adis16400_product_id_fops);
debugfs_create_file_unsafe("flash_count", 0400,
- indio_dev->debugfs_dentry, st,
- &adis16400_flash_count_fops);
+ d, st, &adis16400_flash_count_fops);
return 0;
}
@@ -1195,7 +1193,7 @@ static int adis16400_probe(struct spi_device *spi)
indio_dev->available_scan_masks = st->avail_scan_mask;
st->adis.burst = &adis16400_burst;
if (st->variant->flags & ADIS16400_BURST_DIAG_STAT)
- st->adis.burst->extra_len = sizeof(u16);
+ st->adis.burst_extra_len = sizeof(u16);
}
adis16400_data = &st->variant->adis_data;
diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c
index 0957f5cfe9c0..ad20c488a3ba 100644
--- a/drivers/iio/imu/adis16460.c
+++ b/drivers/iio/imu/adis16460.c
@@ -129,16 +129,14 @@ DEFINE_DEBUGFS_ATTRIBUTE(adis16460_flash_count_fops,
static int adis16460_debugfs_init(struct iio_dev *indio_dev)
{
struct adis16460 *adis16460 = iio_priv(indio_dev);
+ struct dentry *d = iio_get_debugfs_dentry(indio_dev);
debugfs_create_file_unsafe("serial_number", 0400,
- indio_dev->debugfs_dentry, adis16460,
- &adis16460_serial_number_fops);
+ d, adis16460, &adis16460_serial_number_fops);
debugfs_create_file_unsafe("product_id", 0400,
- indio_dev->debugfs_dentry, adis16460,
- &adis16460_product_id_fops);
+ d, adis16460, &adis16460_product_id_fops);
debugfs_create_file_unsafe("flash_count", 0400,
- indio_dev->debugfs_dentry, adis16460,
- &adis16460_flash_count_fops);
+ d, adis16460, &adis16460_flash_count_fops);
return 0;
}
diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c
new file mode 100644
index 000000000000..c6dac4fc67a1
--- /dev/null
+++ b/drivers/iio/imu/adis16475.c
@@ -0,0 +1,1338 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ADIS16475 IMU driver
+ *
+ * Copyright 2019 Analog Devices Inc.
+ */
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/imu/adis.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/property.h>
+#include <linux/spi/spi.h>
+
+#define ADIS16475_REG_DIAG_STAT 0x02
+#define ADIS16475_REG_X_GYRO_L 0x04
+#define ADIS16475_REG_Y_GYRO_L 0x08
+#define ADIS16475_REG_Z_GYRO_L 0x0C
+#define ADIS16475_REG_X_ACCEL_L 0x10
+#define ADIS16475_REG_Y_ACCEL_L 0x14
+#define ADIS16475_REG_Z_ACCEL_L 0x18
+#define ADIS16475_REG_TEMP_OUT 0x1c
+#define ADIS16475_REG_X_GYRO_BIAS_L 0x40
+#define ADIS16475_REG_Y_GYRO_BIAS_L 0x44
+#define ADIS16475_REG_Z_GYRO_BIAS_L 0x48
+#define ADIS16475_REG_X_ACCEL_BIAS_L 0x4c
+#define ADIS16475_REG_Y_ACCEL_BIAS_L 0x50
+#define ADIS16475_REG_Z_ACCEL_BIAS_L 0x54
+#define ADIS16475_REG_FILT_CTRL 0x5c
+#define ADIS16475_FILT_CTRL_MASK GENMASK(2, 0)
+#define ADIS16475_FILT_CTRL(x) FIELD_PREP(ADIS16475_FILT_CTRL_MASK, x)
+#define ADIS16475_REG_MSG_CTRL 0x60
+#define ADIS16475_MSG_CTRL_DR_POL_MASK BIT(0)
+#define ADIS16475_MSG_CTRL_DR_POL(x) \
+ FIELD_PREP(ADIS16475_MSG_CTRL_DR_POL_MASK, x)
+#define ADIS16475_SYNC_MODE_MASK GENMASK(4, 2)
+#define ADIS16475_SYNC_MODE(x) FIELD_PREP(ADIS16475_SYNC_MODE_MASK, x)
+#define ADIS16475_REG_UP_SCALE 0x62
+#define ADIS16475_REG_DEC_RATE 0x64
+#define ADIS16475_REG_GLOB_CMD 0x68
+#define ADIS16475_REG_FIRM_REV 0x6c
+#define ADIS16475_REG_FIRM_DM 0x6e
+#define ADIS16475_REG_FIRM_Y 0x70
+#define ADIS16475_REG_PROD_ID 0x72
+#define ADIS16475_REG_SERIAL_NUM 0x74
+#define ADIS16475_REG_FLASH_CNT 0x7c
+#define ADIS16500_BURST32_MASK BIT(9)
+#define ADIS16500_BURST32(x) FIELD_PREP(ADIS16500_BURST32_MASK, x)
+/* number of data elements in burst mode */
+#define ADIS16475_BURST32_MAX_DATA 32
+#define ADIS16475_BURST_MAX_DATA 20
+#define ADIS16475_MAX_SCAN_DATA 20
+/* spi max speed in brust mode */
+#define ADIS16475_BURST_MAX_SPEED 1000000
+#define ADIS16475_LSB_DEC_MASK BIT(0)
+#define ADIS16475_LSB_FIR_MASK BIT(1)
+
+enum {
+ ADIS16475_SYNC_DIRECT = 1,
+ ADIS16475_SYNC_SCALED,
+ ADIS16475_SYNC_OUTPUT,
+ ADIS16475_SYNC_PULSE = 5,
+};
+
+struct adis16475_sync {
+ u16 sync_mode;
+ u16 min_rate;
+ u16 max_rate;
+};
+
+struct adis16475_chip_info {
+ const struct iio_chan_spec *channels;
+ const struct adis16475_sync *sync;
+ const struct adis_data adis_data;
+ const char *name;
+ u32 num_channels;
+ u32 gyro_max_val;
+ u32 gyro_max_scale;
+ u32 accel_max_val;
+ u32 accel_max_scale;
+ u32 temp_scale;
+ u32 int_clk;
+ u16 max_dec;
+ u8 num_sync;
+ bool has_burst32;
+};
+
+struct adis16475 {
+ const struct adis16475_chip_info *info;
+ struct adis adis;
+ u32 clk_freq;
+ bool burst32;
+ unsigned long lsb_flag;
+ /* Alignment needed for the timestamp */
+ __be16 data[ADIS16475_MAX_SCAN_DATA] __aligned(8);
+};
+
+enum {
+ ADIS16475_SCAN_GYRO_X,
+ ADIS16475_SCAN_GYRO_Y,
+ ADIS16475_SCAN_GYRO_Z,
+ ADIS16475_SCAN_ACCEL_X,
+ ADIS16475_SCAN_ACCEL_Y,
+ ADIS16475_SCAN_ACCEL_Z,
+ ADIS16475_SCAN_TEMP,
+ ADIS16475_SCAN_DIAG_S_FLAGS,
+ ADIS16475_SCAN_CRC_FAILURE,
+};
+
+#ifdef CONFIG_DEBUG_FS
+static ssize_t adis16475_show_firmware_revision(struct file *file,
+ char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct adis16475 *st = file->private_data;
+ char buf[7];
+ size_t len;
+ u16 rev;
+ int ret;
+
+ ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIRM_REV, &rev);
+ if (ret)
+ return ret;
+
+ len = scnprintf(buf, sizeof(buf), "%x.%x\n", rev >> 8, rev & 0xff);
+
+ return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+
+static const struct file_operations adis16475_firmware_revision_fops = {
+ .open = simple_open,
+ .read = adis16475_show_firmware_revision,
+ .llseek = default_llseek,
+ .owner = THIS_MODULE,
+};
+
+static ssize_t adis16475_show_firmware_date(struct file *file,
+ char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct adis16475 *st = file->private_data;
+ u16 md, year;
+ char buf[12];
+ size_t len;
+ int ret;
+
+ ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIRM_Y, &year);
+ if (ret)
+ return ret;
+
+ ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIRM_DM, &md);
+ if (ret)
+ return ret;
+
+ len = snprintf(buf, sizeof(buf), "%.2x-%.2x-%.4x\n", md >> 8, md & 0xff,
+ year);
+
+ return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+
+static const struct file_operations adis16475_firmware_date_fops = {
+ .open = simple_open,
+ .read = adis16475_show_firmware_date,
+ .llseek = default_llseek,
+ .owner = THIS_MODULE,
+};
+
+static int adis16475_show_serial_number(void *arg, u64 *val)
+{
+ struct adis16475 *st = arg;
+ u16 serial;
+ int ret;
+
+ ret = adis_read_reg_16(&st->adis, ADIS16475_REG_SERIAL_NUM, &serial);
+ if (ret)
+ return ret;
+
+ *val = serial;
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(adis16475_serial_number_fops,
+ adis16475_show_serial_number, NULL, "0x%.4llx\n");
+
+static int adis16475_show_product_id(void *arg, u64 *val)
+{
+ struct adis16475 *st = arg;
+ u16 prod_id;
+ int ret;
+
+ ret = adis_read_reg_16(&st->adis, ADIS16475_REG_PROD_ID, &prod_id);
+ if (ret)
+ return ret;
+
+ *val = prod_id;
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(adis16475_product_id_fops,
+ adis16475_show_product_id, NULL, "%llu\n");
+
+static int adis16475_show_flash_count(void *arg, u64 *val)
+{
+ struct adis16475 *st = arg;
+ u32 flash_count;
+ int ret;
+
+ ret = adis_read_reg_32(&st->adis, ADIS16475_REG_FLASH_CNT,
+ &flash_count);
+ if (ret)
+ return ret;
+
+ *val = flash_count;
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(adis16475_flash_count_fops,
+ adis16475_show_flash_count, NULL, "%lld\n");
+
+static void adis16475_debugfs_init(struct iio_dev *indio_dev)
+{
+ struct adis16475 *st = iio_priv(indio_dev);
+ struct dentry *d = iio_get_debugfs_dentry(indio_dev);
+
+ debugfs_create_file_unsafe("serial_number", 0400,
+ d, st, &adis16475_serial_number_fops);
+ debugfs_create_file_unsafe("product_id", 0400,
+ d, st, &adis16475_product_id_fops);
+ debugfs_create_file_unsafe("flash_count", 0400,
+ d, st, &adis16475_flash_count_fops);
+ debugfs_create_file("firmware_revision", 0400,
+ d, st, &adis16475_firmware_revision_fops);
+ debugfs_create_file("firmware_date", 0400, d,
+ st, &adis16475_firmware_date_fops);
+}
+#else
+static void adis16475_debugfs_init(struct iio_dev *indio_dev)
+{
+}
+#endif
+
+static int adis16475_get_freq(struct adis16475 *st, u32 *freq)
+{
+ int ret;
+ u16 dec;
+
+ ret = adis_read_reg_16(&st->adis, ADIS16475_REG_DEC_RATE, &dec);
+ if (ret)
+ return -EINVAL;
+
+ *freq = DIV_ROUND_CLOSEST(st->clk_freq, dec + 1);
+
+ return 0;
+}
+
+static int adis16475_set_freq(struct adis16475 *st, const u32 freq)
+{
+ u16 dec;
+ int ret;
+
+ if (!freq)
+ return -EINVAL;
+
+ dec = DIV_ROUND_CLOSEST(st->clk_freq, freq);
+
+ if (dec)
+ dec--;
+
+ if (dec > st->info->max_dec)
+ dec = st->info->max_dec;
+
+ ret = adis_write_reg_16(&st->adis, ADIS16475_REG_DEC_RATE, dec);
+ if (ret)
+ return ret;
+
+ /*
+ * If decimation is used, then gyro and accel data will have meaningful
+ * bits on the LSB registers. This info is used on the trigger handler.
+ */
+ assign_bit(ADIS16475_LSB_DEC_MASK, &st->lsb_flag, dec);
+
+ return 0;
+}
+
+/* The values are approximated. */
+static const u32 adis16475_3db_freqs[] = {
+ [0] = 720, /* Filter disabled, full BW (~720Hz) */
+ [1] = 360,
+ [2] = 164,
+ [3] = 80,
+ [4] = 40,
+ [5] = 20,
+ [6] = 10,
+};
+
+static int adis16475_get_filter(struct adis16475 *st, u32 *filter)
+{
+ u16 filter_sz;
+ int ret;
+ const int mask = ADIS16475_FILT_CTRL_MASK;
+
+ ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FILT_CTRL, &filter_sz);
+ if (ret)
+ return ret;
+
+ *filter = adis16475_3db_freqs[filter_sz & mask];
+
+ return 0;
+}
+
+static int adis16475_set_filter(struct adis16475 *st, const u32 filter)
+{
+ int i = ARRAY_SIZE(adis16475_3db_freqs);
+ int ret;
+
+ while (--i) {
+ if (adis16475_3db_freqs[i] >= filter)
+ break;
+ }
+
+ ret = adis_write_reg_16(&st->adis, ADIS16475_REG_FILT_CTRL,
+ ADIS16475_FILT_CTRL(i));
+ if (ret)
+ return ret;
+
+ /*
+ * If FIR is used, then gyro and accel data will have meaningful
+ * bits on the LSB registers. This info is used on the trigger handler.
+ */
+ assign_bit(ADIS16475_LSB_FIR_MASK, &st->lsb_flag, i);
+
+ return 0;
+}
+
+static const u32 adis16475_calib_regs[] = {
+ [ADIS16475_SCAN_GYRO_X] = ADIS16475_REG_X_GYRO_BIAS_L,
+ [ADIS16475_SCAN_GYRO_Y] = ADIS16475_REG_Y_GYRO_BIAS_L,
+ [ADIS16475_SCAN_GYRO_Z] = ADIS16475_REG_Z_GYRO_BIAS_L,
+ [ADIS16475_SCAN_ACCEL_X] = ADIS16475_REG_X_ACCEL_BIAS_L,
+ [ADIS16475_SCAN_ACCEL_Y] = ADIS16475_REG_Y_ACCEL_BIAS_L,
+ [ADIS16475_SCAN_ACCEL_Z] = ADIS16475_REG_Z_ACCEL_BIAS_L,
+};
+
+static int adis16475_read_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2, long info)
+{
+ struct adis16475 *st = iio_priv(indio_dev);
+ int ret;
+ u32 tmp;
+
+ switch (info) {
+ case IIO_CHAN_INFO_RAW:
+ return adis_single_conversion(indio_dev, chan, 0, val);
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_ANGL_VEL:
+ *val = st->info->gyro_max_val;
+ *val2 = st->info->gyro_max_scale;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_ACCEL:
+ *val = st->info->accel_max_val;
+ *val2 = st->info->accel_max_scale;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_TEMP:
+ *val = st->info->temp_scale;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_CALIBBIAS:
+ ret = adis_read_reg_32(&st->adis,
+ adis16475_calib_regs[chan->scan_index],
+ val);
+ if (ret)
+ return ret;
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+ ret = adis16475_get_filter(st, val);
+ if (ret)
+ return ret;
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ ret = adis16475_get_freq(st, &tmp);
+ if (ret)
+ return ret;
+
+ *val = tmp / 1000;
+ *val2 = (tmp % 1000) * 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int adis16475_write_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ int val, int val2, long info)
+{
+ struct adis16475 *st = iio_priv(indio_dev);
+ u32 tmp;
+
+ switch (info) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ tmp = val * 1000 + val2 / 1000;
+ return adis16475_set_freq(st, tmp);
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+ return adis16475_set_filter(st, val);
+ case IIO_CHAN_INFO_CALIBBIAS:
+ return adis_write_reg_32(&st->adis,
+ adis16475_calib_regs[chan->scan_index],
+ val);
+ default:
+ return -EINVAL;
+ }
+}
+
+#define ADIS16475_MOD_CHAN(_type, _mod, _address, _si, _r_bits, _s_bits) \
+ { \
+ .type = (_type), \
+ .modified = 1, \
+ .channel2 = (_mod), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_CALIBBIAS), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .address = (_address), \
+ .scan_index = (_si), \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = (_r_bits), \
+ .storagebits = (_s_bits), \
+ .endianness = IIO_BE, \
+ }, \
+ }
+
+#define ADIS16475_GYRO_CHANNEL(_mod) \
+ ADIS16475_MOD_CHAN(IIO_ANGL_VEL, IIO_MOD_ ## _mod, \
+ ADIS16475_REG_ ## _mod ## _GYRO_L, \
+ ADIS16475_SCAN_GYRO_ ## _mod, 32, 32)
+
+#define ADIS16475_ACCEL_CHANNEL(_mod) \
+ ADIS16475_MOD_CHAN(IIO_ACCEL, IIO_MOD_ ## _mod, \
+ ADIS16475_REG_ ## _mod ## _ACCEL_L, \
+ ADIS16475_SCAN_ACCEL_ ## _mod, 32, 32)
+
+#define ADIS16475_TEMP_CHANNEL() { \
+ .type = IIO_TEMP, \
+ .indexed = 1, \
+ .channel = 0, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .address = ADIS16475_REG_TEMP_OUT, \
+ .scan_index = ADIS16475_SCAN_TEMP, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_BE, \
+ }, \
+ }
+
+static const struct iio_chan_spec adis16475_channels[] = {
+ ADIS16475_GYRO_CHANNEL(X),
+ ADIS16475_GYRO_CHANNEL(Y),
+ ADIS16475_GYRO_CHANNEL(Z),
+ ADIS16475_ACCEL_CHANNEL(X),
+ ADIS16475_ACCEL_CHANNEL(Y),
+ ADIS16475_ACCEL_CHANNEL(Z),
+ ADIS16475_TEMP_CHANNEL(),
+ IIO_CHAN_SOFT_TIMESTAMP(7)
+};
+
+enum adis16475_variant {
+ ADIS16470,
+ ADIS16475_1,
+ ADIS16475_2,
+ ADIS16475_3,
+ ADIS16477_1,
+ ADIS16477_2,
+ ADIS16477_3,
+ ADIS16465_1,
+ ADIS16465_2,
+ ADIS16465_3,
+ ADIS16467_1,
+ ADIS16467_2,
+ ADIS16467_3,
+ ADIS16500,
+ ADIS16505_1,
+ ADIS16505_2,
+ ADIS16505_3,
+ ADIS16507_1,
+ ADIS16507_2,
+ ADIS16507_3,
+};
+
+enum {
+ ADIS16475_DIAG_STAT_DATA_PATH = 1,
+ ADIS16475_DIAG_STAT_FLASH_MEM,
+ ADIS16475_DIAG_STAT_SPI,
+ ADIS16475_DIAG_STAT_STANDBY,
+ ADIS16475_DIAG_STAT_SENSOR,
+ ADIS16475_DIAG_STAT_MEMORY,
+ ADIS16475_DIAG_STAT_CLK,
+};
+
+static const char * const adis16475_status_error_msgs[] = {
+ [ADIS16475_DIAG_STAT_DATA_PATH] = "Data Path Overrun",
+ [ADIS16475_DIAG_STAT_FLASH_MEM] = "Flash memory update failure",
+ [ADIS16475_DIAG_STAT_SPI] = "SPI communication error",
+ [ADIS16475_DIAG_STAT_STANDBY] = "Standby mode",
+ [ADIS16475_DIAG_STAT_SENSOR] = "Sensor failure",
+ [ADIS16475_DIAG_STAT_MEMORY] = "Memory failure",
+ [ADIS16475_DIAG_STAT_CLK] = "Clock error",
+};
+
+static int adis16475_enable_irq(struct adis *adis, bool enable)
+{
+ /*
+ * There is no way to gate the data-ready signal internally inside the
+ * ADIS16475. We can only control it's polarity...
+ */
+ if (enable)
+ enable_irq(adis->spi->irq);
+ else
+ disable_irq(adis->spi->irq);
+
+ return 0;
+}
+
+#define ADIS16475_DATA(_prod_id, _timeouts) \
+{ \
+ .msc_ctrl_reg = ADIS16475_REG_MSG_CTRL, \
+ .glob_cmd_reg = ADIS16475_REG_GLOB_CMD, \
+ .diag_stat_reg = ADIS16475_REG_DIAG_STAT, \
+ .prod_id_reg = ADIS16475_REG_PROD_ID, \
+ .prod_id = (_prod_id), \
+ .self_test_mask = BIT(2), \
+ .self_test_reg = ADIS16475_REG_GLOB_CMD, \
+ .cs_change_delay = 16, \
+ .read_delay = 5, \
+ .write_delay = 5, \
+ .status_error_msgs = adis16475_status_error_msgs, \
+ .status_error_mask = BIT(ADIS16475_DIAG_STAT_DATA_PATH) | \
+ BIT(ADIS16475_DIAG_STAT_FLASH_MEM) | \
+ BIT(ADIS16475_DIAG_STAT_SPI) | \
+ BIT(ADIS16475_DIAG_STAT_STANDBY) | \
+ BIT(ADIS16475_DIAG_STAT_SENSOR) | \
+ BIT(ADIS16475_DIAG_STAT_MEMORY) | \
+ BIT(ADIS16475_DIAG_STAT_CLK), \
+ .enable_irq = adis16475_enable_irq, \
+ .timeouts = (_timeouts), \
+}
+
+static const struct adis16475_sync adis16475_sync_mode[] = {
+ { ADIS16475_SYNC_OUTPUT },
+ { ADIS16475_SYNC_DIRECT, 1900, 2100 },
+ { ADIS16475_SYNC_SCALED, 1, 128 },
+ { ADIS16475_SYNC_PULSE, 1000, 2100 },
+};
+
+static const struct adis_timeout adis16475_timeouts = {
+ .reset_ms = 200,
+ .sw_reset_ms = 200,
+ .self_test_ms = 20,
+};
+
+static const struct adis_timeout adis1650x_timeouts = {
+ .reset_ms = 260,
+ .sw_reset_ms = 260,
+ .self_test_ms = 30,
+};
+
+static const struct adis16475_chip_info adis16475_chip_info[] = {
+ [ADIS16470] = {
+ .name = "adis16470",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16470, &adis16475_timeouts),
+ },
+ [ADIS16475_1] = {
+ .name = "adis16475-1",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts),
+ },
+ [ADIS16475_2] = {
+ .name = "adis16475-2",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts),
+ },
+ [ADIS16475_3] = {
+ .name = "adis16475-3",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts),
+ },
+ [ADIS16477_1] = {
+ .name = "adis16477-1",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
+ },
+ [ADIS16477_2] = {
+ .name = "adis16477-2",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
+ },
+ [ADIS16477_3] = {
+ .name = "adis16477-3",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
+ },
+ [ADIS16465_1] = {
+ .name = "adis16465-1",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts),
+ },
+ [ADIS16465_2] = {
+ .name = "adis16465-2",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts),
+ },
+ [ADIS16465_3] = {
+ .name = "adis16465-3",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts),
+ },
+ [ADIS16467_1] = {
+ .name = "adis16467-1",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts),
+ },
+ [ADIS16467_2] = {
+ .name = "adis16467-2",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts),
+ },
+ [ADIS16467_3] = {
+ .name = "adis16467-3",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts),
+ },
+ [ADIS16500] = {
+ .name = "adis16500",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 392,
+ .accel_max_scale = 32000 << 16,
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ /* pulse sync not supported */
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
+ .has_burst32 = true,
+ .adis_data = ADIS16475_DATA(16500, &adis1650x_timeouts),
+ },
+ [ADIS16505_1] = {
+ .name = "adis16505-1",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
+ .accel_max_val = 78,
+ .accel_max_scale = 32000 << 16,
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ /* pulse sync not supported */
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
+ .has_burst32 = true,
+ .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
+ },
+ [ADIS16505_2] = {
+ .name = "adis16505-2",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+ .accel_max_val = 78,
+ .accel_max_scale = 32000 << 16,
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ /* pulse sync not supported */
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
+ .has_burst32 = true,
+ .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
+ },
+ [ADIS16505_3] = {
+ .name = "adis16505-3",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 78,
+ .accel_max_scale = 32000 << 16,
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ /* pulse sync not supported */
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
+ .has_burst32 = true,
+ .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
+ },
+ [ADIS16507_1] = {
+ .name = "adis16507-1",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
+ .accel_max_val = 392,
+ .accel_max_scale = 32000 << 16,
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ /* pulse sync not supported */
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
+ .has_burst32 = true,
+ .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts),
+ },
+ [ADIS16507_2] = {
+ .name = "adis16507-2",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+ .accel_max_val = 392,
+ .accel_max_scale = 32000 << 16,
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ /* pulse sync not supported */
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
+ .has_burst32 = true,
+ .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts),
+ },
+ [ADIS16507_3] = {
+ .name = "adis16507-3",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 392,
+ .accel_max_scale = 32000 << 16,
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ /* pulse sync not supported */
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
+ .has_burst32 = true,
+ .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts),
+ },
+};
+
+static const struct iio_info adis16475_info = {
+ .read_raw = &adis16475_read_raw,
+ .write_raw = &adis16475_write_raw,
+ .update_scan_mode = adis_update_scan_mode,
+ .debugfs_reg_access = adis_debugfs_reg_access,
+};
+
+static struct adis_burst adis16475_burst = {
+ .en = true,
+ .reg_cmd = ADIS16475_REG_GLOB_CMD,
+ /*
+ * adis_update_scan_mode_burst() sets the burst length in respect with
+ * the number of channels and allocates 16 bits for each. However,
+ * adis1647x devices also need space for DIAG_STAT, DATA_CNTR or
+ * TIME_STAMP (depending on the clock mode but for us these bytes are
+ * don't care...) and CRC.
+ */
+ .extra_len = 3 * sizeof(u16),
+ .burst_max_len = ADIS16475_BURST32_MAX_DATA,
+};
+
+static bool adis16475_validate_crc(const u8 *buffer, u16 crc,
+ const bool burst32)
+{
+ int i;
+ /* extra 6 elements for low gyro and accel */
+ const u16 sz = burst32 ? ADIS16475_BURST32_MAX_DATA :
+ ADIS16475_BURST_MAX_DATA;
+
+ for (i = 0; i < sz - 2; i++)
+ crc -= buffer[i];
+
+ return crc == 0;
+}
+
+static void adis16475_burst32_check(struct adis16475 *st)
+{
+ int ret;
+ struct adis *adis = &st->adis;
+
+ if (!st->info->has_burst32)
+ return;
+
+ if (st->lsb_flag && !st->burst32) {
+ const u16 en = ADIS16500_BURST32(1);
+
+ ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
+ ADIS16500_BURST32_MASK, en);
+ if (ret)
+ return;
+
+ st->burst32 = true;
+
+ /*
+ * In 32-bit mode we need extra 2 bytes for all gyro
+ * and accel channels.
+ */
+ adis->burst_extra_len = 6 * sizeof(u16);
+ adis->xfer[1].len += 6 * sizeof(u16);
+ dev_dbg(&adis->spi->dev, "Enable burst32 mode, xfer:%d",
+ adis->xfer[1].len);
+
+ } else if (!st->lsb_flag && st->burst32) {
+ const u16 en = ADIS16500_BURST32(0);
+
+ ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
+ ADIS16500_BURST32_MASK, en);
+ if (ret)
+ return;
+
+ st->burst32 = false;
+
+ /* Remove the extra bits */
+ adis->burst_extra_len = 0;
+ adis->xfer[1].len -= 6 * sizeof(u16);
+ dev_dbg(&adis->spi->dev, "Disable burst32 mode, xfer:%d\n",
+ adis->xfer[1].len);
+ }
+}
+
+static irqreturn_t adis16475_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct adis16475 *st = iio_priv(indio_dev);
+ struct adis *adis = &st->adis;
+ int ret, bit, i = 0;
+ __be16 *buffer;
+ u16 crc;
+ bool valid;
+ /* offset until the first element after gyro and accel */
+ const u8 offset = st->burst32 ? 13 : 7;
+ const u32 cached_spi_speed_hz = adis->spi->max_speed_hz;
+
+ adis->spi->max_speed_hz = ADIS16475_BURST_MAX_SPEED;
+
+ ret = spi_sync(adis->spi, &adis->msg);
+ if (ret)
+ return ret;
+
+ adis->spi->max_speed_hz = cached_spi_speed_hz;
+ buffer = adis->buffer;
+
+ crc = be16_to_cpu(buffer[offset + 2]);
+ valid = adis16475_validate_crc(adis->buffer, crc, st->burst32);
+ if (!valid) {
+ dev_err(&adis->spi->dev, "Invalid crc\n");
+ goto check_burst32;
+ }
+
+ for_each_set_bit(bit, indio_dev->active_scan_mask,
+ indio_dev->masklength) {
+ /*
+ * When burst mode is used, system flags is the first data
+ * channel in the sequence, but the scan index is 7.
+ */
+ switch (bit) {
+ case ADIS16475_SCAN_TEMP:
+ st->data[i++] = buffer[offset];
+ break;
+ case ADIS16475_SCAN_GYRO_X ... ADIS16475_SCAN_ACCEL_Z:
+ /*
+ * The first 2 bytes on the received data are the
+ * DIAG_STAT reg, hence the +1 offset here...
+ */
+ if (st->burst32) {
+ /* upper 16 */
+ st->data[i++] = buffer[bit * 2 + 2];
+ /* lower 16 */
+ st->data[i++] = buffer[bit * 2 + 1];
+ } else {
+ st->data[i++] = buffer[bit + 1];
+ /*
+ * Don't bother in doing the manual read if the
+ * device supports burst32. burst32 will be
+ * enabled in the next call to
+ * adis16475_burst32_check()...
+ */
+ if (st->lsb_flag && !st->info->has_burst32) {
+ u16 val = 0;
+ const u32 reg = ADIS16475_REG_X_GYRO_L +
+ bit * 4;
+
+ adis_read_reg_16(adis, reg, &val);
+ st->data[i++] = cpu_to_be16(val);
+ } else {
+ /* lower not used */
+ st->data[i++] = 0;
+ }
+ }
+ break;
+ }
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, st->data, pf->timestamp);
+check_burst32:
+ /*
+ * We only check the burst mode at the end of the current capture since
+ * it takes a full data ready cycle for the device to update the burst
+ * array.
+ */
+ adis16475_burst32_check(st);
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static void adis16475_disable_clk(void *data)
+{
+ clk_disable_unprepare((struct clk *)data);
+}
+
+static int adis16475_config_sync_mode(struct adis16475 *st)
+{
+ int ret;
+ struct device *dev = &st->adis.spi->dev;
+ const struct adis16475_sync *sync;
+ u32 sync_mode;
+
+ /* default to internal clk */
+ st->clk_freq = st->info->int_clk * 1000;
+
+ ret = device_property_read_u32(dev, "adi,sync-mode", &sync_mode);
+ if (ret)
+ return 0;
+
+ if (sync_mode >= st->info->num_sync) {
+ dev_err(dev, "Invalid sync mode: %u for %s\n", sync_mode,
+ st->info->name);
+ return -EINVAL;
+ }
+
+ sync = &st->info->sync[sync_mode];
+
+ /* All the other modes require external input signal */
+ if (sync->sync_mode != ADIS16475_SYNC_OUTPUT) {
+ struct clk *clk = devm_clk_get(dev, NULL);
+
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ ret = clk_prepare_enable(clk);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, adis16475_disable_clk, clk);
+ if (ret)
+ return ret;
+
+ st->clk_freq = clk_get_rate(clk);
+ if (st->clk_freq < sync->min_rate ||
+ st->clk_freq > sync->max_rate) {
+ dev_err(dev,
+ "Clk rate:%u not in a valid range:[%u %u]\n",
+ st->clk_freq, sync->min_rate, sync->max_rate);
+ return -EINVAL;
+ }
+
+ if (sync->sync_mode == ADIS16475_SYNC_SCALED) {
+ u16 up_scale;
+ u32 scaled_out_freq = 0;
+ /*
+ * If we are in scaled mode, we must have an up_scale.
+ * In scaled mode the allowable input clock range is
+ * 1 Hz to 128 Hz, and the allowable output range is
+ * 1900 to 2100 Hz. Hence, a scale must be given to
+ * get the allowable output.
+ */
+ ret = device_property_read_u32(dev,
+ "adi,scaled-output-hz",
+ &scaled_out_freq);
+ if (ret) {
+ dev_err(dev, "adi,scaled-output-hz must be given when in scaled sync mode");
+ return -EINVAL;
+ } else if (scaled_out_freq < 1900 ||
+ scaled_out_freq > 2100) {
+ dev_err(dev, "Invalid value: %u for adi,scaled-output-hz",
+ scaled_out_freq);
+ return -EINVAL;
+ }
+
+ up_scale = DIV_ROUND_CLOSEST(scaled_out_freq,
+ st->clk_freq);
+
+ ret = __adis_write_reg_16(&st->adis,
+ ADIS16475_REG_UP_SCALE,
+ up_scale);
+ if (ret)
+ return ret;
+
+ st->clk_freq = scaled_out_freq;
+ }
+
+ st->clk_freq *= 1000;
+ }
+ /*
+ * Keep in mind that the mask for the clk modes in adis1650*
+ * chips is different (1100 instead of 11100). However, we
+ * are not configuring BIT(4) in these chips and the default
+ * value is 0, so we are fine in doing the below operations.
+ * I'm keeping this for simplicity and avoiding extra variables
+ * in chip_info.
+ */
+ ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
+ ADIS16475_SYNC_MODE_MASK, sync->sync_mode);
+ if (ret)
+ return ret;
+
+ usleep_range(250, 260);
+
+ return 0;
+}
+
+static int adis16475_config_irq_pin(struct adis16475 *st)
+{
+ int ret;
+ struct irq_data *desc;
+ u32 irq_type;
+ u16 val = 0;
+ u8 polarity;
+ struct spi_device *spi = st->adis.spi;
+
+ desc = irq_get_irq_data(spi->irq);
+ if (!desc) {
+ dev_err(&spi->dev, "Could not find IRQ %d\n", spi->irq);
+ return -EINVAL;
+ }
+ /*
+ * It is possible to configure the data ready polarity. Furthermore, we
+ * need to update the adis struct if we want data ready as active low.
+ */
+ irq_type = irqd_get_trigger_type(desc);
+ if (irq_type == IRQ_TYPE_EDGE_RISING) {
+ polarity = 1;
+ st->adis.irq_flag = IRQF_TRIGGER_RISING;
+ } else if (irq_type == IRQ_TYPE_EDGE_FALLING) {
+ polarity = 0;
+ st->adis.irq_flag = IRQF_TRIGGER_FALLING;
+ } else {
+ dev_err(&spi->dev, "Invalid interrupt type 0x%x specified\n",
+ irq_type);
+ return -EINVAL;
+ }
+
+ val = ADIS16475_MSG_CTRL_DR_POL(polarity);
+ ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
+ ADIS16475_MSG_CTRL_DR_POL_MASK, val);
+ if (ret)
+ return ret;
+ /*
+ * There is a delay writing to any bits written to the MSC_CTRL
+ * register. It should not be bigger than 200us, so 250 should be more
+ * than enough!
+ */
+ usleep_range(250, 260);
+
+ return 0;
+}
+
+static const struct of_device_id adis16475_of_match[] = {
+ { .compatible = "adi,adis16470",
+ .data = &adis16475_chip_info[ADIS16470] },
+ { .compatible = "adi,adis16475-1",
+ .data = &adis16475_chip_info[ADIS16475_1] },
+ { .compatible = "adi,adis16475-2",
+ .data = &adis16475_chip_info[ADIS16475_2] },
+ { .compatible = "adi,adis16475-3",
+ .data = &adis16475_chip_info[ADIS16475_3] },
+ { .compatible = "adi,adis16477-1",
+ .data = &adis16475_chip_info[ADIS16477_1] },
+ { .compatible = "adi,adis16477-2",
+ .data = &adis16475_chip_info[ADIS16477_2] },
+ { .compatible = "adi,adis16477-3",
+ .data = &adis16475_chip_info[ADIS16477_3] },
+ { .compatible = "adi,adis16465-1",
+ .data = &adis16475_chip_info[ADIS16465_1] },
+ { .compatible = "adi,adis16465-2",
+ .data = &adis16475_chip_info[ADIS16465_2] },
+ { .compatible = "adi,adis16465-3",
+ .data = &adis16475_chip_info[ADIS16465_3] },
+ { .compatible = "adi,adis16467-1",
+ .data = &adis16475_chip_info[ADIS16467_1] },
+ { .compatible = "adi,adis16467-2",
+ .data = &adis16475_chip_info[ADIS16467_2] },
+ { .compatible = "adi,adis16467-3",
+ .data = &adis16475_chip_info[ADIS16467_3] },
+ { .compatible = "adi,adis16500",
+ .data = &adis16475_chip_info[ADIS16500] },
+ { .compatible = "adi,adis16505-1",
+ .data = &adis16475_chip_info[ADIS16505_1] },
+ { .compatible = "adi,adis16505-2",
+ .data = &adis16475_chip_info[ADIS16505_2] },
+ { .compatible = "adi,adis16505-3",
+ .data = &adis16475_chip_info[ADIS16505_3] },
+ { .compatible = "adi,adis16507-1",
+ .data = &adis16475_chip_info[ADIS16507_1] },
+ { .compatible = "adi,adis16507-2",
+ .data = &adis16475_chip_info[ADIS16507_2] },
+ { .compatible = "adi,adis16507-3",
+ .data = &adis16475_chip_info[ADIS16507_3] },
+ { },
+};
+MODULE_DEVICE_TABLE(of, adis16475_of_match);
+
+static int adis16475_probe(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev;
+ struct adis16475 *st;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+ spi_set_drvdata(spi, indio_dev);
+ st->adis.burst = &adis16475_burst;
+
+ st->info = device_get_match_data(&spi->dev);
+ if (!st->info)
+ return -EINVAL;
+
+ ret = adis_init(&st->adis, indio_dev, spi, &st->info->adis_data);
+ if (ret)
+ return ret;
+
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = st->info->name;
+ indio_dev->channels = st->info->channels;
+ indio_dev->num_channels = st->info->num_channels;
+ indio_dev->info = &adis16475_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ ret = __adis_initial_startup(&st->adis);
+ if (ret)
+ return ret;
+
+ ret = adis16475_config_irq_pin(st);
+ if (ret)
+ return ret;
+
+ ret = adis16475_config_sync_mode(st);
+ if (ret)
+ return ret;
+
+ ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev,
+ adis16475_trigger_handler);
+ if (ret)
+ return ret;
+
+ adis16475_enable_irq(&st->adis, false);
+
+ ret = devm_iio_device_register(&spi->dev, indio_dev);
+ if (ret)
+ return ret;
+
+ adis16475_debugfs_init(indio_dev);
+
+ return 0;
+}
+
+static struct spi_driver adis16475_driver = {
+ .driver = {
+ .name = "adis16475",
+ .of_match_table = adis16475_of_match,
+ },
+ .probe = adis16475_probe,
+};
+module_spi_driver(adis16475_driver);
+
+MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");
+MODULE_DESCRIPTION("Analog Devices ADIS16475 IMU driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c
index cfae0e4476e7..6a471eee110e 100644
--- a/drivers/iio/imu/adis16480.c
+++ b/drivers/iio/imu/adis16480.c
@@ -284,22 +284,18 @@ DEFINE_DEBUGFS_ATTRIBUTE(adis16480_flash_count_fops,
static int adis16480_debugfs_init(struct iio_dev *indio_dev)
{
struct adis16480 *adis16480 = iio_priv(indio_dev);
+ struct dentry *d = iio_get_debugfs_dentry(indio_dev);
debugfs_create_file_unsafe("firmware_revision", 0400,
- indio_dev->debugfs_dentry, adis16480,
- &adis16480_firmware_revision_fops);
+ d, adis16480, &adis16480_firmware_revision_fops);
debugfs_create_file_unsafe("firmware_date", 0400,
- indio_dev->debugfs_dentry, adis16480,
- &adis16480_firmware_date_fops);
+ d, adis16480, &adis16480_firmware_date_fops);
debugfs_create_file_unsafe("serial_number", 0400,
- indio_dev->debugfs_dentry, adis16480,
- &adis16480_serial_number_fops);
+ d, adis16480, &adis16480_serial_number_fops);
debugfs_create_file_unsafe("product_id", 0400,
- indio_dev->debugfs_dentry, adis16480,
- &adis16480_product_id_fops);
+ d, adis16480, &adis16480_product_id_fops);
debugfs_create_file_unsafe("flash_count", 0400,
- indio_dev->debugfs_dentry, adis16480,
- &adis16480_flash_count_fops);
+ d, adis16480, &adis16480_flash_count_fops);
return 0;
}
diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c
index 04e5e2a0fd6b..5b4225ee09b9 100644
--- a/drivers/iio/imu/adis_buffer.c
+++ b/drivers/iio/imu/adis_buffer.c
@@ -23,25 +23,30 @@ static int adis_update_scan_mode_burst(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
struct adis *adis = iio_device_get_drvdata(indio_dev);
- unsigned int burst_length;
+ unsigned int burst_length, burst_max_length;
u8 *tx;
/* All but the timestamp channel */
burst_length = (indio_dev->num_channels - 1) * sizeof(u16);
- burst_length += adis->burst->extra_len;
+ burst_length += adis->burst->extra_len + adis->burst_extra_len;
+
+ if (adis->burst->burst_max_len)
+ burst_max_length = adis->burst->burst_max_len;
+ else
+ burst_max_length = burst_length;
adis->xfer = kcalloc(2, sizeof(*adis->xfer), GFP_KERNEL);
if (!adis->xfer)
return -ENOMEM;
- adis->buffer = kzalloc(burst_length + sizeof(u16), GFP_KERNEL);
+ adis->buffer = kzalloc(burst_max_length + sizeof(u16), GFP_KERNEL);
if (!adis->buffer) {
kfree(adis->xfer);
adis->xfer = NULL;
return -ENOMEM;
}
- tx = adis->buffer + burst_length;
+ tx = adis->buffer + burst_max_length;
tx[0] = ADIS_READ_REG(adis->burst->reg_cmd);
tx[1] = 0;
@@ -156,6 +161,14 @@ static irqreturn_t adis_trigger_handler(int irq, void *p)
return IRQ_HANDLED;
}
+static void adis_buffer_cleanup(void *arg)
+{
+ struct adis *adis = arg;
+
+ kfree(adis->buffer);
+ kfree(adis->xfer);
+}
+
/**
* adis_setup_buffer_and_trigger() - Sets up buffer and trigger for the adis device
* @adis: The adis device.
@@ -199,6 +212,43 @@ error_buffer_cleanup:
EXPORT_SYMBOL_GPL(adis_setup_buffer_and_trigger);
/**
+ * devm_adis_setup_buffer_and_trigger() - Sets up buffer and trigger for
+ * the managed adis device
+ * @adis: The adis device
+ * @indio_dev: The IIO device
+ * @trigger_handler: Optional trigger handler, may be NULL.
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * This function perfoms exactly the same as adis_setup_buffer_and_trigger()
+ */
+int
+devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev,
+ irq_handler_t trigger_handler)
+{
+ int ret;
+
+ if (!trigger_handler)
+ trigger_handler = adis_trigger_handler;
+
+ ret = devm_iio_triggered_buffer_setup(&adis->spi->dev, indio_dev,
+ &iio_pollfunc_store_time,
+ trigger_handler, NULL);
+ if (ret)
+ return ret;
+
+ if (adis->spi->irq) {
+ ret = devm_adis_probe_trigger(adis, indio_dev);
+ if (ret)
+ return ret;
+ }
+
+ return devm_add_action_or_reset(&adis->spi->dev, adis_buffer_cleanup,
+ adis);
+}
+EXPORT_SYMBOL_GPL(devm_adis_setup_buffer_and_trigger);
+
+/**
* adis_cleanup_buffer_and_trigger() - Free buffer and trigger resources
* @adis: The adis device.
* @indio_dev: The IIO device.
diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c
index 8b9cd02c0f9f..8afe71947c00 100644
--- a/drivers/iio/imu/adis_trigger.c
+++ b/drivers/iio/imu/adis_trigger.c
@@ -27,6 +27,34 @@ static const struct iio_trigger_ops adis_trigger_ops = {
.set_trigger_state = &adis_data_rdy_trigger_set_state,
};
+static void adis_trigger_setup(struct adis *adis)
+{
+ adis->trig->dev.parent = &adis->spi->dev;
+ adis->trig->ops = &adis_trigger_ops;
+ iio_trigger_set_drvdata(adis->trig, adis);
+}
+
+static int adis_validate_irq_flag(struct adis *adis)
+{
+ /*
+ * Typically this devices have data ready either on the rising edge or
+ * on the falling edge of the data ready pin. This checks enforces that
+ * one of those is set in the drivers... It defaults to
+ * IRQF_TRIGGER_RISING for backward compatibility wiht devices that
+ * don't support changing the pin polarity.
+ */
+ if (!adis->irq_flag) {
+ adis->irq_flag = IRQF_TRIGGER_RISING;
+ return 0;
+ } else if (adis->irq_flag != IRQF_TRIGGER_RISING &&
+ adis->irq_flag != IRQF_TRIGGER_FALLING) {
+ dev_err(&adis->spi->dev, "Invalid IRQ mask: %08lx\n",
+ adis->irq_flag);
+ return -EINVAL;
+ }
+
+ return 0;
+}
/**
* adis_probe_trigger() - Sets up trigger for a adis device
* @adis: The adis device
@@ -45,13 +73,15 @@ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
if (adis->trig == NULL)
return -ENOMEM;
- adis->trig->dev.parent = &adis->spi->dev;
- adis->trig->ops = &adis_trigger_ops;
- iio_trigger_set_drvdata(adis->trig, adis);
+ adis_trigger_setup(adis);
+
+ ret = adis_validate_irq_flag(adis);
+ if (ret)
+ return ret;
ret = request_irq(adis->spi->irq,
&iio_trigger_generic_data_rdy_poll,
- IRQF_TRIGGER_RISING,
+ adis->irq_flag,
indio_dev->name,
adis->trig);
if (ret)
@@ -74,6 +104,40 @@ error_free_trig:
EXPORT_SYMBOL_GPL(adis_probe_trigger);
/**
+ * devm_adis_probe_trigger() - Sets up trigger for a managed adis device
+ * @adis: The adis device
+ * @indio_dev: The IIO device
+ *
+ * Returns 0 on success or a negative error code
+ */
+int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
+{
+ int ret;
+
+ adis->trig = devm_iio_trigger_alloc(&adis->spi->dev, "%s-dev%d",
+ indio_dev->name, indio_dev->id);
+ if (!adis->trig)
+ return -ENOMEM;
+
+ adis_trigger_setup(adis);
+
+ ret = adis_validate_irq_flag(adis);
+ if (ret)
+ return ret;
+
+ ret = devm_request_irq(&adis->spi->dev, adis->spi->irq,
+ &iio_trigger_generic_data_rdy_poll,
+ adis->irq_flag,
+ indio_dev->name,
+ adis->trig);
+ if (ret)
+ return ret;
+
+ return devm_iio_trigger_register(&adis->spi->dev, adis->trig);
+}
+EXPORT_SYMBOL_GPL(devm_adis_probe_trigger);
+
+/**
* adis_remove_trigger() - Remove trigger for a adis devices
* @adis: The adis device
*
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
index 4426524b59f2..0b776cb91928 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
@@ -27,7 +27,8 @@
* - FIFO size: 4KB
*
* - LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX:
- * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416
+ * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416,
+ * 833
* - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
* - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
* - FIFO size: 3KB
@@ -791,7 +792,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.odr_avl[3] = { 104000, 0x04 },
.odr_avl[4] = { 208000, 0x05 },
.odr_avl[5] = { 416000, 0x06 },
- .odr_len = 6,
+ .odr_avl[6] = { 833000, 0x07 },
+ .odr_len = 7,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
@@ -804,7 +806,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.odr_avl[3] = { 104000, 0x04 },
.odr_avl[4] = { 208000, 0x05 },
.odr_avl[5] = { 416000, 0x06 },
- .odr_len = 6,
+ .odr_avl[6] = { 833000, 0x07 },
+ .odr_len = 7,
},
},
.fs_table = {
@@ -994,7 +997,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.odr_avl[3] = { 104000, 0x04 },
.odr_avl[4] = { 208000, 0x05 },
.odr_avl[5] = { 416000, 0x06 },
- .odr_len = 6,
+ .odr_avl[6] = { 833000, 0x07 },
+ .odr_len = 7,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
@@ -1007,7 +1011,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.odr_avl[3] = { 104000, 0x04 },
.odr_avl[4] = { 208000, 0x05 },
.odr_avl[5] = { 416000, 0x06 },
- .odr_len = 6,
+ .odr_avl[6] = { 833000, 0x07 },
+ .odr_len = 7,
},
},
.fs_table = {
@@ -1171,7 +1176,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.odr_avl[3] = { 104000, 0x04 },
.odr_avl[4] = { 208000, 0x05 },
.odr_avl[5] = { 416000, 0x06 },
- .odr_len = 6,
+ .odr_avl[6] = { 833000, 0x07 },
+ .odr_len = 7,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
@@ -1184,7 +1190,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.odr_avl[3] = { 104000, 0x04 },
.odr_avl[4] = { 208000, 0x05 },
.odr_avl[5] = { 416000, 0x06 },
- .odr_len = 6,
+ .odr_avl[6] = { 833000, 0x07 },
+ .odr_len = 7,
},
},
.fs_table = {