Skip to content

Commit 240bd24

Browse files
committed
rtio: add helper function rtio_read_transaction()
Add a helper function that constructs a rtio SQE chain with the purpose to perform a bus read operation on a list of registers. Usage: uint8_t regs_list[] = { reg_addr1, reg_addr2. ... } struct rtio_reg_buf rbuf[] = {{mem_addr_1, mem_len_1}, {mem_addr_2, mem_len_2}, ... }; rtio_read_transaction(dev, regs_list, ARRAY_SIZE(regs_list), BUS_SPI, rbuf, sqe, iodev, rtio, op_cb); Signed-off-by: Armando Visconti <armando.visconti@st.com>
1 parent 8ab712a commit 240bd24

File tree

3 files changed

+175
-56
lines changed

3 files changed

+175
-56
lines changed

drivers/sensor/st/lsm6dsv16x/lsm6dsv16x.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,9 @@ struct lsm6dsv16x_data {
171171
uint16_t accel_batch_odr : 4;
172172
uint16_t gyro_batch_odr : 4;
173173
uint16_t temp_batch_odr : 2;
174-
uint16_t bus_type : 2; /* I2C is 0, SPI is 1, I3C is 2 */
175174
uint16_t sflp_batch_odr : 3;
176-
uint16_t reserved : 1;
175+
uint16_t reserved : 3;
176+
rtio_bus_type bus_type;
177177
int32_t gbias_x_udps;
178178
int32_t gbias_y_udps;
179179
int32_t gbias_z_udps;
@@ -206,10 +206,6 @@ struct lsm6dsv16x_data {
206206
};
207207

208208
#ifdef CONFIG_LSM6DSV16X_STREAM
209-
#define BUS_I2C 0
210-
#define BUS_SPI 1
211-
#define BUS_I3C 2
212-
213209
static inline uint8_t lsm6dsv16x_bus_reg(struct lsm6dsv16x_data *data, uint8_t x)
214210
{
215211
return (data->bus_type == BUS_SPI) ? x | 0x80 : x;

drivers/sensor/st/lsm6dsv16x/lsm6dsv16x_rtio_stream.c

Lines changed: 49 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -16,48 +16,6 @@
1616
#include <zephyr/logging/log.h>
1717
LOG_MODULE_DECLARE(LSM6DSV16X_RTIO);
1818

19-
/*
20-
* Create a chain of SQEs representing a bus transaction to read a reg.
21-
* The RTIO-enabled bus driver will:
22-
*
23-
* - write "reg" address
24-
* - read "len" data bytes into "buf".
25-
* - call complete_op callback
26-
*
27-
* If drdy_xl is active it reads XL data (6 bytes) from LSM6DSV16X_OUTX_L_A reg.
28-
*/
29-
static void lsm6dsv16x_rtio_rw_transaction(const struct device *dev, uint8_t reg,
30-
uint8_t *buf, uint32_t len,
31-
rtio_callback_t complete_op_cb)
32-
{
33-
struct lsm6dsv16x_data *lsm6dsv16x = dev->data;
34-
struct rtio *rtio = lsm6dsv16x->rtio_ctx;
35-
struct rtio_iodev *iodev = lsm6dsv16x->iodev;
36-
struct rtio_sqe *write_addr = rtio_sqe_acquire(rtio);
37-
struct rtio_sqe *read_reg = rtio_sqe_acquire(rtio);
38-
struct rtio_sqe *complete_op = rtio_sqe_acquire(rtio);
39-
struct rtio_iodev_sqe *sqe = lsm6dsv16x->streaming_sqe;
40-
uint8_t reg_bus = lsm6dsv16x_bus_reg(lsm6dsv16x, reg);
41-
42-
/* check we have been able to acquire sqe */
43-
if (write_addr == NULL || read_reg == NULL || complete_op == NULL) {
44-
return;
45-
}
46-
47-
rtio_sqe_prep_tiny_write(write_addr, iodev, RTIO_PRIO_NORM, &reg_bus, 1, NULL);
48-
write_addr->flags = RTIO_SQE_TRANSACTION;
49-
rtio_sqe_prep_read(read_reg, iodev, RTIO_PRIO_NORM, buf, len, NULL);
50-
read_reg->flags = RTIO_SQE_CHAINED;
51-
if (lsm6dsv16x->bus_type == BUS_I2C) {
52-
read_reg->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
53-
} else if (lsm6dsv16x->bus_type == BUS_I3C) {
54-
read_reg->iodev_flags |= RTIO_IODEV_I3C_STOP | RTIO_IODEV_I3C_RESTART;
55-
}
56-
57-
rtio_sqe_prep_callback_no_cqe(complete_op, complete_op_cb, (void *)dev, sqe);
58-
rtio_submit(rtio, 0);
59-
}
60-
6119
static void lsm6dsv16x_config_drdy(const struct device *dev, struct trigger_config trig_cfg)
6220
{
6321
const struct lsm6dsv16x_config *config = dev->config;
@@ -500,6 +458,9 @@ static void lsm6dsv16x_read_fifo_cb(struct rtio *r, const struct rtio_sqe *sqe,
500458
read_buf = buf + sizeof(hdr);
501459
buf_avail = buf_len - sizeof(hdr);
502460

461+
uint8_t fifo_regs[] = { LSM6DSV16X_FIFO_DATA_OUT_TAG, };
462+
struct rtio_reg_buf rbuf[] = { {read_buf, buf_avail}, };
463+
503464
/*
504465
* Prepare rtio enabled bus to read all fifo_count entries from
505466
* LSM6DSV16X_FIFO_DATA_OUT_TAG. Then lsm6dsv16x_complete_op_cb
@@ -515,8 +476,15 @@ static void lsm6dsv16x_read_fifo_cb(struct rtio *r, const struct rtio_sqe *sqe,
515476
* lsm6dsv16x_fifo_out_raw_get(&dev_ctx, &f_data);
516477
* }
517478
*/
518-
lsm6dsv16x_rtio_rw_transaction(dev, LSM6DSV16X_FIFO_DATA_OUT_TAG,
519-
read_buf, buf_avail, lsm6dsv16x_complete_op_cb);
479+
rtio_read_transaction(dev,
480+
fifo_regs,
481+
ARRAY_SIZE(fifo_regs),
482+
lsm6dsv16x->bus_type,
483+
rbuf,
484+
lsm6dsv16x->streaming_sqe,
485+
lsm6dsv16x->iodev,
486+
lsm6dsv16x->rtio_ctx,
487+
lsm6dsv16x_complete_op_cb);
520488
}
521489

522490
/*
@@ -643,6 +611,9 @@ static void lsm6dsv16x_read_status_cb(struct rtio *r, const struct rtio_sqe *sqe
643611
memcpy(buf, &hdr, sizeof(hdr));
644612
read_buf = (uint8_t *)&((struct lsm6dsv16x_rtio_data *)buf)->acc[0];
645613

614+
uint8_t fifo_regs[] = { LSM6DSV16X_OUTX_L_A, };
615+
struct rtio_reg_buf rbuf[] = { {read_buf, 6}, };
616+
646617
/*
647618
* Prepare rtio enabled bus to read LSM6DSV16X_OUTX_L_A register
648619
* where accelerometer data is available.
@@ -654,8 +625,15 @@ static void lsm6dsv16x_read_status_cb(struct rtio *r, const struct rtio_sqe *sqe
654625
*
655626
* lsm6dsv16x_acceleration_raw_get(&dev_ctx, accel_raw);
656627
*/
657-
lsm6dsv16x_rtio_rw_transaction(dev, LSM6DSV16X_OUTX_L_A,
658-
read_buf, 6, lsm6dsv16x_complete_op_cb);
628+
rtio_read_transaction(dev,
629+
fifo_regs,
630+
ARRAY_SIZE(fifo_regs),
631+
lsm6dsv16x->bus_type,
632+
rbuf,
633+
lsm6dsv16x->streaming_sqe,
634+
lsm6dsv16x->iodev,
635+
lsm6dsv16x->rtio_ctx,
636+
lsm6dsv16x_complete_op_cb);
659637
}
660638
}
661639

@@ -711,6 +689,9 @@ void lsm6dsv16x_stream_irq_handler(const struct device *dev)
711689
#endif
712690
lsm6dsv16x->fifo_status[0] = lsm6dsv16x->fifo_status[1] = 0;
713691

692+
uint8_t fifo_regs[] = { LSM6DSV16X_FIFO_STATUS1, };
693+
struct rtio_reg_buf rbuf[] = { {lsm6dsv16x->fifo_status, 2}, };
694+
714695
/*
715696
* Prepare rtio enabled bus to read LSM6DSV16X_FIFO_STATUS1 and
716697
* LSM6DSV16X_FIFO_STATUS2 registers where FIFO threshold condition and
@@ -723,8 +704,16 @@ void lsm6dsv16x_stream_irq_handler(const struct device *dev)
723704
*
724705
* lsm6dsv16x_fifo_status_get(&dev_ctx, &fifo_status);
725706
*/
726-
lsm6dsv16x_rtio_rw_transaction(dev, LSM6DSV16X_FIFO_STATUS1,
727-
lsm6dsv16x->fifo_status, 2, lsm6dsv16x_read_fifo_cb);
707+
rtio_read_transaction(dev,
708+
fifo_regs,
709+
ARRAY_SIZE(fifo_regs),
710+
lsm6dsv16x->bus_type,
711+
rbuf,
712+
lsm6dsv16x->streaming_sqe,
713+
lsm6dsv16x->iodev,
714+
lsm6dsv16x->rtio_ctx,
715+
lsm6dsv16x_read_fifo_cb);
716+
728717
#if LSM6DSVXXX_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
729718
}
730719
#endif
@@ -734,6 +723,9 @@ void lsm6dsv16x_stream_irq_handler(const struct device *dev)
734723
if (lsm6dsv16x->trig_cfg.int_drdy) {
735724
lsm6dsv16x->status = 0;
736725

726+
uint8_t fifo_regs[] = { LSM6DSV16X_STATUS_REG, };
727+
struct rtio_reg_buf rbuf[] = { {&lsm6dsv16x->status, 1}, };
728+
737729
/*
738730
* Prepare rtio enabled bus to read LSM6DSV16X_STATUS_REG register
739731
* where accelerometer and gyroscope data ready status is available.
@@ -745,7 +737,14 @@ void lsm6dsv16x_stream_irq_handler(const struct device *dev)
745737
*
746738
* lsm6dsv16x_flag_data_ready_get(&dev_ctx, &drdy);
747739
*/
748-
lsm6dsv16x_rtio_rw_transaction(dev, LSM6DSV16X_STATUS_REG,
749-
&lsm6dsv16x->status, 1, lsm6dsv16x_read_status_cb);
740+
rtio_read_transaction(dev,
741+
fifo_regs,
742+
ARRAY_SIZE(fifo_regs),
743+
lsm6dsv16x->bus_type,
744+
rbuf,
745+
lsm6dsv16x->streaming_sqe,
746+
lsm6dsv16x->iodev,
747+
lsm6dsv16x->rtio_ctx,
748+
lsm6dsv16x_read_status_cb);
750749
}
751750
}

include/zephyr/rtio/rtio.h

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,45 @@ struct rtio {
459459
struct mpsc cq;
460460
};
461461

462+
/**
463+
* @brief A structure to describe a list of not-consecutive memory chunks
464+
* for RTIO operations.
465+
*/
466+
struct rtio_reg_buf {
467+
/* Valid pointer to a data buffer */
468+
void *bufp;
469+
470+
/* Length of the buffer in bytes */
471+
size_t len;
472+
};
473+
474+
/**
475+
* @brief bus type
476+
*
477+
* RTIO works on top of a RTIO enabled bus, Some RTIO ops require
478+
* a bus-related handling (e.g. rtio_read_transaction)
479+
*/
480+
typedef enum {
481+
BUS_I2C,
482+
BUS_SPI,
483+
BUS_I3C,
484+
} rtio_bus_type;
485+
486+
static inline bool rtio_is_spi(rtio_bus_type bus_type)
487+
{
488+
return (bus_type == BUS_SPI);
489+
}
490+
491+
static inline bool rtio_is_i2c(rtio_bus_type bus_type)
492+
{
493+
return (bus_type == BUS_I2C);
494+
}
495+
496+
static inline bool rtio_is_i3c(rtio_bus_type bus_type)
497+
{
498+
return (bus_type == BUS_I3C);
499+
}
500+
462501
/** The memory partition associated with all RTIO context information */
463502
extern struct k_mem_partition rtio_partition;
464503

@@ -1674,6 +1713,91 @@ static inline int z_impl_rtio_submit(struct rtio *r, uint32_t wait_count)
16741713
}
16751714
#endif /* CONFIG_RTIO_SUBMIT_SEM */
16761715

1716+
/*
1717+
* @brief Create a chain of SQEs representing a bus transaction to read a reg.
1718+
*
1719+
* The RTIO-enabled bus driver is isnstrumented to perform bus read ops
1720+
* for each register in the list.
1721+
*
1722+
* Usage:
1723+
*
1724+
* uint8_t regs_list[] = { reg_addr1, reg_addr2. ... }
1725+
* struct rtio_reg_buf rbuf[] = {{mem_addr_1, mem_len_1},
1726+
* {mem_addr_2, mem_len_2},
1727+
* ...
1728+
* };
1729+
*
1730+
* rtio_read_transaction(dev,
1731+
* regs_list,
1732+
* ARRAY_SIZE(regs_list),
1733+
* BUS_SPI,
1734+
* rbuf,
1735+
* sqe,
1736+
* iodev,
1737+
* rtio,
1738+
* op_cb);
1739+
*
1740+
* @param rtio_bus_type bus type (i2c, spi, i3c)
1741+
* @param rtio_reg_buf buffer of memory chunks
1742+
* @param iodev_sqe IODEV submission for the await op
1743+
* @param iodev IO device
1744+
* @param r RTIO context
1745+
* @param rtio_callback_t callback routine at the end of op
1746+
*/
1747+
static inline void rtio_read_transaction(const struct device *dev,
1748+
uint8_t *regs,
1749+
uint8_t regs_num,
1750+
rtio_bus_type bus_type,
1751+
struct rtio_reg_buf *buf,
1752+
struct rtio_iodev_sqe *iodev_sqe,
1753+
struct rtio_iodev *iodev,
1754+
struct rtio *r,
1755+
rtio_callback_t complete_op_cb)
1756+
{
1757+
struct rtio_sqe *write_addr;
1758+
struct rtio_sqe *read_reg;
1759+
struct rtio_sqe *complete_op;
1760+
uint8_t i;
1761+
1762+
for (i = 0; i < regs_num; i++) {
1763+
1764+
write_addr = rtio_sqe_acquire(r);
1765+
read_reg = rtio_sqe_acquire(r);
1766+
1767+
if (write_addr == NULL || read_reg == NULL) {
1768+
rtio_iodev_sqe_err(iodev_sqe, -ENOMEM);
1769+
rtio_sqe_drop_all(r);
1770+
return;
1771+
}
1772+
1773+
if (rtio_is_spi(bus_type)) {
1774+
regs[i] |= 0x80; /* mark the SPI read transaction */
1775+
}
1776+
1777+
rtio_sqe_prep_tiny_write(write_addr, iodev, RTIO_PRIO_NORM, &regs[i], 1, NULL);
1778+
write_addr->flags = RTIO_SQE_TRANSACTION;
1779+
rtio_sqe_prep_read(read_reg, iodev, RTIO_PRIO_NORM, buf[i].bufp, buf[i].len, NULL);
1780+
read_reg->flags = RTIO_SQE_CHAINED;
1781+
1782+
if (rtio_is_i2c(bus_type)) {
1783+
read_reg->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
1784+
} else if (rtio_is_i3c(bus_type)) {
1785+
read_reg->iodev_flags |= RTIO_IODEV_I3C_STOP | RTIO_IODEV_I3C_RESTART;
1786+
}
1787+
}
1788+
1789+
complete_op = rtio_sqe_acquire(r);
1790+
if (complete_op == NULL) {
1791+
rtio_iodev_sqe_err(iodev_sqe, -ENOMEM);
1792+
rtio_sqe_drop_all(r);
1793+
return;
1794+
}
1795+
1796+
rtio_sqe_prep_callback_no_cqe(complete_op, complete_op_cb, (void *)dev, iodev_sqe);
1797+
1798+
rtio_submit(r, 0);
1799+
}
1800+
16771801
/**
16781802
* @}
16791803
*/

0 commit comments

Comments
 (0)