diff --git a/drivers/spi/spi_rtio.c b/drivers/spi/spi_rtio.c index 48460cb2ffab6ec..d78a27e29755bea 100644 --- a/drivers/spi/spi_rtio.c +++ b/drivers/spi/spi_rtio.c @@ -14,6 +14,165 @@ const struct rtio_iodev_api spi_iodev_api = { .submit = spi_iodev_submit, }; + +/** + * @brief Copy the tx_bufs and rx_bufs into a set of RTIO requests + * + * @param[in] r rtio context + * @param[in] iodev iodev to transceive with + * @param[in] tx_bufs transmit buffer set + * @param[in] rx_bufs receive buffer set + * @param[out] last_sqe last sqe submitted, NULL if not enough memory + * + * @retval Number of submission queue entries + * @retval -ENOMEM out of memory + */ +int spi_rtio_copy(struct rtio *r, + struct rtio_iodev *iodev, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, + struct rtio_sqe **last_sqe) +{ + int ret = 0; + size_t tx_count = tx_bufs ? tx_bufs->count : 0; + size_t rx_count = rx_bufs ? rx_bufs->count : 0; + + uint32_t tx = 0, tx_len = 0; + uint32_t rx = 0, rx_len = 0; + uint8_t *tx_buf, *rx_buf; + + struct rtio_sqe *sqe = NULL; + + if (tx < tx_count) { + tx_buf = tx_bufs->buffers[tx].buf; + tx_len = tx_bufs->buffers[tx].len; + } else { + tx_buf = NULL; + tx_len = rx_bufs->buffers[rx].len; + } + + if (rx < rx_count) { + rx_buf = rx_bufs->buffers[rx].buf; + rx_len = rx_bufs->buffers[rx].len; + } else { + rx_buf = NULL; + rx_len = tx_bufs->buffers[tx].len; + } + + + while ((tx < tx_count || rx < rx_count) && (tx_len > 0 || rx_len > 0)) { + sqe = rtio_sqe_acquire(r); + + if (sqe == NULL) { + ret = -ENOMEM; + rtio_sqe_drop_all(r); + goto out; + } + + ret++; + + /* If tx/rx len are same, we can do a simple transceive */ + if (tx_len == rx_len) { + if (tx_buf == NULL) { + rtio_sqe_prep_read(sqe, iodev, RTIO_PRIO_NORM, + rx_buf, rx_len, NULL); + } else if (rx_buf == NULL) { + rtio_sqe_prep_write(sqe, iodev, RTIO_PRIO_NORM, + tx_buf, tx_len, NULL); + } else { + rtio_sqe_prep_transceive(sqe, iodev, RTIO_PRIO_NORM, + tx_buf, rx_buf, rx_len, NULL); + } + tx++; + rx++; + if (rx < rx_count) { + rx_buf = rx_bufs->buffers[rx].buf; + rx_len = rx_bufs->buffers[rx].len; + } else { + rx_buf = NULL; + rx_len = 0; + } + if (tx < tx_count) { + tx_buf = tx_bufs->buffers[tx].buf; + tx_len = tx_bufs->buffers[tx].len; + } else { + tx_buf = NULL; + tx_len = 0; + } + } else if (tx_len == 0) { + rtio_sqe_prep_read(sqe, iodev, RTIO_PRIO_NORM, + (uint8_t *)rx_buf, + (uint32_t)rx_len, + NULL); + rx++; + if (rx < rx_count) { + rx_buf = rx_bufs->buffers[rx].buf; + rx_len = rx_bufs->buffers[rx].len; + } else { + rx_buf = NULL; + rx_len = 0; + } + } else if (rx_len == 0) { + rtio_sqe_prep_write(sqe, iodev, RTIO_PRIO_NORM, + (uint8_t *)tx_buf, + (uint32_t)tx_len, + NULL); + tx++; + if (tx < tx_count) { + tx_buf = rx_bufs->buffers[rx].buf; + tx_len = rx_bufs->buffers[rx].len; + } else { + tx_buf = NULL; + tx_len = 0; + } + } else if (tx_len > rx_len) { + rtio_sqe_prep_transceive(sqe, iodev, RTIO_PRIO_NORM, + (uint8_t *)tx_buf, + (uint8_t *)rx_buf, + (uint32_t)rx_len, + NULL); + tx_len -= rx_len; + tx_buf += rx_len; + rx++; + if (rx < rx_count) { + rx_buf = rx_bufs->buffers[rx].buf; + rx_len = rx_bufs->buffers[rx].len; + } else { + rx_buf = NULL; + rx_len = tx_len; + } + } else if (rx_len > tx_len) { + rtio_sqe_prep_transceive(sqe, iodev, RTIO_PRIO_NORM, + (uint8_t *)tx_buf, + (uint8_t *)rx_buf, + (uint32_t)tx_len, + NULL); + rx_len -= tx_len; + rx_buf += tx_len; + tx++; + if (tx < tx_count) { + tx_buf = tx_bufs->buffers[tx].buf; + tx_len = tx_bufs->buffers[tx].len; + } else { + tx_buf = NULL; + tx_len = rx_len; + } + } else { + __ASSERT(false, "Invalid %s state", __func__); + } + + sqe->flags = RTIO_SQE_TRANSACTION; + } + + if (sqe != NULL) { + sqe->flags = 0; + *last_sqe = sqe; + } + +out: + return ret; +} + /** * @brief Lock the SPI RTIO spinlock * diff --git a/drivers/spi/spi_sam.c b/drivers/spi/spi_sam.c index fc8e296194ef0c8..e8fd42375ab082e 100644 --- a/drivers/spi/spi_sam.c +++ b/drivers/spi/spi_sam.c @@ -17,6 +17,7 @@ LOG_MODULE_REGISTER(spi_sam); #include #include #include +#include #include #include #include diff --git a/include/zephyr/drivers/spi.h b/include/zephyr/drivers/spi.h index 56d2cd3d925382b..958211e8294d03f 100644 --- a/include/zephyr/drivers/spi.h +++ b/include/zephyr/drivers/spi.h @@ -1085,164 +1085,6 @@ static inline bool spi_is_ready_iodev(const struct rtio_iodev *spi_iodev) return spi_is_ready_dt(spec); } -/** - * @brief Copy the tx_bufs and rx_bufs into a set of RTIO requests - * - * @param[in] r rtio context - * @param[in] iodev iodev to transceive with - * @param[in] tx_bufs transmit buffer set - * @param[in] rx_bufs receive buffer set - * @param[out] last_sqe last sqe submitted, NULL if not enough memory - * - * @retval Number of submission queue entries - * @retval -ENOMEM out of memory - */ -static inline int spi_rtio_copy(struct rtio *r, - struct rtio_iodev *iodev, - const struct spi_buf_set *tx_bufs, - const struct spi_buf_set *rx_bufs, - struct rtio_sqe **last_sqe) -{ - int ret = 0; - size_t tx_count = tx_bufs ? tx_bufs->count : 0; - size_t rx_count = rx_bufs ? rx_bufs->count : 0; - - uint32_t tx = 0, tx_len = 0; - uint32_t rx = 0, rx_len = 0; - uint8_t *tx_buf, *rx_buf; - - struct rtio_sqe *sqe = NULL; - - if (tx < tx_count) { - tx_buf = tx_bufs->buffers[tx].buf; - tx_len = tx_bufs->buffers[tx].len; - } else { - tx_buf = NULL; - tx_len = rx_bufs->buffers[rx].len; - } - - if (rx < rx_count) { - rx_buf = rx_bufs->buffers[rx].buf; - rx_len = rx_bufs->buffers[rx].len; - } else { - rx_buf = NULL; - rx_len = tx_bufs->buffers[tx].len; - } - - - while ((tx < tx_count || rx < rx_count) && (tx_len > 0 || rx_len > 0)) { - sqe = rtio_sqe_acquire(r); - - if (sqe == NULL) { - ret = -ENOMEM; - rtio_sqe_drop_all(r); - goto out; - } - - ret++; - - /* If tx/rx len are same, we can do a simple transceive */ - if (tx_len == rx_len) { - if (tx_buf == NULL) { - rtio_sqe_prep_read(sqe, iodev, RTIO_PRIO_NORM, - rx_buf, rx_len, NULL); - } else if (rx_buf == NULL) { - rtio_sqe_prep_write(sqe, iodev, RTIO_PRIO_NORM, - tx_buf, tx_len, NULL); - } else { - rtio_sqe_prep_transceive(sqe, iodev, RTIO_PRIO_NORM, - tx_buf, rx_buf, rx_len, NULL); - } - tx++; - rx++; - if (rx < rx_count) { - rx_buf = rx_bufs->buffers[rx].buf; - rx_len = rx_bufs->buffers[rx].len; - } else { - rx_buf = NULL; - rx_len = 0; - } - if (tx < tx_count) { - tx_buf = tx_bufs->buffers[tx].buf; - tx_len = tx_bufs->buffers[tx].len; - } else { - tx_buf = NULL; - tx_len = 0; - } - } else if (tx_len == 0) { - rtio_sqe_prep_read(sqe, iodev, RTIO_PRIO_NORM, - (uint8_t *)rx_buf, - (uint32_t)rx_len, - NULL); - rx++; - if (rx < rx_count) { - rx_buf = rx_bufs->buffers[rx].buf; - rx_len = rx_bufs->buffers[rx].len; - } else { - rx_buf = NULL; - rx_len = 0; - } - } else if (rx_len == 0) { - rtio_sqe_prep_write(sqe, iodev, RTIO_PRIO_NORM, - (uint8_t *)tx_buf, - (uint32_t)tx_len, - NULL); - tx++; - if (tx < tx_count) { - tx_buf = rx_bufs->buffers[rx].buf; - tx_len = rx_bufs->buffers[rx].len; - } else { - tx_buf = NULL; - tx_len = 0; - } - } else if (tx_len > rx_len) { - rtio_sqe_prep_transceive(sqe, iodev, RTIO_PRIO_NORM, - (uint8_t *)tx_buf, - (uint8_t *)rx_buf, - (uint32_t)rx_len, - NULL); - tx_len -= rx_len; - tx_buf += rx_len; - rx++; - if (rx < rx_count) { - rx_buf = rx_bufs->buffers[rx].buf; - rx_len = rx_bufs->buffers[rx].len; - } else { - rx_buf = NULL; - rx_len = tx_len; - } - } else if (rx_len > tx_len) { - rtio_sqe_prep_transceive(sqe, iodev, RTIO_PRIO_NORM, - (uint8_t *)tx_buf, - (uint8_t *)rx_buf, - (uint32_t)tx_len, - NULL); - rx_len -= tx_len; - rx_buf += tx_len; - tx++; - if (tx < tx_count) { - tx_buf = tx_bufs->buffers[tx].buf; - tx_len = tx_bufs->buffers[tx].len; - } else { - tx_buf = NULL; - tx_len = rx_len; - } - } else { - __ASSERT_NO_MSG("Invalid spi_rtio_copy state"); - } - - sqe->flags = RTIO_SQE_TRANSACTION; - } - - if (sqe != NULL) { - sqe->flags = 0; - *last_sqe = sqe; - } - -out: - return ret; -} - #endif /* CONFIG_SPI_RTIO */ /** diff --git a/include/zephyr/drivers/spi/rtio.h b/include/zephyr/drivers/spi/rtio.h index 43958a6979887f9..4635da4c8b4388c 100644 --- a/include/zephyr/drivers/spi/rtio.h +++ b/include/zephyr/drivers/spi/rtio.h @@ -41,6 +41,24 @@ struct spi_rtio { .r = &CONCAT(_name, _r), \ }; +/** + * @brief Copy the tx_bufs and rx_bufs into a set of RTIO requests + * + * @param[in] r rtio context + * @param[in] iodev iodev to transceive with + * @param[in] tx_bufs transmit buffer set + * @param[in] rx_bufs receive buffer set + * @param[out] last_sqe last sqe submitted, NULL if not enough memory + * + * @retval Number of submission queue entries + * @retval -ENOMEM out of memory + */ +int spi_rtio_copy(struct rtio *r, + struct rtio_iodev *iodev, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, + struct rtio_sqe **last_sqe); + /** * @brief Initialize a SPI RTIO context *