diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-04-04 22:25:29 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-04-04 22:25:29 +0200 |
commit | 932f98922f6fca9f8c45274346b49058dd50d51a (patch) | |
tree | 75635c62cfbaa0397d7169a69e132c0a2a235ade /drivers/iio/imu | |
parent | 44b8ef17c435ecc1a2a505e39e8556f26c0da4ef (diff) | |
parent | df1d80aee963480c5c2938c64ec0ac3e4a0df2e0 (diff) | |
download | lwn-932f98922f6fca9f8c45274346b49058dd50d51a.tar.gz lwn-932f98922f6fca9f8c45274346b49058dd50d51a.zip |
Merge tag 'iio-for-5.2a-2' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
Jonathan writes:
First set of new device support, features and fixes for IIO in the 5.2 cycle
Staging graduations
* ad7780
- Move this ADC driver out of staging. Included adding some new features
along the way (see below). Also added DT bindings.
New device support
* adis16480
- Support the ADIS16495 and ADIS16497 IMU devices making
heavy use of refactoring of various aspects of the driver in precursor
patches.
* lsm6dsx
- Support for the ASM330LHH 6-axis (accelerometer + gyro) sensor.
- Support for the LSM6DS0X
* matbotix mb1232
- New driver for this ultrasound ranging device family. Including bindings.
- Supports mb1202, mb1212, mb1222, mb1232, mb1242, mb7040 and mb7137.
* max31856
- New driver for this thermocouple temperature sensor.
* meson saradc
- Support the Meson-G12A (ID addition only).
* stmpe-adc
- New driver supporting generic ADC alongside touchscreen support which
previously existed. Includes DT bindings.
* vcnl4000
- Support for the vcln4040 proximity and light sensor, including adding
DT bindings for this and parts previously supported.
Features
* core
- Allow reading of mount matrices from ACPI in addition to DT.
- Common binding for theromcouple types.
* ad5933
- Add ABI docs as there are a few 'unsual' elements about this
device - perhaps because it's our only impedance analyser.
* ad7780
- Add gain and filter gpio support + readback of current gain and filter.
* adis16480
- Allow selection fo the dataready pin to be used.
- Device tree ID table and binding documentation.
- Support external clock modes, including new bindings.
* bma180
- Mount matrix support.
* bmc150
- Mount matrix support.
* bmg160
- Mount matrix support.
- DT id table and bindings doc.
* bmp280
- Put calibration data into the entropy pool.
* hmc5843
- Mount matrix support.
* itg3200
- Mount matrix support.
* kxcjk1013
- Device tree id table, and binding docs.
* lpc32xx
- Add scale when regulator specified including DT docs for regulator.
* pms7003
- Add device IDs for all supported parts to driver and binding.
* stm32-dfsdm
- Enable hw consumer support, scan mode control and a complex set of
triggered buffer modes.
- Power management.
* stm32-lptimer-counter
- power management.
- Document the pinctrl sleep state binding.
* ti-ads7950
- GPIO pin support.
Cleanups, minor fixes
* core
- Use bitmap_zalloc to make it explicit that is what we are doing.
- Tidy up all the Kconfig files (which had slowly gotten messy)
- Fix a forwards definition missing issue in iio/driver.h
* ad sigma delta core
- Improve handling of SPI bus locking vs CS assertion. This has been
wrong a long time so not rushing this in.
* ad5064
- Mlock to local lock.
* ad5933 (staging cleanup)
- Multiline comment fixes.
- Include ordering.
- SPDX.
- Tidy up Kconfig help which was a bit missleading.
- Change some non standard attributes to ABI defined ones.
* ad7124
- White space fix.
* ad7192
- White space.
- Use DT clock binding.
- Improve error reporting.
- Platform data to DT conversion.
- Use read_avail callback, mostly to avoid the endless series of
patches from new contributors trying to falsely put spaces around
the negative sign.
* ad7280a
- Add brackets to macros to avoid potential precedence isseus.
- Add temp vars for event codes to reduce indent and improved readability.
- Clean out som CamelCase notation.
- White space.
* ad7606
- Fix broken file naming in MAINTAINERS.
* ad7780
- Missing switch defaults to supress warnings and harden the code slightly.
- Set pattern masks more directly.
- Add ID values and masks for all supported chips.
- SPDX + add Renato as a copyright holder as he has done a lot of work on
this driver.
- Add brackets to macros to avoid potential precedence issues.
* ad7923
- White space fixes.
- Use BIT macro to improve readability.
- Add brackets to macros to avoid potential precedence issues.
- Tidy up a null comparisom.
* ad9523
- Fix a typo in naming of variables.
* adis16400
- Combine trigger file into main code as no advantage in separate files.
Rename core file to just adis16400.
- Squash the header into the c file now there is only one file.
- Generalize burst mode to support new variants.
* ak8975
- Local variable to improve readability around mount matrix support.
* as3935
- Avoid potential race by ensuring remove does exact opposite of
probe rather than a slightly different order.
* cross_ec
- Drop some unnecessary includes.
- Fix some warning and the slightly 'unusual' code.
- Add some docs for non obvious function.
- SPDX
* hmc5843
- Potential unhandled error case.
* iio trigger core
- Print an error if there is no available irq due to max consumers per
trigger being set to low.
* iio loop trigger
- Drop an unlikely on IS_ERR as IS_ERR already has the annotation.
* ingenic-adc
- Drop a redundant dev_err call as devm_ioremap_resource reports the same
internally.
* lmp91000
- Drop some unncessary parentheses and white space tidy up.
- Invert and if statement to improve readability.
- Fix a wrong error message.
* lpc32xx
- Header sorting + drop some unused ones.
* mma8542
- Mark a switch fallthrough.
* mpu6050
- Add a local variable to improve code readability around mount matrix
support.
* mxs-lradc-adc
- Handle devm_iio_trigger_alloc failure.
* sps30
- Fix up a kernel version in the ABI docs.
* srf04
- DT binding doc converted to yaml.
* ssp_sensors
- Supress a clang build warning due to lack of visibility of conditional
within a iio_push_to_buffers_with_timestamp. (reasonable false warning!)
* st_accel
- Drop pointless less than 0 comparisom of unsigned int.
* stm32-dfsdm
- Improve accuracy of spi_master_frequency calculation.
- Improve calculation fo sampling frequency.
- Rework various internals to simplify adding triggered buffer support.
- Claim direct mode to avoid racing around read_raw and being in buffered
mode.
* stmpe
- Fix a clang false positive warning.
* ti-ads7950
- Use local lock rather than using the core mlock when not locking around
the device mode.
* vcnl4000
- Use word writes instead of byte writes. It seems byte writes are fine
for some parts (undocument) but not others that the driver will shortly
support.
Other
* mailmap
- Add email address change for Sean Nyekjaer. Update in relevant drivers
* tag 'iio-for-5.2a-2' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (129 commits)
iio: ad_sigma_delta: Properly handle SPI bus locking vs CS assertion
iio: adc: stm32-dfsdm: add PM support
iio: adc: stm32-dfsdm: improve sampling frequency accuracy
staging: iio: adc: ad7280a: Tab alignment
MAINTAINERS: Fix the link to ad7606 dt-bindings
iio:temperature: Add MAX31856 thermocouple support
iio:temperature:max31856:Add device tree bind info
dt-bindings: iio/temperature: Add thermocouple types (and doc)
devantech-srf04.yaml: transform DT binding to YAML
iio: frequency: ad9523: Fix typo in ad9523_platform_data
iio: Make possible to include driver.h first
dt-bindings: iio: add Bosch BMG160 gyroscope sensor
iio: gyro: bmg160: add device tree compatibility table
staging: iio: adc: ad7192: Use read_avail for available attributes
dt-bindings: iio: light: add vcnl4040 devicetree bindings
iio: light: vcnl4000 add support for the VCNL4040 proximity and light sensor
dt-bindings: iio: light: add vcnl4000 devicetree bindings
iio: light: vcnl4000 add devicetree hooks
iio: light: vcnl4000 use word writes instead of byte writes
iio: adc: stm32-dfsdm: claim direct mode for raw read and settings
...
Diffstat (limited to 'drivers/iio/imu')
-rw-r--r-- | drivers/iio/imu/Makefile | 2 | ||||
-rw-r--r-- | drivers/iio/imu/adis16400.c (renamed from drivers/iio/imu/adis16400_core.c) | 232 | ||||
-rw-r--r-- | drivers/iio/imu/adis16400.h | 215 | ||||
-rw-r--r-- | drivers/iio/imu/adis16400_buffer.c | 101 | ||||
-rw-r--r-- | drivers/iio/imu/adis16480.c | 435 | ||||
-rw-r--r-- | drivers/iio/imu/adis_buffer.c | 40 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 10 | ||||
-rw-r--r-- | drivers/iio/imu/st_lsm6dsx/Kconfig | 2 | ||||
-rw-r--r-- | drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 4 | ||||
-rw-r--r-- | drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 8 | ||||
-rw-r--r-- | drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 42 | ||||
-rw-r--r-- | drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c | 10 | ||||
-rw-r--r-- | drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c | 10 |
13 files changed, 763 insertions, 348 deletions
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index 68629c68b19b..9e452fce1aaf 100644 --- a/drivers/iio/imu/Makefile +++ b/drivers/iio/imu/Makefile @@ -4,8 +4,6 @@ # # When adding new entries keep the list in alphabetical order -adis16400-y := adis16400_core.o -adis16400-$(CONFIG_IIO_BUFFER) += adis16400_buffer.o obj-$(CONFIG_ADIS16400) += adis16400.o obj-$(CONFIG_ADIS16480) += adis16480.o diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400.c index 46a569005a13..beb6919e7180 100644 --- a/drivers/iio/imu/adis16400_core.c +++ b/drivers/iio/imu/adis16400.c @@ -31,8 +31,183 @@ #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> #include <linux/iio/buffer.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/imu/adis.h> + +#define ADIS16400_STARTUP_DELAY 290 /* ms */ +#define ADIS16400_MTEST_DELAY 90 /* ms */ + +#define ADIS16400_FLASH_CNT 0x00 /* Flash memory write count */ +#define ADIS16400_SUPPLY_OUT 0x02 /* Power supply measurement */ +#define ADIS16400_XGYRO_OUT 0x04 /* X-axis gyroscope output */ +#define ADIS16400_YGYRO_OUT 0x06 /* Y-axis gyroscope output */ +#define ADIS16400_ZGYRO_OUT 0x08 /* Z-axis gyroscope output */ +#define ADIS16400_XACCL_OUT 0x0A /* X-axis accelerometer output */ +#define ADIS16400_YACCL_OUT 0x0C /* Y-axis accelerometer output */ +#define ADIS16400_ZACCL_OUT 0x0E /* Z-axis accelerometer output */ +#define ADIS16400_XMAGN_OUT 0x10 /* X-axis magnetometer measurement */ +#define ADIS16400_YMAGN_OUT 0x12 /* Y-axis magnetometer measurement */ +#define ADIS16400_ZMAGN_OUT 0x14 /* Z-axis magnetometer measurement */ +#define ADIS16400_TEMP_OUT 0x16 /* Temperature output */ +#define ADIS16400_AUX_ADC 0x18 /* Auxiliary ADC measurement */ + +#define ADIS16350_XTEMP_OUT 0x10 /* X-axis gyroscope temperature measurement */ +#define ADIS16350_YTEMP_OUT 0x12 /* Y-axis gyroscope temperature measurement */ +#define ADIS16350_ZTEMP_OUT 0x14 /* Z-axis gyroscope temperature measurement */ + +#define ADIS16300_PITCH_OUT 0x12 /* X axis inclinometer output measurement */ +#define ADIS16300_ROLL_OUT 0x14 /* Y axis inclinometer output measurement */ +#define ADIS16300_AUX_ADC 0x16 /* Auxiliary ADC measurement */ + +#define ADIS16448_BARO_OUT 0x16 /* Barometric pressure output */ +#define ADIS16448_TEMP_OUT 0x18 /* Temperature output */ + +/* Calibration parameters */ +#define ADIS16400_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */ +#define ADIS16400_YGYRO_OFF 0x1C /* Y-axis gyroscope bias offset factor */ +#define ADIS16400_ZGYRO_OFF 0x1E /* Z-axis gyroscope bias offset factor */ +#define ADIS16400_XACCL_OFF 0x20 /* X-axis acceleration bias offset factor */ +#define ADIS16400_YACCL_OFF 0x22 /* Y-axis acceleration bias offset factor */ +#define ADIS16400_ZACCL_OFF 0x24 /* Z-axis acceleration bias offset factor */ +#define ADIS16400_XMAGN_HIF 0x26 /* X-axis magnetometer, hard-iron factor */ +#define ADIS16400_YMAGN_HIF 0x28 /* Y-axis magnetometer, hard-iron factor */ +#define ADIS16400_ZMAGN_HIF 0x2A /* Z-axis magnetometer, hard-iron factor */ +#define ADIS16400_XMAGN_SIF 0x2C /* X-axis magnetometer, soft-iron factor */ +#define ADIS16400_YMAGN_SIF 0x2E /* Y-axis magnetometer, soft-iron factor */ +#define ADIS16400_ZMAGN_SIF 0x30 /* Z-axis magnetometer, soft-iron factor */ + +#define ADIS16400_GPIO_CTRL 0x32 /* Auxiliary digital input/output control */ +#define ADIS16400_MSC_CTRL 0x34 /* Miscellaneous control */ +#define ADIS16400_SMPL_PRD 0x36 /* Internal sample period (rate) control */ +#define ADIS16400_SENS_AVG 0x38 /* Dynamic range and digital filter control */ +#define ADIS16400_SLP_CNT 0x3A /* Sleep mode control */ +#define ADIS16400_DIAG_STAT 0x3C /* System status */ + +/* Alarm functions */ +#define ADIS16400_GLOB_CMD 0x3E /* System command */ +#define ADIS16400_ALM_MAG1 0x40 /* Alarm 1 amplitude threshold */ +#define ADIS16400_ALM_MAG2 0x42 /* Alarm 2 amplitude threshold */ +#define ADIS16400_ALM_SMPL1 0x44 /* Alarm 1 sample size */ +#define ADIS16400_ALM_SMPL2 0x46 /* Alarm 2 sample size */ +#define ADIS16400_ALM_CTRL 0x48 /* Alarm control */ +#define ADIS16400_AUX_DAC 0x4A /* Auxiliary DAC data */ + +#define ADIS16334_LOT_ID1 0x52 /* Lot identification code 1 */ +#define ADIS16334_LOT_ID2 0x54 /* Lot identification code 2 */ +#define ADIS16400_PRODUCT_ID 0x56 /* Product identifier */ +#define ADIS16334_SERIAL_NUMBER 0x58 /* Serial number, lot specific */ + +#define ADIS16400_ERROR_ACTIVE (1<<14) +#define ADIS16400_NEW_DATA (1<<14) + +/* MSC_CTRL */ +#define ADIS16400_MSC_CTRL_MEM_TEST (1<<11) +#define ADIS16400_MSC_CTRL_INT_SELF_TEST (1<<10) +#define ADIS16400_MSC_CTRL_NEG_SELF_TEST (1<<9) +#define ADIS16400_MSC_CTRL_POS_SELF_TEST (1<<8) +#define ADIS16400_MSC_CTRL_GYRO_BIAS (1<<7) +#define ADIS16400_MSC_CTRL_ACCL_ALIGN (1<<6) +#define ADIS16400_MSC_CTRL_DATA_RDY_EN (1<<2) +#define ADIS16400_MSC_CTRL_DATA_RDY_POL_HIGH (1<<1) +#define ADIS16400_MSC_CTRL_DATA_RDY_DIO2 (1<<0) + +/* SMPL_PRD */ +#define ADIS16400_SMPL_PRD_TIME_BASE (1<<7) +#define ADIS16400_SMPL_PRD_DIV_MASK 0x7F + +/* DIAG_STAT */ +#define ADIS16400_DIAG_STAT_ZACCL_FAIL 15 +#define ADIS16400_DIAG_STAT_YACCL_FAIL 14 +#define ADIS16400_DIAG_STAT_XACCL_FAIL 13 +#define ADIS16400_DIAG_STAT_XGYRO_FAIL 12 +#define ADIS16400_DIAG_STAT_YGYRO_FAIL 11 +#define ADIS16400_DIAG_STAT_ZGYRO_FAIL 10 +#define ADIS16400_DIAG_STAT_ALARM2 9 +#define ADIS16400_DIAG_STAT_ALARM1 8 +#define ADIS16400_DIAG_STAT_FLASH_CHK 6 +#define ADIS16400_DIAG_STAT_SELF_TEST 5 +#define ADIS16400_DIAG_STAT_OVERFLOW 4 +#define ADIS16400_DIAG_STAT_SPI_FAIL 3 +#define ADIS16400_DIAG_STAT_FLASH_UPT 2 +#define ADIS16400_DIAG_STAT_POWER_HIGH 1 +#define ADIS16400_DIAG_STAT_POWER_LOW 0 + +/* GLOB_CMD */ +#define ADIS16400_GLOB_CMD_SW_RESET (1<<7) +#define ADIS16400_GLOB_CMD_P_AUTO_NULL (1<<4) +#define ADIS16400_GLOB_CMD_FLASH_UPD (1<<3) +#define ADIS16400_GLOB_CMD_DAC_LATCH (1<<2) +#define ADIS16400_GLOB_CMD_FAC_CALIB (1<<1) +#define ADIS16400_GLOB_CMD_AUTO_NULL (1<<0) + +/* SLP_CNT */ +#define ADIS16400_SLP_CNT_POWER_OFF (1<<8) + +#define ADIS16334_RATE_DIV_SHIFT 8 +#define ADIS16334_RATE_INT_CLK BIT(0) + +#define ADIS16400_SPI_SLOW (u32)(300 * 1000) +#define ADIS16400_SPI_BURST (u32)(1000 * 1000) +#define ADIS16400_SPI_FAST (u32)(2000 * 1000) + +#define ADIS16400_HAS_PROD_ID BIT(0) +#define ADIS16400_NO_BURST BIT(1) +#define ADIS16400_HAS_SLOW_MODE BIT(2) +#define ADIS16400_HAS_SERIAL_NUMBER BIT(3) +#define ADIS16400_BURST_DIAG_STAT BIT(4) + +struct adis16400_state; + +struct adis16400_chip_info { + const struct iio_chan_spec *channels; + const int num_channels; + const long flags; + unsigned int gyro_scale_micro; + unsigned int accel_scale_micro; + int temp_scale_nano; + int temp_offset; + int (*set_freq)(struct adis16400_state *st, unsigned int freq); + int (*get_freq)(struct adis16400_state *st); +}; + +/** + * struct adis16400_state - device instance specific data + * @variant: chip variant info + * @filt_int: integer part of requested filter frequency + * @adis: adis device + **/ +struct adis16400_state { + struct adis16400_chip_info *variant; + int filt_int; + + struct adis adis; + unsigned long avail_scan_mask[2]; +}; -#include "adis16400.h" +/* At the moment triggers are only used for ring buffer + * filling. This may change! + */ + +enum { + ADIS16400_SCAN_SUPPLY, + ADIS16400_SCAN_GYRO_X, + ADIS16400_SCAN_GYRO_Y, + ADIS16400_SCAN_GYRO_Z, + ADIS16400_SCAN_ACC_X, + ADIS16400_SCAN_ACC_Y, + ADIS16400_SCAN_ACC_Z, + ADIS16400_SCAN_MAGN_X, + ADIS16400_SCAN_MAGN_Y, + ADIS16400_SCAN_MAGN_Z, + ADIS16400_SCAN_BARO, + ADIS16350_SCAN_TEMP_X, + ADIS16350_SCAN_TEMP_Y, + ADIS16350_SCAN_TEMP_Z, + ADIS16300_SCAN_INCLI_X, + ADIS16300_SCAN_INCLI_Y, + ADIS16400_SCAN_ADC, + ADIS16400_SCAN_TIMESTAMP, +}; #ifdef CONFIG_DEBUG_FS @@ -145,6 +320,11 @@ enum adis16400_chip_variant { ADIS16448, }; +static struct adis_burst adis16400_burst = { + .en = true, + .reg_cmd = ADIS16400_GLOB_CMD, +}; + static int adis16334_get_freq(struct adis16400_state *st) { int ret; @@ -465,6 +645,51 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, } } +#if IS_ENABLED(CONFIG_IIO_BUFFER) +static irqreturn_t adis16400_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct adis16400_state *st = iio_priv(indio_dev); + struct adis *adis = &st->adis; + u32 old_speed_hz = st->adis.spi->max_speed_hz; + void *buffer; + int ret; + + if (!adis->buffer) + return -ENOMEM; + + if (!(st->variant->flags & ADIS16400_NO_BURST) && + st->adis.spi->max_speed_hz > ADIS16400_SPI_BURST) { + st->adis.spi->max_speed_hz = ADIS16400_SPI_BURST; + spi_setup(st->adis.spi); + } + + ret = spi_sync(adis->spi, &adis->msg); + if (ret) + dev_err(&adis->spi->dev, "Failed to read data: %d\n", ret); + + if (!(st->variant->flags & ADIS16400_NO_BURST)) { + st->adis.spi->max_speed_hz = old_speed_hz; + spi_setup(st->adis.spi); + } + + if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) + buffer = adis->buffer + sizeof(u16); + else + buffer = adis->buffer; + + iio_push_to_buffers_with_timestamp(indio_dev, buffer, + pf->timestamp); + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} +#else +#define adis16400_trigger_handler NULL +#endif /* IS_ENABLED(CONFIG_IIO_BUFFER) */ + #define ADIS16400_VOLTAGE_CHAN(addr, bits, name, si, chn) { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ @@ -835,7 +1060,7 @@ static struct adis16400_chip_info adis16400_chips[] = { static const struct iio_info adis16400_info = { .read_raw = &adis16400_read_raw, .write_raw = &adis16400_write_raw, - .update_scan_mode = adis16400_update_scan_mode, + .update_scan_mode = adis_update_scan_mode, .debugfs_reg_access = adis_debugfs_reg_access, }; @@ -926,6 +1151,9 @@ static int adis16400_probe(struct spi_device *spi) if (!(st->variant->flags & ADIS16400_NO_BURST)) { adis16400_setup_chan_mask(st); 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); } ret = adis_init(&st->adis, indio_dev, spi, &adis16400_data); diff --git a/drivers/iio/imu/adis16400.h b/drivers/iio/imu/adis16400.h deleted file mode 100644 index 73b189c1c0fb..000000000000 --- a/drivers/iio/imu/adis16400.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - * adis16400.h support Analog Devices ADIS16400 - * 3d 18g accelerometers, - * 3d gyroscopes, - * 3d 2.5gauss magnetometers via SPI - * - * Copyright (c) 2009 Manuel Stahl <manuel.stahl@iis.fraunhofer.de> - * Copyright (c) 2007 Jonathan Cameron <jic23@kernel.org> - * - * Loosely based upon lis3l02dq.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef SPI_ADIS16400_H_ -#define SPI_ADIS16400_H_ - -#include <linux/iio/imu/adis.h> - -#define ADIS16400_STARTUP_DELAY 290 /* ms */ -#define ADIS16400_MTEST_DELAY 90 /* ms */ - -#define ADIS16400_FLASH_CNT 0x00 /* Flash memory write count */ -#define ADIS16400_SUPPLY_OUT 0x02 /* Power supply measurement */ -#define ADIS16400_XGYRO_OUT 0x04 /* X-axis gyroscope output */ -#define ADIS16400_YGYRO_OUT 0x06 /* Y-axis gyroscope output */ -#define ADIS16400_ZGYRO_OUT 0x08 /* Z-axis gyroscope output */ -#define ADIS16400_XACCL_OUT 0x0A /* X-axis accelerometer output */ -#define ADIS16400_YACCL_OUT 0x0C /* Y-axis accelerometer output */ -#define ADIS16400_ZACCL_OUT 0x0E /* Z-axis accelerometer output */ -#define ADIS16400_XMAGN_OUT 0x10 /* X-axis magnetometer measurement */ -#define ADIS16400_YMAGN_OUT 0x12 /* Y-axis magnetometer measurement */ -#define ADIS16400_ZMAGN_OUT 0x14 /* Z-axis magnetometer measurement */ -#define ADIS16400_TEMP_OUT 0x16 /* Temperature output */ -#define ADIS16400_AUX_ADC 0x18 /* Auxiliary ADC measurement */ - -#define ADIS16350_XTEMP_OUT 0x10 /* X-axis gyroscope temperature measurement */ -#define ADIS16350_YTEMP_OUT 0x12 /* Y-axis gyroscope temperature measurement */ -#define ADIS16350_ZTEMP_OUT 0x14 /* Z-axis gyroscope temperature measurement */ - -#define ADIS16300_PITCH_OUT 0x12 /* X axis inclinometer output measurement */ -#define ADIS16300_ROLL_OUT 0x14 /* Y axis inclinometer output measurement */ -#define ADIS16300_AUX_ADC 0x16 /* Auxiliary ADC measurement */ - -#define ADIS16448_BARO_OUT 0x16 /* Barometric pressure output */ -#define ADIS16448_TEMP_OUT 0x18 /* Temperature output */ - -/* Calibration parameters */ -#define ADIS16400_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */ -#define ADIS16400_YGYRO_OFF 0x1C /* Y-axis gyroscope bias offset factor */ -#define ADIS16400_ZGYRO_OFF 0x1E /* Z-axis gyroscope bias offset factor */ -#define ADIS16400_XACCL_OFF 0x20 /* X-axis acceleration bias offset factor */ -#define ADIS16400_YACCL_OFF 0x22 /* Y-axis acceleration bias offset factor */ -#define ADIS16400_ZACCL_OFF 0x24 /* Z-axis acceleration bias offset factor */ -#define ADIS16400_XMAGN_HIF 0x26 /* X-axis magnetometer, hard-iron factor */ -#define ADIS16400_YMAGN_HIF 0x28 /* Y-axis magnetometer, hard-iron factor */ -#define ADIS16400_ZMAGN_HIF 0x2A /* Z-axis magnetometer, hard-iron factor */ -#define ADIS16400_XMAGN_SIF 0x2C /* X-axis magnetometer, soft-iron factor */ -#define ADIS16400_YMAGN_SIF 0x2E /* Y-axis magnetometer, soft-iron factor */ -#define ADIS16400_ZMAGN_SIF 0x30 /* Z-axis magnetometer, soft-iron factor */ - -#define ADIS16400_GPIO_CTRL 0x32 /* Auxiliary digital input/output control */ -#define ADIS16400_MSC_CTRL 0x34 /* Miscellaneous control */ -#define ADIS16400_SMPL_PRD 0x36 /* Internal sample period (rate) control */ -#define ADIS16400_SENS_AVG 0x38 /* Dynamic range and digital filter control */ -#define ADIS16400_SLP_CNT 0x3A /* Sleep mode control */ -#define ADIS16400_DIAG_STAT 0x3C /* System status */ - -/* Alarm functions */ -#define ADIS16400_GLOB_CMD 0x3E /* System command */ -#define ADIS16400_ALM_MAG1 0x40 /* Alarm 1 amplitude threshold */ -#define ADIS16400_ALM_MAG2 0x42 /* Alarm 2 amplitude threshold */ -#define ADIS16400_ALM_SMPL1 0x44 /* Alarm 1 sample size */ -#define ADIS16400_ALM_SMPL2 0x46 /* Alarm 2 sample size */ -#define ADIS16400_ALM_CTRL 0x48 /* Alarm control */ -#define ADIS16400_AUX_DAC 0x4A /* Auxiliary DAC data */ - -#define ADIS16334_LOT_ID1 0x52 /* Lot identification code 1 */ -#define ADIS16334_LOT_ID2 0x54 /* Lot identification code 2 */ -#define ADIS16400_PRODUCT_ID 0x56 /* Product identifier */ -#define ADIS16334_SERIAL_NUMBER 0x58 /* Serial number, lot specific */ - -#define ADIS16400_ERROR_ACTIVE (1<<14) -#define ADIS16400_NEW_DATA (1<<14) - -/* MSC_CTRL */ -#define ADIS16400_MSC_CTRL_MEM_TEST (1<<11) -#define ADIS16400_MSC_CTRL_INT_SELF_TEST (1<<10) -#define ADIS16400_MSC_CTRL_NEG_SELF_TEST (1<<9) -#define ADIS16400_MSC_CTRL_POS_SELF_TEST (1<<8) -#define ADIS16400_MSC_CTRL_GYRO_BIAS (1<<7) -#define ADIS16400_MSC_CTRL_ACCL_ALIGN (1<<6) -#define ADIS16400_MSC_CTRL_DATA_RDY_EN (1<<2) -#define ADIS16400_MSC_CTRL_DATA_RDY_POL_HIGH (1<<1) -#define ADIS16400_MSC_CTRL_DATA_RDY_DIO2 (1<<0) - -/* SMPL_PRD */ -#define ADIS16400_SMPL_PRD_TIME_BASE (1<<7) -#define ADIS16400_SMPL_PRD_DIV_MASK 0x7F - -/* DIAG_STAT */ -#define ADIS16400_DIAG_STAT_ZACCL_FAIL 15 -#define ADIS16400_DIAG_STAT_YACCL_FAIL 14 -#define ADIS16400_DIAG_STAT_XACCL_FAIL 13 -#define ADIS16400_DIAG_STAT_XGYRO_FAIL 12 -#define ADIS16400_DIAG_STAT_YGYRO_FAIL 11 -#define ADIS16400_DIAG_STAT_ZGYRO_FAIL 10 -#define ADIS16400_DIAG_STAT_ALARM2 9 -#define ADIS16400_DIAG_STAT_ALARM1 8 -#define ADIS16400_DIAG_STAT_FLASH_CHK 6 -#define ADIS16400_DIAG_STAT_SELF_TEST 5 -#define ADIS16400_DIAG_STAT_OVERFLOW 4 -#define ADIS16400_DIAG_STAT_SPI_FAIL 3 -#define ADIS16400_DIAG_STAT_FLASH_UPT 2 -#define ADIS16400_DIAG_STAT_POWER_HIGH 1 -#define ADIS16400_DIAG_STAT_POWER_LOW 0 - -/* GLOB_CMD */ -#define ADIS16400_GLOB_CMD_SW_RESET (1<<7) -#define ADIS16400_GLOB_CMD_P_AUTO_NULL (1<<4) -#define ADIS16400_GLOB_CMD_FLASH_UPD (1<<3) -#define ADIS16400_GLOB_CMD_DAC_LATCH (1<<2) -#define ADIS16400_GLOB_CMD_FAC_CALIB (1<<1) -#define ADIS16400_GLOB_CMD_AUTO_NULL (1<<0) - -/* SLP_CNT */ -#define ADIS16400_SLP_CNT_POWER_OFF (1<<8) - -#define ADIS16334_RATE_DIV_SHIFT 8 -#define ADIS16334_RATE_INT_CLK BIT(0) - -#define ADIS16400_SPI_SLOW (u32)(300 * 1000) -#define ADIS16400_SPI_BURST (u32)(1000 * 1000) -#define ADIS16400_SPI_FAST (u32)(2000 * 1000) - -#define ADIS16400_HAS_PROD_ID BIT(0) -#define ADIS16400_NO_BURST BIT(1) -#define ADIS16400_HAS_SLOW_MODE BIT(2) -#define ADIS16400_HAS_SERIAL_NUMBER BIT(3) -#define ADIS16400_BURST_DIAG_STAT BIT(4) - -struct adis16400_state; - -struct adis16400_chip_info { - const struct iio_chan_spec *channels; - const int num_channels; - const long flags; - unsigned int gyro_scale_micro; - unsigned int accel_scale_micro; - int temp_scale_nano; - int temp_offset; - int (*set_freq)(struct adis16400_state *st, unsigned int freq); - int (*get_freq)(struct adis16400_state *st); -}; - -/** - * struct adis16400_state - device instance specific data - * @variant: chip variant info - * @filt_int: integer part of requested filter frequency - * @adis: adis device - **/ -struct adis16400_state { - struct adis16400_chip_info *variant; - int filt_int; - - struct adis adis; - unsigned long avail_scan_mask[2]; -}; - -/* At the moment triggers are only used for ring buffer - * filling. This may change! - */ - -enum { - ADIS16400_SCAN_SUPPLY, - ADIS16400_SCAN_GYRO_X, - ADIS16400_SCAN_GYRO_Y, - ADIS16400_SCAN_GYRO_Z, - ADIS16400_SCAN_ACC_X, - ADIS16400_SCAN_ACC_Y, - ADIS16400_SCAN_ACC_Z, - ADIS16400_SCAN_MAGN_X, - ADIS16400_SCAN_MAGN_Y, - ADIS16400_SCAN_MAGN_Z, - ADIS16400_SCAN_BARO, - ADIS16350_SCAN_TEMP_X, - ADIS16350_SCAN_TEMP_Y, - ADIS16350_SCAN_TEMP_Z, - ADIS16300_SCAN_INCLI_X, - ADIS16300_SCAN_INCLI_Y, - ADIS16400_SCAN_ADC, - ADIS16400_SCAN_TIMESTAMP, -}; - -#ifdef CONFIG_IIO_BUFFER - -ssize_t adis16400_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf); - - -int adis16400_update_scan_mode(struct iio_dev *indio_dev, - const unsigned long *scan_mask); -irqreturn_t adis16400_trigger_handler(int irq, void *p); - -#else /* CONFIG_IIO_BUFFER */ - -#define adis16400_update_scan_mode NULL -#define adis16400_trigger_handler NULL - -#endif /* CONFIG_IIO_BUFFER */ - -#endif /* SPI_ADIS16400_H_ */ diff --git a/drivers/iio/imu/adis16400_buffer.c b/drivers/iio/imu/adis16400_buffer.c deleted file mode 100644 index e70a5339acb1..000000000000 --- a/drivers/iio/imu/adis16400_buffer.c +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include <linux/interrupt.h> -#include <linux/mutex.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/bitops.h> -#include <linux/export.h> - -#include <linux/iio/iio.h> -#include <linux/iio/buffer.h> -#include <linux/iio/triggered_buffer.h> -#include <linux/iio/trigger_consumer.h> - -#include "adis16400.h" - -int adis16400_update_scan_mode(struct iio_dev *indio_dev, - const unsigned long *scan_mask) -{ - struct adis16400_state *st = iio_priv(indio_dev); - struct adis *adis = &st->adis; - unsigned int burst_length; - u8 *tx; - - if (st->variant->flags & ADIS16400_NO_BURST) - return adis_update_scan_mode(indio_dev, scan_mask); - - kfree(adis->xfer); - kfree(adis->buffer); - - /* All but the timestamp channel */ - burst_length = (indio_dev->num_channels - 1) * sizeof(u16); - if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) - burst_length += sizeof(u16); - - adis->xfer = kcalloc(2, sizeof(*adis->xfer), GFP_KERNEL); - if (!adis->xfer) - return -ENOMEM; - - adis->buffer = kzalloc(burst_length + sizeof(u16), GFP_KERNEL); - if (!adis->buffer) - return -ENOMEM; - - tx = adis->buffer + burst_length; - tx[0] = ADIS_READ_REG(ADIS16400_GLOB_CMD); - tx[1] = 0; - - adis->xfer[0].tx_buf = tx; - adis->xfer[0].bits_per_word = 8; - adis->xfer[0].len = 2; - adis->xfer[1].rx_buf = adis->buffer; - adis->xfer[1].bits_per_word = 8; - adis->xfer[1].len = burst_length; - - spi_message_init(&adis->msg); - spi_message_add_tail(&adis->xfer[0], &adis->msg); - spi_message_add_tail(&adis->xfer[1], &adis->msg); - - return 0; -} - -irqreturn_t adis16400_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct adis16400_state *st = iio_priv(indio_dev); - struct adis *adis = &st->adis; - u32 old_speed_hz = st->adis.spi->max_speed_hz; - void *buffer; - int ret; - - if (!adis->buffer) - return -ENOMEM; - - if (!(st->variant->flags & ADIS16400_NO_BURST) && - st->adis.spi->max_speed_hz > ADIS16400_SPI_BURST) { - st->adis.spi->max_speed_hz = ADIS16400_SPI_BURST; - spi_setup(st->adis.spi); - } - - ret = spi_sync(adis->spi, &adis->msg); - if (ret) - dev_err(&adis->spi->dev, "Failed to read data: %d\n", ret); - - if (!(st->variant->flags & ADIS16400_NO_BURST)) { - st->adis.spi->max_speed_hz = old_speed_hz; - spi_setup(st->adis.spi); - } - - if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) - buffer = adis->buffer + sizeof(u16); - else - buffer = adis->buffer; - - iio_push_to_buffers_with_timestamp(indio_dev, buffer, - pf->timestamp); - - iio_trigger_notify_done(indio_dev->trig); - - return IRQ_HANDLED; -} diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index a27fe208f3ae..ab137c1bbe7b 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -9,6 +9,9 @@ * */ +#include <linux/clk.h> +#include <linux/bitfield.h> +#include <linux/of_irq.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/mutex.h> @@ -97,6 +100,12 @@ #define ADIS16480_REG_FIRM_DM ADIS16480_REG(0x03, 0x7A) #define ADIS16480_REG_FIRM_Y ADIS16480_REG(0x03, 0x7C) +/* + * External clock scaling in PPS mode. + * Available only for ADIS1649x devices + */ +#define ADIS16495_REG_SYNC_SCALE ADIS16480_REG(0x03, 0x10) + #define ADIS16480_REG_SERIAL_NUM ADIS16480_REG(0x04, 0x20) /* Each filter coefficent bank spans two pages */ @@ -107,6 +116,20 @@ #define ADIS16480_FIR_COEF_C(x) ADIS16480_FIR_COEF(0x09, (x)) #define ADIS16480_FIR_COEF_D(x) ADIS16480_FIR_COEF(0x0B, (x)) +/* ADIS16480_REG_FNCTIO_CTRL */ +#define ADIS16480_DRDY_SEL_MSK GENMASK(1, 0) +#define ADIS16480_DRDY_SEL(x) FIELD_PREP(ADIS16480_DRDY_SEL_MSK, x) +#define ADIS16480_DRDY_POL_MSK BIT(2) +#define ADIS16480_DRDY_POL(x) FIELD_PREP(ADIS16480_DRDY_POL_MSK, x) +#define ADIS16480_DRDY_EN_MSK BIT(3) +#define ADIS16480_DRDY_EN(x) FIELD_PREP(ADIS16480_DRDY_EN_MSK, x) +#define ADIS16480_SYNC_SEL_MSK GENMASK(5, 4) +#define ADIS16480_SYNC_SEL(x) FIELD_PREP(ADIS16480_SYNC_SEL_MSK, x) +#define ADIS16480_SYNC_EN_MSK BIT(7) +#define ADIS16480_SYNC_EN(x) FIELD_PREP(ADIS16480_SYNC_EN_MSK, x) +#define ADIS16480_SYNC_MODE_MSK BIT(8) +#define ADIS16480_SYNC_MODE(x) FIELD_PREP(ADIS16480_SYNC_MODE_MSK, x) + struct adis16480_chip_info { unsigned int num_channels; const struct iio_chan_spec *channels; @@ -114,12 +137,40 @@ struct adis16480_chip_info { unsigned int gyro_max_scale; unsigned int accel_max_val; unsigned int accel_max_scale; + unsigned int temp_scale; + unsigned int int_clk; + unsigned int max_dec_rate; + const unsigned int *filter_freqs; + bool has_pps_clk_mode; +}; + +enum adis16480_int_pin { + ADIS16480_PIN_DIO1, + ADIS16480_PIN_DIO2, + ADIS16480_PIN_DIO3, + ADIS16480_PIN_DIO4 +}; + +enum adis16480_clock_mode { + ADIS16480_CLK_SYNC, + ADIS16480_CLK_PPS, + ADIS16480_CLK_INT }; struct adis16480 { const struct adis16480_chip_info *chip_info; struct adis adis; + struct clk *ext_clk; + enum adis16480_clock_mode clk_mode; + unsigned int clk_freq; +}; + +static const char * const adis16480_int_pin_names[4] = { + [ADIS16480_PIN_DIO1] = "DIO1", + [ADIS16480_PIN_DIO2] = "DIO2", + [ADIS16480_PIN_DIO3] = "DIO3", + [ADIS16480_PIN_DIO4] = "DIO4", }; #ifdef CONFIG_DEBUG_FS @@ -268,20 +319,34 @@ static int adis16480_debugfs_init(struct iio_dev *indio_dev) static int adis16480_set_freq(struct iio_dev *indio_dev, int val, int val2) { struct adis16480 *st = iio_priv(indio_dev); - unsigned int t; + unsigned int t, reg; t = val * 1000 + val2 / 1000; if (t <= 0) return -EINVAL; - t = 2460000 / t; - if (t > 2048) - t = 2048; + /* + * When using PPS mode, the rate of data collection is equal to the + * product of the external clock frequency and the scale factor in the + * SYNC_SCALE register. + * When using sync mode, or internal clock, the output data rate is + * equal with the clock frequency divided by DEC_RATE + 1. + */ + if (st->clk_mode == ADIS16480_CLK_PPS) { + t = t / st->clk_freq; + reg = ADIS16495_REG_SYNC_SCALE; + } else { + t = st->clk_freq / t; + reg = ADIS16480_REG_DEC_RATE; + } + + if (t > st->chip_info->max_dec_rate) + t = st->chip_info->max_dec_rate; - if (t != 0) + if ((t != 0) && (st->clk_mode != ADIS16480_CLK_PPS)) t--; - return adis_write_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, t); + return adis_write_reg_16(&st->adis, reg, t); } static int adis16480_get_freq(struct iio_dev *indio_dev, int *val, int *val2) @@ -290,12 +355,29 @@ static int adis16480_get_freq(struct iio_dev *indio_dev, int *val, int *val2) uint16_t t; int ret; unsigned freq; + unsigned int reg; - ret = adis_read_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, &t); + if (st->clk_mode == ADIS16480_CLK_PPS) + reg = ADIS16495_REG_SYNC_SCALE; + else + reg = ADIS16480_REG_DEC_RATE; + + ret = adis_read_reg_16(&st->adis, reg, &t); if (ret < 0) return ret; - freq = 2460000 / (t + 1); + /* + * When using PPS mode, the rate of data collection is equal to the + * product of the external clock frequency and the scale factor in the + * SYNC_SCALE register. + * When using sync mode, or internal clock, the output data rate is + * equal with the clock frequency divided by DEC_RATE + 1. + */ + if (st->clk_mode == ADIS16480_CLK_PPS) + freq = st->clk_freq * t; + else + freq = st->clk_freq / (t + 1); + *val = freq / 1000; *val2 = (freq % 1000) * 1000; @@ -425,6 +507,13 @@ static const unsigned int adis16480_def_filter_freqs[] = { 63, }; +static const unsigned int adis16495_def_filter_freqs[] = { + 300, + 100, + 300, + 100, +}; + static const unsigned int ad16480_filter_data[][2] = { [ADIS16480_SCAN_GYRO_X] = { ADIS16480_REG_FILTER_BNK0, 0 }, [ADIS16480_SCAN_GYRO_Y] = { ADIS16480_REG_FILTER_BNK0, 3 }, @@ -456,7 +545,7 @@ static int adis16480_get_filter_freq(struct iio_dev *indio_dev, if (!(val & enable_mask)) *freq = 0; else - *freq = adis16480_def_filter_freqs[(val >> offset) & 0x3]; + *freq = st->chip_info->filter_freqs[(val >> offset) & 0x3]; return IIO_VAL_INT; } @@ -483,10 +572,10 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev, val &= ~enable_mask; } else { best_freq = 0; - best_diff = 310; + best_diff = st->chip_info->filter_freqs[0]; for (i = 0; i < ARRAY_SIZE(adis16480_def_filter_freqs); i++) { - if (adis16480_def_filter_freqs[i] >= freq) { - diff = adis16480_def_filter_freqs[i] - freq; + if (st->chip_info->filter_freqs[i] >= freq) { + diff = st->chip_info->filter_freqs[i] - freq; if (diff < best_diff) { best_diff = diff; best_freq = i; @@ -506,6 +595,7 @@ static int adis16480_read_raw(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, int *val, int *val2, long info) { struct adis16480 *st = iio_priv(indio_dev); + unsigned int temp; switch (info) { case IIO_CHAN_INFO_RAW: @@ -525,8 +615,13 @@ static int adis16480_read_raw(struct iio_dev *indio_dev, *val2 = 100; /* 0.0001 gauss */ return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 5; - *val2 = 650000; /* 5.65 milli degree Celsius */ + /* + * +85 degrees Celsius = temp_max_scale + * +25 degrees Celsius = 0 + * LSB, 25 degrees Celsius = 60 / temp_max_scale + */ + *val = st->chip_info->temp_scale / 1000; + *val2 = (st->chip_info->temp_scale % 1000) * 1000; return IIO_VAL_INT_PLUS_MICRO; case IIO_PRESSURE: *val = 0; @@ -537,7 +632,8 @@ static int adis16480_read_raw(struct iio_dev *indio_dev, } case IIO_CHAN_INFO_OFFSET: /* Only the temperature channel has a offset */ - *val = 4425; /* 25 degree Celsius = 0x0000 */ + temp = 25 * 1000000LL; /* 25 degree Celsius = 0x0000 */ + *val = DIV_ROUND_CLOSEST_ULL(temp, st->chip_info->temp_scale); return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: return adis16480_get_calibbias(indio_dev, chan, val); @@ -678,6 +774,12 @@ enum adis16480_variant { ADIS16480, ADIS16485, ADIS16488, + ADIS16495_1, + ADIS16495_2, + ADIS16495_3, + ADIS16497_1, + ADIS16497_2, + ADIS16497_3, }; static const struct adis16480_chip_info adis16480_chip_info[] = { @@ -693,6 +795,10 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .gyro_max_scale = 300, .accel_max_val = IIO_M_S_2_TO_G(21973), .accel_max_scale = 18, + .temp_scale = 5650, /* 5.65 milli degree Celsius */ + .int_clk = 2460000, + .max_dec_rate = 2048, + .filter_freqs = adis16480_def_filter_freqs, }, [ADIS16480] = { .channels = adis16480_channels, @@ -701,6 +807,10 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .gyro_max_scale = 450, .accel_max_val = IIO_M_S_2_TO_G(12500), .accel_max_scale = 10, + .temp_scale = 5650, /* 5.65 milli degree Celsius */ + .int_clk = 2460000, + .max_dec_rate = 2048, + .filter_freqs = adis16480_def_filter_freqs, }, [ADIS16485] = { .channels = adis16485_channels, @@ -709,6 +819,10 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .gyro_max_scale = 450, .accel_max_val = IIO_M_S_2_TO_G(20000), .accel_max_scale = 5, + .temp_scale = 5650, /* 5.65 milli degree Celsius */ + .int_clk = 2460000, + .max_dec_rate = 2048, + .filter_freqs = adis16480_def_filter_freqs, }, [ADIS16488] = { .channels = adis16480_channels, @@ -717,6 +831,88 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .gyro_max_scale = 450, .accel_max_val = IIO_M_S_2_TO_G(22500), .accel_max_scale = 18, + .temp_scale = 5650, /* 5.65 milli degree Celsius */ + .int_clk = 2460000, + .max_dec_rate = 2048, + .filter_freqs = adis16480_def_filter_freqs, + }, + [ADIS16495_1] = { + .channels = adis16485_channels, + .num_channels = ARRAY_SIZE(adis16485_channels), + .gyro_max_val = IIO_RAD_TO_DEGREE(20000), + .gyro_max_scale = 125, + .accel_max_val = IIO_M_S_2_TO_G(32000), + .accel_max_scale = 8, + .temp_scale = 12500, /* 12.5 milli degree Celsius */ + .int_clk = 4250000, + .max_dec_rate = 4250, + .filter_freqs = adis16495_def_filter_freqs, + .has_pps_clk_mode = true, + }, + [ADIS16495_2] = { + .channels = adis16485_channels, + .num_channels = ARRAY_SIZE(adis16485_channels), + .gyro_max_val = IIO_RAD_TO_DEGREE(18000), + .gyro_max_scale = 450, + .accel_max_val = IIO_M_S_2_TO_G(32000), + .accel_max_scale = 8, + .temp_scale = 12500, /* 12.5 milli degree Celsius */ + .int_clk = 4250000, + .max_dec_rate = 4250, + .filter_freqs = adis16495_def_filter_freqs, + .has_pps_clk_mode = true, + }, + [ADIS16495_3] = { + .channels = adis16485_channels, + .num_channels = ARRAY_SIZE(adis16485_channels), + .gyro_max_val = IIO_RAD_TO_DEGREE(20000), + .gyro_max_scale = 2000, + .accel_max_val = IIO_M_S_2_TO_G(32000), + .accel_max_scale = 8, + .temp_scale = 12500, /* 12.5 milli degree Celsius */ + .int_clk = 4250000, + .max_dec_rate = 4250, + .filter_freqs = adis16495_def_filter_freqs, + .has_pps_clk_mode = true, + }, + [ADIS16497_1] = { + .channels = adis16485_channels, + .num_channels = ARRAY_SIZE(adis16485_channels), + .gyro_max_val = IIO_RAD_TO_DEGREE(20000), + .gyro_max_scale = 125, + .accel_max_val = IIO_M_S_2_TO_G(32000), + .accel_max_scale = 40, + .temp_scale = 12500, /* 12.5 milli degree Celsius */ + .int_clk = 4250000, + .max_dec_rate = 4250, + .filter_freqs = adis16495_def_filter_freqs, + .has_pps_clk_mode = true, + }, + [ADIS16497_2] = { + .channels = adis16485_channels, + .num_channels = ARRAY_SIZE(adis16485_channels), + .gyro_max_val = IIO_RAD_TO_DEGREE(18000), + .gyro_max_scale = 450, + .accel_max_val = IIO_M_S_2_TO_G(32000), + .accel_max_scale = 40, + .temp_scale = 12500, /* 12.5 milli degree Celsius */ + .int_clk = 4250000, + .max_dec_rate = 4250, + .filter_freqs = adis16495_def_filter_freqs, + .has_pps_clk_mode = true, + }, + [ADIS16497_3] = { + .channels = adis16485_channels, + .num_channels = ARRAY_SIZE(adis16485_channels), + .gyro_max_val = IIO_RAD_TO_DEGREE(20000), + .gyro_max_scale = 2000, + .accel_max_val = IIO_M_S_2_TO_G(32000), + .accel_max_scale = 40, + .temp_scale = 12500, /* 12.5 milli degree Celsius */ + .int_clk = 4250000, + .max_dec_rate = 4250, + .filter_freqs = adis16495_def_filter_freqs, + .has_pps_clk_mode = true, }, }; @@ -741,8 +937,17 @@ static int adis16480_stop_device(struct iio_dev *indio_dev) static int adis16480_enable_irq(struct adis *adis, bool enable) { - return adis_write_reg_16(adis, ADIS16480_REG_FNCTIO_CTRL, - enable ? BIT(3) : 0); + uint16_t val; + int ret; + + ret = adis_read_reg_16(adis, ADIS16480_REG_FNCTIO_CTRL, &val); + if (ret < 0) + return ret; + + val &= ~ADIS16480_DRDY_EN_MSK; + val |= ADIS16480_DRDY_EN(enable); + + return adis_write_reg_16(adis, ADIS16480_REG_FNCTIO_CTRL, val); } static int adis16480_initial_setup(struct iio_dev *indio_dev) @@ -826,6 +1031,156 @@ static const struct adis_data adis16480_data = { .enable_irq = adis16480_enable_irq, }; +static int adis16480_config_irq_pin(struct device_node *of_node, + struct adis16480 *st) +{ + struct irq_data *desc; + enum adis16480_int_pin pin; + unsigned int irq_type; + uint16_t val; + int i, irq = 0; + + desc = irq_get_irq_data(st->adis.spi->irq); + if (!desc) { + dev_err(&st->adis.spi->dev, "Could not find IRQ %d\n", irq); + return -EINVAL; + } + + /* Disable data ready since the default after reset is on */ + val = ADIS16480_DRDY_EN(0); + + /* + * Get the interrupt from the devicetre by reading the interrupt-names + * property. If it is not specified, use DIO1 pin as default. + * According to the datasheet, the factory default assigns DIO2 as data + * ready signal. However, in the previous versions of the driver, DIO1 + * pin was used. So, we should leave it as is since some devices might + * be expecting the interrupt on the wrong physical pin. + */ + pin = ADIS16480_PIN_DIO1; + for (i = 0; i < ARRAY_SIZE(adis16480_int_pin_names); i++) { + irq = of_irq_get_byname(of_node, adis16480_int_pin_names[i]); + if (irq > 0) { + pin = i; + break; + } + } + + val |= ADIS16480_DRDY_SEL(pin); + + /* + * Get the interrupt line behaviour. The data ready polarity can be + * configured as positive or negative, corresponding to + * IRQF_TRIGGER_RISING or IRQF_TRIGGER_FALLING respectively. + */ + irq_type = irqd_get_trigger_type(desc); + if (irq_type == IRQF_TRIGGER_RISING) { /* Default */ + val |= ADIS16480_DRDY_POL(1); + } else if (irq_type == IRQF_TRIGGER_FALLING) { + val |= ADIS16480_DRDY_POL(0); + } else { + dev_err(&st->adis.spi->dev, + "Invalid interrupt type 0x%x specified\n", irq_type); + return -EINVAL; + } + /* Write the data ready configuration to the FNCTIO_CTRL register */ + return adis_write_reg_16(&st->adis, ADIS16480_REG_FNCTIO_CTRL, val); +} + +static int adis16480_of_get_ext_clk_pin(struct adis16480 *st, + struct device_node *of_node) +{ + const char *ext_clk_pin; + enum adis16480_int_pin pin; + int i; + + pin = ADIS16480_PIN_DIO2; + if (of_property_read_string(of_node, "adi,ext-clk-pin", &ext_clk_pin)) + goto clk_input_not_found; + + for (i = 0; i < ARRAY_SIZE(adis16480_int_pin_names); i++) { + if (strcasecmp(ext_clk_pin, adis16480_int_pin_names[i]) == 0) + return i; + } + +clk_input_not_found: + dev_info(&st->adis.spi->dev, + "clk input line not specified, using DIO2\n"); + return pin; +} + +static int adis16480_ext_clk_config(struct adis16480 *st, + struct device_node *of_node, + bool enable) +{ + unsigned int mode, mask; + enum adis16480_int_pin pin; + uint16_t val; + int ret; + + ret = adis_read_reg_16(&st->adis, ADIS16480_REG_FNCTIO_CTRL, &val); + if (ret < 0) + return ret; + + pin = adis16480_of_get_ext_clk_pin(st, of_node); + /* + * Each DIOx pin supports only one function at a time. When a single pin + * has two assignments, the enable bit for a lower priority function + * automatically resets to zero (disabling the lower priority function). + */ + if (pin == ADIS16480_DRDY_SEL(val)) + dev_warn(&st->adis.spi->dev, + "DIO%x pin supports only one function at a time\n", + pin + 1); + + mode = ADIS16480_SYNC_EN(enable) | ADIS16480_SYNC_SEL(pin); + mask = ADIS16480_SYNC_EN_MSK | ADIS16480_SYNC_SEL_MSK; + /* Only ADIS1649x devices support pps ext clock mode */ + if (st->chip_info->has_pps_clk_mode) { + mode |= ADIS16480_SYNC_MODE(st->clk_mode); + mask |= ADIS16480_SYNC_MODE_MSK; + } + + val &= ~mask; + val |= mode; + + ret = adis_write_reg_16(&st->adis, ADIS16480_REG_FNCTIO_CTRL, val); + if (ret < 0) + return ret; + + return clk_prepare_enable(st->ext_clk); +} + +static int adis16480_get_ext_clocks(struct adis16480 *st) +{ + st->clk_mode = ADIS16480_CLK_INT; + st->ext_clk = devm_clk_get(&st->adis.spi->dev, "sync"); + if (!IS_ERR_OR_NULL(st->ext_clk)) { + st->clk_mode = ADIS16480_CLK_SYNC; + return 0; + } + + if (PTR_ERR(st->ext_clk) != -ENOENT) { + dev_err(&st->adis.spi->dev, "failed to get ext clk\n"); + return PTR_ERR(st->ext_clk); + } + + if (st->chip_info->has_pps_clk_mode) { + st->ext_clk = devm_clk_get(&st->adis.spi->dev, "pps"); + if (!IS_ERR_OR_NULL(st->ext_clk)) { + st->clk_mode = ADIS16480_CLK_PPS; + return 0; + } + + if (PTR_ERR(st->ext_clk) != -ENOENT) { + dev_err(&st->adis.spi->dev, "failed to get ext clk\n"); + return PTR_ERR(st->ext_clk); + } + } + + return 0; +} + static int adis16480_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); @@ -853,10 +1208,29 @@ static int adis16480_probe(struct spi_device *spi) if (ret) return ret; - ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL); + ret = adis16480_config_irq_pin(spi->dev.of_node, st); + if (ret) + return ret; + + ret = adis16480_get_ext_clocks(st); if (ret) return ret; + if (!IS_ERR_OR_NULL(st->ext_clk)) { + ret = adis16480_ext_clk_config(st, spi->dev.of_node, true); + if (ret) + return ret; + + st->clk_freq = clk_get_rate(st->ext_clk); + st->clk_freq *= 1000; /* micro */ + } else { + st->clk_freq = st->chip_info->int_clk; + } + + ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL); + if (ret) + goto error_clk_disable_unprepare; + ret = adis16480_initial_setup(indio_dev); if (ret) goto error_cleanup_buffer; @@ -873,6 +1247,8 @@ error_stop_device: adis16480_stop_device(indio_dev); error_cleanup_buffer: adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); +error_clk_disable_unprepare: + clk_disable_unprepare(st->ext_clk); return ret; } @@ -885,6 +1261,7 @@ static int adis16480_remove(struct spi_device *spi) adis16480_stop_device(indio_dev); adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); + clk_disable_unprepare(st->ext_clk); return 0; } @@ -894,13 +1271,35 @@ static const struct spi_device_id adis16480_ids[] = { { "adis16480", ADIS16480 }, { "adis16485", ADIS16485 }, { "adis16488", ADIS16488 }, + { "adis16495-1", ADIS16495_1 }, + { "adis16495-2", ADIS16495_2 }, + { "adis16495-3", ADIS16495_3 }, + { "adis16497-1", ADIS16497_1 }, + { "adis16497-2", ADIS16497_2 }, + { "adis16497-3", ADIS16497_3 }, { } }; MODULE_DEVICE_TABLE(spi, adis16480_ids); +static const struct of_device_id adis16480_of_match[] = { + { .compatible = "adi,adis16375" }, + { .compatible = "adi,adis16480" }, + { .compatible = "adi,adis16485" }, + { .compatible = "adi,adis16488" }, + { .compatible = "adi,adis16495-1" }, + { .compatible = "adi,adis16495-2" }, + { .compatible = "adi,adis16495-3" }, + { .compatible = "adi,adis16497-1" }, + { .compatible = "adi,adis16497-2" }, + { .compatible = "adi,adis16497-3" }, + { }, +}; +MODULE_DEVICE_TABLE(of, adis16480_of_match); + static struct spi_driver adis16480_driver = { .driver = { .name = "adis16480", + .of_match_table = adis16480_of_match, }, .id_table = adis16480_ids, .probe = adis16480_probe, diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c index 76643c5571aa..3a7c970568dc 100644 --- a/drivers/iio/imu/adis_buffer.c +++ b/drivers/iio/imu/adis_buffer.c @@ -20,6 +20,43 @@ #include <linux/iio/triggered_buffer.h> #include <linux/iio/imu/adis.h> +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; + u8 *tx; + + /* All but the timestamp channel */ + burst_length = (indio_dev->num_channels - 1) * sizeof(u16); + burst_length += adis->burst->extra_len; + + adis->xfer = kcalloc(2, sizeof(*adis->xfer), GFP_KERNEL); + if (!adis->xfer) + return -ENOMEM; + + adis->buffer = kzalloc(burst_length + sizeof(u16), GFP_KERNEL); + if (!adis->buffer) + return -ENOMEM; + + tx = adis->buffer + burst_length; + tx[0] = ADIS_READ_REG(adis->burst->reg_cmd); + tx[1] = 0; + + adis->xfer[0].tx_buf = tx; + adis->xfer[0].bits_per_word = 8; + adis->xfer[0].len = 2; + adis->xfer[1].rx_buf = adis->buffer; + adis->xfer[1].bits_per_word = 8; + adis->xfer[1].len = burst_length; + + spi_message_init(&adis->msg); + spi_message_add_tail(&adis->xfer[0], &adis->msg); + spi_message_add_tail(&adis->xfer[1], &adis->msg); + + return 0; +} + int adis_update_scan_mode(struct iio_dev *indio_dev, const unsigned long *scan_mask) { @@ -32,6 +69,9 @@ int adis_update_scan_mode(struct iio_dev *indio_dev, kfree(adis->xfer); kfree(adis->buffer); + if (adis->burst && adis->burst->en) + return adis_update_scan_mode_burst(indio_dev, scan_mask); + scan_count = indio_dev->scan_bytes / 2; adis->xfer = kcalloc(scan_count + 1, sizeof(*adis->xfer), GFP_KERNEL); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 650de0fefb7b..6138a6d86afb 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -796,12 +796,14 @@ static const struct iio_mount_matrix * inv_get_mount_matrix(const struct iio_dev *indio_dev, const struct iio_chan_spec *chan) { - return &((struct inv_mpu6050_state *)iio_priv(indio_dev))->orientation; + struct inv_mpu6050_state *data = iio_priv(indio_dev); + + return &data->orientation; } static const struct iio_chan_spec_ext_info inv_ext_info[] = { IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, inv_get_mount_matrix), - { }, + { } }; #define INV_MPU6050_CHAN(_type, _channel2, _index) \ @@ -1021,8 +1023,8 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, pdata = dev_get_platdata(dev); if (!pdata) { - result = of_iio_read_mount_matrix(dev, "mount-matrix", - &st->orientation); + result = iio_read_mount_matrix(dev, "mount-matrix", + &st->orientation); if (result) { dev_err(dev, "Failed to retrieve mounting matrix %d\n", result); diff --git a/drivers/iio/imu/st_lsm6dsx/Kconfig b/drivers/iio/imu/st_lsm6dsx/Kconfig index 094fd006b63d..8dcf5137b8da 100644 --- a/drivers/iio/imu/st_lsm6dsx/Kconfig +++ b/drivers/iio/imu/st_lsm6dsx/Kconfig @@ -9,7 +9,7 @@ config IIO_ST_LSM6DSX help Say yes here to build support for STMicroelectronics LSM6DSx imu sensor. Supported devices: lsm6ds3, lsm6ds3h, lsm6dsl, lsm6dsm, - ism330dlc, lsm6dso + ism330dlc, lsm6dso, lsm6dsox, asm330lhh To compile this driver as a module, choose M here: the module will be called st_lsm6dsx. diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index d1d8d07a0714..0a0c56c1701d 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -20,6 +20,8 @@ #define ST_LSM6DSM_DEV_NAME "lsm6dsm" #define ST_ISM330DLC_DEV_NAME "ism330dlc" #define ST_LSM6DSO_DEV_NAME "lsm6dso" +#define ST_ASM330LHH_DEV_NAME "asm330lhh" +#define ST_LSM6DSOX_DEV_NAME "lsm6dsox" enum st_lsm6dsx_hw_id { ST_LSM6DS3_ID, @@ -28,6 +30,8 @@ enum st_lsm6dsx_hw_id { ST_LSM6DSM_ID, ST_ISM330DLC_ID, ST_LSM6DSO_ID, + ST_ASM330LHH_ID, + ST_LSM6DSOX_ID, ST_LSM6DSX_MAX_ID, }; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index 2c0d3763405a..2da8c5ff699a 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -13,9 +13,9 @@ * (e.g. Gx, Gy, Gz, Ax, Ay, Az), then data are repeated depending on the * value of the decimation factor and ODR set for each FIFO data set. * - * LSM6DSO: The FIFO buffer can be configured to store data from gyroscope and - * accelerometer. Each sample is queued with a tag (1B) indicating data source - * (gyroscope, accelerometer, hw timer). + * LSM6DSO/LSM6DSOX/ASM330LHH: The FIFO buffer can be configured to store data + * from gyroscope and accelerometer. Each sample is queued with a tag (1B) + * indicating data source (gyroscope, accelerometer, hw timer). * * FIFO supported modes: * - BYPASS: FIFO disabled @@ -506,7 +506,7 @@ st_lsm6dsx_push_tagged_data(struct st_lsm6dsx_hw *hw, u8 tag, } /** - * st_lsm6dsx_read_tagged_fifo() - LSM6DSO read FIFO routine + * st_lsm6dsx_read_tagged_fifo() - LSM6DSO/LSM6DSOX/ASM330LHH read FIFO routine * @hw: Pointer to instance of struct st_lsm6dsx_hw. * * Read samples from the hw FIFO and push them to IIO buffers. diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 12e29dda9b98..c167ae2c21ab 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -23,7 +23,7 @@ * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 * - FIFO size: 4KB * - * - LSM6DSO + * - LSM6DSO/LSM6DSOX/ASM330LHH * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 @@ -287,6 +287,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .max_fifo_size = 512, .id = { [0] = ST_LSM6DSO_ID, + [1] = ST_LSM6DSOX_ID, }, .batch = { [ST_LSM6DSX_ID_ACC] = { @@ -347,6 +348,45 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .batch_en = BIT(3), } }, + { + .wai = 0x6b, + .max_fifo_size = 512, + .id = { + [0] = ST_ASM330LHH_ID, + }, + .batch = { + [ST_LSM6DSX_ID_ACC] = { + .addr = 0x09, + .mask = GENMASK(3, 0), + }, + [ST_LSM6DSX_ID_GYRO] = { + .addr = 0x09, + .mask = GENMASK(7, 4), + }, + }, + .fifo_ops = { + .read_fifo = st_lsm6dsx_read_tagged_fifo, + .fifo_th = { + .addr = 0x07, + .mask = GENMASK(8, 0), + }, + .fifo_diff = { + .addr = 0x3a, + .mask = GENMASK(8, 0), + }, + .th_wl = 1, + }, + .ts_settings = { + .timer_en = { + .addr = 0x19, + .mask = BIT(5), + }, + .decimator = { + .addr = 0x0a, + .mask = GENMASK(7, 6), + }, + }, + }, }; static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c index 448b7bc1e578..0bfc66d2d772 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c @@ -65,6 +65,14 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = { .compatible = "st,lsm6dso", .data = (void *)ST_LSM6DSO_ID, }, + { + .compatible = "st,asm330lhh", + .data = (void *)ST_ASM330LHH_ID, + }, + { + .compatible = "st,lsm6dsox", + .data = (void *)ST_LSM6DSOX_ID, + }, {}, }; MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match); @@ -76,6 +84,8 @@ static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = { { ST_LSM6DSM_DEV_NAME, ST_LSM6DSM_ID }, { ST_ISM330DLC_DEV_NAME, ST_ISM330DLC_ID }, { ST_LSM6DSO_DEV_NAME, ST_LSM6DSO_ID }, + { ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID }, + { ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID }, {}, }; MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table); diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c index b1df8a6973e6..9f46d4ce9fc1 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c @@ -65,6 +65,14 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = { .compatible = "st,lsm6dso", .data = (void *)ST_LSM6DSO_ID, }, + { + .compatible = "st,asm330lhh", + .data = (void *)ST_ASM330LHH_ID, + }, + { + .compatible = "st,lsm6dsox", + .data = (void *)ST_LSM6DSOX_ID, + }, {}, }; MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match); @@ -76,6 +84,8 @@ static const struct spi_device_id st_lsm6dsx_spi_id_table[] = { { ST_LSM6DSM_DEV_NAME, ST_LSM6DSM_ID }, { ST_ISM330DLC_DEV_NAME, ST_ISM330DLC_ID }, { ST_LSM6DSO_DEV_NAME, ST_LSM6DSO_ID }, + { ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID }, + { ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID }, {}, }; MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table); |