| /* Copyright 2016 The ChromiumOS Authors |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| /* LSM6DSM (also LSM6DSL) Accel and Gyro driver for Chrome EC */ |
| |
| #ifndef __CROS_EC_ACCELGYRO_LSM6DSM_H |
| #define __CROS_EC_ACCELGYRO_LSM6DSM_H |
| |
| #include "mag_bmm150.h" |
| #include "mag_cal.h" |
| #include "mag_lis2mdl.h" |
| #include "stm_mems_common.h" |
| |
| /* |
| * 7-bit address is 110101xb. Where 'x' is determined |
| * by the voltage on the ADDR pin |
| */ |
| #define LSM6DSM_ADDR0_FLAGS 0x6a |
| #define LSM6DSM_ADDR1_FLAGS 0x6b |
| |
| /* COMMON DEFINE FOR ACCEL-GYRO SENSORS */ |
| #define LSM6DSM_EN_BIT 0x01 |
| #define LSM6DSM_DIS_BIT 0x00 |
| |
| /* Access to embedded sensor hub register bank */ |
| #define LSM6DSM_FUNC_CFG_ACC_ADDR 0x01 |
| #define LSM6DSM_FUNC_CFG_EN 0x80 |
| #define LSM6DSM_FUNC_CFG_EN_B 0x20 |
| |
| /* FIFO decimator registers and bitmask */ |
| #define LSM6DSM_FIFO_CTRL1_ADDR 0x06 |
| |
| /* Output data rate registers and masks */ |
| #define LSM6DSM_ODR_REG(_sensor) (LSM6DSM_CTRL1_ADDR + _sensor) |
| #define LSM6DSM_ODR_MASK 0xf0 |
| |
| #define LSM6DSM_FIFO_CTRL2_ADDR 0x07 |
| |
| #define LSM6DSM_FIFO_CTRL3_ADDR 0x08 |
| #define LSM6DSM_FIFO_DEC_XL_OFF 0 |
| #define LSM6DSM_FIFO_DEC_G_OFF 3 |
| |
| #define LSM6DSM_FIFO_CTRL4_ADDR 0x09 |
| |
| #define LSM6DSM_FIFO_DECIMATOR(_dec) \ |
| (_dec < 8 ? _dec : (2 + __builtin_ctz(_dec))) |
| |
| /* Hardware FIFO size in byte */ |
| #define LSM6DSM_MAX_FIFO_SIZE 4096 |
| #define LSM6DSM_MAX_FIFO_LENGTH (LSM6DSM_MAX_FIFO_SIZE / OUT_XYZ_SIZE) |
| |
| #define LSM6DSM_FIFO_CTRL5_ADDR 0x0a |
| #define LSM6DSM_FIFO_CTRL5_ODR_OFF 3 |
| #define LSM6DSM_FIFO_CTRL5_ODR_MASK (0xf << LSM6DSM_FIFO_CTRL5_ODR_OFF) |
| #define LSM6DSM_FIFO_CTRL5_MODE_MASK 0x07 |
| |
| #define LSM6DSM_INT1_CTRL 0x0d |
| #define LSM6DSM_INT_FIFO_TH 0x08 |
| #define LSM6DSM_INT_FIFO_OVR 0x10 |
| #define LSM6DSM_INT_FIFO_FULL 0x20 |
| #define LSM6DSM_INT_SIGMO 0x40 |
| |
| /* Who Am I */ |
| #define LSM6DSM_WHO_AM_I_REG 0x0f |
| /* LSM6DSM/LSM6DSL/LSM6DS3TR-C */ |
| #define LSM6DSM_WHO_AM_I 0x6a |
| /* LSM6DS3 */ |
| #define LSM6DS3_WHO_AM_I 0x69 |
| |
| #define LSM6DSM_CTRL1_ADDR 0x10 |
| #define LSM6DSM_XL_ODR_MASK 0xf0 |
| |
| #define LSM6DSM_CTRL2_ADDR 0x11 |
| #define LSM6DSM_CTRL3_ADDR 0x12 |
| #define LSM6DSM_SW_RESET 0x01 |
| #define LSM6DSM_IF_INC 0x04 |
| #define LSM6DSM_PP_OD 0x10 |
| #define LSM6DSM_H_L_ACTIVE 0x20 |
| #define LSM6DSM_BDU 0x40 |
| #define LSM6DSM_BOOT 0x80 |
| |
| #define LSM6DSM_CTRL4_ADDR 0x13 |
| #define LSM6DSM_INT2_ON_INT1_MASK 0x20 |
| |
| #define LSM6DSM_CTRL6_ADDR 0x15 |
| #define LSM6DSM_CTRL7_ADDR 0x16 |
| |
| #define LSM6DSM_CTRL10_ADDR 0x19 |
| #define LSM6DSM_FUNC_EN_MASK 0x04 |
| #define LSM6DSM_SIG_MOT_MASK 0x01 |
| #define LSM6DSM_EMBED_FUNC_EN 0x04 |
| #define LSM6DSM_SIG_MOT_EN 0x01 |
| |
| /* Controller mode configuration register */ |
| #define LSM6DSM_CONTROLLER_CFG_ADDR 0x1a |
| #define LSM6DSM_PASSTROUGH_MASK 0x1f |
| #define LSM6DSM_EXT_TRIGGER_EN 0x10 |
| #define LSM6DSM_PULLUP_EN 0x08 |
| #define LSM6DSM_I2C_PASS_THRU_MODE 0x04 |
| #define LSM6DSM_I2C_CONTROLLER_ON 0x01 |
| |
| #define LSM6DSM_TAP_SRC_ADDR 0x1c |
| #define LSM6DSM_STAP_DETECT 0x20 |
| #define LSM6DSM_DTAP_DETECT 0x10 |
| |
| #define LSM6DSM_STATUS_REG 0x1e |
| |
| #define LSM6DSM_OUT_TEMP_L_ADDR 0x20 |
| |
| #define LSM6DSM_GYRO_OUT_X_L_ADDR 0x22 |
| #define LSM6DSM_ACCEL_OUT_X_L_ADDR 0x28 |
| |
| #define LSM6DSM_SENSORHUB1_REG 0x2e |
| |
| #define LSM6DSM_FIFO_STS1_ADDR 0x3a |
| #define LSM6DSM_FIFO_STS2_ADDR 0x3b |
| #define LSM6DSM_FIFO_DIFF_MASK 0x0fff |
| #define LSM6DSM_FIFO_EMPTY 0x1000 |
| #define LSM6DSM_FIFO_FULL 0x2000 |
| #define LSM6DSM_FIFO_DATA_OVR 0x4000 |
| #define LSM6DSM_FIFO_WATERMARK 0x8000 |
| #define LSM6DSM_FIFO_NODECIM 0x01 |
| |
| /* Out data register */ |
| #define LSM6DSM_FIFO_DATA_ADDR 0x3e |
| |
| /* Registers value for supported FIFO mode */ |
| #define LSM6DSM_FIFO_MODE_BYPASS_VAL 0x00 |
| #define LSM6DSM_FIFO_MODE_CONTINUOUS_VAL 0x06 |
| |
| #define LSM6DSM_FUNC_SRC1_ADDR 0x53 |
| #define LSM6DSM_SENSORHUB_END_OP 0x01 |
| #define LSM6DSM_SIGN_MOTION_IA 0x40 |
| |
| #define LSM6DSM_LIR_ADDR 0x58 |
| #define LSM6DSM_LIR_MASK 0x01 |
| #define LSM6DSM_EN_INT 0x80 |
| #define LSM6DSM_EN_TAP 0x0e |
| #define LSM6DSM_TAP_MASK 0x8e |
| |
| #define LSM6DSM_TAP_THS_6D 0x59 |
| #define LSM6DSM_D4D_EN_MASK 0x80 |
| #define LSM6DSM_TAP_TH_MASK 0x1f |
| |
| #define LSM6DSM_INT_DUR2_ADDR 0x5a |
| #define LSM6DSM_TAP_DUR_MASK 0xf0 |
| #define LSM6DSM_TAP_QUIET_MASK 0x0c |
| |
| #define LSM6DSM_WUP_THS_ADDR 0x5b |
| #define LSM6DSM_S_D_TAP_MASK 0x80 |
| #define LSM6DSM_STAP_EN 0 |
| #define LSM6DSM_DTAP_EN 1 |
| |
| #define LSM6DSM_MD1_CFG_ADDR 0x5e |
| #define LSM6DSM_INT1_STAP 0x40 |
| #define LSM6DSM_INT1_DTAP 0x08 |
| |
| /* Register values for Sensor Hub Slave 0 / Bank A */ |
| #define LSM6DSM_SLV0_ADD_ADDR 0x02 |
| #define LSM6DSM_SLV0_ADDR_SHFT 1 |
| #define LSM6DSM_SLV0_ADDR_MASK 0xfe |
| #define LSM6DSM_SLV0_RD_BIT 0x01 |
| |
| #define LSM6DSM_SLV0_SUBADD_ADDR 0x03 |
| |
| #define LSM6DSM_SLV0_CONFIG_ADDR 0x04 |
| #define LSM6DSM_SLV0_SLV_RATE_SHFT 6 |
| #define LSM6DSM_SLV0_SLV_RATE_MASK 0xc0 |
| #define LSM6DSM_SLV0_AUX_SENS_SHFT 4 |
| #define LSM6DSM_SLV0_AUX_SENS_MASK 0x30 |
| #define LSM6DSM_SLV0_NUM_OPS_MASK 0x07 |
| |
| #define LSM6DSM_SLV1_CONFIG_ADDR 0x07 |
| #define LSM6DSM_SLV0_WR_ONCE_MASK 0x20 |
| |
| #define LSM6DSM_DATA_WRITE_SUB_SLV0_ADDR 0x0e |
| |
| /* Define device available in FIFO pattern */ |
| enum dev_fifo { |
| FIFO_DEV_INVALID = -1, |
| FIFO_DEV_GYRO = 0, |
| FIFO_DEV_ACCEL, |
| FIFO_DEV_MAG, |
| }; |
| |
| #ifdef CONFIG_LSM6DSM_SEC_I2C |
| #define FIFO_DEV_NUM (FIFO_DEV_MAG + 1) |
| #else |
| #define FIFO_DEV_NUM (FIFO_DEV_ACCEL + 1) |
| #endif |
| |
| struct fstatus { |
| uint16_t len; |
| uint16_t pattern; |
| }; |
| |
| /* Absolute maximum rate for acc and gyro sensors */ |
| #define LSM6DSM_ODR_MIN_VAL 13000 |
| #define LSM6DSM_ODR_MAX_VAL \ |
| MOTION_MAX_SENSOR_FREQUENCY(416000, LSM6DSM_ODR_MIN_VAL) |
| |
| /* ODR reg value from selected data rate in mHz */ |
| #define LSM6DSM_ODR_TO_REG(_odr) (__fls(_odr / LSM6DSM_ODR_MIN_VAL) + 1) |
| |
| /* normalized ODR value from selected data rate in mHz */ |
| #define LSM6DSM_REG_TO_ODR(_reg) (LSM6DSM_ODR_MIN_VAL << (_reg - 1)) |
| |
| /* Full Scale range value and gain for Acc */ |
| #define LSM6DSM_FS_LIST_NUM 4 |
| |
| #define LSM6DSM_ACCEL_FS_ADDR 0x10 |
| #define LSM6DSM_ACCEL_FS_MASK 0x0c |
| |
| #define LSM6DSM_ACCEL_FS_2G_VAL 0x00 |
| #define LSM6DSM_ACCEL_FS_4G_VAL 0x02 |
| #define LSM6DSM_ACCEL_FS_8G_VAL 0x03 |
| #define LSM6DSM_ACCEL_FS_16G_VAL 0x01 |
| |
| #define LSM6DSM_ACCEL_FS_MAX_VAL 16 |
| |
| /* Accel Reg value from Full Scale */ |
| #define LSM6DSM_ACCEL_FS_REG(_fs) \ |
| (_fs == 2 ? LSM6DSM_ACCEL_FS_2G_VAL : \ |
| _fs == 16 ? LSM6DSM_ACCEL_FS_16G_VAL : \ |
| __fls(_fs)) |
| |
| /* Accel normalized FS value from Full Scale */ |
| #define LSM6DSM_ACCEL_NORMALIZE_FS(_fs) (1 << __fls(_fs)) |
| |
| /* Full Scale range value and gain for Gyro */ |
| #define LSM6DSM_GYRO_FS_ADDR 0x11 |
| #define LSM6DSM_GYRO_FS_MASK 0x0c |
| |
| /* Supported gyroscope ranges: |
| * name(dps) | register | gain(udps/LSB) | actual value(dps) |
| * 250 | 0 | 8750 | 286.72 |
| * 500 | 1 | 17500 | 573.44 |
| * 1000 | 2 | 35000 | 1146.88 |
| * 2000 | 3 | 70000 | 2293.76 |
| */ |
| #define LSM6DSM_GYRO_FS_MIN_VAL_MDPS ((8750 << 15) / 1000) |
| #define LSM6DSM_GYRO_FS_MAX_REG_VAL 3 |
| |
| /* Gyro Reg value for Full Scale selection */ |
| #define LSM6DSM_GYRO_FS_REG(_fs) \ |
| __fls(MAX(1, (_fs * 1000) / LSM6DSM_GYRO_FS_MIN_VAL_MDPS)) |
| |
| /* Gyro normalized FS value from Full Scale register */ |
| #define LSM6DSM_GYRO_NORMALIZE_FS(_reg) \ |
| ((LSM6DSM_GYRO_FS_MIN_VAL_MDPS << (_reg)) / 1000) |
| |
| /* FS register address/mask for Acc/Gyro sensors */ |
| #define LSM6DSM_RANGE_REG(_sensor) (LSM6DSM_ACCEL_FS_ADDR + (_sensor)) |
| #define LSM6DSM_RANGE_MASK 0x0c |
| |
| /* Status register bitmask for Acc/Gyro data ready */ |
| enum lsm6dsm_status { |
| LSM6DSM_STS_DOWN = 0x00, |
| LSM6DSM_STS_XLDA_UP = 0x01, |
| LSM6DSM_STS_GDA_UP = 0x02 |
| }; |
| |
| #define LSM6DSM_STS_XLDA_MASK 0x01 |
| #define LSM6DSM_STS_GDA_MASK 0x02 |
| |
| /* Sensor resolution in number of bits: fixed 16 bit */ |
| #define LSM6DSM_RESOLUTION 16 |
| |
| extern const struct accelgyro_drv lsm6dsm_drv; |
| |
| void lsm6dsm_interrupt(enum gpio_signal signal); |
| |
| struct lsm6dsm_fifo_data { |
| /* |
| * FIFO data order is based on the ODR of each sensors. |
| * For example Acc @ 52 Hz, Gyro @ 26 Hz Mag @ 13 Hz in FIFO we have |
| * for each pattern this data samples: |
| * ________ _______ _______ _______ ________ _______ _______ |
| * | Gyro_0 | Acc_0 | Mag_0 | Acc_1 | Gyro_1 | Acc_2 | Acc_3 | |
| * |________|_______|_______|_______|________|_______|_______| |
| * |
| * Total samples for each pattern: 2 Gyro, 4 Acc, 1 Mag |
| */ |
| /* Calculated samples in a pattern, based on ODR. */ |
| int samples_in_pattern[FIFO_DEV_NUM]; |
| |
| /* Sum of all samples_in_pattern. */ |
| int total_samples_in_pattern; |
| }; |
| |
| /** |
| * Structure used to hold fifo state. This struct should only be used if |
| * CONFIG_ACCEL_FIFO is defined. |
| */ |
| struct lsm6dsm_accel_fifo_state { |
| struct lsm6dsm_fifo_data config; |
| struct lsm6dsm_fifo_data current; |
| int next_in_pattern; |
| /* |
| * After an ODR change, the sensor filters need settling time; discard |
| * initial samples with incorrect values |
| */ |
| unsigned int samples_to_discard[FIFO_DEV_NUM]; |
| }; |
| |
| /* |
| * lsm6dsm_data is used for accel gyro and the sensor connect to a LSM6DSM. |
| * |
| * +---- lsm6dsm_data ------------------------------------------------+ |
| * | +--- stprivate_data ---+ | |
| * | | | ST common data for accelerometer | |
| * | +----------------------+ | |
| * | +--- stprivate_data ---+ | |
| * | | | ST common data for gyroscope | |
| * | +----------------------+ | |
| * | +--- stprivate_data ---+ | |
| * | | | ST common data for LIS2MDL magnetomer | |
| * | +----------------------+ (optional) | |
| * | | |
| * | Fifo Information | |
| * | | |
| * | +----- Magnetometer information -----------------------------+ | |
| * | | +--- mag_cal_t ------+ | | |
| * | | | | Data for online calibration | | |
| * | | +--------------------+ | | |
| * | | Other privata data | | |
| * | +------------------------------------------------------------+ | |
| * +------------------------------------------------------------------+ |
| * |
| * In motion_sensors array, use LSM6DSM_ST_DATA to point drv_data |
| * to the right st_data structure. |
| */ |
| struct lsm6dsm_data { |
| #ifdef CONFIG_MAG_LSM6DSM_LIS2MDL |
| /* LIS2MDL uses st_mems_common and needs stprivate_data */ |
| struct stprivate_data st_data[3]; |
| #else |
| /* BMM150 doesn't use st_mems_common; no stprivate_data */ |
| struct stprivate_data st_data[2]; |
| #endif |
| struct lsm6dsm_accel_fifo_state *accel_fifo_state; |
| #if defined(CONFIG_LSM6DSM_SEC_I2C) && defined(CONFIG_MAG_CALIBRATE) |
| union { |
| #ifdef CONFIG_MAG_LSM6DSM_BMM150 |
| struct bmm150_private_data compass; |
| #endif |
| #ifdef CONFIG_MAG_LSM6DSM_LIS2MDL |
| struct lis2mdl_private_data compass; |
| #endif |
| struct mag_cal_t cal; |
| }; |
| #endif /* CONFIG_MAG_CALIBRATE */ |
| }; |
| |
| #ifdef CONFIG_ACCEL_FIFO |
| #define LSM6DSM_ACCEL_FIFO_STATE (&((struct lsm6dsm_accel_fifo_state){})) |
| #else |
| #define LSM6DSM_ACCEL_FIFO_STATE NULL |
| #endif |
| |
| #define LSM6DSM_DATA \ |
| ((struct lsm6dsm_data){ \ |
| .accel_fifo_state = LSM6DSM_ACCEL_FIFO_STATE, \ |
| }) |
| |
| /* |
| * Note: The specific number of samples to discard depends on the filters |
| * configured for the chip, as well as the ODR being set. For most of our |
| * allowed ODRs, 5 should suffice. |
| * See: ST's LSM6DSM application notes (AN4987) Tables 17 and 19 for details |
| */ |
| #define LSM6DSM_DISCARD_SAMPLES 5 |
| |
| #define LSM6DSM_ST_DATA(g, type) (&(&(g))->st_data[(type)]) |
| |
| #define LSM6DSM_MAIN_SENSOR(_s) ((_s) - (_s)->type) |
| |
| #define LSM6DSM_GET_DATA(_s) \ |
| ((struct lsm6dsm_data *)(LSM6DSM_MAIN_SENSOR(_s))->drv_data) |
| |
| #if defined(CONFIG_LSM6DSM_SEC_I2C) && defined(CONFIG_MAG_CALIBRATE) |
| #define LIS2MDL_CAL(_s) (&LSM6DSM_GET_DATA(_s)->cal) |
| #endif |
| |
| int lsm6dsm_set_data_rate(const struct motion_sensor_t *s, int rate, int rnd); |
| |
| #if defined(CONFIG_ZEPHYR) |
| /* Get the motion sensor ID of the LSM6DSM sensor that generates the |
| * interrupt. The interrupt is converted to the event and transferred to |
| * motion sense task that actually handles the interrupt. |
| * |
| * Here we use an alias (lsm6dsm_int) to get the motion sensor ID. This alias |
| * MUST be defined for this driver to work. |
| * aliases { |
| * lsm6dsm-int = &lid_accel; |
| * }; |
| */ |
| #if DT_NODE_EXISTS(DT_ALIAS(lsm6dsm_int)) |
| #define CONFIG_ACCEL_LSM6DSM_INT_EVENT \ |
| TASK_EVENT_MOTION_SENSOR_INTERRUPT(SENSOR_ID(DT_ALIAS(lsm6dsm_int))) |
| #endif |
| #endif |
| |
| #endif /* __CROS_EC_ACCELGYRO_LSM6DSM_H */ |