1290a6ce1SLorenzo Bianconi /* 2290a6ce1SLorenzo Bianconi * STMicroelectronics st_lsm6dsx sensor driver 3290a6ce1SLorenzo Bianconi * 4290a6ce1SLorenzo Bianconi * The ST LSM6DSx IMU MEMS series consists of 3D digital accelerometer 5290a6ce1SLorenzo Bianconi * and 3D digital gyroscope system-in-package with a digital I2C/SPI serial 6290a6ce1SLorenzo Bianconi * interface standard output. 7290a6ce1SLorenzo Bianconi * LSM6DSx IMU MEMS series has a dynamic user-selectable full-scale 8290a6ce1SLorenzo Bianconi * acceleration range of +-2/+-4/+-8/+-16 g and an angular rate range of 9290a6ce1SLorenzo Bianconi * +-125/+-245/+-500/+-1000/+-2000 dps 10290a6ce1SLorenzo Bianconi * LSM6DSx series has an integrated First-In-First-Out (FIFO) buffer 11290a6ce1SLorenzo Bianconi * allowing dynamic batching of sensor data. 12290a6ce1SLorenzo Bianconi * 13290a6ce1SLorenzo Bianconi * Supported sensors: 14290a6ce1SLorenzo Bianconi * - LSM6DS3: 15290a6ce1SLorenzo Bianconi * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 16290a6ce1SLorenzo Bianconi * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 17290a6ce1SLorenzo Bianconi * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 18290a6ce1SLorenzo Bianconi * - FIFO size: 8KB 19290a6ce1SLorenzo Bianconi * 20179c8d60SLorenzo Bianconi * - LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC: 21290a6ce1SLorenzo Bianconi * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 22290a6ce1SLorenzo Bianconi * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 23290a6ce1SLorenzo Bianconi * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 24290a6ce1SLorenzo Bianconi * - FIFO size: 4KB 25290a6ce1SLorenzo Bianconi * 26801a6e0aSLorenzo Bianconi * - LSM6DSO 27801a6e0aSLorenzo Bianconi * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 28801a6e0aSLorenzo Bianconi * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 29801a6e0aSLorenzo Bianconi * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 30801a6e0aSLorenzo Bianconi * - FIFO size: 3KB 31801a6e0aSLorenzo Bianconi * 32290a6ce1SLorenzo Bianconi * Copyright 2016 STMicroelectronics Inc. 33290a6ce1SLorenzo Bianconi * 34290a6ce1SLorenzo Bianconi * Lorenzo Bianconi <lorenzo.bianconi@st.com> 35290a6ce1SLorenzo Bianconi * Denis Ciocca <denis.ciocca@st.com> 36290a6ce1SLorenzo Bianconi * 37290a6ce1SLorenzo Bianconi * Licensed under the GPL-2. 38290a6ce1SLorenzo Bianconi */ 39290a6ce1SLorenzo Bianconi 40290a6ce1SLorenzo Bianconi #include <linux/kernel.h> 41290a6ce1SLorenzo Bianconi #include <linux/module.h> 42290a6ce1SLorenzo Bianconi #include <linux/delay.h> 43290a6ce1SLorenzo Bianconi #include <linux/iio/iio.h> 44290a6ce1SLorenzo Bianconi #include <linux/iio/sysfs.h> 45d3f77058SLorenzo Bianconi #include <linux/pm.h> 4651a8b707SLorenzo Bianconi #include <linux/regmap.h> 4751a8b707SLorenzo Bianconi #include <linux/bitfield.h> 48290a6ce1SLorenzo Bianconi 49dba32904SLorenzo Bianconi #include <linux/platform_data/st_sensors_pdata.h> 50dba32904SLorenzo Bianconi 51290a6ce1SLorenzo Bianconi #include "st_lsm6dsx.h" 52290a6ce1SLorenzo Bianconi 53290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_INT1_ADDR 0x0d 54dba32904SLorenzo Bianconi #define ST_LSM6DSX_REG_INT2_ADDR 0x0e 55290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_FIFO_FTH_IRQ_MASK BIT(3) 56290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_WHOAMI_ADDR 0x0f 57290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_RESET_ADDR 0x12 58290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_RESET_MASK BIT(0) 5919435425SLorenzo Bianconi #define ST_LSM6DSX_REG_BOOT_MASK BIT(7) 60290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_BDU_ADDR 0x12 61290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_BDU_MASK BIT(6) 62290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_INT2_ON_INT1_ADDR 0x13 63290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_INT2_ON_INT1_MASK BIT(5) 64290a6ce1SLorenzo Bianconi 65290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_ACC_ODR_ADDR 0x10 66290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_ACC_ODR_MASK GENMASK(7, 4) 67290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_ACC_FS_ADDR 0x10 68290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_ACC_FS_MASK GENMASK(3, 2) 69290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_ACC_OUT_X_L_ADDR 0x28 70290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_ACC_OUT_Y_L_ADDR 0x2a 71290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_ACC_OUT_Z_L_ADDR 0x2c 72290a6ce1SLorenzo Bianconi 73290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_GYRO_ODR_ADDR 0x11 74290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_GYRO_ODR_MASK GENMASK(7, 4) 75290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_GYRO_FS_ADDR 0x11 76290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_GYRO_FS_MASK GENMASK(3, 2) 77290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_GYRO_OUT_X_L_ADDR 0x22 78290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR 0x24 79290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_REG_GYRO_OUT_Z_L_ADDR 0x26 80290a6ce1SLorenzo Bianconi 81290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_ACC_FS_2G_GAIN IIO_G_TO_M_S_2(61) 82290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_ACC_FS_4G_GAIN IIO_G_TO_M_S_2(122) 83290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_ACC_FS_8G_GAIN IIO_G_TO_M_S_2(244) 84290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_ACC_FS_16G_GAIN IIO_G_TO_M_S_2(488) 85290a6ce1SLorenzo Bianconi 86dfebd8d8SLorenzo Bianconi #define ST_LSM6DSX_GYRO_FS_245_GAIN IIO_DEGREE_TO_RAD(8750) 87dfebd8d8SLorenzo Bianconi #define ST_LSM6DSX_GYRO_FS_500_GAIN IIO_DEGREE_TO_RAD(17500) 88dfebd8d8SLorenzo Bianconi #define ST_LSM6DSX_GYRO_FS_1000_GAIN IIO_DEGREE_TO_RAD(35000) 89290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_GYRO_FS_2000_GAIN IIO_DEGREE_TO_RAD(70000) 90290a6ce1SLorenzo Bianconi 91290a6ce1SLorenzo Bianconi struct st_lsm6dsx_odr { 92290a6ce1SLorenzo Bianconi u16 hz; 93290a6ce1SLorenzo Bianconi u8 val; 94290a6ce1SLorenzo Bianconi }; 95290a6ce1SLorenzo Bianconi 96290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_ODR_LIST_SIZE 6 97290a6ce1SLorenzo Bianconi struct st_lsm6dsx_odr_table_entry { 98290a6ce1SLorenzo Bianconi struct st_lsm6dsx_reg reg; 99290a6ce1SLorenzo Bianconi struct st_lsm6dsx_odr odr_avl[ST_LSM6DSX_ODR_LIST_SIZE]; 100290a6ce1SLorenzo Bianconi }; 101290a6ce1SLorenzo Bianconi 102290a6ce1SLorenzo Bianconi static const struct st_lsm6dsx_odr_table_entry st_lsm6dsx_odr_table[] = { 103290a6ce1SLorenzo Bianconi [ST_LSM6DSX_ID_ACC] = { 104290a6ce1SLorenzo Bianconi .reg = { 105290a6ce1SLorenzo Bianconi .addr = ST_LSM6DSX_REG_ACC_ODR_ADDR, 106290a6ce1SLorenzo Bianconi .mask = ST_LSM6DSX_REG_ACC_ODR_MASK, 107290a6ce1SLorenzo Bianconi }, 108290a6ce1SLorenzo Bianconi .odr_avl[0] = { 13, 0x01 }, 109290a6ce1SLorenzo Bianconi .odr_avl[1] = { 26, 0x02 }, 110290a6ce1SLorenzo Bianconi .odr_avl[2] = { 52, 0x03 }, 111290a6ce1SLorenzo Bianconi .odr_avl[3] = { 104, 0x04 }, 112290a6ce1SLorenzo Bianconi .odr_avl[4] = { 208, 0x05 }, 113290a6ce1SLorenzo Bianconi .odr_avl[5] = { 416, 0x06 }, 114290a6ce1SLorenzo Bianconi }, 115290a6ce1SLorenzo Bianconi [ST_LSM6DSX_ID_GYRO] = { 116290a6ce1SLorenzo Bianconi .reg = { 117290a6ce1SLorenzo Bianconi .addr = ST_LSM6DSX_REG_GYRO_ODR_ADDR, 118290a6ce1SLorenzo Bianconi .mask = ST_LSM6DSX_REG_GYRO_ODR_MASK, 119290a6ce1SLorenzo Bianconi }, 120290a6ce1SLorenzo Bianconi .odr_avl[0] = { 13, 0x01 }, 121290a6ce1SLorenzo Bianconi .odr_avl[1] = { 26, 0x02 }, 122290a6ce1SLorenzo Bianconi .odr_avl[2] = { 52, 0x03 }, 123290a6ce1SLorenzo Bianconi .odr_avl[3] = { 104, 0x04 }, 124290a6ce1SLorenzo Bianconi .odr_avl[4] = { 208, 0x05 }, 125290a6ce1SLorenzo Bianconi .odr_avl[5] = { 416, 0x06 }, 126290a6ce1SLorenzo Bianconi } 127290a6ce1SLorenzo Bianconi }; 128290a6ce1SLorenzo Bianconi 129290a6ce1SLorenzo Bianconi struct st_lsm6dsx_fs { 130290a6ce1SLorenzo Bianconi u32 gain; 131290a6ce1SLorenzo Bianconi u8 val; 132290a6ce1SLorenzo Bianconi }; 133290a6ce1SLorenzo Bianconi 134290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_FS_LIST_SIZE 4 135290a6ce1SLorenzo Bianconi struct st_lsm6dsx_fs_table_entry { 136290a6ce1SLorenzo Bianconi struct st_lsm6dsx_reg reg; 137290a6ce1SLorenzo Bianconi struct st_lsm6dsx_fs fs_avl[ST_LSM6DSX_FS_LIST_SIZE]; 138290a6ce1SLorenzo Bianconi }; 139290a6ce1SLorenzo Bianconi 140290a6ce1SLorenzo Bianconi static const struct st_lsm6dsx_fs_table_entry st_lsm6dsx_fs_table[] = { 141290a6ce1SLorenzo Bianconi [ST_LSM6DSX_ID_ACC] = { 142290a6ce1SLorenzo Bianconi .reg = { 143290a6ce1SLorenzo Bianconi .addr = ST_LSM6DSX_REG_ACC_FS_ADDR, 144290a6ce1SLorenzo Bianconi .mask = ST_LSM6DSX_REG_ACC_FS_MASK, 145290a6ce1SLorenzo Bianconi }, 146290a6ce1SLorenzo Bianconi .fs_avl[0] = { ST_LSM6DSX_ACC_FS_2G_GAIN, 0x0 }, 147290a6ce1SLorenzo Bianconi .fs_avl[1] = { ST_LSM6DSX_ACC_FS_4G_GAIN, 0x2 }, 148290a6ce1SLorenzo Bianconi .fs_avl[2] = { ST_LSM6DSX_ACC_FS_8G_GAIN, 0x3 }, 149290a6ce1SLorenzo Bianconi .fs_avl[3] = { ST_LSM6DSX_ACC_FS_16G_GAIN, 0x1 }, 150290a6ce1SLorenzo Bianconi }, 151290a6ce1SLorenzo Bianconi [ST_LSM6DSX_ID_GYRO] = { 152290a6ce1SLorenzo Bianconi .reg = { 153290a6ce1SLorenzo Bianconi .addr = ST_LSM6DSX_REG_GYRO_FS_ADDR, 154290a6ce1SLorenzo Bianconi .mask = ST_LSM6DSX_REG_GYRO_FS_MASK, 155290a6ce1SLorenzo Bianconi }, 156290a6ce1SLorenzo Bianconi .fs_avl[0] = { ST_LSM6DSX_GYRO_FS_245_GAIN, 0x0 }, 157290a6ce1SLorenzo Bianconi .fs_avl[1] = { ST_LSM6DSX_GYRO_FS_500_GAIN, 0x1 }, 158290a6ce1SLorenzo Bianconi .fs_avl[2] = { ST_LSM6DSX_GYRO_FS_1000_GAIN, 0x2 }, 159290a6ce1SLorenzo Bianconi .fs_avl[3] = { ST_LSM6DSX_GYRO_FS_2000_GAIN, 0x3 }, 160290a6ce1SLorenzo Bianconi } 161290a6ce1SLorenzo Bianconi }; 162290a6ce1SLorenzo Bianconi 163290a6ce1SLorenzo Bianconi static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { 164290a6ce1SLorenzo Bianconi { 165d068e4a0SLorenzo Bianconi .wai = 0x69, 1668f2a88a2SLorenzo Bianconi .max_fifo_size = 1365, 167d068e4a0SLorenzo Bianconi .id = { 168d068e4a0SLorenzo Bianconi [0] = ST_LSM6DS3_ID, 169d068e4a0SLorenzo Bianconi }, 1707ca3ac9eSLorenzo Bianconi .decimator = { 1717ca3ac9eSLorenzo Bianconi [ST_LSM6DSX_ID_ACC] = { 1727ca3ac9eSLorenzo Bianconi .addr = 0x08, 1737ca3ac9eSLorenzo Bianconi .mask = GENMASK(2, 0), 1747ca3ac9eSLorenzo Bianconi }, 1757ca3ac9eSLorenzo Bianconi [ST_LSM6DSX_ID_GYRO] = { 1767ca3ac9eSLorenzo Bianconi .addr = 0x08, 1777ca3ac9eSLorenzo Bianconi .mask = GENMASK(5, 3), 1787ca3ac9eSLorenzo Bianconi }, 1797ca3ac9eSLorenzo Bianconi }, 18092617c15SLorenzo Bianconi .fifo_ops = { 18150ff457dSLorenzo Bianconi .read_fifo = st_lsm6dsx_read_fifo, 18292617c15SLorenzo Bianconi .fifo_th = { 18392617c15SLorenzo Bianconi .addr = 0x06, 18492617c15SLorenzo Bianconi .mask = GENMASK(11, 0), 18592617c15SLorenzo Bianconi }, 18692617c15SLorenzo Bianconi .fifo_diff = { 18792617c15SLorenzo Bianconi .addr = 0x3a, 18892617c15SLorenzo Bianconi .mask = GENMASK(11, 0), 18992617c15SLorenzo Bianconi }, 19092617c15SLorenzo Bianconi .th_wl = 3, /* 1LSB = 2B */ 19192617c15SLorenzo Bianconi }, 19221345107SLorenzo Bianconi .ts_settings = { 19321345107SLorenzo Bianconi .timer_en = { 19421345107SLorenzo Bianconi .addr = 0x58, 19521345107SLorenzo Bianconi .mask = BIT(7), 19621345107SLorenzo Bianconi }, 19721345107SLorenzo Bianconi .hr_timer = { 19821345107SLorenzo Bianconi .addr = 0x5c, 19921345107SLorenzo Bianconi .mask = BIT(4), 20021345107SLorenzo Bianconi }, 20121345107SLorenzo Bianconi .fifo_en = { 20221345107SLorenzo Bianconi .addr = 0x07, 20321345107SLorenzo Bianconi .mask = BIT(7), 20421345107SLorenzo Bianconi }, 20521345107SLorenzo Bianconi .decimator = { 20621345107SLorenzo Bianconi .addr = 0x09, 20721345107SLorenzo Bianconi .mask = GENMASK(5, 3), 20821345107SLorenzo Bianconi }, 20921345107SLorenzo Bianconi }, 210290a6ce1SLorenzo Bianconi }, 211290a6ce1SLorenzo Bianconi { 212df47710aSLorenzo Bianconi .wai = 0x69, 2138f2a88a2SLorenzo Bianconi .max_fifo_size = 682, 214df47710aSLorenzo Bianconi .id = { 215df47710aSLorenzo Bianconi [0] = ST_LSM6DS3H_ID, 216df47710aSLorenzo Bianconi }, 2177ca3ac9eSLorenzo Bianconi .decimator = { 2187ca3ac9eSLorenzo Bianconi [ST_LSM6DSX_ID_ACC] = { 2197ca3ac9eSLorenzo Bianconi .addr = 0x08, 2207ca3ac9eSLorenzo Bianconi .mask = GENMASK(2, 0), 2217ca3ac9eSLorenzo Bianconi }, 2227ca3ac9eSLorenzo Bianconi [ST_LSM6DSX_ID_GYRO] = { 2237ca3ac9eSLorenzo Bianconi .addr = 0x08, 2247ca3ac9eSLorenzo Bianconi .mask = GENMASK(5, 3), 2257ca3ac9eSLorenzo Bianconi }, 2267ca3ac9eSLorenzo Bianconi }, 22792617c15SLorenzo Bianconi .fifo_ops = { 22850ff457dSLorenzo Bianconi .read_fifo = st_lsm6dsx_read_fifo, 22992617c15SLorenzo Bianconi .fifo_th = { 23092617c15SLorenzo Bianconi .addr = 0x06, 23192617c15SLorenzo Bianconi .mask = GENMASK(11, 0), 23292617c15SLorenzo Bianconi }, 23392617c15SLorenzo Bianconi .fifo_diff = { 23492617c15SLorenzo Bianconi .addr = 0x3a, 23592617c15SLorenzo Bianconi .mask = GENMASK(11, 0), 23692617c15SLorenzo Bianconi }, 23792617c15SLorenzo Bianconi .th_wl = 3, /* 1LSB = 2B */ 23892617c15SLorenzo Bianconi }, 23921345107SLorenzo Bianconi .ts_settings = { 24021345107SLorenzo Bianconi .timer_en = { 24121345107SLorenzo Bianconi .addr = 0x58, 24221345107SLorenzo Bianconi .mask = BIT(7), 24321345107SLorenzo Bianconi }, 24421345107SLorenzo Bianconi .hr_timer = { 24521345107SLorenzo Bianconi .addr = 0x5c, 24621345107SLorenzo Bianconi .mask = BIT(4), 24721345107SLorenzo Bianconi }, 24821345107SLorenzo Bianconi .fifo_en = { 24921345107SLorenzo Bianconi .addr = 0x07, 25021345107SLorenzo Bianconi .mask = BIT(7), 25121345107SLorenzo Bianconi }, 25221345107SLorenzo Bianconi .decimator = { 25321345107SLorenzo Bianconi .addr = 0x09, 25421345107SLorenzo Bianconi .mask = GENMASK(5, 3), 25521345107SLorenzo Bianconi }, 25621345107SLorenzo Bianconi }, 257df47710aSLorenzo Bianconi }, 258df47710aSLorenzo Bianconi { 259d068e4a0SLorenzo Bianconi .wai = 0x6a, 2608f2a88a2SLorenzo Bianconi .max_fifo_size = 682, 261d068e4a0SLorenzo Bianconi .id = { 2620b2a3e5fSLorenzo Bianconi [0] = ST_LSM6DSL_ID, 2630b2a3e5fSLorenzo Bianconi [1] = ST_LSM6DSM_ID, 264179c8d60SLorenzo Bianconi [2] = ST_ISM330DLC_ID, 265d068e4a0SLorenzo Bianconi }, 2667ca3ac9eSLorenzo Bianconi .decimator = { 2677ca3ac9eSLorenzo Bianconi [ST_LSM6DSX_ID_ACC] = { 2687ca3ac9eSLorenzo Bianconi .addr = 0x08, 2697ca3ac9eSLorenzo Bianconi .mask = GENMASK(2, 0), 2707ca3ac9eSLorenzo Bianconi }, 2717ca3ac9eSLorenzo Bianconi [ST_LSM6DSX_ID_GYRO] = { 2727ca3ac9eSLorenzo Bianconi .addr = 0x08, 2737ca3ac9eSLorenzo Bianconi .mask = GENMASK(5, 3), 2747ca3ac9eSLorenzo Bianconi }, 2757ca3ac9eSLorenzo Bianconi }, 27692617c15SLorenzo Bianconi .fifo_ops = { 27750ff457dSLorenzo Bianconi .read_fifo = st_lsm6dsx_read_fifo, 27892617c15SLorenzo Bianconi .fifo_th = { 27992617c15SLorenzo Bianconi .addr = 0x06, 280be75eb86SLorenzo Bianconi .mask = GENMASK(10, 0), 28192617c15SLorenzo Bianconi }, 28292617c15SLorenzo Bianconi .fifo_diff = { 28392617c15SLorenzo Bianconi .addr = 0x3a, 284be75eb86SLorenzo Bianconi .mask = GENMASK(10, 0), 28592617c15SLorenzo Bianconi }, 28692617c15SLorenzo Bianconi .th_wl = 3, /* 1LSB = 2B */ 28792617c15SLorenzo Bianconi }, 28821345107SLorenzo Bianconi .ts_settings = { 28921345107SLorenzo Bianconi .timer_en = { 29021345107SLorenzo Bianconi .addr = 0x19, 29121345107SLorenzo Bianconi .mask = BIT(5), 29221345107SLorenzo Bianconi }, 29321345107SLorenzo Bianconi .hr_timer = { 29421345107SLorenzo Bianconi .addr = 0x5c, 29521345107SLorenzo Bianconi .mask = BIT(4), 29621345107SLorenzo Bianconi }, 29721345107SLorenzo Bianconi .fifo_en = { 29821345107SLorenzo Bianconi .addr = 0x07, 29921345107SLorenzo Bianconi .mask = BIT(7), 30021345107SLorenzo Bianconi }, 30121345107SLorenzo Bianconi .decimator = { 30221345107SLorenzo Bianconi .addr = 0x09, 30321345107SLorenzo Bianconi .mask = GENMASK(5, 3), 30421345107SLorenzo Bianconi }, 30521345107SLorenzo Bianconi }, 306290a6ce1SLorenzo Bianconi }, 307801a6e0aSLorenzo Bianconi { 308801a6e0aSLorenzo Bianconi .wai = 0x6c, 309801a6e0aSLorenzo Bianconi .max_fifo_size = 512, 310801a6e0aSLorenzo Bianconi .id = { 311801a6e0aSLorenzo Bianconi [0] = ST_LSM6DSO_ID, 312801a6e0aSLorenzo Bianconi }, 313801a6e0aSLorenzo Bianconi .batch = { 314801a6e0aSLorenzo Bianconi [ST_LSM6DSX_ID_ACC] = { 315801a6e0aSLorenzo Bianconi .addr = 0x09, 316801a6e0aSLorenzo Bianconi .mask = GENMASK(3, 0), 317801a6e0aSLorenzo Bianconi }, 318801a6e0aSLorenzo Bianconi [ST_LSM6DSX_ID_GYRO] = { 319801a6e0aSLorenzo Bianconi .addr = 0x09, 320801a6e0aSLorenzo Bianconi .mask = GENMASK(7, 4), 321801a6e0aSLorenzo Bianconi }, 322801a6e0aSLorenzo Bianconi }, 323801a6e0aSLorenzo Bianconi .fifo_ops = { 324801a6e0aSLorenzo Bianconi .read_fifo = st_lsm6dsx_read_tagged_fifo, 325801a6e0aSLorenzo Bianconi .fifo_th = { 326801a6e0aSLorenzo Bianconi .addr = 0x07, 327801a6e0aSLorenzo Bianconi .mask = GENMASK(8, 0), 328801a6e0aSLorenzo Bianconi }, 329801a6e0aSLorenzo Bianconi .fifo_diff = { 330801a6e0aSLorenzo Bianconi .addr = 0x3a, 331801a6e0aSLorenzo Bianconi .mask = GENMASK(8, 0), 332801a6e0aSLorenzo Bianconi }, 333801a6e0aSLorenzo Bianconi .th_wl = 1, 334801a6e0aSLorenzo Bianconi }, 335801a6e0aSLorenzo Bianconi .ts_settings = { 336801a6e0aSLorenzo Bianconi .timer_en = { 337801a6e0aSLorenzo Bianconi .addr = 0x19, 338801a6e0aSLorenzo Bianconi .mask = BIT(5), 339801a6e0aSLorenzo Bianconi }, 340801a6e0aSLorenzo Bianconi .decimator = { 341801a6e0aSLorenzo Bianconi .addr = 0x0a, 342801a6e0aSLorenzo Bianconi .mask = GENMASK(7, 6), 343801a6e0aSLorenzo Bianconi }, 344801a6e0aSLorenzo Bianconi }, 345801a6e0aSLorenzo Bianconi }, 346290a6ce1SLorenzo Bianconi }; 347290a6ce1SLorenzo Bianconi 348290a6ce1SLorenzo Bianconi #define ST_LSM6DSX_CHANNEL(chan_type, addr, mod, scan_idx) \ 349290a6ce1SLorenzo Bianconi { \ 350290a6ce1SLorenzo Bianconi .type = chan_type, \ 351290a6ce1SLorenzo Bianconi .address = addr, \ 352290a6ce1SLorenzo Bianconi .modified = 1, \ 353290a6ce1SLorenzo Bianconi .channel2 = mod, \ 354290a6ce1SLorenzo Bianconi .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 355290a6ce1SLorenzo Bianconi BIT(IIO_CHAN_INFO_SCALE), \ 356290a6ce1SLorenzo Bianconi .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 357290a6ce1SLorenzo Bianconi .scan_index = scan_idx, \ 358290a6ce1SLorenzo Bianconi .scan_type = { \ 359290a6ce1SLorenzo Bianconi .sign = 's', \ 360290a6ce1SLorenzo Bianconi .realbits = 16, \ 361290a6ce1SLorenzo Bianconi .storagebits = 16, \ 362290a6ce1SLorenzo Bianconi .endianness = IIO_LE, \ 363290a6ce1SLorenzo Bianconi }, \ 364290a6ce1SLorenzo Bianconi } 365290a6ce1SLorenzo Bianconi 366290a6ce1SLorenzo Bianconi static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { 367290a6ce1SLorenzo Bianconi ST_LSM6DSX_CHANNEL(IIO_ACCEL, ST_LSM6DSX_REG_ACC_OUT_X_L_ADDR, 368290a6ce1SLorenzo Bianconi IIO_MOD_X, 0), 369290a6ce1SLorenzo Bianconi ST_LSM6DSX_CHANNEL(IIO_ACCEL, ST_LSM6DSX_REG_ACC_OUT_Y_L_ADDR, 370290a6ce1SLorenzo Bianconi IIO_MOD_Y, 1), 371290a6ce1SLorenzo Bianconi ST_LSM6DSX_CHANNEL(IIO_ACCEL, ST_LSM6DSX_REG_ACC_OUT_Z_L_ADDR, 372290a6ce1SLorenzo Bianconi IIO_MOD_Z, 2), 373290a6ce1SLorenzo Bianconi IIO_CHAN_SOFT_TIMESTAMP(3), 374290a6ce1SLorenzo Bianconi }; 375290a6ce1SLorenzo Bianconi 376290a6ce1SLorenzo Bianconi static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = { 377290a6ce1SLorenzo Bianconi ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM6DSX_REG_GYRO_OUT_X_L_ADDR, 378290a6ce1SLorenzo Bianconi IIO_MOD_X, 0), 379290a6ce1SLorenzo Bianconi ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR, 380290a6ce1SLorenzo Bianconi IIO_MOD_Y, 1), 381290a6ce1SLorenzo Bianconi ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM6DSX_REG_GYRO_OUT_Z_L_ADDR, 382290a6ce1SLorenzo Bianconi IIO_MOD_Z, 2), 383290a6ce1SLorenzo Bianconi IIO_CHAN_SOFT_TIMESTAMP(3), 384290a6ce1SLorenzo Bianconi }; 385290a6ce1SLorenzo Bianconi 386290a6ce1SLorenzo Bianconi static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id) 387290a6ce1SLorenzo Bianconi { 38851a8b707SLorenzo Bianconi int err, i, j, data; 389290a6ce1SLorenzo Bianconi 390290a6ce1SLorenzo Bianconi for (i = 0; i < ARRAY_SIZE(st_lsm6dsx_sensor_settings); i++) { 391d068e4a0SLorenzo Bianconi for (j = 0; j < ST_LSM6DSX_MAX_ID; j++) { 392d068e4a0SLorenzo Bianconi if (id == st_lsm6dsx_sensor_settings[i].id[j]) 393d068e4a0SLorenzo Bianconi break; 394d068e4a0SLorenzo Bianconi } 395d068e4a0SLorenzo Bianconi if (j < ST_LSM6DSX_MAX_ID) 396290a6ce1SLorenzo Bianconi break; 397290a6ce1SLorenzo Bianconi } 398290a6ce1SLorenzo Bianconi 399290a6ce1SLorenzo Bianconi if (i == ARRAY_SIZE(st_lsm6dsx_sensor_settings)) { 400290a6ce1SLorenzo Bianconi dev_err(hw->dev, "unsupported hw id [%02x]\n", id); 401290a6ce1SLorenzo Bianconi return -ENODEV; 402290a6ce1SLorenzo Bianconi } 403290a6ce1SLorenzo Bianconi 40451a8b707SLorenzo Bianconi err = regmap_read(hw->regmap, ST_LSM6DSX_REG_WHOAMI_ADDR, &data); 405290a6ce1SLorenzo Bianconi if (err < 0) { 406290a6ce1SLorenzo Bianconi dev_err(hw->dev, "failed to read whoami register\n"); 407290a6ce1SLorenzo Bianconi return err; 408290a6ce1SLorenzo Bianconi } 409290a6ce1SLorenzo Bianconi 410290a6ce1SLorenzo Bianconi if (data != st_lsm6dsx_sensor_settings[i].wai) { 411290a6ce1SLorenzo Bianconi dev_err(hw->dev, "unsupported whoami [%02x]\n", data); 412290a6ce1SLorenzo Bianconi return -ENODEV; 413290a6ce1SLorenzo Bianconi } 414290a6ce1SLorenzo Bianconi 415290a6ce1SLorenzo Bianconi hw->settings = &st_lsm6dsx_sensor_settings[i]; 416290a6ce1SLorenzo Bianconi 417290a6ce1SLorenzo Bianconi return 0; 418290a6ce1SLorenzo Bianconi } 419290a6ce1SLorenzo Bianconi 420290a6ce1SLorenzo Bianconi static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor, 421290a6ce1SLorenzo Bianconi u32 gain) 422290a6ce1SLorenzo Bianconi { 42351a8b707SLorenzo Bianconi struct st_lsm6dsx_hw *hw = sensor->hw; 42451a8b707SLorenzo Bianconi const struct st_lsm6dsx_reg *reg; 425739aff87SLorenzo Bianconi unsigned int data; 426290a6ce1SLorenzo Bianconi int i, err; 427290a6ce1SLorenzo Bianconi u8 val; 428290a6ce1SLorenzo Bianconi 429290a6ce1SLorenzo Bianconi for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++) 43051a8b707SLorenzo Bianconi if (st_lsm6dsx_fs_table[sensor->id].fs_avl[i].gain == gain) 431290a6ce1SLorenzo Bianconi break; 432290a6ce1SLorenzo Bianconi 433290a6ce1SLorenzo Bianconi if (i == ST_LSM6DSX_FS_LIST_SIZE) 434290a6ce1SLorenzo Bianconi return -EINVAL; 435290a6ce1SLorenzo Bianconi 43651a8b707SLorenzo Bianconi val = st_lsm6dsx_fs_table[sensor->id].fs_avl[i].val; 43751a8b707SLorenzo Bianconi reg = &st_lsm6dsx_fs_table[sensor->id].reg; 438739aff87SLorenzo Bianconi data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); 439739aff87SLorenzo Bianconi err = st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data); 440290a6ce1SLorenzo Bianconi if (err < 0) 441290a6ce1SLorenzo Bianconi return err; 442290a6ce1SLorenzo Bianconi 443290a6ce1SLorenzo Bianconi sensor->gain = gain; 444290a6ce1SLorenzo Bianconi 445290a6ce1SLorenzo Bianconi return 0; 446290a6ce1SLorenzo Bianconi } 447290a6ce1SLorenzo Bianconi 44854a6d0c6SLorenzo Bianconi int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u16 odr, u8 *val) 449290a6ce1SLorenzo Bianconi { 4502ccc1503SLorenzo Bianconi int i; 451290a6ce1SLorenzo Bianconi 452290a6ce1SLorenzo Bianconi for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++) 4532ccc1503SLorenzo Bianconi if (st_lsm6dsx_odr_table[sensor->id].odr_avl[i].hz == odr) 454290a6ce1SLorenzo Bianconi break; 455290a6ce1SLorenzo Bianconi 456290a6ce1SLorenzo Bianconi if (i == ST_LSM6DSX_ODR_LIST_SIZE) 457290a6ce1SLorenzo Bianconi return -EINVAL; 458290a6ce1SLorenzo Bianconi 4592ccc1503SLorenzo Bianconi *val = st_lsm6dsx_odr_table[sensor->id].odr_avl[i].val; 460290a6ce1SLorenzo Bianconi 461290a6ce1SLorenzo Bianconi return 0; 462290a6ce1SLorenzo Bianconi } 463290a6ce1SLorenzo Bianconi 4642ccc1503SLorenzo Bianconi static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 odr) 4652ccc1503SLorenzo Bianconi { 46651a8b707SLorenzo Bianconi struct st_lsm6dsx_hw *hw = sensor->hw; 46751a8b707SLorenzo Bianconi const struct st_lsm6dsx_reg *reg; 468739aff87SLorenzo Bianconi unsigned int data; 4692ccc1503SLorenzo Bianconi int err; 4702ccc1503SLorenzo Bianconi u8 val; 4712ccc1503SLorenzo Bianconi 4722ccc1503SLorenzo Bianconi err = st_lsm6dsx_check_odr(sensor, odr, &val); 4732ccc1503SLorenzo Bianconi if (err < 0) 4742ccc1503SLorenzo Bianconi return err; 4752ccc1503SLorenzo Bianconi 47651a8b707SLorenzo Bianconi reg = &st_lsm6dsx_odr_table[sensor->id].reg; 477739aff87SLorenzo Bianconi data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); 478739aff87SLorenzo Bianconi return st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data); 4792ccc1503SLorenzo Bianconi } 4802ccc1503SLorenzo Bianconi 481290a6ce1SLorenzo Bianconi int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor) 482290a6ce1SLorenzo Bianconi { 483290a6ce1SLorenzo Bianconi int err; 484290a6ce1SLorenzo Bianconi 485290a6ce1SLorenzo Bianconi err = st_lsm6dsx_set_odr(sensor, sensor->odr); 486290a6ce1SLorenzo Bianconi if (err < 0) 487290a6ce1SLorenzo Bianconi return err; 488290a6ce1SLorenzo Bianconi 489290a6ce1SLorenzo Bianconi sensor->hw->enable_mask |= BIT(sensor->id); 490290a6ce1SLorenzo Bianconi 491290a6ce1SLorenzo Bianconi return 0; 492290a6ce1SLorenzo Bianconi } 493290a6ce1SLorenzo Bianconi 494290a6ce1SLorenzo Bianconi int st_lsm6dsx_sensor_disable(struct st_lsm6dsx_sensor *sensor) 495290a6ce1SLorenzo Bianconi { 49651a8b707SLorenzo Bianconi struct st_lsm6dsx_hw *hw = sensor->hw; 49751a8b707SLorenzo Bianconi const struct st_lsm6dsx_reg *reg; 498739aff87SLorenzo Bianconi unsigned int data; 499290a6ce1SLorenzo Bianconi int err; 500290a6ce1SLorenzo Bianconi 50151a8b707SLorenzo Bianconi reg = &st_lsm6dsx_odr_table[sensor->id].reg; 502739aff87SLorenzo Bianconi data = ST_LSM6DSX_SHIFT_VAL(0, reg->mask); 503739aff87SLorenzo Bianconi err = st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data); 504290a6ce1SLorenzo Bianconi if (err < 0) 505290a6ce1SLorenzo Bianconi return err; 506290a6ce1SLorenzo Bianconi 50751a8b707SLorenzo Bianconi sensor->hw->enable_mask &= ~BIT(sensor->id); 508290a6ce1SLorenzo Bianconi 509290a6ce1SLorenzo Bianconi return 0; 510290a6ce1SLorenzo Bianconi } 511290a6ce1SLorenzo Bianconi 512290a6ce1SLorenzo Bianconi static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor, 513290a6ce1SLorenzo Bianconi u8 addr, int *val) 514290a6ce1SLorenzo Bianconi { 51551a8b707SLorenzo Bianconi struct st_lsm6dsx_hw *hw = sensor->hw; 516290a6ce1SLorenzo Bianconi int err, delay; 517290a6ce1SLorenzo Bianconi __le16 data; 518290a6ce1SLorenzo Bianconi 519290a6ce1SLorenzo Bianconi err = st_lsm6dsx_sensor_enable(sensor); 520290a6ce1SLorenzo Bianconi if (err < 0) 521290a6ce1SLorenzo Bianconi return err; 522290a6ce1SLorenzo Bianconi 523290a6ce1SLorenzo Bianconi delay = 1000000 / sensor->odr; 524290a6ce1SLorenzo Bianconi usleep_range(delay, 2 * delay); 525290a6ce1SLorenzo Bianconi 526739aff87SLorenzo Bianconi err = st_lsm6dsx_read_locked(hw, addr, &data, sizeof(data)); 527290a6ce1SLorenzo Bianconi if (err < 0) 528290a6ce1SLorenzo Bianconi return err; 529290a6ce1SLorenzo Bianconi 530290a6ce1SLorenzo Bianconi st_lsm6dsx_sensor_disable(sensor); 531290a6ce1SLorenzo Bianconi 5327b9ebe42SLorenzo Bianconi *val = (s16)le16_to_cpu(data); 533290a6ce1SLorenzo Bianconi 534290a6ce1SLorenzo Bianconi return IIO_VAL_INT; 535290a6ce1SLorenzo Bianconi } 536290a6ce1SLorenzo Bianconi 537290a6ce1SLorenzo Bianconi static int st_lsm6dsx_read_raw(struct iio_dev *iio_dev, 538290a6ce1SLorenzo Bianconi struct iio_chan_spec const *ch, 539290a6ce1SLorenzo Bianconi int *val, int *val2, long mask) 540290a6ce1SLorenzo Bianconi { 541290a6ce1SLorenzo Bianconi struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); 542290a6ce1SLorenzo Bianconi int ret; 543290a6ce1SLorenzo Bianconi 544290a6ce1SLorenzo Bianconi switch (mask) { 545290a6ce1SLorenzo Bianconi case IIO_CHAN_INFO_RAW: 546290a6ce1SLorenzo Bianconi ret = iio_device_claim_direct_mode(iio_dev); 547290a6ce1SLorenzo Bianconi if (ret) 548290a6ce1SLorenzo Bianconi break; 549290a6ce1SLorenzo Bianconi 550290a6ce1SLorenzo Bianconi ret = st_lsm6dsx_read_oneshot(sensor, ch->address, val); 551290a6ce1SLorenzo Bianconi iio_device_release_direct_mode(iio_dev); 552290a6ce1SLorenzo Bianconi break; 553290a6ce1SLorenzo Bianconi case IIO_CHAN_INFO_SAMP_FREQ: 554290a6ce1SLorenzo Bianconi *val = sensor->odr; 555290a6ce1SLorenzo Bianconi ret = IIO_VAL_INT; 556290a6ce1SLorenzo Bianconi break; 557290a6ce1SLorenzo Bianconi case IIO_CHAN_INFO_SCALE: 558290a6ce1SLorenzo Bianconi *val = 0; 559290a6ce1SLorenzo Bianconi *val2 = sensor->gain; 560290a6ce1SLorenzo Bianconi ret = IIO_VAL_INT_PLUS_MICRO; 561290a6ce1SLorenzo Bianconi break; 562290a6ce1SLorenzo Bianconi default: 563290a6ce1SLorenzo Bianconi ret = -EINVAL; 564290a6ce1SLorenzo Bianconi break; 565290a6ce1SLorenzo Bianconi } 566290a6ce1SLorenzo Bianconi 567290a6ce1SLorenzo Bianconi return ret; 568290a6ce1SLorenzo Bianconi } 569290a6ce1SLorenzo Bianconi 570290a6ce1SLorenzo Bianconi static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev, 571290a6ce1SLorenzo Bianconi struct iio_chan_spec const *chan, 572290a6ce1SLorenzo Bianconi int val, int val2, long mask) 573290a6ce1SLorenzo Bianconi { 574290a6ce1SLorenzo Bianconi struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); 575290a6ce1SLorenzo Bianconi int err; 576290a6ce1SLorenzo Bianconi 577290a6ce1SLorenzo Bianconi err = iio_device_claim_direct_mode(iio_dev); 578290a6ce1SLorenzo Bianconi if (err) 579290a6ce1SLorenzo Bianconi return err; 580290a6ce1SLorenzo Bianconi 581290a6ce1SLorenzo Bianconi switch (mask) { 582290a6ce1SLorenzo Bianconi case IIO_CHAN_INFO_SCALE: 583290a6ce1SLorenzo Bianconi err = st_lsm6dsx_set_full_scale(sensor, val2); 584290a6ce1SLorenzo Bianconi break; 5852ccc1503SLorenzo Bianconi case IIO_CHAN_INFO_SAMP_FREQ: { 5862ccc1503SLorenzo Bianconi u8 data; 5872ccc1503SLorenzo Bianconi 5882ccc1503SLorenzo Bianconi err = st_lsm6dsx_check_odr(sensor, val, &data); 5895e3c3e33SLorenzo Bianconi if (!err) 5905e3c3e33SLorenzo Bianconi sensor->odr = val; 591290a6ce1SLorenzo Bianconi break; 5922ccc1503SLorenzo Bianconi } 593290a6ce1SLorenzo Bianconi default: 594290a6ce1SLorenzo Bianconi err = -EINVAL; 595290a6ce1SLorenzo Bianconi break; 596290a6ce1SLorenzo Bianconi } 597290a6ce1SLorenzo Bianconi 598290a6ce1SLorenzo Bianconi iio_device_release_direct_mode(iio_dev); 599290a6ce1SLorenzo Bianconi 600290a6ce1SLorenzo Bianconi return err; 601290a6ce1SLorenzo Bianconi } 602290a6ce1SLorenzo Bianconi 603d40464f3SLorenzo Bianconi int st_lsm6dsx_set_watermark(struct iio_dev *iio_dev, unsigned int val) 604290a6ce1SLorenzo Bianconi { 605290a6ce1SLorenzo Bianconi struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); 606290a6ce1SLorenzo Bianconi struct st_lsm6dsx_hw *hw = sensor->hw; 6078f2a88a2SLorenzo Bianconi int err; 608290a6ce1SLorenzo Bianconi 6098f2a88a2SLorenzo Bianconi if (val < 1 || val > hw->settings->max_fifo_size) 610290a6ce1SLorenzo Bianconi return -EINVAL; 611290a6ce1SLorenzo Bianconi 612335eaedcSLorenzo Bianconi mutex_lock(&hw->conf_lock); 613335eaedcSLorenzo Bianconi 614290a6ce1SLorenzo Bianconi err = st_lsm6dsx_update_watermark(sensor, val); 615335eaedcSLorenzo Bianconi 616335eaedcSLorenzo Bianconi mutex_unlock(&hw->conf_lock); 617335eaedcSLorenzo Bianconi 618290a6ce1SLorenzo Bianconi if (err < 0) 619290a6ce1SLorenzo Bianconi return err; 620290a6ce1SLorenzo Bianconi 621290a6ce1SLorenzo Bianconi sensor->watermark = val; 622290a6ce1SLorenzo Bianconi 623290a6ce1SLorenzo Bianconi return 0; 624290a6ce1SLorenzo Bianconi } 625290a6ce1SLorenzo Bianconi 626290a6ce1SLorenzo Bianconi static ssize_t 627290a6ce1SLorenzo Bianconi st_lsm6dsx_sysfs_sampling_frequency_avail(struct device *dev, 628290a6ce1SLorenzo Bianconi struct device_attribute *attr, 629290a6ce1SLorenzo Bianconi char *buf) 630290a6ce1SLorenzo Bianconi { 631290a6ce1SLorenzo Bianconi struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev)); 632290a6ce1SLorenzo Bianconi enum st_lsm6dsx_sensor_id id = sensor->id; 633290a6ce1SLorenzo Bianconi int i, len = 0; 634290a6ce1SLorenzo Bianconi 635290a6ce1SLorenzo Bianconi for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++) 636290a6ce1SLorenzo Bianconi len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", 637290a6ce1SLorenzo Bianconi st_lsm6dsx_odr_table[id].odr_avl[i].hz); 638290a6ce1SLorenzo Bianconi buf[len - 1] = '\n'; 639290a6ce1SLorenzo Bianconi 640290a6ce1SLorenzo Bianconi return len; 641290a6ce1SLorenzo Bianconi } 642290a6ce1SLorenzo Bianconi 643290a6ce1SLorenzo Bianconi static ssize_t st_lsm6dsx_sysfs_scale_avail(struct device *dev, 644290a6ce1SLorenzo Bianconi struct device_attribute *attr, 645290a6ce1SLorenzo Bianconi char *buf) 646290a6ce1SLorenzo Bianconi { 647290a6ce1SLorenzo Bianconi struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev)); 648290a6ce1SLorenzo Bianconi enum st_lsm6dsx_sensor_id id = sensor->id; 649290a6ce1SLorenzo Bianconi int i, len = 0; 650290a6ce1SLorenzo Bianconi 651290a6ce1SLorenzo Bianconi for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++) 652290a6ce1SLorenzo Bianconi len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ", 653290a6ce1SLorenzo Bianconi st_lsm6dsx_fs_table[id].fs_avl[i].gain); 654290a6ce1SLorenzo Bianconi buf[len - 1] = '\n'; 655290a6ce1SLorenzo Bianconi 656290a6ce1SLorenzo Bianconi return len; 657290a6ce1SLorenzo Bianconi } 658290a6ce1SLorenzo Bianconi 659290a6ce1SLorenzo Bianconi static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(st_lsm6dsx_sysfs_sampling_frequency_avail); 660290a6ce1SLorenzo Bianconi static IIO_DEVICE_ATTR(in_accel_scale_available, 0444, 661290a6ce1SLorenzo Bianconi st_lsm6dsx_sysfs_scale_avail, NULL, 0); 662290a6ce1SLorenzo Bianconi static IIO_DEVICE_ATTR(in_anglvel_scale_available, 0444, 663290a6ce1SLorenzo Bianconi st_lsm6dsx_sysfs_scale_avail, NULL, 0); 664290a6ce1SLorenzo Bianconi 665290a6ce1SLorenzo Bianconi static struct attribute *st_lsm6dsx_acc_attributes[] = { 666290a6ce1SLorenzo Bianconi &iio_dev_attr_sampling_frequency_available.dev_attr.attr, 667290a6ce1SLorenzo Bianconi &iio_dev_attr_in_accel_scale_available.dev_attr.attr, 668290a6ce1SLorenzo Bianconi NULL, 669290a6ce1SLorenzo Bianconi }; 670290a6ce1SLorenzo Bianconi 671290a6ce1SLorenzo Bianconi static const struct attribute_group st_lsm6dsx_acc_attribute_group = { 672290a6ce1SLorenzo Bianconi .attrs = st_lsm6dsx_acc_attributes, 673290a6ce1SLorenzo Bianconi }; 674290a6ce1SLorenzo Bianconi 675290a6ce1SLorenzo Bianconi static const struct iio_info st_lsm6dsx_acc_info = { 676290a6ce1SLorenzo Bianconi .attrs = &st_lsm6dsx_acc_attribute_group, 677290a6ce1SLorenzo Bianconi .read_raw = st_lsm6dsx_read_raw, 678290a6ce1SLorenzo Bianconi .write_raw = st_lsm6dsx_write_raw, 679290a6ce1SLorenzo Bianconi .hwfifo_set_watermark = st_lsm6dsx_set_watermark, 680290a6ce1SLorenzo Bianconi }; 681290a6ce1SLorenzo Bianconi 682290a6ce1SLorenzo Bianconi static struct attribute *st_lsm6dsx_gyro_attributes[] = { 683290a6ce1SLorenzo Bianconi &iio_dev_attr_sampling_frequency_available.dev_attr.attr, 684290a6ce1SLorenzo Bianconi &iio_dev_attr_in_anglvel_scale_available.dev_attr.attr, 685290a6ce1SLorenzo Bianconi NULL, 686290a6ce1SLorenzo Bianconi }; 687290a6ce1SLorenzo Bianconi 688290a6ce1SLorenzo Bianconi static const struct attribute_group st_lsm6dsx_gyro_attribute_group = { 689290a6ce1SLorenzo Bianconi .attrs = st_lsm6dsx_gyro_attributes, 690290a6ce1SLorenzo Bianconi }; 691290a6ce1SLorenzo Bianconi 692290a6ce1SLorenzo Bianconi static const struct iio_info st_lsm6dsx_gyro_info = { 693290a6ce1SLorenzo Bianconi .attrs = &st_lsm6dsx_gyro_attribute_group, 694290a6ce1SLorenzo Bianconi .read_raw = st_lsm6dsx_read_raw, 695290a6ce1SLorenzo Bianconi .write_raw = st_lsm6dsx_write_raw, 696290a6ce1SLorenzo Bianconi .hwfifo_set_watermark = st_lsm6dsx_set_watermark, 697290a6ce1SLorenzo Bianconi }; 698290a6ce1SLorenzo Bianconi 699290a6ce1SLorenzo Bianconi static const unsigned long st_lsm6dsx_available_scan_masks[] = {0x7, 0x0}; 700290a6ce1SLorenzo Bianconi 701dba32904SLorenzo Bianconi static int st_lsm6dsx_of_get_drdy_pin(struct st_lsm6dsx_hw *hw, int *drdy_pin) 702dba32904SLorenzo Bianconi { 703dba32904SLorenzo Bianconi struct device_node *np = hw->dev->of_node; 704dba32904SLorenzo Bianconi 705dba32904SLorenzo Bianconi if (!np) 706dba32904SLorenzo Bianconi return -EINVAL; 707dba32904SLorenzo Bianconi 708bf235277SLorenzo Bianconi return of_property_read_u32(np, "st,drdy-int-pin", drdy_pin); 709dba32904SLorenzo Bianconi } 710dba32904SLorenzo Bianconi 711dba32904SLorenzo Bianconi static int st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw, u8 *drdy_reg) 712dba32904SLorenzo Bianconi { 713dba32904SLorenzo Bianconi int err = 0, drdy_pin; 714dba32904SLorenzo Bianconi 715dba32904SLorenzo Bianconi if (st_lsm6dsx_of_get_drdy_pin(hw, &drdy_pin) < 0) { 716dba32904SLorenzo Bianconi struct st_sensors_platform_data *pdata; 717dba32904SLorenzo Bianconi struct device *dev = hw->dev; 718dba32904SLorenzo Bianconi 719dba32904SLorenzo Bianconi pdata = (struct st_sensors_platform_data *)dev->platform_data; 720dba32904SLorenzo Bianconi drdy_pin = pdata ? pdata->drdy_int_pin : 1; 721dba32904SLorenzo Bianconi } 722dba32904SLorenzo Bianconi 723dba32904SLorenzo Bianconi switch (drdy_pin) { 724dba32904SLorenzo Bianconi case 1: 725dba32904SLorenzo Bianconi *drdy_reg = ST_LSM6DSX_REG_INT1_ADDR; 726dba32904SLorenzo Bianconi break; 727dba32904SLorenzo Bianconi case 2: 728dba32904SLorenzo Bianconi *drdy_reg = ST_LSM6DSX_REG_INT2_ADDR; 729dba32904SLorenzo Bianconi break; 730dba32904SLorenzo Bianconi default: 731dba32904SLorenzo Bianconi dev_err(hw->dev, "unsupported data ready pin\n"); 732dba32904SLorenzo Bianconi err = -EINVAL; 733dba32904SLorenzo Bianconi break; 734dba32904SLorenzo Bianconi } 735dba32904SLorenzo Bianconi 736dba32904SLorenzo Bianconi return err; 737dba32904SLorenzo Bianconi } 738dba32904SLorenzo Bianconi 73921345107SLorenzo Bianconi static int st_lsm6dsx_init_hw_timer(struct st_lsm6dsx_hw *hw) 74021345107SLorenzo Bianconi { 74121345107SLorenzo Bianconi const struct st_lsm6dsx_hw_ts_settings *ts_settings; 74221345107SLorenzo Bianconi int err, val; 74321345107SLorenzo Bianconi 74421345107SLorenzo Bianconi ts_settings = &hw->settings->ts_settings; 74521345107SLorenzo Bianconi /* enable hw timestamp generation if necessary */ 74621345107SLorenzo Bianconi if (ts_settings->timer_en.addr) { 74721345107SLorenzo Bianconi val = ST_LSM6DSX_SHIFT_VAL(1, ts_settings->timer_en.mask); 74821345107SLorenzo Bianconi err = regmap_update_bits(hw->regmap, 74921345107SLorenzo Bianconi ts_settings->timer_en.addr, 75021345107SLorenzo Bianconi ts_settings->timer_en.mask, val); 75121345107SLorenzo Bianconi if (err < 0) 75221345107SLorenzo Bianconi return err; 75321345107SLorenzo Bianconi } 75421345107SLorenzo Bianconi 75521345107SLorenzo Bianconi /* enable high resolution for hw ts timer if necessary */ 75621345107SLorenzo Bianconi if (ts_settings->hr_timer.addr) { 75721345107SLorenzo Bianconi val = ST_LSM6DSX_SHIFT_VAL(1, ts_settings->hr_timer.mask); 75821345107SLorenzo Bianconi err = regmap_update_bits(hw->regmap, 75921345107SLorenzo Bianconi ts_settings->hr_timer.addr, 76021345107SLorenzo Bianconi ts_settings->hr_timer.mask, val); 76121345107SLorenzo Bianconi if (err < 0) 76221345107SLorenzo Bianconi return err; 76321345107SLorenzo Bianconi } 76421345107SLorenzo Bianconi 76521345107SLorenzo Bianconi /* enable ts queueing in FIFO if necessary */ 76621345107SLorenzo Bianconi if (ts_settings->fifo_en.addr) { 76721345107SLorenzo Bianconi val = ST_LSM6DSX_SHIFT_VAL(1, ts_settings->fifo_en.mask); 76821345107SLorenzo Bianconi err = regmap_update_bits(hw->regmap, 76921345107SLorenzo Bianconi ts_settings->fifo_en.addr, 77021345107SLorenzo Bianconi ts_settings->fifo_en.mask, val); 77121345107SLorenzo Bianconi if (err < 0) 77221345107SLorenzo Bianconi return err; 77321345107SLorenzo Bianconi } 77421345107SLorenzo Bianconi return 0; 77521345107SLorenzo Bianconi } 77621345107SLorenzo Bianconi 777290a6ce1SLorenzo Bianconi static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw) 778290a6ce1SLorenzo Bianconi { 77951a8b707SLorenzo Bianconi u8 drdy_int_reg; 780290a6ce1SLorenzo Bianconi int err; 781290a6ce1SLorenzo Bianconi 78219435425SLorenzo Bianconi /* device sw reset */ 78319435425SLorenzo Bianconi err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_RESET_ADDR, 78419435425SLorenzo Bianconi ST_LSM6DSX_REG_RESET_MASK, 78519435425SLorenzo Bianconi FIELD_PREP(ST_LSM6DSX_REG_RESET_MASK, 1)); 786290a6ce1SLorenzo Bianconi if (err < 0) 787290a6ce1SLorenzo Bianconi return err; 788290a6ce1SLorenzo Bianconi 78919435425SLorenzo Bianconi msleep(50); 79019435425SLorenzo Bianconi 79119435425SLorenzo Bianconi /* reload trimming parameter */ 79219435425SLorenzo Bianconi err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_RESET_ADDR, 79319435425SLorenzo Bianconi ST_LSM6DSX_REG_BOOT_MASK, 79419435425SLorenzo Bianconi FIELD_PREP(ST_LSM6DSX_REG_BOOT_MASK, 1)); 79519435425SLorenzo Bianconi if (err < 0) 79619435425SLorenzo Bianconi return err; 79719435425SLorenzo Bianconi 79819435425SLorenzo Bianconi msleep(50); 799290a6ce1SLorenzo Bianconi 800290a6ce1SLorenzo Bianconi /* enable Block Data Update */ 80151a8b707SLorenzo Bianconi err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_BDU_ADDR, 80251a8b707SLorenzo Bianconi ST_LSM6DSX_REG_BDU_MASK, 80351a8b707SLorenzo Bianconi FIELD_PREP(ST_LSM6DSX_REG_BDU_MASK, 1)); 804290a6ce1SLorenzo Bianconi if (err < 0) 805290a6ce1SLorenzo Bianconi return err; 806290a6ce1SLorenzo Bianconi 807290a6ce1SLorenzo Bianconi /* enable FIFO watermak interrupt */ 808dba32904SLorenzo Bianconi err = st_lsm6dsx_get_drdy_reg(hw, &drdy_int_reg); 809290a6ce1SLorenzo Bianconi if (err < 0) 810290a6ce1SLorenzo Bianconi return err; 811290a6ce1SLorenzo Bianconi 81221345107SLorenzo Bianconi err = regmap_update_bits(hw->regmap, drdy_int_reg, 81351a8b707SLorenzo Bianconi ST_LSM6DSX_REG_FIFO_FTH_IRQ_MASK, 81451a8b707SLorenzo Bianconi FIELD_PREP(ST_LSM6DSX_REG_FIFO_FTH_IRQ_MASK, 81551a8b707SLorenzo Bianconi 1)); 81621345107SLorenzo Bianconi if (err < 0) 81721345107SLorenzo Bianconi return err; 81821345107SLorenzo Bianconi 81921345107SLorenzo Bianconi return st_lsm6dsx_init_hw_timer(hw); 820290a6ce1SLorenzo Bianconi } 821290a6ce1SLorenzo Bianconi 822290a6ce1SLorenzo Bianconi static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw, 823510c0106SLorenzo Bianconi enum st_lsm6dsx_sensor_id id, 824510c0106SLorenzo Bianconi const char *name) 825290a6ce1SLorenzo Bianconi { 826290a6ce1SLorenzo Bianconi struct st_lsm6dsx_sensor *sensor; 827290a6ce1SLorenzo Bianconi struct iio_dev *iio_dev; 828290a6ce1SLorenzo Bianconi 829290a6ce1SLorenzo Bianconi iio_dev = devm_iio_device_alloc(hw->dev, sizeof(*sensor)); 830290a6ce1SLorenzo Bianconi if (!iio_dev) 831290a6ce1SLorenzo Bianconi return NULL; 832290a6ce1SLorenzo Bianconi 833290a6ce1SLorenzo Bianconi iio_dev->modes = INDIO_DIRECT_MODE; 834290a6ce1SLorenzo Bianconi iio_dev->dev.parent = hw->dev; 835290a6ce1SLorenzo Bianconi iio_dev->available_scan_masks = st_lsm6dsx_available_scan_masks; 836290a6ce1SLorenzo Bianconi 837290a6ce1SLorenzo Bianconi sensor = iio_priv(iio_dev); 838290a6ce1SLorenzo Bianconi sensor->id = id; 839290a6ce1SLorenzo Bianconi sensor->hw = hw; 840290a6ce1SLorenzo Bianconi sensor->odr = st_lsm6dsx_odr_table[id].odr_avl[0].hz; 841290a6ce1SLorenzo Bianconi sensor->gain = st_lsm6dsx_fs_table[id].fs_avl[0].gain; 842290a6ce1SLorenzo Bianconi sensor->watermark = 1; 843290a6ce1SLorenzo Bianconi 844290a6ce1SLorenzo Bianconi switch (id) { 845290a6ce1SLorenzo Bianconi case ST_LSM6DSX_ID_ACC: 846290a6ce1SLorenzo Bianconi iio_dev->channels = st_lsm6dsx_acc_channels; 847290a6ce1SLorenzo Bianconi iio_dev->num_channels = ARRAY_SIZE(st_lsm6dsx_acc_channels); 848290a6ce1SLorenzo Bianconi iio_dev->info = &st_lsm6dsx_acc_info; 849290a6ce1SLorenzo Bianconi 850510c0106SLorenzo Bianconi scnprintf(sensor->name, sizeof(sensor->name), "%s_accel", 851510c0106SLorenzo Bianconi name); 852290a6ce1SLorenzo Bianconi break; 853290a6ce1SLorenzo Bianconi case ST_LSM6DSX_ID_GYRO: 854290a6ce1SLorenzo Bianconi iio_dev->channels = st_lsm6dsx_gyro_channels; 855290a6ce1SLorenzo Bianconi iio_dev->num_channels = ARRAY_SIZE(st_lsm6dsx_gyro_channels); 856290a6ce1SLorenzo Bianconi iio_dev->info = &st_lsm6dsx_gyro_info; 857290a6ce1SLorenzo Bianconi 858510c0106SLorenzo Bianconi scnprintf(sensor->name, sizeof(sensor->name), "%s_gyro", 859510c0106SLorenzo Bianconi name); 860290a6ce1SLorenzo Bianconi break; 861290a6ce1SLorenzo Bianconi default: 862290a6ce1SLorenzo Bianconi return NULL; 863290a6ce1SLorenzo Bianconi } 864510c0106SLorenzo Bianconi iio_dev->name = sensor->name; 865290a6ce1SLorenzo Bianconi 866290a6ce1SLorenzo Bianconi return iio_dev; 867290a6ce1SLorenzo Bianconi } 868290a6ce1SLorenzo Bianconi 869510c0106SLorenzo Bianconi int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name, 87051a8b707SLorenzo Bianconi struct regmap *regmap) 871290a6ce1SLorenzo Bianconi { 872290a6ce1SLorenzo Bianconi struct st_lsm6dsx_hw *hw; 873290a6ce1SLorenzo Bianconi int i, err; 874290a6ce1SLorenzo Bianconi 875290a6ce1SLorenzo Bianconi hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL); 876290a6ce1SLorenzo Bianconi if (!hw) 877290a6ce1SLorenzo Bianconi return -ENOMEM; 878290a6ce1SLorenzo Bianconi 879290a6ce1SLorenzo Bianconi dev_set_drvdata(dev, (void *)hw); 880290a6ce1SLorenzo Bianconi 881290a6ce1SLorenzo Bianconi mutex_init(&hw->fifo_lock); 882335eaedcSLorenzo Bianconi mutex_init(&hw->conf_lock); 883739aff87SLorenzo Bianconi mutex_init(&hw->page_lock); 884290a6ce1SLorenzo Bianconi 88591a6b841SLorenzo Bianconi hw->buff = devm_kzalloc(dev, ST_LSM6DSX_BUFF_SIZE, GFP_KERNEL); 88691a6b841SLorenzo Bianconi if (!hw->buff) 88791a6b841SLorenzo Bianconi return -ENOMEM; 88891a6b841SLorenzo Bianconi 889290a6ce1SLorenzo Bianconi hw->dev = dev; 890290a6ce1SLorenzo Bianconi hw->irq = irq; 89151a8b707SLorenzo Bianconi hw->regmap = regmap; 892290a6ce1SLorenzo Bianconi 893290a6ce1SLorenzo Bianconi err = st_lsm6dsx_check_whoami(hw, hw_id); 894290a6ce1SLorenzo Bianconi if (err < 0) 895290a6ce1SLorenzo Bianconi return err; 896290a6ce1SLorenzo Bianconi 897290a6ce1SLorenzo Bianconi for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { 898510c0106SLorenzo Bianconi hw->iio_devs[i] = st_lsm6dsx_alloc_iiodev(hw, i, name); 899290a6ce1SLorenzo Bianconi if (!hw->iio_devs[i]) 900290a6ce1SLorenzo Bianconi return -ENOMEM; 901290a6ce1SLorenzo Bianconi } 902290a6ce1SLorenzo Bianconi 903290a6ce1SLorenzo Bianconi err = st_lsm6dsx_init_device(hw); 904290a6ce1SLorenzo Bianconi if (err < 0) 905290a6ce1SLorenzo Bianconi return err; 906290a6ce1SLorenzo Bianconi 907290a6ce1SLorenzo Bianconi if (hw->irq > 0) { 908290a6ce1SLorenzo Bianconi err = st_lsm6dsx_fifo_setup(hw); 909290a6ce1SLorenzo Bianconi if (err < 0) 910290a6ce1SLorenzo Bianconi return err; 911290a6ce1SLorenzo Bianconi } 912290a6ce1SLorenzo Bianconi 913290a6ce1SLorenzo Bianconi for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { 914290a6ce1SLorenzo Bianconi err = devm_iio_device_register(hw->dev, hw->iio_devs[i]); 915290a6ce1SLorenzo Bianconi if (err) 916290a6ce1SLorenzo Bianconi return err; 917290a6ce1SLorenzo Bianconi } 918290a6ce1SLorenzo Bianconi 919290a6ce1SLorenzo Bianconi return 0; 920290a6ce1SLorenzo Bianconi } 921290a6ce1SLorenzo Bianconi EXPORT_SYMBOL(st_lsm6dsx_probe); 922290a6ce1SLorenzo Bianconi 9233cec4850SLorenzo Bianconi static int __maybe_unused st_lsm6dsx_suspend(struct device *dev) 924d3f77058SLorenzo Bianconi { 925d3f77058SLorenzo Bianconi struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev); 926d3f77058SLorenzo Bianconi struct st_lsm6dsx_sensor *sensor; 92751a8b707SLorenzo Bianconi const struct st_lsm6dsx_reg *reg; 928739aff87SLorenzo Bianconi unsigned int data; 929d3f77058SLorenzo Bianconi int i, err = 0; 930d3f77058SLorenzo Bianconi 931d3f77058SLorenzo Bianconi for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { 932d3f77058SLorenzo Bianconi sensor = iio_priv(hw->iio_devs[i]); 933d3f77058SLorenzo Bianconi if (!(hw->enable_mask & BIT(sensor->id))) 934d3f77058SLorenzo Bianconi continue; 935d3f77058SLorenzo Bianconi 93651a8b707SLorenzo Bianconi reg = &st_lsm6dsx_odr_table[sensor->id].reg; 937739aff87SLorenzo Bianconi data = ST_LSM6DSX_SHIFT_VAL(0, reg->mask); 938739aff87SLorenzo Bianconi err = st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, 939739aff87SLorenzo Bianconi data); 940d3f77058SLorenzo Bianconi if (err < 0) 941d3f77058SLorenzo Bianconi return err; 942d3f77058SLorenzo Bianconi } 943d3f77058SLorenzo Bianconi 944d3f77058SLorenzo Bianconi if (hw->fifo_mode != ST_LSM6DSX_FIFO_BYPASS) 945d3f77058SLorenzo Bianconi err = st_lsm6dsx_flush_fifo(hw); 946d3f77058SLorenzo Bianconi 947d3f77058SLorenzo Bianconi return err; 948d3f77058SLorenzo Bianconi } 949d3f77058SLorenzo Bianconi 9503cec4850SLorenzo Bianconi static int __maybe_unused st_lsm6dsx_resume(struct device *dev) 951d3f77058SLorenzo Bianconi { 952d3f77058SLorenzo Bianconi struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev); 953d3f77058SLorenzo Bianconi struct st_lsm6dsx_sensor *sensor; 954d3f77058SLorenzo Bianconi int i, err = 0; 955d3f77058SLorenzo Bianconi 956d3f77058SLorenzo Bianconi for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { 957d3f77058SLorenzo Bianconi sensor = iio_priv(hw->iio_devs[i]); 958d3f77058SLorenzo Bianconi if (!(hw->enable_mask & BIT(sensor->id))) 959d3f77058SLorenzo Bianconi continue; 960d3f77058SLorenzo Bianconi 961d3f77058SLorenzo Bianconi err = st_lsm6dsx_set_odr(sensor, sensor->odr); 962d3f77058SLorenzo Bianconi if (err < 0) 963d3f77058SLorenzo Bianconi return err; 964d3f77058SLorenzo Bianconi } 965d3f77058SLorenzo Bianconi 966d3f77058SLorenzo Bianconi if (hw->enable_mask) 967d3f77058SLorenzo Bianconi err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT); 968d3f77058SLorenzo Bianconi 969d3f77058SLorenzo Bianconi return err; 970d3f77058SLorenzo Bianconi } 971d3f77058SLorenzo Bianconi 972d3f77058SLorenzo Bianconi const struct dev_pm_ops st_lsm6dsx_pm_ops = { 973d3f77058SLorenzo Bianconi SET_SYSTEM_SLEEP_PM_OPS(st_lsm6dsx_suspend, st_lsm6dsx_resume) 974d3f77058SLorenzo Bianconi }; 975d3f77058SLorenzo Bianconi EXPORT_SYMBOL(st_lsm6dsx_pm_ops); 976d3f77058SLorenzo Bianconi 977290a6ce1SLorenzo Bianconi MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>"); 978290a6ce1SLorenzo Bianconi MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>"); 979290a6ce1SLorenzo Bianconi MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx driver"); 980290a6ce1SLorenzo Bianconi MODULE_LICENSE("GPL v2"); 981