Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions drivers/sensor/tdk/icm45686/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ zephyr_library()
zephyr_library_include_directories(.)
zephyr_library_sources(
icm45686.c
icm45686_bus.c
)
zephyr_library_sources_ifdef(CONFIG_SENSOR_ASYNC_API
icm45686_decoder.c
Expand Down
82 changes: 34 additions & 48 deletions drivers/sensor/tdk/icm45686/icm45686.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,16 @@ LOG_MODULE_REGISTER(ICM45686, CONFIG_SENSOR_LOG_LEVEL);

static inline int reg_write(const struct device *dev, uint8_t reg, uint8_t val)
{
return icm45686_bus_write(dev, reg, &val, 1);
struct icm45686_data *data = dev->data;

return icm45686_reg_write_rtio(&data->bus, reg, &val, 1);
}

static inline int reg_read(const struct device *dev, uint8_t reg, uint8_t *val)
{
return icm45686_bus_read(dev, reg, val, 1);
struct icm45686_data *data = dev->data;

return icm45686_reg_read_rtio(&data->bus, reg | REG_READ_BIT, val, 1);
}

static int icm45686_sample_fetch(const struct device *dev,
Expand All @@ -50,10 +54,9 @@ static int icm45686_sample_fetch(const struct device *dev,
return -ENOTSUP;
}

err = icm45686_bus_read(dev,
REG_ACCEL_DATA_X1_UI,
edata->payload.buf,
sizeof(edata->payload.buf));
err = icm45686_reg_read_rtio(&data->bus, REG_ACCEL_DATA_X1_UI | REG_READ_BIT,
edata->payload.buf,
sizeof(edata->payload.buf));

LOG_HEXDUMP_DBG(edata->payload.buf,
sizeof(edata->payload.buf),
Expand Down Expand Up @@ -161,14 +164,14 @@ static inline void icm45686_submit_one_shot(const struct device *dev,
uint32_t buf_len;
struct icm45686_encoded_data *edata;
struct icm45686_data *data = dev->data;
struct rtio_sqe *read_sqe;

err = rtio_sqe_rx_buf(iodev_sqe, min_buf_len, min_buf_len, &buf, &buf_len);
if (err != 0) {
LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len);
rtio_iodev_sqe_err(iodev_sqe, err);
return;
}

edata = (struct icm45686_encoded_data *)buf;

err = icm45686_encode(dev, channels, num_channels, buf);
Expand All @@ -178,45 +181,28 @@ static inline void icm45686_submit_one_shot(const struct device *dev,
return;
}

struct rtio_sqe *write_sqe = rtio_sqe_acquire(data->rtio.ctx);
struct rtio_sqe *read_sqe = rtio_sqe_acquire(data->rtio.ctx);
struct rtio_sqe *complete_sqe = rtio_sqe_acquire(data->rtio.ctx);

if (!write_sqe || !read_sqe || !complete_sqe) {
LOG_ERR("Failed to acquire RTIO SQEs");
err = icm45686_prep_reg_read_rtio_async(&data->bus, REG_ACCEL_DATA_X1_UI | REG_READ_BIT,
edata->payload.buf, sizeof(edata->payload.buf),
&read_sqe);
if (err < 0) {
LOG_ERR("Fail to prepare read: %d", err);
rtio_iodev_sqe_err(iodev_sqe, -ENOMEM);
return;
}

uint8_t val = REG_ACCEL_DATA_X1_UI | REG_READ_BIT;

rtio_sqe_prep_tiny_write(write_sqe,
data->rtio.iodev,
RTIO_PRIO_HIGH,
&val,
1,
NULL);
write_sqe->flags |= RTIO_SQE_TRANSACTION;

rtio_sqe_prep_read(read_sqe,
data->rtio.iodev,
RTIO_PRIO_HIGH,
edata->payload.buf,
sizeof(edata->payload.buf),
NULL);
if (data->rtio.type == ICM45686_BUS_I2C) {
read_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
} else if (data->rtio.type == ICM45686_BUS_I3C) {
read_sqe->iodev_flags |= RTIO_IODEV_I3C_STOP | RTIO_IODEV_I3C_RESTART;
}
read_sqe->flags |= RTIO_SQE_CHAINED;

rtio_sqe_prep_callback_no_cqe(complete_sqe,
icm45686_complete_result,
(void *)dev,
struct rtio_sqe *complete_sqe = rtio_sqe_acquire(data->bus.rtio.ctx);

if (!complete_sqe) {
LOG_ERR("Failed to acquire complete read-sqe");
rtio_sqe_drop_all(data->bus.rtio.ctx);
rtio_iodev_sqe_err(iodev_sqe, -ENOMEM);
return;
}
rtio_sqe_prep_callback_no_cqe(complete_sqe, icm45686_complete_result, (void *)dev,
iodev_sqe);

rtio_submit(data->rtio.ctx, 0);
rtio_submit(data->bus.rtio.ctx, 0);
}

static void icm45686_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe)
Expand Down Expand Up @@ -256,13 +242,13 @@ static int icm45686_init(const struct device *dev)
int err;

#if CONFIG_SPI_RTIO
if ((data->rtio.type == ICM45686_BUS_SPI) && !spi_is_ready_iodev(data->rtio.iodev)) {
if (data->bus.rtio.type == ICM45686_BUS_SPI && !spi_is_ready_iodev(data->bus.rtio.iodev)) {
LOG_ERR("Bus is not ready");
return -ENODEV;
}
#endif
#if CONFIG_I2C_RTIO
if ((data->rtio.type == ICM45686_BUS_I2C) && !i2c_is_ready_iodev(data->rtio.iodev)) {
if (data->bus.rtio.type == ICM45686_BUS_I2C && !i2c_is_ready_iodev(data->bus.rtio.iodev)) {
LOG_ERR("Bus is not ready");
return -ENODEV;
}
Expand All @@ -271,7 +257,7 @@ static int icm45686_init(const struct device *dev)
/** Soft-reset sensor to restore config to defaults,
* unless it's already handled by I3C initialization.
*/
if (data->rtio.type != ICM45686_BUS_I3C) {
if (data->bus.rtio.type != ICM45686_BUS_I3C) {
err = reg_write(dev, REG_MISC2, REG_MISC2_SOFT_RST(1));
if (err) {
LOG_ERR("Failed to write soft-reset: %d", err);
Expand Down Expand Up @@ -352,8 +338,8 @@ static int icm45686_init(const struct device *dev)
REG_IPREG_SYS1_REG_172_GYRO_LPFBW_SEL(
cfg->settings.gyro.lpf));

err = icm45686_bus_write(dev, REG_IREG_ADDR_15_8, gyro_lpf_write_array,
sizeof(gyro_lpf_write_array));
err = icm45686_reg_write_rtio(&data->bus, REG_IREG_ADDR_15_8, gyro_lpf_write_array,
sizeof(gyro_lpf_write_array));
if (err) {
LOG_ERR("Failed to set Gyro BW settings: %d", err);
return err;
Expand All @@ -370,8 +356,8 @@ static int icm45686_init(const struct device *dev)
REG_IPREG_SYS2_REG_131_ACCEL_LPFBW_SEL(
cfg->settings.accel.lpf));

err = icm45686_bus_write(dev, REG_IREG_ADDR_15_8, accel_lpf_write_array,
sizeof(accel_lpf_write_array));
err = icm45686_reg_write_rtio(&data->bus, REG_IREG_ADDR_15_8, accel_lpf_write_array,
sizeof(accel_lpf_write_array));
if (err) {
LOG_ERR("Failed to set Accel BW settings: %d", err);
return err;
Expand Down Expand Up @@ -408,7 +394,7 @@ static int icm45686_init(const struct device *dev)

#define ICM45686_INIT(inst) \
\
RTIO_DEFINE(icm45686_rtio_ctx_##inst, 8, 8); \
RTIO_DEFINE(icm45686_rtio_ctx_##inst, 32, 32); \
\
COND_CODE_1(DT_INST_ON_BUS(inst, i3c), \
(I3C_DT_IODEV_DEFINE(icm45686_bus_##inst, \
Expand Down Expand Up @@ -448,7 +434,7 @@ static int icm45686_init(const struct device *dev)
.accel_fs = DT_INST_PROP(inst, accel_fs), \
.gyro_fs = DT_INST_PROP(inst, gyro_fs), \
}, \
.rtio = { \
.bus.rtio = { \
.iodev = &icm45686_bus_##inst, \
.ctx = &icm45686_rtio_ctx_##inst, \
COND_CODE_1(DT_INST_ON_BUS(inst, i3c), \
Expand Down
24 changes: 4 additions & 20 deletions drivers/sensor/tdk/icm45686/icm45686.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <zephyr/drivers/i3c.h>
#endif

#include "icm45686_bus.h"

struct icm45686_encoded_payload {
union {
uint8_t buf[14];
Expand Down Expand Up @@ -105,7 +107,7 @@ struct icm45686_stream {
struct gpio_callback cb;
const struct device *dev;
struct rtio_iodev_sqe *iodev_sqe;
atomic_t in_progress;
atomic_t state;
struct {
struct {
bool drdy : 1;
Expand All @@ -124,7 +126,6 @@ struct icm45686_stream {
struct {
uint64_t timestamp;
uint8_t int_status;
uint16_t fifo_count;
struct {
bool drdy : 1;
bool fifo_ths : 1;
Expand All @@ -133,25 +134,8 @@ struct icm45686_stream {
} data;
};

enum icm45686_bus_type {
ICM45686_BUS_SPI,
ICM45686_BUS_I2C,
ICM45686_BUS_I3C,
};

struct icm45686_data {
struct {
struct rtio_iodev *iodev;
struct rtio *ctx;
enum icm45686_bus_type type;
/** Required to support In-band Interrupts */
#if DT_HAS_COMPAT_ON_BUS_STATUS_OKAY(invensense_icm45686, i3c)
struct {
struct i3c_device_desc *desc;
const struct i3c_device_id id;
} i3c;
#endif
} rtio;
struct icm45686_bus bus;
/** Single-shot encoded data instance to support fetch/get API */
struct icm45686_encoded_data edata;
#if defined(CONFIG_ICM45686_TRIGGER)
Expand Down
134 changes: 134 additions & 0 deletions drivers/sensor/tdk/icm45686/icm45686_bus.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* Copyright (c) 2025 Croxel, Inc.
* Copyright (c) 2025 CogniPilot Foundation
*
* SPDX-License-Identifier: Apache-2.0
*/

#include "icm45686_bus.h"

int icm45686_prep_reg_read_rtio_async(const struct icm45686_bus *bus,
uint8_t reg, uint8_t *buf, size_t size,
struct rtio_sqe **out)
{
struct rtio *ctx = bus->rtio.ctx;
struct rtio_iodev *iodev = bus->rtio.iodev;
struct rtio_sqe *write_reg_sqe = rtio_sqe_acquire(ctx);
struct rtio_sqe *read_buf_sqe = rtio_sqe_acquire(ctx);

if (!write_reg_sqe || !read_buf_sqe) {
rtio_sqe_drop_all(ctx);
return -ENOMEM;
}

rtio_sqe_prep_tiny_write(write_reg_sqe, iodev, RTIO_PRIO_NORM, &reg, 1, NULL);
write_reg_sqe->flags |= RTIO_SQE_TRANSACTION;
rtio_sqe_prep_read(read_buf_sqe, iodev, RTIO_PRIO_NORM, buf, size, NULL);
if (bus->rtio.type == ICM45686_BUS_I2C) {
read_buf_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
} else if (bus->rtio.type == ICM45686_BUS_I3C) {
read_buf_sqe->iodev_flags |= RTIO_IODEV_I3C_STOP | RTIO_IODEV_I3C_RESTART;
} else {
/* SPI does not require setting additional flags to the read-buf SQE */
}

/** Send back last SQE so it can be concatenated later. */
if (out) {
*out = read_buf_sqe;
}

return 2;
}

int icm45686_prep_reg_write_rtio_async(const struct icm45686_bus *bus,
uint8_t reg, const uint8_t *buf, size_t size,
struct rtio_sqe **out)
{
struct rtio *ctx = bus->rtio.ctx;
struct rtio_iodev *iodev = bus->rtio.iodev;
struct rtio_sqe *write_reg_sqe = rtio_sqe_acquire(ctx);
struct rtio_sqe *write_buf_sqe = rtio_sqe_acquire(ctx);

if (!write_reg_sqe || !write_buf_sqe) {
rtio_sqe_drop_all(ctx);
return -ENOMEM;
}

/** More than 7 won't work with tiny-write */
if (size > 7) {
return -EINVAL;
}

rtio_sqe_prep_tiny_write(write_reg_sqe, iodev, RTIO_PRIO_NORM, &reg, 1, NULL);
write_reg_sqe->flags |= RTIO_SQE_TRANSACTION;
rtio_sqe_prep_tiny_write(write_buf_sqe, iodev, RTIO_PRIO_NORM, buf, size, NULL);
if (bus->rtio.type == ICM45686_BUS_I2C) {
write_buf_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP;
} else if (bus->rtio.type == ICM45686_BUS_I3C) {
write_buf_sqe->iodev_flags |= RTIO_IODEV_I3C_STOP;
} else {
/* SPI does not require setting additional flags to the write-buf SQE */
}

/** Send back last SQE so it can be concatenated later. */
if (out) {
*out = write_buf_sqe;
}

return 2;
}

int icm45686_reg_read_rtio(const struct icm45686_bus *bus, uint8_t start, uint8_t *buf, int size)
{
struct rtio *ctx = bus->rtio.ctx;
struct rtio_cqe *cqe;
int ret;

ret = icm45686_prep_reg_read_rtio_async(bus, start, buf, size, NULL);
if (ret < 0) {
return ret;
}

ret = rtio_submit(ctx, ret);
if (ret) {
return ret;
}

do {
cqe = rtio_cqe_consume(ctx);
if (cqe != NULL) {
ret = cqe->result;
rtio_cqe_release(ctx, cqe);
}
} while (cqe != NULL);

return ret;
}

int icm45686_reg_write_rtio(const struct icm45686_bus *bus, uint8_t reg, const uint8_t *buf,
int size)
{
struct rtio *ctx = bus->rtio.ctx;
struct rtio_cqe *cqe;
int ret;

ret = icm45686_prep_reg_write_rtio_async(bus, reg, buf, size, NULL);
if (ret < 0) {
return ret;
}

ret = rtio_submit(ctx, ret);
if (ret) {
return ret;
}

do {
cqe = rtio_cqe_consume(ctx);
if (cqe != NULL) {
ret = cqe->result;
rtio_cqe_release(ctx, cqe);
}
} while (cqe != NULL);

return ret;
}
Loading
Loading