Skip to content

Commit

Permalink
spi: rtio: Extract common APIs into separate file
Browse files Browse the repository at this point in the history
Extracted common SPI RTIO operations from the spi_mcux_lpspi driver
into spi_rtio, which should be common across RTIO drivers.

Tested with spi_loopback with and without CONFIG_SPI_RTIO. Ran on
mimxrt1010_evk.

Also, verified the other SPI RTIO driver (spi_sam) is not broken by
these changes (tested building for target: robokit1 with the same
conditions as above).

Signed-off-by: Luis Ubieda <luisf@croxel.com>
  • Loading branch information
ubieda committed Sep 16, 2024
1 parent f628a15 commit 37b6ad1
Show file tree
Hide file tree
Showing 3 changed files with 236 additions and 135 deletions.
163 changes: 28 additions & 135 deletions drivers/spi/spi_mcux_lpspi.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <zephyr/drivers/pinctrl.h>
#ifdef CONFIG_SPI_RTIO
#include <zephyr/rtio/rtio.h>
#include <zephyr/drivers/spi/rtio.h>
#include <zephyr/spinlock.h>
#endif

Expand Down Expand Up @@ -74,13 +75,7 @@ struct spi_mcux_data {
size_t transfer_len;

#ifdef CONFIG_SPI_RTIO
struct rtio *r;
struct mpsc io_q;
struct rtio_iodev iodev;
struct rtio_iodev_sqe *txn_head;
struct rtio_iodev_sqe *txn_curr;
struct spi_dt_spec dt_spec;
struct k_spinlock lock;
struct spi_rtio *rtio_ctx;
#endif

#ifdef CONFIG_SPI_MCUX_LPSPI_DMA
Expand Down Expand Up @@ -181,7 +176,9 @@ static void spi_mcux_master_transfer_callback(LPSPI_Type *base,
struct spi_mcux_data *data = userData;

#ifdef CONFIG_SPI_RTIO
if (data->txn_head != NULL) {
struct spi_rtio *rtio_ctx = data->rtio_ctx;

if (rtio_ctx->txn_head != NULL) {
spi_mcux_iodev_complete(data->dev, status);
return;
}
Expand Down Expand Up @@ -576,59 +573,25 @@ static int transceive_dma(const struct device *dev,

#ifdef CONFIG_SPI_RTIO

int spi_rtio_transceive(const struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs)
{
struct spi_mcux_data *data = dev->data;
struct spi_dt_spec *dt_spec = &data->dt_spec;
struct rtio_sqe *sqe;
struct rtio_cqe *cqe;
int err = 0;
int ret;

dt_spec->config = *config;

ret = spi_rtio_copy(data->r, &data->iodev, tx_bufs, rx_bufs, &sqe);
if (ret < 0) {
return ret;
}

/** Submit request and wait */
rtio_submit(data->r, ret);

while (ret > 0) {
cqe = rtio_cqe_consume(data->r);
if (cqe->result < 0) {
err = cqe->result;
}

rtio_cqe_release(data->r, cqe);
ret--;
}

return err;
}

static inline int transceive_rtio(const struct device *dev,
const struct spi_config *spi_cfg,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs)
{
struct spi_mcux_data *data = dev->data;
struct spi_rtio *rtio_ctx = data->rtio_ctx;
int ret;

spi_context_lock(&data->ctx, false, NULL, NULL, spi_cfg);

ret = spi_rtio_transceive(dev, spi_cfg, tx_bufs, rx_bufs);
ret = spi_rtio_transceive(rtio_ctx, spi_cfg, tx_bufs, rx_bufs);

spi_context_release(&data->ctx, ret);

return ret;
}

#else
#endif /* CONFIG_SPI_RTIO */

static int transceive(const struct device *dev,
const struct spi_config *spi_cfg,
Expand Down Expand Up @@ -664,16 +627,15 @@ static int transceive(const struct device *dev,
return ret;
}

#endif /* CONFIG_SPI_RTIO */

static int spi_mcux_transceive(const struct device *dev,
const struct spi_config *spi_cfg,
const struct spi_buf_set *tx_bufs,
const struct spi_buf_set *rx_bufs)
{
#ifdef CONFIG_SPI_RTIO
return transceive_rtio(dev, spi_cfg, tx_bufs, rx_bufs);
#else
#endif /* CONFIG_SPI_RTIO */

#ifdef CONFIG_SPI_MCUX_LPSPI_DMA
const struct spi_mcux_data *data = dev->data;

Expand All @@ -683,7 +645,6 @@ static int spi_mcux_transceive(const struct device *dev,
#endif /* CONFIG_SPI_MCUX_LPSPI_DMA */

return transceive(dev, spi_cfg, tx_bufs, rx_bufs, false, NULL, NULL);
#endif /* CONFIG_SPI_RTIO */
}

#ifdef CONFIG_SPI_ASYNC
Expand Down Expand Up @@ -761,10 +722,7 @@ static int spi_mcux_init(const struct device *dev)
#endif /* CONFIG_SPI_MCUX_LPSPI_DMA */

#ifdef CONFIG_SPI_RTIO
data->dt_spec.bus = dev;
data->iodev.api = &spi_iodev_api;
data->iodev.data = &data->dt_spec;
mpsc_init(&data->io_q);
spi_rtio_init(data->rtio_ctx, dev);
#endif

err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
Expand All @@ -778,24 +736,12 @@ static int spi_mcux_init(const struct device *dev)
}

#ifdef CONFIG_SPI_RTIO
static inline k_spinlock_key_t spi_spin_lock(const struct device *dev)
{
struct spi_mcux_data *data = dev->data;

return k_spin_lock(&data->lock);
}

static inline void spi_spin_unlock(const struct device *dev, k_spinlock_key_t key)
{
struct spi_mcux_data *data = dev->data;

k_spin_unlock(&data->lock, key);
}

static inline void spi_mcux_iodev_prepare_start(const struct device *dev)
{
struct spi_mcux_data *data = dev->data;
struct spi_dt_spec *spi_dt_spec = data->txn_curr->sqe.iodev->data;
struct spi_rtio *rtio_ctx = data->rtio_ctx;
struct spi_dt_spec *spi_dt_spec = rtio_ctx->txn_curr->sqe.iodev->data;
struct spi_config *spi_config = &spi_dt_spec->config;
int err;

Expand All @@ -805,16 +751,14 @@ static inline void spi_mcux_iodev_prepare_start(const struct device *dev)
spi_context_cs_control(&data->ctx, true);
}

static bool spi_rtio_next(const struct device *dev, bool completion);

static void spi_mcux_iodev_start(const struct device *dev)
{
/* const struct spi_mcux_config *config = dev->config; */
struct spi_mcux_data *data = dev->data;
struct rtio_sqe *sqe = &data->txn_curr->sqe;
struct spi_rtio *rtio_ctx = data->rtio_ctx;
struct rtio_sqe *sqe = &rtio_ctx->txn_curr->sqe;
struct spi_dt_spec *spi_dt_spec = sqe->iodev->data;
struct spi_config *spi_cfg = &spi_dt_spec->config;
struct rtio_iodev_sqe *txn_head = data->txn_head;

LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
lpspi_transfer_t transfer;
Expand Down Expand Up @@ -856,69 +800,17 @@ static void spi_mcux_iodev_start(const struct device *dev)
&transfer);
if (status != kStatus_Success) {
LOG_ERR("Transfer could not start");
rtio_iodev_sqe_err(txn_head, -EIO);
spi_mcux_iodev_complete(dev, -EIO);
}
}

static bool spi_rtio_next(const struct device *dev, bool completion)
{
struct spi_mcux_data *data = dev->data;

k_spinlock_key_t key = spi_spin_lock(dev);

if (!completion && data->txn_curr != NULL) {
spi_spin_unlock(dev, key);
return false;
}

struct mpsc_node *next = mpsc_pop(&data->io_q);

if (next != NULL) {
struct rtio_iodev_sqe *next_sqe = CONTAINER_OF(next, struct rtio_iodev_sqe, q);

data->txn_head = next_sqe;
data->txn_curr = next_sqe;
} else {
data->txn_head = NULL;
data->txn_curr = NULL;
}

spi_spin_unlock(dev, key);

return (data->txn_curr != NULL);
}

static bool spi_rtio_submit(const struct device *dev,
struct rtio_iodev_sqe *iodev_sqe)
{
struct spi_mcux_data *data = dev->data;

mpsc_push(&data->io_q, &iodev_sqe->q);

return spi_rtio_next(dev, false);
}

static bool spi_rtio_complete(const struct device *dev, int status)
{
struct spi_mcux_data *data = dev->data;
struct rtio_iodev_sqe *txn_head = data->txn_head;
bool result;

result = spi_rtio_next(dev, true);

if (status < 0) {
rtio_iodev_sqe_err(txn_head, status);
} else {
rtio_iodev_sqe_ok(txn_head, status);
}

return result;
}

static void spi_mcux_iodev_submit(const struct device *dev,
struct rtio_iodev_sqe *iodev_sqe)
{
if (spi_rtio_submit(dev, iodev_sqe)) {
struct spi_mcux_data *data = dev->data;
struct spi_rtio *rtio_ctx = data->rtio_ctx;

if (spi_rtio_submit(rtio_ctx, iodev_sqe)) {
spi_mcux_iodev_prepare_start(dev);
spi_mcux_iodev_start(dev);
}
Expand All @@ -927,15 +819,16 @@ static void spi_mcux_iodev_submit(const struct device *dev,
static void spi_mcux_iodev_complete(const struct device *dev, int status)
{
struct spi_mcux_data *data = dev->data;
struct spi_rtio *rtio_ctx = data->rtio_ctx;

if (!status && data->txn_curr->sqe.flags & RTIO_SQE_TRANSACTION) {
data->txn_curr = rtio_txn_next(data->txn_curr);
if (!status && rtio_ctx->txn_curr->sqe.flags & RTIO_SQE_TRANSACTION) {
rtio_ctx->txn_curr = rtio_txn_next(rtio_ctx->txn_curr);
spi_mcux_iodev_start(dev);
} else {
/** De-assert CS-line to space from next transaction */
spi_context_cs_control(&data->ctx, false);

if (spi_rtio_complete(dev, status)) {
if (spi_rtio_complete(rtio_ctx, status)) {
spi_mcux_iodev_prepare_start(dev);
spi_mcux_iodev_start(dev);
}
Expand All @@ -956,9 +849,9 @@ static const struct spi_driver_api spi_mcux_driver_api = {
.release = spi_mcux_release,
};


#define SPI_MCUX_RTIO_DEFINE(n) RTIO_DEFINE(spi_mcux_rtio_##n, CONFIG_SPI_MCUX_RTIO_SQ_SIZE, \
CONFIG_SPI_MCUX_RTIO_SQ_SIZE)
#define SPI_MCUX_RTIO_DEFINE(n) SPI_RTIO_DEFINE(spi_mcux_rtio_##n, \
CONFIG_SPI_MCUX_RTIO_SQ_SIZE, \
CONFIG_SPI_MCUX_RTIO_SQ_SIZE)

#ifdef CONFIG_SPI_MCUX_LPSPI_DMA
#define SPI_DMA_CHANNELS(n) \
Expand Down Expand Up @@ -1050,7 +943,7 @@ static const struct spi_driver_api spi_mcux_driver_api = {
SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(n), ctx) \
SPI_DMA_CHANNELS(n) \
IF_ENABLED(CONFIG_SPI_RTIO, \
(.r = &spi_mcux_rtio_##n,)) \
(.rtio_ctx = &spi_mcux_rtio_##n,)) \
\
}; \
\
Expand Down
Loading

0 comments on commit 37b6ad1

Please sign in to comment.