drivers/sensor: lsm6dsvxxx: add ism6hg256x support

Add support to ism6hg256x sensor variant of LSM6DSVXXX driver.

More information:
https://www.st.com/resource/en/datasheet/ism6hg256x.pdf

Signed-off-by: Armando Visconti <armando.visconti@st.com>
This commit is contained in:
Armando Visconti
2025-10-23 16:37:52 +02:00
committed by Maureen Helm
parent 310457448a
commit 56b85ea61a
13 changed files with 1063 additions and 5 deletions

View File

@@ -13,5 +13,6 @@ zephyr_library_sources_ifdef(CONFIG_LSM6DSVXXX_TRIGGER lsm6dsvxxx_trigger.c)
zephyr_library_sources_ifdef(CONFIG_DT_HAS_ST_LSM6DSV320X_ENABLED lsm6dsv320x.c)
zephyr_library_sources_ifdef(CONFIG_DT_HAS_ST_LSM6DSV80X_ENABLED lsm6dsv80x.c)
zephyr_library_sources_ifdef(CONFIG_DT_HAS_ST_ISM6HG256X_ENABLED ism6hg256x.c)
zephyr_library_include_directories(../stmemsc)

View File

@@ -6,17 +6,22 @@
menuconfig LSM6DSVXXX
bool "LSM6DSVXXX IMU sensor"
default y
depends on DT_HAS_ST_LSM6DSV320X_ENABLED || DT_HAS_ST_LSM6DSV80X_ENABLED
depends on DT_HAS_ST_LSM6DSV320X_ENABLED || DT_HAS_ST_LSM6DSV80X_ENABLED ||\
DT_HAS_ST_ISM6HG256X_ENABLED
depends on ZEPHYR_HAL_ST_MODULE
select I2C if $(dt_compat_on_bus,$(DT_COMPAT_ST_LSM6DSV320X),i2c) ||\
$(dt_compat_on_bus,$(DT_COMPAT_ST_LSM6DSV80X),i2c)
$(dt_compat_on_bus,$(DT_COMPAT_ST_LSM6DSV80X),i2c) ||\
$(dt_compat_on_bus,$(DT_COMPAT_ST_ISM6HG256X),i2c)
select I3C if $(dt_compat_on_bus,$(DT_COMPAT_ST_LSM6DSV320X),i3c) ||\
$(dt_compat_on_bus,$(DT_COMPAT_ST_LSM6DSV80X),i3c)
$(dt_compat_on_bus,$(DT_COMPAT_ST_LSM6DSV80X),i3c) ||\
$(dt_compat_on_bus,$(DT_COMPAT_ST_ISM6HG256X),i3c)
select SPI if $(dt_compat_on_bus,$(DT_COMPAT_ST_LSM6DSV320X),spi) ||\
$(dt_compat_on_bus,$(DT_COMPAT_ST_LSM6DSV80X),spi)
$(dt_compat_on_bus,$(DT_COMPAT_ST_LSM6DSV80X),spi) ||\
$(dt_compat_on_bus,$(DT_COMPAT_ST_ISM6HG256X),spi)
select HAS_STMEMSC
select USE_STDC_LSM6DSV320X if DT_HAS_ST_LSM6DSV320X_ENABLED
select USE_STDC_LSM6DSV80X if DT_HAS_ST_LSM6DSV80X_ENABLED
select USE_STDC_ISM6HG256X if DT_HAS_ST_ISM6HG256X_ENABLED
help
Enable driver for LSM6DSVXXX family IMU sensors.

View File

@@ -0,0 +1,843 @@
/* ST Microelectronics LSM6DSVXXX family IMU sensor
*
* Copyright (c) 2025 STMicroelectronics
*
* SPDX-License-Identifier: Apache-2.0
*
* Datasheet:
* https://www.st.com/resource/en/datasheet/ism6hg256x.pdf
*/
#include "ism6hg256x.h"
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(LSM6DSVXXX, CONFIG_SENSOR_LOG_LEVEL);
static bool ism6hg256x_is_std_fs(uint8_t fs)
{
return (fs < 4); /* 2g/4g/8g/16g */
}
static bool ism6hg256x_is_hg_fs(uint8_t fs)
{
return (fs >= 4 && fs <= 7); /* 32g/64g/128g/256g */
}
/*
* XL configuration
*/
static uint16_t ism6hg256x_accel_gain_ug(uint8_t fs)
{
return (61 * (1 << fs));
}
/* The first nibble of fs tells if it is High-G or not */
static int ism6hg256x_accel_range_to_fs_val(const struct device *dev, int32_t range, uint8_t *fs)
{
switch (range) {
case ISM6HG256X_DT_FS_2G:
*fs = 0;
break;
case ISM6HG256X_DT_FS_4G:
*fs = 1;
break;
case ISM6HG256X_DT_FS_8G:
*fs = 2;
break;
case ISM6HG256X_DT_FS_16G:
*fs = 3;
break;
case ISM6HG256X_DT_FS_32G:
*fs = 4;
break;
case ISM6HG256X_DT_FS_64G:
*fs = 5;
break;
case ISM6HG256X_DT_FS_128G:
*fs = 6;
break;
case ISM6HG256X_DT_FS_256G:
*fs = 7;
break;
default:
return -EINVAL;
}
return 0;
}
static int ism6hg256x_accel_set_fs_raw(const struct device *dev, uint8_t fs)
{
const struct lsm6dsvxxx_config *cfg = dev->config;
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
struct lsm6dsvxxx_data *data = dev->data;
if (ism6hg256x_is_std_fs(fs)) { /* 2g/4g/8g/16g */
ism6hg256x_xl_full_scale_t val = fs;
if (ism6hg256x_xl_full_scale_set(ctx, val) < 0) {
return -EIO;
}
data->out_xl = ISM6HG256X_OUTX_L_A;
} else if (ism6hg256x_is_hg_fs(fs)) { /* 32g/64g/128g/256g */
ism6hg256x_hg_xl_full_scale_t val = (fs - 4);
if (ism6hg256x_hg_xl_full_scale_set(ctx, val) < 0) {
return -EIO;
}
data->out_xl = ISM6HG256X_UI_OUTX_L_A_OIS_HG;
} else {
return -EINVAL;
}
data->accel_fs = fs;
data->acc_gain = ism6hg256x_accel_gain_ug(fs);
return 0;
}
static int ism6hg256x_accel_set_fs(const struct device *dev, int32_t range)
{
uint8_t fs;
int ret;
ret = ism6hg256x_accel_range_to_fs_val(dev, range, &fs);
if (ret < 0) {
return ret;
}
ret = ism6hg256x_accel_set_fs_raw(dev, fs);
if (ret < 0) {
return ret;
}
return 0;
}
static int ism6hg256x_accel_set_odr_raw(const struct device *dev, uint8_t odr)
{
const struct lsm6dsvxxx_config *cfg = dev->config;
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
struct lsm6dsvxxx_data *data = dev->data;
if (cfg->accel_hg_odr != ISM6HG256X_HG_XL_ODR_OFF) {
if (ism6hg256x_hg_xl_data_rate_set(ctx, cfg->accel_hg_odr, 1) < 0) {
return -EIO;
}
} else {
if (ism6hg256x_xl_data_rate_set(ctx, odr) < 0) {
return -EIO;
}
}
data->accel_freq = odr;
return 0;
}
/*
* values taken from ism6hg256x_data_rate_t in hal/st module. The mode/accuracy
* should be selected through accel-odr property in DT
*/
static const float ism6hg256x_odr_map[3][13] = {
/* High Accuracy off */
{0.0f, 1.875f, 7.5f, 15.0f, 30.0f, 60.0f, 120.0f, 240.0f, 480.0f, 960.0f, 1920.0f, 3840.0f,
7680.0f},
/* High Accuracy 1 */
{0.0f, 1.875f, 7.5f, 15.625f, 31.25f, 62.5f, 125.0f, 250.0f, 500.0f, 1000.0f, 2000.0f,
4000.0f, 8000.0f},
/* High Accuracy 2 */
{0.0f, 1.875f, 7.5f, 12.5f, 25.0f, 50.0f, 100.0f, 200.0f, 400.0f, 800.0f, 1600.0f, 3200.0f,
6400.0f},
};
static uint8_t ism6hg256x_freq_to_odr_val(const struct device *dev, int32_t freq)
{
const struct lsm6dsvxxx_config *cfg = dev->config;
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
ism6hg256x_data_rate_t odr;
int8_t mode;
size_t i;
if (ism6hg256x_xl_data_rate_get(ctx, &odr) < 0) {
return -EINVAL;
}
mode = (odr >> 4) & 0xf;
for (i = 0; i < ARRAY_SIZE(ism6hg256x_odr_map[mode]); i++) {
if (freq <= ism6hg256x_odr_map[mode][i]) {
LOG_DBG("mode: %d - odr: %d", mode, i);
return i | (mode << 4);
}
}
return 0xFF;
}
static int ism6hg256x_accel_set_odr(const struct device *dev, int32_t freq)
{
uint8_t odr;
odr = ism6hg256x_freq_to_odr_val(dev, freq);
if (odr == 0xFF) {
return -EINVAL;
}
if (ism6hg256x_accel_set_odr_raw(dev, odr) < 0) {
LOG_DBG("failed to set accelerometer sampling rate");
return -EIO;
}
return 0;
}
static int32_t ism6hg256x_accel_set_mode(const struct device *dev, int32_t mode)
{
const struct lsm6dsvxxx_config *cfg = dev->config;
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
switch (mode) {
case 0: /* High Performance */
mode = ISM6HG256X_XL_HIGH_PERFORMANCE_MD;
break;
case 1: /* High Accuracy */
mode = ISM6HG256X_XL_HIGH_ACCURACY_ODR_MD;
break;
case 3: /* ODR triggered */
mode = ISM6HG256X_XL_ODR_TRIGGERED_MD;
break;
case 4: /* Low Power 2 */
mode = ISM6HG256X_XL_LOW_POWER_2_AVG_MD;
break;
case 5: /* Low Power 4 */
mode = ISM6HG256X_XL_LOW_POWER_4_AVG_MD;
break;
case 6: /* Low Power 8 */
mode = ISM6HG256X_XL_LOW_POWER_8_AVG_MD;
break;
case 7: /* Normal */
mode = ISM6HG256X_XL_NORMAL_MD;
break;
default:
return -EIO;
}
return ism6hg256x_xl_mode_set(ctx, mode);
}
static int32_t ism6hg256x_accel_get_fs(const struct device *dev, int32_t *range)
{
return -ENOTSUP;
}
static int32_t ism6hg256x_accel_get_odr(const struct device *dev, int32_t *freq)
{
return -ENOTSUP;
}
static int32_t ism6hg256x_accel_get_mode(const struct device *dev, int32_t *mode)
{
const struct lsm6dsvxxx_config *cfg = dev->config;
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
ism6hg256x_xl_mode_t md;
ism6hg256x_xl_mode_get(ctx, &md);
switch (md) {
case ISM6HG256X_XL_HIGH_PERFORMANCE_MD:
*mode = 0;
break;
case ISM6HG256X_XL_HIGH_ACCURACY_ODR_MD:
*mode = 1;
break;
case ISM6HG256X_XL_ODR_TRIGGERED_MD:
*mode = 3;
break;
case ISM6HG256X_XL_LOW_POWER_2_AVG_MD:
*mode = 4;
break;
case ISM6HG256X_XL_LOW_POWER_4_AVG_MD:
*mode = 5;
break;
case ISM6HG256X_XL_LOW_POWER_8_AVG_MD:
*mode = 6;
break;
case ISM6HG256X_XL_NORMAL_MD:
*mode = 7;
break;
default:
return -EIO;
}
return 0;
}
/*
* GY configuration
*/
static int ism6hg256x_gyro_range_to_fs_val(const struct device *dev, int32_t range, uint8_t *fs)
{
switch (range) {
case 0:
*fs = 0;
break;
case 250:
*fs = ISM6HG256X_DT_FS_250DPS;
break;
case 500:
*fs = ISM6HG256X_DT_FS_500DPS;
break;
case 1000:
*fs = ISM6HG256X_DT_FS_1000DPS;
break;
case 2000:
*fs = ISM6HG256X_DT_FS_2000DPS;
break;
case 4000:
*fs = ISM6HG256X_DT_FS_4000DPS;
break;
default:
return -EINVAL;
}
return 0;
}
static uint32_t ism6hg256x_gyro_gain_udps(uint8_t fs)
{
return (4375 * (1 << fs));
}
static int ism6hg256x_gyro_set_fs_raw(const struct device *dev, uint8_t fs)
{
const struct lsm6dsvxxx_config *cfg = dev->config;
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
struct lsm6dsvxxx_data *data = dev->data;
if (fs == 0) {
/* skip power-up value */
return 0;
}
if (ism6hg256x_gy_full_scale_set(ctx, fs) < 0) {
return -EIO;
}
data->gyro_fs = fs;
data->gyro_gain = ism6hg256x_gyro_gain_udps(fs);
return 0;
}
static int ism6hg256x_gyro_set_fs(const struct device *dev, int32_t range)
{
uint8_t fs;
int ret;
ret = ism6hg256x_gyro_range_to_fs_val(dev, range, &fs);
if (ret < 0) {
return ret;
}
if (ism6hg256x_gyro_set_fs_raw(dev, fs) < 0) {
return -EIO;
}
return 0;
}
static int ism6hg256x_gyro_set_odr_raw(const struct device *dev, uint8_t odr)
{
const struct lsm6dsvxxx_config *cfg = dev->config;
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
struct lsm6dsvxxx_data *data = dev->data;
if (ism6hg256x_gy_data_rate_set(ctx, odr) < 0) {
return -EIO;
}
data->gyro_freq = odr;
return 0;
}
static int ism6hg256x_gyro_set_odr(const struct device *dev, int32_t freq)
{
uint8_t odr;
odr = ism6hg256x_freq_to_odr_val(dev, freq);
if (odr == 0xFF) {
return -EINVAL;
}
if (ism6hg256x_gyro_set_odr_raw(dev, odr) < 0) {
LOG_DBG("failed to set gyroscope sampling rate");
return -EIO;
}
return 0;
}
static int32_t ism6hg256x_gyro_set_mode(const struct device *dev, int32_t mode)
{
const struct lsm6dsvxxx_config *cfg = dev->config;
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
switch (mode) {
case 0: /* High Performance */
mode = ISM6HG256X_GY_HIGH_PERFORMANCE_MD;
break;
case 1: /* High Accuracy */
mode = ISM6HG256X_GY_HIGH_ACCURACY_ODR_MD;
break;
case 4: /* Sleep */
mode = ISM6HG256X_GY_SLEEP_MD;
break;
case 5: /* Low Power */
mode = ISM6HG256X_GY_LOW_POWER_MD;
break;
default:
return -EIO;
}
return ism6hg256x_gy_mode_set(ctx, mode);
}
static int32_t ism6hg256x_gyro_get_fs(const struct device *dev, int32_t *range)
{
return -ENOTSUP;
}
static int32_t ism6hg256x_gyro_get_odr(const struct device *dev, int32_t *freq)
{
return -ENOTSUP;
}
static int32_t ism6hg256x_gyro_get_mode(const struct device *dev, int32_t *mode)
{
const struct lsm6dsvxxx_config *cfg = dev->config;
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
ism6hg256x_gy_mode_t md;
ism6hg256x_gy_mode_get(ctx, &md);
switch (md) {
case ISM6HG256X_GY_HIGH_PERFORMANCE_MD:
*mode = 0;
break;
case ISM6HG256X_GY_HIGH_ACCURACY_ODR_MD:
*mode = 1;
break;
case ISM6HG256X_GY_SLEEP_MD:
*mode = 4;
break;
case ISM6HG256X_GY_LOW_POWER_MD:
*mode = 5;
break;
default:
return -EIO;
}
return 0;
}
#if defined(CONFIG_LSM6DSVXXX_TRIGGER)
int32_t ism6hg256x_drdy_mode_set(const struct device *dev)
{
const struct lsm6dsvxxx_config *config = dev->config;
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&config->ctx;
/* enable drdy on int1/int2 in pulse mode */
ism6hg256x_data_ready_mode_t drdy =
(config->drdy_pulsed) ? ISM6HG256X_DRDY_PULSED : ISM6HG256X_DRDY_LATCHED;
if (ism6hg256x_data_ready_mode_set(ctx, drdy)) {
return -EIO;
}
return 0;
}
#endif /* CONFIG_LSM6DSVXXX_TRIGGER */
/* init routine */
static int ism6hg256x_init_chip(const struct device *dev)
{
const struct lsm6dsvxxx_config *cfg = dev->config;
struct lsm6dsvxxx_data *data = dev->data;
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
uint8_t chip_id;
uint8_t odr, fs;
#if LSM6DSVXXX_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
if (cfg->i3c.bus != NULL) {
/*
* Need to grab the pointer to the I3C device descriptor
* before we can talk to the sensor.
*/
lsm6dsvxxx->i3c_dev = i3c_device_find(cfg->i3c.bus, &cfg->i3c.dev_id);
if (lsm6dsvxxx->i3c_dev == NULL) {
LOG_ERR("Cannot find I3C device descriptor");
return -ENODEV;
}
}
#endif
/* All registers except 0x01 are different between banks, including the WHO_AM_I
* register and the register used for a SW reset. If the lsm6dsvxxx wasn't on the user
* bank when it reset, then both the chip id check and the sw reset will fail unless we
* set the bank now.
*/
if (ism6hg256x_mem_bank_set(ctx, ISM6HG256X_MAIN_MEM_BANK) < 0) {
LOG_DBG("Failed to set user bank");
return -EIO;
}
if (ism6hg256x_device_id_get(ctx, &chip_id) < 0) {
LOG_DBG("Failed reading chip id");
return -EIO;
}
LOG_INF("chip id 0x%x", chip_id);
if (chip_id != ISM6HG256X_ID) {
LOG_DBG("Invalid chip id 0x%x", chip_id);
return -EIO;
}
/* Resetting the whole device while using I3C will also reset the DA, therefore perform
* only a software reset if the bus is I3C. It should be assumed that the device was
* already fully reset by the I3C CCC RSTACT (whole chip) done as apart of the I3C Bus
* initialization.
*/
if (ON_I3C_BUS(cfg)) {
/* Restore default configuration */
ism6hg256x_reboot(ctx);
/* wait 150us as reported in AN5763 */
k_sleep(K_USEC(150));
} else {
/* reset device (sw_por) */
if (ism6hg256x_sw_por(ctx) < 0) {
return -EIO;
}
/* wait 30ms as reported in AN5763 */
k_sleep(K_MSEC(30));
}
data->out_xl = ISM6HG256X_OUTX_L_A;
data->out_tp = ISM6HG256X_OUT_TEMP_L;
fs = cfg->accel_range;
LOG_DBG("accel range is %d", fs);
if (ism6hg256x_accel_set_fs_raw(dev, fs) < 0) {
LOG_ERR("failed to set accelerometer range %d", fs);
return -EIO;
}
odr = cfg->accel_odr;
LOG_DBG("accel odr is %d", odr);
if (ism6hg256x_accel_set_odr_raw(dev, odr) < 0) {
LOG_ERR("failed to set accelerometer odr %d", odr);
return -EIO;
}
fs = cfg->gyro_range;
LOG_DBG("gyro range is %d", fs);
if (ism6hg256x_gyro_set_fs_raw(dev, fs) < 0) {
LOG_ERR("failed to set gyroscope range %d", fs);
return -EIO;
}
odr = cfg->gyro_odr;
LOG_DBG("gyro odr is %d", odr);
if (ism6hg256x_gyro_set_odr_raw(dev, odr) < 0) {
LOG_ERR("failed to set gyroscope odr %d", odr);
return -EIO;
}
#if LSM6DSVXXX_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
if (IS_ENABLED(CONFIG_LSM6DSVXXX_STREAM) && (ON_I3C_BUS(cfg))) {
/*
* Set MRL to the Max Size of the FIFO so the entire FIFO can be read
* out at once
*/
struct i3c_ccc_mrl setmrl = {
.len = 0x0700,
.ibi_len = lsm6dsvxxx->i3c_dev->data_length.max_ibi,
};
if (i3c_ccc_do_setmrl(lsm6dsvxxx->i3c_dev, &setmrl) < 0) {
LOG_ERR("failed to set mrl");
return -EIO;
}
}
#endif
if (ism6hg256x_block_data_update_set(ctx, 1) < 0) {
LOG_DBG("failed to set BDU mode");
return -EIO;
}
return 0;
}
#if defined(CONFIG_PM_DEVICE)
static int ism6hg256x_pm_action(const struct device *dev, enum pm_device_action action)
{
struct lsm6dsvxxx_data *data = dev->data;
const struct lsm6dsvxxx_config *cfg = dev->config;
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
int ret = 0;
LOG_DBG("PM action: %d", (int)action);
switch (action) {
case PM_DEVICE_ACTION_RESUME:
if (ism6hg256x_xl_data_rate_set(ctx, data->accel_freq) < 0) {
LOG_ERR("failed to set accelerometer odr %d", (int)data->accel_freq);
ret = -EIO;
}
if (ism6hg256x_gy_data_rate_set(ctx, data->gyro_freq) < 0) {
LOG_ERR("failed to set gyroscope odr %d", (int)data->gyro_freq);
ret = -EIO;
}
break;
case PM_DEVICE_ACTION_SUSPEND:
if (ism6hg256x_xl_data_rate_set(ctx, LSM6DSVXXX_DT_ODR_OFF) < 0) {
LOG_ERR("failed to disable accelerometer");
ret = -EIO;
}
if (ism6hg256x_gy_data_rate_set(ctx, LSM6DSVXXX_DT_ODR_OFF) < 0) {
LOG_ERR("failed to disable gyroscope");
ret = -EIO;
}
break;
default:
ret = -ENOTSUP;
break;
}
return ret;
}
#endif /* CONFIG_PM_DEVICE */
#if defined(CONFIG_LSM6DSVXXX_STREAM)
static void ism6hg256x_config_fifo(const struct device *dev, struct trigger_config trig_cfg)
{
struct lsm6dsvxxx_data *data = dev->data;
const struct lsm6dsvxxx_config *config = dev->config;
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&config->ctx;
uint8_t fifo_wtm = 0;
ism6hg256x_pin_int_route_t pin_int = {0};
ism6hg256x_fifo_xl_batch_t xl_batch = LSM6DSVXXX_DT_XL_NOT_BATCHED;
ism6hg256x_fifo_gy_batch_t gy_batch = LSM6DSVXXX_DT_GY_NOT_BATCHED;
ism6hg256x_fifo_temp_batch_t temp_batch = LSM6DSVXXX_DT_TEMP_NOT_BATCHED;
ism6hg256x_fifo_mode_t fifo_mode = ISM6HG256X_BYPASS_MODE;
ism6hg256x_sflp_data_rate_t sflp_odr = ISM6HG256X_SFLP_120Hz;
ism6hg256x_fifo_sflp_raw_t sflp_fifo = {0};
ism6hg256x_sflp_gbias_t gbias;
uint8_t xl_hg_batch = 0;
/* disable FIFO as first thing */
ism6hg256x_fifo_mode_set(ctx, ISM6HG256X_BYPASS_MODE);
pin_int.fifo_th = PROPERTY_DISABLE;
pin_int.fifo_full = PROPERTY_DISABLE;
if (trig_cfg.int_fifo_th || trig_cfg.int_fifo_full) {
pin_int.fifo_th = (trig_cfg.int_fifo_th) ? PROPERTY_ENABLE : PROPERTY_DISABLE;
pin_int.fifo_full = (trig_cfg.int_fifo_full) ? PROPERTY_ENABLE : PROPERTY_DISABLE;
xl_batch = config->accel_batch;
gy_batch = config->gyro_batch;
temp_batch = config->temp_batch;
xl_hg_batch = (ism6hg256x_is_hg_fs(config->accel_range)) ? 1 : 0;
fifo_mode = ISM6HG256X_STREAM_MODE;
fifo_wtm = config->fifo_wtm;
if (config->sflp_fifo_en & LSM6DSVXXX_DT_SFLP_FIFO_GAME_ROTATION) {
sflp_fifo.game_rotation = 1;
}
if (config->sflp_fifo_en & LSM6DSVXXX_DT_SFLP_FIFO_GRAVITY) {
sflp_fifo.gravity = 1;
}
if (config->sflp_fifo_en & LSM6DSVXXX_DT_SFLP_FIFO_GBIAS) {
sflp_fifo.gbias = 1;
}
sflp_odr = config->sflp_odr;
}
/*
* Set FIFO watermark (number of unread sensor data TAG + 6 bytes
* stored in FIFO) to FIFO_WATERMARK samples
*/
ism6hg256x_fifo_watermark_set(ctx, config->fifo_wtm);
/* Turn on/off FIFO */
ism6hg256x_fifo_mode_set(ctx, fifo_mode);
/* Set FIFO batch rates */
ism6hg256x_fifo_xl_batch_set(ctx, xl_batch);
data->accel_batch_odr = xl_batch;
ism6hg256x_fifo_hg_xl_batch_set(ctx, xl_hg_batch);
ism6hg256x_fifo_gy_batch_set(ctx, gy_batch);
data->gyro_batch_odr = gy_batch;
#if defined(CONFIG_LSM6DSVXXX_ENABLE_TEMP)
ism6hg256x_fifo_temp_batch_set(ctx, temp_batch);
data->temp_batch_odr = temp_batch;
#endif
ism6hg256x_sflp_data_rate_set(ctx, sflp_odr);
data->sflp_batch_odr = sflp_odr;
ism6hg256x_fifo_sflp_batch_set(ctx, sflp_fifo);
ism6hg256x_sflp_game_rotation_set(ctx, PROPERTY_ENABLE);
/*
* Temporarly set Accel and gyro odr same as sensor fusion LP in order to
* make the SFLP gbias setting effective. Then restore it to saved values.
*/
switch (sflp_odr) {
case LSM6DSVXXX_DT_SFLP_ODR_AT_480Hz:
ism6hg256x_accel_set_odr_raw(dev, LSM6DSVXXX_DT_ODR_AT_480Hz);
ism6hg256x_gyro_set_odr_raw(dev, LSM6DSVXXX_DT_ODR_AT_480Hz);
break;
case LSM6DSVXXX_DT_SFLP_ODR_AT_240Hz:
ism6hg256x_accel_set_odr_raw(dev, LSM6DSVXXX_DT_ODR_AT_240Hz);
ism6hg256x_gyro_set_odr_raw(dev, LSM6DSVXXX_DT_ODR_AT_240Hz);
break;
case LSM6DSVXXX_DT_SFLP_ODR_AT_120Hz:
ism6hg256x_accel_set_odr_raw(dev, LSM6DSVXXX_DT_ODR_AT_120Hz);
ism6hg256x_gyro_set_odr_raw(dev, LSM6DSVXXX_DT_ODR_AT_120Hz);
break;
case LSM6DSVXXX_DT_SFLP_ODR_AT_60Hz:
ism6hg256x_accel_set_odr_raw(dev, LSM6DSVXXX_DT_ODR_AT_60Hz);
ism6hg256x_gyro_set_odr_raw(dev, LSM6DSVXXX_DT_ODR_AT_60Hz);
break;
case LSM6DSVXXX_DT_SFLP_ODR_AT_30Hz:
ism6hg256x_accel_set_odr_raw(dev, LSM6DSVXXX_DT_ODR_AT_30Hz);
ism6hg256x_gyro_set_odr_raw(dev, LSM6DSVXXX_DT_ODR_AT_30Hz);
break;
case LSM6DSVXXX_DT_SFLP_ODR_AT_15Hz:
default:
ism6hg256x_accel_set_odr_raw(dev, LSM6DSVXXX_DT_ODR_AT_15Hz);
ism6hg256x_gyro_set_odr_raw(dev, LSM6DSVXXX_DT_ODR_AT_15Hz);
break;
}
/* set sflp gbias */
gbias.gbias_x = (float)data->gbias_x_udps / 1000000;
gbias.gbias_y = (float)data->gbias_y_udps / 1000000;
gbias.gbias_z = (float)data->gbias_z_udps / 1000000;
ism6hg256x_sflp_game_gbias_set(ctx, &gbias);
/* restore accel/gyro odr to saved values */
ism6hg256x_accel_set_odr_raw(dev, data->accel_freq);
ism6hg256x_gyro_set_odr_raw(dev, data->gyro_freq);
/* Set pin interrupt (fifo_th could be on or off) */
if ((config->drdy_pin == 1) || (ON_I3C_BUS(config) && (!I3C_INT_PIN(config)))) {
ism6hg256x_pin_int1_route_set(ctx, &pin_int);
} else {
ism6hg256x_pin_int2_route_set(ctx, &pin_int);
}
}
static void ism6hg256x_config_drdy(const struct device *dev, struct trigger_config trig_cfg)
{
const struct lsm6dsvxxx_config *config = dev->config;
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&config->ctx;
ism6hg256x_pin_int_route_t pin_int = {0};
pin_int.drdy_xl = (trig_cfg.int_drdy) ? PROPERTY_ENABLE : PROPERTY_DISABLE;
/* Set pin interrupt (fifo_th could be on or off) */
if ((config->drdy_pin == 1) || (ON_I3C_BUS(config) && (!I3C_INT_PIN(config)))) {
ism6hg256x_pin_int1_route_set(ctx, &pin_int);
} else {
ism6hg256x_pin_int2_route_set(ctx, &pin_int);
}
}
#endif /* CONFIG_LSM6DSVXXX_STREAM */
const struct lsm6dsvxxx_chip_api st_ism6hg256x_chip_api = {
.init_chip = ism6hg256x_init_chip,
#if defined(CONFIG_LSM6DSVXXX_TRIGGER)
.drdy_mode_set = ism6hg256x_drdy_mode_set,
#endif /* CONFIG_LSM6DSVXXX_TRIGGER */
#if defined(CONFIG_PM_DEVICE)
.pm_action = ism6hg256x_pm_action,
#endif /* CONFIG_PM_DEVICE */
.accel_fs_set = ism6hg256x_accel_set_fs,
.accel_odr_set = ism6hg256x_accel_set_odr,
.accel_mode_set = ism6hg256x_accel_set_mode,
.accel_fs_get = ism6hg256x_accel_get_fs,
.accel_odr_get = ism6hg256x_accel_get_odr,
.accel_mode_get = ism6hg256x_accel_get_mode,
.gyro_fs_set = ism6hg256x_gyro_set_fs,
.gyro_odr_set = ism6hg256x_gyro_set_odr,
.gyro_mode_set = ism6hg256x_gyro_set_mode,
.gyro_fs_get = ism6hg256x_gyro_get_fs,
.gyro_odr_get = ism6hg256x_gyro_get_odr,
.gyro_mode_get = ism6hg256x_gyro_get_mode,
#if defined(CONFIG_LSM6DSVXXX_STREAM)
.config_fifo = ism6hg256x_config_fifo,
.config_drdy = ism6hg256x_config_drdy,
.from_f16_to_f32 = ism6hg256x_from_f16_to_f32,
.from_sflp_to_mg = ism6hg256x_from_sflp_to_mg,
#endif /* CONFIG_LSM6DSVXXX_STREAM */
};
/* bit shift for Accelerometer for a given range value */
const int8_t st_ism6hg256x_accel_bit_shift[] = {
5, /* FS_2G */
6, /* FS_4G */
7, /* FS_8G */
8, /* FS_16G */
9, /* FS_32G */
10, /* FS_64G */
11, /* FS_128G */
12, /* FS_256G */
};
/*
* Accelerometer scaling factors table for a given range value
* GAIN_UNIT_XL is expressed in ug/LSB.
*/
const int32_t st_ism6hg256x_accel_scaler[] = {
SENSOR_SCALE_UG_TO_UMS2(61), /* FS_2G */
SENSOR_SCALE_UG_TO_UMS2(122), /* FS_4G */
SENSOR_SCALE_UG_TO_UMS2(244), /* FS_8G */
SENSOR_SCALE_UG_TO_UMS2(488), /* FS_16G */
SENSOR_SCALE_UG_TO_UMS2(976), /* FS_32G */
SENSOR_SCALE_UG_TO_UMS2(1952), /* FS_64G */
SENSOR_SCALE_UG_TO_UMS2(2904), /* FS_128G */
SENSOR_SCALE_UG_TO_UMS2(7808), /* FS_256G */
};

View File

@@ -0,0 +1,25 @@
/* ST Microelectronics LSM6DSVXXX family IMU sensor
*
* Copyright (c) 2025 STMicroelectronics
*
* SPDX-License-Identifier: Apache-2.0
*
* Datasheet:
* https://www.st.com/resource/en/datasheet/ism6hg256x.pdf
*/
#ifndef ZEPHYR_DRIVERS_SENSOR_ISM6HG256X_H_
#define ZEPHYR_DRIVERS_SENSOR_ISM6HG256X_H_
#include <stdint.h>
#include <stmemsc.h>
#include "lsm6dsvxxx.h"
#include "ism6hg256x_reg.h"
#include <zephyr/drivers/sensor.h>
extern const struct lsm6dsvxxx_chip_api st_ism6hg256x_chip_api;
extern const int8_t st_ism6hg256x_accel_bit_shift[];
extern const int32_t st_ism6hg256x_accel_scaler[];
#endif /* ZEPHYR_DRIVERS_SENSOR_ISM6HG256X_H_ */

View File

@@ -27,6 +27,10 @@
#include "lsm6dsv80x.h"
#endif
#if DT_HAS_COMPAT_STATUS_OKAY(st_ism6hg256x)
#include "ism6hg256x.h"
#endif
LOG_MODULE_REGISTER(LSM6DSVXXX, CONFIG_SENSOR_LOG_LEVEL);
static int lsm6dsvxxx_accel_config(const struct device *dev,
@@ -516,3 +520,7 @@ DT_INST_FOREACH_STATUS_OKAY_VARGS(LSM6DSVXXX_DEFINE, DT_DRV_COMPAT)
#define DT_DRV_COMPAT st_lsm6dsv80x
DT_INST_FOREACH_STATUS_OKAY_VARGS(LSM6DSVXXX_DEFINE, DT_DRV_COMPAT)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT st_ism6hg256x
DT_INST_FOREACH_STATUS_OKAY_VARGS(LSM6DSVXXX_DEFINE, DT_DRV_COMPAT)
#undef DT_DRV_COMPAT

View File

@@ -25,7 +25,8 @@
#define LSM6DSVXXX_ANY_INST_ON_BUS_STATUS_OKAY(bus) \
(DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lsm6dsv320x, bus) ||\
DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lsm6dsv80x, bus))
DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_lsm6dsv80x, bus) ||\
DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(st_ism6hg256x, bus))
#if DT_HAS_COMPAT_STATUS_OKAY(st_lsm6dsv320x)
#include "lsm6dsv320x_reg.h"
@@ -37,6 +38,11 @@
#include <zephyr/dt-bindings/sensor/lsm6dsv80x.h>
#endif
#if DT_HAS_COMPAT_STATUS_OKAY(st_ism6hg256x)
#include "ism6hg256x_reg.h"
#include <zephyr/dt-bindings/sensor/ism6hg256x.h>
#endif
#if LSM6DSVXXX_ANY_INST_ON_BUS_STATUS_OKAY(spi)
#include <zephyr/drivers/spi.h>
#endif /* LSM6DSVXXX_ANY_INST_ON_BUS_STATUS_OKAY(spi) */

View File

@@ -0,0 +1,75 @@
# Copyright (c) 2025 STMicroelectronics
# SPDX-License-Identifier: Apache-2.0
description: |
When setting the accel-range, accel-odr, gyro-range, gyro-odr properties in
a .dts or .dtsi file you may include ism6hg256x.h and use the macros
defined there.
Example:
#include <zephyr/dt-bindings/sensor/ism6hg256x.h>
ism6hg256x: ism6hg256x@0 {
...
accel-range = <ISM6HG256X_DT_FS_8G>;
accel-odr = <ISM6HG256XDT_ODR_AT_60Hz>;
gyro-range = <ISM6HG256X_DT_FS_4000DPS>;
gyro-odr = <ISM6HG256XDT_ODR_AT_60Hz>;
};
include: st,lsm6dsvxxx-common.yaml
properties:
accel-hg-odr:
type: int
default: 0x0
description: |
Specify the default accelerometer High-g output data rate expressed in samples per
second (Hz).
The values are taken in accordance to ism6hg256x_hg_xl_data_rate_t enumerative in hal/st
module. Please note that this values will not change the operating mode, which will remain
High Performance (device default)
Default is power-up configuration.
- 0x0 # ISM6HG256X_HG_XL_ODR_OFF
- 0x3 # ISM6HG256X_HG_XL_ODR_AT_480Hz
- 0x4 # ISM6HG256X_HG_XL_ODR_AT_960Hz
- 0x5 # ISM6HG256X_HG_XL_ODR_AT_1920Hz
- 0x6 # ISM6HG256X_HG_XL_ODR_AT_3840Hz
- 0x7 # ISM6HG256X_HG_XL_ODR_AT_7680Hz
enum: [0x0, 0x3, 0x4, 0x5, 0x6, 0x7]
accel-range:
type: int
default: 2
description: |
Range in g. Default is power-up configuration.
Ranges from 32g and above requires the High-g sensor to be turned on (see accel-hg-odr).
- 2 # ISM6HG256X_DT_FS_2G (0.061 mg/LSB)
- 4 # ISM6HG256X_DT_FS_4G (0.122 mg/LSB)
- 8 # ISM6HG256X_DT_FS_8G (0.244 mg/LSB)
- 16 # ISM6HG256X_DT_FS_16G (0.488 mg/LSB)
- 32 # ISM6HG256X_DT_FS_32G (0.976 mg/LSB)
- 64 # ISM6HG256X_DT_FS_64G (1.952 mg/LSB)
- 128 # ISM6HG256X_DT_FS_128G (3.904 mg/LSB)
- 256 # ISM6HG256X_DT_FS_256G (7.808 mg/LSB)
enum: [2, 4, 8, 16, 32, 64, 128, 256]
gyro-range:
type: int
default: 0
description: |
Range in dps. Default is power-up configuration.
- 0x0 # power-up configuration
- 0x1 # ISM6HG256X_DT_FS_250DPS (8.75 mdps/LSB)
- 0x2 # ISM6HG256X_DT_FS_500DPS (17.50 mdps/LSB)
- 0x3 # ISM6HG256X_DT_FS_1000DPS (35 mdps/LSB)
- 0x4 # ISM6HG256X_DT_FS_2000DPS (70 mdps/LSB)
- 0x5 # ISM6HG256X_DT_FS_4000DPS (140 mdps/LSB)
enum: [0x0, 0x1, 0x2, 0x3, 0x4, 0x5]

View File

@@ -0,0 +1,10 @@
# Copyright (c) 2025 STMicroelectronics
# SPDX-License-Identifier: Apache-2.0
description: |
STMicroelectronics ISM6HG256X 6-axis IMU (Inertial Measurement Unit) sensor
accessed through I2C bus
compatible: "st,ism6hg256x"
include: ["i2c-device.yaml", "st,ism6hg256x-common.yaml"]

View File

@@ -0,0 +1,24 @@
# Copyright (c) 2025 STMicroelectronics
# SPDX-License-Identifier: Apache-2.0
description: |
STMicroelectronics ISM6HG256X 6-axis IMU (Inertial Measurement Unit) sensor
accessed through I3C bus
compatible: "st,ism6hg256x"
include: ["i3c-device.yaml", "st,ism6hg256x-common.yaml"]
properties:
int-en-i3c:
type: boolean
description: |
Enables INT pin when I3C is enabled
bus-act-sel-us:
type: int
default: 50
description: |
Bus available time for I3C IBI in microseconds
enum: [50, 2, 1000, 25000]

View File

@@ -0,0 +1,10 @@
# Copyright (c) 2025 STMicroelectronics
# SPDX-License-Identifier: Apache-2.0
description: |
STMicroelectronics ISM6HG256X 6-axis IMU (Inertial Measurement Unit) sensor
accessed through SPI bus
compatible: "st,ism6hg256x"
include: ["spi-device.yaml", "st,ism6hg256x-common.yaml"]

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2025 STMicroelectronics
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ST_ISM6HG256X_H_
#define ZEPHYR_INCLUDE_DT_BINDINGS_ST_ISM6HG256X_H_
#include "lsm6dsvxxx.h"
/* Accel High-g odr */
#define ISM6HG256X_HG_XL_ODR_OFF 0x0
#define ISM6HG256X_HG_XL_ODR_AT_480Hz 0x3
#define ISM6HG256X_HG_XL_ODR_AT_960Hz 0x4
#define ISM6HG256X_HG_XL_ODR_AT_1920Hz 0x5
#define ISM6HG256X_HG_XL_ODR_AT_3840Hz 0x6
#define ISM6HG256X_HG_XL_ODR_AT_7680Hz 0x7
/* Accel range */
#define ISM6HG256X_DT_FS_2G 2
#define ISM6HG256X_DT_FS_4G 4
#define ISM6HG256X_DT_FS_8G 8
#define ISM6HG256X_DT_FS_16G 16
#define ISM6HG256X_DT_FS_32G 32
#define ISM6HG256X_DT_FS_64G 64
#define ISM6HG256X_DT_FS_128G 128
#define ISM6HG256X_DT_FS_256G 256
/* Gyro range */
#define ISM6HG256X_DT_FS_250DPS 0x1
#define ISM6HG256X_DT_FS_500DPS 0x2
#define ISM6HG256X_DT_FS_1000DPS 0x3
#define ISM6HG256X_DT_FS_2000DPS 0x4
#define ISM6HG256X_DT_FS_4000DPS 0x5
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ST_ISM6HG256X_H_ */

View File

@@ -69,6 +69,9 @@ config USE_STDC_ISM330DHCX
config USE_STDC_ISM330DLC
bool
config USE_STDC_ISM6HG256X
bool
config USE_STDC_L20G20IS
bool

View File

@@ -10,6 +10,7 @@
#include <zephyr/dt-bindings/sensor/lsm6dsv32x.h>
#include <zephyr/dt-bindings/sensor/lsm6dsv320x.h>
#include <zephyr/dt-bindings/sensor/lsm6dsv80x.h>
#include <zephyr/dt-bindings/sensor/ism6hg256x.h>
#include <zephyr/dt-bindings/sensor/lsm6dso.h>
#include <zephyr/dt-bindings/sensor/lsm6dso16is.h>
#include <zephyr/dt-bindings/sensor/lps22hh.h>
@@ -1513,3 +1514,14 @@ test_i2c_lsm6dsv80x: lsm6dsv80x@c7 {
gyro-range = <LSM6DSV80X_DT_FS_2000DPS>;
gyro-odr = <LSM6DSVXXX_DT_ODR_AT_60Hz>;
};
test_i2c_ism6hg256x: ism6hg256x@c8 {
compatible = "st,ism6hg256x";
reg = <0xc8>;
int1-gpios = <&test_gpio 0 0>;
int2-gpios = <&test_gpio 0 0>;
accel-range = <LSM6DSV80X_DT_FS_8G>;
accel-odr = <LSM6DSVXXX_DT_ODR_AT_60Hz>;
gyro-range = <LSM6DSV80X_DT_FS_2000DPS>;
gyro-odr = <LSM6DSVXXX_DT_ODR_AT_60Hz>;
};