diff --git a/drivers/sensor/st/CMakeLists.txt b/drivers/sensor/st/CMakeLists.txt index b833043ae6c..816a4cf0d4f 100644 --- a/drivers/sensor/st/CMakeLists.txt +++ b/drivers/sensor/st/CMakeLists.txt @@ -32,6 +32,7 @@ add_subdirectory_ifdef(CONFIG_LSM6DSO16IS lsm6dso16is) add_subdirectory_ifdef(CONFIG_LSM6DSV16X lsm6dsv16x) add_subdirectory_ifdef(CONFIG_LSM9DS0_GYRO lsm9ds0_gyro) add_subdirectory_ifdef(CONFIG_LSM9DS0_MFD lsm9ds0_mfd) +add_subdirectory_ifdef(CONFIG_LSM9DS1 lsm9ds1) add_subdirectory_ifdef(CONFIG_QDEC_STM32 qdec_stm32) add_subdirectory_ifdef(CONFIG_STM32_DIGI_TEMP stm32_digi_temp) add_subdirectory_ifdef(CONFIG_STM32_TEMP stm32_temp) diff --git a/drivers/sensor/st/Kconfig b/drivers/sensor/st/Kconfig index a3f03a36b66..79a57bb6168 100644 --- a/drivers/sensor/st/Kconfig +++ b/drivers/sensor/st/Kconfig @@ -31,6 +31,7 @@ source "drivers/sensor/st/lsm6dso16is/Kconfig" source "drivers/sensor/st/lsm6dsv16x/Kconfig" source "drivers/sensor/st/lsm9ds0_gyro/Kconfig" source "drivers/sensor/st/lsm9ds0_mfd/Kconfig" +source "drivers/sensor/st/lsm9ds1/Kconfig" source "drivers/sensor/st/qdec_stm32/Kconfig" source "drivers/sensor/st/stm32_digi_temp/Kconfig" source "drivers/sensor/st/stm32_temp/Kconfig" diff --git a/drivers/sensor/st/lsm9ds1/CMakeLists.txt b/drivers/sensor/st/lsm9ds1/CMakeLists.txt new file mode 100644 index 00000000000..1dc9559d9f1 --- /dev/null +++ b/drivers/sensor/st/lsm9ds1/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(lsm9ds1.c) + +zephyr_library_include_directories(../stmemsc) diff --git a/drivers/sensor/st/lsm9ds1/Kconfig b/drivers/sensor/st/lsm9ds1/Kconfig new file mode 100644 index 00000000000..fb6564e6250 --- /dev/null +++ b/drivers/sensor/st/lsm9ds1/Kconfig @@ -0,0 +1,19 @@ +# Copyright (c) 2024 Bootlin +# SPDX-License-Identifier: Apache-2.0 + +menuconfig LSM9DS1 + bool "LSM9DS1 I2C accelerometer and gyroscope chip" + default y + depends on DT_HAS_ST_LSM9DS1_ENABLED + select I2C + select HAS_STMEMSC + select USE_STDC_LSM9DS1 + +if LSM9DS1 + +config LSM9DS1_ENABLE_TEMP + bool "LSM9DS1 Temperature sensor" + help + Enable/disable temperature + +endif #LSM9DS1 diff --git a/drivers/sensor/st/lsm9ds1/lsm9ds1.c b/drivers/sensor/st/lsm9ds1/lsm9ds1.c new file mode 100644 index 00000000000..4f6131e6b68 --- /dev/null +++ b/drivers/sensor/st/lsm9ds1/lsm9ds1.c @@ -0,0 +1,651 @@ +/* + * Copyright (c) 2024 Bootlin + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT st_lsm9ds1 + +#include +#include + +#include "lsm9ds1.h" +#include + +LOG_MODULE_REGISTER(LSM9DS1, CONFIG_SENSOR_LOG_LEVEL); + +/* Sensitivity of the accelerometer, indexed by the raw full scale value. Unit is µg/ LSB */ +static const uint16_t lsm9ds1_accel_fs_sens[] = {61, 732, 122, 244}; + +/* + * Sensitivity of the gyroscope, indexed by the raw full scale value. + * The value here is just a factor applied to GAIN_UNIT_G, as the sensitivity is + * proportional to the full scale size. + * The index 2 is never used : the value `0` is just a placeholder. + */ +static const uint16_t lsm9ds1_gyro_fs_sens[] = {1, 2, 0, 8}; + +/* + * Values of the different sampling frequencies of the accelerometer, indexed by the raw odr + * value that the sensor understands. + */ +static const uint16_t lsm9ds1_odr_map[] = {0, 10, 50, 119, 238, 476, 952}; + +/* + * Value of the different sampling frequencies of the gyroscope, indexed by the raw odr value + * that the sensor understands. + */ +static const uint16_t lsm9ds1_gyro_odr_map[] = {0, 15, 59, 119, 238, 476, 952}; + +static int lsm9ds1_reboot(const struct device *dev) +{ + const struct lsm9ds1_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lsm9ds1_ctrl_reg8_t ctrl8_reg; + int ret; + + ret = lsm9ds1_read_reg(ctx, LSM9DS1_CTRL_REG8, (uint8_t *)&ctrl8_reg, 1); + if (ret < 0) { + return ret; + } + + ctrl8_reg.boot = 1; + + ret = lsm9ds1_write_reg(ctx, LSM9DS1_CTRL_REG8, (uint8_t *)&ctrl8_reg, 1); + if (ret < 0) { + return ret; + } + + k_msleep(50); + + return 0; +} + +static int lsm9ds1_accel_range_to_fs_val(int32_t range) +{ + switch (range) { + case 2: + return LSM9DS1_2g; + case 4: + return LSM9DS1_4g; + case 8: + return LSM9DS1_8g; + case 16: + return LSM9DS1_16g; + default: + return -EINVAL; + } +} + +static int lsm9ds1_gyro_range_to_fs_val(int32_t range) +{ + switch (range) { + case 245: + return LSM9DS1_245dps; + case 500: + return LSM9DS1_500dps; + case 2000: + return LSM9DS1_2000dps; + default: + return -EINVAL; + } +} + +static int lsm9ds1_accel_fs_val_to_gain(int fs) +{ + return lsm9ds1_accel_fs_sens[fs]; +} + +static int lsm9ds1_accel_freq_to_odr_val(uint16_t freq) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(lsm9ds1_odr_map); i++) { + if (freq <= lsm9ds1_odr_map[i]) { + return i; + } + } + + return -EINVAL; +} + +static int lsm9ds1_gyro_freq_to_odr_val(uint16_t freq) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(lsm9ds1_gyro_odr_map); i++) { + if (freq <= lsm9ds1_gyro_odr_map[i]) { + return i; + } + } + + return -EINVAL; +} + +static int lsm9ds1_accel_set_odr_raw(const struct device *dev, uint8_t odr) +{ + const struct lsm9ds1_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + struct lsm9ds1_data *data = dev->data; + int ret; + + lsm9ds1_ctrl_reg6_xl_t ctrl_reg6_xl; + + ret = lsm9ds1_read_reg(ctx, LSM9DS1_CTRL_REG6_XL, (uint8_t *)&ctrl_reg6_xl, 1); + if (ret < 0) { + return ret; + } + + ctrl_reg6_xl.odr_xl = odr; + + ret = lsm9ds1_write_reg(ctx, LSM9DS1_CTRL_REG6_XL, (uint8_t *)&ctrl_reg6_xl, 1); + if (ret < 0) { + return ret; + } + + data->accel_odr = odr; + + return 0; +} + +static int lsm9ds1_gyro_set_odr_raw(const struct device *dev, uint8_t odr) +{ + const struct lsm9ds1_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + struct lsm9ds1_data *data = dev->data; + int ret; + + lsm9ds1_ctrl_reg1_g_t ctrl_reg1; + + ret = lsm9ds1_read_reg(ctx, LSM9DS1_CTRL_REG1_G, (uint8_t *)&ctrl_reg1, 1); + if (ret < 0) { + return ret; + } + + ctrl_reg1.odr_g = odr; + + ret = lsm9ds1_write_reg(ctx, LSM9DS1_CTRL_REG1_G, (uint8_t *)&ctrl_reg1, 1); + if (ret < 0) { + return ret; + } + + data->gyro_odr = odr; + return 0; +} + +static int lsm9ds1_gyro_odr_set(const struct device *dev, uint16_t freq) +{ + struct lsm9ds1_data *data = dev->data; + int odr; + int ret; + + odr = lsm9ds1_gyro_freq_to_odr_val(freq); + + if (odr == data->gyro_odr) { + return 0; + } + + LOG_INF("You are also changing the odr of the accelerometer"); + + ret = lsm9ds1_gyro_set_odr_raw(dev, odr); + if (ret < 0) { + LOG_DBG("failed to set gyroscope sampling rate"); + return ret; + } + + /* + * When the gyroscope is on, the value of the accelerometer odr must be + * the same as the value of the gyroscope. + */ + + ret = lsm9ds1_accel_set_odr_raw(dev, odr); + if (ret < 0) { + LOG_ERR("failed to set accelerometer sampling rate"); + return ret; + } + + return 0; +} + +static int lsm9ds1_accel_odr_set(const struct device *dev, uint16_t freq) +{ + const struct lsm9ds1_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + struct lsm9ds1_data *data = dev->data; + int odr, ret; + lsm9ds1_imu_odr_t old_odr; + + ret = lsm9ds1_imu_data_rate_get(ctx, &old_odr); + if (ret < 0) { + return ret; + } + + /* + * The gyroscope is on : + * we have to change the odr on both the accelerometer and the gyroscope + */ + if (old_odr & GYRO_ODR_MASK) { + + odr = lsm9ds1_gyro_freq_to_odr_val(freq); + + if (odr == data->gyro_odr) { + return 0; + } + + LOG_INF("You are also changing the odr of the gyroscope"); + + ret = lsm9ds1_accel_set_odr_raw(dev, odr); + if (ret < 0) { + LOG_DBG("failed to set accelerometer sampling rate"); + return ret; + } + + ret = lsm9ds1_gyro_set_odr_raw(dev, odr); + if (ret < 0) { + LOG_ERR("failed to set gyroscope sampling rate"); + return ret; + } + + /* The gyroscope is off, we have to change the odr of just the accelerometer */ + } else { + + odr = lsm9ds1_accel_freq_to_odr_val(freq); + + if (odr == data->accel_odr) { + return 0; + } + + if (odr < 0) { + return odr; + } + + ret = lsm9ds1_accel_set_odr_raw(dev, odr); + if (ret < 0) { + LOG_DBG("failed to set accelerometer sampling rate"); + return ret; + } + } + return 0; +} + +static int lsm9ds1_accel_range_set(const struct device *dev, int32_t range) +{ + int fs; + struct lsm9ds1_data *data = dev->data; + const struct lsm9ds1_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + int ret; + + fs = lsm9ds1_accel_range_to_fs_val(range); + if (fs < 0) { + LOG_DBG("full scale value not supported"); + return fs; + } + + ret = lsm9ds1_xl_full_scale_set(ctx, fs); + if (ret < 0) { + LOG_DBG("failed to set accelerometer full-scale"); + return ret; + } + + data->acc_gain = lsm9ds1_accel_fs_val_to_gain(fs); + return 0; +} + +static int lsm9ds1_gyro_range_set(const struct device *dev, int32_t range) +{ + int fs; + struct lsm9ds1_data *data = dev->data; + const struct lsm9ds1_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + int ret; + + fs = lsm9ds1_gyro_range_to_fs_val(range); + if (fs < 0) { + return fs; + } + + ret = lsm9ds1_gy_full_scale_set(ctx, fs); + if (ret < 0) { + LOG_DBG("failed to set gyroscope full-scale"); + return ret; + } + + data->gyro_gain = (lsm9ds1_gyro_fs_sens[fs] * GAIN_UNIT_G); + return 0; +} + +static int lsm9ds1_accel_config(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + switch (attr) { + case SENSOR_ATTR_FULL_SCALE: + return lsm9ds1_accel_range_set(dev, sensor_ms2_to_g(val)); + case SENSOR_ATTR_SAMPLING_FREQUENCY: + return lsm9ds1_accel_odr_set(dev, val->val1); + default: + LOG_DBG("Accel attribute not supported."); + return -ENOTSUP; + } + + return 0; +} + +static int lsm9ds1_gyro_config(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + switch (attr) { + case SENSOR_ATTR_FULL_SCALE: + return lsm9ds1_gyro_range_set(dev, sensor_rad_to_degrees(val)); + case SENSOR_ATTR_SAMPLING_FREQUENCY: + return lsm9ds1_gyro_odr_set(dev, val->val1); + default: + LOG_DBG("Gyro attribute not supported."); + return -ENOTSUP; + } + + return 0; +} + +static int lsm9ds1_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + switch (chan) { + case SENSOR_CHAN_ACCEL_XYZ: + return lsm9ds1_accel_config(dev, chan, attr, val); + case SENSOR_CHAN_GYRO_XYZ: + return lsm9ds1_gyro_config(dev, chan, attr, val); + default: + LOG_WRN("attr_set() not supported on this channel."); + return -ENOTSUP; + } + return 0; +} + +static int lsm9ds1_sample_fetch_accel(const struct device *dev) +{ + const struct lsm9ds1_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + struct lsm9ds1_data *data = dev->data; + int ret; + + ret = lsm9ds1_acceleration_raw_get(ctx, data->acc); + if (ret < 0) { + LOG_DBG("Failed to read sample"); + return ret; + } + + return 0; +} + +static int lsm9ds1_sample_fetch_gyro(const struct device *dev) +{ + const struct lsm9ds1_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + struct lsm9ds1_data *data = dev->data; + int ret; + + ret = lsm9ds1_angular_rate_raw_get(ctx, data->gyro); + if (ret < 0) { + LOG_DBG("Failed to read sample"); + return ret; + } + return 0; +} + +#if IS_ENABLED(CONFIG_LSM9DS1_ENABLE_TEMP) +static int lsm9ds1_sample_fetch_temp(const struct device *dev) +{ + const struct lsm9ds1_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + struct lsm9ds1_data *data = dev->data; + int ret; + + ret = lsm9ds1_temperature_raw_get(ctx, &data->temp_sample); + if (ret < 0) { + LOG_DBG("Failed to read sample"); + return ret; + } + + return 0; +} +#endif + +static int lsm9ds1_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + switch (chan) { + case SENSOR_CHAN_ACCEL_XYZ: + lsm9ds1_sample_fetch_accel(dev); + break; + case SENSOR_CHAN_GYRO_XYZ: + lsm9ds1_sample_fetch_gyro(dev); + break; +#if IS_ENABLED(CONFIG_LSM9DS1_ENABLE_TEMP) + case SENSOR_CHAN_DIE_TEMP: + lsm9ds1_sample_fetch_temp(dev); + break; +#endif + case SENSOR_CHAN_ALL: + lsm9ds1_sample_fetch_accel(dev); + lsm9ds1_sample_fetch_gyro(dev); +#if IS_ENABLED(CONFIG_LSM9DS1_ENABLE_TEMP) + lsm9ds1_sample_fetch_temp(dev); +#endif + break; + default: + return -ENOTSUP; + } + return 0; +} + +static inline void lsm9ds1_accel_convert(struct sensor_value *val, int raw_val, + uint32_t sensitivity) +{ + /* Sensitivity is exposed in ug/LSB */ + /* Convert to m/s^2 */ + sensor_ug_to_ms2(raw_val * sensitivity, val); +} + +static inline int lsm9ds1_accel_get_channel(enum sensor_channel chan, struct sensor_value *val, + struct lsm9ds1_data *data, uint32_t sensitivity) +{ + uint8_t i; + + switch (chan) { + case SENSOR_CHAN_ACCEL_X: + lsm9ds1_accel_convert(val, data->acc[0], sensitivity); + break; + case SENSOR_CHAN_ACCEL_Y: + lsm9ds1_accel_convert(val, data->acc[1], sensitivity); + break; + case SENSOR_CHAN_ACCEL_Z: + lsm9ds1_accel_convert(val, data->acc[2], sensitivity); + break; + case SENSOR_CHAN_ACCEL_XYZ: + for (i = 0; i < 3; i++) { + lsm9ds1_accel_convert(val++, data->acc[i], sensitivity); + } + break; + default: + return -ENOTSUP; + } + + return 0; +} + +static int lsm9ds1_accel_channel_get(enum sensor_channel chan, struct sensor_value *val, + struct lsm9ds1_data *data) +{ + return lsm9ds1_accel_get_channel(chan, val, data, data->acc_gain); +} + +static inline void lsm9ds1_gyro_convert(struct sensor_value *val, int raw_val, uint32_t sensitivity) +{ + /* Sensitivity is exposed in udps/LSB */ + /* Convert to rad/s */ + sensor_10udegrees_to_rad((raw_val * (int32_t)sensitivity) / 10, val); +} + +static inline int lsm9ds1_gyro_get_channel(enum sensor_channel chan, struct sensor_value *val, + struct lsm9ds1_data *data, uint32_t sensitivity) +{ + uint8_t i; + + switch (chan) { + case SENSOR_CHAN_GYRO_X: + lsm9ds1_gyro_convert(val, data->gyro[0], sensitivity); + break; + case SENSOR_CHAN_GYRO_Y: + lsm9ds1_gyro_convert(val, data->gyro[1], sensitivity); + break; + case SENSOR_CHAN_GYRO_Z: + lsm9ds1_gyro_convert(val, data->gyro[2], sensitivity); + break; + case SENSOR_CHAN_GYRO_XYZ: + for (i = 0; i < 3; i++) { + lsm9ds1_gyro_convert(val++, data->gyro[i], sensitivity); + } + break; + default: + return -ENOTSUP; + } + + return 0; +} + +static int lsm9ds1_gyro_channel_get(enum sensor_channel chan, struct sensor_value *val, + struct lsm9ds1_data *data) +{ + return lsm9ds1_gyro_get_channel(chan, val, data, data->gyro_gain); +} + +#if IS_ENABLED(CONFIG_LSM9DS1_ENABLE_TEMP) +static void lsm9ds1_temp_channel_get(struct sensor_value *val, struct lsm9ds1_data *data) +{ + val->val1 = data->temp_sample / TEMP_SENSITIVITY + TEMP_OFFSET; + val->val2 = (data->temp_sample % TEMP_SENSITIVITY) * (1000000 / TEMP_SENSITIVITY); +} +#endif + +static int lsm9ds1_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct lsm9ds1_data *data = dev->data; + + switch (chan) { + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: + lsm9ds1_accel_channel_get(chan, val, data); + break; + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + case SENSOR_CHAN_GYRO_XYZ: + lsm9ds1_gyro_channel_get(chan, val, data); + break; +#if IS_ENABLED(CONFIG_LSM9DS1_ENABLE_TEMP) + case SENSOR_CHAN_DIE_TEMP: + lsm9ds1_temp_channel_get(val, data); + break; +#endif + default: + return -ENOTSUP; + } + + return 0; +} + +static const struct sensor_driver_api lsm9ds1_api_funcs = { + .sample_fetch = lsm9ds1_sample_fetch, + .channel_get = lsm9ds1_channel_get, + .attr_set = lsm9ds1_attr_set, +}; + +static int lsm9ds1_init(const struct device *dev) +{ + const struct lsm9ds1_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + struct lsm9ds1_data *lsm9ds1 = dev->data; + uint8_t chip_id, fs; + int ret; + + ret = lsm9ds1_reboot(dev); + if (ret < 0) { + LOG_ERR("Failed to reboot device"); + return ret; + } + + ret = lsm9ds1_read_reg(ctx, LSM9DS1_WHO_AM_I, &chip_id, 1); + if (ret < 0) { + LOG_ERR("failed reading chip id"); + return ret; + } + + if (chip_id != LSM9DS1_IMU_ID) { + LOG_ERR("Invalid ID : got %x", chip_id); + return -EIO; + } + LOG_DBG("chip_id : %x", chip_id); + + LOG_DBG("output data rate is %d\n", cfg->imu_odr); + ret = lsm9ds1_imu_data_rate_set(ctx, cfg->imu_odr); + if (ret < 0) { + LOG_ERR("failed to set IMU odr"); + return ret; + } + + fs = cfg->accel_range; + LOG_DBG("accel range is %d\n", fs); + ret = lsm9ds1_xl_full_scale_set(ctx, fs); + if (ret < 0) { + LOG_ERR("failed to set accelerometer range %d", fs); + return ret; + } + + lsm9ds1->acc_gain = lsm9ds1_accel_fs_val_to_gain(fs); + + fs = cfg->gyro_range; + LOG_DBG("gyro range is %d", fs); + ret = lsm9ds1_gy_full_scale_set(ctx, fs); + if (ret < 0) { + LOG_ERR("failed to set gyroscope range %d\n", fs); + return ret; + } + lsm9ds1->gyro_gain = (lsm9ds1_gyro_fs_sens[fs] * GAIN_UNIT_G); + + return 0; +} + +#define LSM9DS1_CONFIG_COMMON(inst) \ + .imu_odr = DT_INST_PROP(inst, imu_odr), \ + .accel_range = DT_INST_PROP(inst, accel_range), \ + .gyro_range = DT_INST_PROP(inst, gyro_range), + +/* + * Instantiation macros used when a device is on an I2C bus. + */ + +#define LSM9DS1_CONFIG_I2C(inst) \ + { \ + STMEMSC_CTX_I2C(&lsm9ds1_config_##inst.stmemsc_cfg), \ + .stmemsc_cfg = \ + { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }, \ + LSM9DS1_CONFIG_COMMON(inst) \ + } + +#define LSM9DS1_DEFINE(inst) \ + static struct lsm9ds1_data lsm9ds1_data_##inst = { \ + .acc_gain = 0, \ + }; \ + \ + static struct lsm9ds1_config lsm9ds1_config_##inst = LSM9DS1_CONFIG_I2C(inst); \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, lsm9ds1_init, NULL, &lsm9ds1_data_##inst, \ + &lsm9ds1_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &lsm9ds1_api_funcs); + +DT_INST_FOREACH_STATUS_OKAY(LSM9DS1_DEFINE); diff --git a/drivers/sensor/st/lsm9ds1/lsm9ds1.h b/drivers/sensor/st/lsm9ds1/lsm9ds1.h new file mode 100644 index 00000000000..a0dde3191a8 --- /dev/null +++ b/drivers/sensor/st/lsm9ds1/lsm9ds1.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 Bootlin + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_LSM9DS1_LSM9DS1_H_ +#define ZEPHYR_DRIVERS_SENSOR_LSM9DS1_LSM9DS1_H_ + +#include "lsm9ds1_reg.h" + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) +#include +#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) */ + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) +#include +#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */ + +#define GAIN_UNIT_XL (61LL) +#define GAIN_UNIT_G (8750LL) + +#define TEMP_OFFSET 25 /* raw output of zero indicate 25°C */ +#define TEMP_SENSITIVITY 16 /* 16 LSB / °C */ + +#define GYRO_ODR_MASK 0x7 + +struct lsm9ds1_config { + stmdev_ctx_t ctx; + union { +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) + const struct i2c_dt_spec i2c; +#endif +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) + const struct spi_dt_spec spi; +#endif + } stmemsc_cfg; + uint8_t accel_range; + uint8_t gyro_range; + uint8_t imu_odr; +}; + +struct lsm9ds1_data { + int16_t acc[3]; + uint32_t acc_gain; + int16_t gyro[3]; + uint32_t gyro_gain; + + uint16_t accel_odr; + uint16_t gyro_odr; +#if defined(CONFIG_LSM9DS1_ENABLE_TEMP) + int16_t temp_sample; +#endif +}; + +#endif /* ZEPHYR_DRIVERS_SENSOR_LSM9DS1_LSM9DS1_H_ */ diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index dda3eeb008d..8fb151efdf6 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -1067,3 +1067,8 @@ test_i2c_sht21@90 { compatible = "sensirion,sht21"; reg = <0x90>; }; + +test_i2c_lsm9ds1: lsm9ds1@91 { + compatible = "st,lsm9ds1"; + reg = <0x8e>; +};