sensor: icm45686: Add I2C bus support
Validated for read/decode APIs, as well as Streaming mode (FIFO). Signed-off-by: Luis Ubieda <luisf@croxel.com>
This commit is contained in:
parent
b22299d262
commit
0a4d86c557
6 changed files with 94 additions and 7 deletions
|
@ -6,8 +6,10 @@ menuconfig ICM45686
|
||||||
bool "ICM45686 High-precision 6-Axis Motion Tracking Device"
|
bool "ICM45686 High-precision 6-Axis Motion Tracking Device"
|
||||||
default y
|
default y
|
||||||
depends on DT_HAS_INVENSENSE_ICM45686_ENABLED
|
depends on DT_HAS_INVENSENSE_ICM45686_ENABLED
|
||||||
select SPI
|
select SPI if $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM45686),spi)
|
||||||
select SPI_RTIO
|
select SPI_RTIO if $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM45686),spi)
|
||||||
|
select I2C if $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM45686),i2c)
|
||||||
|
select I2C_RTIO if $(dt_compat_on_bus,$(DT_COMPAT_INVENSENSE_ICM45686),i2c)
|
||||||
help
|
help
|
||||||
Enable driver for ICM45686 High-precision 6-axis motion
|
Enable driver for ICM45686 High-precision 6-axis motion
|
||||||
tracking device.
|
tracking device.
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include <zephyr/drivers/sensor.h>
|
#include <zephyr/drivers/sensor.h>
|
||||||
#include <zephyr/drivers/spi.h>
|
#include <zephyr/drivers/spi.h>
|
||||||
|
#include <zephyr/drivers/i2c.h>
|
||||||
#include <zephyr/drivers/gpio.h>
|
#include <zephyr/drivers/gpio.h>
|
||||||
#include <zephyr/rtio/rtio.h>
|
#include <zephyr/rtio/rtio.h>
|
||||||
|
|
||||||
|
@ -199,6 +200,9 @@ static inline void icm45686_submit_one_shot(const struct device *dev,
|
||||||
edata->payload.buf,
|
edata->payload.buf,
|
||||||
sizeof(edata->payload.buf),
|
sizeof(edata->payload.buf),
|
||||||
NULL);
|
NULL);
|
||||||
|
if (data->rtio.type == ICM45686_BUS_I2C) {
|
||||||
|
read_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
|
||||||
|
}
|
||||||
read_sqe->flags |= RTIO_SQE_CHAINED;
|
read_sqe->flags |= RTIO_SQE_CHAINED;
|
||||||
|
|
||||||
rtio_sqe_prep_callback_no_cqe(complete_sqe,
|
rtio_sqe_prep_callback_no_cqe(complete_sqe,
|
||||||
|
@ -245,10 +249,18 @@ static int icm45686_init(const struct device *dev)
|
||||||
uint8_t val;
|
uint8_t val;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!spi_is_ready_iodev(data->rtio.iodev)) {
|
#if CONFIG_SPI_RTIO
|
||||||
|
if ((data->rtio.type == ICM45686_BUS_SPI) && !spi_is_ready_iodev(data->rtio.iodev)) {
|
||||||
LOG_ERR("Bus is not ready");
|
LOG_ERR("Bus is not ready");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#if CONFIG_I2C_RTIO
|
||||||
|
if ((data->rtio.type == ICM45686_BUS_I2C) && !i2c_is_ready_iodev(data->rtio.iodev)) {
|
||||||
|
LOG_ERR("Bus is not ready");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Soft-reset sensor to restore config to defaults */
|
/* Soft-reset sensor to restore config to defaults */
|
||||||
|
|
||||||
|
@ -383,10 +395,18 @@ static int icm45686_init(const struct device *dev)
|
||||||
#define ICM45686_INIT(inst) \
|
#define ICM45686_INIT(inst) \
|
||||||
\
|
\
|
||||||
RTIO_DEFINE(icm45686_rtio_ctx_##inst, 8, 8); \
|
RTIO_DEFINE(icm45686_rtio_ctx_##inst, 8, 8); \
|
||||||
SPI_DT_IODEV_DEFINE(icm45686_bus_##inst, \
|
\
|
||||||
|
COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
|
||||||
|
(SPI_DT_IODEV_DEFINE(icm45686_bus_##inst, \
|
||||||
DT_DRV_INST(inst), \
|
DT_DRV_INST(inst), \
|
||||||
SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_TRANSFER_MSB, \
|
SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_TRANSFER_MSB, \
|
||||||
0U); \
|
0U)), \
|
||||||
|
()); \
|
||||||
|
\
|
||||||
|
COND_CODE_1(DT_INST_ON_BUS(inst, i2c), \
|
||||||
|
(I2C_DT_IODEV_DEFINE(icm45686_bus_##inst, \
|
||||||
|
DT_DRV_INST(inst))), \
|
||||||
|
()); \
|
||||||
\
|
\
|
||||||
static const struct icm45686_config icm45686_cfg_##inst = { \
|
static const struct icm45686_config icm45686_cfg_##inst = { \
|
||||||
.settings = { \
|
.settings = { \
|
||||||
|
@ -414,6 +434,10 @@ static int icm45686_init(const struct device *dev)
|
||||||
.rtio = { \
|
.rtio = { \
|
||||||
.iodev = &icm45686_bus_##inst, \
|
.iodev = &icm45686_bus_##inst, \
|
||||||
.ctx = &icm45686_rtio_ctx_##inst, \
|
.ctx = &icm45686_rtio_ctx_##inst, \
|
||||||
|
COND_CODE_1(DT_INST_ON_BUS(inst, i2c), \
|
||||||
|
(.type = ICM45686_BUS_I2C), ()) \
|
||||||
|
COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
|
||||||
|
(.type = ICM45686_BUS_SPI), ()) \
|
||||||
}, \
|
}, \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
|
|
|
@ -130,10 +130,16 @@ struct icm45686_stream {
|
||||||
} data;
|
} data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum icm45686_bus_type {
|
||||||
|
ICM45686_BUS_SPI,
|
||||||
|
ICM45686_BUS_I2C,
|
||||||
|
};
|
||||||
|
|
||||||
struct icm45686_data {
|
struct icm45686_data {
|
||||||
struct {
|
struct {
|
||||||
struct rtio_iodev *iodev;
|
struct rtio_iodev *iodev;
|
||||||
struct rtio *ctx;
|
struct rtio *ctx;
|
||||||
|
enum icm45686_bus_type type;
|
||||||
} rtio;
|
} rtio;
|
||||||
/** Single-shot encoded data instance to support fetch/get API */
|
/** Single-shot encoded data instance to support fetch/get API */
|
||||||
struct icm45686_encoded_data edata;
|
struct icm45686_encoded_data edata;
|
||||||
|
|
|
@ -36,6 +36,9 @@ static inline int icm45686_bus_read(const struct device *dev,
|
||||||
rtio_sqe_prep_write(write_sqe, iodev, RTIO_PRIO_HIGH, ®, 1, NULL);
|
rtio_sqe_prep_write(write_sqe, iodev, RTIO_PRIO_HIGH, ®, 1, NULL);
|
||||||
write_sqe->flags |= RTIO_SQE_TRANSACTION;
|
write_sqe->flags |= RTIO_SQE_TRANSACTION;
|
||||||
rtio_sqe_prep_read(read_sqe, iodev, RTIO_PRIO_HIGH, buf, len, NULL);
|
rtio_sqe_prep_read(read_sqe, iodev, RTIO_PRIO_HIGH, buf, len, NULL);
|
||||||
|
if (data->rtio.type == ICM45686_BUS_I2C) {
|
||||||
|
read_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
|
||||||
|
}
|
||||||
|
|
||||||
err = rtio_submit(ctx, 2);
|
err = rtio_submit(ctx, 2);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -73,6 +76,9 @@ static inline int icm45686_bus_write(const struct device *dev,
|
||||||
rtio_sqe_prep_write(write_reg_sqe, iodev, RTIO_PRIO_HIGH, ®, 1, NULL);
|
rtio_sqe_prep_write(write_reg_sqe, iodev, RTIO_PRIO_HIGH, ®, 1, NULL);
|
||||||
write_reg_sqe->flags |= RTIO_SQE_TRANSACTION;
|
write_reg_sqe->flags |= RTIO_SQE_TRANSACTION;
|
||||||
rtio_sqe_prep_write(write_buf_sqe, iodev, RTIO_PRIO_HIGH, buf, len, NULL);
|
rtio_sqe_prep_write(write_buf_sqe, iodev, RTIO_PRIO_HIGH, buf, len, NULL);
|
||||||
|
if (data->rtio.type == ICM45686_BUS_I2C) {
|
||||||
|
write_buf_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
err = rtio_submit(ctx, 2);
|
err = rtio_submit(ctx, 2);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
|
@ -204,6 +204,9 @@ static void icm45686_handle_event_actions(struct rtio *ctx,
|
||||||
(buf->header.fifo_count *
|
(buf->header.fifo_count *
|
||||||
sizeof(struct icm45686_encoded_fifo_payload)),
|
sizeof(struct icm45686_encoded_fifo_payload)),
|
||||||
NULL);
|
NULL);
|
||||||
|
if (data->rtio.type == ICM45686_BUS_I2C) {
|
||||||
|
data_rd_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
|
||||||
|
}
|
||||||
data_rd_sqe->flags |= RTIO_SQE_CHAINED;
|
data_rd_sqe->flags |= RTIO_SQE_CHAINED;
|
||||||
|
|
||||||
} else if (should_flush_fifo(read_cfg, int_status)) {
|
} else if (should_flush_fifo(read_cfg, int_status)) {
|
||||||
|
@ -232,6 +235,9 @@ static void icm45686_handle_event_actions(struct rtio *ctx,
|
||||||
write_reg,
|
write_reg,
|
||||||
sizeof(write_reg),
|
sizeof(write_reg),
|
||||||
NULL);
|
NULL);
|
||||||
|
if (data->rtio.type == ICM45686_BUS_I2C) {
|
||||||
|
write_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP;
|
||||||
|
}
|
||||||
write_sqe->flags |= RTIO_SQE_CHAINED;
|
write_sqe->flags |= RTIO_SQE_CHAINED;
|
||||||
|
|
||||||
} else if (should_read_data(read_cfg, int_status)) {
|
} else if (should_read_data(read_cfg, int_status)) {
|
||||||
|
@ -269,6 +275,9 @@ static void icm45686_handle_event_actions(struct rtio *ctx,
|
||||||
buf->payload.buf,
|
buf->payload.buf,
|
||||||
sizeof(buf->payload.buf),
|
sizeof(buf->payload.buf),
|
||||||
NULL);
|
NULL);
|
||||||
|
if (data->rtio.type == ICM45686_BUS_I2C) {
|
||||||
|
read_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
|
||||||
|
}
|
||||||
read_sqe->flags |= RTIO_SQE_CHAINED;
|
read_sqe->flags |= RTIO_SQE_CHAINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,6 +327,9 @@ static void icm45686_event_handler(const struct device *dev)
|
||||||
wr_data,
|
wr_data,
|
||||||
sizeof(wr_data),
|
sizeof(wr_data),
|
||||||
NULL);
|
NULL);
|
||||||
|
if (data->rtio.type == ICM45686_BUS_I2C) {
|
||||||
|
write_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP;
|
||||||
|
}
|
||||||
rtio_submit(data->rtio.ctx, 0);
|
rtio_submit(data->rtio.ctx, 0);
|
||||||
|
|
||||||
data->stream.settings.enabled.drdy = false;
|
data->stream.settings.enabled.drdy = false;
|
||||||
|
@ -375,8 +387,12 @@ static void icm45686_event_handler(const struct device *dev)
|
||||||
&data->stream.data.int_status,
|
&data->stream.data.int_status,
|
||||||
1,
|
1,
|
||||||
NULL);
|
NULL);
|
||||||
|
if (data->rtio.type == ICM45686_BUS_I2C) {
|
||||||
|
read_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
|
||||||
|
}
|
||||||
read_sqe->flags |= RTIO_SQE_CHAINED;
|
read_sqe->flags |= RTIO_SQE_CHAINED;
|
||||||
|
|
||||||
|
|
||||||
/** Preemptively read FIFO count so we can decide on the next callback
|
/** Preemptively read FIFO count so we can decide on the next callback
|
||||||
* how much FIFO data we'd read (if needed).
|
* how much FIFO data we'd read (if needed).
|
||||||
*/
|
*/
|
||||||
|
@ -395,6 +411,9 @@ static void icm45686_event_handler(const struct device *dev)
|
||||||
(uint8_t *)&data->stream.data.fifo_count,
|
(uint8_t *)&data->stream.data.fifo_count,
|
||||||
2,
|
2,
|
||||||
NULL);
|
NULL);
|
||||||
|
if (data->rtio.type == ICM45686_BUS_I2C) {
|
||||||
|
read_fifo_ct_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
|
||||||
|
}
|
||||||
read_fifo_ct_sqe->flags |= RTIO_SQE_CHAINED;
|
read_fifo_ct_sqe->flags |= RTIO_SQE_CHAINED;
|
||||||
|
|
||||||
rtio_sqe_prep_callback_no_cqe(complete_sqe,
|
rtio_sqe_prep_callback_no_cqe(complete_sqe,
|
||||||
|
|
30
dts/bindings/sensor/invensense,icm45686-i2c.yaml
Normal file
30
dts/bindings/sensor/invensense,icm45686-i2c.yaml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# Copyright (c) 2025 Croxel Inc.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
description: |
|
||||||
|
ICM45686 High-precision 6-axis motion tracking device
|
||||||
|
When setting the accel-pm, accel-range, accel-odr, gyro-pm, gyro-range,
|
||||||
|
gyro-odr properties in a .dts or .dtsi file you may include icm45686.h
|
||||||
|
and use the macros defined there.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
#include <zephyr/dt-bindings/sensor/icm45686.h>
|
||||||
|
|
||||||
|
&i2c0 {
|
||||||
|
...
|
||||||
|
|
||||||
|
icm42688: icm45686@68 {
|
||||||
|
...
|
||||||
|
|
||||||
|
accel-pwr-mode = <ICM45686_DT_ACCEL_LN>;
|
||||||
|
accel-fs = <ICM45686_DT_ACCEL_FS_32>;
|
||||||
|
accel-odr = <ICM45686_DT_ACCEL_ODR_800>;
|
||||||
|
gyro-pwr-mode= <ICM45686_DT_GYRO_LN>;
|
||||||
|
gyro-fs = <ICM45686_DT_GYRO_FS_4000>;
|
||||||
|
gyro-odr = <ICM45686_DT_GYRO_ODR_800>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
compatible: "invensense,icm45686"
|
||||||
|
|
||||||
|
include: ["i2c-device.yaml", "invensense,icm45686-common.yaml"]
|
Loading…
Add table
Add a link
Reference in a new issue