From 92092c07b83220bdb9b9cdd9141c9479d469160e Mon Sep 17 00:00:00 2001 From: Milan Misic Date: Wed, 25 Mar 2026 22:31:09 +0100 Subject: Actually bump the version everywhere this time, minor postinst fixes --- usr/src/st-lsm6dsx-shift13mi-0.1/Makefile | 2 - usr/src/st-lsm6dsx-shift13mi-0.1/dkms.conf | 14 - usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx.h | 572 ---- .../st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_buffer.c | 872 ------ usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_core.c | 2808 -------------------- usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_i2c.c | 197 -- usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_shub.c | 922 ------- 7 files changed, 5387 deletions(-) delete mode 100644 usr/src/st-lsm6dsx-shift13mi-0.1/Makefile delete mode 100644 usr/src/st-lsm6dsx-shift13mi-0.1/dkms.conf delete mode 100644 usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx.h delete mode 100644 usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_buffer.c delete mode 100644 usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_core.c delete mode 100644 usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_i2c.c delete mode 100644 usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_shub.c (limited to 'usr/src/st-lsm6dsx-shift13mi-0.1') diff --git a/usr/src/st-lsm6dsx-shift13mi-0.1/Makefile b/usr/src/st-lsm6dsx-shift13mi-0.1/Makefile deleted file mode 100644 index 787d987..0000000 --- a/usr/src/st-lsm6dsx-shift13mi-0.1/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-m += st_lsm6dsx.o st_lsm6dsx_i2c.o -st_lsm6dsx-objs := st_lsm6dsx_core.o st_lsm6dsx_buffer.o st_lsm6dsx_shub.o diff --git a/usr/src/st-lsm6dsx-shift13mi-0.1/dkms.conf b/usr/src/st-lsm6dsx-shift13mi-0.1/dkms.conf deleted file mode 100644 index bb13d3b..0000000 --- a/usr/src/st-lsm6dsx-shift13mi-0.1/dkms.conf +++ /dev/null @@ -1,14 +0,0 @@ -PACKAGE_NAME="st-lsm6dsx-shift13mi" -PACKAGE_VERSION="0.1" - -BUILT_MODULE_NAME[0]="st_lsm6dsx_i2c" - -BUILT_MODULE_LOCATION[0]="" - -DEST_MODULE_LOCATION[0]="/kernel/drivers/iio/imu/st_lsm6dsx/" - -AUTOINSTALL="yes" - -MAKE="make -C /usr/lib/modules/${kernelver}/build M=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build" -CLEAN="make -C /usr/lib/modules/${kernelver}/build M=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build clean" - diff --git a/usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx.h b/usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx.h deleted file mode 100644 index 6405a53..0000000 --- a/usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx.h +++ /dev/null @@ -1,572 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * STMicroelectronics st_lsm6dsx sensor driver - * - * Copyright 2016 STMicroelectronics Inc. - * - * Lorenzo Bianconi - * Denis Ciocca - */ - -#ifndef ST_LSM6DSX_H -#define ST_LSM6DSX_H - -#include -#include -#include - -#define ST_LSM6DS3_DEV_NAME "lsm6ds3" -#define ST_LSM6DS3H_DEV_NAME "lsm6ds3h" -#define ST_LSM6DSL_DEV_NAME "lsm6dsl" -#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" -#define ST_LSM6DSR_DEV_NAME "lsm6dsr" -#define ST_LSM6DS3TRC_DEV_NAME "lsm6ds3tr-c" -#define ST_ISM330DHCX_DEV_NAME "ism330dhcx" -#define ST_LSM9DS1_DEV_NAME "lsm9ds1-imu" -#define ST_LSM6DS0_DEV_NAME "lsm6ds0" -#define ST_LSM6DSRX_DEV_NAME "lsm6dsrx" -#define ST_LSM6DST_DEV_NAME "lsm6dst" -#define ST_LSM6DSOP_DEV_NAME "lsm6dsop" -#define ST_ASM330LHHX_DEV_NAME "asm330lhhx" -#define ST_LSM6DSTX_DEV_NAME "lsm6dstx" -#define ST_LSM6DSV_DEV_NAME "lsm6dsv" -#define ST_LSM6DSV16X_DEV_NAME "lsm6dsv16x" -#define ST_LSM6DSO16IS_DEV_NAME "lsm6dso16is" -#define ST_ISM330IS_DEV_NAME "ism330is" -#define ST_ASM330LHB_DEV_NAME "asm330lhb" -#define ST_ASM330LHHXG1_DEV_NAME "asm330lhhxg1" - -enum st_lsm6dsx_hw_id { - ST_LSM6DS3_ID = 1, - ST_LSM6DS3H_ID, - ST_LSM6DSL_ID, - ST_LSM6DSM_ID, - ST_ISM330DLC_ID, - ST_LSM6DSO_ID, - ST_ASM330LHH_ID, - ST_LSM6DSOX_ID, - ST_LSM6DSR_ID, - ST_LSM6DS3TRC_ID, - ST_ISM330DHCX_ID, - ST_LSM9DS1_ID, - ST_LSM6DS0_ID, - ST_LSM6DSRX_ID, - ST_LSM6DST_ID, - ST_LSM6DSOP_ID, - ST_ASM330LHHX_ID, - ST_LSM6DSTX_ID, - ST_LSM6DSV_ID, - ST_LSM6DSV16X_ID, - ST_LSM6DSO16IS_ID, - ST_ISM330IS_ID, - ST_ASM330LHB_ID, - ST_ASM330LHHXG1_ID, - ST_LSM6DSX_MAX_ID, -}; - -#define ST_LSM6DSX_BUFF_SIZE 512 -#define ST_LSM6DSX_CHAN_SIZE 2 -#define ST_LSM6DSX_SAMPLE_SIZE 6 -#define ST_LSM6DSX_TAG_SIZE 1 -#define ST_LSM6DSX_TAGGED_SAMPLE_SIZE (ST_LSM6DSX_SAMPLE_SIZE + \ - ST_LSM6DSX_TAG_SIZE) -#define ST_LSM6DSX_MAX_WORD_LEN ((32 / ST_LSM6DSX_SAMPLE_SIZE) * \ - ST_LSM6DSX_SAMPLE_SIZE) -#define ST_LSM6DSX_MAX_TAGGED_WORD_LEN ((32 / ST_LSM6DSX_TAGGED_SAMPLE_SIZE) \ - * ST_LSM6DSX_TAGGED_SAMPLE_SIZE) -#define ST_LSM6DSX_SHIFT_VAL(val, mask) (((val) << __ffs(mask)) & (mask)) - -#define ST_LSM6DSX_CHANNEL_ACC(chan_type, addr, mod, scan_idx) \ -{ \ - .type = chan_type, \ - .address = addr, \ - .modified = 1, \ - .channel2 = mod, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ - .scan_index = scan_idx, \ - .scan_type = { \ - .sign = 's', \ - .realbits = 16, \ - .storagebits = 16, \ - .endianness = IIO_LE, \ - }, \ - .event_spec = &st_lsm6dsx_event, \ - .ext_info = st_lsm6dsx_ext_info, \ - .num_event_specs = 1, \ -} - -#define ST_LSM6DSX_CHANNEL(chan_type, addr, mod, scan_idx) \ -{ \ - .type = chan_type, \ - .address = addr, \ - .modified = 1, \ - .channel2 = mod, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ - .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ - .scan_index = scan_idx, \ - .scan_type = { \ - .sign = 's', \ - .realbits = 16, \ - .storagebits = 16, \ - .endianness = IIO_LE, \ - }, \ - .ext_info = st_lsm6dsx_ext_info, \ -} - -struct st_lsm6dsx_reg { - u8 addr; - u8 mask; -}; - -struct st_lsm6dsx_sensor; -struct st_lsm6dsx_hw; - -struct st_lsm6dsx_odr { - u32 milli_hz; - u8 val; -}; - -#define ST_LSM6DSX_ODR_LIST_SIZE 8 -struct st_lsm6dsx_odr_table_entry { - struct st_lsm6dsx_reg reg; - - struct st_lsm6dsx_odr odr_avl[ST_LSM6DSX_ODR_LIST_SIZE]; - int odr_len; -}; - -struct st_lsm6dsx_samples_to_discard { - struct { - u32 milli_hz; - u16 samples; - } val[ST_LSM6DSX_ODR_LIST_SIZE]; -}; - -struct st_lsm6dsx_fs { - u32 gain; - u8 val; -}; - -#define ST_LSM6DSX_FS_LIST_SIZE 4 -struct st_lsm6dsx_fs_table_entry { - struct st_lsm6dsx_reg reg; - - struct st_lsm6dsx_fs fs_avl[ST_LSM6DSX_FS_LIST_SIZE]; - int fs_len; -}; - -/** - * struct st_lsm6dsx_fifo_ops - ST IMU FIFO settings - * @update_fifo: Update FIFO configuration callback. - * @read_fifo: Read FIFO callback. - * @fifo_th: FIFO threshold register info (addr + mask). - * @fifo_diff: FIFO diff status register info (addr + mask). - * @max_size: Sensor max fifo length in FIFO words. - * @th_wl: FIFO threshold word length. - */ -struct st_lsm6dsx_fifo_ops { - int (*update_fifo)(struct st_lsm6dsx_sensor *sensor, bool enable); - int (*read_fifo)(struct st_lsm6dsx_hw *hw); - struct { - u8 addr; - u16 mask; - } fifo_th; - struct { - u8 addr; - u16 mask; - } fifo_diff; - u16 max_size; - u8 th_wl; -}; - -/** - * struct st_lsm6dsx_hw_ts_settings - ST IMU hw timer settings - * @timer_en: Hw timer enable register info (addr + mask). - * @hr_timer: Hw timer resolution register info (addr + mask). - * @fifo_en: Hw timer FIFO enable register info (addr + mask). - * @decimator: Hw timer FIFO decimator register info (addr + mask). - * @freq_fine: Difference in % of ODR with respect to the typical. - * @ts_sensitivity: Nominal timestamp sensitivity. - * @ts_trim_coeff: Coefficient for calculating the calibrated timestamp gain. - * This coefficient comes into play when linearizing the formula - * used to calculate the calibrated timestamp (please see the - * relevant formula in the AN for the specific IMU). - * For example, in the case of LSM6DSO we have: - * - * 1 / (1 + x) ~= 1 - x (Taylor’s Series) - * ttrim[s] = 1 / (40000 * (1 + 0.0015 * val)) (from AN5192) - * ttrim[ns] ~= 25000 - 37.5 * val - * ttrim[ns] ~= 25000 - (37500 * val) / 1000 - * - * so, replacing ts_sensitivity = 25000 and - * ts_trim_coeff = 37500 - * - * ttrim[ns] ~= ts_sensitivity - (ts_trim_coeff * val) / 1000 - */ -struct st_lsm6dsx_hw_ts_settings { - struct st_lsm6dsx_reg timer_en; - struct st_lsm6dsx_reg hr_timer; - struct st_lsm6dsx_reg fifo_en; - struct st_lsm6dsx_reg decimator; - u8 freq_fine; - u16 ts_sensitivity; - u16 ts_trim_coeff; -}; - -/** - * struct st_lsm6dsx_shub_settings - ST IMU hw i2c controller settings - * @page_mux: register page mux info (addr + mask). - * @master_en: master config register info (addr + mask). - * @pullup_en: i2c controller pull-up register info (addr + mask). - * @aux_sens: aux sensor register info (addr + mask). - * @wr_once: write_once register info (addr + mask). - * @emb_func: embedded function register info (addr + mask). - * @num_ext_dev: max number of slave devices. - * @shub_out: sensor hub first output register info. - * @slv0_addr: slave0 address in secondary page. - * @dw_slv0_addr: slave0 write register address in secondary page. - * @batch_en: Enable/disable FIFO batching. - * @pause: controller pause value. - */ -struct st_lsm6dsx_shub_settings { - struct st_lsm6dsx_reg page_mux; - struct { - bool sec_page; - u8 addr; - u8 mask; - } master_en; - struct { - bool sec_page; - u8 addr; - u8 mask; - } pullup_en; - struct st_lsm6dsx_reg aux_sens; - struct st_lsm6dsx_reg wr_once; - struct st_lsm6dsx_reg emb_func; - u8 num_ext_dev; - struct { - bool sec_page; - u8 addr; - } shub_out; - u8 slv0_addr; - u8 dw_slv0_addr; - u8 batch_en; - u8 pause; -}; - -struct st_lsm6dsx_event_settings { - struct st_lsm6dsx_reg enable_reg; - struct st_lsm6dsx_reg wakeup_reg; - u8 wakeup_src_reg; - u8 wakeup_src_status_mask; - u8 wakeup_src_z_mask; - u8 wakeup_src_y_mask; - u8 wakeup_src_x_mask; -}; - -enum st_lsm6dsx_sensor_id { - ST_LSM6DSX_ID_GYRO, - ST_LSM6DSX_ID_ACC, - ST_LSM6DSX_ID_EXT0, - ST_LSM6DSX_ID_EXT1, - ST_LSM6DSX_ID_EXT2, - ST_LSM6DSX_ID_MAX -}; - -enum st_lsm6dsx_ext_sensor_id { - ST_LSM6DSX_ID_MAGN, -}; - -/** - * struct st_lsm6dsx_ext_dev_settings - i2c controller slave settings - * @i2c_addr: I2c slave address list. - * @wai: Wai address info. - * @id: external sensor id. - * @odr_table: Output data rate of the sensor [Hz]. - * @fs_table: Configured sensor sensitivity table depending on full scale. - * @temp_comp: Temperature compensation register info (addr + mask). - * @pwr_table: Power on register info (addr + mask). - * @off_canc: Offset cancellation register info (addr + mask). - * @bdu: Block data update register info (addr + mask). - * @out: Output register info. - */ -struct st_lsm6dsx_ext_dev_settings { - u8 i2c_addr[2]; - struct { - u8 addr; - u8 val; - } wai; - enum st_lsm6dsx_ext_sensor_id id; - struct st_lsm6dsx_odr_table_entry odr_table; - struct st_lsm6dsx_fs_table_entry fs_table; - struct st_lsm6dsx_reg temp_comp; - struct { - struct st_lsm6dsx_reg reg; - u8 off_val; - u8 on_val; - } pwr_table; - struct st_lsm6dsx_reg off_canc; - struct st_lsm6dsx_reg bdu; - struct { - u8 addr; - u8 len; - } out; -}; - -/** - * struct st_lsm6dsx_settings - ST IMU sensor settings - * @reset: register address for reset. - * @boot: register address for boot. - * @bdu: register address for Block Data Update. - * @id: List of hw id/device name supported by the driver configuration. - * @channels: IIO channels supported by the device. - * @irq_config: interrupts related registers. - * @drdy_mask: register info for data-ready mask (addr + mask). - * @odr_table: Hw sensors odr table (Hz + val). - * @samples_to_discard: Number of samples to discard for filters settling time. - * @fs_table: Hw sensors gain table (gain + val). - * @decimator: List of decimator register info (addr + mask). - * @batch: List of FIFO batching register info (addr + mask). - * @fifo_ops: Sensor hw FIFO parameters. - * @ts_settings: Hw timer related settings. - * @shub_settings: i2c controller related settings. - */ -struct st_lsm6dsx_settings { - struct st_lsm6dsx_reg reset; - struct st_lsm6dsx_reg boot; - struct st_lsm6dsx_reg bdu; - struct { - enum st_lsm6dsx_hw_id hw_id; - const char *name; - u8 wai; - } id[ST_LSM6DSX_MAX_ID]; - struct { - const struct iio_chan_spec *chan; - int len; - } channels[2]; - struct { - struct st_lsm6dsx_reg irq1; - struct st_lsm6dsx_reg irq2; - struct st_lsm6dsx_reg irq1_func; - struct st_lsm6dsx_reg irq2_func; - struct st_lsm6dsx_reg lir; - struct st_lsm6dsx_reg clear_on_read; - struct st_lsm6dsx_reg hla; - struct st_lsm6dsx_reg od; - } irq_config; - struct st_lsm6dsx_reg drdy_mask; - struct st_lsm6dsx_odr_table_entry odr_table[2]; - struct st_lsm6dsx_samples_to_discard samples_to_discard[2]; - struct st_lsm6dsx_fs_table_entry fs_table[2]; - struct st_lsm6dsx_reg decimator[ST_LSM6DSX_ID_MAX]; - struct st_lsm6dsx_reg batch[2]; - struct st_lsm6dsx_fifo_ops fifo_ops; - struct st_lsm6dsx_hw_ts_settings ts_settings; - struct st_lsm6dsx_shub_settings shub_settings; - struct st_lsm6dsx_event_settings event_settings; -}; - -enum st_lsm6dsx_fifo_mode { - ST_LSM6DSX_FIFO_BYPASS = 0x0, - ST_LSM6DSX_FIFO_CONT = 0x6, -}; - -/** - * struct st_lsm6dsx_sensor - ST IMU sensor instance - * @name: Sensor name. - * @id: Sensor identifier. - * @hw: Pointer to instance of struct st_lsm6dsx_hw. - * @gain: Configured sensor sensitivity. - * @odr: Output data rate of the sensor [mHz]. - * hwfifo_odr_mHz: Batch data rate for hardware FIFO [mHz] - * @samples_to_discard: Number of samples to discard for filters settling time. - * @watermark: Sensor watermark level. - * @decimator: Sensor decimation factor. - * @sip: Number of samples in a given pattern. - * @ts_ref: Sensor timestamp reference for hw one. - * @ext_info: Sensor settings if it is connected to i2c controller - */ -struct st_lsm6dsx_sensor { - char name[32]; - enum st_lsm6dsx_sensor_id id; - struct st_lsm6dsx_hw *hw; - - u32 gain; - u32 odr; - u32 hwfifo_odr_mHz; - - u16 samples_to_discard; - u16 watermark; - u8 decimator; - u8 sip; - s64 ts_ref; - - struct { - const struct st_lsm6dsx_ext_dev_settings *settings; - u32 slv_odr; - u8 addr; - } ext_info; -}; - -/** - * struct st_lsm6dsx_hw - ST IMU MEMS hw instance - * @dev: Pointer to instance of struct device (I2C or SPI). - * @regmap: Register map of the device. - * @irq: Device interrupt line (I2C or SPI). - * @fifo_lock: Mutex to prevent concurrent access to the hw FIFO. - * @conf_lock: Mutex to prevent concurrent FIFO configuration update. - * @page_lock: Mutex to prevent concurrent memory page configuration. - * @suspend_mask: Suspended sensor bitmask. - * @enable_mask: Enabled sensor bitmask. - * @fifo_mask: Enabled hw FIFO bitmask. - * @ts_gain: Hw timestamp rate after internal calibration. - * @ts_sip: Total number of timestamp samples in a given pattern. - * @sip: Total number of samples (acc/gyro/ts) in a given pattern. - * @buff: Device read buffer. - * @irq_routing: pointer to interrupt routing configuration. - * @event_threshold: wakeup event threshold. - * @enable_event: enabled event bitmask. - * @iio_devs: Pointers to acc/gyro iio_dev instances. - * @settings: Pointer to the specific sensor settings in use. - * @orientation: sensor chip orientation relative to main hardware. - * @scan: Temporary buffers used to align data before iio_push_to_buffers() - */ -struct st_lsm6dsx_hw { - struct device *dev; - struct regmap *regmap; - int irq; - - struct mutex fifo_lock; - struct mutex conf_lock; - struct mutex page_lock; - - u8 suspend_mask; - u8 enable_mask; - u8 fifo_mask; - s64 ts_gain; - u8 ts_sip; - u8 sip; - - const struct st_lsm6dsx_reg *irq_routing; - u8 event_threshold; - u8 enable_event; - - u8 *buff; - - struct iio_dev *iio_devs[ST_LSM6DSX_ID_MAX]; - - const struct st_lsm6dsx_settings *settings; - - struct iio_mount_matrix orientation; - /* Ensure natural alignment of buffer elements */ - struct { - __le16 channels[3]; - aligned_s64 ts; - } scan[ST_LSM6DSX_ID_MAX]; -}; - -static __maybe_unused const struct iio_event_spec st_lsm6dsx_event = { - .type = IIO_EV_TYPE_THRESH, - .dir = IIO_EV_DIR_EITHER, - .mask_separate = BIT(IIO_EV_INFO_VALUE) | - BIT(IIO_EV_INFO_ENABLE) -}; - -static __maybe_unused const unsigned long st_lsm6dsx_available_scan_masks[] = { - 0x7, 0x0, -}; - -extern const struct dev_pm_ops st_lsm6dsx_pm_ops; - -int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, - struct regmap *regmap); -int st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor, - bool enable); -int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw); -int st_lsm6dsx_set_watermark(struct iio_dev *iio_dev, unsigned int val); -int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, - u16 watermark); -int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable); -int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw); -int st_lsm6dsx_resume_fifo(struct st_lsm6dsx_hw *hw); -int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw); -int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw); -int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u32 odr, u8 *val); -int st_lsm6dsx_shub_probe(struct st_lsm6dsx_hw *hw, const char *name); -int st_lsm6dsx_shub_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable); -int st_lsm6dsx_shub_read_output(struct st_lsm6dsx_hw *hw, u8 *data, int len); -int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable); - -static inline int -st_lsm6dsx_update_bits_locked(struct st_lsm6dsx_hw *hw, unsigned int addr, - unsigned int mask, unsigned int val) -{ - int err; - - mutex_lock(&hw->page_lock); - err = regmap_update_bits(hw->regmap, addr, mask, val); - mutex_unlock(&hw->page_lock); - - return err; -} - -static inline int -st_lsm6dsx_read_locked(struct st_lsm6dsx_hw *hw, unsigned int addr, - void *val, unsigned int len) -{ - int err; - - mutex_lock(&hw->page_lock); - err = regmap_bulk_read(hw->regmap, addr, val, len); - mutex_unlock(&hw->page_lock); - - return err; -} - -static inline int -st_lsm6dsx_write_locked(struct st_lsm6dsx_hw *hw, unsigned int addr, - unsigned int val) -{ - int err; - - mutex_lock(&hw->page_lock); - err = regmap_write(hw->regmap, addr, val); - mutex_unlock(&hw->page_lock); - - return err; -} - -static inline const struct iio_mount_matrix * -st_lsm6dsx_get_mount_matrix(const struct iio_dev *iio_dev, - const struct iio_chan_spec *chan) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); - struct st_lsm6dsx_hw *hw = sensor->hw; - - return &hw->orientation; -} - -static inline int -st_lsm6dsx_device_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable) -{ - if (sensor->id == ST_LSM6DSX_ID_EXT0 || - sensor->id == ST_LSM6DSX_ID_EXT1 || - sensor->id == ST_LSM6DSX_ID_EXT2) - return st_lsm6dsx_shub_set_enable(sensor, enable); - - return st_lsm6dsx_sensor_set_enable(sensor, enable); -} - -static const -struct iio_chan_spec_ext_info __maybe_unused st_lsm6dsx_ext_info[] = { - IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_lsm6dsx_get_mount_matrix), - { } -}; - -#endif /* ST_LSM6DSX_H */ diff --git a/usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_buffer.c b/usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_buffer.c deleted file mode 100644 index 55d8777..0000000 --- a/usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_buffer.c +++ /dev/null @@ -1,872 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * STMicroelectronics st_lsm6dsx FIFO buffer library driver - * - * Pattern FIFO: - * The FIFO buffer can be configured to store data from gyroscope and - * accelerometer. Samples are queued without any tag according to a - * specific pattern based on 'FIFO data sets' (6 bytes each): - * - 1st data set is reserved for gyroscope data - * - 2nd data set is reserved for accelerometer data - * The FIFO pattern changes depending on the ODRs and decimation factors - * assigned to the FIFO data sets. The first sequence of data stored in FIFO - * buffer contains the data of all the enabled FIFO data sets - * (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. - * - * Supported devices: - * - ISM330DLC - * - LSM6DS3 - * - LSM6DS3H - * - LSM6DS3TR-C - * - LSM6DSL - * - LSM6DSM - * - * Tagged FIFO: - * 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). - * - * Supported devices: - * - ASM330LHB - * - ASM330LHH - * - ASM330LHHX - * - ASM330LHHXG1 - * - ISM330DHCX - * - LSM6DSO - * - LSM6DSOP - * - LSM6DSOX - * - LSM6DSR - * - LSM6DSRX - * - LSM6DST - * - LSM6DSTX - * - LSM6DSV - * - * FIFO supported modes: - * - BYPASS: FIFO disabled - * - CONTINUOUS: FIFO enabled. When the buffer is full, the FIFO index - * restarts from the beginning and the oldest sample is overwritten - * - * Copyright 2016 STMicroelectronics Inc. - * - * Lorenzo Bianconi - * Denis Ciocca - */ -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "st_lsm6dsx.h" - -#define ST_LSM6DSX_REG_FIFO_MODE_ADDR 0x0a -#define ST_LSM6DSX_FIFO_MODE_MASK GENMASK(2, 0) -#define ST_LSM6DSX_FIFO_ODR_MASK GENMASK(6, 3) -#define ST_LSM6DSX_FIFO_EMPTY_MASK BIT(12) -#define ST_LSM6DSX_REG_FIFO_OUTL_ADDR 0x3e -#define ST_LSM6DSX_REG_FIFO_OUT_TAG_ADDR 0x78 -#define ST_LSM6DSX_REG_TS_RESET_ADDR 0x42 - -#define ST_LSM6DSX_MAX_FIFO_ODR_VAL 0x08 - -#define ST_LSM6DSX_TS_RESET_VAL 0xaa - -struct st_lsm6dsx_decimator_entry { - u8 decimator; - u8 val; -}; - -enum st_lsm6dsx_fifo_tag { - ST_LSM6DSX_GYRO_TAG = 0x01, - ST_LSM6DSX_ACC_TAG = 0x02, - ST_LSM6DSX_TS_TAG = 0x04, - ST_LSM6DSX_EXT0_TAG = 0x0f, - ST_LSM6DSX_EXT1_TAG = 0x10, - ST_LSM6DSX_EXT2_TAG = 0x11, -}; - -static const -struct st_lsm6dsx_decimator_entry st_lsm6dsx_decimator_table[] = { - { 0, 0x0 }, - { 1, 0x1 }, - { 2, 0x2 }, - { 3, 0x3 }, - { 4, 0x4 }, - { 8, 0x5 }, - { 16, 0x6 }, - { 32, 0x7 }, -}; - -static int -st_lsm6dsx_get_decimator_val(struct st_lsm6dsx_sensor *sensor, u32 max_odr) -{ - const int max_size = ARRAY_SIZE(st_lsm6dsx_decimator_table); - u32 decimator = max_odr / sensor->hwfifo_odr_mHz; - int i; - - if (decimator > 1) - decimator = round_down(decimator, 2); - - for (i = 0; i < max_size; i++) { - if (st_lsm6dsx_decimator_table[i].decimator == decimator) - break; - } - - sensor->decimator = decimator; - return i == max_size ? 0 : st_lsm6dsx_decimator_table[i].val; -} - -static void st_lsm6dsx_get_max_min_odr(struct st_lsm6dsx_hw *hw, - u32 *max_odr, u32 *min_odr) -{ - struct st_lsm6dsx_sensor *sensor; - int i; - - *max_odr = 0, *min_odr = ~0; - for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { - if (!hw->iio_devs[i]) - continue; - - sensor = iio_priv(hw->iio_devs[i]); - - if (!(hw->enable_mask & BIT(sensor->id))) - continue; - - *max_odr = max(*max_odr, sensor->hwfifo_odr_mHz); - *min_odr = min(*min_odr, sensor->hwfifo_odr_mHz); - } -} - -static u8 st_lsm6dsx_get_sip(struct st_lsm6dsx_sensor *sensor, u32 min_odr) -{ - u8 sip = sensor->hwfifo_odr_mHz / min_odr; - - return sip > 1 ? round_down(sip, 2) : sip; -} - -static int st_lsm6dsx_update_decimators(struct st_lsm6dsx_hw *hw) -{ - const struct st_lsm6dsx_reg *ts_dec_reg; - struct st_lsm6dsx_sensor *sensor; - u16 sip = 0, ts_sip = 0; - u32 max_odr, min_odr; - int err = 0, i; - u8 data; - - st_lsm6dsx_get_max_min_odr(hw, &max_odr, &min_odr); - - for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { - const struct st_lsm6dsx_reg *dec_reg; - - if (!hw->iio_devs[i]) - continue; - - sensor = iio_priv(hw->iio_devs[i]); - /* update fifo decimators and sample in pattern */ - if (hw->enable_mask & BIT(sensor->id)) { - sensor->sip = st_lsm6dsx_get_sip(sensor, min_odr); - data = st_lsm6dsx_get_decimator_val(sensor, max_odr); - } else { - sensor->sip = 0; - data = 0; - } - ts_sip = max_t(u16, ts_sip, sensor->sip); - - dec_reg = &hw->settings->decimator[sensor->id]; - if (dec_reg->addr) { - int val = ST_LSM6DSX_SHIFT_VAL(data, dec_reg->mask); - - err = st_lsm6dsx_update_bits_locked(hw, dec_reg->addr, - dec_reg->mask, - val); - if (err < 0) - return err; - } - sip += sensor->sip; - } - hw->sip = sip + ts_sip; - hw->ts_sip = ts_sip; - - /* - * update hw ts decimator if necessary. Decimator for hw timestamp - * is always 1 or 0 in order to have a ts sample for each data - * sample in FIFO - */ - ts_dec_reg = &hw->settings->ts_settings.decimator; - if (ts_dec_reg->addr) { - int val, ts_dec = !!hw->ts_sip; - - val = ST_LSM6DSX_SHIFT_VAL(ts_dec, ts_dec_reg->mask); - err = st_lsm6dsx_update_bits_locked(hw, ts_dec_reg->addr, - ts_dec_reg->mask, val); - } - return err; -} - -static int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw, - enum st_lsm6dsx_fifo_mode fifo_mode) -{ - unsigned int data; - - data = FIELD_PREP(ST_LSM6DSX_FIFO_MODE_MASK, fifo_mode); - return st_lsm6dsx_update_bits_locked(hw, ST_LSM6DSX_REG_FIFO_MODE_ADDR, - ST_LSM6DSX_FIFO_MODE_MASK, data); -} - -static int st_lsm6dsx_set_fifo_odr(struct st_lsm6dsx_sensor *sensor, - bool enable) -{ - struct st_lsm6dsx_hw *hw = sensor->hw; - const struct st_lsm6dsx_reg *batch_reg; - u8 data; - - batch_reg = &hw->settings->batch[sensor->id]; - if (batch_reg->addr) { - int val; - - if (enable) { - int err; - - err = st_lsm6dsx_check_odr(sensor, sensor->hwfifo_odr_mHz, - &data); - if (err < 0) - return err; - } else { - data = 0; - } - val = ST_LSM6DSX_SHIFT_VAL(data, batch_reg->mask); - return st_lsm6dsx_update_bits_locked(hw, batch_reg->addr, - batch_reg->mask, val); - } else { - data = hw->enable_mask ? ST_LSM6DSX_MAX_FIFO_ODR_VAL : 0; - return st_lsm6dsx_update_bits_locked(hw, - ST_LSM6DSX_REG_FIFO_MODE_ADDR, - ST_LSM6DSX_FIFO_ODR_MASK, - FIELD_PREP(ST_LSM6DSX_FIFO_ODR_MASK, - data)); - } -} - -int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, u16 watermark) -{ - u16 fifo_watermark = ~0, cur_watermark, fifo_th_mask; - struct st_lsm6dsx_hw *hw = sensor->hw; - struct st_lsm6dsx_sensor *cur_sensor; - int i, err, data; - __le16 wdata; - - if (!hw->sip) - return 0; - - for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { - if (!hw->iio_devs[i]) - continue; - - cur_sensor = iio_priv(hw->iio_devs[i]); - - if (!(hw->enable_mask & BIT(cur_sensor->id))) - continue; - - cur_watermark = (cur_sensor == sensor) ? watermark - : cur_sensor->watermark; - - fifo_watermark = min_t(u16, fifo_watermark, cur_watermark); - } - - fifo_watermark = max_t(u16, fifo_watermark, hw->sip); - fifo_watermark = (fifo_watermark / hw->sip) * hw->sip; - fifo_watermark = fifo_watermark * hw->settings->fifo_ops.th_wl; - - mutex_lock(&hw->page_lock); - err = regmap_read(hw->regmap, hw->settings->fifo_ops.fifo_th.addr + 1, - &data); - if (err < 0) - goto out; - - fifo_th_mask = hw->settings->fifo_ops.fifo_th.mask; - fifo_watermark = ((data << 8) & ~fifo_th_mask) | - (fifo_watermark & fifo_th_mask); - - wdata = cpu_to_le16(fifo_watermark); - err = regmap_bulk_write(hw->regmap, - hw->settings->fifo_ops.fifo_th.addr, - &wdata, sizeof(wdata)); -out: - mutex_unlock(&hw->page_lock); - return err; -} - -static int st_lsm6dsx_reset_hw_ts(struct st_lsm6dsx_hw *hw) -{ - struct st_lsm6dsx_sensor *sensor; - int i, err; - - /* reset hw ts counter */ - err = st_lsm6dsx_write_locked(hw, ST_LSM6DSX_REG_TS_RESET_ADDR, - ST_LSM6DSX_TS_RESET_VAL); - if (err < 0) - return err; - - for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { - if (!hw->iio_devs[i]) - continue; - - sensor = iio_priv(hw->iio_devs[i]); - /* - * store enable buffer timestamp as reference for - * hw timestamp - */ - sensor->ts_ref = iio_get_time_ns(hw->iio_devs[i]); - } - return 0; -} - -int st_lsm6dsx_resume_fifo(struct st_lsm6dsx_hw *hw) -{ - int err; - - /* reset hw ts counter */ - err = st_lsm6dsx_reset_hw_ts(hw); - if (err < 0) - return err; - - return st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT); -} - -/* - * Set max bulk read to ST_LSM6DSX_MAX_WORD_LEN/ST_LSM6DSX_MAX_TAGGED_WORD_LEN - * in order to avoid a kmalloc for each bus access - */ -static inline int st_lsm6dsx_read_block(struct st_lsm6dsx_hw *hw, u8 addr, - u8 *data, unsigned int data_len, - unsigned int max_word_len) -{ - unsigned int word_len, read_len = 0; - int err; - - while (read_len < data_len) { - word_len = min_t(unsigned int, data_len - read_len, - max_word_len); - err = st_lsm6dsx_read_locked(hw, addr, data + read_len, - word_len); - if (err < 0) - return err; - read_len += word_len; - } - return 0; -} - -#define ST_LSM6DSX_IIO_BUFF_SIZE (ALIGN(ST_LSM6DSX_SAMPLE_SIZE, \ - sizeof(s64)) + sizeof(s64)) -/** - * st_lsm6dsx_read_fifo() - hw FIFO read routine - * @hw: Pointer to instance of struct st_lsm6dsx_hw. - * - * Read samples from the hw FIFO and push them to IIO buffers. - * - * Return: Number of bytes read from the FIFO - */ -int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) -{ - struct st_lsm6dsx_sensor *acc_sensor, *gyro_sensor, *ext_sensor = NULL; - int err, sip, acc_sip, gyro_sip, ts_sip, ext_sip, read_len, offset; - u16 fifo_len, pattern_len = hw->sip * ST_LSM6DSX_SAMPLE_SIZE; - u16 fifo_diff_mask = hw->settings->fifo_ops.fifo_diff.mask; - bool reset_ts = false; - __le16 fifo_status; - s64 ts = 0; - - err = st_lsm6dsx_read_locked(hw, - hw->settings->fifo_ops.fifo_diff.addr, - &fifo_status, sizeof(fifo_status)); - if (err < 0) { - dev_err(hw->dev, "failed to read fifo status (err=%d)\n", - err); - return err; - } - - if (fifo_status & cpu_to_le16(ST_LSM6DSX_FIFO_EMPTY_MASK)) - return 0; - - if (!pattern_len) - pattern_len = ST_LSM6DSX_SAMPLE_SIZE; - - fifo_len = (le16_to_cpu(fifo_status) & fifo_diff_mask) * - ST_LSM6DSX_CHAN_SIZE; - fifo_len = (fifo_len / pattern_len) * pattern_len; - - acc_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]); - gyro_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_GYRO]); - if (hw->iio_devs[ST_LSM6DSX_ID_EXT0]) - ext_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_EXT0]); - - for (read_len = 0; read_len < fifo_len; read_len += pattern_len) { - err = st_lsm6dsx_read_block(hw, ST_LSM6DSX_REG_FIFO_OUTL_ADDR, - hw->buff, pattern_len, - ST_LSM6DSX_MAX_WORD_LEN); - if (err < 0) { - dev_err(hw->dev, - "failed to read pattern from fifo (err=%d)\n", - err); - return err; - } - - /* - * Data are written to the FIFO with a specific pattern - * depending on the configured ODRs. The first sequence of data - * stored in FIFO contains the data of all enabled sensors - * (e.g. Gx, Gy, Gz, Ax, Ay, Az, Ts), then data are repeated - * depending on the value of the decimation factor set for each - * sensor. - * - * Supposing the FIFO is storing data from gyroscope and - * accelerometer at different ODRs: - * - gyroscope ODR = 208Hz, accelerometer ODR = 104Hz - * Since the gyroscope ODR is twice the accelerometer one, the - * following pattern is repeated every 9 samples: - * - Gx, Gy, Gz, Ax, Ay, Az, Ts, Gx, Gy, Gz, Ts, Gx, .. - */ - ext_sip = ext_sensor ? ext_sensor->sip : 0; - gyro_sip = gyro_sensor->sip; - acc_sip = acc_sensor->sip; - ts_sip = hw->ts_sip; - offset = 0; - sip = 0; - - while (acc_sip > 0 || gyro_sip > 0 || ext_sip > 0) { - if (gyro_sip > 0 && !(sip % gyro_sensor->decimator)) { - memcpy(hw->scan[ST_LSM6DSX_ID_GYRO].channels, - &hw->buff[offset], - sizeof(hw->scan[ST_LSM6DSX_ID_GYRO].channels)); - offset += sizeof(hw->scan[ST_LSM6DSX_ID_GYRO].channels); - } - if (acc_sip > 0 && !(sip % acc_sensor->decimator)) { - memcpy(hw->scan[ST_LSM6DSX_ID_ACC].channels, - &hw->buff[offset], - sizeof(hw->scan[ST_LSM6DSX_ID_ACC].channels)); - offset += sizeof(hw->scan[ST_LSM6DSX_ID_ACC].channels); - } - if (ext_sip > 0 && !(sip % ext_sensor->decimator)) { - memcpy(hw->scan[ST_LSM6DSX_ID_EXT0].channels, - &hw->buff[offset], - sizeof(hw->scan[ST_LSM6DSX_ID_EXT0].channels)); - offset += sizeof(hw->scan[ST_LSM6DSX_ID_EXT0].channels); - } - - if (ts_sip-- > 0) { - u8 data[ST_LSM6DSX_SAMPLE_SIZE]; - - memcpy(data, &hw->buff[offset], sizeof(data)); - /* - * hw timestamp is 3B long and it is stored - * in FIFO using 6B as 4th FIFO data set - * according to this schema: - * B0 = ts[15:8], B1 = ts[23:16], B3 = ts[7:0] - */ - ts = data[1] << 16 | data[0] << 8 | data[3]; - /* - * check if hw timestamp engine is going to - * reset (the sensor generates an interrupt - * to signal the hw timestamp will reset in - * 1.638s) - */ - if (!reset_ts && ts >= 0xff0000) - reset_ts = true; - ts *= hw->ts_gain; - - offset += ST_LSM6DSX_SAMPLE_SIZE; - } - - if (gyro_sip > 0 && !(sip % gyro_sensor->decimator)) { - /* - * We need to discards gyro samples during - * filters settling time - */ - if (gyro_sensor->samples_to_discard > 0) - gyro_sensor->samples_to_discard--; - else - iio_push_to_buffers_with_timestamp( - hw->iio_devs[ST_LSM6DSX_ID_GYRO], - &hw->scan[ST_LSM6DSX_ID_GYRO], - gyro_sensor->ts_ref + ts); - gyro_sip--; - } - if (acc_sip > 0 && !(sip % acc_sensor->decimator)) { - /* - * We need to discards accel samples during - * filters settling time - */ - if (acc_sensor->samples_to_discard > 0) - acc_sensor->samples_to_discard--; - else - iio_push_to_buffers_with_timestamp( - hw->iio_devs[ST_LSM6DSX_ID_ACC], - &hw->scan[ST_LSM6DSX_ID_ACC], - acc_sensor->ts_ref + ts); - acc_sip--; - } - if (ext_sip > 0 && !(sip % ext_sensor->decimator)) { - iio_push_to_buffers_with_timestamp( - hw->iio_devs[ST_LSM6DSX_ID_EXT0], - &hw->scan[ST_LSM6DSX_ID_EXT0], - ext_sensor->ts_ref + ts); - ext_sip--; - } - sip++; - } - } - - if (unlikely(reset_ts)) { - err = st_lsm6dsx_reset_hw_ts(hw); - if (err < 0) { - dev_err(hw->dev, "failed to reset hw ts (err=%d)\n", - err); - return err; - } - } - return read_len; -} - -#define ST_LSM6DSX_INVALID_SAMPLE 0x7ffd -static int -st_lsm6dsx_push_tagged_data(struct st_lsm6dsx_hw *hw, u8 tag, - u8 *data, s64 ts) -{ - s16 val = le16_to_cpu(*(__le16 *)data); - struct st_lsm6dsx_sensor *sensor; - struct iio_dev *iio_dev; - - /* invalid sample during bootstrap phase */ - if (val >= ST_LSM6DSX_INVALID_SAMPLE) - return -EINVAL; - - /* - * EXT_TAG are managed in FIFO fashion so ST_LSM6DSX_EXT0_TAG - * corresponds to the first enabled channel, ST_LSM6DSX_EXT1_TAG - * to the second one and ST_LSM6DSX_EXT2_TAG to the last enabled - * channel - */ - switch (tag) { - case ST_LSM6DSX_GYRO_TAG: - iio_dev = hw->iio_devs[ST_LSM6DSX_ID_GYRO]; - break; - case ST_LSM6DSX_ACC_TAG: - iio_dev = hw->iio_devs[ST_LSM6DSX_ID_ACC]; - break; - case ST_LSM6DSX_EXT0_TAG: - if (hw->enable_mask & BIT(ST_LSM6DSX_ID_EXT0)) - iio_dev = hw->iio_devs[ST_LSM6DSX_ID_EXT0]; - else if (hw->enable_mask & BIT(ST_LSM6DSX_ID_EXT1)) - iio_dev = hw->iio_devs[ST_LSM6DSX_ID_EXT1]; - else - iio_dev = hw->iio_devs[ST_LSM6DSX_ID_EXT2]; - break; - case ST_LSM6DSX_EXT1_TAG: - if ((hw->enable_mask & BIT(ST_LSM6DSX_ID_EXT0)) && - (hw->enable_mask & BIT(ST_LSM6DSX_ID_EXT1))) - iio_dev = hw->iio_devs[ST_LSM6DSX_ID_EXT1]; - else - iio_dev = hw->iio_devs[ST_LSM6DSX_ID_EXT2]; - break; - case ST_LSM6DSX_EXT2_TAG: - iio_dev = hw->iio_devs[ST_LSM6DSX_ID_EXT2]; - break; - default: - return -EINVAL; - } - - sensor = iio_priv(iio_dev); - iio_push_to_buffers_with_timestamp(iio_dev, data, - ts + sensor->ts_ref); - - return 0; -} - -/** - * st_lsm6dsx_read_tagged_fifo() - tagged hw FIFO read routine - * @hw: Pointer to instance of struct st_lsm6dsx_hw. - * - * Read samples from the hw FIFO and push them to IIO buffers. - * - * Return: Number of bytes read from the FIFO - */ -int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw) -{ - u16 pattern_len = hw->sip * ST_LSM6DSX_TAGGED_SAMPLE_SIZE; - u16 fifo_len, fifo_diff_mask; - /* - * Alignment needed as this can ultimately be passed to a - * call to iio_push_to_buffers_with_timestamp() which - * must be passed a buffer that is aligned to 8 bytes so - * as to allow insertion of a naturally aligned timestamp. - */ - u8 iio_buff[ST_LSM6DSX_IIO_BUFF_SIZE] __aligned(8); - u8 tag; - bool reset_ts = false; - int i, err, read_len; - __le16 fifo_status; - s64 ts = 0; - - err = st_lsm6dsx_read_locked(hw, - hw->settings->fifo_ops.fifo_diff.addr, - &fifo_status, sizeof(fifo_status)); - if (err < 0) { - dev_err(hw->dev, "failed to read fifo status (err=%d)\n", - err); - return err; - } - - fifo_diff_mask = hw->settings->fifo_ops.fifo_diff.mask; - fifo_len = (le16_to_cpu(fifo_status) & fifo_diff_mask) * - ST_LSM6DSX_TAGGED_SAMPLE_SIZE; - if (!fifo_len) - return 0; - - if (!pattern_len) - pattern_len = ST_LSM6DSX_TAGGED_SAMPLE_SIZE; - - for (read_len = 0; read_len < fifo_len; read_len += pattern_len) { - err = st_lsm6dsx_read_block(hw, - ST_LSM6DSX_REG_FIFO_OUT_TAG_ADDR, - hw->buff, pattern_len, - ST_LSM6DSX_MAX_TAGGED_WORD_LEN); - if (err < 0) { - dev_err(hw->dev, - "failed to read pattern from fifo (err=%d)\n", - err); - return err; - } - - for (i = 0; i < pattern_len; - i += ST_LSM6DSX_TAGGED_SAMPLE_SIZE) { - memcpy(iio_buff, &hw->buff[i + ST_LSM6DSX_TAG_SIZE], - ST_LSM6DSX_SAMPLE_SIZE); - - tag = hw->buff[i] >> 3; - if (tag == ST_LSM6DSX_TS_TAG) { - /* - * hw timestamp is 4B long and it is stored - * in FIFO according to this schema: - * B0 = ts[7:0], B1 = ts[15:8], B2 = ts[23:16], - * B3 = ts[31:24] - */ - ts = le32_to_cpu(*((__le32 *)iio_buff)); - /* - * check if hw timestamp engine is going to - * reset (the sensor generates an interrupt - * to signal the hw timestamp will reset in - * 1.638s) - */ - if (!reset_ts && ts >= 0xffff0000) - reset_ts = true; - ts *= hw->ts_gain; - } else { - st_lsm6dsx_push_tagged_data(hw, tag, iio_buff, - ts); - } - } - } - - if (unlikely(reset_ts)) { - err = st_lsm6dsx_reset_hw_ts(hw); - if (err < 0) - return err; - } - return read_len; -} - -int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw) -{ - int err; - - if (!hw->settings->fifo_ops.read_fifo) - return -ENOTSUPP; - - mutex_lock(&hw->fifo_lock); - - hw->settings->fifo_ops.read_fifo(hw); - err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_BYPASS); - - mutex_unlock(&hw->fifo_lock); - - return err; -} - -static void -st_lsm6dsx_update_samples_to_discard(struct st_lsm6dsx_sensor *sensor) -{ - const struct st_lsm6dsx_samples_to_discard *data; - struct st_lsm6dsx_hw *hw = sensor->hw; - int i; - - if (sensor->id != ST_LSM6DSX_ID_GYRO && - sensor->id != ST_LSM6DSX_ID_ACC) - return; - - /* check if drdy mask is supported in hw */ - if (hw->settings->drdy_mask.addr) - return; - - data = &hw->settings->samples_to_discard[sensor->id]; - for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++) { - if (data->val[i].milli_hz == sensor->hwfifo_odr_mHz) { - sensor->samples_to_discard = data->val[i].samples; - return; - } - } -} - -int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable) -{ - struct st_lsm6dsx_hw *hw = sensor->hw; - u8 fifo_mask; - int err; - - mutex_lock(&hw->conf_lock); - - if (enable) - fifo_mask = hw->fifo_mask | BIT(sensor->id); - else - fifo_mask = hw->fifo_mask & ~BIT(sensor->id); - - if (hw->fifo_mask) { - err = st_lsm6dsx_flush_fifo(hw); - if (err < 0) - goto out; - } - - if (enable) - st_lsm6dsx_update_samples_to_discard(sensor); - - err = st_lsm6dsx_device_set_enable(sensor, enable); - if (err < 0) - goto out; - - err = st_lsm6dsx_set_fifo_odr(sensor, enable); - if (err < 0) - goto out; - - err = st_lsm6dsx_update_decimators(hw); - if (err < 0) - goto out; - - err = st_lsm6dsx_update_watermark(sensor, sensor->watermark); - if (err < 0) - goto out; - - if (fifo_mask) { - err = st_lsm6dsx_resume_fifo(hw); - if (err < 0) - goto out; - } - - hw->fifo_mask = fifo_mask; - -out: - mutex_unlock(&hw->conf_lock); - - return err; -} - -static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); - struct st_lsm6dsx_hw *hw = sensor->hw; - - if (!hw->settings->fifo_ops.update_fifo) - return -ENOTSUPP; - - return hw->settings->fifo_ops.update_fifo(sensor, true); -} - -static int st_lsm6dsx_buffer_postdisable(struct iio_dev *iio_dev) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); - struct st_lsm6dsx_hw *hw = sensor->hw; - - if (!hw->settings->fifo_ops.update_fifo) - return -ENOTSUPP; - - return hw->settings->fifo_ops.update_fifo(sensor, false); -} - -static const struct iio_buffer_setup_ops st_lsm6dsx_buffer_ops = { - .preenable = st_lsm6dsx_buffer_preenable, - .postdisable = st_lsm6dsx_buffer_postdisable, -}; - -static ssize_t st_lsm6dsx_hwfifo_odr_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(dev_to_iio_dev(dev)); - - return sysfs_emit(buf, "%d.%03d\n", sensor->hwfifo_odr_mHz / 1000, - sensor->hwfifo_odr_mHz % 1000); -} - -static ssize_t st_lsm6dsx_hwfifo_odr_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *iio_dev = dev_to_iio_dev(dev); - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); - int integer, milli; - int ret; - u32 hwfifo_odr; - u8 data; - - if (!iio_device_claim_direct(iio_dev)) - return -EBUSY; - - ret = iio_str_to_fixpoint(buf, 100, &integer, &milli); - if (ret) - goto out; - - hwfifo_odr = integer * 1000 + milli; - ret = st_lsm6dsx_check_odr(sensor, hwfifo_odr, &data); - if (ret < 0) - goto out; - - hwfifo_odr = ret; - - /* the batch data rate must not exceed the sensor output data rate */ - if (hwfifo_odr <= sensor->odr) - sensor->hwfifo_odr_mHz = hwfifo_odr; - else - ret = -EINVAL; - -out: - iio_device_release_direct(iio_dev); - - return ret < 0 ? ret : len; -} - -static IIO_DEV_ATTR_SAMP_FREQ(0664, st_lsm6dsx_hwfifo_odr_show, st_lsm6dsx_hwfifo_odr_store); - -static const struct iio_dev_attr *st_lsm6dsx_buffer_attrs[] = { - &iio_dev_attr_sampling_frequency, - NULL -}; - -int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw) -{ - int i, ret; - - for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { - if (!hw->iio_devs[i]) - continue; - - ret = devm_iio_kfifo_buffer_setup_ext(hw->dev, hw->iio_devs[i], - &st_lsm6dsx_buffer_ops, - st_lsm6dsx_buffer_attrs); - if (ret) - return ret; - } - - return 0; -} diff --git a/usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_core.c b/usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_core.c deleted file mode 100644 index dc78227..0000000 --- a/usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_core.c +++ /dev/null @@ -1,2808 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * STMicroelectronics st_lsm6dsx sensor driver - * - * The ST LSM6DSx IMU MEMS series consists of 3D digital accelerometer - * and 3D digital gyroscope system-in-package with a digital I2C/SPI serial - * interface standard output. - * LSM6DSx IMU MEMS series has a dynamic user-selectable full-scale - * acceleration range of +-2/+-4/+-8/+-16 g and an angular rate range of - * +-125/+-245/+-500/+-1000/+-2000 dps - * LSM6DSx series has an integrated First-In-First-Out (FIFO) buffer - * allowing dynamic batching of sensor data. - * LSM9DSx series is similar but includes an additional magnetometer, handled - * by a different driver. - * - * Supported sensors: - * - * - LSM6DS3 - * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416 - * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 - * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 - * - FIFO size: 8KB - * - * - ISM330DLC - * - LSM6DS3H - * - LSM6DS3TR-C - * - LSM6DSL - * - LSM6DSM - * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416 - * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 - * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 - * - FIFO size: 4KB - * - * - ASM330LHH - * - ASM330LHHX - * - ASM330LHHXG1 - * - ISM330DHCX - * - ISM330IS - * - LSM6DSO - * - LSM6DSO16IS - * - LSM6DSOP - * - LSM6DSOX - * - LSM6DSR - * - LSM6DST - * - LSM6DSTX - * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 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 - * - * - LSM6DSV - * - LSM6DSV16X - * - Accelerometer/Gyroscope supported ODR [Hz]: 7.5, 15, 30, 60, 120, 240, - * 480, 960 - * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 - * - Gyroscope supported full-scale [dps]: +-125/+-250/+-500/+-1000/+-2000 - * - FIFO size: 3KB - * - * - LSM6DS0 - * - LSM9DS1 - * - Accelerometer supported ODR [Hz]: 10, 50, 119, 238, 476, 952 - * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 - * - Gyroscope supported ODR [Hz]: 15, 60, 119, 238, 476, 952 - * - Gyroscope supported full-scale [dps]: +-245/+-500/+-2000 - * - FIFO size: 32 - * - * Copyright 2016 STMicroelectronics Inc. - * - * Lorenzo Bianconi - * Denis Ciocca - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "st_lsm6dsx.h" - -#define ST_LSM6DSX_REG_WHOAMI_ADDR 0x0f - -static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { - ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x28, IIO_MOD_X, 0), - ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1), - ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x2c, IIO_MOD_Z, 2), - IIO_CHAN_SOFT_TIMESTAMP(3), -}; - -static const struct iio_chan_spec st_lsm6ds0_acc_channels[] = { - ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x28, IIO_MOD_X, 0), - ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1), - ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2c, IIO_MOD_Z, 2), - IIO_CHAN_SOFT_TIMESTAMP(3), -}; - -static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = { - ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x22, IIO_MOD_X, 0), - ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x24, IIO_MOD_Y, 1), - ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x26, IIO_MOD_Z, 2), - IIO_CHAN_SOFT_TIMESTAMP(3), -}; - -static const struct iio_chan_spec st_lsm6ds0_gyro_channels[] = { - ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x18, IIO_MOD_X, 0), - ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x1a, IIO_MOD_Y, 1), - ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x1c, IIO_MOD_Z, 2), - IIO_CHAN_SOFT_TIMESTAMP(3), -}; - -static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { - { - .reset = { - .addr = 0x22, - .mask = BIT(0), - }, - .boot = { - .addr = 0x22, - .mask = BIT(7), - }, - .bdu = { - .addr = 0x22, - .mask = BIT(6), - }, - .id = { - { - .hw_id = ST_LSM9DS1_ID, - .name = ST_LSM9DS1_DEV_NAME, - .wai = 0x68, - }, { - .hw_id = ST_LSM6DS0_ID, - .name = ST_LSM6DS0_DEV_NAME, - .wai = 0x68, - }, - }, - .channels = { - [ST_LSM6DSX_ID_ACC] = { - .chan = st_lsm6ds0_acc_channels, - .len = ARRAY_SIZE(st_lsm6ds0_acc_channels), - }, - [ST_LSM6DSX_ID_GYRO] = { - .chan = st_lsm6ds0_gyro_channels, - .len = ARRAY_SIZE(st_lsm6ds0_gyro_channels), - }, - }, - .odr_table = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x20, - .mask = GENMASK(7, 5), - }, - .odr_avl[0] = { 10000, 0x01 }, - .odr_avl[1] = { 50000, 0x02 }, - .odr_avl[2] = { 119000, 0x03 }, - .odr_avl[3] = { 238000, 0x04 }, - .odr_avl[4] = { 476000, 0x05 }, - .odr_avl[5] = { 952000, 0x06 }, - .odr_len = 6, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(7, 5), - }, - .odr_avl[0] = { 14900, 0x01 }, - .odr_avl[1] = { 59500, 0x02 }, - .odr_avl[2] = { 119000, 0x03 }, - .odr_avl[3] = { 238000, 0x04 }, - .odr_avl[4] = { 476000, 0x05 }, - .odr_avl[5] = { 952000, 0x06 }, - .odr_len = 6, - }, - }, - .fs_table = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x20, - .mask = GENMASK(4, 3), - }, - .fs_avl[0] = { IIO_G_TO_M_S_2(61000), 0x0 }, - .fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 }, - .fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 }, - .fs_avl[3] = { IIO_G_TO_M_S_2(732000), 0x1 }, - .fs_len = 4, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(4, 3), - }, - - .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750000), 0x0 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(70000000), 0x3 }, - .fs_len = 3, - }, - }, - .irq_config = { - .irq1 = { - .addr = 0x0c, - .mask = BIT(3), - }, - .irq2 = { - .addr = 0x0d, - .mask = BIT(3), - }, - .hla = { - .addr = 0x22, - .mask = BIT(5), - }, - .od = { - .addr = 0x22, - .mask = BIT(4), - }, - }, - .fifo_ops = { - .max_size = 32, - }, - }, - { - .reset = { - .addr = 0x12, - .mask = BIT(0), - }, - .boot = { - .addr = 0x12, - .mask = BIT(7), - }, - .bdu = { - .addr = 0x12, - .mask = BIT(6), - }, - .id = { - { - .hw_id = ST_LSM6DS3_ID, - .name = ST_LSM6DS3_DEV_NAME, - .wai = 0x69, - }, - }, - .channels = { - [ST_LSM6DSX_ID_ACC] = { - .chan = st_lsm6dsx_acc_channels, - .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), - }, - [ST_LSM6DSX_ID_GYRO] = { - .chan = st_lsm6dsx_gyro_channels, - .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), - }, - }, - .odr_table = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(7, 4), - }, - .odr_avl[0] = { 12500, 0x01 }, - .odr_avl[1] = { 26000, 0x02 }, - .odr_avl[2] = { 52000, 0x03 }, - .odr_avl[3] = { 104000, 0x04 }, - .odr_avl[4] = { 208000, 0x05 }, - .odr_avl[5] = { 416000, 0x06 }, - .odr_len = 6, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x11, - .mask = GENMASK(7, 4), - }, - .odr_avl[0] = { 12500, 0x01 }, - .odr_avl[1] = { 26000, 0x02 }, - .odr_avl[2] = { 52000, 0x03 }, - .odr_avl[3] = { 104000, 0x04 }, - .odr_avl[4] = { 208000, 0x05 }, - .odr_avl[5] = { 416000, 0x06 }, - .odr_len = 6, - }, - }, - .fs_table = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(3, 2), - }, - .fs_avl[0] = { IIO_G_TO_M_S_2(61000), 0x0 }, - .fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 }, - .fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 }, - .fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 }, - .fs_len = 4, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x11, - .mask = GENMASK(3, 2), - }, - .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750000), 0x0 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 }, - .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 }, - .fs_len = 4, - }, - }, - .irq_config = { - .irq1 = { - .addr = 0x0d, - .mask = BIT(3), - }, - .irq2 = { - .addr = 0x0e, - .mask = BIT(3), - }, - .lir = { - .addr = 0x58, - .mask = BIT(0), - }, - .irq1_func = { - .addr = 0x5e, - .mask = BIT(5), - }, - .irq2_func = { - .addr = 0x5f, - .mask = BIT(5), - }, - .hla = { - .addr = 0x12, - .mask = BIT(5), - }, - .od = { - .addr = 0x12, - .mask = BIT(4), - }, - }, - .decimator = { - [ST_LSM6DSX_ID_ACC] = { - .addr = 0x08, - .mask = GENMASK(2, 0), - }, - [ST_LSM6DSX_ID_GYRO] = { - .addr = 0x08, - .mask = GENMASK(5, 3), - }, - }, - .fifo_ops = { - .update_fifo = st_lsm6dsx_update_fifo, - .read_fifo = st_lsm6dsx_read_fifo, - .fifo_th = { - .addr = 0x06, - .mask = GENMASK(11, 0), - }, - .fifo_diff = { - .addr = 0x3a, - .mask = GENMASK(11, 0), - }, - .max_size = 1365, - .th_wl = 3, /* 1LSB = 2B */ - }, - .ts_settings = { - .timer_en = { - .addr = 0x58, - .mask = BIT(7), - }, - .hr_timer = { - .addr = 0x5c, - .mask = BIT(4), - }, - .fifo_en = { - .addr = 0x07, - .mask = BIT(7), - }, - .decimator = { - .addr = 0x09, - .mask = GENMASK(5, 3), - }, - }, - .event_settings = { - .wakeup_reg = { - .addr = 0x5B, - .mask = GENMASK(5, 0), - }, - .wakeup_src_reg = 0x1b, - .wakeup_src_status_mask = BIT(3), - .wakeup_src_z_mask = BIT(0), - .wakeup_src_y_mask = BIT(1), - .wakeup_src_x_mask = BIT(2), - }, - }, - { - .reset = { - .addr = 0x12, - .mask = BIT(0), - }, - .boot = { - .addr = 0x12, - .mask = BIT(7), - }, - .bdu = { - .addr = 0x12, - .mask = BIT(6), - }, - .id = { - { - .hw_id = ST_LSM6DS3H_ID, - .name = ST_LSM6DS3H_DEV_NAME, - .wai = 0x69, - }, - }, - .channels = { - [ST_LSM6DSX_ID_ACC] = { - .chan = st_lsm6dsx_acc_channels, - .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), - }, - [ST_LSM6DSX_ID_GYRO] = { - .chan = st_lsm6dsx_gyro_channels, - .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), - }, - }, - .odr_table = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(7, 4), - }, - .odr_avl[0] = { 12500, 0x01 }, - .odr_avl[1] = { 26000, 0x02 }, - .odr_avl[2] = { 52000, 0x03 }, - .odr_avl[3] = { 104000, 0x04 }, - .odr_avl[4] = { 208000, 0x05 }, - .odr_avl[5] = { 416000, 0x06 }, - .odr_len = 6, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x11, - .mask = GENMASK(7, 4), - }, - .odr_avl[0] = { 12500, 0x01 }, - .odr_avl[1] = { 26000, 0x02 }, - .odr_avl[2] = { 52000, 0x03 }, - .odr_avl[3] = { 104000, 0x04 }, - .odr_avl[4] = { 208000, 0x05 }, - .odr_avl[5] = { 416000, 0x06 }, - .odr_len = 6, - }, - }, - .fs_table = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(3, 2), - }, - .fs_avl[0] = { IIO_G_TO_M_S_2(61000), 0x0 }, - .fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 }, - .fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 }, - .fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 }, - .fs_len = 4, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x11, - .mask = GENMASK(3, 2), - }, - .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750000), 0x0 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 }, - .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 }, - .fs_len = 4, - }, - }, - .irq_config = { - .irq1 = { - .addr = 0x0d, - .mask = BIT(3), - }, - .irq2 = { - .addr = 0x0e, - .mask = BIT(3), - }, - .lir = { - .addr = 0x58, - .mask = BIT(0), - }, - .irq1_func = { - .addr = 0x5e, - .mask = BIT(5), - }, - .irq2_func = { - .addr = 0x5f, - .mask = BIT(5), - }, - .hla = { - .addr = 0x12, - .mask = BIT(5), - }, - .od = { - .addr = 0x12, - .mask = BIT(4), - }, - }, - .decimator = { - [ST_LSM6DSX_ID_ACC] = { - .addr = 0x08, - .mask = GENMASK(2, 0), - }, - [ST_LSM6DSX_ID_GYRO] = { - .addr = 0x08, - .mask = GENMASK(5, 3), - }, - }, - .fifo_ops = { - .update_fifo = st_lsm6dsx_update_fifo, - .read_fifo = st_lsm6dsx_read_fifo, - .fifo_th = { - .addr = 0x06, - .mask = GENMASK(11, 0), - }, - .fifo_diff = { - .addr = 0x3a, - .mask = GENMASK(11, 0), - }, - .max_size = 682, - .th_wl = 3, /* 1LSB = 2B */ - }, - .ts_settings = { - .timer_en = { - .addr = 0x58, - .mask = BIT(7), - }, - .hr_timer = { - .addr = 0x5c, - .mask = BIT(4), - }, - .fifo_en = { - .addr = 0x07, - .mask = BIT(7), - }, - .decimator = { - .addr = 0x09, - .mask = GENMASK(5, 3), - }, - }, - .event_settings = { - .wakeup_reg = { - .addr = 0x5B, - .mask = GENMASK(5, 0), - }, - .wakeup_src_reg = 0x1b, - .wakeup_src_status_mask = BIT(3), - .wakeup_src_z_mask = BIT(0), - .wakeup_src_y_mask = BIT(1), - .wakeup_src_x_mask = BIT(2), - }, - }, - { - .reset = { - .addr = 0x12, - .mask = BIT(0), - }, - .boot = { - .addr = 0x12, - .mask = BIT(7), - }, - .bdu = { - .addr = 0x12, - .mask = BIT(6), - }, - .id = { - { - .hw_id = ST_LSM6DSL_ID, - .name = ST_LSM6DSL_DEV_NAME, - .wai = 0x6a, - }, { - .hw_id = ST_LSM6DSM_ID, - .name = ST_LSM6DSM_DEV_NAME, - .wai = 0x6a, - }, { - .hw_id = ST_ISM330DLC_ID, - .name = ST_ISM330DLC_DEV_NAME, - .wai = 0x6a, - }, { - .hw_id = ST_LSM6DS3TRC_ID, - .name = ST_LSM6DS3TRC_DEV_NAME, - .wai = 0x6a, - }, - }, - .channels = { - [ST_LSM6DSX_ID_ACC] = { - .chan = st_lsm6dsx_acc_channels, - .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), - }, - [ST_LSM6DSX_ID_GYRO] = { - .chan = st_lsm6dsx_gyro_channels, - .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), - }, - }, - .odr_table = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(7, 4), - }, - .odr_avl[0] = { 12500, 0x01 }, - .odr_avl[1] = { 26000, 0x02 }, - .odr_avl[2] = { 52000, 0x03 }, - .odr_avl[3] = { 104000, 0x04 }, - .odr_avl[4] = { 208000, 0x05 }, - .odr_avl[5] = { 416000, 0x06 }, - .odr_len = 6, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x11, - .mask = GENMASK(7, 4), - }, - .odr_avl[0] = { 12500, 0x01 }, - .odr_avl[1] = { 26000, 0x02 }, - .odr_avl[2] = { 52000, 0x03 }, - .odr_avl[3] = { 104000, 0x04 }, - .odr_avl[4] = { 208000, 0x05 }, - .odr_avl[5] = { 416000, 0x06 }, - .odr_len = 6, - }, - }, - .fs_table = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(3, 2), - }, - .fs_avl[0] = { IIO_G_TO_M_S_2(61000), 0x0 }, - .fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 }, - .fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 }, - .fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 }, - .fs_len = 4, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x11, - .mask = GENMASK(3, 2), - }, - .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750000), 0x0 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 }, - .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 }, - .fs_len = 4, - }, - }, - .samples_to_discard = { - [ST_LSM6DSX_ID_ACC] = { - .val[0] = { 12500, 1 }, - .val[1] = { 26000, 1 }, - .val[2] = { 52000, 1 }, - .val[3] = { 104000, 2 }, - .val[4] = { 208000, 2 }, - .val[5] = { 416000, 2 }, - }, - [ST_LSM6DSX_ID_GYRO] = { - .val[0] = { 12500, 2 }, - .val[1] = { 26000, 5 }, - .val[2] = { 52000, 7 }, - .val[3] = { 104000, 12 }, - .val[4] = { 208000, 20 }, - .val[5] = { 416000, 36 }, - }, - }, - .irq_config = { - .irq1 = { - .addr = 0x0d, - .mask = BIT(3), - }, - .irq2 = { - .addr = 0x0e, - .mask = BIT(3), - }, - .lir = { - .addr = 0x58, - .mask = BIT(0), - }, - .irq1_func = { - .addr = 0x5e, - .mask = BIT(5), - }, - .irq2_func = { - .addr = 0x5f, - .mask = BIT(5), - }, - .hla = { - .addr = 0x12, - .mask = BIT(5), - }, - .od = { - .addr = 0x12, - .mask = BIT(4), - }, - }, - .decimator = { - [ST_LSM6DSX_ID_ACC] = { - .addr = 0x08, - .mask = GENMASK(2, 0), - }, - [ST_LSM6DSX_ID_GYRO] = { - .addr = 0x08, - .mask = GENMASK(5, 3), - }, - [ST_LSM6DSX_ID_EXT0] = { - .addr = 0x09, - .mask = GENMASK(2, 0), - }, - }, - .fifo_ops = { - .update_fifo = st_lsm6dsx_update_fifo, - .read_fifo = st_lsm6dsx_read_fifo, - .fifo_th = { - .addr = 0x06, - .mask = GENMASK(10, 0), - }, - .fifo_diff = { - .addr = 0x3a, - .mask = GENMASK(10, 0), - }, - .max_size = 682, - .th_wl = 3, /* 1LSB = 2B */ - }, - .ts_settings = { - .timer_en = { - .addr = 0x19, - .mask = BIT(5), - }, - .hr_timer = { - .addr = 0x5c, - .mask = BIT(4), - }, - .fifo_en = { - .addr = 0x07, - .mask = BIT(7), - }, - .decimator = { - .addr = 0x09, - .mask = GENMASK(5, 3), - }, - }, - .shub_settings = { - .page_mux = { - .addr = 0x01, - .mask = BIT(7), - }, - .master_en = { - .addr = 0x1a, - .mask = BIT(0), - }, - .pullup_en = { - .addr = 0x1a, - .mask = BIT(3), - }, - .aux_sens = { - .addr = 0x04, - .mask = GENMASK(5, 4), - }, - .wr_once = { - .addr = 0x07, - .mask = BIT(5), - }, - .emb_func = { - .addr = 0x19, - .mask = BIT(2), - }, - .num_ext_dev = 1, - .shub_out = { - .addr = 0x2e, - }, - .slv0_addr = 0x02, - .dw_slv0_addr = 0x0e, - .pause = 0x7, - }, - .event_settings = { - .enable_reg = { - .addr = 0x58, - .mask = BIT(7), - }, - .wakeup_reg = { - .addr = 0x5B, - .mask = GENMASK(5, 0), - }, - .wakeup_src_reg = 0x1b, - .wakeup_src_status_mask = BIT(3), - .wakeup_src_z_mask = BIT(0), - .wakeup_src_y_mask = BIT(1), - .wakeup_src_x_mask = BIT(2), - }, - }, - { - .reset = { - .addr = 0x12, - .mask = BIT(0), - }, - .boot = { - .addr = 0x12, - .mask = BIT(7), - }, - .bdu = { - .addr = 0x12, - .mask = BIT(6), - }, - .id = { - { - .hw_id = ST_LSM6DSR_ID, - .name = ST_LSM6DSR_DEV_NAME, - .wai = 0x6b, - }, { - .hw_id = ST_ISM330DHCX_ID, - .name = ST_ISM330DHCX_DEV_NAME, - .wai = 0x6b, - }, { - .hw_id = ST_LSM6DSRX_ID, - .name = ST_LSM6DSRX_DEV_NAME, - .wai = 0x6b, - }, { - .hw_id = ST_LSM6DSO_ID, - .name = ST_LSM6DSO_DEV_NAME, - .wai = 0x6c, - }, { - .hw_id = ST_LSM6DSOX_ID, - .name = ST_LSM6DSOX_DEV_NAME, - .wai = 0x6c, - }, { - .hw_id = ST_LSM6DST_ID, - .name = ST_LSM6DST_DEV_NAME, - .wai = 0x6d, - }, { - .hw_id = ST_ASM330LHHX_ID, - .name = ST_ASM330LHHX_DEV_NAME, - .wai = 0x6b, - }, { - .hw_id = ST_ASM330LHHXG1_ID, - .name = ST_ASM330LHHXG1_DEV_NAME, - .wai = 0x6b, - }, { - .hw_id = ST_LSM6DSTX_ID, - .name = ST_LSM6DSTX_DEV_NAME, - .wai = 0x6d, - }, - }, - .channels = { - [ST_LSM6DSX_ID_ACC] = { - .chan = st_lsm6dsx_acc_channels, - .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), - }, - [ST_LSM6DSX_ID_GYRO] = { - .chan = st_lsm6dsx_gyro_channels, - .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), - }, - }, - .drdy_mask = { - .addr = 0x13, - .mask = BIT(3), - }, - .odr_table = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(7, 4), - }, - .odr_avl[0] = { 12500, 0x01 }, - .odr_avl[1] = { 26000, 0x02 }, - .odr_avl[2] = { 52000, 0x03 }, - .odr_avl[3] = { 104000, 0x04 }, - .odr_avl[4] = { 208000, 0x05 }, - .odr_avl[5] = { 416000, 0x06 }, - .odr_avl[6] = { 833000, 0x07 }, - .odr_len = 7, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x11, - .mask = GENMASK(7, 4), - }, - .odr_avl[0] = { 12500, 0x01 }, - .odr_avl[1] = { 26000, 0x02 }, - .odr_avl[2] = { 52000, 0x03 }, - .odr_avl[3] = { 104000, 0x04 }, - .odr_avl[4] = { 208000, 0x05 }, - .odr_avl[5] = { 416000, 0x06 }, - .odr_avl[6] = { 833000, 0x07 }, - .odr_len = 7, - }, - }, - .fs_table = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(3, 2), - }, - .fs_avl[0] = { IIO_G_TO_M_S_2(61000), 0x0 }, - .fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 }, - .fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 }, - .fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 }, - .fs_len = 4, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x11, - .mask = GENMASK(3, 2), - }, - .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750000), 0x0 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 }, - .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 }, - .fs_len = 4, - }, - }, - .irq_config = { - .irq1 = { - .addr = 0x0d, - .mask = BIT(3), - }, - .irq2 = { - .addr = 0x0e, - .mask = BIT(3), - }, - .lir = { - .addr = 0x56, - .mask = BIT(0), - }, - .clear_on_read = { - .addr = 0x56, - .mask = BIT(6), - }, - .irq1_func = { - .addr = 0x5e, - .mask = BIT(5), - }, - .irq2_func = { - .addr = 0x5f, - .mask = BIT(5), - }, - .hla = { - .addr = 0x12, - .mask = BIT(5), - }, - .od = { - .addr = 0x12, - .mask = BIT(4), - }, - }, - .batch = { - [ST_LSM6DSX_ID_ACC] = { - .addr = 0x09, - .mask = GENMASK(3, 0), - }, - [ST_LSM6DSX_ID_GYRO] = { - .addr = 0x09, - .mask = GENMASK(7, 4), - }, - }, - .fifo_ops = { - .update_fifo = st_lsm6dsx_update_fifo, - .read_fifo = st_lsm6dsx_read_tagged_fifo, - .fifo_th = { - .addr = 0x07, - .mask = GENMASK(8, 0), - }, - .fifo_diff = { - .addr = 0x3a, - .mask = GENMASK(9, 0), - }, - .max_size = 512, - .th_wl = 1, - }, - .ts_settings = { - .timer_en = { - .addr = 0x19, - .mask = BIT(5), - }, - .decimator = { - .addr = 0x0a, - .mask = GENMASK(7, 6), - }, - .freq_fine = 0x63, - .ts_sensitivity = 25000, - .ts_trim_coeff = 37500, - }, - .shub_settings = { - .page_mux = { - .addr = 0x01, - .mask = BIT(6), - }, - .master_en = { - .sec_page = true, - .addr = 0x14, - .mask = BIT(2), - }, - .pullup_en = { - .sec_page = true, - .addr = 0x14, - .mask = BIT(3), - }, - .aux_sens = { - .addr = 0x14, - .mask = GENMASK(1, 0), - }, - .wr_once = { - .addr = 0x14, - .mask = BIT(6), - }, - .num_ext_dev = 3, - .shub_out = { - .sec_page = true, - .addr = 0x02, - }, - .slv0_addr = 0x15, - .dw_slv0_addr = 0x21, - .batch_en = BIT(3), - }, - .event_settings = { - .enable_reg = { - .addr = 0x58, - .mask = BIT(7), - }, - .wakeup_reg = { - .addr = 0x5b, - .mask = GENMASK(5, 0), - }, - .wakeup_src_reg = 0x1b, - .wakeup_src_status_mask = BIT(3), - .wakeup_src_z_mask = BIT(0), - .wakeup_src_y_mask = BIT(1), - .wakeup_src_x_mask = BIT(2), - }, - }, - { - .reset = { - .addr = 0x12, - .mask = BIT(0), - }, - .boot = { - .addr = 0x12, - .mask = BIT(7), - }, - .bdu = { - .addr = 0x12, - .mask = BIT(6), - }, - .id = { - { - .hw_id = ST_ASM330LHH_ID, - .name = ST_ASM330LHH_DEV_NAME, - .wai = 0x6b, - }, { - .hw_id = ST_LSM6DSOP_ID, - .name = ST_LSM6DSOP_DEV_NAME, - .wai = 0x6c, - }, { - .hw_id = ST_ASM330LHB_ID, - .name = ST_ASM330LHB_DEV_NAME, - .wai = 0x6b, - }, - }, - .channels = { - [ST_LSM6DSX_ID_ACC] = { - .chan = st_lsm6dsx_acc_channels, - .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), - }, - [ST_LSM6DSX_ID_GYRO] = { - .chan = st_lsm6dsx_gyro_channels, - .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), - }, - }, - .drdy_mask = { - .addr = 0x13, - .mask = BIT(3), - }, - .odr_table = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(7, 4), - }, - .odr_avl[0] = { 12500, 0x01 }, - .odr_avl[1] = { 26000, 0x02 }, - .odr_avl[2] = { 52000, 0x03 }, - .odr_avl[3] = { 104000, 0x04 }, - .odr_avl[4] = { 208000, 0x05 }, - .odr_avl[5] = { 416000, 0x06 }, - .odr_avl[6] = { 833000, 0x07 }, - .odr_len = 7, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x11, - .mask = GENMASK(7, 4), - }, - .odr_avl[0] = { 12500, 0x01 }, - .odr_avl[1] = { 26000, 0x02 }, - .odr_avl[2] = { 52000, 0x03 }, - .odr_avl[3] = { 104000, 0x04 }, - .odr_avl[4] = { 208000, 0x05 }, - .odr_avl[5] = { 416000, 0x06 }, - .odr_avl[6] = { 833000, 0x07 }, - .odr_len = 7, - }, - }, - .fs_table = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(3, 2), - }, - .fs_avl[0] = { IIO_G_TO_M_S_2(61000), 0x0 }, - .fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 }, - .fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 }, - .fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 }, - .fs_len = 4, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x11, - .mask = GENMASK(3, 2), - }, - .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750000), 0x0 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 }, - .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 }, - .fs_len = 4, - }, - }, - .irq_config = { - .irq1 = { - .addr = 0x0d, - .mask = BIT(3), - }, - .irq2 = { - .addr = 0x0e, - .mask = BIT(3), - }, - .lir = { - .addr = 0x56, - .mask = BIT(0), - }, - .clear_on_read = { - .addr = 0x56, - .mask = BIT(6), - }, - .irq1_func = { - .addr = 0x5e, - .mask = BIT(5), - }, - .irq2_func = { - .addr = 0x5f, - .mask = BIT(5), - }, - .hla = { - .addr = 0x12, - .mask = BIT(5), - }, - .od = { - .addr = 0x12, - .mask = BIT(4), - }, - }, - .batch = { - [ST_LSM6DSX_ID_ACC] = { - .addr = 0x09, - .mask = GENMASK(3, 0), - }, - [ST_LSM6DSX_ID_GYRO] = { - .addr = 0x09, - .mask = GENMASK(7, 4), - }, - }, - .fifo_ops = { - .update_fifo = st_lsm6dsx_update_fifo, - .read_fifo = st_lsm6dsx_read_tagged_fifo, - .fifo_th = { - .addr = 0x07, - .mask = GENMASK(8, 0), - }, - .fifo_diff = { - .addr = 0x3a, - .mask = GENMASK(9, 0), - }, - .max_size = 512, - .th_wl = 1, - }, - .ts_settings = { - .timer_en = { - .addr = 0x19, - .mask = BIT(5), - }, - .decimator = { - .addr = 0x0a, - .mask = GENMASK(7, 6), - }, - .freq_fine = 0x63, - .ts_sensitivity = 25000, - .ts_trim_coeff = 37500, - }, - .event_settings = { - .enable_reg = { - .addr = 0x58, - .mask = BIT(7), - }, - .wakeup_reg = { - .addr = 0x5B, - .mask = GENMASK(5, 0), - }, - .wakeup_src_reg = 0x1b, - .wakeup_src_status_mask = BIT(3), - .wakeup_src_z_mask = BIT(0), - .wakeup_src_y_mask = BIT(1), - .wakeup_src_x_mask = BIT(2), - }, - }, - { - .reset = { - .addr = 0x12, - .mask = BIT(0), - }, - .boot = { - .addr = 0x12, - .mask = BIT(7), - }, - .bdu = { - .addr = 0x12, - .mask = BIT(6), - }, - .id = { - { - .hw_id = ST_LSM6DSV_ID, - .name = ST_LSM6DSV_DEV_NAME, - .wai = 0x70, - }, { - .hw_id = ST_LSM6DSV16X_ID, - .name = ST_LSM6DSV16X_DEV_NAME, - .wai = 0x70, - }, - }, - .channels = { - [ST_LSM6DSX_ID_ACC] = { - .chan = st_lsm6dsx_acc_channels, - .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), - }, - [ST_LSM6DSX_ID_GYRO] = { - .chan = st_lsm6dsx_gyro_channels, - .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), - }, - }, - .drdy_mask = { - .addr = 0x13, - .mask = BIT(3), - }, - .odr_table = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(3, 0), - }, - .odr_avl[0] = { 7500, 0x02 }, - .odr_avl[1] = { 15000, 0x03 }, - .odr_avl[2] = { 30000, 0x04 }, - .odr_avl[3] = { 60000, 0x05 }, - .odr_avl[4] = { 120000, 0x06 }, - .odr_avl[5] = { 240000, 0x07 }, - .odr_avl[6] = { 480000, 0x08 }, - .odr_avl[7] = { 960000, 0x09 }, - .odr_len = 8, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x11, - .mask = GENMASK(3, 0), - }, - .odr_avl[0] = { 7500, 0x02 }, - .odr_avl[1] = { 15000, 0x03 }, - .odr_avl[2] = { 30000, 0x04 }, - .odr_avl[3] = { 60000, 0x05 }, - .odr_avl[4] = { 120000, 0x06 }, - .odr_avl[5] = { 240000, 0x07 }, - .odr_avl[6] = { 480000, 0x08 }, - .odr_avl[7] = { 960000, 0x09 }, - .odr_len = 8, - }, - }, - .fs_table = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x17, - .mask = GENMASK(1, 0), - }, - .fs_avl[0] = { IIO_G_TO_M_S_2(61000), 0x0 }, - .fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x1 }, - .fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x2 }, - .fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x3 }, - .fs_len = 4, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x15, - .mask = GENMASK(3, 0), - }, - .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750000), 0x1 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x2 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x3 }, - .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x4 }, - .fs_len = 4, - }, - }, - .irq_config = { - .irq1 = { - .addr = 0x0d, - .mask = BIT(3), - }, - .irq2 = { - .addr = 0x0e, - .mask = BIT(3), - }, - .lir = { - .addr = 0x56, - .mask = BIT(0), - }, - .irq1_func = { - .addr = 0x5e, - .mask = BIT(5), - }, - .irq2_func = { - .addr = 0x5f, - .mask = BIT(5), - }, - .hla = { - .addr = 0x03, - .mask = BIT(4), - }, - .od = { - .addr = 0x03, - .mask = BIT(3), - }, - }, - .batch = { - [ST_LSM6DSX_ID_ACC] = { - .addr = 0x09, - .mask = GENMASK(3, 0), - }, - [ST_LSM6DSX_ID_GYRO] = { - .addr = 0x09, - .mask = GENMASK(7, 4), - }, - }, - .fifo_ops = { - .update_fifo = st_lsm6dsx_update_fifo, - .read_fifo = st_lsm6dsx_read_tagged_fifo, - .fifo_th = { - .addr = 0x07, - .mask = GENMASK(7, 0), - }, - .fifo_diff = { - .addr = 0x1b, - .mask = GENMASK(8, 0), - }, - .max_size = 512, - .th_wl = 1, - }, - .ts_settings = { - .timer_en = { - .addr = 0x50, - .mask = BIT(6), - }, - .decimator = { - .addr = 0x0a, - .mask = GENMASK(7, 6), - }, - .freq_fine = 0x4f, - .ts_sensitivity = 21701, - .ts_trim_coeff = 28212, - }, - .shub_settings = { - .page_mux = { - .addr = 0x01, - .mask = BIT(6), - }, - .master_en = { - .sec_page = true, - .addr = 0x14, - .mask = BIT(2), - }, - .pullup_en = { - .addr = 0x03, - .mask = BIT(6), - }, - .aux_sens = { - .addr = 0x14, - .mask = GENMASK(1, 0), - }, - .wr_once = { - .addr = 0x14, - .mask = BIT(6), - }, - .num_ext_dev = 3, - .shub_out = { - .sec_page = true, - .addr = 0x02, - }, - .slv0_addr = 0x15, - .dw_slv0_addr = 0x21, - .batch_en = BIT(3), - }, - .event_settings = { - .enable_reg = { - .addr = 0x50, - .mask = BIT(7), - }, - .wakeup_reg = { - .addr = 0x5b, - .mask = GENMASK(5, 0), - }, - .wakeup_src_reg = 0x45, - .wakeup_src_status_mask = BIT(3), - .wakeup_src_z_mask = BIT(0), - .wakeup_src_y_mask = BIT(1), - .wakeup_src_x_mask = BIT(2), - }, - }, - { - .reset = { - .addr = 0x12, - .mask = BIT(0), - }, - .boot = { - .addr = 0x12, - .mask = BIT(7), - }, - .bdu = { - .addr = 0x12, - .mask = BIT(6), - }, - .id = { - { - .hw_id = ST_LSM6DSO16IS_ID, - .name = ST_LSM6DSO16IS_DEV_NAME, - .wai = 0x22, - }, { - .hw_id = ST_ISM330IS_ID, - .name = ST_ISM330IS_DEV_NAME, - .wai = 0x22, - } - }, - .channels = { - [ST_LSM6DSX_ID_ACC] = { - .chan = st_lsm6ds0_acc_channels, - .len = ARRAY_SIZE(st_lsm6ds0_acc_channels), - }, - [ST_LSM6DSX_ID_GYRO] = { - .chan = st_lsm6dsx_gyro_channels, - .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), - }, - }, - .odr_table = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(7, 4), - }, - .odr_avl[0] = { 12500, 0x01 }, - .odr_avl[1] = { 26000, 0x02 }, - .odr_avl[2] = { 52000, 0x03 }, - .odr_avl[3] = { 104000, 0x04 }, - .odr_avl[4] = { 208000, 0x05 }, - .odr_avl[5] = { 416000, 0x06 }, - .odr_avl[6] = { 833000, 0x07 }, - .odr_len = 7, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x11, - .mask = GENMASK(7, 4), - }, - .odr_avl[0] = { 12500, 0x01 }, - .odr_avl[1] = { 26000, 0x02 }, - .odr_avl[2] = { 52000, 0x03 }, - .odr_avl[3] = { 104000, 0x04 }, - .odr_avl[4] = { 208000, 0x05 }, - .odr_avl[5] = { 416000, 0x06 }, - .odr_avl[6] = { 833000, 0x07 }, - .odr_len = 7, - }, - }, - .fs_table = { - [ST_LSM6DSX_ID_ACC] = { - .reg = { - .addr = 0x10, - .mask = GENMASK(3, 2), - }, - .fs_avl[0] = { IIO_G_TO_M_S_2(61000), 0x0 }, - .fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 }, - .fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 }, - .fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 }, - .fs_len = 4, - }, - [ST_LSM6DSX_ID_GYRO] = { - .reg = { - .addr = 0x11, - .mask = GENMASK(3, 2), - }, - .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750000), 0x0 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 }, - .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 }, - .fs_len = 4, - }, - }, - .irq_config = { - .hla = { - .addr = 0x12, - .mask = BIT(5), - }, - .od = { - .addr = 0x12, - .mask = BIT(4), - }, - }, - .shub_settings = { - .page_mux = { - .addr = 0x01, - .mask = BIT(6), - }, - .master_en = { - .sec_page = true, - .addr = 0x14, - .mask = BIT(2), - }, - .pullup_en = { - .sec_page = true, - .addr = 0x14, - .mask = BIT(3), - }, - .aux_sens = { - .addr = 0x14, - .mask = GENMASK(1, 0), - }, - .wr_once = { - .addr = 0x14, - .mask = BIT(6), - }, - .num_ext_dev = 3, - .shub_out = { - .sec_page = true, - .addr = 0x02, - }, - .slv0_addr = 0x15, - .dw_slv0_addr = 0x21, - }, - }, -}; - -int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable) -{ - const struct st_lsm6dsx_shub_settings *hub_settings; - unsigned int data; - int err; - - hub_settings = &hw->settings->shub_settings; - data = ST_LSM6DSX_SHIFT_VAL(enable, hub_settings->page_mux.mask); - err = regmap_update_bits(hw->regmap, hub_settings->page_mux.addr, - hub_settings->page_mux.mask, data); - usleep_range(100, 150); - - return err; -} - -static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id, - const char **name) -{ - int err, i, j, data; - - for (i = 0; i < ARRAY_SIZE(st_lsm6dsx_sensor_settings); i++) { - for (j = 0; j < ST_LSM6DSX_MAX_ID; j++) { - if (st_lsm6dsx_sensor_settings[i].id[j].name && - id == st_lsm6dsx_sensor_settings[i].id[j].hw_id) - break; - } - if (j < ST_LSM6DSX_MAX_ID) - break; - } - - if (i == ARRAY_SIZE(st_lsm6dsx_sensor_settings)) { - dev_err(hw->dev, "unsupported hw id [%02x]\n", id); - return -ENODEV; - } - - err = regmap_read(hw->regmap, ST_LSM6DSX_REG_WHOAMI_ADDR, &data); - if (err < 0) { - dev_err(hw->dev, "failed to read whoami register\n"); - return err; - } - - if (data != st_lsm6dsx_sensor_settings[i].id[j].wai) { - dev_err(hw->dev, "unsupported whoami [%02x]\n", data); - return -ENODEV; - } - - *name = st_lsm6dsx_sensor_settings[i].id[j].name; - hw->settings = &st_lsm6dsx_sensor_settings[i]; - - return 0; -} - -static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor, - u32 gain) -{ - const struct st_lsm6dsx_fs_table_entry *fs_table; - unsigned int data; - int i, err; - - fs_table = &sensor->hw->settings->fs_table[sensor->id]; - for (i = 0; i < fs_table->fs_len; i++) { - if (fs_table->fs_avl[i].gain == gain) - break; - } - - if (i == fs_table->fs_len) - return -EINVAL; - - data = ST_LSM6DSX_SHIFT_VAL(fs_table->fs_avl[i].val, - fs_table->reg.mask); - err = st_lsm6dsx_update_bits_locked(sensor->hw, fs_table->reg.addr, - fs_table->reg.mask, data); - if (err < 0) - return err; - - sensor->gain = gain; - - return 0; -} - -int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u32 odr, u8 *val) -{ - const struct st_lsm6dsx_odr_table_entry *odr_table; - int i; - - odr_table = &sensor->hw->settings->odr_table[sensor->id]; - for (i = 0; i < odr_table->odr_len; i++) { - /* - * ext devices can run at different odr respect to - * accel sensor - */ - if (odr_table->odr_avl[i].milli_hz >= odr) - break; - } - - if (i == odr_table->odr_len) - return -EINVAL; - - *val = odr_table->odr_avl[i].val; - return odr_table->odr_avl[i].milli_hz; -} - -static int -st_lsm6dsx_check_odr_dependency(struct st_lsm6dsx_hw *hw, u32 odr, - enum st_lsm6dsx_sensor_id id) -{ - struct st_lsm6dsx_sensor *ref = iio_priv(hw->iio_devs[id]); - - if (odr > 0) { - if (hw->enable_mask & BIT(id)) - return max_t(u32, ref->odr, odr); - else - return odr; - } else { - return (hw->enable_mask & BIT(id)) ? ref->odr : 0; - } -} - -static int -st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u32 req_odr) -{ - struct st_lsm6dsx_sensor *ref_sensor = sensor; - struct st_lsm6dsx_hw *hw = sensor->hw; - const struct st_lsm6dsx_reg *reg; - unsigned int data; - u8 val = 0; - int err; - - switch (sensor->id) { - case ST_LSM6DSX_ID_GYRO: - break; - case ST_LSM6DSX_ID_EXT0: - case ST_LSM6DSX_ID_EXT1: - case ST_LSM6DSX_ID_EXT2: - case ST_LSM6DSX_ID_ACC: { - u32 odr; - int i; - - /* - * i2c embedded controller relies on the accelerometer sensor as - * bus read/write trigger so we need to enable accel device - * at odr = max(accel_odr, ext_odr) in order to properly - * communicate with i2c slave devices - */ - ref_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]); - for (i = ST_LSM6DSX_ID_ACC; i < ST_LSM6DSX_ID_MAX; i++) { - if (!hw->iio_devs[i] || i == sensor->id) - continue; - - odr = st_lsm6dsx_check_odr_dependency(hw, req_odr, i); - if (odr != req_odr) - /* device already configured */ - return 0; - } - break; - } - default: /* should never occur */ - return -EINVAL; - } - - if (req_odr > 0) { - err = st_lsm6dsx_check_odr(ref_sensor, req_odr, &val); - if (err < 0) - return err; - } - - reg = &hw->settings->odr_table[ref_sensor->id].reg; - data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); - return st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data); -} - -static int -__st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor, - bool enable) -{ - struct st_lsm6dsx_hw *hw = sensor->hw; - u32 odr = enable ? sensor->odr : 0; - int err; - - err = st_lsm6dsx_set_odr(sensor, odr); - if (err < 0) - return err; - - if (enable) - hw->enable_mask |= BIT(sensor->id); - else - hw->enable_mask &= ~BIT(sensor->id); - - return 0; -} - -static int -st_lsm6dsx_check_events(struct st_lsm6dsx_sensor *sensor, bool enable) -{ - struct st_lsm6dsx_hw *hw = sensor->hw; - - if (sensor->id == ST_LSM6DSX_ID_GYRO || enable) - return 0; - - return hw->enable_event; -} - -int st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor, - bool enable) -{ - if (st_lsm6dsx_check_events(sensor, enable)) - return 0; - - return __st_lsm6dsx_sensor_set_enable(sensor, enable); -} - -static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor, - u8 addr, int *val) -{ - struct st_lsm6dsx_hw *hw = sensor->hw; - int err, delay; - __le16 data; - - err = st_lsm6dsx_sensor_set_enable(sensor, true); - if (err < 0) - return err; - - /* - * we need to wait for sensor settling time before - * reading data in order to avoid corrupted samples - */ - delay = 1000000000 / sensor->odr; - usleep_range(3 * delay, 4 * delay); - - err = st_lsm6dsx_read_locked(hw, addr, &data, sizeof(data)); - if (err < 0) - return err; - - if (!hw->enable_event) { - err = st_lsm6dsx_sensor_set_enable(sensor, false); - if (err < 0) - return err; - } - - *val = (s16)le16_to_cpu(data); - - return IIO_VAL_INT; -} - -static int st_lsm6dsx_read_raw(struct iio_dev *iio_dev, - struct iio_chan_spec const *ch, - int *val, int *val2, long mask) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); - int ret; - - switch (mask) { - case IIO_CHAN_INFO_RAW: - if (!iio_device_claim_direct(iio_dev)) - return -EBUSY; - - ret = st_lsm6dsx_read_oneshot(sensor, ch->address, val); - iio_device_release_direct(iio_dev); - break; - case IIO_CHAN_INFO_SAMP_FREQ: - *val = sensor->odr / 1000; - *val2 = (sensor->odr % 1000) * 1000; - ret = IIO_VAL_INT_PLUS_MICRO; - break; - case IIO_CHAN_INFO_SCALE: - *val = 0; - *val2 = sensor->gain; - ret = IIO_VAL_INT_PLUS_NANO; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev, - struct iio_chan_spec const *chan, - int val, int val2, long mask) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); - int err = 0; - - if (!iio_device_claim_direct(iio_dev)) - return -EBUSY; - - switch (mask) { - case IIO_CHAN_INFO_SCALE: - err = st_lsm6dsx_set_full_scale(sensor, val2); - break; - case IIO_CHAN_INFO_SAMP_FREQ: { - u8 data; - - val = val * 1000 + val2 / 1000; - val = st_lsm6dsx_check_odr(sensor, val, &data); - if (val < 0) { - err = val; - } else { - sensor->odr = val; - sensor->hwfifo_odr_mHz = val; - } - break; - } - default: - err = -EINVAL; - break; - } - - iio_device_release_direct(iio_dev); - - return err; -} - -static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, bool state) -{ - const struct st_lsm6dsx_reg *reg; - unsigned int data; - int err; - - if (!hw->settings->irq_config.irq1_func.addr) - return -ENOTSUPP; - - reg = &hw->settings->event_settings.enable_reg; - if (reg->addr) { - data = ST_LSM6DSX_SHIFT_VAL(state, reg->mask); - err = st_lsm6dsx_update_bits_locked(hw, reg->addr, - reg->mask, data); - if (err < 0) - return err; - } - - /* Enable wakeup interrupt */ - data = ST_LSM6DSX_SHIFT_VAL(state, hw->irq_routing->mask); - return st_lsm6dsx_update_bits_locked(hw, hw->irq_routing->addr, - hw->irq_routing->mask, data); -} - -static int st_lsm6dsx_read_event(struct iio_dev *iio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int *val, int *val2) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); - struct st_lsm6dsx_hw *hw = sensor->hw; - - if (type != IIO_EV_TYPE_THRESH) - return -EINVAL; - - *val2 = 0; - *val = hw->event_threshold; - - return IIO_VAL_INT; -} - -static int -st_lsm6dsx_write_event(struct iio_dev *iio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int val, int val2) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); - struct st_lsm6dsx_hw *hw = sensor->hw; - const struct st_lsm6dsx_reg *reg; - unsigned int data; - int err; - - if (type != IIO_EV_TYPE_THRESH) - return -EINVAL; - - if (val < 0 || val > 31) - return -EINVAL; - - reg = &hw->settings->event_settings.wakeup_reg; - data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); - err = st_lsm6dsx_update_bits_locked(hw, reg->addr, - reg->mask, data); - if (err < 0) - return -EINVAL; - - hw->event_threshold = val; - - return 0; -} - -static int -st_lsm6dsx_read_event_config(struct iio_dev *iio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); - struct st_lsm6dsx_hw *hw = sensor->hw; - - if (type != IIO_EV_TYPE_THRESH) - return -EINVAL; - - return !!(hw->enable_event & BIT(chan->channel2)); -} - -static int -st_lsm6dsx_write_event_config(struct iio_dev *iio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, bool state) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); - struct st_lsm6dsx_hw *hw = sensor->hw; - u8 enable_event; - int err; - - if (type != IIO_EV_TYPE_THRESH) - return -EINVAL; - - if (state) { - enable_event = hw->enable_event | BIT(chan->channel2); - - /* do not enable events if they are already enabled */ - if (hw->enable_event) - goto out; - } else { - enable_event = hw->enable_event & ~BIT(chan->channel2); - - /* only turn off sensor if no events is enabled */ - if (enable_event) - goto out; - } - - /* stop here if no changes have been made */ - if (hw->enable_event == enable_event) - return 0; - - err = st_lsm6dsx_event_setup(hw, state); - if (err < 0) - return err; - - mutex_lock(&hw->conf_lock); - if (enable_event || !(hw->fifo_mask & BIT(sensor->id))) - err = __st_lsm6dsx_sensor_set_enable(sensor, state); - mutex_unlock(&hw->conf_lock); - if (err < 0) - return err; - -out: - hw->enable_event = enable_event; - - return 0; -} - -int st_lsm6dsx_set_watermark(struct iio_dev *iio_dev, unsigned int val) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); - struct st_lsm6dsx_hw *hw = sensor->hw; - int err; - - val = clamp_val(val, 1, hw->settings->fifo_ops.max_size); - - mutex_lock(&hw->conf_lock); - - err = st_lsm6dsx_update_watermark(sensor, val); - - mutex_unlock(&hw->conf_lock); - - if (err < 0) - return err; - - sensor->watermark = val; - - return 0; -} - -static ssize_t -st_lsm6dsx_sysfs_sampling_frequency_avail(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(dev_to_iio_dev(dev)); - const struct st_lsm6dsx_odr_table_entry *odr_table; - int i, len = 0; - - odr_table = &sensor->hw->settings->odr_table[sensor->id]; - for (i = 0; i < odr_table->odr_len; i++) - len += sysfs_emit_at(buf, len, "%d.%03d%c", - odr_table->odr_avl[i].milli_hz / 1000, - odr_table->odr_avl[i].milli_hz % 1000, - (i == odr_table->odr_len - 1) ? '\n' : ' '); - - return len; -} - -static ssize_t st_lsm6dsx_sysfs_scale_avail(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(dev_to_iio_dev(dev)); - const struct st_lsm6dsx_fs_table_entry *fs_table; - struct st_lsm6dsx_hw *hw = sensor->hw; - int i, len = 0; - - fs_table = &hw->settings->fs_table[sensor->id]; - for (i = 0; i < fs_table->fs_len; i++) - len += sysfs_emit_at(buf, len, "0.%09u%c", - fs_table->fs_avl[i].gain, - (i == fs_table->fs_len - 1) ? '\n' : ' '); - - return len; -} - -static int st_lsm6dsx_write_raw_get_fmt(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - long mask) -{ - switch (mask) { - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_ANGL_VEL: - case IIO_ACCEL: - return IIO_VAL_INT_PLUS_NANO; - default: - return IIO_VAL_INT_PLUS_MICRO; - } - default: - return IIO_VAL_INT_PLUS_MICRO; - } -} - -static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(st_lsm6dsx_sysfs_sampling_frequency_avail); -static IIO_DEVICE_ATTR(in_accel_scale_available, 0444, - st_lsm6dsx_sysfs_scale_avail, NULL, 0); -static IIO_DEVICE_ATTR(in_anglvel_scale_available, 0444, - st_lsm6dsx_sysfs_scale_avail, NULL, 0); - -static struct attribute *st_lsm6dsx_acc_attributes[] = { - &iio_dev_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_in_accel_scale_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group st_lsm6dsx_acc_attribute_group = { - .attrs = st_lsm6dsx_acc_attributes, -}; - -static const struct iio_info st_lsm6dsx_acc_info = { - .attrs = &st_lsm6dsx_acc_attribute_group, - .read_raw = st_lsm6dsx_read_raw, - .write_raw = st_lsm6dsx_write_raw, - .read_event_value = st_lsm6dsx_read_event, - .write_event_value = st_lsm6dsx_write_event, - .read_event_config = st_lsm6dsx_read_event_config, - .write_event_config = st_lsm6dsx_write_event_config, - .hwfifo_set_watermark = st_lsm6dsx_set_watermark, - .write_raw_get_fmt = st_lsm6dsx_write_raw_get_fmt, -}; - -static struct attribute *st_lsm6dsx_gyro_attributes[] = { - &iio_dev_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_in_anglvel_scale_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group st_lsm6dsx_gyro_attribute_group = { - .attrs = st_lsm6dsx_gyro_attributes, -}; - -static const struct iio_info st_lsm6dsx_gyro_info = { - .attrs = &st_lsm6dsx_gyro_attribute_group, - .read_raw = st_lsm6dsx_read_raw, - .write_raw = st_lsm6dsx_write_raw, - .hwfifo_set_watermark = st_lsm6dsx_set_watermark, - .write_raw_get_fmt = st_lsm6dsx_write_raw_get_fmt, -}; - -static int -st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw, - const struct st_lsm6dsx_reg **drdy_reg) -{ - struct device *dev = hw->dev; - const struct st_sensors_platform_data *pdata = dev_get_platdata(dev); - int err = 0, drdy_pin; - - if (device_property_read_u32(dev, "st,drdy-int-pin", &drdy_pin) < 0) - drdy_pin = pdata ? pdata->drdy_int_pin : 1; - - switch (drdy_pin) { - case 1: - hw->irq_routing = &hw->settings->irq_config.irq1_func; - *drdy_reg = &hw->settings->irq_config.irq1; - break; - case 2: - hw->irq_routing = &hw->settings->irq_config.irq2_func; - *drdy_reg = &hw->settings->irq_config.irq2; - break; - default: - dev_err(hw->dev, "unsupported data ready pin\n"); - err = -EINVAL; - break; - } - - return err; -} - -static int st_lsm6dsx_init_shub(struct st_lsm6dsx_hw *hw) -{ - const struct st_lsm6dsx_shub_settings *hub_settings; - struct device *dev = hw->dev; - const struct st_sensors_platform_data *pdata = dev_get_platdata(dev); - unsigned int data; - int err = 0; - - hub_settings = &hw->settings->shub_settings; - - if (device_property_read_bool(dev, "st,pullups") || - (pdata && pdata->pullups)) { - if (hub_settings->pullup_en.sec_page) { - err = st_lsm6dsx_set_page(hw, true); - if (err < 0) - return err; - } - - data = ST_LSM6DSX_SHIFT_VAL(1, hub_settings->pullup_en.mask); - err = regmap_update_bits(hw->regmap, - hub_settings->pullup_en.addr, - hub_settings->pullup_en.mask, data); - - if (hub_settings->pullup_en.sec_page) - st_lsm6dsx_set_page(hw, false); - - if (err < 0) - return err; - } - - if (hub_settings->aux_sens.addr) { - /* configure aux sensors */ - err = st_lsm6dsx_set_page(hw, true); - if (err < 0) - return err; - - data = ST_LSM6DSX_SHIFT_VAL(3, hub_settings->aux_sens.mask); - err = regmap_update_bits(hw->regmap, - hub_settings->aux_sens.addr, - hub_settings->aux_sens.mask, data); - - st_lsm6dsx_set_page(hw, false); - - if (err < 0) - return err; - } - - if (hub_settings->emb_func.addr) { - data = ST_LSM6DSX_SHIFT_VAL(1, hub_settings->emb_func.mask); - err = regmap_update_bits(hw->regmap, - hub_settings->emb_func.addr, - hub_settings->emb_func.mask, data); - } - - return err; -} - -static int st_lsm6dsx_init_hw_timer(struct st_lsm6dsx_hw *hw) -{ - const struct st_lsm6dsx_hw_ts_settings *ts_settings; - int err, val; - - ts_settings = &hw->settings->ts_settings; - /* enable hw timestamp generation if necessary */ - if (ts_settings->timer_en.addr) { - val = ST_LSM6DSX_SHIFT_VAL(1, ts_settings->timer_en.mask); - err = regmap_update_bits(hw->regmap, - ts_settings->timer_en.addr, - ts_settings->timer_en.mask, val); - if (err < 0) - return err; - } - - /* enable high resolution for hw ts timer if necessary */ - if (ts_settings->hr_timer.addr) { - val = ST_LSM6DSX_SHIFT_VAL(1, ts_settings->hr_timer.mask); - err = regmap_update_bits(hw->regmap, - ts_settings->hr_timer.addr, - ts_settings->hr_timer.mask, val); - if (err < 0) - return err; - } - - /* enable ts queueing in FIFO if necessary */ - if (ts_settings->fifo_en.addr) { - val = ST_LSM6DSX_SHIFT_VAL(1, ts_settings->fifo_en.mask); - err = regmap_update_bits(hw->regmap, - ts_settings->fifo_en.addr, - ts_settings->fifo_en.mask, val); - if (err < 0) - return err; - } - - /* calibrate timestamp sensitivity */ - hw->ts_gain = ts_settings->ts_sensitivity; - if (ts_settings->freq_fine) { - err = regmap_read(hw->regmap, ts_settings->freq_fine, &val); - if (err < 0) - return err; - - hw->ts_gain -= ((s8)val * ts_settings->ts_trim_coeff) / 1000; - } - - return 0; -} - -static int st_lsm6dsx_reset_device(struct st_lsm6dsx_hw *hw) -{ - const struct st_lsm6dsx_reg *reg; - int err; - - /* - * flush hw FIFO before device reset in order to avoid - * possible races on interrupt line 1. If the first interrupt - * line is asserted during hw reset the device will work in - * I3C-only mode (if it is supported) - */ - err = st_lsm6dsx_flush_fifo(hw); - if (err < 0 && err != -ENOTSUPP) - return err; - - /* device sw reset */ - reg = &hw->settings->reset; - err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, - ST_LSM6DSX_SHIFT_VAL(1, reg->mask)); - if (err < 0) - return err; - - msleep(50); - - /* reload trimming parameter */ - reg = &hw->settings->boot; - err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, - ST_LSM6DSX_SHIFT_VAL(1, reg->mask)); - if (err < 0) - return err; - - msleep(50); - - return 0; -} - -static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw) -{ - const struct st_lsm6dsx_reg *reg; - int err; - - err = st_lsm6dsx_reset_device(hw); - if (err < 0) - return err; - - /* enable Block Data Update */ - reg = &hw->settings->bdu; - err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, - ST_LSM6DSX_SHIFT_VAL(1, reg->mask)); - if (err < 0) - return err; - - /* enable FIFO watermak interrupt */ - err = st_lsm6dsx_get_drdy_reg(hw, ®); - if (err < 0) - return err; - - err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, - ST_LSM6DSX_SHIFT_VAL(1, reg->mask)); - if (err < 0) - return err; - - /* enable Latched interrupts for device events */ - if (hw->settings->irq_config.lir.addr) { - reg = &hw->settings->irq_config.lir; - err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, - ST_LSM6DSX_SHIFT_VAL(1, reg->mask)); - if (err < 0) - return err; - - /* enable clear on read for latched interrupts */ - if (hw->settings->irq_config.clear_on_read.addr) { - reg = &hw->settings->irq_config.clear_on_read; - err = regmap_update_bits(hw->regmap, - reg->addr, reg->mask, - ST_LSM6DSX_SHIFT_VAL(1, reg->mask)); - if (err < 0) - return err; - } - } - - /* enable drdy-mas if available */ - if (hw->settings->drdy_mask.addr) { - reg = &hw->settings->drdy_mask; - err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, - ST_LSM6DSX_SHIFT_VAL(1, reg->mask)); - if (err < 0) - return err; - } - - err = st_lsm6dsx_init_shub(hw); - if (err < 0) - return err; - - return st_lsm6dsx_init_hw_timer(hw); -} - -static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw, - enum st_lsm6dsx_sensor_id id, - const char *name) -{ - struct st_lsm6dsx_sensor *sensor; - struct iio_dev *iio_dev; - - iio_dev = devm_iio_device_alloc(hw->dev, sizeof(*sensor)); - if (!iio_dev) - return NULL; - - iio_dev->modes = INDIO_DIRECT_MODE; - iio_dev->available_scan_masks = st_lsm6dsx_available_scan_masks; - iio_dev->channels = hw->settings->channels[id].chan; - iio_dev->num_channels = hw->settings->channels[id].len; - - sensor = iio_priv(iio_dev); - sensor->id = id; - sensor->hw = hw; - sensor->odr = hw->settings->odr_table[id].odr_avl[0].milli_hz; - sensor->hwfifo_odr_mHz = sensor->odr; - sensor->gain = hw->settings->fs_table[id].fs_avl[0].gain; - sensor->watermark = 1; - - switch (id) { - case ST_LSM6DSX_ID_ACC: - iio_dev->info = &st_lsm6dsx_acc_info; - scnprintf(sensor->name, sizeof(sensor->name), "%s_accel", - name); - break; - case ST_LSM6DSX_ID_GYRO: - iio_dev->info = &st_lsm6dsx_gyro_info; - scnprintf(sensor->name, sizeof(sensor->name), "%s_gyro", - name); - break; - default: - return NULL; - } - iio_dev->name = sensor->name; - - return iio_dev; -} - -static bool -st_lsm6dsx_report_motion_event(struct st_lsm6dsx_hw *hw) -{ - const struct st_lsm6dsx_event_settings *event_settings; - int err, data; - s64 timestamp; - - if (!hw->enable_event) - return false; - - event_settings = &hw->settings->event_settings; - err = st_lsm6dsx_read_locked(hw, event_settings->wakeup_src_reg, - &data, sizeof(data)); - if (err < 0) - return false; - - timestamp = iio_get_time_ns(hw->iio_devs[ST_LSM6DSX_ID_ACC]); - if ((data & hw->settings->event_settings.wakeup_src_z_mask) && - (hw->enable_event & BIT(IIO_MOD_Z))) - iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC], - IIO_MOD_EVENT_CODE(IIO_ACCEL, - 0, - IIO_MOD_Z, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_EITHER), - timestamp); - - if ((data & hw->settings->event_settings.wakeup_src_y_mask) && - (hw->enable_event & BIT(IIO_MOD_Y))) - iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC], - IIO_MOD_EVENT_CODE(IIO_ACCEL, - 0, - IIO_MOD_Y, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_EITHER), - timestamp); - - if ((data & hw->settings->event_settings.wakeup_src_x_mask) && - (hw->enable_event & BIT(IIO_MOD_X))) - iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC], - IIO_MOD_EVENT_CODE(IIO_ACCEL, - 0, - IIO_MOD_X, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_EITHER), - timestamp); - - return data & event_settings->wakeup_src_status_mask; -} - -static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private) -{ - struct st_lsm6dsx_hw *hw = private; - int fifo_len = 0, len; - bool event; - - event = st_lsm6dsx_report_motion_event(hw); - - if (!hw->settings->fifo_ops.read_fifo) - return event ? IRQ_HANDLED : IRQ_NONE; - - /* - * If we are using edge IRQs, new samples can arrive while - * processing current interrupt since there are no hw - * guarantees the irq line stays "low" long enough to properly - * detect the new interrupt. In this case the new sample will - * be missed. - * Polling FIFO status register allow us to read new - * samples even if the interrupt arrives while processing - * previous data and the timeslot where the line is "low" is - * too short to be properly detected. - */ - do { - mutex_lock(&hw->fifo_lock); - len = hw->settings->fifo_ops.read_fifo(hw); - mutex_unlock(&hw->fifo_lock); - - if (len > 0) - fifo_len += len; - } while (len > 0); - - return fifo_len || event ? IRQ_HANDLED : IRQ_NONE; -} - -static irqreturn_t st_lsm6dsx_sw_trigger_handler_thread(int irq, - void *private) -{ - struct iio_poll_func *pf = private; - struct iio_dev *iio_dev = pf->indio_dev; - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); - struct st_lsm6dsx_hw *hw = sensor->hw; - - if (sensor->id == ST_LSM6DSX_ID_EXT0 || - sensor->id == ST_LSM6DSX_ID_EXT1 || - sensor->id == ST_LSM6DSX_ID_EXT2) - st_lsm6dsx_shub_read_output(hw, - (u8 *)hw->scan[sensor->id].channels, - sizeof(hw->scan[sensor->id].channels)); - else - st_lsm6dsx_read_locked(hw, iio_dev->channels[0].address, - hw->scan[sensor->id].channels, - sizeof(hw->scan[sensor->id].channels)); - - iio_push_to_buffers_with_timestamp(iio_dev, &hw->scan[sensor->id], - iio_get_time_ns(iio_dev)); - iio_trigger_notify_done(iio_dev->trig); - - return IRQ_HANDLED; -} - -static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw) -{ - const struct st_lsm6dsx_reg *reg; - struct device *dev = hw->dev; - const struct st_sensors_platform_data *pdata = dev_get_platdata(dev); - unsigned long irq_type; - bool irq_active_low; - int err; - - irq_type = irq_get_trigger_type(hw->irq); - switch (irq_type) { - case IRQF_TRIGGER_HIGH: - case IRQF_TRIGGER_RISING: - irq_active_low = false; - break; - case IRQF_TRIGGER_LOW: - case IRQF_TRIGGER_FALLING: - irq_active_low = true; - break; - default: - dev_info(hw->dev, "mode %lx unsupported\n", irq_type); - return -EINVAL; - } - - reg = &hw->settings->irq_config.hla; - err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, - ST_LSM6DSX_SHIFT_VAL(irq_active_low, - reg->mask)); - if (err < 0) - return err; - - if (device_property_read_bool(dev, "drive-open-drain") || - (pdata && pdata->open_drain)) { - reg = &hw->settings->irq_config.od; - err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, - ST_LSM6DSX_SHIFT_VAL(1, reg->mask)); - if (err < 0) - return err; - - irq_type |= IRQF_SHARED; - } - - err = devm_request_threaded_irq(hw->dev, hw->irq, - NULL, - st_lsm6dsx_handler_thread, - irq_type | IRQF_ONESHOT, - "lsm6dsx", hw); - if (err) { - dev_err(hw->dev, "failed to request trigger irq %d\n", - hw->irq); - return err; - } - - return 0; -} - -static int st_lsm6dsx_sw_buffer_preenable(struct iio_dev *iio_dev) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); - - return st_lsm6dsx_device_set_enable(sensor, true); -} - -static int st_lsm6dsx_sw_buffer_postdisable(struct iio_dev *iio_dev) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); - - return st_lsm6dsx_device_set_enable(sensor, false); -} - -static const struct iio_buffer_setup_ops st_lsm6dsx_sw_buffer_ops = { - .preenable = st_lsm6dsx_sw_buffer_preenable, - .postdisable = st_lsm6dsx_sw_buffer_postdisable, -}; - -static int st_lsm6dsx_sw_buffers_setup(struct st_lsm6dsx_hw *hw) -{ - int i; - - for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { - int err; - - if (!hw->iio_devs[i]) - continue; - - err = devm_iio_triggered_buffer_setup(hw->dev, - hw->iio_devs[i], NULL, - st_lsm6dsx_sw_trigger_handler_thread, - &st_lsm6dsx_sw_buffer_ops); - if (err) - return err; - } - - return 0; -} - -static int st_lsm6dsx_init_regulators(struct device *dev) -{ - /* vdd-vddio power regulators */ - static const char * const regulators[] = { "vdd", "vddio" }; - int err; - - err = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulators), - regulators); - if (err) - return dev_err_probe(dev, err, "failed to enable regulators\n"); - - msleep(50); - - return 0; -} - -int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, - struct regmap *regmap) -{ - const struct st_sensors_platform_data *pdata = dev_get_platdata(dev); - const struct st_lsm6dsx_shub_settings *hub_settings; - struct st_lsm6dsx_hw *hw; - const char *name = NULL; - int i, err; - - hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL); - if (!hw) - return -ENOMEM; - - dev_set_drvdata(dev, hw); - - mutex_init(&hw->fifo_lock); - mutex_init(&hw->conf_lock); - mutex_init(&hw->page_lock); - - err = st_lsm6dsx_init_regulators(dev); - if (err) - return err; - - hw->buff = devm_kzalloc(dev, ST_LSM6DSX_BUFF_SIZE, GFP_KERNEL); - if (!hw->buff) - return -ENOMEM; - - hw->dev = dev; - hw->irq = irq; - hw->regmap = regmap; - - err = st_lsm6dsx_check_whoami(hw, hw_id, &name); - if (err < 0) - return err; - - for (i = 0; i < ST_LSM6DSX_ID_EXT0; i++) { - hw->iio_devs[i] = st_lsm6dsx_alloc_iiodev(hw, i, name); - if (!hw->iio_devs[i]) - return -ENOMEM; - } - - err = st_lsm6dsx_init_device(hw); - if (err < 0) - return err; - - hub_settings = &hw->settings->shub_settings; - if (hub_settings->master_en.addr && - !device_property_read_bool(dev, "st,disable-sensor-hub")) { - err = st_lsm6dsx_shub_probe(hw, name); - if (err < 0) - return err; - } - - if (hw->irq > 0) { - err = st_lsm6dsx_irq_setup(hw); - if (err < 0) - return err; - - err = st_lsm6dsx_fifo_setup(hw); - if (err < 0) - return err; - } - - if (!hw->irq || !hw->settings->fifo_ops.read_fifo) { - /* - * Rely on sw triggers (e.g. hr-timers) if irq pin is not - * connected of if the device does not support HW FIFO - */ - err = st_lsm6dsx_sw_buffers_setup(hw); - if (err) - return err; - } - - if (!iio_read_acpi_mount_matrix(hw->dev, &hw->orientation, "ROTM")) { - err = iio_read_mount_matrix(hw->dev, &hw->orientation); - if (err) - return err; - } - - for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { - if (!hw->iio_devs[i]) - continue; - - err = devm_iio_device_register(hw->dev, hw->iio_devs[i]); - if (err) - return err; - } - - if (device_property_read_bool(dev, "wakeup-source") || - (pdata && pdata->wakeup_source)) { - err = devm_device_init_wakeup(dev); - if (err) - return dev_err_probe(dev, err, "Failed to init wakeup\n"); - } - - return 0; -} -EXPORT_SYMBOL_NS(st_lsm6dsx_probe, "IIO_LSM6DSX"); - -static int st_lsm6dsx_suspend(struct device *dev) -{ - struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev); - struct st_lsm6dsx_sensor *sensor; - int i, err = 0; - - for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { - if (!hw->iio_devs[i]) - continue; - - sensor = iio_priv(hw->iio_devs[i]); - if (!(hw->enable_mask & BIT(sensor->id))) - continue; - - if (device_may_wakeup(dev) && - sensor->id == ST_LSM6DSX_ID_ACC && hw->enable_event) { - /* Enable wake from IRQ */ - enable_irq_wake(hw->irq); - continue; - } - - err = st_lsm6dsx_device_set_enable(sensor, false); - if (err < 0) - return err; - - hw->suspend_mask |= BIT(sensor->id); - } - - if (hw->fifo_mask) - err = st_lsm6dsx_flush_fifo(hw); - - return err; -} - -static int st_lsm6dsx_resume(struct device *dev) -{ - struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev); - struct st_lsm6dsx_sensor *sensor; - int i, err = 0; - - for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { - if (!hw->iio_devs[i]) - continue; - - sensor = iio_priv(hw->iio_devs[i]); - if (device_may_wakeup(dev) && - sensor->id == ST_LSM6DSX_ID_ACC && hw->enable_event) - disable_irq_wake(hw->irq); - - if (!(hw->suspend_mask & BIT(sensor->id))) - continue; - - err = st_lsm6dsx_device_set_enable(sensor, true); - if (err < 0) - return err; - - hw->suspend_mask &= ~BIT(sensor->id); - } - - if (hw->fifo_mask) - err = st_lsm6dsx_resume_fifo(hw); - - return err; -} - -EXPORT_NS_SIMPLE_DEV_PM_OPS(st_lsm6dsx_pm_ops, st_lsm6dsx_suspend, - st_lsm6dsx_resume, IIO_LSM6DSX); - -MODULE_AUTHOR("Lorenzo Bianconi "); -MODULE_AUTHOR("Denis Ciocca "); -MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx driver"); -MODULE_LICENSE("GPL v2"); diff --git a/usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_i2c.c b/usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_i2c.c deleted file mode 100644 index b2a7c2e..0000000 --- a/usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_i2c.c +++ /dev/null @@ -1,197 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * STMicroelectronics st_lsm6dsx i2c driver - * - * Copyright 2016 STMicroelectronics Inc. - * - * Lorenzo Bianconi - * Denis Ciocca - */ - -#include -#include -#include -#include -#include - -#include "st_lsm6dsx.h" - -static const struct regmap_config st_lsm6dsx_i2c_regmap_config = { - .reg_bits = 8, - .val_bits = 8, -}; - -static int st_lsm6dsx_i2c_probe(struct i2c_client *client) -{ - int hw_id; - struct regmap *regmap; - - hw_id = (kernel_ulong_t)device_get_match_data(&client->dev); - if (!hw_id) - hw_id = i2c_client_get_device_id(client)->driver_data; - if (!hw_id) - return -EINVAL; - - regmap = devm_regmap_init_i2c(client, &st_lsm6dsx_i2c_regmap_config); - if (IS_ERR(regmap)) { - dev_err(&client->dev, "Failed to register i2c regmap %ld\n", PTR_ERR(regmap)); - return PTR_ERR(regmap); - } - - return st_lsm6dsx_probe(&client->dev, client->irq, hw_id, regmap); -} - -static const struct of_device_id st_lsm6dsx_i2c_of_match[] = { - { - .compatible = "st,lsm6ds3", - .data = (void *)ST_LSM6DS3_ID, - }, - { - .compatible = "st,lsm6ds3h", - .data = (void *)ST_LSM6DS3H_ID, - }, - { - .compatible = "st,lsm6dsl", - .data = (void *)ST_LSM6DSL_ID, - }, - { - .compatible = "st,lsm6dsm", - .data = (void *)ST_LSM6DSM_ID, - }, - { - .compatible = "st,ism330dlc", - .data = (void *)ST_ISM330DLC_ID, - }, - { - .compatible = "st,lsm6dso", - .data = (void *)ST_LSM6DSO_ID, - }, - { - .compatible = "st,asm330lhh", - .data = (void *)ST_ASM330LHH_ID, - }, - { - .compatible = "st,lsm6dsox", - .data = (void *)ST_LSM6DSOX_ID, - }, - { - .compatible = "st,lsm6dsr", - .data = (void *)ST_LSM6DSR_ID, - }, - { - .compatible = "st,lsm6ds3tr-c", - .data = (void *)ST_LSM6DS3TRC_ID, - }, - { - .compatible = "st,ism330dhcx", - .data = (void *)ST_ISM330DHCX_ID, - }, - { - .compatible = "st,lsm9ds1-imu", - .data = (void *)ST_LSM9DS1_ID, - }, - { - .compatible = "st,lsm6ds0", - .data = (void *)ST_LSM6DS0_ID, - }, - { - .compatible = "st,lsm6dsrx", - .data = (void *)ST_LSM6DSRX_ID, - }, - { - .compatible = "st,lsm6dst", - .data = (void *)ST_LSM6DST_ID, - }, - { - .compatible = "st,lsm6dsop", - .data = (void *)ST_LSM6DSOP_ID, - }, - { - .compatible = "st,asm330lhhx", - .data = (void *)ST_ASM330LHHX_ID, - }, - { - .compatible = "st,lsm6dstx", - .data = (void *)ST_LSM6DSTX_ID, - }, - { - .compatible = "st,lsm6dsv", - .data = (void *)ST_LSM6DSV_ID, - }, - { - .compatible = "st,lsm6dsv16x", - .data = (void *)ST_LSM6DSV16X_ID, - }, - { - .compatible = "st,lsm6dso16is", - .data = (void *)ST_LSM6DSO16IS_ID, - }, - { - .compatible = "st,ism330is", - .data = (void *)ST_ISM330IS_ID, - }, - { - .compatible = "st,asm330lhb", - .data = (void *)ST_ASM330LHB_ID, - }, - { - .compatible = "st,asm330lhhxg1", - .data = (void *)ST_ASM330LHHXG1_ID, - }, - { } -}; -MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match); - -static const struct acpi_device_id st_lsm6dsx_i2c_acpi_match[] = { - { "SMO8B30", ST_LSM6DS3TRC_ID, }, - { "SMOCF00", ST_LSM6DSO_ID, }, - { } -}; -MODULE_DEVICE_TABLE(acpi, st_lsm6dsx_i2c_acpi_match); - -static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = { - { ST_LSM6DS3_DEV_NAME, ST_LSM6DS3_ID }, - { ST_LSM6DS3H_DEV_NAME, ST_LSM6DS3H_ID }, - { ST_LSM6DSL_DEV_NAME, ST_LSM6DSL_ID }, - { 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 }, - { ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID }, - { ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID }, - { ST_ISM330DHCX_DEV_NAME, ST_ISM330DHCX_ID }, - { ST_LSM9DS1_DEV_NAME, ST_LSM9DS1_ID }, - { ST_LSM6DS0_DEV_NAME, ST_LSM6DS0_ID }, - { ST_LSM6DSRX_DEV_NAME, ST_LSM6DSRX_ID }, - { ST_LSM6DST_DEV_NAME, ST_LSM6DST_ID }, - { ST_LSM6DSOP_DEV_NAME, ST_LSM6DSOP_ID }, - { ST_ASM330LHHX_DEV_NAME, ST_ASM330LHHX_ID }, - { ST_LSM6DSTX_DEV_NAME, ST_LSM6DSTX_ID }, - { ST_LSM6DSV_DEV_NAME, ST_LSM6DSV_ID }, - { ST_LSM6DSV16X_DEV_NAME, ST_LSM6DSV16X_ID }, - { ST_LSM6DSO16IS_DEV_NAME, ST_LSM6DSO16IS_ID }, - { ST_ISM330IS_DEV_NAME, ST_ISM330IS_ID }, - { ST_ASM330LHB_DEV_NAME, ST_ASM330LHB_ID }, - { ST_ASM330LHHXG1_DEV_NAME, ST_ASM330LHHXG1_ID }, - { } -}; -MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table); - -static struct i2c_driver st_lsm6dsx_driver = { - .driver = { - .name = "st_lsm6dsx_i2c", - .pm = pm_sleep_ptr(&st_lsm6dsx_pm_ops), - .of_match_table = st_lsm6dsx_i2c_of_match, - .acpi_match_table = st_lsm6dsx_i2c_acpi_match, - }, - .probe = st_lsm6dsx_i2c_probe, - .id_table = st_lsm6dsx_i2c_id_table, -}; -module_i2c_driver(st_lsm6dsx_driver); - -MODULE_AUTHOR("Lorenzo Bianconi "); -MODULE_AUTHOR("Denis Ciocca "); -MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx i2c driver"); -MODULE_LICENSE("GPL v2"); -MODULE_IMPORT_NS("IIO_LSM6DSX"); diff --git a/usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_shub.c b/usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_shub.c deleted file mode 100644 index d6a1eeb..0000000 --- a/usr/src/st-lsm6dsx-shift13mi-0.1/st_lsm6dsx_shub.c +++ /dev/null @@ -1,922 +0,0 @@ -/* - * STMicroelectronics st_lsm6dsx i2c controller driver - * - * i2c controller embedded in lsm6dx series can connect up to four - * slave devices using accelerometer sensor as trigger for i2c - * read/write operations. Current implementation relies on SLV0 channel - * for slave configuration and SLV{1,2,3} to read data and push them into - * the hw FIFO - * - * Copyright (C) 2018 Lorenzo Bianconi - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ -#include -#include -#include -#include -#include - -#include "st_lsm6dsx.h" - -#define ST_LSM6DSX_SLV_ADDR(n, base) ((base) + (n) * 3) -#define ST_LSM6DSX_SLV_SUB_ADDR(n, base) ((base) + 1 + (n) * 3) -#define ST_LSM6DSX_SLV_CONFIG(n, base) ((base) + 2 + (n) * 3) - -#define ST_LS6DSX_READ_OP_MASK GENMASK(2, 0) - -static const struct st_lsm6dsx_ext_dev_settings st_lsm6dsx_ext_dev_table[] = { - /* LIS2MDL */ - { - .i2c_addr = { 0x1e }, - .wai = { - .addr = 0x4f, - .val = 0x40, - }, - .id = ST_LSM6DSX_ID_MAGN, - .odr_table = { - .reg = { - .addr = 0x60, - .mask = GENMASK(3, 2), - }, - .odr_avl[0] = { 10000, 0x0 }, - .odr_avl[1] = { 20000, 0x1 }, - .odr_avl[2] = { 50000, 0x2 }, - .odr_avl[3] = { 100000, 0x3 }, - .odr_len = 4, - }, - .fs_table = { - .fs_avl[0] = { - .gain = 1500, - .val = 0x0, - }, /* 1500 uG/LSB */ - .fs_len = 1, - }, - .temp_comp = { - .addr = 0x60, - .mask = BIT(7), - }, - .pwr_table = { - .reg = { - .addr = 0x60, - .mask = GENMASK(1, 0), - }, - .off_val = 0x2, - .on_val = 0x0, - }, - .off_canc = { - .addr = 0x61, - .mask = BIT(1), - }, - .bdu = { - .addr = 0x62, - .mask = BIT(4), - }, - .out = { - .addr = 0x68, - .len = 6, - }, - }, - /* LIS3MDL */ - { - .i2c_addr = { 0x1e }, - .wai = { - .addr = 0x0f, - .val = 0x3d, - }, - .id = ST_LSM6DSX_ID_MAGN, - .odr_table = { - .reg = { - .addr = 0x20, - .mask = GENMASK(4, 2), - }, - .odr_avl[0] = { 1000, 0x0 }, - .odr_avl[1] = { 2000, 0x1 }, - .odr_avl[2] = { 3000, 0x2 }, - .odr_avl[3] = { 5000, 0x3 }, - .odr_avl[4] = { 10000, 0x4 }, - .odr_avl[5] = { 20000, 0x5 }, - .odr_avl[6] = { 40000, 0x6 }, - .odr_avl[7] = { 80000, 0x7 }, - .odr_len = 8, - }, - .fs_table = { - .reg = { - .addr = 0x21, - .mask = GENMASK(6, 5), - }, - .fs_avl[0] = { - .gain = 146, - .val = 0x00, - }, /* 4000 uG/LSB */ - .fs_avl[1] = { - .gain = 292, - .val = 0x01, - }, /* 8000 uG/LSB */ - .fs_avl[2] = { - .gain = 438, - .val = 0x02, - }, /* 12000 uG/LSB */ - .fs_avl[3] = { - .gain = 584, - .val = 0x03, - }, /* 16000 uG/LSB */ - .fs_len = 4, - }, - .pwr_table = { - .reg = { - .addr = 0x22, - .mask = GENMASK(1, 0), - }, - .off_val = 0x2, - .on_val = 0x0, - }, - .bdu = { - .addr = 0x24, - .mask = BIT(6), - }, - .out = { - .addr = 0x28, - .len = 6, - }, - }, -}; - -static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw) -{ - struct st_lsm6dsx_sensor *sensor; - u32 odr, timeout; - - sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]); - odr = (hw->enable_mask & BIT(ST_LSM6DSX_ID_ACC)) ? sensor->odr : 12500; - /* set 10ms as minimum timeout for i2c slave configuration */ - timeout = max_t(u32, 2000000U / odr + 1, 10); - msleep(timeout); -} - -/* - * st_lsm6dsx_shub_read_output - read i2c controller register - * - * Read st_lsm6dsx i2c controller register - */ -int st_lsm6dsx_shub_read_output(struct st_lsm6dsx_hw *hw, u8 *data, int len) -{ - const struct st_lsm6dsx_shub_settings *hub_settings; - int err; - - mutex_lock(&hw->page_lock); - - hub_settings = &hw->settings->shub_settings; - if (hub_settings->shub_out.sec_page) { - err = st_lsm6dsx_set_page(hw, true); - if (err < 0) - goto out; - } - - err = regmap_bulk_read(hw->regmap, hub_settings->shub_out.addr, - data, len); - - if (hub_settings->shub_out.sec_page) - st_lsm6dsx_set_page(hw, false); -out: - mutex_unlock(&hw->page_lock); - - return err; -} - -/* - * st_lsm6dsx_shub_write_reg - write i2c controller register - * - * Write st_lsm6dsx i2c controller register - */ -static int st_lsm6dsx_shub_write_reg(struct st_lsm6dsx_hw *hw, u8 addr, - u8 *data, int len) -{ - int err; - - mutex_lock(&hw->page_lock); - err = st_lsm6dsx_set_page(hw, true); - if (err < 0) - goto out; - - err = regmap_bulk_write(hw->regmap, addr, data, len); - - st_lsm6dsx_set_page(hw, false); -out: - mutex_unlock(&hw->page_lock); - - return err; -} - -static int -st_lsm6dsx_shub_write_reg_with_mask(struct st_lsm6dsx_hw *hw, u8 addr, - u8 mask, u8 val) -{ - int err; - - mutex_lock(&hw->page_lock); - err = st_lsm6dsx_set_page(hw, true); - if (err < 0) - goto out; - - err = regmap_update_bits(hw->regmap, addr, mask, val); - - st_lsm6dsx_set_page(hw, false); -out: - mutex_unlock(&hw->page_lock); - - return err; -} - -static int st_lsm6dsx_shub_master_enable(struct st_lsm6dsx_sensor *sensor, - bool enable) -{ - const struct st_lsm6dsx_shub_settings *hub_settings; - struct st_lsm6dsx_hw *hw = sensor->hw; - unsigned int data; - int err; - - /* enable acc sensor as trigger */ - err = st_lsm6dsx_sensor_set_enable(sensor, enable); - if (err < 0) - return err; - - mutex_lock(&hw->page_lock); - - hub_settings = &hw->settings->shub_settings; - if (hub_settings->master_en.sec_page) { - err = st_lsm6dsx_set_page(hw, true); - if (err < 0) - goto out; - } - - data = ST_LSM6DSX_SHIFT_VAL(enable, hub_settings->master_en.mask); - err = regmap_update_bits(hw->regmap, hub_settings->master_en.addr, - hub_settings->master_en.mask, data); - - if (hub_settings->master_en.sec_page) - st_lsm6dsx_set_page(hw, false); -out: - mutex_unlock(&hw->page_lock); - - return err; -} - -/* - * st_lsm6dsx_shub_read - read data from slave device register - * - * Read data from slave device register. SLV0 is used for - * one-shot read operation - */ -static int -st_lsm6dsx_shub_read(struct st_lsm6dsx_sensor *sensor, u8 addr, - u8 *data, int len) -{ - const struct st_lsm6dsx_shub_settings *hub_settings; - u8 config[3], slv_addr, slv_config = 0; - struct st_lsm6dsx_hw *hw = sensor->hw; - const struct st_lsm6dsx_reg *aux_sens; - int err; - - hub_settings = &hw->settings->shub_settings; - slv_addr = ST_LSM6DSX_SLV_ADDR(0, hub_settings->slv0_addr); - aux_sens = &hw->settings->shub_settings.aux_sens; - /* do not overwrite aux_sens */ - if (slv_addr + 2 == aux_sens->addr) - slv_config = ST_LSM6DSX_SHIFT_VAL(3, aux_sens->mask); - - config[0] = (sensor->ext_info.addr << 1) | 1; - config[1] = addr; - config[2] = (len & ST_LS6DSX_READ_OP_MASK) | slv_config; - - err = st_lsm6dsx_shub_write_reg(hw, slv_addr, config, - sizeof(config)); - if (err < 0) - return err; - - err = st_lsm6dsx_shub_master_enable(sensor, true); - if (err < 0) - return err; - - st_lsm6dsx_shub_wait_complete(hw); - - err = st_lsm6dsx_shub_read_output(hw, data, - len & ST_LS6DSX_READ_OP_MASK); - if (err < 0) - return err; - - st_lsm6dsx_shub_master_enable(sensor, false); - - config[0] = hub_settings->pause; - config[1] = 0; - config[2] = slv_config; - return st_lsm6dsx_shub_write_reg(hw, slv_addr, config, - sizeof(config)); -} - -/* - * st_lsm6dsx_shub_write - write data to slave device register - * - * Write data from slave device register. SLV0 is used for - * one-shot write operation - */ -static int -st_lsm6dsx_shub_write(struct st_lsm6dsx_sensor *sensor, u8 addr, - u8 *data, int len) -{ - const struct st_lsm6dsx_shub_settings *hub_settings; - struct st_lsm6dsx_hw *hw = sensor->hw; - u8 config[2], slv_addr; - int err, i; - - hub_settings = &hw->settings->shub_settings; - if (hub_settings->wr_once.addr) { - unsigned int data; - - data = ST_LSM6DSX_SHIFT_VAL(1, hub_settings->wr_once.mask); - err = st_lsm6dsx_shub_write_reg_with_mask(hw, - hub_settings->wr_once.addr, - hub_settings->wr_once.mask, - data); - if (err < 0) - return err; - } - - slv_addr = ST_LSM6DSX_SLV_ADDR(0, hub_settings->slv0_addr); - config[0] = sensor->ext_info.addr << 1; - for (i = 0 ; i < len; i++) { - config[1] = addr + i; - - err = st_lsm6dsx_shub_write_reg(hw, slv_addr, config, - sizeof(config)); - if (err < 0) - return err; - - err = st_lsm6dsx_shub_write_reg(hw, hub_settings->dw_slv0_addr, - &data[i], 1); - if (err < 0) - return err; - - err = st_lsm6dsx_shub_master_enable(sensor, true); - if (err < 0) - return err; - - st_lsm6dsx_shub_wait_complete(hw); - - st_lsm6dsx_shub_master_enable(sensor, false); - } - - config[0] = hub_settings->pause; - config[1] = 0; - return st_lsm6dsx_shub_write_reg(hw, slv_addr, config, sizeof(config)); -} - -static int -st_lsm6dsx_shub_write_with_mask(struct st_lsm6dsx_sensor *sensor, - u8 addr, u8 mask, u8 val) -{ - int err; - u8 data; - - err = st_lsm6dsx_shub_read(sensor, addr, &data, sizeof(data)); - if (err < 0) - return err; - - data = ((data & ~mask) | (val << __ffs(mask) & mask)); - - return st_lsm6dsx_shub_write(sensor, addr, &data, sizeof(data)); -} - -static int -st_lsm6dsx_shub_get_odr_val(struct st_lsm6dsx_sensor *sensor, - u32 odr, u16 *val) -{ - const struct st_lsm6dsx_ext_dev_settings *settings; - int i; - - settings = sensor->ext_info.settings; - for (i = 0; i < settings->odr_table.odr_len; i++) { - if (settings->odr_table.odr_avl[i].milli_hz == odr) - break; - } - - if (i == settings->odr_table.odr_len) - return -EINVAL; - - *val = settings->odr_table.odr_avl[i].val; - return 0; -} - -static int -st_lsm6dsx_shub_set_odr(struct st_lsm6dsx_sensor *sensor, u32 odr) -{ - const struct st_lsm6dsx_ext_dev_settings *settings; - u16 val; - int err; - - err = st_lsm6dsx_shub_get_odr_val(sensor, odr, &val); - if (err < 0) - return err; - - settings = sensor->ext_info.settings; - return st_lsm6dsx_shub_write_with_mask(sensor, - settings->odr_table.reg.addr, - settings->odr_table.reg.mask, - val); -} - -/* use SLV{1,2,3} for FIFO read operations */ -static int -st_lsm6dsx_shub_config_channels(struct st_lsm6dsx_sensor *sensor, - bool enable) -{ - const struct st_lsm6dsx_shub_settings *hub_settings; - const struct st_lsm6dsx_ext_dev_settings *settings; - u8 config[9] = {}, enable_mask, slv_addr; - struct st_lsm6dsx_hw *hw = sensor->hw; - struct st_lsm6dsx_sensor *cur_sensor; - int i, j = 0; - - hub_settings = &hw->settings->shub_settings; - if (enable) - enable_mask = hw->enable_mask | BIT(sensor->id); - else - enable_mask = hw->enable_mask & ~BIT(sensor->id); - - for (i = ST_LSM6DSX_ID_EXT0; i <= ST_LSM6DSX_ID_EXT2; i++) { - if (!hw->iio_devs[i]) - continue; - - cur_sensor = iio_priv(hw->iio_devs[i]); - if (!(enable_mask & BIT(cur_sensor->id))) - continue; - - settings = cur_sensor->ext_info.settings; - config[j] = (sensor->ext_info.addr << 1) | 1; - config[j + 1] = settings->out.addr; - config[j + 2] = (settings->out.len & ST_LS6DSX_READ_OP_MASK) | - hub_settings->batch_en; - j += 3; - } - - slv_addr = ST_LSM6DSX_SLV_ADDR(1, hub_settings->slv0_addr); - return st_lsm6dsx_shub_write_reg(hw, slv_addr, config, - sizeof(config)); -} - -int st_lsm6dsx_shub_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable) -{ - const struct st_lsm6dsx_ext_dev_settings *settings; - int err; - - err = st_lsm6dsx_shub_config_channels(sensor, enable); - if (err < 0) - return err; - - settings = sensor->ext_info.settings; - if (enable) { - err = st_lsm6dsx_shub_set_odr(sensor, - sensor->ext_info.slv_odr); - if (err < 0) - return err; - } else { - err = st_lsm6dsx_shub_write_with_mask(sensor, - settings->odr_table.reg.addr, - settings->odr_table.reg.mask, 0); - if (err < 0) - return err; - } - - if (settings->pwr_table.reg.addr) { - u8 val; - - val = enable ? settings->pwr_table.on_val - : settings->pwr_table.off_val; - err = st_lsm6dsx_shub_write_with_mask(sensor, - settings->pwr_table.reg.addr, - settings->pwr_table.reg.mask, val); - if (err < 0) - return err; - } - - return st_lsm6dsx_shub_master_enable(sensor, enable); -} - -static int -st_lsm6dsx_shub_read_oneshot(struct st_lsm6dsx_sensor *sensor, - struct iio_chan_spec const *ch, - int *val) -{ - int err, delay, len; - u8 data[4]; - - err = st_lsm6dsx_shub_set_enable(sensor, true); - if (err < 0) - return err; - - delay = 1000000000 / sensor->ext_info.slv_odr; - usleep_range(delay, 2 * delay); - - len = min_t(int, sizeof(data), ch->scan_type.realbits >> 3); - err = st_lsm6dsx_shub_read(sensor, ch->address, data, len); - if (err < 0) - return err; - - err = st_lsm6dsx_shub_set_enable(sensor, false); - if (err < 0) - return err; - - switch (len) { - case 2: - *val = (s16)le16_to_cpu(*((__le16 *)data)); - break; - default: - return -EINVAL; - } - - return IIO_VAL_INT; -} - -static int -st_lsm6dsx_shub_read_raw(struct iio_dev *iio_dev, - struct iio_chan_spec const *ch, - int *val, int *val2, long mask) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); - int ret; - - switch (mask) { - case IIO_CHAN_INFO_RAW: - if (!iio_device_claim_direct(iio_dev)) - return -EBUSY; - - ret = st_lsm6dsx_shub_read_oneshot(sensor, ch, val); - iio_device_release_direct(iio_dev); - break; - case IIO_CHAN_INFO_SAMP_FREQ: - *val = sensor->ext_info.slv_odr / 1000; - *val2 = (sensor->ext_info.slv_odr % 1000) * 1000; - ret = IIO_VAL_INT_PLUS_MICRO; - break; - case IIO_CHAN_INFO_SCALE: - *val = 0; - *val2 = sensor->gain; - ret = IIO_VAL_INT_PLUS_MICRO; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static int -st_lsm6dsx_shub_set_full_scale(struct st_lsm6dsx_sensor *sensor, - u32 gain) -{ - const struct st_lsm6dsx_fs_table_entry *fs_table; - int i, err; - - fs_table = &sensor->ext_info.settings->fs_table; - if (!fs_table->reg.addr) - return -ENOTSUPP; - - for (i = 0; i < fs_table->fs_len; i++) { - if (fs_table->fs_avl[i].gain == gain) - break; - } - - if (i == fs_table->fs_len) - return -EINVAL; - - err = st_lsm6dsx_shub_write_with_mask(sensor, fs_table->reg.addr, - fs_table->reg.mask, - fs_table->fs_avl[i].val); - if (err < 0) - return err; - - sensor->gain = gain; - - return 0; -} - -static int -__st_lsm6dsx_shub_write_raw(struct iio_dev *iio_dev, - struct iio_chan_spec const *chan, - int val, int val2, long mask) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); - int err; - - switch (mask) { - case IIO_CHAN_INFO_SAMP_FREQ: { - struct st_lsm6dsx_hw *hw = sensor->hw; - struct st_lsm6dsx_sensor *ref_sensor; - u8 odr_val; - u16 data; - int odr; - - val = val * 1000 + val2 / 1000; - err = st_lsm6dsx_shub_get_odr_val(sensor, val, &data); - if (err) - return err; - - ref_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]); - odr = st_lsm6dsx_check_odr(ref_sensor, val, &odr_val); - if (odr < 0) - return odr; - - sensor->ext_info.slv_odr = val; - sensor->odr = odr; - sensor->hwfifo_odr_mHz = odr; - return 0; - } - case IIO_CHAN_INFO_SCALE: - return st_lsm6dsx_shub_set_full_scale(sensor, val2); - default: - return -EINVAL; - } -} - -static int -st_lsm6dsx_shub_write_raw(struct iio_dev *iio_dev, - struct iio_chan_spec const *chan, - int val, int val2, long mask) -{ - int ret; - - if (!iio_device_claim_direct(iio_dev)) - return -EBUSY; - - ret = __st_lsm6dsx_shub_write_raw(iio_dev, chan, val, val2, mask); - - iio_device_release_direct(iio_dev); - - return ret; -} - -static ssize_t -st_lsm6dsx_shub_sampling_freq_avail(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev)); - const struct st_lsm6dsx_ext_dev_settings *settings; - int i, len = 0; - - settings = sensor->ext_info.settings; - for (i = 0; i < settings->odr_table.odr_len; i++) { - u32 val = settings->odr_table.odr_avl[i].milli_hz; - - len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%03d ", - val / 1000, val % 1000); - } - buf[len - 1] = '\n'; - - return len; -} - -static ssize_t st_lsm6dsx_shub_scale_avail(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev)); - const struct st_lsm6dsx_ext_dev_settings *settings; - int i, len = 0; - - settings = sensor->ext_info.settings; - for (i = 0; i < settings->fs_table.fs_len; i++) - len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ", - settings->fs_table.fs_avl[i].gain); - buf[len - 1] = '\n'; - - return len; -} - -static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(st_lsm6dsx_shub_sampling_freq_avail); -static IIO_DEVICE_ATTR(in_scale_available, 0444, - st_lsm6dsx_shub_scale_avail, NULL, 0); -static struct attribute *st_lsm6dsx_shub_attributes[] = { - &iio_dev_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_in_scale_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group st_lsm6dsx_shub_attribute_group = { - .attrs = st_lsm6dsx_shub_attributes, -}; - -static const struct iio_info st_lsm6dsx_shub_info = { - .attrs = &st_lsm6dsx_shub_attribute_group, - .read_raw = st_lsm6dsx_shub_read_raw, - .write_raw = st_lsm6dsx_shub_write_raw, - .hwfifo_set_watermark = st_lsm6dsx_set_watermark, -}; - -static struct iio_dev * -st_lsm6dsx_shub_alloc_iiodev(struct st_lsm6dsx_hw *hw, - enum st_lsm6dsx_sensor_id id, - const struct st_lsm6dsx_ext_dev_settings *info, - u8 i2c_addr, const char *name) -{ - enum st_lsm6dsx_sensor_id ref_id = ST_LSM6DSX_ID_ACC; - struct iio_chan_spec *ext_channels; - struct st_lsm6dsx_sensor *sensor; - struct iio_dev *iio_dev; - - iio_dev = devm_iio_device_alloc(hw->dev, sizeof(*sensor)); - if (!iio_dev) - return NULL; - - iio_dev->modes = INDIO_DIRECT_MODE; - iio_dev->info = &st_lsm6dsx_shub_info; - - sensor = iio_priv(iio_dev); - sensor->id = id; - sensor->hw = hw; - sensor->odr = hw->settings->odr_table[ref_id].odr_avl[0].milli_hz; - sensor->hwfifo_odr_mHz = sensor->odr; - sensor->ext_info.slv_odr = info->odr_table.odr_avl[0].milli_hz; - sensor->gain = info->fs_table.fs_avl[0].gain; - sensor->ext_info.settings = info; - sensor->ext_info.addr = i2c_addr; - sensor->watermark = 1; - - switch (info->id) { - case ST_LSM6DSX_ID_MAGN: { - const struct iio_chan_spec magn_channels[] = { - ST_LSM6DSX_CHANNEL(IIO_MAGN, info->out.addr, - IIO_MOD_X, 0), - ST_LSM6DSX_CHANNEL(IIO_MAGN, info->out.addr + 2, - IIO_MOD_Y, 1), - ST_LSM6DSX_CHANNEL(IIO_MAGN, info->out.addr + 4, - IIO_MOD_Z, 2), - IIO_CHAN_SOFT_TIMESTAMP(3), - }; - - ext_channels = devm_kzalloc(hw->dev, sizeof(magn_channels), - GFP_KERNEL); - if (!ext_channels) - return NULL; - - memcpy(ext_channels, magn_channels, sizeof(magn_channels)); - iio_dev->available_scan_masks = st_lsm6dsx_available_scan_masks; - iio_dev->channels = ext_channels; - iio_dev->num_channels = ARRAY_SIZE(magn_channels); - - scnprintf(sensor->name, sizeof(sensor->name), "%s_magn", - name); - break; - } - default: - return NULL; - } - iio_dev->name = sensor->name; - - return iio_dev; -} - -static int st_lsm6dsx_shub_init_device(struct st_lsm6dsx_sensor *sensor) -{ - const struct st_lsm6dsx_ext_dev_settings *settings; - int err; - - settings = sensor->ext_info.settings; - if (settings->bdu.addr) { - err = st_lsm6dsx_shub_write_with_mask(sensor, - settings->bdu.addr, - settings->bdu.mask, 1); - if (err < 0) - return err; - } - - if (settings->temp_comp.addr) { - err = st_lsm6dsx_shub_write_with_mask(sensor, - settings->temp_comp.addr, - settings->temp_comp.mask, 1); - if (err < 0) - return err; - } - - if (settings->off_canc.addr) { - err = st_lsm6dsx_shub_write_with_mask(sensor, - settings->off_canc.addr, - settings->off_canc.mask, 1); - if (err < 0) - return err; - } - - return 0; -} - -static int -st_lsm6dsx_shub_check_wai(struct st_lsm6dsx_hw *hw, u8 *i2c_addr, - const struct st_lsm6dsx_ext_dev_settings *settings) -{ - const struct st_lsm6dsx_shub_settings *hub_settings; - u8 config[3], data, slv_addr, slv_config = 0; - const struct st_lsm6dsx_reg *aux_sens; - struct st_lsm6dsx_sensor *sensor; - bool found = false; - int i, err; - - sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]); - hub_settings = &hw->settings->shub_settings; - aux_sens = &hw->settings->shub_settings.aux_sens; - slv_addr = ST_LSM6DSX_SLV_ADDR(0, hub_settings->slv0_addr); - /* do not overwrite aux_sens */ - if (slv_addr + 2 == aux_sens->addr) - slv_config = ST_LSM6DSX_SHIFT_VAL(3, aux_sens->mask); - - for (i = 0; i < ARRAY_SIZE(settings->i2c_addr); i++) { - if (!settings->i2c_addr[i]) - continue; - - /* read wai slave register */ - config[0] = (settings->i2c_addr[i] << 1) | 0x1; - config[1] = settings->wai.addr; - config[2] = 0x1 | slv_config; - - err = st_lsm6dsx_shub_write_reg(hw, slv_addr, config, - sizeof(config)); - if (err < 0) - return err; - - err = st_lsm6dsx_shub_master_enable(sensor, true); - if (err < 0) - return err; - - st_lsm6dsx_shub_wait_complete(hw); - - err = st_lsm6dsx_shub_read_output(hw, &data, sizeof(data)); - - st_lsm6dsx_shub_master_enable(sensor, false); - - if (err < 0) - return err; - - if (data != settings->wai.val) - continue; - - *i2c_addr = settings->i2c_addr[i]; - found = true; - break; - } - - /* reset SLV0 channel */ - config[0] = hub_settings->pause; - config[1] = 0; - config[2] = slv_config; - err = st_lsm6dsx_shub_write_reg(hw, slv_addr, config, - sizeof(config)); - if (err < 0) - return err; - - return found ? 0 : -ENODEV; -} - -int st_lsm6dsx_shub_probe(struct st_lsm6dsx_hw *hw, const char *name) -{ - enum st_lsm6dsx_sensor_id id = ST_LSM6DSX_ID_EXT0; - struct st_lsm6dsx_sensor *sensor; - int err, i, num_ext_dev = 0; - u8 i2c_addr = 0; - - for (i = 0; i < ARRAY_SIZE(st_lsm6dsx_ext_dev_table); i++) { - err = st_lsm6dsx_shub_check_wai(hw, &i2c_addr, - &st_lsm6dsx_ext_dev_table[i]); - if (err == -ENODEV) - continue; - else if (err < 0) - return err; - - hw->iio_devs[id] = st_lsm6dsx_shub_alloc_iiodev(hw, id, - &st_lsm6dsx_ext_dev_table[i], - i2c_addr, name); - if (!hw->iio_devs[id]) - return -ENOMEM; - - sensor = iio_priv(hw->iio_devs[id]); - err = st_lsm6dsx_shub_init_device(sensor); - if (err < 0) - return err; - - if (++num_ext_dev >= hw->settings->shub_settings.num_ext_dev) - break; - id++; - } - - return 0; -} -- cgit v1.2.3