1 /*
2  * Copyright (c) 2024 Croxel, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_DRIVERS_SPI_RTIO_H_
8 #define ZEPHYR_DRIVERS_SPI_RTIO_H_
9 
10 #include <zephyr/kernel.h>
11 #include <zephyr/drivers/spi.h>
12 #include <zephyr/rtio/rtio.h>
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 /**
19  * @brief Driver context for implementing SPI with RTIO
20  */
21 struct spi_rtio {
22 	struct k_spinlock lock;
23 	struct rtio *r;
24 	struct mpsc io_q;
25 	struct rtio_iodev iodev;
26 	struct rtio_iodev_sqe *txn_head;
27 	struct rtio_iodev_sqe *txn_curr;
28 	struct spi_dt_spec dt_spec;
29 };
30 
31 /**
32  * @brief Statically define a spi_rtio context
33  *
34  * @param _name Symbolic name of the context
35  * @param _sq_sz Submission queue entry pool size
36  * @param _cq_sz Completion queue entry pool size
37  */
38 #define SPI_RTIO_DEFINE(_name, _sq_sz, _cq_sz)				       \
39 	RTIO_DEFINE(CONCAT(_name, _r), _sq_sz, _cq_sz);			       \
40 	static struct spi_rtio _name = {				       \
41 		.r = &CONCAT(_name, _r),				       \
42 	};
43 
44 /**
45  * @brief Copy the tx_bufs and rx_bufs into a set of RTIO requests
46  *
47  * @param[in] r rtio context
48  * @param[in] iodev iodev to transceive with
49  * @param[in] tx_bufs transmit buffer set
50  * @param[in] rx_bufs receive buffer set
51  * @param[out] last_sqe last sqe submitted, NULL if not enough memory
52  *
53  * @retval Number of submission queue entries
54  * @retval -ENOMEM out of memory
55  */
56 int spi_rtio_copy(struct rtio *r,
57 		  struct rtio_iodev *iodev,
58 		  const struct spi_buf_set *tx_bufs,
59 		  const struct spi_buf_set *rx_bufs,
60 		  struct rtio_sqe **last_sqe);
61 
62 /**
63  * @brief Initialize a SPI RTIO context
64  *
65  * @param ctx SPI RTIO driver context
66  * @param dev SPI bus
67  */
68 void spi_rtio_init(struct spi_rtio *ctx, const struct device *dev);
69 
70 /**
71  * @brief Signal that the current (ctx->txn_curr) submission has been completed
72  *
73  * @param ctx SPI RTIO driver context
74  * @param status Completion status, negative values are errors
75  *
76  * @retval true Next submission is ready to start
77  * @retval false No more submissions to work on
78  */
79 bool spi_rtio_complete(struct spi_rtio *ctx, int status);
80 
81 /**
82  * @brief Submit, atomically, a submission to work on at some point
83  *
84  * @retval true Next submission is ready to start
85  * @retval false No new submission to start or submissions are in progress already
86  */
87 bool spi_rtio_submit(struct spi_rtio *ctx, struct rtio_iodev_sqe *iodev_sqe);
88 
89 /**
90  * @brief Perform a SPI Transfer (transceive) in a blocking call
91  *
92  * Provides a compatible API for the existing spi_transceive API by blocking
93  * the caller until the operation is complete.
94  * For details see @ref spi_transceive.
95  */
96 int spi_rtio_transceive(struct spi_rtio *ctx,
97 			const struct spi_config *config,
98 			const struct spi_buf_set *tx_bufs,
99 			const struct spi_buf_set *rx_bufs);
100 
101 /**
102  * @brief Fallback SPI RTIO submit implementation.
103  *
104  * Default RTIO SPI implementation for drivers who do no yet have
105  * native support. For details, see @ref spi_iodev_submit.
106  */
107 void spi_rtio_iodev_default_submit(const struct device *dev,
108 				   struct rtio_iodev_sqe *iodev_sqe);
109 
110 #ifdef __cplusplus
111 }
112 #endif
113 
114 #endif /* ZEPHYR_DRIVERS_SPI_RTIO_H_ */
115