1 /*
2  * Copyright 2022-2024 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #ifndef FSL_I3C_DMA_H_
7 #define FSL_I3C_DMA_H_
8 
9 #include "fsl_i3c.h"
10 #include "fsl_dma.h"
11 
12 /*******************************************************************************
13  * Definitions
14  ******************************************************************************/
15 
16 /*! @name Driver version */
17 /*! @{ */
18 /*! @brief I3C DMA driver version. */
19 #define FSL_I3C_DMA_DRIVER_VERSION (MAKE_VERSION(2, 1, 6))
20 /*@}*/
21 
22 /*!
23  * @addtogroup i3c_master_dma_driver
24  * @{
25  */
26 
27 /* Forward declaration of the transfer descriptor and handle typedefs. */
28 typedef struct _i3c_master_dma_handle i3c_master_dma_handle_t;
29 
30 /*! @brief i3c master callback functions. */
31 typedef struct _i3c_master_dma_callback
32 {
33     void (*slave2Master)(I3C_Type *base, void *userData); /*!< Transfer complete callback */
34     void (*ibiCallback)(I3C_Type *base,
35                         i3c_master_dma_handle_t *handle,
36                         i3c_ibi_type_t ibiType,
37                         i3c_ibi_state_t ibiState); /*!< IBI event callback */
38     void (*transferComplete)(I3C_Type *base,
39                              i3c_master_dma_handle_t *handle,
40                              status_t status,
41                              void *userData); /*!< Transfer complete callback */
42 } i3c_master_dma_callback_t;
43 /*!
44  * @brief Driver handle for master DMA APIs.
45  * @note The contents of this structure are private and subject to change.
46  */
47 struct _i3c_master_dma_handle
48 {
49     I3C_Type *base;                     /*!< I3C base pointer. */
50     uint8_t state;                      /*!< Transfer state machine current state. */
51     uint32_t transferCount;             /*!< Indicates progress of the transfer */
52     uint8_t subaddressBuffer[4];        /*!< Saving subaddress command. */
53     uint8_t subaddressCount;            /*!< Saving command count. */
54     i3c_master_transfer_t transfer;     /*!< Copy of the current transfer info. */
55     i3c_master_dma_callback_t callback; /*!< Callback function pointer. */
56     void *userData;                     /*!< Application data passed to callback. */
57     dma_handle_t *rxDmaHandle;          /*!< Handle for receive DMA channel. */
58     dma_handle_t *txDmaHandle;          /*!< Handle for transmit DMA channel. */
59     uint8_t ibiAddress;                 /*!< Slave address which request IBI. */
60     uint8_t *ibiBuff;                   /*!< Pointer to IBI buffer to keep ibi bytes. */
61     size_t ibiPayloadSize;              /*!< IBI payload size. */
62     i3c_ibi_type_t ibiType;             /*!< IBI type. */
63 #if defined(FSL_FEATURE_I3C_HAS_ERRATA_052123) && (FSL_FEATURE_I3C_HAS_ERRATA_052123)
64     uint32_t transDataSize;             /*!< Transferred data size. */
65     uint8_t workaroundBuff[16];         /*!< Workaround buffer to store temporary data. */
66 #endif
67 };
68 
69 /*! @} */
70 
71 /*!
72  * @addtogroup i3c_slave_dma_driver
73  * @{
74  */
75 /* Forward declaration of the transfer descriptor and handle typedefs. */
76 typedef struct _i3c_slave_dma_handle i3c_slave_dma_handle_t;
77 
78 /*! @brief I3C slave transfer structure */
79 typedef struct _i3c_slave_dma_transfer
80 {
81     uint32_t event;            /*!< Reason the callback is being invoked. */
82     uint8_t *txData;           /*!< Transfer buffer */
83     size_t txDataSize;         /*!< Transfer size */
84     uint8_t *rxData;           /*!< Transfer buffer */
85     size_t rxDataSize;         /*!< Transfer size */
86     status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for
87                                   #kI3C_SlaveCompletionEvent. */
88 } i3c_slave_dma_transfer_t;
89 
90 /*!
91  * @brief Slave event callback function pointer type.
92  *
93  * This callback is used only for the slave DMA transfer API.
94  *
95  * @param base Base address for the I3C instance on which the event occurred.
96  * @param handle   Pointer to slave DMA transfer handle.
97  * @param transfer Pointer to transfer descriptor containing values passed to and/or from the callback.
98  * @param userData Arbitrary pointer-sized value passed from the application.
99  */
100 typedef void (*i3c_slave_dma_callback_t)(I3C_Type *base, i3c_slave_dma_transfer_t *transfer, void *userData);
101 /*!
102  * @brief I3C slave dma handle structure.
103  * @note The contents of this structure are private and subject to change.
104  */
105 struct _i3c_slave_dma_handle
106 {
107     I3C_Type *base;                    /*!< I3C base pointer. */
108     i3c_slave_dma_transfer_t transfer; /*!< I3C slave transfer copy. */
109     bool isBusy;                       /*!< Whether transfer is busy. */
110     bool wasTransmit;                  /*!< Whether the last transfer was a transmit. */
111     uint32_t eventMask;                /*!< Mask of enabled events. */
112     i3c_slave_dma_callback_t callback; /*!< Callback function called at transfer event. */
113     dma_handle_t *rxDmaHandle;         /*!< Handle for receive DMA channel. */
114     dma_handle_t *txDmaHandle;         /*!< Handle for transmit DMA channel. */
115     void *userData;                    /*!< Callback parameter passed to callback. */
116 };
117 /*! @} */
118 /*******************************************************************************
119  * API
120  ******************************************************************************/
121 
122 #if defined(__cplusplus)
123 extern "C" {
124 #endif
125 
126 /*!
127  * @addtogroup i3c_master_dma_driver
128  * @{
129  */
130 
131 /*! @name Master DMA */
132 /*! @{ */
133 
134 /*!
135  * @brief Create a new handle for the I3C master DMA APIs.
136  *
137  * The creation of a handle is for use with the DMA APIs. Once a handle
138  * is created, there is not a corresponding destroy handle. If the user wants to
139  * terminate a transfer, the I3C_MasterTransferAbortDMA() API shall be called.
140  *
141  * For devices where the I3C send and receive DMA requests are OR'd together, the @a txDmaHandle
142  * parameter is ignored and may be set to NULL.
143  *
144  * @param base The I3C peripheral base address.
145  * @param handle Pointer to the I3C master driver handle.
146  * @param callback User provided pointer to the asynchronous callback function.
147  * @param userData User provided pointer to the application callback data.
148  * @param rxDmaHandle Handle for the DMA receive channel. Created by the user prior to calling this function.
149  * @param txDmaHandle Handle for the DMA transmit channel. Created by the user prior to calling this function.
150  */
151 void I3C_MasterTransferCreateHandleDMA(I3C_Type *base,
152                                        i3c_master_dma_handle_t *handle,
153                                        const i3c_master_dma_callback_t *callback,
154                                        void *userData,
155                                        dma_handle_t *rxDmaHandle,
156                                        dma_handle_t *txDmaHandle);
157 
158 /*!
159  * @brief Performs a non-blocking DMA-based transaction on the I3C bus.
160  *
161  * The callback specified when the @a handle was created is invoked when the transaction has
162  * completed.
163  *
164  * @param base The I3C peripheral base address.
165  * @param handle Pointer to the I3C master driver handle.
166  * @param transfer The pointer to the transfer descriptor.
167  * @retval kStatus_Success The transaction was started successfully.
168  * @retval #kStatus_I3C_Busy Either another master is currently utilizing the bus, or another DMA
169  *      transaction is already in progress.
170  */
171 status_t I3C_MasterTransferDMA(I3C_Type *base, i3c_master_dma_handle_t *handle, i3c_master_transfer_t *transfer);
172 
173 /*!
174  * @brief Returns number of bytes transferred so far.
175  *
176  * @param base The I3C peripheral base address.
177  * @param handle Pointer to the I3C master driver handle.
178  * @param[out] count Number of bytes transferred so far by the non-blocking transaction.
179  * @retval kStatus_Success
180  * @retval kStatus_NoTransferInProgress There is not a DMA transaction currently in progress.
181  */
182 status_t I3C_MasterTransferGetCountDMA(I3C_Type *base, i3c_master_dma_handle_t *handle, size_t *count);
183 
184 /*!
185  * @brief Terminates a non-blocking I3C master transmission early.
186  *
187  * @note It is not safe to call this function from an IRQ handler that has a higher priority than the
188  *      DMA peripheral's IRQ priority.
189  *
190  * @param base The I3C peripheral base address.
191  * @param handle Pointer to the I3C master driver handle.
192  */
193 void I3C_MasterTransferAbortDMA(I3C_Type *base, i3c_master_dma_handle_t *handle);
194 
195 /*!
196  * @brief Reusable routine to handle master interrupts.
197  * @note This function does not need to be called unless you are reimplementing the
198  *  nonblocking API's interrupt handler routines to add special functionality.
199  * @param base The I3C peripheral base address.
200  * @param handle Pointer to the I3C master DMA driver handle.
201  */
202 void I3C_MasterTransferDMAHandleIRQ(I3C_Type *base, void *i3cHandle);
203 /*! @} */
204 
205 /*! @} */
206 
207 /*!
208  * @addtogroup i3c_slave_dma_driver
209  * @{
210  */
211 
212 /*! @name Slave DMA */
213 /*! @{ */
214 /*!
215  * @brief Create a new handle for the I3C slave DMA APIs.
216  *
217  * The creation of a handle is for use with the DMA APIs. Once a handle
218  * is created, there is not a corresponding destroy handle. If the user wants to
219  * terminate a transfer, the I3C_SlaveTransferAbortDMA() API shall be called.
220  *
221  * For devices where the I3C send and receive DMA requests are OR'd together, the @a txDmaHandle
222  * parameter is ignored and may be set to NULL.
223  *
224  * @param base The I3C peripheral base address.
225  * @param handle Pointer to the I3C slave driver handle.
226  * @param callback User provided pointer to the asynchronous callback function.
227  * @param userData User provided pointer to the application callback data.
228  * @param rxDmaHandle Handle for the DMA receive channel. Created by the user prior to calling this function.
229  * @param txDmaHandle Handle for the DMA transmit channel. Created by the user prior to calling this function.
230  */
231 void I3C_SlaveTransferCreateHandleDMA(I3C_Type *base,
232                                       i3c_slave_dma_handle_t *handle,
233                                       i3c_slave_dma_callback_t callback,
234                                       void *userData,
235                                       dma_handle_t *rxDmaHandle,
236                                       dma_handle_t *txDmaHandle);
237 
238 /*!
239  * @brief Prepares for a non-blocking DMA-based transaction on the I3C bus.
240  *
241  * The API will do DMA configuration according to the input transfer descriptor, and the data will be transferred when
242  * there's bus master requesting transfer from/to this slave. So the timing of call to this API need be aligned
243  * with master application to ensure the transfer is executed as expected.
244  * Callback specified when the @a handle was created is invoked when the transaction has completed.
245  *
246  * @param base The I3C peripheral base address.
247  * @param handle Pointer to the I3C slave driver handle.
248  * @param transfer The pointer to the transfer descriptor.
249  * @param eventMask Bit mask formed by OR'ing together #i3c_slave_transfer_event_t enumerators to specify
250  *      which events to send to the callback. The transmit and receive events is not allowed to be enabled.
251  * @retval kStatus_Success The transaction was started successfully.
252  * @retval #kStatus_I3C_Busy Either another master is currently utilizing the bus, or another DMA
253  *      transaction is already in progress.
254  */
255 status_t I3C_SlaveTransferDMA(I3C_Type *base,
256                               i3c_slave_dma_handle_t *handle,
257                               i3c_slave_dma_transfer_t *transfer,
258                               uint32_t eventMask);
259 /*!
260  * @brief Abort a slave dma non-blocking transfer in a early time
261  *
262  * @param base I3C peripheral base address
263  * @param handle pointer to i3c_slave_dma_handle_t structure
264  */
265 void I3C_SlaveTransferAbortDMA(I3C_Type *base, i3c_slave_dma_handle_t *handle);
266 
267 /*!
268  * @brief Reusable routine to handle slave interrupts.
269  * @note This function does not need to be called unless you are reimplementing the
270  *  nonblocking API's interrupt handler routines to add special functionality.
271  * @param base The I3C peripheral base address.
272  * @param handle Pointer to the I3C slave DMA driver handle.
273  */
274 void I3C_SlaveTransferDMAHandleIRQ(I3C_Type *base, void *i3cHandle);
275 /*! @} */
276 
277 /*! @} */
278 #if defined(__cplusplus)
279 }
280 #endif
281 
282 #endif /* FSL_I3C_DMA_H_ */
283