1 /*
2  * Copyright 2018-2023 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "fsl_i3c.h"
8 #if !(defined(FSL_FEATURE_I3C_HAS_NO_RESET) && FSL_FEATURE_I3C_HAS_NO_RESET)
9 #include "fsl_reset.h"
10 #endif
11 #include <stdlib.h>
12 #include <string.h>
13 
14 /*******************************************************************************
15  * Definitions
16  ******************************************************************************/
17 
18 /* Component ID definition, used by tools. */
19 #ifndef FSL_COMPONENT_ID
20 #define FSL_COMPONENT_ID "platform.drivers.i3c"
21 #endif
22 
23 #define I3C_BROADCASE_ADDR (0x7EU)
24 
25 #define NSEC_PER_SEC            (1000000000UL)
26 #define FSL_I3C_ERROR_RATE_MAX  (10U)
27 #define FSL_I3C_PPBAUD_DIV_MAX  ((I3C_MCONFIG_PPBAUD_MASK >> I3C_MCONFIG_PPBAUD_SHIFT) + 1U)
28 #define FSL_I3C_ODBAUD_DIV_MAX  ((I3C_MCONFIG_ODBAUD_MASK >> I3C_MCONFIG_ODBAUD_SHIFT) + 1U)
29 #define FSL_I3C_I2CBAUD_DIV_MAX (((I3C_MCONFIG_I2CBAUD_MASK >> I3C_MCONFIG_I2CBAUD_SHIFT) + 1U) / 2U)
30 
31 /*! @brief Common sets of flags used by the driver. */
32 enum _i3c_flag_constants
33 {
34     /*! All flags which are cleared by the driver upon starting a transfer. */
35     kMasterClearFlags = kI3C_MasterSlaveStartFlag | kI3C_MasterControlDoneFlag | kI3C_MasterCompleteFlag |
36                         kI3C_MasterArbitrationWonFlag | kI3C_MasterSlave2MasterFlag | kI3C_MasterErrorFlag,
37 
38     /*! IRQ sources enabled by the non-blocking transactional API. */
39     kMasterIrqFlags = kI3C_MasterSlaveStartFlag | kI3C_MasterControlDoneFlag | kI3C_MasterCompleteFlag |
40                       kI3C_MasterRxReadyFlag /* | kI3C_MasterTxReadyFlag */ | kI3C_MasterArbitrationWonFlag |
41                       kI3C_MasterErrorFlag | kI3C_MasterSlave2MasterFlag,
42 
43     /*! Errors to check for. */
44     kMasterErrorFlags = kI3C_MasterErrorNackFlag | kI3C_MasterErrorWriteAbortFlag |
45 #if !defined(FSL_FEATURE_I3C_HAS_NO_MERRWARN_TERM) || (!FSL_FEATURE_I3C_HAS_NO_MERRWARN_TERM)
46                         kI3C_MasterErrorTermFlag |
47 #endif
48                         kI3C_MasterErrorParityFlag | kI3C_MasterErrorCrcFlag | kI3C_MasterErrorReadFlag |
49                         kI3C_MasterErrorWriteFlag | kI3C_MasterErrorMsgFlag | kI3C_MasterErrorInvalidReqFlag |
50                         kI3C_MasterErrorTimeoutFlag,
51     /*! All flags which are cleared by the driver upon starting a transfer. */
52     kSlaveClearFlags = kI3C_SlaveBusStartFlag | kI3C_SlaveMatchedFlag | kI3C_SlaveBusStopFlag,
53 
54     /*! IRQ sources enabled by the non-blocking transactional API. */
55     kSlaveIrqFlags = kI3C_SlaveBusStartFlag | kI3C_SlaveMatchedFlag | kI3C_SlaveBusStopFlag | kI3C_SlaveRxReadyFlag |
56                      kI3C_SlaveDynamicAddrChangedFlag | kI3C_SlaveReceivedCCCFlag | kI3C_SlaveErrorFlag |
57                      kI3C_SlaveHDRCommandMatchFlag | kI3C_SlaveCCCHandledFlag | kI3C_SlaveEventSentFlag,
58 
59     /*! Errors to check for. */
60     kSlaveErrorFlags = kI3C_SlaveErrorOverrunFlag | kI3C_SlaveErrorUnderrunFlag | kI3C_SlaveErrorUnderrunNakFlag |
61                        kI3C_SlaveErrorTermFlag | kI3C_SlaveErrorInvalidStartFlag | kI3C_SlaveErrorSdrParityFlag |
62                        kI3C_SlaveErrorHdrParityFlag | kI3C_SlaveErrorHdrCRCFlag | kI3C_SlaveErrorS0S1Flag |
63                        kI3C_SlaveErrorOverreadFlag | kI3C_SlaveErrorOverwriteFlag,
64 };
65 
66 /*! @brief States for the state machine used by transactional APIs. */
67 enum _i3c_transfer_states
68 {
69     kIdleState = 0,
70     kIBIWonState,
71     kSlaveStartState,
72     kSendCommandState,
73     kWaitRepeatedStartCompleteState,
74     kTransferDataState,
75     kStopState,
76     kWaitForCompletionState,
77 };
78 
79 /*!
80  * @brief Used for conversion between `uint8_t*` and `uint32_t`.
81  */
82 typedef union i3c_puint8_to_u32
83 {
84     uint8_t *puint8;
85     uint32_t u32;
86     const uint8_t *cpuint8;
87 } i3c_puint8_to_u32_t;
88 
89 /*
90  * <! Structure definition for variables that passed as parameters in I3C_RunTransferStateMachine.
91  * The structure is private.
92  */
93 typedef struct _i3c_state_machine_param
94 {
95     bool state_complete;
96     size_t txCount;
97     size_t rxCount;
98     uint32_t status;
99     status_t result;
100     i3c_master_state_t masterState;
101 } i3c_master_state_machine_param_t;
102 
103 /*
104  * <! Structure definition for variables that passed as parameters in I3C_SlaveTransferHandleIRQ.
105  * The structure is private.
106  */
107 typedef struct _i3c_transfer_handleIrq_param
108 {
109     size_t txCount;
110     size_t rxCount;
111     uint32_t flags;
112     uint32_t pendingInts;
113     uint32_t enabledInts;
114 } i3c_slave_handleIrq_param_t;
115 
116 /*******************************************************************************
117  * Prototypes
118  ******************************************************************************/
119 
120 /* Not static so it can be used from fsl_i3c_dma.c. */
121 static status_t I3C_MasterWaitForTxReady(I3C_Type *base, uint8_t byteCounts);
122 /*******************************************************************************
123  * Variables
124  ******************************************************************************/
125 
126 /*! @brief Array to map I3C instance number to base pointer. */
127 static I3C_Type *const kI3cBases[] = I3C_BASE_PTRS;
128 
129 /*! @brief Array to map I3C instance number to IRQ number. */
130 IRQn_Type const kI3cIrqs[] = I3C_IRQS;
131 
132 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
133 /*! @brief Array to map I3C instance number to clock gate enum. */
134 static clock_ip_name_t const kI3cClocks[] = I3C_CLOCKS;
135 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
136 
137 #if !(defined(FSL_FEATURE_I3C_HAS_NO_RESET) && FSL_FEATURE_I3C_HAS_NO_RESET)
138 /*! @brief Pointers to I3C resets for each instance. */
139 static const reset_ip_name_t kI3cResets[] = I3C_RSTS;
140 #endif
141 
142 static i3c_device_info_t devList[I3C_MAX_DEVCNT]; /*!< I3C slave record list */
143 static uint8_t usedDevCount = 0;
144 
145 /*! @brief Pointer to master IRQ handler for each instance. */
146 i3c_master_isr_t s_i3cMasterIsr;
147 
148 /*! @brief Pointers to master handles for each instance. */
149 void *s_i3cMasterHandle[ARRAY_SIZE(kI3cBases)];
150 
151 /*! @brief Pointer to slave IRQ handler for each instance. */
152 i3c_slave_isr_t s_i3cSlaveIsr;
153 
154 /*! @brief Pointers to slave handles for each instance. */
155 void *s_i3cSlaveHandle[ARRAY_SIZE(kI3cBases)];
156 
157 /*!
158  * @brief introduce function I3C_TransferStateMachineIBIWonState.
159  * This function was deal with init function I3C_RunTransferStateMachine`s variable.
160  *
161  * @param base The I3C peripheral base address.
162  * @param handle handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
163  * @param stateParams Pass the address of the parent function variable.
164  */
165 static void I3C_TransferStateMachineIBIWonState(I3C_Type *base,
166                                                 i3c_master_handle_t *handle,
167                                                 i3c_master_state_machine_param_t *stateParams);
168 
169 /*!
170  * @brief introduce function static bool I3C_TransferStateMachineSendCommandState.
171  * This function was deal with when state is stop.
172  *
173  * @param base The I3C peripheral base address.
174  * @param handle handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
175  * @param stateParams Pass the address of the parent function variable.
176  */
177 static void I3C_TransferStateMachineSendCommandState(I3C_Type *base,
178                                                      i3c_master_handle_t *handle,
179                                                      i3c_master_state_machine_param_t *stateParams);
180 
181 /*!
182  * @brief introduce function I3C_TransferStateMachineWaitRepeatedStartCompleteState.
183  * This function was deal with Wait Repeated Start Complete State.
184  *
185  * @param base The I3C peripheral base address.
186  * @param handle handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
187  * @param stateParams Pass the address of the parent function variable.
188  */
189 static void I3C_TransferStateMachineWaitRepeatedStartCompleteState(I3C_Type *base,
190                                                                    i3c_master_handle_t *handle,
191                                                                    i3c_master_state_machine_param_t *stateParams);
192 
193 /*!
194  * @brief introduce function I3C_TransferStateMachineTransferDataState.
195  * This function was deal with Transfer Data State.
196  *
197  * @param base The I3C peripheral base address.
198  * @param handle handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
199  * @param stateParams Pass the address of the parent function variable.
200  */
201 static void I3C_TransferStateMachineTransferDataState(I3C_Type *base,
202                                                       i3c_master_handle_t *handle,
203                                                       i3c_master_state_machine_param_t *stateParams);
204 /*!
205  * @brief introduce function I3C_TransferStateMachineWaitForCompletionState.
206  * This function was deal with Wait For Completion State.
207  *
208  * @param handle handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
209  * @param stateParams Pass the address of the parent function variable.
210  */
211 static void I3C_TransferStateMachineWaitForCompletionState(i3c_master_handle_t *handle,
212                                                            i3c_master_state_machine_param_t *stateParams);
213 
214 /*!
215  * @brief introduce function I3C_TransferStateMachineStopState.
216  * This function was deal with Stop State.
217  *
218  * @param base The I3C peripheral base address.
219  * @param stateParams Pass the address of the parent function variable.
220  */
221 static void I3C_TransferStateMachineStopState(I3C_Type *base,
222                                               i3c_master_handle_t *handle,
223                                               i3c_master_state_machine_param_t *stateParams);
224 
225 /*!
226  * @brief introduce function I3C_SlaveTransferHandleGetStatusFlags.
227  * This function was deal get status flag.
228  *
229  * @param base The I3C peripheral base address.
230  * @param handle handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
231  * @param stateParams Pass the address of the parent function variable.
232  *
233  * @return default true when No abnormality.
234  * @return true when error.
235  */
236 static bool I3C_SlaveTransferHandleGetStatusFlags(I3C_Type *base,
237                                                   i3c_slave_handle_t *handle,
238                                                   i3c_slave_handleIrq_param_t *stateParams);
239 /*!
240  * @brief introduce function I3C_SlaveTransferHandleBusStart.
241  * This function was deal start Bus.
242  *
243  * @param base The I3C peripheral base address.
244  * @param xfer address to xfer.
245  * @param pendingInts address to pendingInts.
246  */
247 static void I3C_SlaveTransferHandleBusStart(I3C_Type *base, i3c_slave_transfer_t *xfer, uint32_t *pendingInts);
248 
249 /*!
250  * @brief introduce function I3C_SlaveTransferHandleEventSent.
251  * This function was deal sent event.
252  *
253  * @param base The I3C peripheral base address.
254  * @param handle handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
255  * @param xfer address to xfer.
256  */
257 static void I3C_SlaveTransferHandleEventSent(I3C_Type *base, i3c_slave_handle_t *handle, i3c_slave_transfer_t *xfer);
258 
259 /*!
260  * @brief introduce function I3C_SlaveTransferHandleReceivedCCC.
261  * This function was deal Received.
262  *
263  * @param base The I3C peripheral base address.
264  * @param handle handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
265  * @param xfer address to xfer.
266  */
267 static void I3C_SlaveTransferHandleReceivedCCC(I3C_Type *base, i3c_slave_handle_t *handle, i3c_slave_transfer_t *xfer);
268 
269 /*!
270  * @brief introduce function I3C_SlaveTransferHandleBusStop.
271  * This function was deal stop Bus.
272  *
273  * @param base The I3C peripheral base address.
274  * @param handle handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
275  * @param stateParams Pass the address of the parent function variable.
276  */
277 static void I3C_SlaveTransferHandleBusStop(I3C_Type *base,
278                                            i3c_slave_handle_t *handle,
279                                            i3c_slave_handleIrq_param_t *stateParams);
280 
281 /*!
282  * @brief introduce function I3C_SlaveTransferHandleMatched.
283  * This function was deal matched.
284  *
285  * @param base The I3C peripheral base address.
286  * @param handle handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
287  * @param xfer address to xfer.
288  */
289 static void I3C_SlaveTransferHandleMatched(I3C_Type *base, i3c_slave_handle_t *handle, i3c_slave_transfer_t *xfer);
290 
291 /*!
292  * @brief introduce function I3C_SlaveTransferHandleTxReady.
293  * This function was deal when Tx was ready.
294  *
295  * @param base The I3C peripheral base address.
296  * @param handle handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
297  * @param stateParams Pass the address of the parent function variable.
298  */
299 static void I3C_SlaveTransferHandleTxReady(I3C_Type *base,
300                                            i3c_slave_handle_t *handle,
301                                            i3c_slave_handleIrq_param_t *stateParams);
302 
303 /*!
304  * @brief introduce function I3C_SlaveTransferHandleRxReadyy.
305  * This function was deal with when Rx was ready.
306  *
307  * @param base The I3C peripheral base address.
308  * @param handle handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
309  * @param stateParams Pass the address of the parent function variable.
310  */
311 static void I3C_SlaveTransferHandleRxReady(I3C_Type *base,
312                                            i3c_slave_handle_t *handle,
313                                            i3c_slave_handleIrq_param_t *stateParams);
314 
315 /*******************************************************************************
316  * Code
317  ******************************************************************************/
318 
319 /*!
320  * @brief Returns an instance number given a base address.
321  *
322  * If an invalid base address is passed, debug builds will assert. Release builds will just return
323  * instance number 0.
324  *
325  * @param base The I3C peripheral base address.
326  * @return I3C instance number starting from 0.
327  */
I3C_GetInstance(I3C_Type * base)328 uint32_t I3C_GetInstance(I3C_Type *base)
329 {
330     uint32_t instance;
331     for (instance = 0; instance < ARRAY_SIZE(kI3cBases); ++instance)
332     {
333         if (kI3cBases[instance] == base)
334         {
335             break;
336         }
337     }
338 
339     assert(instance < ARRAY_SIZE(kI3cBases));
340 
341     return instance;
342 }
343 
344 /*!
345  * @brief Convert provided flags to status code, and clear any errors if present.
346  * @param base The I3C peripheral base address.
347  * @param status Current status flags value that will be checked.
348  * @retval #kStatus_Success
349  * @retval #kStatus_I3C_Nak
350  * @retval #kStatus_I3C_WriteAbort
351  * @retval #kStatus_I3C_Term
352  * @retval #kStatus_I3C_HdrParityError
353  * @retval #kStatus_I3C_CrcError
354  * @retval #kStatus_I3C_ReadFifoError
355  * @retval #kStatus_I3C_WriteFifoError
356  * @retval #kStatus_I3C_MsgError
357  * @retval #kStatus_I3C_InvalidReq
358  * @retval #kStatus_I3C_Timeout
359  */
360 /* Not static so it can be used from fsl_i3c_edma.c. */
I3C_MasterCheckAndClearError(I3C_Type * base,uint32_t status)361 status_t I3C_MasterCheckAndClearError(I3C_Type *base, uint32_t status)
362 {
363     status_t result = kStatus_Success;
364 
365     /* Check for error. These errors cause a stop to automatically be sent. We must */
366     /* clear the errors before a new transfer can start. */
367     status &= (uint32_t)kMasterErrorFlags;
368 
369 #if defined(I3C_DMA_IGNORE_FIFO_ERROR)
370     status &= ~((uint32_t)kI3C_MasterErrorWriteFlag | (uint32_t)kI3C_MasterErrorReadFlag);
371     I3C_MasterClearErrorStatusFlags(base, ((uint32_t)kI3C_MasterErrorWriteFlag | (uint32_t)kI3C_MasterErrorReadFlag));
372 #endif
373 
374     if (0UL != (status))
375     {
376         /* Select the correct error code. Ordered by severity, with bus issues first. */
377         if (0UL != (status & (uint32_t)kI3C_MasterErrorTimeoutFlag))
378         {
379             result = kStatus_I3C_Timeout;
380         }
381         else if (0UL != (status & (uint32_t)kI3C_MasterErrorNackFlag))
382         {
383             result = kStatus_I3C_Nak;
384         }
385         else if (0UL != (status & (uint32_t)kI3C_MasterErrorWriteAbortFlag))
386         {
387             result = kStatus_I3C_WriteAbort;
388         }
389 #if !defined(FSL_FEATURE_I3C_HAS_NO_MERRWARN_TERM) || (!FSL_FEATURE_I3C_HAS_NO_MERRWARN_TERM)
390         else if (0UL != (status & (uint32_t)kI3C_MasterErrorTermFlag))
391         {
392             result = kStatus_I3C_Term;
393         }
394 #endif
395         else if (0UL != (status & (uint32_t)kI3C_MasterErrorParityFlag))
396         {
397             result = kStatus_I3C_HdrParityError;
398         }
399         else if (0UL != (status & (uint32_t)kI3C_MasterErrorCrcFlag))
400         {
401             result = kStatus_I3C_CrcError;
402         }
403         else if (0UL != (status & (uint32_t)kI3C_MasterErrorMsgFlag))
404         {
405             result = kStatus_I3C_MsgError;
406         }
407         else if (0UL != (status & (uint32_t)kI3C_MasterErrorReadFlag))
408         {
409             result = kStatus_I3C_ReadFifoError;
410         }
411         else if (0UL != (status & (uint32_t)kI3C_MasterErrorWriteFlag))
412         {
413             result = kStatus_I3C_WriteFifoError;
414         }
415         else if (0UL != (status & (uint32_t)kI3C_MasterErrorInvalidReqFlag))
416         {
417             result = kStatus_I3C_InvalidReq;
418         }
419         else
420         {
421             assert(false);
422         }
423 
424         /* Clear the flags. */
425         I3C_MasterClearErrorStatusFlags(base, status);
426 
427         /* Reset fifos. These flags clear automatically. */
428         base->MDATACTRL |= I3C_MDATACTRL_FLUSHTB_MASK | I3C_MDATACTRL_FLUSHFB_MASK;
429     }
430 
431     return result;
432 }
433 
I3C_MasterWaitForCtrlDone(I3C_Type * base,bool waitIdle)434 static status_t I3C_MasterWaitForCtrlDone(I3C_Type *base, bool waitIdle)
435 {
436     status_t result = kStatus_Success;
437     uint32_t status, errStatus;
438 #if I3C_RETRY_TIMES
439     uint32_t waitTimes = I3C_RETRY_TIMES;
440 #endif
441 
442 #if I3C_RETRY_TIMES
443     while ((result == kStatus_Success) && (--waitTimes))
444 #else
445     while (result == kStatus_Success)
446 #endif
447     {
448         status    = I3C_MasterGetStatusFlags(base);
449         errStatus = I3C_MasterGetErrorStatusFlags(base);
450         /* Check for error flags. */
451         result = I3C_MasterCheckAndClearError(base, errStatus);
452         /* Check if the control finishes. */
453         if (0UL != (status & (uint32_t)kI3C_MasterControlDoneFlag))
454         {
455             I3C_MasterClearStatusFlags(base, (uint32_t)kI3C_MasterControlDoneFlag);
456             if (!waitIdle)
457             {
458                 break;
459             }
460         }
461         /* kI3C_MasterControlDoneFlag only indicates ACK got, need to wait for SDA high. */
462         if (waitIdle && I3C_MasterGetState(base) == kI3C_MasterStateIdle)
463         {
464             break;
465         }
466     }
467 
468 #if I3C_RETRY_TIMES
469     if (waitTimes == 0)
470     {
471         return kStatus_I3C_Timeout;
472     }
473 #endif
474 
475     return result;
476 }
477 
I3C_MasterWaitForTxReady(I3C_Type * base,uint8_t byteCounts)478 static status_t I3C_MasterWaitForTxReady(I3C_Type *base, uint8_t byteCounts)
479 {
480     uint32_t errStatus;
481     status_t result;
482     size_t txCount;
483     size_t txFifoSize =
484         2UL << ((base->SCAPABILITIES & I3C_SCAPABILITIES_FIFOTX_MASK) >> I3C_SCAPABILITIES_FIFOTX_SHIFT);
485 
486 #if I3C_RETRY_TIMES
487     uint32_t waitTimes = I3C_RETRY_TIMES;
488 #endif
489     do
490     {
491         /* Get the number of words in the tx fifo and compute empty slots. */
492         I3C_MasterGetFifoCounts(base, NULL, &txCount);
493         txCount = txFifoSize - txCount;
494 
495         /* Check for error flags. */
496         errStatus = I3C_MasterGetErrorStatusFlags(base);
497         result    = I3C_MasterCheckAndClearError(base, errStatus);
498         if (kStatus_Success != result)
499         {
500             return result;
501         }
502 #if I3C_RETRY_TIMES
503     } while ((txCount < byteCounts) && (--waitTimes));
504 
505     if (waitTimes == 0)
506     {
507         return kStatus_I3C_Timeout;
508     }
509 #else
510     } while (txCount < byteCounts);
511 #endif
512 
513     return kStatus_Success;
514 }
515 
I3C_MasterWaitForComplete(I3C_Type * base,bool waitIdle)516 static status_t I3C_MasterWaitForComplete(I3C_Type *base, bool waitIdle)
517 {
518     uint32_t status, errStatus;
519     status_t result = kStatus_Success;
520 #if I3C_RETRY_TIMES
521     uint32_t waitTimes = I3C_RETRY_TIMES;
522 #endif
523     do
524     {
525         status    = I3C_MasterGetStatusFlags(base);
526         errStatus = I3C_MasterGetErrorStatusFlags(base);
527         result    = I3C_MasterCheckAndClearError(base, errStatus);
528 #if I3C_RETRY_TIMES
529     } while (((status & (uint32_t)kI3C_MasterCompleteFlag) != (uint32_t)kI3C_MasterCompleteFlag) &&
530              (result == kStatus_Success) && --waitTimes);
531 #else
532     } while (((status & (uint32_t)kI3C_MasterCompleteFlag) != (uint32_t)kI3C_MasterCompleteFlag) &&
533              (result == kStatus_Success));
534 #endif
535 
536     I3C_MasterClearStatusFlags(base, (uint32_t)kI3C_MasterCompleteFlag);
537 
538 #if I3C_RETRY_TIMES
539     if (waitTimes == 0UL)
540     {
541         return kStatus_I3C_Timeout;
542     }
543 #endif
544 
545     if (waitIdle)
546     {
547 #if I3C_RETRY_TIMES
548         while ((I3C_MasterGetState(base) != kI3C_MasterStateIdle) && --waitTimes)
549 #else
550         while (I3C_MasterGetState(base) != kI3C_MasterStateIdle)
551 #endif
552         {
553         }
554     }
555 
556     return result;
557 }
558 
559 /*!
560  * @brief Convert provided flags to status code, and clear any errors if present.
561  * @param base The I3C peripheral base address.
562  * @param status Current status flags value that will be checked.
563  * @retval #kStatus_Success
564  * @retval #kStatus_I3C_OverrunError
565  * @retval #kStatus_I3C_UnderrunError
566  * @retval #kStatus_I3C_UnderrunNak
567  * @retval #kStatus_I3C_Term
568  * @retval #kStatus_I3C_InvalidStart
569  * @retval #kStatus_I3C_SdrParityError
570  * @retval #kStatus_I3C_HdrParityError
571  * @retval #kStatus_I3C_CrcError
572  * @retval #kStatus_I3C_S0S1Error
573  * @retval #kStatus_I3C_ReadFifoError
574  * @retval #kStatus_I3C_WriteFifoError
575  */
I3C_SlaveCheckAndClearError(I3C_Type * base,uint32_t status)576 status_t I3C_SlaveCheckAndClearError(I3C_Type *base, uint32_t status)
577 {
578     status_t result = kStatus_Success;
579 
580     /* Check for error. These errors cause a stop to automatically be sent. We must */
581     /* clear the errors before a new transfer can start. */
582     status &= (uint32_t)kSlaveErrorFlags;
583 
584 #if defined(I3C_DMA_IGNORE_FIFO_ERROR)
585     status &= ~((uint32_t)kI3C_SlaveErrorUnderrunFlag | (uint32_t)kI3C_SlaveErrorOverwriteFlag);
586     I3C_SlaveClearErrorStatusFlags(base,
587                                    ((uint32_t)kI3C_SlaveErrorUnderrunFlag | (uint32_t)kI3C_SlaveErrorOverwriteFlag));
588 #endif
589 
590     if (0UL != status)
591     {
592         /* Select the correct error code. Ordered by severity, with bus issues first. */
593         if (0UL != (status & (uint32_t)kI3C_SlaveErrorOverrunFlag))
594         {
595             result = kStatus_I3C_OverrunError;
596         }
597         else if (0UL != (status & (uint32_t)kI3C_SlaveErrorUnderrunFlag))
598         {
599             result = kStatus_I3C_UnderrunError;
600         }
601         else if (0UL != (status & (uint32_t)kI3C_SlaveErrorUnderrunNakFlag))
602         {
603             result = kStatus_I3C_UnderrunNak;
604         }
605         else if (0UL != (status & (uint32_t)kI3C_SlaveErrorTermFlag))
606         {
607             result = kStatus_I3C_Term;
608         }
609         else if (0UL != (status & (uint32_t)kI3C_SlaveErrorInvalidStartFlag))
610         {
611             result = kStatus_I3C_InvalidStart;
612         }
613         else if (0UL != (status & (uint32_t)kI3C_SlaveErrorSdrParityFlag))
614         {
615             result = kStatus_I3C_SdrParityError;
616         }
617         else if (0UL != (status & (uint32_t)kI3C_SlaveErrorHdrParityFlag))
618         {
619             result = kStatus_I3C_HdrParityError;
620         }
621         else if (0UL != (status & (uint32_t)kI3C_SlaveErrorHdrCRCFlag))
622         {
623             result = kStatus_I3C_CrcError;
624         }
625         else if (0UL != (status & (uint32_t)kI3C_SlaveErrorS0S1Flag))
626         {
627             result = kStatus_I3C_S0S1Error;
628         }
629         else if (0UL != (status & (uint32_t)kI3C_SlaveErrorOverreadFlag))
630         {
631             result = kStatus_I3C_ReadFifoError;
632         }
633         else if (0UL != (status & (uint32_t)kI3C_SlaveErrorOverwriteFlag))
634         {
635             result = kStatus_I3C_WriteFifoError;
636         }
637         else
638         {
639             assert(false);
640         }
641 
642         /* Clear the flags. */
643         I3C_SlaveClearErrorStatusFlags(base, status);
644 
645         /* Reset fifos. These flags clear automatically. */
646         base->SDATACTRL |= I3C_SDATACTRL_FLUSHTB_MASK | I3C_SDATACTRL_FLUSHFB_MASK;
647     }
648 
649     return result;
650 }
651 
I3C_SlaveWaitForTxReady(I3C_Type * base)652 static status_t I3C_SlaveWaitForTxReady(I3C_Type *base)
653 {
654     uint32_t errStatus;
655     status_t result;
656     size_t txCount;
657     size_t txFifoSize =
658         2UL << ((base->SCAPABILITIES & I3C_SCAPABILITIES_FIFOTX_MASK) >> I3C_SCAPABILITIES_FIFOTX_SHIFT);
659 
660 #if I3C_RETRY_TIMES
661     uint32_t waitTimes = I3C_RETRY_TIMES;
662 #endif
663     do
664     {
665         /* Get the number of words in the tx fifo and compute empty slots. */
666         I3C_SlaveGetFifoCounts(base, NULL, &txCount);
667         txCount = txFifoSize - txCount;
668 
669         /* Check for error flags. */
670         errStatus = I3C_SlaveGetErrorStatusFlags(base);
671         result    = I3C_SlaveCheckAndClearError(base, errStatus);
672         if (kStatus_Success != result)
673         {
674             return result;
675         }
676 #if I3C_RETRY_TIMES
677     } while ((txCount == 0UL) && (--waitTimes));
678 
679     if (waitTimes == 0)
680     {
681         return kStatus_I3C_Timeout;
682     }
683 #else
684     } while (txCount == 0UL);
685 #endif
686 
687     return kStatus_Success;
688 }
689 
I3C_MasterEmitStop(I3C_Type * base,bool waitIdle)690 static status_t I3C_MasterEmitStop(I3C_Type *base, bool waitIdle)
691 {
692     status_t result = kStatus_Success;
693 
694     /* Return an error if the bus is not in transaction. */
695     if (I3C_MasterGetState(base) != kI3C_MasterStateNormAct)
696     {
697         return kStatus_I3C_InvalidReq;
698     }
699 
700     /* Send the STOP signal */
701     base->MCTRL = (base->MCTRL & ~(I3C_MCTRL_REQUEST_MASK | I3C_MCTRL_DIR_MASK | I3C_MCTRL_RDTERM_MASK)) |
702                   I3C_MCTRL_REQUEST(kI3C_RequestEmitStop);
703 
704     /* Wait for the stop operation finishes. */
705     /* Also check for errors while waiting. */
706     result = I3C_MasterWaitForCtrlDone(base, waitIdle);
707 
708     return result;
709 }
710 
711 /*!
712  * brief I3C master get IBI Type.
713  *
714  * param base The I3C peripheral base address.
715  * param i3c_ibi_type_t Type of #i3c_ibi_type_t.
716  */
I3C_GetIBIType(I3C_Type * base)717 i3c_ibi_type_t I3C_GetIBIType(I3C_Type *base)
718 {
719     uint32_t ibiValue      = (base->MSTATUS & I3C_MSTATUS_IBITYPE_MASK) >> I3C_MSTATUS_IBITYPE_SHIFT;
720     i3c_ibi_type_t ibiType = kI3C_IbiNormal;
721 
722     switch (ibiValue)
723     {
724         case 3L:
725             ibiType = kI3C_IbiHotJoin;
726             break;
727         case 2L:
728             ibiType = kI3C_IbiMasterRequest;
729             break;
730         default:
731             ibiType = kI3C_IbiNormal;
732             break;
733     }
734 
735     return ibiType;
736 }
737 
738 /*!
739  * @brief Make sure the bus isn't already busy.
740  *
741  * A busy bus is allowed if we are the one driving it.
742  *
743  * @param base The I3C peripheral base address.
744  * @retval #kStatus_Success
745  * @retval #kStatus_I3C_Busy
746  */
747 /* Not static so it can be used from fsl_i3c_edma.c. */
I3C_CheckForBusyBus(I3C_Type * base)748 status_t I3C_CheckForBusyBus(I3C_Type *base)
749 {
750     return (I3C_MasterGetBusIdleState(base) == true) ? kStatus_Success : kStatus_I3C_Busy;
751 }
752 
753 /* brief Provides a default configuration for the I3C peripheral.
754  *
755  */
I3C_GetDefaultConfig(i3c_config_t * config)756 void I3C_GetDefaultConfig(i3c_config_t *config)
757 {
758     assert(NULL != config);
759 
760     (void)memset(config, 0, sizeof(*config));
761 
762     config->enableMaster                 = kI3C_MasterCapable;
763     config->disableTimeout               = false;
764     config->hKeep                        = kI3C_MasterHighKeeperNone;
765     config->enableOpenDrainStop          = true;
766     config->enableOpenDrainHigh          = true;
767     config->baudRate_Hz.i2cBaud          = 400000U;
768     config->baudRate_Hz.i3cPushPullBaud  = 12500000U;
769     config->baudRate_Hz.i3cOpenDrainBaud = 2500000U;
770     config->masterDynamicAddress         = 0x0AU;    /* Default master dynamic address. */
771     config->slowClock_Hz                 = 1000000U; /* Default slow timer clock 1MHz. */
772     config->enableSlave                  = true;
773     config->vendorID                     = 0x11BU;
774 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND)
775     config->enableRandomPart = false;
776 #endif
777     config->partNumber = 0;
778     config->dcr        = 0; /* Generic device. */
779     config->bcr = 0; /* BCR[7:6]: device role, I3C slave(2b'00), BCR[5]: SDR Only / SDR and HDR Capable,  SDR and HDR
780                         Capable(1b'1), BCR[4]: Bridge Identifier, Not a bridge device(1b'0), BCR[3]: Offline Capable,
781                         device is offline capable(1b'1), BCR[2]: IBI Payload, No data byte following(1b'0), BCR[1]: IBI
782                         Request Capable, capable(1b'1), BCR[0]: Max Data Speed Limitation, has limitation(1b'1). */
783     config->hdrMode             = (uint8_t)kI3C_HDRModeDDR;
784     config->nakAllRequest       = false;
785     config->ignoreS0S1Error     = false;
786     config->offline             = false;
787     config->matchSlaveStartStop = false;
788     config->maxWriteLength      = 256U;
789     config->maxReadLength       = 256U;
790 }
791 
792 /*!
793  * @brief Initializes the I3C peripheral.
794  *
795  */
I3C_Init(I3C_Type * base,const i3c_config_t * config,uint32_t sourceClock_Hz)796 void I3C_Init(I3C_Type *base, const i3c_config_t *config, uint32_t sourceClock_Hz)
797 {
798 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) || \
799     !(defined(FSL_FEATURE_I3C_HAS_NO_RESET) && FSL_FEATURE_I3C_HAS_NO_RESET)
800     uint32_t instance = I3C_GetInstance(base);
801 #endif
802 
803     uint32_t configValue;
804 
805 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
806     /* Ungate the clock. */
807     CLOCK_EnableClock(kI3cClocks[instance]);
808 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
809 
810 #if !(defined(FSL_FEATURE_I3C_HAS_NO_RESET) && FSL_FEATURE_I3C_HAS_NO_RESET)
811     /* Reset the I3C module */
812     RESET_PeripheralReset(kI3cResets[instance]);
813 #endif
814 
815     if ((config->masterDynamicAddress != 0U) && (config->enableMaster == kI3C_MasterOn))
816     {
817         base->MDYNADDR &= ~I3C_MDYNADDR_DADDR_MASK;
818         base->MDYNADDR |= I3C_MDYNADDR_DADDR(config->masterDynamicAddress) | I3C_MDYNADDR_DAVALID_MASK;
819     }
820 
821     base->MCONFIG = I3C_MCONFIG_MSTENA(config->enableMaster) | I3C_MCONFIG_DISTO(config->disableTimeout) |
822                     I3C_MCONFIG_HKEEP(config->hKeep) | I3C_MCONFIG_ODSTOP(config->enableOpenDrainStop) |
823                     I3C_MCONFIG_ODHPP(config->enableOpenDrainHigh);
824 
825     I3C_MasterSetWatermarks(base, kI3C_TxTriggerUntilOneLessThanFull, kI3C_RxTriggerOnNotEmpty, true, true);
826 
827     I3C_MasterSetBaudRate(base, &config->baudRate_Hz, sourceClock_Hz);
828 
829 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH)
830     uint8_t matchCount;
831     /* Caculate bus available condition match value for current slow clock, count value provides 1us.*/
832     matchCount = (uint8_t)(config->slowClock_Hz / 1000000UL);
833 #endif
834 
835     configValue = base->SCONFIG;
836 
837     configValue &=
838         ~(I3C_SCONFIG_SADDR_MASK |
839 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH)
840           I3C_SCONFIG_BAMATCH_MASK |
841 #endif
842           I3C_SCONFIG_OFFLINE_MASK |
843 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND)
844           I3C_SCONFIG_IDRAND_MASK |
845 #endif
846 #if defined(FSL_FEATURE_I3C_HAS_HDROK) && FSL_FEATURE_I3C_HAS_HDROK
847           I3C_SCONFIG_HDROK_MASK |
848 #else
849           I3C_SCONFIG_DDROK_MASK |
850 #endif
851           I3C_SCONFIG_S0IGNORE_MASK | I3C_SCONFIG_MATCHSS_MASK | I3C_SCONFIG_NACK_MASK | I3C_SCONFIG_SLVENA_MASK);
852 
853     configValue |= I3C_SCONFIG_SADDR(config->staticAddr) |
854 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH)
855                    I3C_SCONFIG_BAMATCH(matchCount) |
856 #endif
857                    I3C_SCONFIG_OFFLINE(config->offline) |
858 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND)
859                    I3C_SCONFIG_IDRAND(config->enableRandomPart) |
860 #endif
861 #if defined(FSL_FEATURE_I3C_HAS_HDROK) && FSL_FEATURE_I3C_HAS_HDROK
862                    I3C_SCONFIG_HDROK((0U != (config->hdrMode & (uint8_t)kI3C_HDRModeDDR)) ? 1U : 0U) |
863 #else
864                    I3C_SCONFIG_DDROK((0U != (config->hdrMode & (uint8_t)kI3C_HDRModeDDR)) ? 1U : 0U) |
865 #endif
866                    I3C_SCONFIG_S0IGNORE(config->ignoreS0S1Error) | I3C_SCONFIG_MATCHSS(config->matchSlaveStartStop) |
867                    I3C_SCONFIG_NACK(config->nakAllRequest) | I3C_SCONFIG_SLVENA(config->enableSlave);
868 
869     base->SVENDORID &= ~I3C_SVENDORID_VID_MASK;
870     base->SVENDORID |= I3C_SVENDORID_VID(config->vendorID);
871 
872 #if defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND
873     base->SIDPARTNO = config->partNumber;
874 #else
875     if (!config->enableRandomPart)
876     {
877         base->SIDPARTNO = config->partNumber;
878     }
879 #endif
880 
881     base->SIDEXT &= ~(I3C_SIDEXT_BCR_MASK | I3C_SIDEXT_DCR_MASK);
882     base->SIDEXT |= I3C_SIDEXT_BCR(config->bcr) | I3C_SIDEXT_DCR(config->dcr);
883 
884     base->SMAXLIMITS &= ~(I3C_SMAXLIMITS_MAXRD_MASK | I3C_SMAXLIMITS_MAXWR_MASK);
885     base->SMAXLIMITS |= (I3C_SMAXLIMITS_MAXRD(config->maxReadLength) | I3C_SMAXLIMITS_MAXWR(config->maxWriteLength));
886 
887     base->SCONFIG = configValue;
888 }
889 
890 /*!
891  * brief Provides a default configuration for the I3C master peripheral.
892  *
893  * This function provides the following default configuration for the I3C master peripheral:
894  * code
895  *  masterConfig->enableMaster            = kI3C_MasterOn;
896  *  masterConfig->disableTimeout          = false;
897  *  masterConfig->hKeep                   = kI3C_MasterHighKeeperNone;
898  *  masterConfig->enableOpenDrainStop     = true;
899  *  masterConfig->enableOpenDrainHigh     = true;
900  *  masterConfig->baudRate_Hz             = 100000U;
901  *  masterConfig->busType                 = kI3C_TypeI2C;
902  * endcode
903  *
904  * After calling this function, you can override any settings in order to customize the configuration,
905  * prior to initializing the master driver with I3C_MasterInit().
906  *
907  * param[out] masterConfig User provided configuration structure for default values. Refer to #i3c_master_config_t.
908  */
I3C_MasterGetDefaultConfig(i3c_master_config_t * masterConfig)909 void I3C_MasterGetDefaultConfig(i3c_master_config_t *masterConfig)
910 {
911     masterConfig->enableMaster                 = kI3C_MasterOn;
912     masterConfig->disableTimeout               = false;
913     masterConfig->hKeep                        = kI3C_MasterHighKeeperNone;
914     masterConfig->enableOpenDrainStop          = true;
915     masterConfig->enableOpenDrainHigh          = true;
916     masterConfig->baudRate_Hz.i2cBaud          = 400000U;
917     masterConfig->baudRate_Hz.i3cPushPullBaud  = 12500000U;
918     masterConfig->baudRate_Hz.i3cOpenDrainBaud = 2500000U;
919 }
920 
921 /*!
922  * brief Initializes the I3C master peripheral.
923  *
924  * This function enables the peripheral clock and initializes the I3C master peripheral as described by the user
925  * provided configuration. A software reset is performed prior to configuration.
926  *
927  * param base The I3C peripheral base address.
928  * param masterConfig User provided peripheral configuration. Use I3C_MasterGetDefaultConfig() to get a set of
929  * defaults that you can override.
930  * param sourceClock_Hz Frequency in Hertz of the I3C functional clock. Used to calculate the baud rate divisors,
931  *      filter widths, and timeout periods.
932  */
I3C_MasterInit(I3C_Type * base,const i3c_master_config_t * masterConfig,uint32_t sourceClock_Hz)933 void I3C_MasterInit(I3C_Type *base, const i3c_master_config_t *masterConfig, uint32_t sourceClock_Hz)
934 {
935 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) || \
936     !(defined(FSL_FEATURE_I3C_HAS_NO_RESET) && FSL_FEATURE_I3C_HAS_NO_RESET)
937     uint32_t instance = I3C_GetInstance(base);
938 #endif
939 
940 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
941     /* Ungate the clock. */
942     CLOCK_EnableClock(kI3cClocks[instance]);
943 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
944 
945 #if !(defined(FSL_FEATURE_I3C_HAS_NO_RESET) && FSL_FEATURE_I3C_HAS_NO_RESET)
946     /* Reset the I3C module */
947     RESET_PeripheralReset(kI3cResets[instance]);
948 #endif
949     base->MCONFIG = I3C_MCONFIG_MSTENA(masterConfig->enableMaster) | I3C_MCONFIG_DISTO(masterConfig->disableTimeout) |
950                     I3C_MCONFIG_HKEEP(masterConfig->hKeep) | I3C_MCONFIG_ODSTOP(masterConfig->enableOpenDrainStop) |
951                     I3C_MCONFIG_ODHPP(masterConfig->enableOpenDrainHigh);
952 
953     I3C_MasterSetWatermarks(base, kI3C_TxTriggerUntilOneLessThanFull, kI3C_RxTriggerOnNotEmpty, true, true);
954 
955     I3C_MasterSetBaudRate(base, &masterConfig->baudRate_Hz, sourceClock_Hz);
956 }
957 
958 /*!
959  * @brief Gets the I3C master state.
960  *
961  * @param base The I3C peripheral base address.
962  * @return I3C master state.
963  */
I3C_MasterGetState(I3C_Type * base)964 i3c_master_state_t I3C_MasterGetState(I3C_Type *base)
965 {
966     uint32_t masterState = (base->MSTATUS & I3C_MSTATUS_STATE_MASK) >> I3C_MSTATUS_STATE_SHIFT;
967     i3c_master_state_t returnCode;
968 
969     switch (masterState)
970     {
971         case (uint32_t)kI3C_MasterStateIdle:
972             returnCode = kI3C_MasterStateIdle;
973             break;
974         case (uint32_t)kI3C_MasterStateSlvReq:
975             returnCode = kI3C_MasterStateSlvReq;
976             break;
977         case (uint32_t)kI3C_MasterStateMsgSdr:
978             returnCode = kI3C_MasterStateMsgSdr;
979             break;
980         case (uint32_t)kI3C_MasterStateNormAct:
981             returnCode = kI3C_MasterStateNormAct;
982             break;
983         case (uint32_t)kI3C_MasterStateDdr:
984             returnCode = kI3C_MasterStateDdr;
985             break;
986         case (uint32_t)kI3C_MasterStateDaa:
987             returnCode = kI3C_MasterStateDaa;
988             break;
989         case (uint32_t)kI3C_MasterStateIbiAck:
990             returnCode = kI3C_MasterStateIbiAck;
991             break;
992         case (uint32_t)kI3C_MasterStateIbiRcv:
993             returnCode = kI3C_MasterStateIbiRcv;
994             break;
995         default:
996             returnCode = kI3C_MasterStateIdle;
997             break;
998     }
999 
1000     return returnCode;
1001 }
1002 
1003 /*!
1004  * brief Deinitializes the I3C master peripheral.
1005  *
1006  * This function disables the I3C master peripheral and gates the clock. It also performs a software
1007  * reset to restore the peripheral to reset conditions.
1008  *
1009  * param base The I3C peripheral base address.
1010  */
I3C_MasterDeinit(I3C_Type * base)1011 void I3C_MasterDeinit(I3C_Type *base)
1012 {
1013     uint32_t idx = I3C_GetInstance(base);
1014 
1015 #if !(defined(FSL_FEATURE_I3C_HAS_NO_RESET) && FSL_FEATURE_I3C_HAS_NO_RESET)
1016     /* Reset the I3C module */
1017     RESET_PeripheralReset(kI3cResets[idx]);
1018 #endif
1019 
1020 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1021     /* Gate clock. */
1022     CLOCK_DisableClock(kI3cClocks[idx]);
1023 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1024 
1025     /* Reset handle pointer. */
1026     s_i3cMasterHandle[idx] = NULL;
1027 }
1028 
I3C_CalcErrorRatio(uint32_t curFreq,uint32_t desiredFreq)1029 static uint32_t I3C_CalcErrorRatio(uint32_t curFreq, uint32_t desiredFreq)
1030 {
1031     if (curFreq > desiredFreq)
1032     {
1033         return (curFreq - desiredFreq) * 100UL / desiredFreq;
1034     }
1035     else
1036     {
1037         return (desiredFreq - curFreq) * 100UL / desiredFreq;
1038     }
1039 }
1040 
1041 /*!
1042  * brief Sets the I3C bus frequency for master transactions.
1043  *
1044  * The I3C master is automatically disabled and re-enabled as necessary to configure the baud
1045  * rate. Do not call this function during a transfer, or the transfer is aborted.
1046  *
1047  * param base The I3C peripheral base address.
1048  * param baudRate_Hz Pointer to structure of requested bus frequency in Hertz.
1049  * param sourceClock_Hz I3C functional clock frequency in Hertz.
1050  */
I3C_MasterSetBaudRate(I3C_Type * base,const i3c_baudrate_hz_t * baudRate_Hz,uint32_t sourceClock_Hz)1051 void I3C_MasterSetBaudRate(I3C_Type *base, const i3c_baudrate_hz_t *baudRate_Hz, uint32_t sourceClock_Hz)
1052 {
1053     uint32_t div, freq;
1054     uint32_t divEven, divOdd;
1055     uint32_t ppBaud, odBaud, i2cBaud;
1056     uint32_t errRate0, errRate1;
1057     uint32_t i3cPPBaud_HZ    = baudRate_Hz->i3cPushPullBaud;
1058     uint32_t i3cPPBaudMax_HZ = i3cPPBaud_HZ / 10U + i3cPPBaud_HZ; /* max is 1.1*i3cPPBaud_HZ */
1059     uint32_t i3cODBaud_HZ    = baudRate_Hz->i3cOpenDrainBaud;
1060     uint32_t i3cODBaudMax_HZ = i3cODBaud_HZ / 10U + i3cODBaud_HZ; /* max is 1.1*i3cODBaud_HZ */
1061     uint32_t i2cBaud_HZ      = baudRate_Hz->i2cBaud;
1062     uint32_t i3cPPLow_Ns, i3cOdLow_Ns;
1063     bool isODHigh = (0U != (base->MCONFIG & I3C_MCONFIG_ODHPP_MASK)) ? true : false;
1064 
1065     /* Find out the div to generate target freq */
1066     freq = sourceClock_Hz / 2UL;
1067     /* ppFreq = FCLK / 2 / (PPBAUD + 1)), 0 <= PPBAUD <= 15 */
1068     /* We need PPBAUD generate 12.5MHz or so. */
1069     div = freq / i3cPPBaud_HZ;
1070     div = (div == 0UL) ? 1UL : div;
1071     if (freq / div > i3cPPBaudMax_HZ)
1072     {
1073         div++;
1074     }
1075     assert(div <= FSL_I3C_PPBAUD_DIV_MAX);
1076     ppBaud = div - 1UL;
1077     freq /= div;
1078 
1079     i3cPPLow_Ns = (uint32_t)(NSEC_PER_SEC / (2UL * freq));
1080 
1081     /* We need ODBAUD generate 2.5MHz or so. */
1082     if (isODHigh)
1083     {
1084         /* odFreq = (2*freq) / (ODBAUD + 2), 1 <= ODBAUD <= 255 */
1085         div = (2UL * freq) / i3cODBaud_HZ;
1086         div = div < 2UL ? 2UL : div;
1087         if ((2UL * freq / div) > i3cODBaudMax_HZ)
1088         {
1089             div++;
1090         }
1091         odBaud = div - 2UL;
1092         freq   = (2UL * freq) / div;
1093     }
1094     else
1095     {
1096         /* odFreq = ppFreq / (ODBAUD + 1), 1 <= ODBAUD <= 255 */
1097         div = freq / i3cODBaud_HZ;
1098         div = div < 1UL ? 1UL : div;
1099         if (freq / div > i3cODBaudMax_HZ)
1100         {
1101             div++;
1102         }
1103         odBaud = div - 1UL;
1104         freq /= div;
1105     }
1106 
1107     i3cOdLow_Ns = (odBaud + 1UL) * i3cPPLow_Ns;
1108 
1109     /* i2cFreq = odFreq / (I2CBAUD + 1), 0 <= I2CBAUD <= 7 (I2CBAUD need << 1 in register) */
1110     /* i2cFreq = NSEC_PER_SEC / (I2CBAUD + 1)*i3cOdLow_Ns */
1111     divEven  = (sourceClock_Hz / i2cBaud_HZ) / (2UL * (ppBaud + 1UL) * (odBaud + 1UL));
1112     divEven  = divEven == 0UL ? 1UL : divEven;
1113     errRate0 = I3C_CalcErrorRatio((uint32_t)(NSEC_PER_SEC / (2UL * divEven * i3cOdLow_Ns)), i2cBaud_HZ);
1114 
1115     divOdd   = ((sourceClock_Hz / i2cBaud_HZ) / ((ppBaud + 1UL) * (odBaud + 1UL) - 1UL)) / 2UL;
1116     divOdd   = divOdd == 0UL ? 1UL : divOdd;
1117     errRate1 = I3C_CalcErrorRatio((uint32_t)(NSEC_PER_SEC / ((2UL * divOdd + 1UL) * i3cOdLow_Ns)), i2cBaud_HZ);
1118 
1119     if (errRate0 < FSL_I3C_ERROR_RATE_MAX || errRate1 < FSL_I3C_ERROR_RATE_MAX)
1120     {
1121         /* Use this div */
1122         i2cBaud = errRate0 < errRate1 ? (divEven - 1UL) * 2UL : (divOdd - 1UL) * 2UL + 1UL;
1123     }
1124     else
1125     {
1126         /* Use div + 1, unless current freq is already lower than desired. */
1127         i2cBaud = freq / divEven < i2cBaud_HZ ? (divEven - 1UL) * 2UL : divEven * 2UL;
1128     }
1129 
1130     base->MCONFIG = (base->MCONFIG & ~(I3C_MCONFIG_PPBAUD_MASK | I3C_MCONFIG_PPLOW_MASK | I3C_MCONFIG_ODBAUD_MASK |
1131                                        I3C_MCONFIG_I2CBAUD_MASK)) |
1132                     I3C_MCONFIG_PPBAUD(ppBaud) | I3C_MCONFIG_ODBAUD(odBaud) | I3C_MCONFIG_I2CBAUD(i2cBaud);
1133 }
1134 
1135 /*!
1136  * brief Sends a START signal and slave address on the I2C/I3C bus, receive size is also specified
1137  * in the call.
1138  * This function is used to initiate a new master mode transfer. First, the bus state is checked to ensure
1139  * that another master is not occupying the bus. Then a START signal is transmitted, followed by the
1140  * 7-bit address specified in the a address parameter. Note that this function does not actually wait
1141  * until the START and address are successfully sent on the bus before returning.
1142  *
1143  * param base The I3C peripheral base address.
1144  * param type The bus type to use in this transaction.
1145  * param address 7-bit slave device address, in bits [6:0].
1146  * param dir Master transfer direction, either #kI3C_Read or #kI3C_Write. This parameter is used to set
1147  *      the R/w bit (bit 0) in the transmitted slave address.
1148  * param rxSize Read terminate size for the followed read transfer, limit to 255 bytes.
1149  * retval #kStatus_Success START signal and address were successfully enqueued in the transmit FIFO.
1150  * retval #kStatus_I3C_Busy Another master is currently utilizing the bus.
1151  */
I3C_MasterStartWithRxSize(I3C_Type * base,i3c_bus_type_t type,uint8_t address,i3c_direction_t dir,uint8_t rxSize)1152 status_t I3C_MasterStartWithRxSize(
1153     I3C_Type *base, i3c_bus_type_t type, uint8_t address, i3c_direction_t dir, uint8_t rxSize)
1154 {
1155     i3c_master_state_t masterState = I3C_MasterGetState(base);
1156     bool checkDdrState             = (type == kI3C_TypeI3CDdr) ? (masterState != kI3C_MasterStateDdr) : true;
1157     if ((masterState != kI3C_MasterStateIdle) && (masterState != kI3C_MasterStateNormAct) && checkDdrState)
1158     {
1159         return kStatus_I3C_Busy;
1160     }
1161 
1162     return I3C_MasterRepeatedStartWithRxSize(base, type, address, dir, rxSize);
1163 }
1164 
1165 /*!
1166  * brief Sends a START signal and slave address on the I2C/I3C bus.
1167  *
1168  * This function is used to initiate a new master mode transfer. First, the bus state is checked to ensure
1169  * that another master is not occupying the bus. Then a START signal is transmitted, followed by the
1170  * 7-bit address specified in the a address parameter. Note that this function does not actually wait
1171  * until the START and address are successfully sent on the bus before returning.
1172  *
1173  * param base The I3C peripheral base address.
1174  * param type The bus type to use in this transaction.
1175  * param address 7-bit slave device address, in bits [6:0].
1176  * param dir Master transfer direction, either #kI3C_Read or #kI3C_Write. This parameter is used to set
1177  *      the R/w bit (bit 0) in the transmitted slave address.
1178  * retval #kStatus_Success START signal and address were successfully enqueued in the transmit FIFO.
1179  * retval #kStatus_I3C_Busy Another master is currently utilizing the bus.
1180  */
I3C_MasterStart(I3C_Type * base,i3c_bus_type_t type,uint8_t address,i3c_direction_t dir)1181 status_t I3C_MasterStart(I3C_Type *base, i3c_bus_type_t type, uint8_t address, i3c_direction_t dir)
1182 {
1183     i3c_master_state_t masterState = I3C_MasterGetState(base);
1184     bool checkDdrState             = (type == kI3C_TypeI3CDdr) ? (masterState != kI3C_MasterStateDdr) : true;
1185     if ((masterState != kI3C_MasterStateIdle) && (masterState != kI3C_MasterStateNormAct) && checkDdrState)
1186     {
1187         return kStatus_I3C_Busy;
1188     }
1189 
1190     return I3C_MasterStartWithRxSize(base, type, address, dir, 0);
1191 }
1192 
1193 /*!
1194  * brief Sends a repeated START signal and slave address on the I2C/I3C bus, receive size is also specified
1195  * in the call.
1196  *
1197  * This function is used to send a Repeated START signal when a transfer is already in progress. Like
1198  * I3C_MasterStart(), it also sends the specified 7-bit address. Call this API also configures the read
1199  * terminate size for the following read transfer. For example, set the rxSize = 2, the following read transfer
1200  * will be terminated after two bytes of data received. Write transfer will not be affected by the rxSize
1201  * configuration.
1202  *
1203  * note This function exists primarily to maintain compatible APIs between I3C and I2C drivers,
1204  *      as well as to better document the intent of code that uses these APIs.
1205  *
1206  * param base The I3C peripheral base address.
1207  * param type The bus type to use in this transaction.
1208  * param address 7-bit slave device address, in bits [6:0].
1209  * param dir Master transfer direction, either #kI3C_Read or #kI3C_Write. This parameter is used to set
1210  *      the R/w bit (bit 0) in the transmitted slave address.
1211  * param rxSize Read terminate size for the followed read transfer, limit to 255 bytes.
1212  * retval #kStatus_Success Repeated START signal and address were successfully enqueued in the transmit FIFO.
1213  */
I3C_MasterRepeatedStartWithRxSize(I3C_Type * base,i3c_bus_type_t type,uint8_t address,i3c_direction_t dir,uint8_t rxSize)1214 status_t I3C_MasterRepeatedStartWithRxSize(
1215     I3C_Type *base, i3c_bus_type_t type, uint8_t address, i3c_direction_t dir, uint8_t rxSize)
1216 {
1217     uint32_t mctrlVal;
1218 
1219     /* Clear all flags. */
1220     I3C_MasterClearStatusFlags(base, (uint32_t)kMasterClearFlags);
1221 
1222 #if defined(FSL_FEATURE_I3C_HAS_ERRATA_051617) && (FSL_FEATURE_I3C_HAS_ERRATA_051617)
1223     /* ERRATA051617: When used as I2C controller generates repeated START randomly before the STOP under PVT condition.
1224     This issue is caused by a glitch at the output of an internal clock MUX. The glitch when generates acts as a clock
1225     pulse which causes the SDA line to fall early during SCL high period and creates the unintended Repeated START before
1226     actual STOP. */
1227     if (type == kI3C_TypeI2C)
1228     {
1229         base->MCONFIG |= I3C_MCONFIG_SKEW(1);
1230     }
1231     else
1232     {
1233         base->MCONFIG &= ~I3C_MCONFIG_SKEW_MASK;
1234     }
1235 #endif
1236 
1237     /* Issue start command. */
1238     mctrlVal = base->MCTRL;
1239     mctrlVal &= ~(I3C_MCTRL_TYPE_MASK | I3C_MCTRL_REQUEST_MASK | I3C_MCTRL_DIR_MASK | I3C_MCTRL_ADDR_MASK |
1240                   I3C_MCTRL_RDTERM_MASK);
1241     mctrlVal |= I3C_MCTRL_TYPE(type) | I3C_MCTRL_REQUEST(kI3C_RequestEmitStartAddr) | I3C_MCTRL_DIR(dir) |
1242                 I3C_MCTRL_ADDR(address) | I3C_MCTRL_RDTERM(rxSize);
1243 
1244     base->MCTRL = mctrlVal;
1245 
1246     return kStatus_Success;
1247 }
1248 /*!
1249  * brief Sends a STOP signal on the I2C/I3C bus.
1250  *
1251  * This function does not return until the STOP signal is seen on the bus, or an error occurs.
1252  *
1253  * param base The I3C peripheral base address.
1254  * retval #kStatus_Success The STOP signal was successfully sent on the bus and the transaction terminated.
1255  * retval #kStatus_I3C_Busy Another master is currently utilizing the bus.
1256  * retval #kStatus_I3C_Nak The slave device sent a NAK in response to a byte.
1257  * retval #kStatus_I3C_FifoError FIFO under run or overrun.
1258  * retval #kStatus_I3C_ArbitrationLost Arbitration lost error.
1259  * retval #kStatus_I3C_PinLowTimeout SCL or SDA were held low longer than the timeout.
1260  */
I3C_MasterStop(I3C_Type * base)1261 status_t I3C_MasterStop(I3C_Type *base)
1262 {
1263     return I3C_MasterEmitStop(base, true);
1264 }
1265 
1266 /*!
1267  * brief I3C master emit request.
1268  *
1269  * param base The I3C peripheral base address.
1270  * param masterReq  I3C master request of type #i3c_bus_request_t
1271  */
I3C_MasterEmitRequest(I3C_Type * base,i3c_bus_request_t masterReq)1272 void I3C_MasterEmitRequest(I3C_Type *base, i3c_bus_request_t masterReq)
1273 {
1274     uint32_t mctrlReg = base->MCTRL;
1275 
1276     mctrlReg &= ~I3C_MCTRL_REQUEST_MASK;
1277 
1278     if (masterReq == kI3C_RequestProcessDAA)
1279     {
1280         mctrlReg &= ~I3C_MCTRL_TYPE_MASK;
1281     }
1282 
1283     mctrlReg |= I3C_MCTRL_REQUEST(masterReq);
1284 
1285     base->MCTRL = mctrlReg;
1286 }
1287 
1288 /*!
1289  * brief I3C master register IBI rule.
1290  *
1291  * param base The I3C peripheral base address.
1292  * param ibiRule Pointer to ibi rule description of type #i3c_register_ibi_addr_t
1293  */
I3C_MasterRegisterIBI(I3C_Type * base,i3c_register_ibi_addr_t * ibiRule)1294 void I3C_MasterRegisterIBI(I3C_Type *base, i3c_register_ibi_addr_t *ibiRule)
1295 {
1296     assert(NULL != ibiRule);
1297     uint32_t ruleValue = I3C_MIBIRULES_MSB0_MASK;
1298 
1299     for (uint32_t count = 0; count < ARRAY_SIZE(ibiRule->address); count++)
1300     {
1301         ruleValue |= ((uint32_t)ibiRule->address[count]) << (count * I3C_MIBIRULES_ADDR1_SHIFT);
1302     }
1303 
1304     ruleValue &= ~I3C_MIBIRULES_NOBYTE_MASK;
1305 
1306     if (!ibiRule->ibiHasPayload)
1307     {
1308         ruleValue |= I3C_MIBIRULES_NOBYTE_MASK;
1309     }
1310 
1311     base->MIBIRULES = ruleValue;
1312 }
1313 
1314 /*!
1315  * brief I3C master get IBI rule.
1316  *
1317  * param base The I3C peripheral base address.
1318  * param ibiRule Pointer to store the read out ibi rule description.
1319  */
I3C_MasterGetIBIRules(I3C_Type * base,i3c_register_ibi_addr_t * ibiRule)1320 void I3C_MasterGetIBIRules(I3C_Type *base, i3c_register_ibi_addr_t *ibiRule)
1321 {
1322     assert(NULL != ibiRule);
1323 
1324     uint32_t ruleValue = base->MIBIRULES;
1325 
1326     for (uint32_t count = 0; count < ARRAY_SIZE(ibiRule->address); count++)
1327     {
1328         ibiRule->address[count] =
1329             (uint8_t)(ruleValue >> (count * I3C_MIBIRULES_ADDR1_SHIFT)) & I3C_MIBIRULES_ADDR0_MASK;
1330     }
1331 
1332     ibiRule->ibiHasPayload = (0U == (ruleValue & I3C_MIBIRULES_NOBYTE_MASK));
1333 }
1334 
1335 /*!
1336  * brief Performs a polling receive transfer on the I2C/I3C bus.
1337  *
1338  * param base  The I3C peripheral base address.
1339  * param rxBuff The pointer to the data to be transferred.
1340  * param rxSize The length in bytes of the data to be transferred.
1341  * param flags Bit mask of options for the transfer. See enumeration #_i3c_master_transfer_flags for available options.
1342  * retval #kStatus_Success Data was received successfully.
1343  * retval #kStatus_I3C_Busy Another master is currently utilizing the bus.
1344  * retval #kStatus_I3C_Nak The slave device sent a NAK in response to a byte.
1345  * retval #kStatus_I3C_FifoError FIFO under run or overrun.
1346  * retval #kStatus_I3C_ArbitrationLost Arbitration lost error.
1347  * retval #kStatus_I3C_PinLowTimeout SCL or SDA were held low longer than the timeout.
1348  */
I3C_MasterReceive(I3C_Type * base,void * rxBuff,size_t rxSize,uint32_t flags)1349 status_t I3C_MasterReceive(I3C_Type *base, void *rxBuff, size_t rxSize, uint32_t flags)
1350 {
1351     status_t result   = kStatus_Success;
1352     bool isRxAutoTerm = ((flags & (uint32_t)kI3C_TransferRxAutoTermFlag) != 0UL);
1353     bool completed    = false;
1354     uint32_t status;
1355     uint8_t *buf;
1356 
1357     assert(NULL != rxBuff);
1358 
1359     /* Handle empty read. */
1360     if (rxSize == 0UL)
1361     {
1362         return kStatus_Success;
1363     }
1364 
1365 #if I3C_RETRY_TIMES
1366     uint32_t waitTimes = I3C_RETRY_TIMES;
1367 #endif
1368 
1369     /* Receive data */
1370     buf = (uint8_t *)rxBuff;
1371 
1372     while ((rxSize != 0UL) || !completed)
1373     {
1374 #if I3C_RETRY_TIMES
1375         if (--waitTimes == 0)
1376         {
1377             return kStatus_I3C_Timeout;
1378         }
1379 #endif
1380         /* Check for errors. */
1381         result = I3C_MasterCheckAndClearError(base, I3C_MasterGetErrorStatusFlags(base));
1382         if (kStatus_Success != result)
1383         {
1384             return result;
1385         }
1386 
1387         /* Check complete flag */
1388         if (!completed)
1389         {
1390             status = I3C_MasterGetStatusFlags(base) & (uint32_t)kI3C_MasterCompleteFlag;
1391             if (0UL != status)
1392             {
1393                 completed = true;
1394                 /* Clear complete flag */
1395                 I3C_MasterClearStatusFlags(base, (uint32_t)kI3C_MasterCompleteFlag);
1396                 /* Send stop if needed */
1397                 if ((flags & (uint32_t)kI3C_TransferNoStopFlag) == 0UL)
1398                 {
1399                     if (I3C_MasterGetState(base) == kI3C_MasterStateDdr)
1400                     {
1401                         I3C_MasterEmitRequest(base, kI3C_RequestForceExit);
1402                     }
1403                     else
1404                     {
1405                         result = I3C_MasterEmitStop(base, false);
1406                     }
1407                     if (kStatus_Success != result)
1408                     {
1409                         return result;
1410                     }
1411                 }
1412             }
1413         }
1414 
1415         /* Check RX data */
1416         if ((0UL != rxSize) && (0UL != (base->MDATACTRL & I3C_MDATACTRL_RXCOUNT_MASK)))
1417         {
1418             *buf++ = (uint8_t)(base->MRDATAB & I3C_MRDATAB_VALUE_MASK);
1419             rxSize--;
1420             if ((!isRxAutoTerm) && (rxSize == 1U))
1421             {
1422                 base->MCTRL |= I3C_MCTRL_RDTERM(1U);
1423             }
1424         }
1425     }
1426 
1427     /* Wait idle if stop is sent. */
1428     if ((flags & (uint32_t)kI3C_TransferNoStopFlag) == 0UL)
1429     {
1430 #if I3C_RETRY_TIMES
1431         while ((I3C_MasterGetState(base) != kI3C_MasterStateIdle) && --waitTimes)
1432 #else
1433         while (I3C_MasterGetState(base) != kI3C_MasterStateIdle)
1434 #endif
1435         {
1436         }
1437     }
1438     return result;
1439 }
1440 
1441 /*!
1442  * brief Performs a polling send transfer on the I2C/I3C bus.
1443  *
1444  * Sends up to a txSize number of bytes to the previously addressed slave device. The slave may
1445  * reply with a NAK to any byte in order to terminate the transfer early. If this happens, this
1446  * function returns #kStatus_I3C_Nak.
1447  *
1448  * param base  The I3C peripheral base address.
1449  * param txBuff The pointer to the data to be transferred.
1450  * param txSize The length in bytes of the data to be transferred.
1451  * param flags Bit mask of options for the transfer. See enumeration #_i3c_master_transfer_flags for available options.
1452  * retval #kStatus_Success Data was sent successfully.
1453  * retval #kStatus_I3C_Busy Another master is currently utilizing the bus.
1454  * retval #kStatus_I3C_Nak The slave device sent a NAK in response to a byte.
1455  * retval #kStatus_I3C_FifoError FIFO under run or over run.
1456  * retval #kStatus_I3C_ArbitrationLost Arbitration lost error.
1457  * retval #kStatus_I3C_PinLowTimeout SCL or SDA were held low longer than the timeout.
1458  */
I3C_MasterSend(I3C_Type * base,const void * txBuff,size_t txSize,uint32_t flags)1459 status_t I3C_MasterSend(I3C_Type *base, const void *txBuff, size_t txSize, uint32_t flags)
1460 {
1461     i3c_puint8_to_u32_t buf;
1462     buf.cpuint8     = (const uint8_t *)((const void *)txBuff);
1463     status_t result = kStatus_Success;
1464     bool enableWord = ((flags & (uint32_t)kI3C_TransferWordsFlag) == (uint32_t)kI3C_TransferWordsFlag) ? true : false;
1465     uint8_t byteCounts = enableWord ? 2U : 1U;
1466 
1467     assert(NULL != txBuff);
1468     if (enableWord)
1469     {
1470         assert(txSize % 2UL == 0UL);
1471     }
1472 
1473     /* Send data buffer */
1474     while (0UL != txSize)
1475     {
1476         /* Wait until there is room in the fifo. This also checks for errors. */
1477         result = I3C_MasterWaitForTxReady(base, byteCounts);
1478         if (kStatus_Success != result)
1479         {
1480             return result;
1481         }
1482 
1483         /* Write byte into I3C master data register. */
1484         if (txSize > byteCounts)
1485         {
1486             if (enableWord)
1487             {
1488                 base->MWDATAH = (uint32_t)buf.cpuint8[1] << 8UL | (uint32_t)buf.cpuint8[0];
1489             }
1490             else
1491             {
1492                 base->MWDATAB = *buf.cpuint8;
1493             }
1494         }
1495         else
1496         {
1497             if (enableWord)
1498             {
1499                 base->MWDATAHE = (uint32_t)buf.cpuint8[1] << 8UL | (uint32_t)buf.cpuint8[0];
1500             }
1501             else
1502             {
1503                 base->MWDATABE = *buf.cpuint8;
1504             }
1505         }
1506 
1507         buf.u32 = buf.u32 + byteCounts;
1508         txSize  = txSize - byteCounts;
1509     }
1510 
1511     result = I3C_MasterWaitForComplete(base, false);
1512     if ((result == kStatus_Success) && ((flags & (uint32_t)kI3C_TransferNoStopFlag) == 0UL))
1513     {
1514         if (I3C_MasterGetState(base) == kI3C_MasterStateDdr)
1515         {
1516             I3C_MasterEmitRequest(base, kI3C_RequestForceExit);
1517         }
1518         else
1519         {
1520             result = I3C_MasterEmitStop(base, true);
1521         }
1522     }
1523 
1524     return result;
1525 }
1526 
1527 /*!
1528  * brief Performs a DAA in the i3c bus with specified temporary baud rate.
1529  *
1530  * param base The I3C peripheral base address.
1531  * param addressList The pointer for address list which is used to do DAA.
1532  * param count The address count in the address list.
1533  * param daaBaudRate The temporary baud rate in DAA process, NULL for using initial setting.
1534  * The initial setting is set back between the completion of the DAA and the return of this function.
1535  * retval #kStatus_Success The transaction was started successfully.
1536  * retval #kStatus_I3C_Busy Either another master is currently utilizing the bus, or a non-blocking
1537  *      transaction is already in progress.
1538  * retval #kStatus_I3C_SlaveCountExceed The I3C slave count has exceed the definition in I3C_MAX_DEVCNT.
1539  */
I3C_MasterProcessDAASpecifiedBaudrate(I3C_Type * base,uint8_t * addressList,uint32_t count,i3c_master_daa_baudrate_t * daaBaudRate)1540 status_t I3C_MasterProcessDAASpecifiedBaudrate(I3C_Type *base,
1541                                                uint8_t *addressList,
1542                                                uint32_t count,
1543                                                i3c_master_daa_baudrate_t *daaBaudRate)
1544 {
1545     assert(addressList != NULL);
1546     assert(count != 0U);
1547 
1548     status_t result       = kStatus_Success;
1549     uint8_t rxBuffer[8]   = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};
1550     uint32_t masterConfig = 0;
1551     uint32_t devCount     = 0;
1552     uint8_t rxSize        = 0;
1553     bool mctrlDone        = false;
1554     i3c_baudrate_hz_t baudRate_Hz;
1555     uint32_t errStatus;
1556     uint32_t status;
1557     size_t rxCount;
1558 
1559     /* Return an error if the bus is already in use not by us. */
1560     result = I3C_CheckForBusyBus(base);
1561     if (kStatus_Success != result)
1562     {
1563         return result;
1564     }
1565 
1566     /* Clear all flags. */
1567     I3C_MasterClearErrorStatusFlags(base, (uint32_t)kMasterErrorFlags);
1568     I3C_MasterClearStatusFlags(base, (uint32_t)kMasterClearFlags);
1569 
1570     /* Disable I3C IRQ sources while we configure stuff. */
1571     uint32_t enabledInts = I3C_MasterGetEnabledInterrupts(base);
1572     I3C_MasterDisableInterrupts(base, enabledInts);
1573 
1574     /* Temporarily adjust baud rate before DAA. */
1575     if (daaBaudRate != NULL)
1576     {
1577         masterConfig = base->MCONFIG;
1578         /* Set non-zero value for I2C baud rate which is useless here. */
1579         baudRate_Hz.i2cBaud          = 1;
1580         baudRate_Hz.i3cOpenDrainBaud = daaBaudRate->i3cOpenDrainBaud;
1581         baudRate_Hz.i3cPushPullBaud  = daaBaudRate->i3cPushPullBaud;
1582         I3C_MasterSetBaudRate(base, &baudRate_Hz, daaBaudRate->sourceClock_Hz);
1583     }
1584 
1585     /* Emit process DAA */
1586     I3C_MasterEmitRequest(base, kI3C_RequestProcessDAA);
1587 
1588     do
1589     {
1590         status = I3C_MasterGetStatusFlags(base);
1591 
1592         /* Check for error flags. */
1593         errStatus = I3C_MasterGetErrorStatusFlags(base);
1594         result    = I3C_MasterCheckAndClearError(base, errStatus);
1595         if (kStatus_Success != result)
1596         {
1597             break;
1598         }
1599 
1600         if ((!mctrlDone) || (rxSize < 8U))
1601         {
1602             I3C_MasterGetFifoCounts(base, &rxCount, NULL);
1603 
1604             if ((0UL != (status & (uint32_t)kI3C_MasterRxReadyFlag)) && (rxCount != 0U))
1605             {
1606                 rxBuffer[rxSize++] = (uint8_t)(base->MRDATAB & I3C_MRDATAB_VALUE_MASK);
1607             }
1608 
1609             if ((status & (uint32_t)kI3C_MasterControlDoneFlag) != 0U)
1610             {
1611                 I3C_MasterClearStatusFlags(base, (uint32_t)kI3C_MasterControlDoneFlag);
1612                 mctrlDone = true;
1613             }
1614         }
1615         else if ((I3C_MasterGetState(base) == kI3C_MasterStateDaa) &&
1616                  (0UL != (I3C_MasterGetStatusFlags(base) & (uint32_t)kI3C_MasterBetweenFlag)))
1617         {
1618             if (((devCount + 1UL) > count) || ((devCount + 1UL) > I3C_MAX_DEVCNT))
1619             {
1620                 result = kStatus_I3C_SlaveCountExceed;
1621                 break;
1622             }
1623 
1624             /* Assign the dynamic address from address list. */
1625             devList[devCount].dynamicAddr = *addressList++;
1626             base->MWDATAB                 = devList[devCount].dynamicAddr;
1627 
1628             /* Emit process DAA again. */
1629             I3C_MasterEmitRequest(base, kI3C_RequestProcessDAA);
1630 
1631             devList[devCount].vendorID   = (((uint16_t)rxBuffer[0] << 8U | (uint16_t)rxBuffer[1]) & 0xFFFEU) >> 1U;
1632             devList[devCount].partNumber = ((uint32_t)rxBuffer[2] << 24U | (uint32_t)rxBuffer[3] << 16U |
1633                                             (uint32_t)rxBuffer[4] << 8U | (uint32_t)rxBuffer[5]);
1634             devList[devCount].bcr        = rxBuffer[6];
1635             devList[devCount].dcr        = rxBuffer[7];
1636             devCount++;
1637             usedDevCount++;
1638 
1639             /* Ready to handle next device. */
1640             mctrlDone = false;
1641             rxSize    = 0;
1642         }
1643         else
1644         {
1645             /* Intentional empty */
1646         }
1647     } while ((status & (uint32_t)kI3C_MasterCompleteFlag) != (uint32_t)kI3C_MasterCompleteFlag);
1648 
1649     /* Master stops DAA if slave device number exceeds the prepared address number. */
1650     if (result == kStatus_I3C_SlaveCountExceed)
1651     {
1652         /* Send the STOP signal */
1653         base->MCTRL = (base->MCTRL & ~(I3C_MCTRL_REQUEST_MASK | I3C_MCTRL_DIR_MASK | I3C_MCTRL_RDTERM_MASK)) |
1654                       I3C_MCTRL_REQUEST(kI3C_RequestEmitStop);
1655     }
1656 
1657     /* Set back initial baud rate after DAA is over. */
1658     if (daaBaudRate != NULL)
1659     {
1660         base->MCONFIG = masterConfig;
1661     }
1662 
1663     /* Clear all flags. */
1664     I3C_MasterClearErrorStatusFlags(base, (uint32_t)kMasterErrorFlags);
1665     I3C_MasterClearStatusFlags(base, (uint32_t)kMasterClearFlags);
1666 
1667     /* Enable I3C IRQ sources while we configure stuff. */
1668     I3C_MasterEnableInterrupts(base, enabledInts);
1669 
1670     return result;
1671 }
1672 
1673 /*!
1674  * brief Get device information list after DAA process is done.
1675  *
1676  * param base The I3C peripheral base address.
1677  * param[out] count The pointer to store the available device count.
1678  * return Pointer to the i3c_device_info_t array.
1679  */
I3C_MasterGetDeviceListAfterDAA(I3C_Type * base,uint8_t * count)1680 i3c_device_info_t *I3C_MasterGetDeviceListAfterDAA(I3C_Type *base, uint8_t *count)
1681 {
1682     assert(NULL != count);
1683 
1684     *count = usedDevCount;
1685 
1686     return devList;
1687 }
1688 
1689 /*!
1690  * @brief introduce function I3C_MasterClearFlagsAndEnableIRQ.
1691  *
1692  * This function was used of Clear all flags and Enable I3C IRQ sources for @param *base.
1693  *
1694  * @param base The I3C peripheral base address.
1695  */
I3C_MasterClearFlagsAndEnableIRQ(I3C_Type * base)1696 static void I3C_MasterClearFlagsAndEnableIRQ(I3C_Type *base)
1697 {
1698     /* Clear all flags. */
1699     I3C_MasterClearStatusFlags(base, (uint32_t)kMasterClearFlags);
1700     /* Enable I3C IRQ sources. */
1701     I3C_MasterEnableInterrupts(base, (uint32_t)kMasterIrqFlags);
1702 }
1703 
1704 /*!
1705  * @brief introduce function I3C_MasterTransferNoStartFlag.
1706  *
1707  * This function was used of Check if device request wins arbitration.
1708  *
1709  * @param base The I3C peripheral base address.
1710  * @param transfer Pointer to the transfer structure.
1711  * @retval #true if the device wins arbitration.
1712  * @retval #false if the device not wins arbitration.
1713  */
I3C_MasterTransferNoStartFlag(I3C_Type * base,i3c_master_transfer_t * transfer)1714 static bool I3C_MasterTransferNoStartFlag(I3C_Type *base, i3c_master_transfer_t *transfer)
1715 {
1716     /* Wait tx fifo empty. */
1717     size_t txCount = 0xFFUL;
1718 
1719     while (txCount != 0U)
1720     {
1721         I3C_MasterGetFifoCounts(base, NULL, &txCount);
1722     }
1723 
1724     /* Check if device request wins arbitration. */
1725     if (0UL != (I3C_MasterGetStatusFlags(base) & (uint32_t)kI3C_MasterArbitrationWonFlag))
1726     {
1727         I3C_MasterClearFlagsAndEnableIRQ(base);
1728         return true;
1729     }
1730     return false;
1731 }
1732 
1733 /*!
1734  * brief Performs a master polling transfer on the I2C/I3C bus.
1735  *
1736  * note The API does not return until the transfer succeeds or fails due
1737  * to error happens during transfer.
1738  *
1739  * param base The I3C peripheral base address.
1740  * param transfer Pointer to the transfer structure.
1741  * retval #kStatus_Success Data was received successfully.
1742  * retval #kStatus_I3C_Busy Another master is currently utilizing the bus.
1743  * retval #kStatus_I3C_Nak The slave device sent a NAK in response to a byte.
1744  * retval #kStatus_I3C_FifoError FIFO under run or overrun.
1745  * retval #kStatus_I3C_ArbitrationLost Arbitration lost error.
1746  * retval #kStatus_I3C_PinLowTimeout SCL or SDA were held low longer than the timeout.
1747  */
I3C_MasterTransferBlocking(I3C_Type * base,i3c_master_transfer_t * transfer)1748 status_t I3C_MasterTransferBlocking(I3C_Type *base, i3c_master_transfer_t *transfer)
1749 {
1750     assert(NULL != transfer);
1751     assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
1752 
1753     status_t result                = kStatus_Success;
1754     i3c_direction_t direction      = transfer->direction;
1755     i3c_master_state_t masterState = I3C_MasterGetState(base);
1756     bool checkDdrState             = false;
1757     bool isRxAutoTerm;
1758 
1759     /* Return an error if the bus is already in use not by us. */
1760     checkDdrState = (transfer->busType == kI3C_TypeI3CDdr) ? (masterState != kI3C_MasterStateDdr) : true;
1761 
1762     if ((masterState != kI3C_MasterStateIdle) && (masterState != kI3C_MasterStateNormAct) && checkDdrState)
1763     {
1764         return kStatus_I3C_Busy;
1765     }
1766 
1767     /* Clear all flags. */
1768     I3C_MasterClearStatusFlags(base, (uint32_t)kMasterClearFlags);
1769     /* Reset fifos. These flags clear automatically. */
1770     base->MDATACTRL |= I3C_MDATACTRL_FLUSHTB_MASK | I3C_MDATACTRL_FLUSHFB_MASK;
1771 
1772     /* Disable I3C IRQ sources while we configure stuff. */
1773     I3C_MasterDisableInterrupts(base, (uint32_t)kMasterIrqFlags);
1774 
1775     if (transfer->busType != kI3C_TypeI3CDdr)
1776     {
1777         direction = (0UL != transfer->subaddressSize) ? kI3C_Write : transfer->direction;
1778     }
1779 
1780     /* True: Set Rx termination bytes at start point, False: Set Rx termination one bytes in advance. */
1781     isRxAutoTerm = (transfer->dataSize <= 255U) ? true : false;
1782 
1783     if (0UL == (transfer->flags & (uint32_t)kI3C_TransferNoStartFlag))
1784     {
1785         if ((direction == kI3C_Read) && isRxAutoTerm)
1786         {
1787             result = I3C_MasterStartWithRxSize(base, transfer->busType, transfer->slaveAddress, direction,
1788                                                (uint8_t)transfer->dataSize);
1789         }
1790         else
1791         {
1792             result = I3C_MasterStart(base, transfer->busType, transfer->slaveAddress, direction);
1793         }
1794 
1795         if (true == I3C_MasterTransferNoStartFlag(base, transfer))
1796         {
1797             return kStatus_I3C_IBIWon;
1798         }
1799     }
1800     else
1801     {
1802         if (direction == kI3C_Read)
1803         {
1804             /* Can't set Rx termination more than one bytes in advance without START. */
1805             isRxAutoTerm = false;
1806         }
1807     }
1808 
1809     /* Subaddress, MSB first. */
1810     if (0U != transfer->subaddressSize)
1811     {
1812         uint32_t subaddressRemaining = transfer->subaddressSize;
1813         while (0UL != subaddressRemaining--)
1814         {
1815             uint8_t subaddressByte = (uint8_t)((transfer->subaddress >> (8UL * subaddressRemaining)) & 0xFFUL);
1816 
1817             result = I3C_MasterWaitForTxReady(base, 1U);
1818 
1819             if ((0UL == subaddressRemaining) && ((transfer->direction == kI3C_Read) || (0UL == transfer->dataSize)) &&
1820                 (transfer->busType != kI3C_TypeI3CDdr))
1821             {
1822                 base->MWDATABE = subaddressByte;
1823                 result         = I3C_MasterWaitForComplete(base, false);
1824                 if (kStatus_Success != result)
1825                 {
1826                     if (result == kStatus_I3C_Nak)
1827                     {
1828                         (void)I3C_MasterEmitStop(base, true);
1829                     }
1830                     I3C_MasterClearFlagsAndEnableIRQ(base);
1831                     return result;
1832                 }
1833             }
1834             else
1835             {
1836                 base->MWDATAB = subaddressByte;
1837             }
1838         }
1839         /* Need to send repeated start if switching directions to read. */
1840         if ((transfer->busType != kI3C_TypeI3CDdr) && (0UL != transfer->dataSize) && (transfer->direction == kI3C_Read))
1841         {
1842             if (isRxAutoTerm)
1843             {
1844                 result = I3C_MasterRepeatedStartWithRxSize(base, transfer->busType, transfer->slaveAddress, kI3C_Read,
1845                                                            (uint8_t)transfer->dataSize);
1846             }
1847             else
1848             {
1849                 result = I3C_MasterRepeatedStart(base, transfer->busType, transfer->slaveAddress, kI3C_Read);
1850             }
1851 
1852             if (kStatus_Success != result)
1853             {
1854                 I3C_MasterClearFlagsAndEnableIRQ(base);
1855                 return result;
1856             }
1857         }
1858     }
1859 
1860     if (isRxAutoTerm)
1861     {
1862         transfer->flags |= (uint32_t)kI3C_TransferRxAutoTermFlag;
1863     }
1864     else
1865     {
1866         transfer->flags &= ~(uint32_t)kI3C_TransferRxAutoTermFlag;
1867     }
1868 
1869     /* Transmit data. */
1870     if ((transfer->direction == kI3C_Write) && (transfer->dataSize > 0UL))
1871     {
1872         /* Send Data. */
1873         result = I3C_MasterSend(base, transfer->data, transfer->dataSize, transfer->flags);
1874     }
1875     /* Receive Data. */
1876     else if ((transfer->direction == kI3C_Read) && (transfer->dataSize > 0UL))
1877     {
1878         result = I3C_MasterReceive(base, transfer->data, transfer->dataSize, transfer->flags);
1879     }
1880     else
1881     {
1882         if ((transfer->flags & (uint32_t)kI3C_TransferNoStopFlag) == 0UL)
1883         {
1884             result = I3C_MasterEmitStop(base, true);
1885         }
1886     }
1887 
1888     if (result == kStatus_I3C_Nak)
1889     {
1890         (void)I3C_MasterEmitStop(base, true);
1891     }
1892 
1893     I3C_MasterClearFlagsAndEnableIRQ(base);
1894 
1895     return result;
1896 }
1897 
1898 /*!
1899  * brief Creates a new handle for the I3C master non-blocking APIs.
1900  *
1901  * The creation of a handle is for use with the non-blocking APIs. Once a handle
1902  * is created, there is not a corresponding destroy handle. If the user wants to
1903  * terminate a transfer, the I3C_MasterTransferAbort() API shall be called.
1904  *
1905  *
1906  * note The function also enables the NVIC IRQ for the input I3C. Need to notice
1907  * that on some SoCs the I3C IRQ is connected to INTMUX, in this case user needs to
1908  * enable the associated INTMUX IRQ in application.
1909  *
1910  * param base The I3C peripheral base address.
1911  * param[out] handle Pointer to the I3C master driver handle.
1912  * param callback User provided pointer to the asynchronous callback function.
1913  * param userData User provided pointer to the application callback data.
1914  */
I3C_MasterTransferCreateHandle(I3C_Type * base,i3c_master_handle_t * handle,const i3c_master_transfer_callback_t * callback,void * userData)1915 void I3C_MasterTransferCreateHandle(I3C_Type *base,
1916                                     i3c_master_handle_t *handle,
1917                                     const i3c_master_transfer_callback_t *callback,
1918                                     void *userData)
1919 {
1920     uint32_t instance;
1921 
1922     assert(NULL != handle);
1923 
1924     /* Clear out the handle. */
1925     (void)memset(handle, 0, sizeof(*handle));
1926 
1927     /* Look up instance number */
1928     instance = I3C_GetInstance(base);
1929 
1930     /* Save base and instance. */
1931     handle->callback = *callback;
1932     handle->userData = userData;
1933 
1934     /* Save this handle for IRQ use. */
1935     s_i3cMasterHandle[instance] = handle;
1936 
1937     /* Set irq handler. */
1938     s_i3cMasterIsr = I3C_MasterTransferHandleIRQ;
1939 
1940     /* Clear all flags. */
1941     I3C_MasterClearErrorStatusFlags(base, (uint32_t)kMasterErrorFlags);
1942     I3C_MasterClearStatusFlags(base, (uint32_t)kMasterClearFlags);
1943     /* Reset fifos. These flags clear automatically. */
1944     base->MDATACTRL |= I3C_MDATACTRL_FLUSHTB_MASK | I3C_MDATACTRL_FLUSHFB_MASK;
1945 
1946     /* Enable NVIC IRQ, this only enables the IRQ directly connected to the NVIC.
1947      In some cases the I3C IRQ is configured through INTMUX, user needs to enable
1948      INTMUX IRQ in application code. */
1949     (void)EnableIRQ(kI3cIrqs[instance]);
1950 
1951     /* Clear internal IRQ enables and enable NVIC IRQ. */
1952     I3C_MasterEnableInterrupts(base, (uint32_t)kMasterIrqFlags);
1953 }
1954 
I3C_TransferStateMachineIBIWonState(I3C_Type * base,i3c_master_handle_t * handle,i3c_master_state_machine_param_t * stateParams)1955 static void I3C_TransferStateMachineIBIWonState(I3C_Type *base,
1956                                                 i3c_master_handle_t *handle,
1957                                                 i3c_master_state_machine_param_t *stateParams)
1958 {
1959     assert(NULL != base && NULL != handle && NULL != stateParams);
1960     if (stateParams->masterState == kI3C_MasterStateIbiAck)
1961     {
1962         handle->ibiType = I3C_GetIBIType(base);
1963         if (handle->callback.ibiCallback != NULL)
1964         {
1965             handle->callback.ibiCallback(base, handle, handle->ibiType, kI3C_IbiAckNackPending);
1966         }
1967         else
1968         {
1969             I3C_MasterEmitIBIResponse(base, kI3C_IbiRespNack);
1970         }
1971     }
1972 
1973     /* Make sure there is data in the rx fifo. */
1974     if (0UL != stateParams->rxCount)
1975     {
1976         if ((handle->ibiBuff == NULL) && (handle->callback.ibiCallback != NULL))
1977         {
1978             handle->callback.ibiCallback(base, handle, kI3C_IbiNormal, kI3C_IbiDataBuffNeed);
1979         }
1980         uint8_t tempData = (uint8_t)base->MRDATAB;
1981         if (handle->ibiBuff != NULL)
1982         {
1983             handle->ibiBuff[handle->ibiPayloadSize++] = tempData;
1984         }
1985         (stateParams->rxCount)--;
1986         return;
1987     }
1988     else if (0UL != (stateParams->status & (uint32_t)kI3C_MasterCompleteFlag))
1989     {
1990         handle->ibiType             = I3C_GetIBIType(base);
1991         handle->ibiAddress          = I3C_GetIBIAddress(base);
1992         stateParams->state_complete = true;
1993         stateParams->result         = kStatus_I3C_IBIWon;
1994     }
1995     else
1996     {
1997         stateParams->state_complete = true;
1998     }
1999 }
2000 
I3C_TransferStateMachineSendCommandState(I3C_Type * base,i3c_master_handle_t * handle,i3c_master_state_machine_param_t * stateParams)2001 static void I3C_TransferStateMachineSendCommandState(I3C_Type *base,
2002                                                      i3c_master_handle_t *handle,
2003                                                      i3c_master_state_machine_param_t *stateParams)
2004 {
2005     assert(NULL != base && NULL != handle && NULL != stateParams);
2006     I3C_MasterEnableInterrupts(base, (uint32_t)kI3C_MasterTxReadyFlag);
2007     /* Make sure there is room in the tx fifo for the next command. */
2008     if (0UL == (stateParams->txCount)--)
2009     {
2010         stateParams->state_complete = true;
2011         return;
2012     }
2013     if (handle->transfer.subaddressSize > 1U)
2014     {
2015         handle->transfer.subaddressSize--;
2016         base->MWDATAB = (uint8_t)((handle->transfer.subaddress) >> (8U * handle->transfer.subaddressSize));
2017     }
2018     else if (handle->transfer.subaddressSize == 1U)
2019     {
2020         handle->transfer.subaddressSize--;
2021 
2022         if ((handle->transfer.direction == kI3C_Read) || (0UL == handle->transfer.dataSize))
2023         {
2024             base->MWDATABE = (uint8_t)((handle->transfer.subaddress) >> (8U * handle->transfer.subaddressSize));
2025 
2026             if (0UL == handle->transfer.dataSize)
2027             {
2028                 handle->state = (uint8_t)kWaitForCompletionState;
2029             }
2030             else
2031             {
2032                 /* xfer->dataSize != 0U, xfer->direction = kI3C_Read */
2033                 handle->state = (uint8_t)kWaitRepeatedStartCompleteState;
2034             }
2035         }
2036         else
2037         {
2038             /* Next state, transfer data. */
2039             handle->state = (uint8_t)kTransferDataState;
2040             base->MWDATAB = (uint8_t)((handle->transfer.subaddress) >> (8U * handle->transfer.subaddressSize));
2041         }
2042     }
2043     else
2044     {
2045         /* Eliminate misra 15.7*/
2046     }
2047 }
2048 
I3C_TransferStateMachineWaitRepeatedStartCompleteState(I3C_Type * base,i3c_master_handle_t * handle,i3c_master_state_machine_param_t * stateParams)2049 static void I3C_TransferStateMachineWaitRepeatedStartCompleteState(I3C_Type *base,
2050                                                                    i3c_master_handle_t *handle,
2051                                                                    i3c_master_state_machine_param_t *stateParams)
2052 {
2053     assert(NULL != base && NULL != handle && NULL != stateParams);
2054     /* We stay in this state until the master complete. */
2055     if (0UL != (stateParams->status & (uint32_t)kI3C_MasterCompleteFlag))
2056     {
2057         handle->state = (uint8_t)kTransferDataState;
2058         I3C_MasterDisableInterrupts(base, (uint32_t)kI3C_MasterTxReadyFlag);
2059 
2060         if (handle->remainingBytes < 256U)
2061         {
2062             handle->isRxAutoTerm = true;
2063             stateParams->result =
2064                 I3C_MasterRepeatedStartWithRxSize(base, handle->transfer.busType, handle->transfer.slaveAddress,
2065                                                   kI3C_Read, (uint8_t)handle->remainingBytes);
2066         }
2067         else
2068         {
2069             stateParams->result =
2070                 I3C_MasterRepeatedStart(base, handle->transfer.busType, handle->transfer.slaveAddress, kI3C_Read);
2071         }
2072     }
2073 
2074     stateParams->state_complete = true;
2075 }
2076 
I3C_TransferStateMachineTransferDataState(I3C_Type * base,i3c_master_handle_t * handle,i3c_master_state_machine_param_t * stateParams)2077 static void I3C_TransferStateMachineTransferDataState(I3C_Type *base,
2078                                                       i3c_master_handle_t *handle,
2079                                                       i3c_master_state_machine_param_t *stateParams)
2080 {
2081     assert(NULL != base && NULL != handle && NULL != stateParams);
2082 
2083     i3c_puint8_to_u32_t dataBuff;
2084     if (handle->transfer.direction == kI3C_Write)
2085     {
2086         /* Make sure there is room in the tx fifo. */
2087         if (0UL == (stateParams->txCount)--)
2088         {
2089             stateParams->state_complete = true;
2090             return;
2091         }
2092 
2093         /* Put byte to send in fifo. */
2094         dataBuff.puint8 = (uint8_t *)handle->transfer.data;
2095         if (handle->transfer.dataSize > 1U)
2096         {
2097             base->MWDATAB = *dataBuff.puint8;
2098         }
2099         else
2100         {
2101             base->MWDATABE = *dataBuff.puint8;
2102         }
2103         dataBuff.u32 = dataBuff.u32 + 1U;
2104         (handle->transfer.dataSize)--;
2105         handle->transfer.data = (void *)(dataBuff.puint8);
2106 
2107         /* Move to stop when the transfer is done. */
2108         if (--handle->remainingBytes == 0UL)
2109         {
2110             handle->state = (uint8_t)kWaitForCompletionState;
2111         }
2112     }
2113     else
2114     {
2115         /* Make sure there is data in the rx fifo. */
2116         if (0UL == (stateParams->rxCount)--)
2117         {
2118             stateParams->state_complete = true;
2119             return;
2120         }
2121 
2122         /* Read byte from fifo. */
2123         dataBuff.puint8       = (uint8_t *)handle->transfer.data;
2124         *dataBuff.puint8      = (uint8_t)base->MRDATAB;
2125         dataBuff.u32          = dataBuff.u32 + 1U;
2126         handle->transfer.data = (void *)(dataBuff.puint8);
2127 
2128         /* Move to stop when the transfer is done. */
2129         if (--handle->remainingBytes == 0UL)
2130         {
2131             handle->isRxAutoTerm = false;
2132             handle->state        = (uint8_t)kWaitForCompletionState;
2133         }
2134 
2135         if (!handle->isRxAutoTerm && (handle->remainingBytes == 1UL))
2136         {
2137             base->MCTRL |= I3C_MCTRL_RDTERM(1UL);
2138         }
2139     }
2140 }
2141 
I3C_TransferStateMachineWaitForCompletionState(i3c_master_handle_t * handle,i3c_master_state_machine_param_t * stateParams)2142 static void I3C_TransferStateMachineWaitForCompletionState(i3c_master_handle_t *handle,
2143                                                            i3c_master_state_machine_param_t *stateParams)
2144 {
2145     /* We stay in this state until the maste complete. */
2146     if (0UL != (stateParams->status & (uint32_t)kI3C_MasterCompleteFlag))
2147     {
2148         handle->state = (uint8_t)kStopState;
2149     }
2150     else
2151     {
2152         stateParams->state_complete = true;
2153     }
2154 }
2155 
I3C_TransferStateMachineStopState(I3C_Type * base,i3c_master_handle_t * handle,i3c_master_state_machine_param_t * stateParams)2156 static void I3C_TransferStateMachineStopState(I3C_Type *base,
2157                                               i3c_master_handle_t *handle,
2158                                               i3c_master_state_machine_param_t *stateParams)
2159 {
2160     /* Only issue a stop transition if the caller requested it. */
2161     if (0UL == (handle->transfer.flags & (uint32_t)kI3C_TransferNoStopFlag))
2162     {
2163         /* Make sure there is room in the tx fifo for the stop command. */
2164         if (0UL == (stateParams->txCount)--)
2165         {
2166             stateParams->state_complete = true;
2167             return;
2168         }
2169         if (handle->transfer.busType == kI3C_TypeI3CDdr)
2170         {
2171             I3C_MasterEmitRequest(base, kI3C_RequestForceExit);
2172         }
2173         else
2174         {
2175             (void)I3C_MasterEmitStop(base, false);
2176         }
2177     }
2178     stateParams->state_complete = true;
2179 }
2180 
I3C_RunTransferStateMachine(I3C_Type * base,i3c_master_handle_t * handle,bool * isDone)2181 static status_t I3C_RunTransferStateMachine(I3C_Type *base, i3c_master_handle_t *handle, bool *isDone)
2182 {
2183     i3c_master_state_machine_param_t stateParams;
2184     (void)memset(&stateParams, 0, sizeof(stateParams));
2185 
2186     stateParams.result         = kStatus_Success;
2187     stateParams.state_complete = false;
2188 
2189     /* Set default isDone return value. */
2190     *isDone = false;
2191 
2192     uint32_t errStatus;
2193     size_t txFifoSize =
2194         2UL << ((base->SCAPABILITIES & I3C_SCAPABILITIES_FIFOTX_MASK) >> I3C_SCAPABILITIES_FIFOTX_SHIFT);
2195 
2196     /* Check for errors. */
2197     stateParams.status = (uint32_t)I3C_MasterGetPendingInterrupts(base);
2198     I3C_MasterClearStatusFlags(base, stateParams.status);
2199 
2200     stateParams.masterState = I3C_MasterGetState(base);
2201     errStatus               = I3C_MasterGetErrorStatusFlags(base);
2202     stateParams.result      = I3C_MasterCheckAndClearError(base, errStatus);
2203     if (kStatus_Success != stateParams.result)
2204     {
2205         return stateParams.result;
2206     }
2207 
2208     if (0UL != (stateParams.status & (uint32_t)kI3C_MasterSlave2MasterFlag))
2209     {
2210         if (handle->callback.slave2Master != NULL)
2211         {
2212             handle->callback.slave2Master(base, handle->userData);
2213         }
2214     }
2215 
2216     if ((0UL != (stateParams.status & (uint32_t)kI3C_MasterSlaveStartFlag)) &&
2217         (handle->transfer.busType != kI3C_TypeI2C))
2218     {
2219         handle->state = (uint8_t)kSlaveStartState;
2220     }
2221 
2222     if ((stateParams.masterState == kI3C_MasterStateIbiRcv) || (stateParams.masterState == kI3C_MasterStateIbiAck))
2223     {
2224         handle->state = (uint8_t)kIBIWonState;
2225     }
2226 
2227     if (handle->state == (uint8_t)kIdleState)
2228     {
2229         return stateParams.result;
2230     }
2231 
2232     /* Get fifo counts and compute room in tx fifo. */
2233     I3C_MasterGetFifoCounts(base, &stateParams.rxCount, &stateParams.txCount);
2234     stateParams.txCount = txFifoSize - stateParams.txCount;
2235 
2236     while (!stateParams.state_complete)
2237     {
2238         /* Execute the state. */
2239         switch (handle->state)
2240         {
2241             case (uint8_t)kSlaveStartState:
2242                 /* Emit start + 0x7E */
2243                 I3C_MasterEmitRequest(base, kI3C_RequestAutoIbi);
2244                 handle->state              = (uint8_t)kIBIWonState;
2245                 stateParams.state_complete = true;
2246                 break;
2247 
2248             case (uint8_t)kIBIWonState:
2249                 I3C_TransferStateMachineIBIWonState(base, handle, &stateParams);
2250                 break;
2251 
2252             case (uint8_t)kSendCommandState:
2253                 I3C_TransferStateMachineSendCommandState(base, handle, &stateParams);
2254                 break;
2255 
2256             case (uint8_t)kWaitRepeatedStartCompleteState:
2257                 I3C_TransferStateMachineWaitRepeatedStartCompleteState(base, handle, &stateParams);
2258                 break;
2259 
2260             case (uint8_t)kTransferDataState:
2261                 I3C_TransferStateMachineTransferDataState(base, handle, &stateParams);
2262                 break;
2263 
2264             case (uint8_t)kWaitForCompletionState:
2265                 I3C_TransferStateMachineWaitForCompletionState(handle, &stateParams);
2266                 break;
2267 
2268             case (uint8_t)kStopState:
2269                 I3C_TransferStateMachineStopState(base, handle, &stateParams);
2270                 *isDone = true;
2271                 break;
2272 
2273             default:
2274                 assert(false);
2275                 break;
2276         }
2277     }
2278     return stateParams.result;
2279 }
2280 
I3C_InitTransferStateMachine(I3C_Type * base,i3c_master_handle_t * handle)2281 static status_t I3C_InitTransferStateMachine(I3C_Type *base, i3c_master_handle_t *handle)
2282 {
2283     i3c_master_transfer_t *xfer = &handle->transfer;
2284     status_t result             = kStatus_Success;
2285     i3c_direction_t direction   = xfer->direction;
2286 
2287     if (xfer->busType != kI3C_TypeI3CDdr)
2288     {
2289         direction = (0UL != xfer->subaddressSize) ? kI3C_Write : xfer->direction;
2290     }
2291 
2292     /* Handle no start option. */
2293     if (0U != (xfer->flags & (uint32_t)kI3C_TransferNoStartFlag))
2294     {
2295         /* No need to send start flag, directly go to send command or data */
2296         if (xfer->subaddressSize > 0UL)
2297         {
2298             handle->state = (uint8_t)kSendCommandState;
2299         }
2300         else
2301         {
2302             if (direction == kI3C_Write)
2303             {
2304                 /* Next state, send data. */
2305                 handle->state = (uint8_t)kTransferDataState;
2306             }
2307             else
2308             {
2309                 /* Only support write with no stop signal. */
2310                 return kStatus_InvalidArgument;
2311             }
2312         }
2313         I3C_MasterTransferHandleIRQ(base, handle);
2314         return result;
2315     }
2316     /* If repeated start is requested, send repeated start. */
2317     else if (0U != (xfer->flags & (uint32_t)kI3C_TransferRepeatedStartFlag))
2318     {
2319         result = I3C_MasterRepeatedStart(base, xfer->busType, xfer->slaveAddress, direction);
2320     }
2321     else /* For normal transfer, send start. */
2322     {
2323         result = I3C_MasterStart(base, xfer->busType, xfer->slaveAddress, direction);
2324     }
2325 
2326     if (xfer->subaddressSize > 0U)
2327     {
2328         handle->state = (uint8_t)kSendCommandState;
2329     }
2330     else
2331     {
2332         handle->state = (uint8_t)kTransferDataState;
2333     }
2334 
2335     if ((handle->remainingBytes < 256U) && (direction == kI3C_Read))
2336     {
2337         handle->isRxAutoTerm = true;
2338         base->MCTRL |= I3C_MCTRL_RDTERM(handle->remainingBytes);
2339     }
2340 
2341     return result;
2342 }
2343 
2344 /*!
2345  * brief Performs a non-blocking transaction on the I2C/I3C bus.
2346  *
2347  * param base The I3C peripheral base address.
2348  * param handle Pointer to the I3C master driver handle.
2349  * param transfer The pointer to the transfer descriptor.
2350  * retval #kStatus_Success The transaction was started successfully.
2351  * retval #kStatus_I3C_Busy Either another master is currently utilizing the bus, or a non-blocking
2352  *      transaction is already in progress.
2353  */
I3C_MasterTransferNonBlocking(I3C_Type * base,i3c_master_handle_t * handle,i3c_master_transfer_t * transfer)2354 status_t I3C_MasterTransferNonBlocking(I3C_Type *base, i3c_master_handle_t *handle, i3c_master_transfer_t *transfer)
2355 {
2356     assert(NULL != handle);
2357     assert(NULL != transfer);
2358     assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
2359     i3c_master_state_t masterState = I3C_MasterGetState(base);
2360     bool checkDdrState             = false;
2361 
2362     /* Return busy if another transaction is in progress. */
2363     if (handle->state != (uint8_t)kIdleState)
2364     {
2365         return kStatus_I3C_Busy;
2366     }
2367 
2368     /* Return an error if the bus is already in use not by us. */
2369     checkDdrState = (transfer->busType == kI3C_TypeI3CDdr) ? (masterState != kI3C_MasterStateDdr) : true;
2370     if ((masterState != kI3C_MasterStateIdle) && (masterState != kI3C_MasterStateNormAct) && checkDdrState)
2371     {
2372         return kStatus_I3C_Busy;
2373     }
2374 
2375     /* Disable I3C IRQ sources while we configure stuff. */
2376     I3C_MasterDisableInterrupts(base, (uint32_t)kMasterIrqFlags);
2377 
2378     /* Save transfer into handle. */
2379     handle->transfer       = *transfer;
2380     handle->remainingBytes = transfer->dataSize;
2381 
2382     /* Configure IBI response type. */
2383     base->MCTRL &= ~I3C_MCTRL_IBIRESP_MASK;
2384     base->MCTRL |= I3C_MCTRL_IBIRESP(transfer->ibiResponse);
2385 
2386     /* Clear all flags. */
2387     I3C_MasterClearErrorStatusFlags(base, (uint32_t)kMasterErrorFlags);
2388     I3C_MasterClearStatusFlags(base, (uint32_t)kMasterClearFlags);
2389     /* Reset fifos. These flags clear automatically. */
2390     base->MDATACTRL |= I3C_MDATACTRL_FLUSHTB_MASK | I3C_MDATACTRL_FLUSHFB_MASK;
2391 
2392     /* Generate commands to send. */
2393     (void)I3C_InitTransferStateMachine(base, handle);
2394 
2395     /* Enable I3C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
2396     I3C_MasterEnableInterrupts(base, (uint32_t)kMasterIrqFlags);
2397 
2398     if (transfer->direction == kI3C_Write)
2399     {
2400         I3C_MasterEnableInterrupts(base, (uint32_t)kI3C_MasterTxReadyFlag);
2401     }
2402 
2403     return kStatus_Success;
2404 }
2405 
2406 /*!
2407  * brief Returns number of bytes transferred so far.
2408  * param base The I3C peripheral base address.
2409  * param handle Pointer to the I3C master driver handle.
2410  * param[out] count Number of bytes transferred so far by the non-blocking transaction.
2411  * retval #kStatus_Success
2412  * retval #kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
2413  */
I3C_MasterTransferGetCount(I3C_Type * base,i3c_master_handle_t * handle,size_t * count)2414 status_t I3C_MasterTransferGetCount(I3C_Type *base, i3c_master_handle_t *handle, size_t *count)
2415 {
2416     assert(NULL != handle);
2417 
2418     if (NULL == count)
2419     {
2420         return kStatus_InvalidArgument;
2421     }
2422 
2423     /* Catch when there is not an active transfer. */
2424     if (handle->state == (uint8_t)kIdleState)
2425     {
2426         *count = 0;
2427         return kStatus_NoTransferInProgress;
2428     }
2429 
2430     uint8_t state;
2431     uint32_t remainingBytes;
2432     uint32_t dataSize;
2433 
2434     /* Cache some fields with IRQs disabled. This ensures all field values */
2435     /* are synchronized with each other during an ongoing transfer. */
2436     uint32_t irqs = I3C_MasterGetEnabledInterrupts(base);
2437     I3C_MasterDisableInterrupts(base, irqs);
2438     state          = handle->state;
2439     remainingBytes = handle->remainingBytes;
2440     dataSize       = handle->transfer.dataSize;
2441     I3C_MasterEnableInterrupts(base, irqs);
2442 
2443     /* Get transfer count based on current transfer state. */
2444     switch (state)
2445     {
2446         case (uint8_t)kIdleState:
2447         case (uint8_t)kSendCommandState:
2448             *count = 0;
2449             break;
2450 
2451         case (uint8_t)kTransferDataState:
2452             *count = dataSize - remainingBytes;
2453             break;
2454 
2455         case (uint8_t)kStopState:
2456         case (uint8_t)kWaitForCompletionState:
2457         default:
2458             *count = dataSize;
2459             break;
2460     }
2461 
2462     return kStatus_Success;
2463 }
2464 
2465 /*!
2466  * brief Terminates a non-blocking I3C master transmission early.
2467  *
2468  * note It is not safe to call this function from an IRQ handler that has a higher priority than the
2469  *      I3C peripheral's IRQ priority.
2470  *
2471  * param base The I3C peripheral base address.
2472  * param handle Pointer to the I3C master driver handle.
2473  * retval #kStatus_Success A transaction was successfully aborted.
2474  * retval #kStatus_I3C_Idle There is not a non-blocking transaction currently in progress.
2475  */
I3C_MasterTransferAbort(I3C_Type * base,i3c_master_handle_t * handle)2476 void I3C_MasterTransferAbort(I3C_Type *base, i3c_master_handle_t *handle)
2477 {
2478     if (handle->state != (uint8_t)kIdleState)
2479     {
2480         /* Disable internal IRQ enables. */
2481         I3C_MasterDisableInterrupts(base, (uint32_t)kMasterIrqFlags);
2482 
2483         /* Reset fifos. These flags clear automatically. */
2484         base->MDATACTRL |= I3C_MDATACTRL_FLUSHTB_MASK | I3C_MDATACTRL_FLUSHFB_MASK;
2485 
2486         /* Send a stop command to finalize the transfer. */
2487         (void)I3C_MasterStop(base);
2488 
2489         /* Reset handle. */
2490         handle->state = (uint8_t)kIdleState;
2491     }
2492 }
2493 
2494 /*!
2495  * brief Reusable routine to handle master interrupts.
2496  * note This function does not need to be called unless you are reimplementing the
2497  *  nonblocking API's interrupt handler routines to add special functionality.
2498  * param base The I3C peripheral base address.
2499  * param handle Pointer to the I3C master driver handle.
2500  */
I3C_MasterTransferHandleIRQ(I3C_Type * base,void * intHandle)2501 void I3C_MasterTransferHandleIRQ(I3C_Type *base, void *intHandle)
2502 {
2503     bool isDone;
2504     status_t result;
2505 
2506     i3c_master_handle_t *handle = (i3c_master_handle_t *)intHandle;
2507     /* Don't do anything if we don't have a valid handle. */
2508     if (NULL == handle)
2509     {
2510         return;
2511     }
2512 
2513     result = I3C_RunTransferStateMachine(base, handle, &isDone);
2514 
2515     if (handle->state == (uint8_t)kIdleState)
2516     {
2517         I3C_MasterDisableInterrupts(base, (uint32_t)kI3C_MasterTxReadyFlag);
2518         return;
2519     }
2520 
2521     if (isDone || (result != kStatus_Success))
2522     {
2523         /* XXX need to handle data that may be in rx fifo below watermark level? */
2524 
2525         /* XXX handle error, terminate xfer */
2526         if ((result == kStatus_I3C_Nak) || (result == kStatus_I3C_IBIWon))
2527         {
2528             (void)I3C_MasterEmitStop(base, false);
2529         }
2530 
2531         /* Disable internal IRQ enables. */
2532         I3C_MasterDisableInterrupts(base, (uint32_t)kI3C_MasterTxReadyFlag);
2533 
2534         /* Set handle to idle state. */
2535         handle->state = (uint8_t)kIdleState;
2536 
2537         /* Invoke IBI user callback. */
2538         if ((result == kStatus_I3C_IBIWon) && (handle->callback.ibiCallback != NULL))
2539         {
2540             handle->callback.ibiCallback(base, handle, handle->ibiType, kI3C_IbiReady);
2541             handle->ibiPayloadSize = 0;
2542         }
2543 
2544         /* Invoke callback. */
2545         if (NULL != handle->callback.transferComplete)
2546         {
2547             handle->callback.transferComplete(base, handle, result, handle->userData);
2548         }
2549     }
2550 }
2551 
2552 /*!
2553  * brief Provides a default configuration for the I3C slave peripheral.
2554  *
2555  * This function provides the following default configuration for the I3C slave peripheral:
2556  * code
2557  *  slaveConfig->enableslave             = true;
2558  * endcode
2559  *
2560  * After calling this function, you can override any settings in order to customize the configuration,
2561  * prior to initializing the slave driver with I3C_SlaveInit().
2562  *
2563  * param[out] slaveConfig User provided configuration structure for default values. Refer to #i3c_slave_config_t.
2564  */
I3C_SlaveGetDefaultConfig(i3c_slave_config_t * slaveConfig)2565 void I3C_SlaveGetDefaultConfig(i3c_slave_config_t *slaveConfig)
2566 {
2567     assert(NULL != slaveConfig);
2568 
2569     (void)memset(slaveConfig, 0, sizeof(*slaveConfig));
2570 
2571     slaveConfig->enableSlave = true;
2572 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SLAVE_IBI_MR_HJ) && FSL_FEATURE_I3C_HAS_NO_SLAVE_IBI_MR_HJ)
2573     slaveConfig->isHotJoin   = false;
2574 #endif
2575     slaveConfig->vendorID    = 0x11BU;
2576 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND)
2577     slaveConfig->enableRandomPart = false;
2578 #endif
2579     slaveConfig->partNumber = 0;
2580     slaveConfig->dcr        = 0; /* Generic device. */
2581     slaveConfig->bcr =
2582         0; /* BCR[7:6]: device role, I3C slave(2b'00), BCR[5]: SDR Only / SDR and HDR Capable,  SDR and HDR
2583               Capable(1b'1), BCR[4]: Bridge Identifier, Not a bridge device(1b'0), BCR[3]: Offline Capable, device is
2584               offline capable(1b'1), BCR[2]: IBI Payload, No data byte following(1b'0), BCR[1]: IBI Request Capable,
2585               capable(1b'1), BCR[0]: Max Data Speed Limitation, has limitation(1b'1). */
2586     slaveConfig->hdrMode             = (uint8_t)kI3C_HDRModeDDR;
2587     slaveConfig->nakAllRequest       = false;
2588     slaveConfig->ignoreS0S1Error     = true;
2589     slaveConfig->offline             = false;
2590     slaveConfig->matchSlaveStartStop = false;
2591     slaveConfig->maxWriteLength      = 256U;
2592     slaveConfig->maxReadLength       = 256U;
2593 }
2594 
2595 /*!
2596  * brief Initializes the I3C slave peripheral.
2597  *
2598  * This function enables the peripheral clock and initializes the I3C slave peripheral as described by the user
2599  * provided configuration.
2600  *
2601  * param base The I3C peripheral base address.
2602  * param slaveConfig User provided peripheral configuration. Use I3C_SlaveGetDefaultConfig() to get a set of
2603  * defaults that you can override.
2604  * param slowClock_Hz Frequency in Hertz of the I3C slow clock. Used to calculate the bus match condition values.
2605  */
I3C_SlaveInit(I3C_Type * base,const i3c_slave_config_t * slaveConfig,uint32_t slowClock_Hz)2606 void I3C_SlaveInit(I3C_Type *base, const i3c_slave_config_t *slaveConfig, uint32_t slowClock_Hz)
2607 {
2608     assert(NULL != slaveConfig);
2609     assert(0UL != slowClock_Hz);
2610 
2611     uint32_t configValue;
2612 
2613 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) || \
2614     !(defined(FSL_FEATURE_I3C_HAS_NO_RESET) && FSL_FEATURE_I3C_HAS_NO_RESET)
2615     uint32_t instance = I3C_GetInstance(base);
2616 #endif
2617 
2618 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
2619     /* Ungate the clock. */
2620     CLOCK_EnableClock(kI3cClocks[instance]);
2621 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
2622 
2623 #if !(defined(FSL_FEATURE_I3C_HAS_NO_RESET) && FSL_FEATURE_I3C_HAS_NO_RESET)
2624     /* Reset the I3C module */
2625     RESET_PeripheralReset(kI3cResets[instance]);
2626 #endif
2627 
2628 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH)
2629     uint8_t matchCount;
2630     /* Caculate bus available condition match value for current slow clock, count value provides 1us.*/
2631     matchCount = (uint8_t)(slowClock_Hz / 1000000UL);
2632 #endif
2633 
2634     configValue = base->SCONFIG;
2635     configValue &=
2636         ~(I3C_SCONFIG_SADDR_MASK |
2637 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH)
2638           I3C_SCONFIG_BAMATCH_MASK |
2639 #endif
2640           I3C_SCONFIG_OFFLINE_MASK |
2641 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND)
2642           I3C_SCONFIG_IDRAND_MASK |
2643 #endif
2644 #if defined(FSL_FEATURE_I3C_HAS_HDROK) && FSL_FEATURE_I3C_HAS_HDROK
2645           I3C_SCONFIG_HDROK_MASK |
2646 #else
2647           I3C_SCONFIG_DDROK_MASK |
2648 #endif
2649           I3C_SCONFIG_S0IGNORE_MASK | I3C_SCONFIG_MATCHSS_MASK | I3C_SCONFIG_NACK_MASK | I3C_SCONFIG_SLVENA_MASK);
2650     configValue |= I3C_SCONFIG_SADDR(slaveConfig->staticAddr) |
2651 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH)
2652                    I3C_SCONFIG_BAMATCH(matchCount) |
2653 #endif
2654                    I3C_SCONFIG_OFFLINE(slaveConfig->offline) |
2655 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND)
2656                    I3C_SCONFIG_IDRAND(slaveConfig->enableRandomPart) |
2657 #endif
2658 #if defined(FSL_FEATURE_I3C_HAS_HDROK) && FSL_FEATURE_I3C_HAS_HDROK
2659                    I3C_SCONFIG_HDROK((0U != (slaveConfig->hdrMode & (uint8_t)kI3C_HDRModeDDR)) ? 1U : 0U) |
2660 #else
2661                    I3C_SCONFIG_DDROK((0U != (slaveConfig->hdrMode & (uint8_t)kI3C_HDRModeDDR)) ? 1U : 0U) |
2662 #endif
2663                    I3C_SCONFIG_S0IGNORE(slaveConfig->ignoreS0S1Error) |
2664                    I3C_SCONFIG_MATCHSS(slaveConfig->matchSlaveStartStop) |
2665                    I3C_SCONFIG_NACK(slaveConfig->nakAllRequest) | I3C_SCONFIG_SLVENA(slaveConfig->enableSlave);
2666 
2667     base->SVENDORID &= ~I3C_SVENDORID_VID_MASK;
2668     base->SVENDORID |= I3C_SVENDORID_VID(slaveConfig->vendorID);
2669 
2670 #if defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND
2671     base->SIDPARTNO = slaveConfig->partNumber;
2672 #else
2673     if (!slaveConfig->enableRandomPart)
2674     {
2675         base->SIDPARTNO = slaveConfig->partNumber;
2676     }
2677 #endif
2678 
2679     base->SIDEXT &= ~(I3C_SIDEXT_BCR_MASK | I3C_SIDEXT_DCR_MASK);
2680     base->SIDEXT |= I3C_SIDEXT_BCR(slaveConfig->bcr) | I3C_SIDEXT_DCR(slaveConfig->dcr);
2681 
2682     base->SMAXLIMITS &= ~(I3C_SMAXLIMITS_MAXRD_MASK | I3C_SMAXLIMITS_MAXWR_MASK);
2683     base->SMAXLIMITS |=
2684         (I3C_SMAXLIMITS_MAXRD(slaveConfig->maxReadLength) | I3C_SMAXLIMITS_MAXWR(slaveConfig->maxWriteLength));
2685 
2686 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SLAVE_IBI_MR_HJ) && FSL_FEATURE_I3C_HAS_NO_SLAVE_IBI_MR_HJ)
2687     if (slaveConfig->isHotJoin)
2688     {
2689         I3C_SlaveRequestEvent(base, kI3C_SlaveEventHotJoinReq);
2690     }
2691 #endif
2692     base->SCONFIG = configValue;
2693 }
2694 
2695 /*!
2696  * brief Deinitializes the I3C master peripheral.
2697  *
2698  * This function disables the I3C master peripheral and gates the clock. It also performs a software
2699  * reset to restore the peripheral to reset conditions.
2700  *
2701  * param base The I3C peripheral base address.
2702  */
I3C_SlaveDeinit(I3C_Type * base)2703 void I3C_SlaveDeinit(I3C_Type *base)
2704 {
2705     uint32_t idx = I3C_GetInstance(base);
2706 
2707 #if !(defined(FSL_FEATURE_I3C_HAS_NO_RESET) && FSL_FEATURE_I3C_HAS_NO_RESET)
2708     /* Reset the I3C module */
2709     RESET_PeripheralReset(kI3cResets[idx]);
2710 #endif
2711 
2712 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
2713     /* Gate clock. */
2714     CLOCK_DisableClock(kI3cClocks[idx]);
2715 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
2716 
2717     /* Reset handle pointer */
2718     s_i3cSlaveHandle[idx] = NULL;
2719 }
2720 
2721 /*!
2722  * @brief Gets the I3C slave state.
2723  *
2724  * @param base The I3C peripheral base address.
2725  * @return I3C slave activity state, refer #i3c_slave_activity_state_t.
2726  */
I3C_SlaveGetActivityState(I3C_Type * base)2727 i3c_slave_activity_state_t I3C_SlaveGetActivityState(I3C_Type *base)
2728 {
2729     uint8_t activeState = (uint8_t)((base->SSTATUS & I3C_SSTATUS_ACTSTATE_MASK) >> I3C_SSTATUS_ACTSTATE_SHIFT);
2730     i3c_slave_activity_state_t returnCode;
2731     switch (activeState)
2732     {
2733         case (uint8_t)kI3C_SlaveNoLatency:
2734             returnCode = kI3C_SlaveNoLatency;
2735             break;
2736         case (uint8_t)kI3C_SlaveLatency1Ms:
2737             returnCode = kI3C_SlaveLatency1Ms;
2738             break;
2739         case (uint8_t)kI3C_SlaveLatency100Ms:
2740             returnCode = kI3C_SlaveLatency100Ms;
2741             break;
2742         case (uint8_t)kI3C_SlaveLatency10S:
2743             returnCode = kI3C_SlaveLatency10S;
2744             break;
2745         default:
2746             returnCode = kI3C_SlaveNoLatency;
2747             break;
2748     }
2749 
2750     return returnCode;
2751 }
2752 
2753 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SLAVE_IBI_MR_HJ) && FSL_FEATURE_I3C_HAS_NO_SLAVE_IBI_MR_HJ)
2754 /*!
2755  * brief I3C slave request event.
2756  *
2757  * param base The I3C peripheral base address.
2758  * param event I3C slave event of type #i3c_slave_event_t
2759  * param data IBI data if In-band interrupt has data, only applicable for event type #kI3C_SlaveEventIBI
2760  */
I3C_SlaveRequestEvent(I3C_Type * base,i3c_slave_event_t event)2761 void I3C_SlaveRequestEvent(I3C_Type *base, i3c_slave_event_t event)
2762 {
2763     uint32_t ctrlValue = base->SCTRL;
2764 
2765     ctrlValue &= ~I3C_SCTRL_EVENT_MASK;
2766     ctrlValue |= I3C_SCTRL_EVENT(event);
2767 
2768     base->SCTRL = ctrlValue;
2769 }
2770 
2771 /*!
2772  * brief I3C slave request event.
2773  * deprecated Do not use this function. It has been superseded by @ref I3C_SlaveRequestIBIWithData.
2774  *
2775  * param base The I3C peripheral base address.
2776  * param data IBI data
2777  * param dataSize IBI data size.
2778  */
I3C_SlaveRequestIBIWithSingleData(I3C_Type * base,uint8_t data,size_t dataSize)2779 void I3C_SlaveRequestIBIWithSingleData(I3C_Type *base, uint8_t data, size_t dataSize)
2780 {
2781     uint32_t ctrlValue = base->SCTRL;
2782 
2783     ctrlValue &= ~(I3C_SCTRL_EVENT_MASK | I3C_SCTRL_IBIDATA_MASK);
2784     ctrlValue |= I3C_SCTRL_EVENT(1U) | I3C_SCTRL_IBIDATA(data);
2785 
2786     base->SCTRL = ctrlValue;
2787 }
2788 
2789 /*!
2790  * brief I3C slave request IBI event with data payload(mandatory and extended).
2791  *
2792  * param base The I3C peripheral base address.
2793  * param data Pointer to IBI data to be sent in the request.
2794  * param dataSize IBI data size.
2795  */
I3C_SlaveRequestIBIWithData(I3C_Type * base,uint8_t * data,size_t dataSize)2796 void I3C_SlaveRequestIBIWithData(I3C_Type *base, uint8_t *data, size_t dataSize)
2797 {
2798     assert((dataSize > 0U) && (dataSize <= 8U));
2799 
2800     uint32_t ctrlValue;
2801 
2802 #if (defined(I3C_IBIEXT1_MAX_MASK) && I3C_IBIEXT1_MAX_MASK)
2803     if (dataSize > 1U)
2804     {
2805         ctrlValue = I3C_IBIEXT1_EXT1(data[1]);
2806         if (dataSize > 2U)
2807         {
2808             ctrlValue |= I3C_IBIEXT1_EXT2(data[2]);
2809         }
2810         if (dataSize > 3U)
2811         {
2812             ctrlValue |= I3C_IBIEXT1_EXT3(data[3]);
2813         }
2814         ctrlValue |= I3C_IBIEXT1_CNT(dataSize - 1U);
2815         base->IBIEXT1 = ctrlValue;
2816     }
2817 
2818     if (dataSize > 4U)
2819     {
2820         ctrlValue = I3C_IBIEXT2_EXT4(data[4]);
2821         if (dataSize > 5U)
2822         {
2823             ctrlValue |= I3C_IBIEXT2_EXT5(data[5]);
2824         }
2825         if (dataSize > 6U)
2826         {
2827             ctrlValue |= I3C_IBIEXT2_EXT6(data[6]);
2828         }
2829         if (dataSize > 7U)
2830         {
2831             ctrlValue |= I3C_IBIEXT2_EXT7(data[7]);
2832         }
2833         base->IBIEXT2 = ctrlValue;
2834     }
2835 #endif
2836 
2837     ctrlValue = base->SCTRL;
2838 #if (defined(I3C_IBIEXT1_MAX_MASK) && I3C_IBIEXT1_MAX_MASK)
2839     ctrlValue &= ~(I3C_SCTRL_EVENT_MASK | I3C_SCTRL_IBIDATA_MASK | I3C_SCTRL_EXTDATA_MASK);
2840     ctrlValue |= I3C_SCTRL_EVENT(1U) | I3C_SCTRL_IBIDATA(data[0]) | I3C_SCTRL_EXTDATA(dataSize > 1U);
2841 #else
2842     ctrlValue &= ~(I3C_SCTRL_EVENT_MASK | I3C_SCTRL_IBIDATA_MASK);
2843     ctrlValue |= I3C_SCTRL_EVENT(1U) | I3C_SCTRL_IBIDATA(data[0]);
2844 #endif
2845     base->SCTRL = ctrlValue;
2846 }
2847 #endif /* !(defined(FSL_FEATURE_I3C_HAS_NO_SLAVE_IBI_MR_HJ) && FSL_FEATURE_I3C_HAS_NO_SLAVE_IBI_MR_HJ) */
2848 
2849 /*!
2850  * brief Performs a polling send transfer on the I3C bus.
2851  *
2852  * param base  The I3C peripheral base address.
2853  * param txBuff The pointer to the data to be transferred.
2854  * param txSize The length in bytes of the data to be transferred.
2855  * return Error or success status returned by API.
2856  */
I3C_SlaveSend(I3C_Type * base,const void * txBuff,size_t txSize)2857 status_t I3C_SlaveSend(I3C_Type *base, const void *txBuff, size_t txSize)
2858 {
2859     const uint8_t *buf = (const uint8_t *)((const void *)txBuff);
2860     status_t result    = kStatus_Success;
2861 
2862     assert(NULL != txBuff);
2863 
2864     /* Send data buffer */
2865     while (0UL != txSize--)
2866     {
2867         /* Wait until there is room in the fifo. This also checks for errors. */
2868         result = I3C_SlaveWaitForTxReady(base);
2869         if (kStatus_Success != result)
2870         {
2871             return result;
2872         }
2873 
2874         /* Write byte into I3C slave data register. */
2875         if (0UL != txSize)
2876         {
2877             base->SWDATAB = *buf++;
2878         }
2879         else
2880         {
2881             base->SWDATABE = *buf++;
2882         }
2883     }
2884 
2885     return result;
2886 }
2887 
2888 /*!
2889  * brief Performs a polling receive transfer on the I3C bus.
2890  *
2891  * param base  The I3C peripheral base address.
2892  * param rxBuff The pointer to the data to be transferred.
2893  * param rxSize The length in bytes of the data to be transferred.
2894  * return Error or success status returned by API.
2895  */
I3C_SlaveReceive(I3C_Type * base,void * rxBuff,size_t rxSize)2896 status_t I3C_SlaveReceive(I3C_Type *base, void *rxBuff, size_t rxSize)
2897 {
2898     status_t result = kStatus_Success;
2899     uint8_t *buf;
2900 
2901     assert(NULL != rxBuff);
2902 
2903     /* Handle empty read. */
2904     if (0UL == rxSize)
2905     {
2906         return kStatus_Success;
2907     }
2908 
2909 #if I3C_RETRY_TIMES
2910     uint32_t waitTimes = I3C_RETRY_TIMES;
2911 #endif
2912 
2913     /* Receive data */
2914     buf = (uint8_t *)rxBuff;
2915     while (0UL != rxSize)
2916     {
2917 #if I3C_RETRY_TIMES
2918         if (--waitTimes == 0)
2919         {
2920             return kStatus_I3C_Timeout;
2921         }
2922 #endif
2923         /* Check for errors. */
2924         result = I3C_SlaveCheckAndClearError(base, I3C_SlaveGetErrorStatusFlags(base));
2925         if (kStatus_Success != result)
2926         {
2927             return result;
2928         }
2929 
2930         /* Check RX data */
2931         if (0UL != (base->SDATACTRL & I3C_SDATACTRL_RXCOUNT_MASK))
2932         {
2933             *buf++ = (uint8_t)(base->SRDATAB & I3C_SRDATAB_DATA0_MASK);
2934             rxSize--;
2935         }
2936     }
2937 
2938     return result;
2939 }
2940 
2941 /*!
2942  * brief Creates a new handle for the I3C slave non-blocking APIs.
2943  *
2944  * The creation of a handle is for use with the non-blocking APIs. Once a handle
2945  * is created, there is not a corresponding destroy handle. If the user wants to
2946  * terminate a transfer, the I3C_SlaveTransferAbort() API shall be called.
2947  *
2948  * note The function also enables the NVIC IRQ for the input I3C. Need to notice
2949  * that on some SoCs the I3C IRQ is connected to INTMUX, in this case user needs to
2950  * enable the associated INTMUX IRQ in application.
2951 
2952  * param base The I3C peripheral base address.
2953  * param[out] handle Pointer to the I3C slave driver handle.
2954  * param callback User provided pointer to the asynchronous callback function.
2955  * param userData User provided pointer to the application callback data.
2956  */
I3C_SlaveTransferCreateHandle(I3C_Type * base,i3c_slave_handle_t * handle,i3c_slave_transfer_callback_t callback,void * userData)2957 void I3C_SlaveTransferCreateHandle(I3C_Type *base,
2958                                    i3c_slave_handle_t *handle,
2959                                    i3c_slave_transfer_callback_t callback,
2960                                    void *userData)
2961 {
2962     uint32_t instance;
2963 
2964     assert(NULL != handle);
2965 
2966     /* Clear out the handle. */
2967     (void)memset(handle, 0, sizeof(*handle));
2968 
2969     /* Look up instance number */
2970     instance = I3C_GetInstance(base);
2971 
2972     /* Save base and instance. */
2973     handle->callback = callback;
2974     handle->userData = userData;
2975 
2976     /* Save Tx FIFO Size. */
2977     handle->txFifoSize =
2978         2U << ((base->SCAPABILITIES & I3C_SCAPABILITIES_FIFOTX_MASK) >> I3C_SCAPABILITIES_FIFOTX_SHIFT);
2979 
2980     /* Save this handle for IRQ use. */
2981     s_i3cSlaveHandle[instance] = handle;
2982 
2983     /* Set irq handler. */
2984     s_i3cSlaveIsr = I3C_SlaveTransferHandleIRQ;
2985 
2986     /* Clear internal IRQ enables and enable NVIC IRQ. */
2987     I3C_SlaveDisableInterrupts(base, (uint32_t)kSlaveIrqFlags);
2988     (void)EnableIRQ(kI3cIrqs[instance]);
2989 }
2990 
2991 /*!
2992  * brief Starts accepting slave transfers.
2993  *
2994  * Call this API after calling I2C_SlaveInit() and I3C_SlaveTransferCreateHandle() to start processing
2995  * transactions driven by an I2C master. The slave monitors the I2C bus and pass events to the
2996  * callback that was passed into the call to I3C_SlaveTransferCreateHandle(). The callback is always invoked
2997  * from the interrupt context.
2998  *
2999  * The set of events received by the callback is customizable. To do so, set the a eventMask parameter to
3000  * the OR'd combination of #i3c_slave_transfer_event_t enumerators for the events you wish to receive.
3001  * The #kI3C_SlaveTransmitEvent and #kI3C_SlaveReceiveEvent events are always enabled and do not need
3002  * to be included in the mask. Alternatively, you can pass 0 to get a default set of only the transmit and
3003  * receive events that are always enabled. In addition, the #kI3C_SlaveAllEvents constant is provided as
3004  * a convenient way to enable all events.
3005  *
3006  * param base The I3C peripheral base address.
3007  * param handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
3008  * param eventMask Bit mask formed by OR'ing together #i3c_slave_transfer_event_t enumerators to specify
3009  *      which events to send to the callback. Other accepted values are 0 to get a default set of
3010  *      only the transmit and receive events, and #kI3C_SlaveAllEvents to enable all events.
3011  *
3012  * retval #kStatus_Success Slave transfers were successfully started.
3013  * retval #kStatus_I3C_Busy Slave transfers have already been started on this handle.
3014  */
I3C_SlaveTransferNonBlocking(I3C_Type * base,i3c_slave_handle_t * handle,uint32_t eventMask)3015 status_t I3C_SlaveTransferNonBlocking(I3C_Type *base, i3c_slave_handle_t *handle, uint32_t eventMask)
3016 {
3017     assert(NULL != handle);
3018 
3019     /* Return busy if another transaction is in progress. */
3020     if (handle->isBusy)
3021     {
3022         return kStatus_I3C_Busy;
3023     }
3024 
3025     /* Disable I3C IRQ sources while we configure stuff. */
3026     I3C_SlaveDisableInterrupts(base, (uint32_t)kSlaveIrqFlags);
3027 
3028     /* Clear transfer in handle. */
3029     (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
3030 
3031     /* Set up event mask. tx and rx are always enabled. */
3032     handle->eventMask = eventMask | (uint32_t)kI3C_SlaveTransmitEvent | (uint32_t)kI3C_SlaveReceiveEvent;
3033 
3034     /* Clear all flags. */
3035     I3C_SlaveClearStatusFlags(base, (uint32_t)kSlaveClearFlags);
3036 
3037     /* Enable I3C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
3038     I3C_SlaveEnableInterrupts(base, (uint32_t)kSlaveIrqFlags);
3039 
3040     return kStatus_Success;
3041 }
3042 
3043 /*!
3044  * brief Gets the slave transfer status during a non-blocking transfer.
3045  * param base The I3C peripheral base address.
3046  * param handle Pointer to i2c_slave_handle_t structure.
3047  * param[out] count Pointer to a value to hold the number of bytes transferred. May be NULL if the count is not
3048  *      required.
3049  * retval #kStatus_Success
3050  * retval #kStatus_NoTransferInProgress
3051  */
I3C_SlaveTransferGetCount(I3C_Type * base,i3c_slave_handle_t * handle,size_t * count)3052 status_t I3C_SlaveTransferGetCount(I3C_Type *base, i3c_slave_handle_t *handle, size_t *count)
3053 {
3054     assert(NULL != handle);
3055 
3056     if (NULL == count)
3057     {
3058         return kStatus_InvalidArgument;
3059     }
3060 
3061     /* Catch when there is not an active transfer. */
3062     if (!handle->isBusy)
3063     {
3064         *count = 0;
3065         return kStatus_NoTransferInProgress;
3066     }
3067 
3068     /* For an active transfer, just return the count from the handle. */
3069     *count = handle->transferredCount;
3070 
3071     return kStatus_Success;
3072 }
3073 
3074 /*!
3075  * brief Aborts the slave non-blocking transfers.
3076  * note This API could be called at any time to stop slave for handling the bus events.
3077  * param base The I3C peripheral base address.
3078  * param handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
3079  * retval #kStatus_Success
3080  * retval #kStatus_I3C_Idle
3081  */
I3C_SlaveTransferAbort(I3C_Type * base,i3c_slave_handle_t * handle)3082 void I3C_SlaveTransferAbort(I3C_Type *base, i3c_slave_handle_t *handle)
3083 {
3084     assert(NULL != handle);
3085 
3086     /* Return idle if no transaction is in progress. */
3087     if (handle->isBusy)
3088     {
3089         /* Disable I3C IRQ sources. */
3090         I3C_SlaveDisableInterrupts(base, (uint32_t)kSlaveIrqFlags);
3091 
3092         /* Reset transfer info. */
3093         (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
3094 
3095         /* We're no longer busy. */
3096         handle->isBusy = false;
3097     }
3098 }
3099 
I3C_SlaveTransferHandleGetStatusFlags(I3C_Type * base,i3c_slave_handle_t * handle,i3c_slave_handleIrq_param_t * stateParams)3100 static bool I3C_SlaveTransferHandleGetStatusFlags(I3C_Type *base,
3101                                                   i3c_slave_handle_t *handle,
3102                                                   i3c_slave_handleIrq_param_t *stateParams)
3103 {
3104     assert(NULL != base && NULL != handle && NULL != stateParams);
3105     /* Check for a valid handle in case of a spurious interrupt. */
3106     uint32_t errFlags;
3107     stateParams->flags = I3C_SlaveGetStatusFlags(base);
3108     errFlags           = I3C_SlaveGetErrorStatusFlags(base);
3109 
3110     stateParams->pendingInts = I3C_SlaveGetPendingInterrupts(base);
3111     stateParams->enabledInts = I3C_SlaveGetEnabledInterrupts(base);
3112 
3113     if (0UL != (errFlags & (uint32_t)kSlaveErrorFlags))
3114     {
3115         handle->transfer.event            = (uint32_t)kI3C_SlaveCompletionEvent;
3116         handle->transfer.completionStatus = I3C_SlaveCheckAndClearError(base, errFlags);
3117 
3118         if ((0UL != (handle->eventMask & (uint32_t)kI3C_SlaveCompletionEvent)) && (NULL != handle->callback))
3119         {
3120             handle->callback(base, &handle->transfer, handle->userData);
3121         }
3122         return false;
3123     }
3124     return true;
3125 }
3126 
I3C_SlaveTransferHandleBusStart(I3C_Type * base,i3c_slave_transfer_t * xfer,uint32_t * pendingInts)3127 static void I3C_SlaveTransferHandleBusStart(I3C_Type *base, i3c_slave_transfer_t *xfer, uint32_t *pendingInts)
3128 {
3129     base->SDATACTRL |= I3C_SDATACTRL_FLUSHTB_MASK;
3130     xfer->txDataSize = 0;
3131     I3C_SlaveEnableInterrupts(base, (uint32_t)kI3C_SlaveTxReadyFlag);
3132     (*pendingInts) |= (uint32_t)kI3C_SlaveTxReadyFlag;
3133 }
3134 
I3C_SlaveTransferHandleEventSent(I3C_Type * base,i3c_slave_handle_t * handle,i3c_slave_transfer_t * xfer)3135 static void I3C_SlaveTransferHandleEventSent(I3C_Type *base, i3c_slave_handle_t *handle, i3c_slave_transfer_t *xfer)
3136 {
3137     xfer->event = (uint32_t)kI3C_SlaveRequestSentEvent;
3138     if ((0UL != (handle->eventMask & xfer->event)) && (NULL != handle->callback))
3139     {
3140         handle->callback(base, xfer, handle->userData);
3141     }
3142 }
3143 
I3C_SlaveTransferHandleReceivedCCC(I3C_Type * base,i3c_slave_handle_t * handle,i3c_slave_transfer_t * xfer)3144 static void I3C_SlaveTransferHandleReceivedCCC(I3C_Type *base, i3c_slave_handle_t *handle, i3c_slave_transfer_t *xfer)
3145 {
3146     handle->isBusy = true;
3147     xfer->event    = (uint32_t)kI3C_SlaveReceivedCCCEvent;
3148     if ((0UL != (handle->eventMask & xfer->event)) && (NULL != handle->callback))
3149     {
3150         handle->callback(base, xfer, handle->userData);
3151     }
3152 }
3153 
I3C_SlaveTransferHandleBusStop(I3C_Type * base,i3c_slave_handle_t * handle,i3c_slave_handleIrq_param_t * stateParams)3154 static void I3C_SlaveTransferHandleBusStop(I3C_Type *base,
3155                                            i3c_slave_handle_t *handle,
3156                                            i3c_slave_handleIrq_param_t *stateParams)
3157 {
3158     assert(NULL != base && NULL != handle && NULL != stateParams);
3159     I3C_SlaveDisableInterrupts(base, (uint32_t)kI3C_SlaveTxReadyFlag);
3160     stateParams->pendingInts &= ~(uint32_t)kI3C_SlaveTxReadyFlag;
3161     base->SDATACTRL |= I3C_SDATACTRL_FLUSHTB_MASK | I3C_SDATACTRL_FLUSHFB_MASK;
3162     if (handle->isBusy == true)
3163     {
3164         handle->transfer.event            = (uint32_t)kI3C_SlaveCompletionEvent;
3165         handle->transfer.completionStatus = kStatus_Success;
3166         handle->transfer.transferredCount = handle->transferredCount;
3167         handle->isBusy                    = false;
3168 
3169         if (handle->wasTransmit)
3170         {
3171             /* Subtract one from the transmit count to offset the fact that I3C asserts the */
3172             /* tx flag before it sees the nack from the master-receiver, thus causing one more */
3173             /* count that the master actually receives. */
3174             --handle->transfer.transferredCount;
3175             handle->wasTransmit = false;
3176         }
3177 
3178         if ((0UL != (handle->eventMask & handle->transfer.event)) && (NULL != handle->callback))
3179         {
3180             handle->callback(base, &handle->transfer, handle->userData);
3181         }
3182 
3183         /* Clean up transfer info on completion, after the callback has been invoked. */
3184         (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
3185     }
3186 }
3187 
I3C_SlaveTransferHandleMatched(I3C_Type * base,i3c_slave_handle_t * handle,i3c_slave_transfer_t * xfer)3188 static void I3C_SlaveTransferHandleMatched(I3C_Type *base, i3c_slave_handle_t *handle, i3c_slave_transfer_t *xfer)
3189 {
3190     assert(NULL != base && NULL != handle && NULL != xfer);
3191     xfer->event    = (uint32_t)kI3C_SlaveAddressMatchEvent;
3192     handle->isBusy = true;
3193     if ((0UL != (handle->eventMask & (uint32_t)kI3C_SlaveAddressMatchEvent)) && (NULL != handle->callback))
3194     {
3195         handle->callback(base, xfer, handle->userData);
3196     }
3197 }
3198 
I3C_SlaveTransferHandleTxReady(I3C_Type * base,i3c_slave_handle_t * handle,i3c_slave_handleIrq_param_t * stateParams)3199 static void I3C_SlaveTransferHandleTxReady(I3C_Type *base,
3200                                            i3c_slave_handle_t *handle,
3201                                            i3c_slave_handleIrq_param_t *stateParams)
3202 {
3203     assert(NULL != base && NULL != handle && NULL != stateParams);
3204     handle->wasTransmit = true;
3205 
3206     /* If we're out of data, invoke callback to get more. */
3207     if ((NULL == handle->transfer.txData) || (0UL == handle->transfer.txDataSize))
3208     {
3209         handle->transfer.event = (uint32_t)kI3C_SlaveTransmitEvent;
3210         if (0UL != (stateParams->flags & (uint32_t)kI3C_SlaveBusHDRModeFlag))
3211         {
3212             handle->transfer.event |= (uint32_t)kI3C_SlaveHDRCommandMatchEvent;
3213         }
3214         if (NULL != handle->callback)
3215         {
3216             handle->callback(base, &handle->transfer, handle->userData);
3217         }
3218 
3219         /* Clear the transferred count now that we have a new buffer. */
3220         handle->transferredCount = 0;
3221     }
3222 
3223     if ((NULL == handle->transfer.txData) || (0UL == handle->transfer.txDataSize))
3224     {
3225         I3C_SlaveDisableInterrupts(base, (uint32_t)kI3C_SlaveTxReadyFlag);
3226         (stateParams->pendingInts) &= ~(uint32_t)kI3C_SlaveTxReadyFlag;
3227     }
3228 
3229     /* Transmit a byte. */
3230     while ((handle->transfer.txDataSize != 0UL) && ((stateParams->txCount) != 0U))
3231     {
3232         if (handle->transfer.txDataSize > 1UL)
3233         {
3234             base->SWDATAB = *handle->transfer.txData++;
3235         }
3236         else
3237         {
3238             base->SWDATABE = *handle->transfer.txData++;
3239             I3C_SlaveDisableInterrupts(base, (uint32_t)kI3C_SlaveTxReadyFlag);
3240         }
3241         --(handle->transfer.txDataSize);
3242         ++(handle->transferredCount);
3243         (stateParams->txCount)--;
3244     }
3245 }
3246 
I3C_SlaveTransferHandleRxReady(I3C_Type * base,i3c_slave_handle_t * handle,i3c_slave_handleIrq_param_t * stateParams)3247 static void I3C_SlaveTransferHandleRxReady(I3C_Type *base,
3248                                            i3c_slave_handle_t *handle,
3249                                            i3c_slave_handleIrq_param_t *stateParams)
3250 {
3251     assert(NULL != base && NULL != handle && NULL != stateParams);
3252     /* If we're out of room in the buffer, invoke callback to get another. */
3253     if ((NULL == handle->transfer.rxData) || (0UL == handle->transfer.rxDataSize))
3254     {
3255         handle->transfer.event = (uint32_t)kI3C_SlaveReceiveEvent;
3256         if (0UL != (stateParams->flags & (uint32_t)kI3C_SlaveBusHDRModeFlag))
3257         {
3258             handle->transfer.event |= (uint32_t)kI3C_SlaveHDRCommandMatchEvent;
3259         }
3260         if (NULL != handle->callback)
3261         {
3262             handle->callback(base, &handle->transfer, handle->userData);
3263         }
3264         handle->transferredCount = 0;
3265     }
3266     /* Receive a byte. */
3267     while ((stateParams->rxCount != 0U) && ((handle->transfer.rxData != NULL) && (handle->transfer.rxDataSize != 0UL)))
3268     {
3269         *(handle->transfer.rxData++) = (uint8_t)base->SRDATAB;
3270         --(handle->transfer.rxDataSize);
3271         ++(handle->transferredCount);
3272         (stateParams->rxCount)--;
3273     }
3274 }
3275 
3276 /*!
3277  * brief Reusable routine to handle slave interrupts.
3278  * note This function does not need to be called unless you are reimplementing the
3279  *  non blocking API's interrupt handler routines to add special functionality.
3280  * param base The I3C peripheral base address.
3281  * param handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
3282  */
I3C_SlaveTransferHandleIRQ(I3C_Type * base,void * intHandle)3283 void I3C_SlaveTransferHandleIRQ(I3C_Type *base, void *intHandle)
3284 {
3285     i3c_slave_handleIrq_param_t stateParams;
3286 
3287     (void)memset(&stateParams, 0, sizeof(stateParams));
3288     i3c_slave_handle_t *handle = (i3c_slave_handle_t *)intHandle;
3289 
3290     /* Check for a valid handle in case of a spurious interrupt. */
3291     if (NULL == handle)
3292     {
3293         return;
3294     }
3295 
3296     /* Get status flags. */
3297     if (false == I3C_SlaveTransferHandleGetStatusFlags(base, handle, &stateParams))
3298     {
3299         return;
3300     }
3301 
3302     /* Clear status flags. */
3303     I3C_SlaveClearStatusFlags(base, stateParams.flags);
3304 
3305     if (0UL != (stateParams.flags & (uint32_t)kI3C_SlaveBusStartFlag))
3306     {
3307         I3C_SlaveTransferHandleBusStart(base, &handle->transfer, &stateParams.pendingInts);
3308     }
3309 
3310     if (0UL != (stateParams.flags & (uint32_t)kI3C_SlaveEventSentFlag))
3311     {
3312         I3C_SlaveTransferHandleEventSent(base, handle, &handle->transfer);
3313     }
3314 
3315     if (0UL != (stateParams.flags & (uint32_t)kI3C_SlaveReceivedCCCFlag))
3316     {
3317         I3C_SlaveTransferHandleReceivedCCC(base, handle, &handle->transfer);
3318     }
3319 
3320     if (0UL != (stateParams.flags & (uint32_t)kI3C_SlaveMatchedFlag))
3321     {
3322         I3C_SlaveTransferHandleMatched(base, handle, &handle->transfer);
3323     }
3324 
3325     /* Get fifo counts and compute room in tx fifo. */
3326     I3C_SlaveGetFifoCounts(base, &stateParams.rxCount, &stateParams.txCount);
3327     stateParams.txCount = handle->txFifoSize - stateParams.txCount;
3328 
3329     /* Handle transmit and receive. */
3330     if ((0UL != (stateParams.flags & (uint32_t)kI3C_SlaveTxReadyFlag)) &&
3331         (0UL != (stateParams.pendingInts & (uint32_t)kI3C_SlaveTxReadyFlag)))
3332     {
3333         I3C_SlaveTransferHandleTxReady(base, handle, &stateParams);
3334     }
3335 
3336     if ((0UL != (stateParams.flags & (uint32_t)kI3C_SlaveRxReadyFlag)) &&
3337         (0UL != (stateParams.enabledInts & (uint32_t)kI3C_SlaveRxReadyFlag)))
3338     {
3339         I3C_SlaveTransferHandleRxReady(base, handle, &stateParams);
3340     }
3341 
3342     /* Handle stop event. */
3343     if (0UL != (stateParams.flags & (uint32_t)kI3C_SlaveBusStopFlag))
3344     {
3345         I3C_SlaveTransferHandleBusStop(base, handle, &stateParams);
3346     }
3347 }
3348 
I3C_CommonIRQHandler(I3C_Type * base,uint32_t instance)3349 static void I3C_CommonIRQHandler(I3C_Type *base, uint32_t instance)
3350 {
3351     /* Check for master IRQ. */
3352     if (((uint32_t)kI3C_MasterOn == (base->MCONFIG & I3C_MCONFIG_MSTENA_MASK)) && (NULL != s_i3cMasterIsr))
3353     {
3354         /* Master mode. */
3355         s_i3cMasterIsr(base, s_i3cMasterHandle[instance]);
3356     }
3357 
3358     /* Check for slave IRQ. */
3359     if ((I3C_SCONFIG_SLVENA_MASK == (base->SCONFIG & I3C_SCONFIG_SLVENA_MASK)) && (NULL != s_i3cSlaveIsr))
3360     {
3361         /* Slave mode. */
3362         s_i3cSlaveIsr(base, s_i3cSlaveHandle[instance]);
3363     }
3364     SDK_ISR_EXIT_BARRIER;
3365 }
3366 
3367 #if defined(I3C)
3368 /* Implementation of I3C handler named in startup code. */
3369 void I3C0_DriverIRQHandler(void);
I3C0_DriverIRQHandler(void)3370 void I3C0_DriverIRQHandler(void)
3371 {
3372     I3C_CommonIRQHandler(I3C, 0);
3373 }
3374 #endif
3375 
3376 #if defined(I3C0)
3377 /* Implementation of I3C0 handler named in startup code. */
3378 void I3C0_DriverIRQHandler(void);
I3C0_DriverIRQHandler(void)3379 void I3C0_DriverIRQHandler(void)
3380 {
3381     I3C_CommonIRQHandler(I3C0, 0);
3382 }
3383 #endif
3384 
3385 #if defined(I3C1)
3386 /* Implementation of I3C1 handler named in startup code. */
3387 void I3C1_DriverIRQHandler(void);
I3C1_DriverIRQHandler(void)3388 void I3C1_DriverIRQHandler(void)
3389 {
3390     I3C_CommonIRQHandler(I3C1, 1);
3391 }
3392 #endif
3393 
3394 #if defined(I3C2)
3395 /* Implementation of I3C2 handler named in startup code. */
3396 void I3C2_DriverIRQHandler(void);
I3C2_DriverIRQHandler(void)3397 void I3C2_DriverIRQHandler(void)
3398 {
3399     I3C_CommonIRQHandler(I3C2, 2);
3400 }
3401 #endif
3402