1 /*
2  * Copyright 2022-2023 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, 4))
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 };
64 
65 /*! @} */
66 
67 /*!
68  * @addtogroup i3c_slave_dma_driver
69  * @{
70  */
71 /* Forward declaration of the transfer descriptor and handle typedefs. */
72 typedef struct _i3c_slave_dma_handle i3c_slave_dma_handle_t;
73 
74 /*! @brief I3C slave transfer structure */
75 typedef struct _i3c_slave_dma_transfer
76 {
77     uint32_t event;            /*!< Reason the callback is being invoked. */
78     uint8_t *txData;           /*!< Transfer buffer */
79     size_t txDataSize;         /*!< Transfer size */
80     uint8_t *rxData;           /*!< Transfer buffer */
81     size_t rxDataSize;         /*!< Transfer size */
82     status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for
83                                   #kI3C_SlaveCompletionEvent. */
84 } i3c_slave_dma_transfer_t;
85 
86 /*!
87  * @brief Slave event callback function pointer type.
88  *
89  * This callback is used only for the slave DMA transfer API.
90  *
91  * @param base Base address for the I3C instance on which the event occurred.
92  * @param handle   Pointer to slave DMA transfer handle.
93  * @param transfer Pointer to transfer descriptor containing values passed to and/or from the callback.
94  * @param userData Arbitrary pointer-sized value passed from the application.
95  */
96 typedef void (*i3c_slave_dma_callback_t)(I3C_Type *base, i3c_slave_dma_transfer_t *transfer, void *userData);
97 /*!
98  * @brief I3C slave dma handle structure.
99  * @note The contents of this structure are private and subject to change.
100  */
101 struct _i3c_slave_dma_handle
102 {
103     I3C_Type *base;                    /*!< I3C base pointer. */
104     i3c_slave_dma_transfer_t transfer; /*!< I3C slave transfer copy. */
105     bool isBusy;                       /*!< Whether transfer is busy. */
106     bool wasTransmit;                  /*!< Whether the last transfer was a transmit. */
107     uint32_t eventMask;                /*!< Mask of enabled events. */
108     i3c_slave_dma_callback_t callback; /*!< Callback function called at transfer event. */
109     dma_handle_t *rxDmaHandle;         /*!< Handle for receive DMA channel. */
110     dma_handle_t *txDmaHandle;         /*!< Handle for transmit DMA channel. */
111     void *userData;                    /*!< Callback parameter passed to callback. */
112 };
113 /*! @} */
114 /*******************************************************************************
115  * API
116  ******************************************************************************/
117 
118 #if defined(__cplusplus)
119 extern "C" {
120 #endif
121 
122 /*!
123  * @addtogroup i3c_master_dma_driver
124  * @{
125  */
126 
127 /*! @name Master DMA */
128 /*! @{ */
129 
130 /*!
131  * @brief Create a new handle for the I3C master DMA APIs.
132  *
133  * The creation of a handle is for use with the DMA APIs. Once a handle
134  * is created, there is not a corresponding destroy handle. If the user wants to
135  * terminate a transfer, the I3C_MasterTransferAbortDMA() API shall be called.
136  *
137  * For devices where the I3C send and receive DMA requests are OR'd together, the @a txDmaHandle
138  * parameter is ignored and may be set to NULL.
139  *
140  * @param base The I3C peripheral base address.
141  * @param handle Pointer to the I3C master driver handle.
142  * @param callback User provided pointer to the asynchronous callback function.
143  * @param userData User provided pointer to the application callback data.
144  * @param rxDmaHandle Handle for the DMA receive channel. Created by the user prior to calling this function.
145  * @param txDmaHandle Handle for the DMA transmit channel. Created by the user prior to calling this function.
146  */
147 void I3C_MasterTransferCreateHandleDMA(I3C_Type *base,
148                                        i3c_master_dma_handle_t *handle,
149                                        const i3c_master_dma_callback_t *callback,
150                                        void *userData,
151                                        dma_handle_t *rxDmaHandle,
152                                        dma_handle_t *txDmaHandle);
153 
154 /*!
155  * @brief Performs a non-blocking DMA-based transaction on the I3C bus.
156  *
157  * The callback specified when the @a handle was created is invoked when the transaction has
158  * completed.
159  *
160  * @param base The I3C peripheral base address.
161  * @param handle Pointer to the I3C master driver handle.
162  * @param transfer The pointer to the transfer descriptor.
163  * @retval kStatus_Success The transaction was started successfully.
164  * @retval #kStatus_I3C_Busy Either another master is currently utilizing the bus, or another DMA
165  *      transaction is already in progress.
166  */
167 status_t I3C_MasterTransferDMA(I3C_Type *base, i3c_master_dma_handle_t *handle, i3c_master_transfer_t *transfer);
168 
169 /*!
170  * @brief Returns number of bytes transferred so far.
171  *
172  * @param base The I3C peripheral base address.
173  * @param handle Pointer to the I3C master driver handle.
174  * @param[out] count Number of bytes transferred so far by the non-blocking transaction.
175  * @retval kStatus_Success
176  * @retval kStatus_NoTransferInProgress There is not a DMA transaction currently in progress.
177  */
178 status_t I3C_MasterTransferGetCountDMA(I3C_Type *base, i3c_master_dma_handle_t *handle, size_t *count);
179 
180 /*!
181  * @brief Terminates a non-blocking I3C master transmission early.
182  *
183  * @note It is not safe to call this function from an IRQ handler that has a higher priority than the
184  *      DMA peripheral's IRQ priority.
185  *
186  * @param base The I3C peripheral base address.
187  * @param handle Pointer to the I3C master driver handle.
188  */
189 void I3C_MasterTransferAbortDMA(I3C_Type *base, i3c_master_dma_handle_t *handle);
190 
191 /*!
192  * @brief Reusable routine to handle master interrupts.
193  * @note This function does not need to be called unless you are reimplementing the
194  *  nonblocking API's interrupt handler routines to add special functionality.
195  * @param base The I3C peripheral base address.
196  * @param handle Pointer to the I3C master DMA driver handle.
197  */
198 void I3C_MasterTransferDMAHandleIRQ(I3C_Type *base, void *i3cHandle);
199 /*! @} */
200 
201 /*! @} */
202 
203 /*!
204  * @addtogroup i3c_slave_dma_driver
205  * @{
206  */
207 
208 /*! @name Slave DMA */
209 /*! @{ */
210 /*!
211  * @brief Create a new handle for the I3C slave DMA APIs.
212  *
213  * The creation of a handle is for use with the DMA APIs. Once a handle
214  * is created, there is not a corresponding destroy handle. If the user wants to
215  * terminate a transfer, the I3C_SlaveTransferAbortDMA() API shall be called.
216  *
217  * For devices where the I3C send and receive DMA requests are OR'd together, the @a txDmaHandle
218  * parameter is ignored and may be set to NULL.
219  *
220  * @param base The I3C peripheral base address.
221  * @param handle Pointer to the I3C slave driver handle.
222  * @param callback User provided pointer to the asynchronous callback function.
223  * @param userData User provided pointer to the application callback data.
224  * @param rxDmaHandle Handle for the DMA receive channel. Created by the user prior to calling this function.
225  * @param txDmaHandle Handle for the DMA transmit channel. Created by the user prior to calling this function.
226  */
227 void I3C_SlaveTransferCreateHandleDMA(I3C_Type *base,
228                                       i3c_slave_dma_handle_t *handle,
229                                       i3c_slave_dma_callback_t callback,
230                                       void *userData,
231                                       dma_handle_t *rxDmaHandle,
232                                       dma_handle_t *txDmaHandle);
233 
234 /*!
235  * @brief Prepares for a non-blocking DMA-based transaction on the I3C bus.
236  *
237  * The API will do DMA configuration according to the input transfer descriptor, and the data will be transferred when
238  * there's bus master requesting transfer from/to this slave. So the timing of call to this API need be aligned
239  * with master application to ensure the transfer is executed as expected.
240  * Callback specified when the @a handle was created is invoked when the transaction has completed.
241  *
242  * @param base The I3C peripheral base address.
243  * @param handle Pointer to the I3C slave driver handle.
244  * @param transfer The pointer to the transfer descriptor.
245  * @param eventMask Bit mask formed by OR'ing together #i3c_slave_transfer_event_t enumerators to specify
246  *      which events to send to the callback. The transmit and receive events is not allowed to be enabled.
247  * @retval kStatus_Success The transaction was started successfully.
248  * @retval #kStatus_I3C_Busy Either another master is currently utilizing the bus, or another DMA
249  *      transaction is already in progress.
250  */
251 status_t I3C_SlaveTransferDMA(I3C_Type *base,
252                               i3c_slave_dma_handle_t *handle,
253                               i3c_slave_dma_transfer_t *transfer,
254                               uint32_t eventMask);
255 /*!
256  * @brief Abort a slave dma non-blocking transfer in a early time
257  *
258  * @param base I3C peripheral base address
259  * @param handle pointer to i3c_slave_dma_handle_t structure
260  */
261 void I3C_SlaveTransferAbortDMA(I3C_Type *base, i3c_slave_dma_handle_t *handle);
262 
263 /*!
264  * @brief Reusable routine to handle slave interrupts.
265  * @note This function does not need to be called unless you are reimplementing the
266  *  nonblocking API's interrupt handler routines to add special functionality.
267  * @param base The I3C peripheral base address.
268  * @param handle Pointer to the I3C slave DMA driver handle.
269  */
270 void I3C_SlaveTransferDMAHandleIRQ(I3C_Type *base, void *i3cHandle);
271 /*! @} */
272 
273 /*! @} */
274 #if defined(__cplusplus)
275 }
276 #endif
277 
278 #endif /* FSL_I3C_DMA_H_ */
279