162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * STMicroelectronics st_lsm6dsx sensor driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2016 STMicroelectronics Inc. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Lorenzo Bianconi <lorenzo.bianconi@st.com> 862306a36Sopenharmony_ci * Denis Ciocca <denis.ciocca@st.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#ifndef ST_LSM6DSX_H 1262306a36Sopenharmony_ci#define ST_LSM6DSX_H 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <linux/device.h> 1562306a36Sopenharmony_ci#include <linux/iio/iio.h> 1662306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define ST_LSM6DS3_DEV_NAME "lsm6ds3" 1962306a36Sopenharmony_ci#define ST_LSM6DS3H_DEV_NAME "lsm6ds3h" 2062306a36Sopenharmony_ci#define ST_LSM6DSL_DEV_NAME "lsm6dsl" 2162306a36Sopenharmony_ci#define ST_LSM6DSM_DEV_NAME "lsm6dsm" 2262306a36Sopenharmony_ci#define ST_ISM330DLC_DEV_NAME "ism330dlc" 2362306a36Sopenharmony_ci#define ST_LSM6DSO_DEV_NAME "lsm6dso" 2462306a36Sopenharmony_ci#define ST_ASM330LHH_DEV_NAME "asm330lhh" 2562306a36Sopenharmony_ci#define ST_LSM6DSOX_DEV_NAME "lsm6dsox" 2662306a36Sopenharmony_ci#define ST_LSM6DSR_DEV_NAME "lsm6dsr" 2762306a36Sopenharmony_ci#define ST_LSM6DS3TRC_DEV_NAME "lsm6ds3tr-c" 2862306a36Sopenharmony_ci#define ST_ISM330DHCX_DEV_NAME "ism330dhcx" 2962306a36Sopenharmony_ci#define ST_LSM9DS1_DEV_NAME "lsm9ds1-imu" 3062306a36Sopenharmony_ci#define ST_LSM6DS0_DEV_NAME "lsm6ds0" 3162306a36Sopenharmony_ci#define ST_LSM6DSRX_DEV_NAME "lsm6dsrx" 3262306a36Sopenharmony_ci#define ST_LSM6DST_DEV_NAME "lsm6dst" 3362306a36Sopenharmony_ci#define ST_LSM6DSOP_DEV_NAME "lsm6dsop" 3462306a36Sopenharmony_ci#define ST_ASM330LHHX_DEV_NAME "asm330lhhx" 3562306a36Sopenharmony_ci#define ST_LSM6DSTX_DEV_NAME "lsm6dstx" 3662306a36Sopenharmony_ci#define ST_LSM6DSV_DEV_NAME "lsm6dsv" 3762306a36Sopenharmony_ci#define ST_LSM6DSV16X_DEV_NAME "lsm6dsv16x" 3862306a36Sopenharmony_ci#define ST_LSM6DSO16IS_DEV_NAME "lsm6dso16is" 3962306a36Sopenharmony_ci#define ST_ISM330IS_DEV_NAME "ism330is" 4062306a36Sopenharmony_ci#define ST_ASM330LHB_DEV_NAME "asm330lhb" 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cienum st_lsm6dsx_hw_id { 4362306a36Sopenharmony_ci ST_LSM6DS3_ID = 1, 4462306a36Sopenharmony_ci ST_LSM6DS3H_ID, 4562306a36Sopenharmony_ci ST_LSM6DSL_ID, 4662306a36Sopenharmony_ci ST_LSM6DSM_ID, 4762306a36Sopenharmony_ci ST_ISM330DLC_ID, 4862306a36Sopenharmony_ci ST_LSM6DSO_ID, 4962306a36Sopenharmony_ci ST_ASM330LHH_ID, 5062306a36Sopenharmony_ci ST_LSM6DSOX_ID, 5162306a36Sopenharmony_ci ST_LSM6DSR_ID, 5262306a36Sopenharmony_ci ST_LSM6DS3TRC_ID, 5362306a36Sopenharmony_ci ST_ISM330DHCX_ID, 5462306a36Sopenharmony_ci ST_LSM9DS1_ID, 5562306a36Sopenharmony_ci ST_LSM6DS0_ID, 5662306a36Sopenharmony_ci ST_LSM6DSRX_ID, 5762306a36Sopenharmony_ci ST_LSM6DST_ID, 5862306a36Sopenharmony_ci ST_LSM6DSOP_ID, 5962306a36Sopenharmony_ci ST_ASM330LHHX_ID, 6062306a36Sopenharmony_ci ST_LSM6DSTX_ID, 6162306a36Sopenharmony_ci ST_LSM6DSV_ID, 6262306a36Sopenharmony_ci ST_LSM6DSV16X_ID, 6362306a36Sopenharmony_ci ST_LSM6DSO16IS_ID, 6462306a36Sopenharmony_ci ST_ISM330IS_ID, 6562306a36Sopenharmony_ci ST_ASM330LHB_ID, 6662306a36Sopenharmony_ci ST_LSM6DSX_MAX_ID, 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci#define ST_LSM6DSX_BUFF_SIZE 512 7062306a36Sopenharmony_ci#define ST_LSM6DSX_CHAN_SIZE 2 7162306a36Sopenharmony_ci#define ST_LSM6DSX_SAMPLE_SIZE 6 7262306a36Sopenharmony_ci#define ST_LSM6DSX_TAG_SIZE 1 7362306a36Sopenharmony_ci#define ST_LSM6DSX_TAGGED_SAMPLE_SIZE (ST_LSM6DSX_SAMPLE_SIZE + \ 7462306a36Sopenharmony_ci ST_LSM6DSX_TAG_SIZE) 7562306a36Sopenharmony_ci#define ST_LSM6DSX_MAX_WORD_LEN ((32 / ST_LSM6DSX_SAMPLE_SIZE) * \ 7662306a36Sopenharmony_ci ST_LSM6DSX_SAMPLE_SIZE) 7762306a36Sopenharmony_ci#define ST_LSM6DSX_MAX_TAGGED_WORD_LEN ((32 / ST_LSM6DSX_TAGGED_SAMPLE_SIZE) \ 7862306a36Sopenharmony_ci * ST_LSM6DSX_TAGGED_SAMPLE_SIZE) 7962306a36Sopenharmony_ci#define ST_LSM6DSX_SHIFT_VAL(val, mask) (((val) << __ffs(mask)) & (mask)) 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci#define ST_LSM6DSX_CHANNEL_ACC(chan_type, addr, mod, scan_idx) \ 8262306a36Sopenharmony_ci{ \ 8362306a36Sopenharmony_ci .type = chan_type, \ 8462306a36Sopenharmony_ci .address = addr, \ 8562306a36Sopenharmony_ci .modified = 1, \ 8662306a36Sopenharmony_ci .channel2 = mod, \ 8762306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 8862306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 8962306a36Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 9062306a36Sopenharmony_ci .scan_index = scan_idx, \ 9162306a36Sopenharmony_ci .scan_type = { \ 9262306a36Sopenharmony_ci .sign = 's', \ 9362306a36Sopenharmony_ci .realbits = 16, \ 9462306a36Sopenharmony_ci .storagebits = 16, \ 9562306a36Sopenharmony_ci .endianness = IIO_LE, \ 9662306a36Sopenharmony_ci }, \ 9762306a36Sopenharmony_ci .event_spec = &st_lsm6dsx_event, \ 9862306a36Sopenharmony_ci .ext_info = st_lsm6dsx_ext_info, \ 9962306a36Sopenharmony_ci .num_event_specs = 1, \ 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci#define ST_LSM6DSX_CHANNEL(chan_type, addr, mod, scan_idx) \ 10362306a36Sopenharmony_ci{ \ 10462306a36Sopenharmony_ci .type = chan_type, \ 10562306a36Sopenharmony_ci .address = addr, \ 10662306a36Sopenharmony_ci .modified = 1, \ 10762306a36Sopenharmony_ci .channel2 = mod, \ 10862306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 10962306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 11062306a36Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 11162306a36Sopenharmony_ci .scan_index = scan_idx, \ 11262306a36Sopenharmony_ci .scan_type = { \ 11362306a36Sopenharmony_ci .sign = 's', \ 11462306a36Sopenharmony_ci .realbits = 16, \ 11562306a36Sopenharmony_ci .storagebits = 16, \ 11662306a36Sopenharmony_ci .endianness = IIO_LE, \ 11762306a36Sopenharmony_ci }, \ 11862306a36Sopenharmony_ci .ext_info = st_lsm6dsx_ext_info, \ 11962306a36Sopenharmony_ci} 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cistruct st_lsm6dsx_reg { 12262306a36Sopenharmony_ci u8 addr; 12362306a36Sopenharmony_ci u8 mask; 12462306a36Sopenharmony_ci}; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistruct st_lsm6dsx_sensor; 12762306a36Sopenharmony_cistruct st_lsm6dsx_hw; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistruct st_lsm6dsx_odr { 13062306a36Sopenharmony_ci u32 milli_hz; 13162306a36Sopenharmony_ci u8 val; 13262306a36Sopenharmony_ci}; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci#define ST_LSM6DSX_ODR_LIST_SIZE 8 13562306a36Sopenharmony_cistruct st_lsm6dsx_odr_table_entry { 13662306a36Sopenharmony_ci struct st_lsm6dsx_reg reg; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci struct st_lsm6dsx_odr odr_avl[ST_LSM6DSX_ODR_LIST_SIZE]; 13962306a36Sopenharmony_ci int odr_len; 14062306a36Sopenharmony_ci}; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistruct st_lsm6dsx_samples_to_discard { 14362306a36Sopenharmony_ci struct { 14462306a36Sopenharmony_ci u32 milli_hz; 14562306a36Sopenharmony_ci u16 samples; 14662306a36Sopenharmony_ci } val[ST_LSM6DSX_ODR_LIST_SIZE]; 14762306a36Sopenharmony_ci}; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistruct st_lsm6dsx_fs { 15062306a36Sopenharmony_ci u32 gain; 15162306a36Sopenharmony_ci u8 val; 15262306a36Sopenharmony_ci}; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci#define ST_LSM6DSX_FS_LIST_SIZE 4 15562306a36Sopenharmony_cistruct st_lsm6dsx_fs_table_entry { 15662306a36Sopenharmony_ci struct st_lsm6dsx_reg reg; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci struct st_lsm6dsx_fs fs_avl[ST_LSM6DSX_FS_LIST_SIZE]; 15962306a36Sopenharmony_ci int fs_len; 16062306a36Sopenharmony_ci}; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci/** 16362306a36Sopenharmony_ci * struct st_lsm6dsx_fifo_ops - ST IMU FIFO settings 16462306a36Sopenharmony_ci * @update_fifo: Update FIFO configuration callback. 16562306a36Sopenharmony_ci * @read_fifo: Read FIFO callback. 16662306a36Sopenharmony_ci * @fifo_th: FIFO threshold register info (addr + mask). 16762306a36Sopenharmony_ci * @fifo_diff: FIFO diff status register info (addr + mask). 16862306a36Sopenharmony_ci * @max_size: Sensor max fifo length in FIFO words. 16962306a36Sopenharmony_ci * @th_wl: FIFO threshold word length. 17062306a36Sopenharmony_ci */ 17162306a36Sopenharmony_cistruct st_lsm6dsx_fifo_ops { 17262306a36Sopenharmony_ci int (*update_fifo)(struct st_lsm6dsx_sensor *sensor, bool enable); 17362306a36Sopenharmony_ci int (*read_fifo)(struct st_lsm6dsx_hw *hw); 17462306a36Sopenharmony_ci struct { 17562306a36Sopenharmony_ci u8 addr; 17662306a36Sopenharmony_ci u16 mask; 17762306a36Sopenharmony_ci } fifo_th; 17862306a36Sopenharmony_ci struct { 17962306a36Sopenharmony_ci u8 addr; 18062306a36Sopenharmony_ci u16 mask; 18162306a36Sopenharmony_ci } fifo_diff; 18262306a36Sopenharmony_ci u16 max_size; 18362306a36Sopenharmony_ci u8 th_wl; 18462306a36Sopenharmony_ci}; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci/** 18762306a36Sopenharmony_ci * struct st_lsm6dsx_hw_ts_settings - ST IMU hw timer settings 18862306a36Sopenharmony_ci * @timer_en: Hw timer enable register info (addr + mask). 18962306a36Sopenharmony_ci * @hr_timer: Hw timer resolution register info (addr + mask). 19062306a36Sopenharmony_ci * @fifo_en: Hw timer FIFO enable register info (addr + mask). 19162306a36Sopenharmony_ci * @decimator: Hw timer FIFO decimator register info (addr + mask). 19262306a36Sopenharmony_ci * @freq_fine: Difference in % of ODR with respect to the typical. 19362306a36Sopenharmony_ci */ 19462306a36Sopenharmony_cistruct st_lsm6dsx_hw_ts_settings { 19562306a36Sopenharmony_ci struct st_lsm6dsx_reg timer_en; 19662306a36Sopenharmony_ci struct st_lsm6dsx_reg hr_timer; 19762306a36Sopenharmony_ci struct st_lsm6dsx_reg fifo_en; 19862306a36Sopenharmony_ci struct st_lsm6dsx_reg decimator; 19962306a36Sopenharmony_ci u8 freq_fine; 20062306a36Sopenharmony_ci}; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci/** 20362306a36Sopenharmony_ci * struct st_lsm6dsx_shub_settings - ST IMU hw i2c controller settings 20462306a36Sopenharmony_ci * @page_mux: register page mux info (addr + mask). 20562306a36Sopenharmony_ci * @master_en: master config register info (addr + mask). 20662306a36Sopenharmony_ci * @pullup_en: i2c controller pull-up register info (addr + mask). 20762306a36Sopenharmony_ci * @aux_sens: aux sensor register info (addr + mask). 20862306a36Sopenharmony_ci * @wr_once: write_once register info (addr + mask). 20962306a36Sopenharmony_ci * @emb_func: embedded function register info (addr + mask). 21062306a36Sopenharmony_ci * @num_ext_dev: max number of slave devices. 21162306a36Sopenharmony_ci * @shub_out: sensor hub first output register info. 21262306a36Sopenharmony_ci * @slv0_addr: slave0 address in secondary page. 21362306a36Sopenharmony_ci * @dw_slv0_addr: slave0 write register address in secondary page. 21462306a36Sopenharmony_ci * @batch_en: Enable/disable FIFO batching. 21562306a36Sopenharmony_ci * @pause: controller pause value. 21662306a36Sopenharmony_ci */ 21762306a36Sopenharmony_cistruct st_lsm6dsx_shub_settings { 21862306a36Sopenharmony_ci struct st_lsm6dsx_reg page_mux; 21962306a36Sopenharmony_ci struct { 22062306a36Sopenharmony_ci bool sec_page; 22162306a36Sopenharmony_ci u8 addr; 22262306a36Sopenharmony_ci u8 mask; 22362306a36Sopenharmony_ci } master_en; 22462306a36Sopenharmony_ci struct { 22562306a36Sopenharmony_ci bool sec_page; 22662306a36Sopenharmony_ci u8 addr; 22762306a36Sopenharmony_ci u8 mask; 22862306a36Sopenharmony_ci } pullup_en; 22962306a36Sopenharmony_ci struct st_lsm6dsx_reg aux_sens; 23062306a36Sopenharmony_ci struct st_lsm6dsx_reg wr_once; 23162306a36Sopenharmony_ci struct st_lsm6dsx_reg emb_func; 23262306a36Sopenharmony_ci u8 num_ext_dev; 23362306a36Sopenharmony_ci struct { 23462306a36Sopenharmony_ci bool sec_page; 23562306a36Sopenharmony_ci u8 addr; 23662306a36Sopenharmony_ci } shub_out; 23762306a36Sopenharmony_ci u8 slv0_addr; 23862306a36Sopenharmony_ci u8 dw_slv0_addr; 23962306a36Sopenharmony_ci u8 batch_en; 24062306a36Sopenharmony_ci u8 pause; 24162306a36Sopenharmony_ci}; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_cistruct st_lsm6dsx_event_settings { 24462306a36Sopenharmony_ci struct st_lsm6dsx_reg enable_reg; 24562306a36Sopenharmony_ci struct st_lsm6dsx_reg wakeup_reg; 24662306a36Sopenharmony_ci u8 wakeup_src_reg; 24762306a36Sopenharmony_ci u8 wakeup_src_status_mask; 24862306a36Sopenharmony_ci u8 wakeup_src_z_mask; 24962306a36Sopenharmony_ci u8 wakeup_src_y_mask; 25062306a36Sopenharmony_ci u8 wakeup_src_x_mask; 25162306a36Sopenharmony_ci}; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_cienum st_lsm6dsx_ext_sensor_id { 25462306a36Sopenharmony_ci ST_LSM6DSX_ID_MAGN, 25562306a36Sopenharmony_ci}; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci/** 25862306a36Sopenharmony_ci * struct st_lsm6dsx_ext_dev_settings - i2c controller slave settings 25962306a36Sopenharmony_ci * @i2c_addr: I2c slave address list. 26062306a36Sopenharmony_ci * @wai: Wai address info. 26162306a36Sopenharmony_ci * @id: external sensor id. 26262306a36Sopenharmony_ci * @odr_table: Output data rate of the sensor [Hz]. 26362306a36Sopenharmony_ci * @fs_table: Configured sensor sensitivity table depending on full scale. 26462306a36Sopenharmony_ci * @temp_comp: Temperature compensation register info (addr + mask). 26562306a36Sopenharmony_ci * @pwr_table: Power on register info (addr + mask). 26662306a36Sopenharmony_ci * @off_canc: Offset cancellation register info (addr + mask). 26762306a36Sopenharmony_ci * @bdu: Block data update register info (addr + mask). 26862306a36Sopenharmony_ci * @out: Output register info. 26962306a36Sopenharmony_ci */ 27062306a36Sopenharmony_cistruct st_lsm6dsx_ext_dev_settings { 27162306a36Sopenharmony_ci u8 i2c_addr[2]; 27262306a36Sopenharmony_ci struct { 27362306a36Sopenharmony_ci u8 addr; 27462306a36Sopenharmony_ci u8 val; 27562306a36Sopenharmony_ci } wai; 27662306a36Sopenharmony_ci enum st_lsm6dsx_ext_sensor_id id; 27762306a36Sopenharmony_ci struct st_lsm6dsx_odr_table_entry odr_table; 27862306a36Sopenharmony_ci struct st_lsm6dsx_fs_table_entry fs_table; 27962306a36Sopenharmony_ci struct st_lsm6dsx_reg temp_comp; 28062306a36Sopenharmony_ci struct { 28162306a36Sopenharmony_ci struct st_lsm6dsx_reg reg; 28262306a36Sopenharmony_ci u8 off_val; 28362306a36Sopenharmony_ci u8 on_val; 28462306a36Sopenharmony_ci } pwr_table; 28562306a36Sopenharmony_ci struct st_lsm6dsx_reg off_canc; 28662306a36Sopenharmony_ci struct st_lsm6dsx_reg bdu; 28762306a36Sopenharmony_ci struct { 28862306a36Sopenharmony_ci u8 addr; 28962306a36Sopenharmony_ci u8 len; 29062306a36Sopenharmony_ci } out; 29162306a36Sopenharmony_ci}; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci/** 29462306a36Sopenharmony_ci * struct st_lsm6dsx_settings - ST IMU sensor settings 29562306a36Sopenharmony_ci * @reset: register address for reset. 29662306a36Sopenharmony_ci * @boot: register address for boot. 29762306a36Sopenharmony_ci * @bdu: register address for Block Data Update. 29862306a36Sopenharmony_ci * @id: List of hw id/device name supported by the driver configuration. 29962306a36Sopenharmony_ci * @channels: IIO channels supported by the device. 30062306a36Sopenharmony_ci * @irq_config: interrupts related registers. 30162306a36Sopenharmony_ci * @drdy_mask: register info for data-ready mask (addr + mask). 30262306a36Sopenharmony_ci * @odr_table: Hw sensors odr table (Hz + val). 30362306a36Sopenharmony_ci * @samples_to_discard: Number of samples to discard for filters settling time. 30462306a36Sopenharmony_ci * @fs_table: Hw sensors gain table (gain + val). 30562306a36Sopenharmony_ci * @decimator: List of decimator register info (addr + mask). 30662306a36Sopenharmony_ci * @batch: List of FIFO batching register info (addr + mask). 30762306a36Sopenharmony_ci * @fifo_ops: Sensor hw FIFO parameters. 30862306a36Sopenharmony_ci * @ts_settings: Hw timer related settings. 30962306a36Sopenharmony_ci * @shub_settings: i2c controller related settings. 31062306a36Sopenharmony_ci */ 31162306a36Sopenharmony_cistruct st_lsm6dsx_settings { 31262306a36Sopenharmony_ci struct st_lsm6dsx_reg reset; 31362306a36Sopenharmony_ci struct st_lsm6dsx_reg boot; 31462306a36Sopenharmony_ci struct st_lsm6dsx_reg bdu; 31562306a36Sopenharmony_ci struct { 31662306a36Sopenharmony_ci enum st_lsm6dsx_hw_id hw_id; 31762306a36Sopenharmony_ci const char *name; 31862306a36Sopenharmony_ci u8 wai; 31962306a36Sopenharmony_ci } id[ST_LSM6DSX_MAX_ID]; 32062306a36Sopenharmony_ci struct { 32162306a36Sopenharmony_ci const struct iio_chan_spec *chan; 32262306a36Sopenharmony_ci int len; 32362306a36Sopenharmony_ci } channels[2]; 32462306a36Sopenharmony_ci struct { 32562306a36Sopenharmony_ci struct st_lsm6dsx_reg irq1; 32662306a36Sopenharmony_ci struct st_lsm6dsx_reg irq2; 32762306a36Sopenharmony_ci struct st_lsm6dsx_reg irq1_func; 32862306a36Sopenharmony_ci struct st_lsm6dsx_reg irq2_func; 32962306a36Sopenharmony_ci struct st_lsm6dsx_reg lir; 33062306a36Sopenharmony_ci struct st_lsm6dsx_reg clear_on_read; 33162306a36Sopenharmony_ci struct st_lsm6dsx_reg hla; 33262306a36Sopenharmony_ci struct st_lsm6dsx_reg od; 33362306a36Sopenharmony_ci } irq_config; 33462306a36Sopenharmony_ci struct st_lsm6dsx_reg drdy_mask; 33562306a36Sopenharmony_ci struct st_lsm6dsx_odr_table_entry odr_table[2]; 33662306a36Sopenharmony_ci struct st_lsm6dsx_samples_to_discard samples_to_discard[2]; 33762306a36Sopenharmony_ci struct st_lsm6dsx_fs_table_entry fs_table[2]; 33862306a36Sopenharmony_ci struct st_lsm6dsx_reg decimator[ST_LSM6DSX_MAX_ID]; 33962306a36Sopenharmony_ci struct st_lsm6dsx_reg batch[ST_LSM6DSX_MAX_ID]; 34062306a36Sopenharmony_ci struct st_lsm6dsx_fifo_ops fifo_ops; 34162306a36Sopenharmony_ci struct st_lsm6dsx_hw_ts_settings ts_settings; 34262306a36Sopenharmony_ci struct st_lsm6dsx_shub_settings shub_settings; 34362306a36Sopenharmony_ci struct st_lsm6dsx_event_settings event_settings; 34462306a36Sopenharmony_ci}; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_cienum st_lsm6dsx_sensor_id { 34762306a36Sopenharmony_ci ST_LSM6DSX_ID_GYRO, 34862306a36Sopenharmony_ci ST_LSM6DSX_ID_ACC, 34962306a36Sopenharmony_ci ST_LSM6DSX_ID_EXT0, 35062306a36Sopenharmony_ci ST_LSM6DSX_ID_EXT1, 35162306a36Sopenharmony_ci ST_LSM6DSX_ID_EXT2, 35262306a36Sopenharmony_ci ST_LSM6DSX_ID_MAX, 35362306a36Sopenharmony_ci}; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cienum st_lsm6dsx_fifo_mode { 35662306a36Sopenharmony_ci ST_LSM6DSX_FIFO_BYPASS = 0x0, 35762306a36Sopenharmony_ci ST_LSM6DSX_FIFO_CONT = 0x6, 35862306a36Sopenharmony_ci}; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci/** 36162306a36Sopenharmony_ci * struct st_lsm6dsx_sensor - ST IMU sensor instance 36262306a36Sopenharmony_ci * @name: Sensor name. 36362306a36Sopenharmony_ci * @id: Sensor identifier. 36462306a36Sopenharmony_ci * @hw: Pointer to instance of struct st_lsm6dsx_hw. 36562306a36Sopenharmony_ci * @gain: Configured sensor sensitivity. 36662306a36Sopenharmony_ci * @odr: Output data rate of the sensor [Hz]. 36762306a36Sopenharmony_ci * @samples_to_discard: Number of samples to discard for filters settling time. 36862306a36Sopenharmony_ci * @watermark: Sensor watermark level. 36962306a36Sopenharmony_ci * @decimator: Sensor decimation factor. 37062306a36Sopenharmony_ci * @sip: Number of samples in a given pattern. 37162306a36Sopenharmony_ci * @ts_ref: Sensor timestamp reference for hw one. 37262306a36Sopenharmony_ci * @ext_info: Sensor settings if it is connected to i2c controller 37362306a36Sopenharmony_ci */ 37462306a36Sopenharmony_cistruct st_lsm6dsx_sensor { 37562306a36Sopenharmony_ci char name[32]; 37662306a36Sopenharmony_ci enum st_lsm6dsx_sensor_id id; 37762306a36Sopenharmony_ci struct st_lsm6dsx_hw *hw; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci u32 gain; 38062306a36Sopenharmony_ci u32 odr; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci u16 samples_to_discard; 38362306a36Sopenharmony_ci u16 watermark; 38462306a36Sopenharmony_ci u8 decimator; 38562306a36Sopenharmony_ci u8 sip; 38662306a36Sopenharmony_ci s64 ts_ref; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci struct { 38962306a36Sopenharmony_ci const struct st_lsm6dsx_ext_dev_settings *settings; 39062306a36Sopenharmony_ci u32 slv_odr; 39162306a36Sopenharmony_ci u8 addr; 39262306a36Sopenharmony_ci } ext_info; 39362306a36Sopenharmony_ci}; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci/** 39662306a36Sopenharmony_ci * struct st_lsm6dsx_hw - ST IMU MEMS hw instance 39762306a36Sopenharmony_ci * @dev: Pointer to instance of struct device (I2C or SPI). 39862306a36Sopenharmony_ci * @regmap: Register map of the device. 39962306a36Sopenharmony_ci * @irq: Device interrupt line (I2C or SPI). 40062306a36Sopenharmony_ci * @fifo_lock: Mutex to prevent concurrent access to the hw FIFO. 40162306a36Sopenharmony_ci * @conf_lock: Mutex to prevent concurrent FIFO configuration update. 40262306a36Sopenharmony_ci * @page_lock: Mutex to prevent concurrent memory page configuration. 40362306a36Sopenharmony_ci * @suspend_mask: Suspended sensor bitmask. 40462306a36Sopenharmony_ci * @enable_mask: Enabled sensor bitmask. 40562306a36Sopenharmony_ci * @fifo_mask: Enabled hw FIFO bitmask. 40662306a36Sopenharmony_ci * @ts_gain: Hw timestamp rate after internal calibration. 40762306a36Sopenharmony_ci * @ts_sip: Total number of timestamp samples in a given pattern. 40862306a36Sopenharmony_ci * @sip: Total number of samples (acc/gyro/ts) in a given pattern. 40962306a36Sopenharmony_ci * @buff: Device read buffer. 41062306a36Sopenharmony_ci * @irq_routing: pointer to interrupt routing configuration. 41162306a36Sopenharmony_ci * @event_threshold: wakeup event threshold. 41262306a36Sopenharmony_ci * @enable_event: enabled event bitmask. 41362306a36Sopenharmony_ci * @iio_devs: Pointers to acc/gyro iio_dev instances. 41462306a36Sopenharmony_ci * @settings: Pointer to the specific sensor settings in use. 41562306a36Sopenharmony_ci * @orientation: sensor chip orientation relative to main hardware. 41662306a36Sopenharmony_ci * @scan: Temporary buffers used to align data before iio_push_to_buffers() 41762306a36Sopenharmony_ci */ 41862306a36Sopenharmony_cistruct st_lsm6dsx_hw { 41962306a36Sopenharmony_ci struct device *dev; 42062306a36Sopenharmony_ci struct regmap *regmap; 42162306a36Sopenharmony_ci int irq; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci struct mutex fifo_lock; 42462306a36Sopenharmony_ci struct mutex conf_lock; 42562306a36Sopenharmony_ci struct mutex page_lock; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci u8 suspend_mask; 42862306a36Sopenharmony_ci u8 enable_mask; 42962306a36Sopenharmony_ci u8 fifo_mask; 43062306a36Sopenharmony_ci s64 ts_gain; 43162306a36Sopenharmony_ci u8 ts_sip; 43262306a36Sopenharmony_ci u8 sip; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci const struct st_lsm6dsx_reg *irq_routing; 43562306a36Sopenharmony_ci u8 event_threshold; 43662306a36Sopenharmony_ci u8 enable_event; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci u8 *buff; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci struct iio_dev *iio_devs[ST_LSM6DSX_ID_MAX]; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci const struct st_lsm6dsx_settings *settings; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci struct iio_mount_matrix orientation; 44562306a36Sopenharmony_ci /* Ensure natural alignment of buffer elements */ 44662306a36Sopenharmony_ci struct { 44762306a36Sopenharmony_ci __le16 channels[3]; 44862306a36Sopenharmony_ci s64 ts __aligned(8); 44962306a36Sopenharmony_ci } scan[ST_LSM6DSX_ID_MAX]; 45062306a36Sopenharmony_ci}; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_cistatic __maybe_unused const struct iio_event_spec st_lsm6dsx_event = { 45362306a36Sopenharmony_ci .type = IIO_EV_TYPE_THRESH, 45462306a36Sopenharmony_ci .dir = IIO_EV_DIR_EITHER, 45562306a36Sopenharmony_ci .mask_separate = BIT(IIO_EV_INFO_VALUE) | 45662306a36Sopenharmony_ci BIT(IIO_EV_INFO_ENABLE) 45762306a36Sopenharmony_ci}; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_cistatic __maybe_unused const unsigned long st_lsm6dsx_available_scan_masks[] = { 46062306a36Sopenharmony_ci 0x7, 0x0, 46162306a36Sopenharmony_ci}; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ciextern const struct dev_pm_ops st_lsm6dsx_pm_ops; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ciint st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, 46662306a36Sopenharmony_ci struct regmap *regmap); 46762306a36Sopenharmony_ciint st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor, 46862306a36Sopenharmony_ci bool enable); 46962306a36Sopenharmony_ciint st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw); 47062306a36Sopenharmony_ciint st_lsm6dsx_set_watermark(struct iio_dev *iio_dev, unsigned int val); 47162306a36Sopenharmony_ciint st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, 47262306a36Sopenharmony_ci u16 watermark); 47362306a36Sopenharmony_ciint st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable); 47462306a36Sopenharmony_ciint st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw); 47562306a36Sopenharmony_ciint st_lsm6dsx_resume_fifo(struct st_lsm6dsx_hw *hw); 47662306a36Sopenharmony_ciint st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw); 47762306a36Sopenharmony_ciint st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw); 47862306a36Sopenharmony_ciint st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u32 odr, u8 *val); 47962306a36Sopenharmony_ciint st_lsm6dsx_shub_probe(struct st_lsm6dsx_hw *hw, const char *name); 48062306a36Sopenharmony_ciint st_lsm6dsx_shub_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable); 48162306a36Sopenharmony_ciint st_lsm6dsx_shub_read_output(struct st_lsm6dsx_hw *hw, u8 *data, int len); 48262306a36Sopenharmony_ciint st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable); 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_cistatic inline int 48562306a36Sopenharmony_cist_lsm6dsx_update_bits_locked(struct st_lsm6dsx_hw *hw, unsigned int addr, 48662306a36Sopenharmony_ci unsigned int mask, unsigned int val) 48762306a36Sopenharmony_ci{ 48862306a36Sopenharmony_ci int err; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci mutex_lock(&hw->page_lock); 49162306a36Sopenharmony_ci err = regmap_update_bits(hw->regmap, addr, mask, val); 49262306a36Sopenharmony_ci mutex_unlock(&hw->page_lock); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci return err; 49562306a36Sopenharmony_ci} 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_cistatic inline int 49862306a36Sopenharmony_cist_lsm6dsx_read_locked(struct st_lsm6dsx_hw *hw, unsigned int addr, 49962306a36Sopenharmony_ci void *val, unsigned int len) 50062306a36Sopenharmony_ci{ 50162306a36Sopenharmony_ci int err; 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci mutex_lock(&hw->page_lock); 50462306a36Sopenharmony_ci err = regmap_bulk_read(hw->regmap, addr, val, len); 50562306a36Sopenharmony_ci mutex_unlock(&hw->page_lock); 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci return err; 50862306a36Sopenharmony_ci} 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_cistatic inline int 51162306a36Sopenharmony_cist_lsm6dsx_write_locked(struct st_lsm6dsx_hw *hw, unsigned int addr, 51262306a36Sopenharmony_ci unsigned int val) 51362306a36Sopenharmony_ci{ 51462306a36Sopenharmony_ci int err; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci mutex_lock(&hw->page_lock); 51762306a36Sopenharmony_ci err = regmap_write(hw->regmap, addr, val); 51862306a36Sopenharmony_ci mutex_unlock(&hw->page_lock); 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci return err; 52162306a36Sopenharmony_ci} 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_cistatic inline const struct iio_mount_matrix * 52462306a36Sopenharmony_cist_lsm6dsx_get_mount_matrix(const struct iio_dev *iio_dev, 52562306a36Sopenharmony_ci const struct iio_chan_spec *chan) 52662306a36Sopenharmony_ci{ 52762306a36Sopenharmony_ci struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); 52862306a36Sopenharmony_ci struct st_lsm6dsx_hw *hw = sensor->hw; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci return &hw->orientation; 53162306a36Sopenharmony_ci} 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_cistatic inline int 53462306a36Sopenharmony_cist_lsm6dsx_device_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable) 53562306a36Sopenharmony_ci{ 53662306a36Sopenharmony_ci if (sensor->id == ST_LSM6DSX_ID_EXT0 || 53762306a36Sopenharmony_ci sensor->id == ST_LSM6DSX_ID_EXT1 || 53862306a36Sopenharmony_ci sensor->id == ST_LSM6DSX_ID_EXT2) 53962306a36Sopenharmony_ci return st_lsm6dsx_shub_set_enable(sensor, enable); 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci return st_lsm6dsx_sensor_set_enable(sensor, enable); 54262306a36Sopenharmony_ci} 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_cistatic const 54562306a36Sopenharmony_cistruct iio_chan_spec_ext_info __maybe_unused st_lsm6dsx_ext_info[] = { 54662306a36Sopenharmony_ci IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_lsm6dsx_get_mount_matrix), 54762306a36Sopenharmony_ci { } 54862306a36Sopenharmony_ci}; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci#endif /* ST_LSM6DSX_H */ 551