sensor: lsm6dsv16x: add i3c support
Add I3C support to the lsm6dsv16x. Signed-off-by: Ryan McClelland <ryanmcclelland@meta.com>
This commit is contained in:
parent
cbfabf8be8
commit
eb93ba03a9
6 changed files with 398 additions and 83 deletions
|
|
@ -4,11 +4,12 @@
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
menuconfig LSM6DSV16X
|
menuconfig LSM6DSV16X
|
||||||
bool "LSM6DSV16X I2C/SPI accelerometer and gyroscope Chip"
|
bool "LSM6DSV16X I3C/I2C/SPI accelerometer and gyroscope Chip"
|
||||||
default y
|
default y
|
||||||
depends on DT_HAS_ST_LSM6DSV16X_ENABLED
|
depends on DT_HAS_ST_LSM6DSV16X_ENABLED
|
||||||
depends on ZEPHYR_HAL_ST_MODULE
|
depends on ZEPHYR_HAL_ST_MODULE
|
||||||
select I2C if $(dt_compat_on_bus,$(DT_COMPAT_ST_LSM6DSV16X),i2c)
|
select I2C if $(dt_compat_on_bus,$(DT_COMPAT_ST_LSM6DSV16X),i2c)
|
||||||
|
select I3C if $(dt_compat_on_bus,$(DT_COMPAT_ST_LSM6DSV16X),i3c)
|
||||||
select SPI if $(dt_compat_on_bus,$(DT_COMPAT_ST_LSM6DSV16X),spi)
|
select SPI if $(dt_compat_on_bus,$(DT_COMPAT_ST_LSM6DSV16X),spi)
|
||||||
select HAS_STMEMSC
|
select HAS_STMEMSC
|
||||||
select USE_STDC_LSM6DSV16X
|
select USE_STDC_LSM6DSV16X
|
||||||
|
|
@ -23,7 +24,7 @@ config LSM6DSV16X_STREAM
|
||||||
bool "Use hardware FIFO to stream data"
|
bool "Use hardware FIFO to stream data"
|
||||||
select LSM6DSV16X_TRIGGER
|
select LSM6DSV16X_TRIGGER
|
||||||
default y
|
default y
|
||||||
depends on I2C_RTIO || SPI_RTIO
|
depends on I2C_RTIO || SPI_RTIO || I3C_RTIO
|
||||||
depends on SENSOR_ASYNC_API
|
depends on SENSOR_ASYNC_API
|
||||||
help
|
help
|
||||||
Use this config option to enable streaming sensor data via RTIO subsystem.
|
Use this config option to enable streaming sensor data via RTIO subsystem.
|
||||||
|
|
@ -40,16 +41,18 @@ config LSM6DSV16X_TRIGGER_NONE
|
||||||
|
|
||||||
config LSM6DSV16X_TRIGGER_GLOBAL_THREAD
|
config LSM6DSV16X_TRIGGER_GLOBAL_THREAD
|
||||||
bool "Use global thread"
|
bool "Use global thread"
|
||||||
depends on GPIO
|
depends on GPIO || I3C
|
||||||
depends on $(dt_compat_any_has_prop,$(DT_COMPAT_ST_LSM6DSV16X),int1-gpios) ||\
|
depends on $(dt_compat_any_has_prop,$(DT_COMPAT_ST_LSM6DSV16X),int1-gpios) ||\
|
||||||
$(dt_compat_any_has_prop,$(DT_COMPAT_ST_LSM6DSV16X),int2-gpios)
|
$(dt_compat_any_has_prop,$(DT_COMPAT_ST_LSM6DSV16X),int2-gpios) ||\
|
||||||
|
$(dt_compat_on_bus,$(DT_COMPAT_ST_LSM6DSV16X),i3c)
|
||||||
select LSM6DSV16X_TRIGGER
|
select LSM6DSV16X_TRIGGER
|
||||||
|
|
||||||
config LSM6DSV16X_TRIGGER_OWN_THREAD
|
config LSM6DSV16X_TRIGGER_OWN_THREAD
|
||||||
bool "Use own thread"
|
bool "Use own thread"
|
||||||
depends on GPIO
|
depends on GPIO || I3C
|
||||||
depends on $(dt_compat_any_has_prop,$(DT_COMPAT_ST_LSM6DSV16X),int1-gpios) ||\
|
depends on $(dt_compat_any_has_prop,$(DT_COMPAT_ST_LSM6DSV16X),int1-gpios) ||\
|
||||||
$(dt_compat_any_has_prop,$(DT_COMPAT_ST_LSM6DSV16X),int2-gpios)
|
$(dt_compat_any_has_prop,$(DT_COMPAT_ST_LSM6DSV16X),int2-gpios) ||\
|
||||||
|
$(dt_compat_on_bus,$(DT_COMPAT_ST_LSM6DSV16X),i3c)
|
||||||
select LSM6DSV16X_TRIGGER
|
select LSM6DSV16X_TRIGGER
|
||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
|
||||||
|
|
@ -951,6 +951,20 @@ static int lsm6dsv16x_init_chip(const struct device *dev)
|
||||||
uint8_t chip_id;
|
uint8_t chip_id;
|
||||||
uint8_t odr, fs;
|
uint8_t odr, fs;
|
||||||
|
|
||||||
|
#if DT_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.
|
||||||
|
*/
|
||||||
|
lsm6dsv16x->i3c_dev = i3c_device_find(cfg->i3c.bus, &cfg->i3c.dev_id);
|
||||||
|
if (lsm6dsv16x->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
|
/* All registers except 0x01 are different between banks, including the WHO_AM_I
|
||||||
* register and the register used for a SW reset. If the lsm6dsv16x wasn't on the user
|
* register and the register used for a SW reset. If the lsm6dsv16x wasn't on the user
|
||||||
* bank when it reset, then both the chip id check and the sw reset will fail unless we
|
* bank when it reset, then both the chip id check and the sw reset will fail unless we
|
||||||
|
|
@ -973,13 +987,26 @@ static int lsm6dsv16x_init_chip(const struct device *dev)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reset device (sw_por) */
|
/* Resetting the whole device while using I3C will also reset the DA, therefore perform
|
||||||
if (lsm6dsv16x_reset_set(ctx, LSM6DSV16X_GLOBAL_RST) < 0) {
|
* only a software reset if the bus is I3C. It should be assumed that the device was
|
||||||
return -EIO;
|
* 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 */
|
||||||
|
lsm6dsv16x_reset_set(ctx, LSM6DSV16X_RESTORE_CAL_PARAM);
|
||||||
|
|
||||||
/* wait 30ms as reported in AN5763 */
|
/* wait 150us as reported in AN5763 */
|
||||||
k_sleep(K_MSEC(30));
|
k_sleep(K_USEC(150));
|
||||||
|
} else {
|
||||||
|
/* reset device (sw_por) */
|
||||||
|
if (lsm6dsv16x_reset_set(ctx, LSM6DSV16X_GLOBAL_RST) < 0) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait 30ms as reported in AN5763 */
|
||||||
|
k_sleep(K_MSEC(30));
|
||||||
|
}
|
||||||
|
|
||||||
fs = cfg->accel_range;
|
fs = cfg->accel_range;
|
||||||
LOG_DBG("accel range is %d", fs);
|
LOG_DBG("accel range is %d", fs);
|
||||||
|
|
@ -1012,6 +1039,23 @@ static int lsm6dsv16x_init_chip(const struct device *dev)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||||
|
if (IS_ENABLED(CONFIG_LSM6DSV16X_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 = lsm6dsv16x->i3c_dev->data_length.max_ibi,
|
||||||
|
};
|
||||||
|
if (i3c_ccc_do_setmrl(lsm6dsv16x->i3c_dev, &setmrl) < 0) {
|
||||||
|
LOG_ERR("failed to set mrl");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (lsm6dsv16x_block_data_update_set(ctx, 1) < 0) {
|
if (lsm6dsv16x_block_data_update_set(ctx, 1) < 0) {
|
||||||
LOG_DBG("failed to set BDU mode");
|
LOG_DBG("failed to set BDU mode");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
@ -1164,15 +1208,55 @@ static int lsm6dsv16x_init(const struct device *dev)
|
||||||
static const struct lsm6dsv16x_config lsm6dsv16x_config_##inst = \
|
static const struct lsm6dsv16x_config lsm6dsv16x_config_##inst = \
|
||||||
LSM6DSV16X_CONFIG_I2C(inst); \
|
LSM6DSV16X_CONFIG_I2C(inst); \
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Instantiation macros used when a device is on an I3C bus.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LSM6DSV16X_I3C_RTIO_DEFINE(inst) \
|
||||||
|
I3C_DT_IODEV_DEFINE(lsm6dsv16x_i3c_iodev_##inst, DT_DRV_INST(inst)); \
|
||||||
|
RTIO_DEFINE(lsm6dsv16x_rtio_ctx_##inst, 4, 4);
|
||||||
|
|
||||||
|
#define LSM6DSV16X_CONFIG_I3C(inst) \
|
||||||
|
{ \
|
||||||
|
STMEMSC_CTX_I3C(&lsm6dsv16x_config_##inst.stmemsc_cfg), \
|
||||||
|
.stmemsc_cfg = { \
|
||||||
|
.i3c = &lsm6dsv16x_data_##inst.i3c_dev, \
|
||||||
|
}, \
|
||||||
|
.i3c.bus = DEVICE_DT_GET(DT_INST_BUS(inst)), \
|
||||||
|
.i3c.dev_id = I3C_DEVICE_ID_DT_INST(inst), \
|
||||||
|
IF_ENABLED(CONFIG_LSM6DSV16X_TRIGGER, \
|
||||||
|
(.int_en_i3c = DT_INST_PROP(inst, int_en_i3c), \
|
||||||
|
.bus_act_sel = DT_INST_ENUM_IDX(inst, bus_act_sel_us),)) \
|
||||||
|
LSM6DSV16X_CONFIG_COMMON(inst) \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LSM6DSV16X_DEFINE_I3C(inst) \
|
||||||
|
IF_ENABLED(CONFIG_LSM6DSV16X_STREAM, (LSM6DSV16X_I3C_RTIO_DEFINE(inst))); \
|
||||||
|
static struct lsm6dsv16x_data lsm6dsv16x_data_##inst = { \
|
||||||
|
IF_ENABLED(CONFIG_LSM6DSV16X_STREAM, \
|
||||||
|
(.rtio_ctx = &lsm6dsv16x_rtio_ctx_##inst, \
|
||||||
|
.iodev = &lsm6dsv16x_i3c_iodev_##inst, \
|
||||||
|
.bus_type = BUS_I3C,)) \
|
||||||
|
}; \
|
||||||
|
static const struct lsm6dsv16x_config lsm6dsv16x_config_##inst = \
|
||||||
|
LSM6DSV16X_CONFIG_I3C(inst); \
|
||||||
|
|
||||||
|
#define LSM6DSV16X_DEFINE_I3C_OR_I2C(inst) \
|
||||||
|
COND_CODE_0(DT_INST_PROP_BY_IDX(inst, reg, 1), \
|
||||||
|
(LSM6DSV16X_DEFINE_I2C(inst)), \
|
||||||
|
(LSM6DSV16X_DEFINE_I3C(inst)))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Main instantiation macro. Use of COND_CODE_1() selects the right
|
* Main instantiation macro. Use of COND_CODE_1() selects the right
|
||||||
* bus-specific macro at preprocessor time.
|
* bus-specific macro at preprocessor time.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define LSM6DSV16X_DEFINE(inst) \
|
#define LSM6DSV16X_DEFINE(inst) \
|
||||||
COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
|
COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
|
||||||
(LSM6DSV16X_DEFINE_SPI(inst)), \
|
(LSM6DSV16X_DEFINE_SPI(inst)), \
|
||||||
(LSM6DSV16X_DEFINE_I2C(inst))); \
|
(COND_CODE_1(DT_INST_ON_BUS(inst, i3c), \
|
||||||
LSM6DSV16X_DEVICE_INIT(inst)
|
(LSM6DSV16X_DEFINE_I3C_OR_I2C(inst)), \
|
||||||
|
(LSM6DSV16X_DEFINE_I2C(inst))))); \
|
||||||
|
LSM6DSV16X_DEVICE_INIT(inst)
|
||||||
|
|
||||||
DT_INST_FOREACH_STATUS_OKAY(LSM6DSV16X_DEFINE)
|
DT_INST_FOREACH_STATUS_OKAY(LSM6DSV16X_DEFINE)
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,18 @@
|
||||||
#include <zephyr/drivers/i2c.h>
|
#include <zephyr/drivers/i2c.h>
|
||||||
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */
|
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */
|
||||||
|
|
||||||
|
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||||
|
#include <zephyr/drivers/i3c.h>
|
||||||
|
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) */
|
||||||
|
|
||||||
|
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||||
|
#define ON_I3C_BUS(cfg) (cfg->i3c.bus != NULL)
|
||||||
|
#define I3C_INT_PIN(cfg) (cfg->int_en_i3c)
|
||||||
|
#else
|
||||||
|
#define ON_I3C_BUS(cfg) (false)
|
||||||
|
#define I3C_INT_PIN(cfg) (false)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define LSM6DSV16X_EN_BIT 0x01
|
#define LSM6DSV16X_EN_BIT 0x01
|
||||||
#define LSM6DSV16X_DIS_BIT 0x00
|
#define LSM6DSV16X_DIS_BIT 0x00
|
||||||
|
|
||||||
|
|
@ -46,6 +58,9 @@ struct lsm6dsv16x_config {
|
||||||
#endif
|
#endif
|
||||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
|
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
|
||||||
const struct spi_dt_spec spi;
|
const struct spi_dt_spec spi;
|
||||||
|
#endif
|
||||||
|
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||||
|
struct i3c_device_desc **i3c;
|
||||||
#endif
|
#endif
|
||||||
} stmemsc_cfg;
|
} stmemsc_cfg;
|
||||||
uint8_t accel_pm;
|
uint8_t accel_pm;
|
||||||
|
|
@ -66,7 +81,18 @@ struct lsm6dsv16x_config {
|
||||||
const struct gpio_dt_spec int2_gpio;
|
const struct gpio_dt_spec int2_gpio;
|
||||||
uint8_t drdy_pin;
|
uint8_t drdy_pin;
|
||||||
bool trig_enabled;
|
bool trig_enabled;
|
||||||
|
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||||
|
bool int_en_i3c;
|
||||||
|
lsm6dsv16x_i3c_ibi_time_t bus_act_sel;
|
||||||
|
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) */
|
||||||
#endif /* CONFIG_LSM6DSV16X_TRIGGER */
|
#endif /* CONFIG_LSM6DSV16X_TRIGGER */
|
||||||
|
|
||||||
|
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||||
|
struct {
|
||||||
|
const struct device *bus;
|
||||||
|
const struct i3c_device_id dev_id;
|
||||||
|
} i3c;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
union samples {
|
union samples {
|
||||||
|
|
@ -78,6 +104,19 @@ union samples {
|
||||||
|
|
||||||
#define LSM6DSV16X_SHUB_MAX_NUM_TARGETS 3
|
#define LSM6DSV16X_SHUB_MAX_NUM_TARGETS 3
|
||||||
|
|
||||||
|
struct lsm6dsv16x_ibi_payload {
|
||||||
|
uint8_t mdb;
|
||||||
|
uint8_t fifo_status1;
|
||||||
|
uint8_t fifo_status2;
|
||||||
|
uint8_t all_int_src;
|
||||||
|
uint8_t status_reg;
|
||||||
|
uint8_t status_reg_ois;
|
||||||
|
uint8_t status_master_main;
|
||||||
|
uint8_t emb_func_status;
|
||||||
|
uint8_t fsm_status;
|
||||||
|
uint8_t mlc_status;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
struct lsm6dsv16x_data {
|
struct lsm6dsv16x_data {
|
||||||
const struct device *dev;
|
const struct device *dev;
|
||||||
int16_t acc[3];
|
int16_t acc[3];
|
||||||
|
|
@ -118,8 +157,8 @@ struct lsm6dsv16x_data {
|
||||||
uint8_t accel_batch_odr : 4;
|
uint8_t accel_batch_odr : 4;
|
||||||
uint8_t gyro_batch_odr : 4;
|
uint8_t gyro_batch_odr : 4;
|
||||||
uint8_t temp_batch_odr : 2;
|
uint8_t temp_batch_odr : 2;
|
||||||
uint8_t bus_type : 1; /* I2C is 0, SPI is 1 */
|
uint8_t bus_type : 2; /* I2C is 0, SPI is 1, I3C is 2 */
|
||||||
uint8_t reserved : 5;
|
uint8_t reserved : 4;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_LSM6DSV16X_TRIGGER
|
#ifdef CONFIG_LSM6DSV16X_TRIGGER
|
||||||
|
|
@ -136,16 +175,22 @@ struct lsm6dsv16x_data {
|
||||||
#if defined(CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD)
|
#if defined(CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD)
|
||||||
K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_LSM6DSV16X_THREAD_STACK_SIZE);
|
K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_LSM6DSV16X_THREAD_STACK_SIZE);
|
||||||
struct k_thread thread;
|
struct k_thread thread;
|
||||||
struct k_sem gpio_sem;
|
struct k_sem intr_sem;
|
||||||
#elif defined(CONFIG_LSM6DSV16X_TRIGGER_GLOBAL_THREAD)
|
#elif defined(CONFIG_LSM6DSV16X_TRIGGER_GLOBAL_THREAD)
|
||||||
struct k_work work;
|
struct k_work work;
|
||||||
#endif
|
#endif
|
||||||
#endif /* CONFIG_LSM6DSV16X_TRIGGER */
|
#endif /* CONFIG_LSM6DSV16X_TRIGGER */
|
||||||
|
|
||||||
|
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||||
|
struct i3c_device_desc *i3c_dev;
|
||||||
|
struct lsm6dsv16x_ibi_payload ibi_payload;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_LSM6DSV16X_STREAM
|
#ifdef CONFIG_LSM6DSV16X_STREAM
|
||||||
#define BUS_I2C 0
|
#define BUS_I2C 0
|
||||||
#define BUS_SPI 1
|
#define BUS_SPI 1
|
||||||
|
#define BUS_I3C 2
|
||||||
|
|
||||||
static inline uint8_t lsm6dsv16x_bus_reg(struct lsm6dsv16x_data *data, uint8_t x)
|
static inline uint8_t lsm6dsv16x_bus_reg(struct lsm6dsv16x_data *data, uint8_t x)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ static void lsm6dsv16x_config_fifo(const struct device *dev, uint8_t fifo_irq)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Set pin interrupt (fifo_th could be on or off) */
|
/* Set pin interrupt (fifo_th could be on or off) */
|
||||||
if (config->drdy_pin == 1) {
|
if ((config->drdy_pin == 1) || (ON_I3C_BUS(config) && (!I3C_INT_PIN(config)))) {
|
||||||
lsm6dsv16x_pin_int1_route_set(ctx, &pin_int);
|
lsm6dsv16x_pin_int1_route_set(ctx, &pin_int);
|
||||||
} else {
|
} else {
|
||||||
lsm6dsv16x_pin_int2_route_set(ctx, &pin_int);
|
lsm6dsv16x_pin_int2_route_set(ctx, &pin_int);
|
||||||
|
|
@ -80,10 +80,15 @@ static void lsm6dsv16x_config_fifo(const struct device *dev, uint8_t fifo_irq)
|
||||||
void lsm6dsv16x_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe)
|
void lsm6dsv16x_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe)
|
||||||
{
|
{
|
||||||
struct lsm6dsv16x_data *lsm6dsv16x = dev->data;
|
struct lsm6dsv16x_data *lsm6dsv16x = dev->data;
|
||||||
|
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||||
|
const struct lsm6dsv16x_config *config = dev->config;
|
||||||
|
#endif
|
||||||
const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data;
|
const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data;
|
||||||
uint8_t fifo_irq = 0;
|
uint8_t fifo_irq = 0;
|
||||||
|
|
||||||
gpio_pin_interrupt_configure_dt(lsm6dsv16x->drdy_gpio, GPIO_INT_DISABLE);
|
if (!ON_I3C_BUS(config) || (I3C_INT_PIN(config))) {
|
||||||
|
gpio_pin_interrupt_configure_dt(lsm6dsv16x->drdy_gpio, GPIO_INT_DISABLE);
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < cfg->count; i++) {
|
for (size_t i = 0; i < cfg->count; i++) {
|
||||||
if (cfg->triggers[i].trigger == SENSOR_TRIG_FIFO_WATERMARK) {
|
if (cfg->triggers[i].trigger == SENSOR_TRIG_FIFO_WATERMARK) {
|
||||||
|
|
@ -103,12 +108,17 @@ void lsm6dsv16x_submit_stream(const struct device *dev, struct rtio_iodev_sqe *i
|
||||||
|
|
||||||
lsm6dsv16x->streaming_sqe = iodev_sqe;
|
lsm6dsv16x->streaming_sqe = iodev_sqe;
|
||||||
|
|
||||||
gpio_pin_interrupt_configure_dt(lsm6dsv16x->drdy_gpio, GPIO_INT_EDGE_TO_ACTIVE);
|
if (!ON_I3C_BUS(config) || (I3C_INT_PIN(config))) {
|
||||||
|
gpio_pin_interrupt_configure_dt(lsm6dsv16x->drdy_gpio, GPIO_INT_EDGE_TO_ACTIVE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lsm6dsv16x_complete_op_cb(struct rtio *r, const struct rtio_sqe *sqe, void *arg)
|
static void lsm6dsv16x_complete_op_cb(struct rtio *r, const struct rtio_sqe *sqe, void *arg)
|
||||||
{
|
{
|
||||||
const struct device *dev = arg;
|
const struct device *dev = arg;
|
||||||
|
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||||
|
const struct lsm6dsv16x_config *config = dev->config;
|
||||||
|
#endif
|
||||||
struct lsm6dsv16x_data *lsm6dsv16x = dev->data;
|
struct lsm6dsv16x_data *lsm6dsv16x = dev->data;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -116,12 +126,17 @@ static void lsm6dsv16x_complete_op_cb(struct rtio *r, const struct rtio_sqe *sqe
|
||||||
*/
|
*/
|
||||||
rtio_iodev_sqe_ok(sqe->userdata, 0);
|
rtio_iodev_sqe_ok(sqe->userdata, 0);
|
||||||
lsm6dsv16x->streaming_sqe = NULL;
|
lsm6dsv16x->streaming_sqe = NULL;
|
||||||
gpio_pin_interrupt_configure_dt(lsm6dsv16x->drdy_gpio, GPIO_INT_EDGE_TO_ACTIVE);
|
if (!ON_I3C_BUS(config) || (I3C_INT_PIN(config))) {
|
||||||
|
gpio_pin_interrupt_configure_dt(lsm6dsv16x->drdy_gpio, GPIO_INT_EDGE_TO_ACTIVE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lsm6dsv16x_read_fifo_cb(struct rtio *r, const struct rtio_sqe *sqe, void *arg)
|
static void lsm6dsv16x_read_fifo_cb(struct rtio *r, const struct rtio_sqe *sqe, void *arg)
|
||||||
{
|
{
|
||||||
const struct device *dev = arg;
|
const struct device *dev = arg;
|
||||||
|
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||||
|
const struct lsm6dsv16x_config *config = dev->config;
|
||||||
|
#endif
|
||||||
struct lsm6dsv16x_data *lsm6dsv16x = dev->data;
|
struct lsm6dsv16x_data *lsm6dsv16x = dev->data;
|
||||||
struct gpio_dt_spec *irq_gpio = lsm6dsv16x->drdy_gpio;
|
struct gpio_dt_spec *irq_gpio = lsm6dsv16x->drdy_gpio;
|
||||||
struct rtio_iodev *iodev = lsm6dsv16x->iodev;
|
struct rtio_iodev *iodev = lsm6dsv16x->iodev;
|
||||||
|
|
@ -168,7 +183,9 @@ static void lsm6dsv16x_read_fifo_cb(struct rtio *r, const struct rtio_sqe *sqe,
|
||||||
rtio_iodev_sqe_ok(sqe->userdata, 0);
|
rtio_iodev_sqe_ok(sqe->userdata, 0);
|
||||||
|
|
||||||
lsm6dsv16x->streaming_sqe = NULL;
|
lsm6dsv16x->streaming_sqe = NULL;
|
||||||
gpio_pin_interrupt_configure_dt(irq_gpio, GPIO_INT_EDGE_TO_ACTIVE);
|
if (!ON_I3C_BUS(config) || (I3C_INT_PIN(config))) {
|
||||||
|
gpio_pin_interrupt_configure_dt(irq_gpio, GPIO_INT_EDGE_TO_ACTIVE);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -215,7 +232,9 @@ static void lsm6dsv16x_read_fifo_cb(struct rtio *r, const struct rtio_sqe *sqe,
|
||||||
sizeof(struct lsm6dsv16x_fifo_data), &buf, &buf_len) != 0) {
|
sizeof(struct lsm6dsv16x_fifo_data), &buf, &buf_len) != 0) {
|
||||||
rtio_iodev_sqe_err(lsm6dsv16x->streaming_sqe, -ENOMEM);
|
rtio_iodev_sqe_err(lsm6dsv16x->streaming_sqe, -ENOMEM);
|
||||||
lsm6dsv16x->streaming_sqe = NULL;
|
lsm6dsv16x->streaming_sqe = NULL;
|
||||||
gpio_pin_interrupt_configure_dt(irq_gpio, GPIO_INT_EDGE_TO_ACTIVE);
|
if (!ON_I3C_BUS(config) || (I3C_INT_PIN(config))) {
|
||||||
|
gpio_pin_interrupt_configure_dt(irq_gpio, GPIO_INT_EDGE_TO_ACTIVE);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -230,7 +249,9 @@ static void lsm6dsv16x_read_fifo_cb(struct rtio *r, const struct rtio_sqe *sqe,
|
||||||
/* complete request with ok */
|
/* complete request with ok */
|
||||||
rtio_iodev_sqe_ok(lsm6dsv16x->streaming_sqe, 0);
|
rtio_iodev_sqe_ok(lsm6dsv16x->streaming_sqe, 0);
|
||||||
lsm6dsv16x->streaming_sqe = NULL;
|
lsm6dsv16x->streaming_sqe = NULL;
|
||||||
gpio_pin_interrupt_configure_dt(irq_gpio, GPIO_INT_EDGE_TO_ACTIVE);
|
if (!ON_I3C_BUS(config) || (I3C_INT_PIN(config))) {
|
||||||
|
gpio_pin_interrupt_configure_dt(irq_gpio, GPIO_INT_EDGE_TO_ACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
if (data_opt == SENSOR_STREAM_DATA_DROP) {
|
if (data_opt == SENSOR_STREAM_DATA_DROP) {
|
||||||
|
|
||||||
|
|
@ -266,7 +287,9 @@ static void lsm6dsv16x_read_fifo_cb(struct rtio *r, const struct rtio_sqe *sqe,
|
||||||
LOG_ERR("Failed to get buffer");
|
LOG_ERR("Failed to get buffer");
|
||||||
rtio_iodev_sqe_err(lsm6dsv16x->streaming_sqe, -ENOMEM);
|
rtio_iodev_sqe_err(lsm6dsv16x->streaming_sqe, -ENOMEM);
|
||||||
lsm6dsv16x->streaming_sqe = NULL;
|
lsm6dsv16x->streaming_sqe = NULL;
|
||||||
gpio_pin_interrupt_configure_dt(irq_gpio, GPIO_INT_EDGE_TO_ACTIVE);
|
if (!ON_I3C_BUS(config) || (I3C_INT_PIN(config))) {
|
||||||
|
gpio_pin_interrupt_configure_dt(irq_gpio, GPIO_INT_EDGE_TO_ACTIVE);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -316,6 +339,8 @@ static void lsm6dsv16x_read_fifo_cb(struct rtio *r, const struct rtio_sqe *sqe,
|
||||||
read_fifo_dout_reg->flags = RTIO_SQE_CHAINED;
|
read_fifo_dout_reg->flags = RTIO_SQE_CHAINED;
|
||||||
if (lsm6dsv16x->bus_type == BUS_I2C) {
|
if (lsm6dsv16x->bus_type == BUS_I2C) {
|
||||||
read_fifo_dout_reg->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
|
read_fifo_dout_reg->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
|
||||||
|
} else if (lsm6dsv16x->bus_type == BUS_I3C) {
|
||||||
|
read_fifo_dout_reg->iodev_flags |= RTIO_IODEV_I3C_STOP | RTIO_IODEV_I3C_RESTART;
|
||||||
}
|
}
|
||||||
rtio_sqe_prep_callback_no_cqe(complete_op, lsm6dsv16x_complete_op_cb, (void *)dev,
|
rtio_sqe_prep_callback_no_cqe(complete_op, lsm6dsv16x_complete_op_cb, (void *)dev,
|
||||||
lsm6dsv16x->streaming_sqe);
|
lsm6dsv16x->streaming_sqe);
|
||||||
|
|
@ -327,6 +352,9 @@ void lsm6dsv16x_stream_irq_handler(const struct device *dev)
|
||||||
{
|
{
|
||||||
struct lsm6dsv16x_data *lsm6dsv16x = dev->data;
|
struct lsm6dsv16x_data *lsm6dsv16x = dev->data;
|
||||||
struct rtio_iodev *iodev = lsm6dsv16x->iodev;
|
struct rtio_iodev *iodev = lsm6dsv16x->iodev;
|
||||||
|
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||||
|
const struct lsm6dsv16x_config *config = dev->config;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (lsm6dsv16x->streaming_sqe == NULL) {
|
if (lsm6dsv16x->streaming_sqe == NULL) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -335,32 +363,50 @@ void lsm6dsv16x_stream_irq_handler(const struct device *dev)
|
||||||
/* get timestamp as soon as the irq is served */
|
/* get timestamp as soon as the irq is served */
|
||||||
lsm6dsv16x->fifo_timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
|
lsm6dsv16x->fifo_timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
|
||||||
|
|
||||||
lsm6dsv16x->fifo_status[0] = lsm6dsv16x->fifo_status[1] = 0;
|
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||||
|
if (ON_I3C_BUS(config) && (!I3C_INT_PIN(config))) {
|
||||||
|
/*
|
||||||
|
* If we are on an I3C bus, then it should be expected that the fifo status was
|
||||||
|
* already received in the IBI payload and we don't need to read it again.
|
||||||
|
*/
|
||||||
|
lsm6dsv16x->fifo_status[0] = lsm6dsv16x->ibi_payload.fifo_status1;
|
||||||
|
lsm6dsv16x->fifo_status[1] = lsm6dsv16x->ibi_payload.fifo_status2;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
lsm6dsv16x->fifo_status[0] = lsm6dsv16x->fifo_status[1] = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare rtio enabled bus to read LSM6DSV16X_FIFO_STATUS1 and LSM6DSV16X_FIFO_STATUS2
|
* Prepare rtio enabled bus to read LSM6DSV16X_FIFO_STATUS1 and
|
||||||
* registers where FIFO threshold condition and count are reported.
|
* LSM6DSV16X_FIFO_STATUS2 registers where FIFO threshold condition and count are
|
||||||
* Then lsm6dsv16x_read_fifo_cb callback will be invoked.
|
* reported. Then lsm6dsv16x_read_fifo_cb callback will be invoked.
|
||||||
*
|
*
|
||||||
* STMEMSC API equivalent code:
|
* STMEMSC API equivalent code:
|
||||||
*
|
*
|
||||||
* lsm6dsv16x_fifo_status_t fifo_status;
|
* lsm6dsv16x_fifo_status_t fifo_status;
|
||||||
*
|
*
|
||||||
* lsm6dsv16x_fifo_status_get(&dev_ctx, &fifo_status);
|
* lsm6dsv16x_fifo_status_get(&dev_ctx, &fifo_status);
|
||||||
*/
|
*/
|
||||||
struct rtio_sqe *write_fifo_status_addr = rtio_sqe_acquire(lsm6dsv16x->rtio_ctx);
|
struct rtio_sqe *write_fifo_status_addr = rtio_sqe_acquire(lsm6dsv16x->rtio_ctx);
|
||||||
struct rtio_sqe *read_fifo_status_reg = rtio_sqe_acquire(lsm6dsv16x->rtio_ctx);
|
struct rtio_sqe *read_fifo_status_reg = rtio_sqe_acquire(lsm6dsv16x->rtio_ctx);
|
||||||
struct rtio_sqe *check_fifo_status_reg = rtio_sqe_acquire(lsm6dsv16x->rtio_ctx);
|
uint8_t reg = lsm6dsv16x_bus_reg(lsm6dsv16x, LSM6DSV16X_FIFO_STATUS1);
|
||||||
uint8_t reg = lsm6dsv16x_bus_reg(lsm6dsv16x, LSM6DSV16X_FIFO_STATUS1);
|
|
||||||
|
|
||||||
rtio_sqe_prep_tiny_write(write_fifo_status_addr, iodev, RTIO_PRIO_NORM, ®, 1, NULL);
|
rtio_sqe_prep_tiny_write(write_fifo_status_addr, iodev, RTIO_PRIO_NORM, ®, 1,
|
||||||
write_fifo_status_addr->flags = RTIO_SQE_TRANSACTION;
|
NULL);
|
||||||
rtio_sqe_prep_read(read_fifo_status_reg, iodev, RTIO_PRIO_NORM,
|
write_fifo_status_addr->flags = RTIO_SQE_TRANSACTION;
|
||||||
lsm6dsv16x->fifo_status, 2, NULL);
|
rtio_sqe_prep_read(read_fifo_status_reg, iodev, RTIO_PRIO_NORM,
|
||||||
read_fifo_status_reg->flags = RTIO_SQE_CHAINED;
|
lsm6dsv16x->fifo_status, 2, NULL);
|
||||||
if (lsm6dsv16x->bus_type == BUS_I2C) {
|
read_fifo_status_reg->flags = RTIO_SQE_CHAINED;
|
||||||
read_fifo_status_reg->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
|
if (lsm6dsv16x->bus_type == BUS_I2C) {
|
||||||
|
read_fifo_status_reg->iodev_flags |=
|
||||||
|
RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
|
||||||
|
} else if (lsm6dsv16x->bus_type == BUS_I3C) {
|
||||||
|
read_fifo_status_reg->iodev_flags |=
|
||||||
|
RTIO_IODEV_I3C_STOP | RTIO_IODEV_I3C_RESTART;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
struct rtio_sqe *check_fifo_status_reg = rtio_sqe_acquire(lsm6dsv16x->rtio_ctx);
|
||||||
|
|
||||||
rtio_sqe_prep_callback_no_cqe(check_fifo_status_reg,
|
rtio_sqe_prep_callback_no_cqe(check_fifo_status_reg,
|
||||||
lsm6dsv16x_read_fifo_cb, (void *)dev, NULL);
|
lsm6dsv16x_read_fifo_cb, (void *)dev, NULL);
|
||||||
rtio_submit(lsm6dsv16x->rtio_ctx, 0);
|
rtio_submit(lsm6dsv16x->rtio_ctx, 0);
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ static int lsm6dsv16x_enable_xl_int(const struct device *dev, int enable)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set interrupt */
|
/* set interrupt */
|
||||||
if (cfg->drdy_pin == 1) {
|
if ((cfg->drdy_pin == 1) || (ON_I3C_BUS(cfg) && (!I3C_INT_PIN(cfg)))) {
|
||||||
lsm6dsv16x_pin_int_route_t val = {};
|
lsm6dsv16x_pin_int_route_t val = {};
|
||||||
|
|
||||||
ret = lsm6dsv16x_pin_int1_route_get(ctx, &val);
|
ret = lsm6dsv16x_pin_int1_route_get(ctx, &val);
|
||||||
|
|
@ -83,7 +83,7 @@ static int lsm6dsv16x_enable_g_int(const struct device *dev, int enable)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set interrupt */
|
/* set interrupt */
|
||||||
if (cfg->drdy_pin == 1) {
|
if ((cfg->drdy_pin == 1) || (ON_I3C_BUS(cfg) && (!I3C_INT_PIN(cfg)))) {
|
||||||
lsm6dsv16x_pin_int_route_t val = {};
|
lsm6dsv16x_pin_int_route_t val = {};
|
||||||
|
|
||||||
ret = lsm6dsv16x_pin_int1_route_get(ctx, &val);
|
ret = lsm6dsv16x_pin_int1_route_get(ctx, &val);
|
||||||
|
|
@ -174,8 +174,13 @@ static void lsm6dsv16x_handle_interrupt(const struct device *dev)
|
||||||
const struct lsm6dsv16x_config *cfg = dev->config;
|
const struct lsm6dsv16x_config *cfg = dev->config;
|
||||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||||
lsm6dsv16x_data_ready_t status;
|
lsm6dsv16x_data_ready_t status;
|
||||||
|
int ret;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
if (IS_ENABLED(CONFIG_LSM6DSV16X_STREAM)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (lsm6dsv16x_flag_data_ready_get(ctx, &status) < 0) {
|
if (lsm6dsv16x_flag_data_ready_get(ctx, &status) < 0) {
|
||||||
LOG_DBG("failed reading status reg");
|
LOG_DBG("failed reading status reg");
|
||||||
return;
|
return;
|
||||||
|
|
@ -195,30 +200,43 @@ static void lsm6dsv16x_handle_interrupt(const struct device *dev)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gpio_pin_interrupt_configure_dt(lsm6dsv16x->drdy_gpio,
|
if (!ON_I3C_BUS(cfg) || (I3C_INT_PIN(cfg))) {
|
||||||
GPIO_INT_EDGE_TO_ACTIVE);
|
ret = gpio_pin_interrupt_configure_dt(lsm6dsv16x->drdy_gpio,
|
||||||
|
GPIO_INT_EDGE_TO_ACTIVE);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("%s: Not able to configure pin_int", dev->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD || CONFIG_LSM6DSV16X_TRIGGER_GLOBAL_THREAD */
|
#endif /* CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD || CONFIG_LSM6DSV16X_TRIGGER_GLOBAL_THREAD */
|
||||||
|
|
||||||
|
static void lsm6dsv16x_intr_callback(struct lsm6dsv16x_data *lsm6dsv16x)
|
||||||
|
{
|
||||||
|
#if defined(CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD)
|
||||||
|
k_sem_give(&lsm6dsv16x->intr_sem);
|
||||||
|
#elif defined(CONFIG_LSM6DSV16X_TRIGGER_GLOBAL_THREAD)
|
||||||
|
k_work_submit(&lsm6dsv16x->work);
|
||||||
|
#endif /* CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD */
|
||||||
|
if (IS_ENABLED(CONFIG_LSM6DSV16X_STREAM)) {
|
||||||
|
lsm6dsv16x_stream_irq_handler(lsm6dsv16x->dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void lsm6dsv16x_gpio_callback(const struct device *dev,
|
static void lsm6dsv16x_gpio_callback(const struct device *dev,
|
||||||
struct gpio_callback *cb, uint32_t pins)
|
struct gpio_callback *cb, uint32_t pins)
|
||||||
{
|
{
|
||||||
struct lsm6dsv16x_data *lsm6dsv16x =
|
struct lsm6dsv16x_data *lsm6dsv16x =
|
||||||
CONTAINER_OF(cb, struct lsm6dsv16x_data, gpio_cb);
|
CONTAINER_OF(cb, struct lsm6dsv16x_data, gpio_cb);
|
||||||
|
int ret;
|
||||||
|
|
||||||
ARG_UNUSED(pins);
|
ARG_UNUSED(pins);
|
||||||
|
|
||||||
gpio_pin_interrupt_configure_dt(lsm6dsv16x->drdy_gpio, GPIO_INT_DISABLE);
|
ret = gpio_pin_interrupt_configure_dt(lsm6dsv16x->drdy_gpio, GPIO_INT_DISABLE);
|
||||||
|
if (ret < 0) {
|
||||||
if (IS_ENABLED(CONFIG_LSM6DSV16X_STREAM)) {
|
LOG_ERR("%s: Not able to configure pin_int", dev->name);
|
||||||
lsm6dsv16x_stream_irq_handler(lsm6dsv16x->dev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD)
|
lsm6dsv16x_intr_callback(lsm6dsv16x);
|
||||||
k_sem_give(&lsm6dsv16x->gpio_sem);
|
|
||||||
#elif defined(CONFIG_LSM6DSV16X_TRIGGER_GLOBAL_THREAD)
|
|
||||||
k_work_submit(&lsm6dsv16x->work);
|
|
||||||
#endif /* CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD
|
#ifdef CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD
|
||||||
|
|
@ -230,7 +248,7 @@ static void lsm6dsv16x_thread(void *p1, void *p2, void *p3)
|
||||||
struct lsm6dsv16x_data *lsm6dsv16x = p1;
|
struct lsm6dsv16x_data *lsm6dsv16x = p1;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
k_sem_take(&lsm6dsv16x->gpio_sem, K_FOREVER);
|
k_sem_take(&lsm6dsv16x->intr_sem, K_FOREVER);
|
||||||
lsm6dsv16x_handle_interrupt(lsm6dsv16x->dev);
|
lsm6dsv16x_handle_interrupt(lsm6dsv16x->dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -246,6 +264,47 @@ static void lsm6dsv16x_work_cb(struct k_work *work)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_LSM6DSV16X_TRIGGER_GLOBAL_THREAD */
|
#endif /* CONFIG_LSM6DSV16X_TRIGGER_GLOBAL_THREAD */
|
||||||
|
|
||||||
|
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||||
|
static int lsm6dsv16x_ibi_cb(struct i3c_device_desc *target,
|
||||||
|
struct i3c_ibi_payload *payload)
|
||||||
|
{
|
||||||
|
const struct device *dev = target->dev;
|
||||||
|
struct lsm6dsv16x_data *lsm6dsv16x = dev->data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The IBI Payload consist of the following 10 bytes :
|
||||||
|
* 1st byte: MDB
|
||||||
|
* - MDB[0]: FIFO interrupts (FIFO_WTM_IA, FIFO_OVR_IA, FIFO_FULL_IA, CONTER_BDR_IA)
|
||||||
|
* - MDB[1]: Physical interrupts (XLDS, GDA, TDA, XLDA_OIS, GDA_OIS)
|
||||||
|
* - MDB[2]: Basic interrupts (SLEEP_CHANGE_IA, D6D_IA, DOUBLE_TAP, SINGLE_TAP, WU_IA,
|
||||||
|
* FF_IA)
|
||||||
|
* - MDB[3]: SHUB DRDY (SENS_HUB_ENDOP)
|
||||||
|
* - MDB[4]: Advanced Function interrupt group
|
||||||
|
* - MDB[7:5]: 3'b000: Vendor Definied
|
||||||
|
* 3'b100: Timing Information
|
||||||
|
* 2nd byte: FIFO_STATUS1
|
||||||
|
* 3rd byte: FIFO_STATUS2
|
||||||
|
* 4th byte: ALL_INT_SRC
|
||||||
|
* 5th byte: STATUS_REG
|
||||||
|
* 6th byte: STATUS_REG_OIS
|
||||||
|
* 7th byte: STATUS_MASTER_MAIN
|
||||||
|
* 8th byte: EMB_FUNC_STATUS
|
||||||
|
* 9th byte: FSM_STATUS
|
||||||
|
* 10th byte: MLC_STATUS
|
||||||
|
*/
|
||||||
|
if (payload->payload_len != sizeof(lsm6dsv16x->ibi_payload)) {
|
||||||
|
LOG_ERR("Invalid IBI payload length");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&lsm6dsv16x->ibi_payload, payload->payload, payload->payload_len);
|
||||||
|
|
||||||
|
lsm6dsv16x_intr_callback(lsm6dsv16x);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int lsm6dsv16x_init_interrupt(const struct device *dev)
|
int lsm6dsv16x_init_interrupt(const struct device *dev)
|
||||||
{
|
{
|
||||||
struct lsm6dsv16x_data *lsm6dsv16x = dev->data;
|
struct lsm6dsv16x_data *lsm6dsv16x = dev->data;
|
||||||
|
|
@ -258,13 +317,17 @@ int lsm6dsv16x_init_interrupt(const struct device *dev)
|
||||||
(struct gpio_dt_spec *)&cfg->int2_gpio;
|
(struct gpio_dt_spec *)&cfg->int2_gpio;
|
||||||
|
|
||||||
/* setup data ready gpio interrupt (INT1 or INT2) */
|
/* setup data ready gpio interrupt (INT1 or INT2) */
|
||||||
if (!gpio_is_ready_dt(lsm6dsv16x->drdy_gpio)) {
|
if ((!ON_I3C_BUS(cfg) || (I3C_INT_PIN(cfg))) && !gpio_is_ready_dt(lsm6dsv16x->drdy_gpio)) {
|
||||||
LOG_ERR("Cannot get pointer to drdy_gpio device");
|
LOG_ERR("Cannot get pointer to drdy_gpio device");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_LSM6DSV16X_STREAM)) {
|
||||||
|
lsm6dsv16x_stream_irq_handler(lsm6dsv16x->dev);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD)
|
#if defined(CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD)
|
||||||
k_sem_init(&lsm6dsv16x->gpio_sem, 0, K_SEM_MAX_LIMIT);
|
k_sem_init(&lsm6dsv16x->intr_sem, 0, K_SEM_MAX_LIMIT);
|
||||||
|
|
||||||
k_thread_create(&lsm6dsv16x->thread, lsm6dsv16x->thread_stack,
|
k_thread_create(&lsm6dsv16x->thread, lsm6dsv16x->thread_stack,
|
||||||
CONFIG_LSM6DSV16X_THREAD_STACK_SIZE,
|
CONFIG_LSM6DSV16X_THREAD_STACK_SIZE,
|
||||||
|
|
@ -276,26 +339,29 @@ int lsm6dsv16x_init_interrupt(const struct device *dev)
|
||||||
lsm6dsv16x->work.handler = lsm6dsv16x_work_cb;
|
lsm6dsv16x->work.handler = lsm6dsv16x_work_cb;
|
||||||
#endif /* CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD */
|
#endif /* CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD */
|
||||||
|
|
||||||
ret = gpio_pin_configure_dt(lsm6dsv16x->drdy_gpio, GPIO_INPUT);
|
if (!ON_I3C_BUS(cfg) || (I3C_INT_PIN(cfg))) {
|
||||||
if (ret < 0) {
|
ret = gpio_pin_configure_dt(lsm6dsv16x->drdy_gpio, GPIO_INPUT);
|
||||||
LOG_DBG("Could not configure gpio");
|
if (ret < 0) {
|
||||||
return ret;
|
LOG_DBG("Could not configure gpio");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_init_callback(&lsm6dsv16x->gpio_cb,
|
||||||
|
lsm6dsv16x_gpio_callback,
|
||||||
|
BIT(lsm6dsv16x->drdy_gpio->pin));
|
||||||
|
|
||||||
|
if (gpio_add_callback(lsm6dsv16x->drdy_gpio->port, &lsm6dsv16x->gpio_cb) < 0) {
|
||||||
|
LOG_DBG("Could not set gpio callback");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gpio_init_callback(&lsm6dsv16x->gpio_cb,
|
/* set data ready mode on int1/int2/tir */
|
||||||
lsm6dsv16x_gpio_callback,
|
|
||||||
BIT(lsm6dsv16x->drdy_gpio->pin));
|
|
||||||
|
|
||||||
if (gpio_add_callback(lsm6dsv16x->drdy_gpio->port, &lsm6dsv16x->gpio_cb) < 0) {
|
|
||||||
LOG_DBG("Could not set gpio callback");
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* set data ready mode on int1/int2 */
|
|
||||||
LOG_DBG("drdy_pulsed is %d", (int)cfg->drdy_pulsed);
|
LOG_DBG("drdy_pulsed is %d", (int)cfg->drdy_pulsed);
|
||||||
lsm6dsv16x_data_ready_mode_t mode = cfg->drdy_pulsed ? LSM6DSV16X_DRDY_PULSED :
|
lsm6dsv16x_data_ready_mode_t mode = cfg->drdy_pulsed ? LSM6DSV16X_DRDY_PULSED :
|
||||||
LSM6DSV16X_DRDY_LATCHED;
|
LSM6DSV16X_DRDY_LATCHED;
|
||||||
|
|
||||||
|
|
||||||
ret = lsm6dsv16x_data_ready_mode_set(ctx, mode);
|
ret = lsm6dsv16x_data_ready_mode_set(ctx, mode);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
|
@ -303,6 +369,53 @@ int lsm6dsv16x_init_interrupt(const struct device *dev)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||||
|
if (ON_I3C_BUS(cfg)) {
|
||||||
|
if (I3C_INT_PIN(cfg)) {
|
||||||
|
/* Enable INT Pins when using I3C */
|
||||||
|
ret = lsm6dsv16x_i3c_int_en_set(ctx, I3C_INT_PIN(cfg));
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("failed to enable int pin for I3C %d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gpio_pin_interrupt_configure_dt(lsm6dsv16x->drdy_gpio,
|
||||||
|
GPIO_INT_EDGE_TO_ACTIVE);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Could not configure gpio interrupt");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* I3C IBI does not utilize GPIO interrupt. */
|
||||||
|
lsm6dsv16x->i3c_dev->ibi_cb = lsm6dsv16x_ibi_cb;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set IBI availability time, this is the time that the sensor
|
||||||
|
* will wait for inactivity before it is okay to generate an IBI TIR.
|
||||||
|
*
|
||||||
|
* NOTE: There is a bug in the API and the Documentation where
|
||||||
|
* the defines for the values are incorrect. The correct values are:
|
||||||
|
* 0 = 50us
|
||||||
|
* 1 = 2us
|
||||||
|
* 2 = 1ms
|
||||||
|
* 3 = 25ms
|
||||||
|
*/
|
||||||
|
ret = lsm6dsv16x_i3c_ibi_time_set(ctx, cfg->bus_act_sel);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("failed to set ibi available time %d", ret);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i3c_ibi_enable(lsm6dsv16x->i3c_dev) != 0) {
|
||||||
|
LOG_ERR("Could not enable I3C IBI");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return gpio_pin_interrupt_configure_dt(lsm6dsv16x->drdy_gpio,
|
return gpio_pin_interrupt_configure_dt(lsm6dsv16x->drdy_gpio,
|
||||||
GPIO_INT_EDGE_TO_ACTIVE);
|
GPIO_INT_EDGE_TO_ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
24
dts/bindings/sensor/st,lsm6dsv16x-i3c.yaml
Normal file
24
dts/bindings/sensor/st,lsm6dsv16x-i3c.yaml
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
# Copyright (c) 2024 Meta Platforms
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
description: |
|
||||||
|
STMicroelectronics LSM6DSV16X 6-axis IMU (Inertial Measurement Unit) sensor
|
||||||
|
accessed through I3C bus
|
||||||
|
|
||||||
|
compatible: "st,lsm6dsv16x"
|
||||||
|
|
||||||
|
include: ["i3c-device.yaml", "st,lsm6dsv16x-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]
|
||||||
Loading…
Reference in a new issue