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 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     uint32_t instance = I3C_GetInstance(base);
799     uint32_t configValue;
800 
801 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
802     /* Ungate the clock. */
803     CLOCK_EnableClock(kI3cClocks[instance]);
804 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
805 
806 #if !(defined(FSL_FEATURE_I3C_HAS_NO_RESET) && FSL_FEATURE_I3C_HAS_NO_RESET)
807     /* Reset the I3C module */
808     RESET_PeripheralReset(kI3cResets[instance]);
809 #endif
810 
811     if ((config->masterDynamicAddress != 0U) && (config->enableMaster == kI3C_MasterOn))
812     {
813         base->MDYNADDR &= ~I3C_MDYNADDR_DADDR_MASK;
814         base->MDYNADDR |= I3C_MDYNADDR_DADDR(config->masterDynamicAddress) | I3C_MDYNADDR_DAVALID_MASK;
815     }
816 
817     base->MCONFIG = I3C_MCONFIG_MSTENA(config->enableMaster) | I3C_MCONFIG_DISTO(config->disableTimeout) |
818                     I3C_MCONFIG_HKEEP(config->hKeep) | I3C_MCONFIG_ODSTOP(config->enableOpenDrainStop) |
819                     I3C_MCONFIG_ODHPP(config->enableOpenDrainHigh);
820 
821     I3C_MasterSetWatermarks(base, kI3C_TxTriggerUntilOneLessThanFull, kI3C_RxTriggerOnNotEmpty, true, true);
822 
823     I3C_MasterSetBaudRate(base, &config->baudRate_Hz, sourceClock_Hz);
824 
825 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH)
826     uint8_t matchCount;
827     /* Caculate bus available condition match value for current slow clock, count value provides 1us.*/
828     matchCount = (uint8_t)(config->slowClock_Hz / 1000000UL);
829 #endif
830 
831     configValue = base->SCONFIG;
832 
833     configValue &=
834         ~(I3C_SCONFIG_SADDR_MASK |
835 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH)
836           I3C_SCONFIG_BAMATCH_MASK |
837 #endif
838           I3C_SCONFIG_OFFLINE_MASK |
839 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND)
840           I3C_SCONFIG_IDRAND_MASK |
841 #endif
842 #if defined(FSL_FEATURE_I3C_HAS_HDROK) && FSL_FEATURE_I3C_HAS_HDROK
843           I3C_SCONFIG_HDROK_MASK |
844 #else
845           I3C_SCONFIG_DDROK_MASK |
846 #endif
847           I3C_SCONFIG_S0IGNORE_MASK | I3C_SCONFIG_MATCHSS_MASK | I3C_SCONFIG_NACK_MASK | I3C_SCONFIG_SLVENA_MASK);
848 
849     configValue |= I3C_SCONFIG_SADDR(config->staticAddr) |
850 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH)
851                    I3C_SCONFIG_BAMATCH(matchCount) |
852 #endif
853                    I3C_SCONFIG_OFFLINE(config->offline) |
854 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND)
855                    I3C_SCONFIG_IDRAND(config->enableRandomPart) |
856 #endif
857 #if defined(FSL_FEATURE_I3C_HAS_HDROK) && FSL_FEATURE_I3C_HAS_HDROK
858                    I3C_SCONFIG_HDROK((0U != (config->hdrMode & (uint8_t)kI3C_HDRModeDDR)) ? 1U : 0U) |
859 #else
860                    I3C_SCONFIG_DDROK((0U != (config->hdrMode & (uint8_t)kI3C_HDRModeDDR)) ? 1U : 0U) |
861 #endif
862                    I3C_SCONFIG_S0IGNORE(config->ignoreS0S1Error) | I3C_SCONFIG_MATCHSS(config->matchSlaveStartStop) |
863                    I3C_SCONFIG_NACK(config->nakAllRequest) | I3C_SCONFIG_SLVENA(config->enableSlave);
864 
865     base->SVENDORID &= ~I3C_SVENDORID_VID_MASK;
866     base->SVENDORID |= I3C_SVENDORID_VID(config->vendorID);
867 
868 #if defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND
869     base->SIDPARTNO = config->partNumber;
870 #else
871     if (!config->enableRandomPart)
872     {
873         base->SIDPARTNO = config->partNumber;
874     }
875 #endif
876 
877     base->SIDEXT &= ~(I3C_SIDEXT_BCR_MASK | I3C_SIDEXT_DCR_MASK);
878     base->SIDEXT |= I3C_SIDEXT_BCR(config->bcr) | I3C_SIDEXT_DCR(config->dcr);
879 
880     base->SMAXLIMITS &= ~(I3C_SMAXLIMITS_MAXRD_MASK | I3C_SMAXLIMITS_MAXWR_MASK);
881     base->SMAXLIMITS |= (I3C_SMAXLIMITS_MAXRD(config->maxReadLength) | I3C_SMAXLIMITS_MAXWR(config->maxWriteLength));
882 
883     base->SCONFIG = configValue;
884 }
885 
886 /*!
887  * brief Provides a default configuration for the I3C master peripheral.
888  *
889  * This function provides the following default configuration for the I3C master peripheral:
890  * code
891  *  masterConfig->enableMaster            = kI3C_MasterOn;
892  *  masterConfig->disableTimeout          = false;
893  *  masterConfig->hKeep                   = kI3C_MasterHighKeeperNone;
894  *  masterConfig->enableOpenDrainStop     = true;
895  *  masterConfig->enableOpenDrainHigh     = true;
896  *  masterConfig->baudRate_Hz             = 100000U;
897  *  masterConfig->busType                 = kI3C_TypeI2C;
898  * endcode
899  *
900  * After calling this function, you can override any settings in order to customize the configuration,
901  * prior to initializing the master driver with I3C_MasterInit().
902  *
903  * param[out] masterConfig User provided configuration structure for default values. Refer to #i3c_master_config_t.
904  */
I3C_MasterGetDefaultConfig(i3c_master_config_t * masterConfig)905 void I3C_MasterGetDefaultConfig(i3c_master_config_t *masterConfig)
906 {
907     masterConfig->enableMaster                 = kI3C_MasterOn;
908     masterConfig->disableTimeout               = false;
909     masterConfig->hKeep                        = kI3C_MasterHighKeeperNone;
910     masterConfig->enableOpenDrainStop          = true;
911     masterConfig->enableOpenDrainHigh          = true;
912     masterConfig->baudRate_Hz.i2cBaud          = 400000U;
913     masterConfig->baudRate_Hz.i3cPushPullBaud  = 12500000U;
914     masterConfig->baudRate_Hz.i3cOpenDrainBaud = 2500000U;
915 }
916 
917 /*!
918  * brief Initializes the I3C master peripheral.
919  *
920  * This function enables the peripheral clock and initializes the I3C master peripheral as described by the user
921  * provided configuration. A software reset is performed prior to configuration.
922  *
923  * param base The I3C peripheral base address.
924  * param masterConfig User provided peripheral configuration. Use I3C_MasterGetDefaultConfig() to get a set of
925  * defaults that you can override.
926  * param sourceClock_Hz Frequency in Hertz of the I3C functional clock. Used to calculate the baud rate divisors,
927  *      filter widths, and timeout periods.
928  */
I3C_MasterInit(I3C_Type * base,const i3c_master_config_t * masterConfig,uint32_t sourceClock_Hz)929 void I3C_MasterInit(I3C_Type *base, const i3c_master_config_t *masterConfig, uint32_t sourceClock_Hz)
930 {
931     uint32_t instance = I3C_GetInstance(base);
932 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
933     /* Ungate the clock. */
934     CLOCK_EnableClock(kI3cClocks[instance]);
935 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
936 
937 #if !(defined(FSL_FEATURE_I3C_HAS_NO_RESET) && FSL_FEATURE_I3C_HAS_NO_RESET)
938     /* Reset the I3C module */
939     RESET_PeripheralReset(kI3cResets[instance]);
940 #endif
941     base->MCONFIG = I3C_MCONFIG_MSTENA(masterConfig->enableMaster) | I3C_MCONFIG_DISTO(masterConfig->disableTimeout) |
942                     I3C_MCONFIG_HKEEP(masterConfig->hKeep) | I3C_MCONFIG_ODSTOP(masterConfig->enableOpenDrainStop) |
943                     I3C_MCONFIG_ODHPP(masterConfig->enableOpenDrainHigh);
944 
945     I3C_MasterSetWatermarks(base, kI3C_TxTriggerUntilOneLessThanFull, kI3C_RxTriggerOnNotEmpty, true, true);
946 
947     I3C_MasterSetBaudRate(base, &masterConfig->baudRate_Hz, sourceClock_Hz);
948 }
949 
950 /*!
951  * @brief Gets the I3C master state.
952  *
953  * @param base The I3C peripheral base address.
954  * @return I3C master state.
955  */
I3C_MasterGetState(I3C_Type * base)956 i3c_master_state_t I3C_MasterGetState(I3C_Type *base)
957 {
958     uint32_t masterState = (base->MSTATUS & I3C_MSTATUS_STATE_MASK) >> I3C_MSTATUS_STATE_SHIFT;
959     i3c_master_state_t returnCode;
960 
961     switch (masterState)
962     {
963         case (uint32_t)kI3C_MasterStateIdle:
964             returnCode = kI3C_MasterStateIdle;
965             break;
966         case (uint32_t)kI3C_MasterStateSlvReq:
967             returnCode = kI3C_MasterStateSlvReq;
968             break;
969         case (uint32_t)kI3C_MasterStateMsgSdr:
970             returnCode = kI3C_MasterStateMsgSdr;
971             break;
972         case (uint32_t)kI3C_MasterStateNormAct:
973             returnCode = kI3C_MasterStateNormAct;
974             break;
975         case (uint32_t)kI3C_MasterStateDdr:
976             returnCode = kI3C_MasterStateDdr;
977             break;
978         case (uint32_t)kI3C_MasterStateDaa:
979             returnCode = kI3C_MasterStateDaa;
980             break;
981         case (uint32_t)kI3C_MasterStateIbiAck:
982             returnCode = kI3C_MasterStateIbiAck;
983             break;
984         case (uint32_t)kI3C_MasterStateIbiRcv:
985             returnCode = kI3C_MasterStateIbiRcv;
986             break;
987         default:
988             returnCode = kI3C_MasterStateIdle;
989             break;
990     }
991 
992     return returnCode;
993 }
994 
995 /*!
996  * brief Deinitializes the I3C master peripheral.
997  *
998  * This function disables the I3C master peripheral and gates the clock. It also performs a software
999  * reset to restore the peripheral to reset conditions.
1000  *
1001  * param base The I3C peripheral base address.
1002  */
I3C_MasterDeinit(I3C_Type * base)1003 void I3C_MasterDeinit(I3C_Type *base)
1004 {
1005     uint32_t idx = I3C_GetInstance(base);
1006 
1007 #if !(defined(FSL_FEATURE_I3C_HAS_NO_RESET) && FSL_FEATURE_I3C_HAS_NO_RESET)
1008     /* Reset the I3C module */
1009     RESET_PeripheralReset(kI3cResets[idx]);
1010 #endif
1011 
1012 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1013     /* Gate clock. */
1014     CLOCK_DisableClock(kI3cClocks[idx]);
1015 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1016 
1017     /* Reset handle pointer. */
1018     s_i3cMasterHandle[idx] = NULL;
1019 }
1020 
I3C_CalcErrorRatio(uint32_t curFreq,uint32_t desiredFreq)1021 static uint32_t I3C_CalcErrorRatio(uint32_t curFreq, uint32_t desiredFreq)
1022 {
1023     if (curFreq > desiredFreq)
1024     {
1025         return (curFreq - desiredFreq) * 100UL / desiredFreq;
1026     }
1027     else
1028     {
1029         return (desiredFreq - curFreq) * 100UL / desiredFreq;
1030     }
1031 }
1032 
1033 /*!
1034  * brief Sets the I3C bus frequency for master transactions.
1035  *
1036  * The I3C master is automatically disabled and re-enabled as necessary to configure the baud
1037  * rate. Do not call this function during a transfer, or the transfer is aborted.
1038  *
1039  * param base The I3C peripheral base address.
1040  * param baudRate_Hz Pointer to structure of requested bus frequency in Hertz.
1041  * param sourceClock_Hz I3C functional clock frequency in Hertz.
1042  */
I3C_MasterSetBaudRate(I3C_Type * base,const i3c_baudrate_hz_t * baudRate_Hz,uint32_t sourceClock_Hz)1043 void I3C_MasterSetBaudRate(I3C_Type *base, const i3c_baudrate_hz_t *baudRate_Hz, uint32_t sourceClock_Hz)
1044 {
1045     uint32_t div, freq;
1046     uint32_t divEven, divOdd;
1047     uint32_t ppBaud, odBaud, i2cBaud;
1048     uint32_t errRate0, errRate1;
1049     uint32_t i3cPPBaud_HZ    = baudRate_Hz->i3cPushPullBaud;
1050     uint32_t i3cPPBaudMax_HZ = i3cPPBaud_HZ / 10U + i3cPPBaud_HZ; /* max is 1.1*i3cPPBaud_HZ */
1051     uint32_t i3cODBaud_HZ    = baudRate_Hz->i3cOpenDrainBaud;
1052     uint32_t i3cODBaudMax_HZ = i3cODBaud_HZ / 10U + i3cODBaud_HZ; /* max is 1.1*i3cODBaud_HZ */
1053     uint32_t i2cBaud_HZ      = baudRate_Hz->i2cBaud;
1054     uint32_t i3cPPLow_Ns, i3cOdLow_Ns;
1055     bool isODHigh = (0U != (base->MCONFIG & I3C_MCONFIG_ODHPP_MASK)) ? true : false;
1056 
1057     /* Find out the div to generate target freq */
1058     freq = sourceClock_Hz / 2UL;
1059     /* ppFreq = FCLK / 2 / (PPBAUD + 1)), 0 <= PPBAUD <= 15 */
1060     /* We need PPBAUD generate 12.5MHz or so. */
1061     div = freq / i3cPPBaud_HZ;
1062     div = (div == 0UL) ? 1UL : div;
1063     if (freq / div > i3cPPBaudMax_HZ)
1064     {
1065         div++;
1066     }
1067     assert(div <= FSL_I3C_PPBAUD_DIV_MAX);
1068     ppBaud = div - 1UL;
1069     freq /= div;
1070 
1071     i3cPPLow_Ns = (uint32_t)(NSEC_PER_SEC / (2UL * freq));
1072 
1073     /* We need ODBAUD generate 2.5MHz or so. */
1074     if (isODHigh)
1075     {
1076         /* odFreq = (2*freq) / (ODBAUD + 2), 1 <= ODBAUD <= 255 */
1077         div = (2UL * freq) / i3cODBaud_HZ;
1078         div = div < 2UL ? 2UL : div;
1079         if ((2UL * freq / div) > i3cODBaudMax_HZ)
1080         {
1081             div++;
1082         }
1083         odBaud = div - 2UL;
1084         freq   = (2UL * freq) / div;
1085     }
1086     else
1087     {
1088         /* odFreq = ppFreq / (ODBAUD + 1), 1 <= ODBAUD <= 255 */
1089         div = freq / i3cODBaud_HZ;
1090         div = div < 1UL ? 1UL : div;
1091         if (freq / div > i3cODBaudMax_HZ)
1092         {
1093             div++;
1094         }
1095         odBaud = div - 1UL;
1096         freq /= div;
1097     }
1098 
1099     i3cOdLow_Ns = (odBaud + 1UL) * i3cPPLow_Ns;
1100 
1101     /* i2cFreq = odFreq / (I2CBAUD + 1), 0 <= I2CBAUD <= 7 (I2CBAUD need << 1 in register) */
1102     /* i2cFreq = NSEC_PER_SEC / (I2CBAUD + 1)*i3cOdLow_Ns */
1103     divEven  = (sourceClock_Hz / i2cBaud_HZ) / (2UL * (ppBaud + 1UL) * (odBaud + 1UL));
1104     divEven  = divEven == 0UL ? 1UL : divEven;
1105     errRate0 = I3C_CalcErrorRatio((uint32_t)(NSEC_PER_SEC / (2UL * divEven * i3cOdLow_Ns)), i2cBaud_HZ);
1106 
1107     divOdd   = ((sourceClock_Hz / i2cBaud_HZ) / ((ppBaud + 1UL) * (odBaud + 1UL) - 1UL)) / 2UL;
1108     divOdd   = divOdd == 0UL ? 1UL : divOdd;
1109     errRate1 = I3C_CalcErrorRatio((uint32_t)(NSEC_PER_SEC / ((2UL * divOdd + 1UL) * i3cOdLow_Ns)), i2cBaud_HZ);
1110 
1111     if (errRate0 < FSL_I3C_ERROR_RATE_MAX || errRate1 < FSL_I3C_ERROR_RATE_MAX)
1112     {
1113         /* Use this div */
1114         i2cBaud = errRate0 < errRate1 ? (divEven - 1UL) * 2UL : (divOdd - 1UL) * 2UL + 1UL;
1115     }
1116     else
1117     {
1118         /* Use div + 1, unless current freq is already lower than desired. */
1119         i2cBaud = freq / divEven < i2cBaud_HZ ? (divEven - 1UL) * 2UL : divEven * 2UL;
1120     }
1121 
1122     base->MCONFIG = (base->MCONFIG & ~(I3C_MCONFIG_PPBAUD_MASK | I3C_MCONFIG_PPLOW_MASK | I3C_MCONFIG_ODBAUD_MASK |
1123                                        I3C_MCONFIG_I2CBAUD_MASK)) |
1124                     I3C_MCONFIG_PPBAUD(ppBaud) | I3C_MCONFIG_ODBAUD(odBaud) | I3C_MCONFIG_I2CBAUD(i2cBaud);
1125 }
1126 
1127 /*!
1128  * brief Sends a START signal and slave address on the I2C/I3C bus, receive size is also specified
1129  * in the call.
1130  * This function is used to initiate a new master mode transfer. First, the bus state is checked to ensure
1131  * that another master is not occupying the bus. Then a START signal is transmitted, followed by the
1132  * 7-bit address specified in the a address parameter. Note that this function does not actually wait
1133  * until the START and address are successfully sent on the bus before returning.
1134  *
1135  * param base The I3C peripheral base address.
1136  * param type The bus type to use in this transaction.
1137  * param address 7-bit slave device address, in bits [6:0].
1138  * param dir Master transfer direction, either #kI3C_Read or #kI3C_Write. This parameter is used to set
1139  *      the R/w bit (bit 0) in the transmitted slave address.
1140  * param rxSize Read terminate size for the followed read transfer, limit to 255 bytes.
1141  * retval #kStatus_Success START signal and address were successfully enqueued in the transmit FIFO.
1142  * retval #kStatus_I3C_Busy Another master is currently utilizing the bus.
1143  */
I3C_MasterStartWithRxSize(I3C_Type * base,i3c_bus_type_t type,uint8_t address,i3c_direction_t dir,uint8_t rxSize)1144 status_t I3C_MasterStartWithRxSize(
1145     I3C_Type *base, i3c_bus_type_t type, uint8_t address, i3c_direction_t dir, uint8_t rxSize)
1146 {
1147     i3c_master_state_t masterState = I3C_MasterGetState(base);
1148     bool checkDdrState             = (type == kI3C_TypeI3CDdr) ? (masterState != kI3C_MasterStateDdr) : true;
1149     if ((masterState != kI3C_MasterStateIdle) && (masterState != kI3C_MasterStateNormAct) && checkDdrState)
1150     {
1151         return kStatus_I3C_Busy;
1152     }
1153 
1154     return I3C_MasterRepeatedStartWithRxSize(base, type, address, dir, rxSize);
1155 }
1156 
1157 /*!
1158  * brief Sends a START signal and slave address on the I2C/I3C bus.
1159  *
1160  * This function is used to initiate a new master mode transfer. First, the bus state is checked to ensure
1161  * that another master is not occupying the bus. Then a START signal is transmitted, followed by the
1162  * 7-bit address specified in the a address parameter. Note that this function does not actually wait
1163  * until the START and address are successfully sent on the bus before returning.
1164  *
1165  * param base The I3C peripheral base address.
1166  * param type The bus type to use in this transaction.
1167  * param address 7-bit slave device address, in bits [6:0].
1168  * param dir Master transfer direction, either #kI3C_Read or #kI3C_Write. This parameter is used to set
1169  *      the R/w bit (bit 0) in the transmitted slave address.
1170  * retval #kStatus_Success START signal and address were successfully enqueued in the transmit FIFO.
1171  * retval #kStatus_I3C_Busy Another master is currently utilizing the bus.
1172  */
I3C_MasterStart(I3C_Type * base,i3c_bus_type_t type,uint8_t address,i3c_direction_t dir)1173 status_t I3C_MasterStart(I3C_Type *base, i3c_bus_type_t type, uint8_t address, i3c_direction_t dir)
1174 {
1175     i3c_master_state_t masterState = I3C_MasterGetState(base);
1176     bool checkDdrState             = (type == kI3C_TypeI3CDdr) ? (masterState != kI3C_MasterStateDdr) : true;
1177     if ((masterState != kI3C_MasterStateIdle) && (masterState != kI3C_MasterStateNormAct) && checkDdrState)
1178     {
1179         return kStatus_I3C_Busy;
1180     }
1181 
1182     return I3C_MasterStartWithRxSize(base, type, address, dir, 0);
1183 }
1184 
1185 /*!
1186  * brief Sends a repeated START signal and slave address on the I2C/I3C bus, receive size is also specified
1187  * in the call.
1188  *
1189  * This function is used to send a Repeated START signal when a transfer is already in progress. Like
1190  * I3C_MasterStart(), it also sends the specified 7-bit address. Call this API also configures the read
1191  * terminate size for the following read transfer. For example, set the rxSize = 2, the following read transfer
1192  * will be terminated after two bytes of data received. Write transfer will not be affected by the rxSize
1193  * configuration.
1194  *
1195  * note This function exists primarily to maintain compatible APIs between I3C and I2C drivers,
1196  *      as well as to better document the intent of code that uses these APIs.
1197  *
1198  * param base The I3C peripheral base address.
1199  * param type The bus type to use in this transaction.
1200  * param address 7-bit slave device address, in bits [6:0].
1201  * param dir Master transfer direction, either #kI3C_Read or #kI3C_Write. This parameter is used to set
1202  *      the R/w bit (bit 0) in the transmitted slave address.
1203  * param rxSize Read terminate size for the followed read transfer, limit to 255 bytes.
1204  * retval #kStatus_Success Repeated START signal and address were successfully enqueued in the transmit FIFO.
1205  */
I3C_MasterRepeatedStartWithRxSize(I3C_Type * base,i3c_bus_type_t type,uint8_t address,i3c_direction_t dir,uint8_t rxSize)1206 status_t I3C_MasterRepeatedStartWithRxSize(
1207     I3C_Type *base, i3c_bus_type_t type, uint8_t address, i3c_direction_t dir, uint8_t rxSize)
1208 {
1209     uint32_t mctrlVal;
1210 
1211     /* Clear all flags. */
1212     I3C_MasterClearStatusFlags(base, (uint32_t)kMasterClearFlags);
1213 
1214 #if defined(FSL_FEATURE_I3C_HAS_ERRATA_051617) && (FSL_FEATURE_I3C_HAS_ERRATA_051617)
1215     /* ERRATA051617: When used as I2C controller generates repeated START randomly before the STOP under PVT condition.
1216     This issue is caused by a glitch at the output of an internal clock MUX. The glitch when generates acts as a clock
1217     pulse which causes the SDA line to fall early during SCL high period and creates the unintended Repeated START before
1218     actual STOP. */
1219     if (type == kI3C_TypeI2C)
1220     {
1221         base->MCONFIG |= I3C_MCONFIG_SKEW(1);
1222     }
1223     else
1224     {
1225         base->MCONFIG &= ~I3C_MCONFIG_SKEW_MASK;
1226     }
1227 #endif
1228 
1229     /* Issue start command. */
1230     mctrlVal = base->MCTRL;
1231     mctrlVal &= ~(I3C_MCTRL_TYPE_MASK | I3C_MCTRL_REQUEST_MASK | I3C_MCTRL_DIR_MASK | I3C_MCTRL_ADDR_MASK |
1232                   I3C_MCTRL_RDTERM_MASK);
1233     mctrlVal |= I3C_MCTRL_TYPE(type) | I3C_MCTRL_REQUEST(kI3C_RequestEmitStartAddr) | I3C_MCTRL_DIR(dir) |
1234                 I3C_MCTRL_ADDR(address) | I3C_MCTRL_RDTERM(rxSize);
1235 
1236     base->MCTRL = mctrlVal;
1237 
1238     return kStatus_Success;
1239 }
1240 /*!
1241  * brief Sends a STOP signal on the I2C/I3C bus.
1242  *
1243  * This function does not return until the STOP signal is seen on the bus, or an error occurs.
1244  *
1245  * param base The I3C peripheral base address.
1246  * retval #kStatus_Success The STOP signal was successfully sent on the bus and the transaction terminated.
1247  * retval #kStatus_I3C_Busy Another master is currently utilizing the bus.
1248  * retval #kStatus_I3C_Nak The slave device sent a NAK in response to a byte.
1249  * retval #kStatus_I3C_FifoError FIFO under run or overrun.
1250  * retval #kStatus_I3C_ArbitrationLost Arbitration lost error.
1251  * retval #kStatus_I3C_PinLowTimeout SCL or SDA were held low longer than the timeout.
1252  */
I3C_MasterStop(I3C_Type * base)1253 status_t I3C_MasterStop(I3C_Type *base)
1254 {
1255     return I3C_MasterEmitStop(base, true);
1256 }
1257 
1258 /*!
1259  * brief I3C master emit request.
1260  *
1261  * param base The I3C peripheral base address.
1262  * param masterReq  I3C master request of type #i3c_bus_request_t
1263  */
I3C_MasterEmitRequest(I3C_Type * base,i3c_bus_request_t masterReq)1264 void I3C_MasterEmitRequest(I3C_Type *base, i3c_bus_request_t masterReq)
1265 {
1266     uint32_t mctrlReg = base->MCTRL;
1267 
1268     mctrlReg &= ~I3C_MCTRL_REQUEST_MASK;
1269 
1270     if (masterReq == kI3C_RequestProcessDAA)
1271     {
1272         mctrlReg &= ~I3C_MCTRL_TYPE_MASK;
1273     }
1274 
1275     mctrlReg |= I3C_MCTRL_REQUEST(masterReq);
1276 
1277     base->MCTRL = mctrlReg;
1278 }
1279 
1280 /*!
1281  * brief I3C master register IBI rule.
1282  *
1283  * param base The I3C peripheral base address.
1284  * param ibiRule Pointer to ibi rule description of type #i3c_register_ibi_addr_t
1285  */
I3C_MasterRegisterIBI(I3C_Type * base,i3c_register_ibi_addr_t * ibiRule)1286 void I3C_MasterRegisterIBI(I3C_Type *base, i3c_register_ibi_addr_t *ibiRule)
1287 {
1288     assert(NULL != ibiRule);
1289     uint32_t ruleValue = I3C_MIBIRULES_MSB0_MASK;
1290 
1291     for (uint32_t count = 0; count < ARRAY_SIZE(ibiRule->address); count++)
1292     {
1293         ruleValue |= ((uint32_t)ibiRule->address[count]) << (count * I3C_MIBIRULES_ADDR1_SHIFT);
1294     }
1295 
1296     ruleValue &= ~I3C_MIBIRULES_NOBYTE_MASK;
1297 
1298     if (!ibiRule->ibiHasPayload)
1299     {
1300         ruleValue |= I3C_MIBIRULES_NOBYTE_MASK;
1301     }
1302 
1303     base->MIBIRULES = ruleValue;
1304 }
1305 
1306 /*!
1307  * brief I3C master get IBI rule.
1308  *
1309  * param base The I3C peripheral base address.
1310  * param ibiRule Pointer to store the read out ibi rule description.
1311  */
I3C_MasterGetIBIRules(I3C_Type * base,i3c_register_ibi_addr_t * ibiRule)1312 void I3C_MasterGetIBIRules(I3C_Type *base, i3c_register_ibi_addr_t *ibiRule)
1313 {
1314     assert(NULL != ibiRule);
1315 
1316     uint32_t ruleValue = base->MIBIRULES;
1317 
1318     for (uint32_t count = 0; count < ARRAY_SIZE(ibiRule->address); count++)
1319     {
1320         ibiRule->address[count] =
1321             (uint8_t)(ruleValue >> (count * I3C_MIBIRULES_ADDR1_SHIFT)) & I3C_MIBIRULES_ADDR0_MASK;
1322     }
1323 
1324     ibiRule->ibiHasPayload = (0U == (ruleValue & I3C_MIBIRULES_NOBYTE_MASK));
1325 }
1326 
1327 /*!
1328  * brief Performs a polling receive transfer on the I2C/I3C bus.
1329  *
1330  * param base  The I3C peripheral base address.
1331  * param rxBuff The pointer to the data to be transferred.
1332  * param rxSize The length in bytes of the data to be transferred.
1333  * param flags Bit mask of options for the transfer. See enumeration #_i3c_master_transfer_flags for available options.
1334  * retval #kStatus_Success Data was received successfully.
1335  * retval #kStatus_I3C_Busy Another master is currently utilizing the bus.
1336  * retval #kStatus_I3C_Nak The slave device sent a NAK in response to a byte.
1337  * retval #kStatus_I3C_FifoError FIFO under run or overrun.
1338  * retval #kStatus_I3C_ArbitrationLost Arbitration lost error.
1339  * retval #kStatus_I3C_PinLowTimeout SCL or SDA were held low longer than the timeout.
1340  */
I3C_MasterReceive(I3C_Type * base,void * rxBuff,size_t rxSize,uint32_t flags)1341 status_t I3C_MasterReceive(I3C_Type *base, void *rxBuff, size_t rxSize, uint32_t flags)
1342 {
1343     status_t result   = kStatus_Success;
1344     bool isRxAutoTerm = ((flags & (uint32_t)kI3C_TransferRxAutoTermFlag) != 0UL);
1345     bool completed    = false;
1346     uint32_t status;
1347     uint8_t *buf;
1348 
1349     assert(NULL != rxBuff);
1350 
1351     /* Handle empty read. */
1352     if (rxSize == 0UL)
1353     {
1354         return kStatus_Success;
1355     }
1356 
1357 #if I3C_RETRY_TIMES
1358     uint32_t waitTimes = I3C_RETRY_TIMES;
1359 #endif
1360 
1361     /* Receive data */
1362     buf = (uint8_t *)rxBuff;
1363 
1364     while ((rxSize != 0UL) || !completed)
1365     {
1366 #if I3C_RETRY_TIMES
1367         if (--waitTimes == 0)
1368         {
1369             return kStatus_I3C_Timeout;
1370         }
1371 #endif
1372         /* Check for errors. */
1373         result = I3C_MasterCheckAndClearError(base, I3C_MasterGetErrorStatusFlags(base));
1374         if (kStatus_Success != result)
1375         {
1376             return result;
1377         }
1378 
1379         /* Check complete flag */
1380         if (!completed)
1381         {
1382             status = I3C_MasterGetStatusFlags(base) & (uint32_t)kI3C_MasterCompleteFlag;
1383             if (0UL != status)
1384             {
1385                 completed = true;
1386                 /* Clear complete flag */
1387                 I3C_MasterClearStatusFlags(base, (uint32_t)kI3C_MasterCompleteFlag);
1388                 /* Send stop if needed */
1389                 if ((flags & (uint32_t)kI3C_TransferNoStopFlag) == 0UL)
1390                 {
1391                     if (I3C_MasterGetState(base) == kI3C_MasterStateDdr)
1392                     {
1393                         I3C_MasterEmitRequest(base, kI3C_RequestForceExit);
1394                         result = I3C_MasterWaitForCtrlDone(base, false);
1395                     }
1396                     else
1397                     {
1398                         result = I3C_MasterEmitStop(base, false);
1399                     }
1400                     if (kStatus_Success != result)
1401                     {
1402                         return result;
1403                     }
1404                 }
1405             }
1406         }
1407 
1408         /* Check RX data */
1409         if ((0UL != rxSize) && (0UL != (base->MDATACTRL & I3C_MDATACTRL_RXCOUNT_MASK)))
1410         {
1411             *buf++ = (uint8_t)(base->MRDATAB & I3C_MRDATAB_VALUE_MASK);
1412             rxSize--;
1413             if ((flags & (uint32_t)kI3C_TransferDisableRxTermFlag) == 0UL)
1414             {
1415                 if ((!isRxAutoTerm) && (rxSize == 1U))
1416                 {
1417                     base->MCTRL |= I3C_MCTRL_RDTERM(1U);
1418                 }
1419             }
1420         }
1421     }
1422 
1423     /* Wait idle if stop is sent. */
1424     if ((flags & (uint32_t)kI3C_TransferNoStopFlag) == 0UL)
1425     {
1426 #if I3C_RETRY_TIMES
1427         while ((I3C_MasterGetState(base) != kI3C_MasterStateIdle) && --waitTimes)
1428 #else
1429         while (I3C_MasterGetState(base) != kI3C_MasterStateIdle)
1430 #endif
1431         {
1432         }
1433     }
1434     return result;
1435 }
1436 
1437 /*!
1438  * brief Performs a polling send transfer on the I2C/I3C bus.
1439  *
1440  * Sends up to a txSize number of bytes to the previously addressed slave device. The slave may
1441  * reply with a NAK to any byte in order to terminate the transfer early. If this happens, this
1442  * function returns #kStatus_I3C_Nak.
1443  *
1444  * param base  The I3C peripheral base address.
1445  * param txBuff The pointer to the data to be transferred.
1446  * param txSize The length in bytes of the data to be transferred.
1447  * param flags Bit mask of options for the transfer. See enumeration #_i3c_master_transfer_flags for available options.
1448  * retval #kStatus_Success Data was sent successfully.
1449  * retval #kStatus_I3C_Busy Another master is currently utilizing the bus.
1450  * retval #kStatus_I3C_Nak The slave device sent a NAK in response to a byte.
1451  * retval #kStatus_I3C_FifoError FIFO under run or over run.
1452  * retval #kStatus_I3C_ArbitrationLost Arbitration lost error.
1453  * retval #kStatus_I3C_PinLowTimeout SCL or SDA were held low longer than the timeout.
1454  */
I3C_MasterSend(I3C_Type * base,const void * txBuff,size_t txSize,uint32_t flags)1455 status_t I3C_MasterSend(I3C_Type *base, const void *txBuff, size_t txSize, uint32_t flags)
1456 {
1457     i3c_puint8_to_u32_t buf;
1458     buf.cpuint8     = (const uint8_t *)((const void *)txBuff);
1459     status_t result = kStatus_Success;
1460     bool enableWord = ((flags & (uint32_t)kI3C_TransferWordsFlag) == (uint32_t)kI3C_TransferWordsFlag) ? true : false;
1461     uint8_t byteCounts = enableWord ? 2U : 1U;
1462 
1463     assert(NULL != txBuff);
1464     if (enableWord)
1465     {
1466         assert(txSize % 2UL == 0UL);
1467     }
1468 
1469     /* Send data buffer */
1470     while (0UL != txSize)
1471     {
1472         /* Wait until there is room in the fifo. This also checks for errors. */
1473         result = I3C_MasterWaitForTxReady(base, byteCounts);
1474         if (kStatus_Success != result)
1475         {
1476             return result;
1477         }
1478 
1479         /* Write byte into I3C master data register. */
1480         if (txSize > byteCounts)
1481         {
1482             if (enableWord)
1483             {
1484                 base->MWDATAH = (uint32_t)buf.cpuint8[1] << 8UL | (uint32_t)buf.cpuint8[0];
1485             }
1486             else
1487             {
1488                 base->MWDATAB = *buf.cpuint8;
1489             }
1490         }
1491         else
1492         {
1493             if (enableWord)
1494             {
1495                 base->MWDATAHE = (uint32_t)buf.cpuint8[1] << 8UL | (uint32_t)buf.cpuint8[0];
1496             }
1497             else
1498             {
1499                 base->MWDATABE = *buf.cpuint8;
1500             }
1501         }
1502 
1503         buf.u32 = buf.u32 + byteCounts;
1504         txSize  = txSize - byteCounts;
1505     }
1506 
1507     result = I3C_MasterWaitForComplete(base, false);
1508     if ((result == kStatus_Success) && ((flags & (uint32_t)kI3C_TransferNoStopFlag) == 0UL))
1509     {
1510         if (I3C_MasterGetState(base) == kI3C_MasterStateDdr)
1511         {
1512             I3C_MasterEmitRequest(base, kI3C_RequestForceExit);
1513             result = I3C_MasterWaitForCtrlDone(base, false);
1514         }
1515         else
1516         {
1517             result = I3C_MasterEmitStop(base, true);
1518         }
1519     }
1520 
1521     return result;
1522 }
1523 
1524 /*!
1525  * brief Performs a DAA in the i3c bus with specified temporary baud rate.
1526  *
1527  * param base The I3C peripheral base address.
1528  * param addressList The pointer for address list which is used to do DAA.
1529  * param count The address count in the address list.
1530  * param daaBaudRate The temporary baud rate in DAA process, NULL for using initial setting.
1531  * The initial setting is set back between the completion of the DAA and the return of this function.
1532  * retval #kStatus_Success The transaction was started successfully.
1533  * retval #kStatus_I3C_Busy Either another master is currently utilizing the bus, or a non-blocking
1534  *      transaction is already in progress.
1535  * retval #kStatus_I3C_SlaveCountExceed The I3C slave count has exceed the definition in I3C_MAX_DEVCNT.
1536  */
I3C_MasterProcessDAASpecifiedBaudrate(I3C_Type * base,uint8_t * addressList,uint32_t count,i3c_master_daa_baudrate_t * daaBaudRate)1537 status_t I3C_MasterProcessDAASpecifiedBaudrate(I3C_Type *base,
1538                                                uint8_t *addressList,
1539                                                uint32_t count,
1540                                                i3c_master_daa_baudrate_t *daaBaudRate)
1541 {
1542     assert(addressList != NULL);
1543     assert(count != 0U);
1544 
1545     status_t result       = kStatus_Success;
1546     uint8_t rxBuffer[8]   = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};
1547     uint32_t masterConfig = 0;
1548     uint32_t devCount     = 0;
1549     uint8_t rxSize        = 0;
1550     bool mctrlDone        = false;
1551     i3c_baudrate_hz_t baudRate_Hz;
1552     uint32_t errStatus;
1553     uint32_t status;
1554     size_t rxCount;
1555 
1556     /* Return an error if the bus is already in use not by us. */
1557     result = I3C_CheckForBusyBus(base);
1558     if (kStatus_Success != result)
1559     {
1560         return result;
1561     }
1562 
1563     /* Clear all flags. */
1564     I3C_MasterClearErrorStatusFlags(base, (uint32_t)kMasterErrorFlags);
1565     I3C_MasterClearStatusFlags(base, (uint32_t)kMasterClearFlags);
1566 
1567     /* Disable I3C IRQ sources while we configure stuff. */
1568     uint32_t enabledInts = I3C_MasterGetEnabledInterrupts(base);
1569     I3C_MasterDisableInterrupts(base, enabledInts);
1570 
1571     /* Temporarily adjust baud rate before DAA. */
1572     if (daaBaudRate != NULL)
1573     {
1574         masterConfig = base->MCONFIG;
1575         /* Set non-zero value for I2C baud rate which is useless here. */
1576         baudRate_Hz.i2cBaud          = 1;
1577         baudRate_Hz.i3cOpenDrainBaud = daaBaudRate->i3cOpenDrainBaud;
1578         baudRate_Hz.i3cPushPullBaud  = daaBaudRate->i3cPushPullBaud;
1579         I3C_MasterSetBaudRate(base, &baudRate_Hz, daaBaudRate->sourceClock_Hz);
1580     }
1581 
1582     /* Emit process DAA */
1583     I3C_MasterEmitRequest(base, kI3C_RequestProcessDAA);
1584 
1585     do
1586     {
1587         status = I3C_MasterGetStatusFlags(base);
1588 
1589         /* Check for error flags. */
1590         errStatus = I3C_MasterGetErrorStatusFlags(base);
1591         result    = I3C_MasterCheckAndClearError(base, errStatus);
1592         if (kStatus_Success != result)
1593         {
1594             break;
1595         }
1596 
1597         if ((!mctrlDone) || (rxSize < 8U))
1598         {
1599             I3C_MasterGetFifoCounts(base, &rxCount, NULL);
1600 
1601             if ((0UL != (status & (uint32_t)kI3C_MasterRxReadyFlag)) && (rxCount != 0U))
1602             {
1603                 rxBuffer[rxSize++] = (uint8_t)(base->MRDATAB & I3C_MRDATAB_VALUE_MASK);
1604             }
1605 
1606             if ((status & (uint32_t)kI3C_MasterControlDoneFlag) != 0U)
1607             {
1608                 I3C_MasterClearStatusFlags(base, (uint32_t)kI3C_MasterControlDoneFlag);
1609                 mctrlDone = true;
1610             }
1611         }
1612         else if ((I3C_MasterGetState(base) == kI3C_MasterStateDaa) &&
1613                  (0UL != (I3C_MasterGetStatusFlags(base) & (uint32_t)kI3C_MasterBetweenFlag)))
1614         {
1615             if (((devCount + 1UL) > count) || ((devCount + 1UL) > I3C_MAX_DEVCNT))
1616             {
1617                 result = kStatus_I3C_SlaveCountExceed;
1618                 break;
1619             }
1620 
1621             /* Assign the dynamic address from address list. */
1622             devList[devCount].dynamicAddr = *addressList++;
1623             base->MWDATAB                 = devList[devCount].dynamicAddr;
1624 
1625             /* Emit process DAA again. */
1626             I3C_MasterEmitRequest(base, kI3C_RequestProcessDAA);
1627 
1628             devList[devCount].vendorID   = (((uint16_t)rxBuffer[0] << 8U | (uint16_t)rxBuffer[1]) & 0xFFFEU) >> 1U;
1629             devList[devCount].partNumber = ((uint32_t)rxBuffer[2] << 24U | (uint32_t)rxBuffer[3] << 16U |
1630                                             (uint32_t)rxBuffer[4] << 8U | (uint32_t)rxBuffer[5]);
1631             devList[devCount].bcr        = rxBuffer[6];
1632             devList[devCount].dcr        = rxBuffer[7];
1633             devCount++;
1634             usedDevCount++;
1635 
1636             /* Ready to handle next device. */
1637             mctrlDone = false;
1638             rxSize    = 0;
1639         }
1640         else
1641         {
1642             /* Intentional empty */
1643         }
1644     } while ((status & (uint32_t)kI3C_MasterCompleteFlag) != (uint32_t)kI3C_MasterCompleteFlag);
1645 
1646     /* Master stops DAA if slave device number exceeds the prepared address number. */
1647     if (result == kStatus_I3C_SlaveCountExceed)
1648     {
1649         /* Send the STOP signal */
1650         base->MCTRL = (base->MCTRL & ~(I3C_MCTRL_REQUEST_MASK | I3C_MCTRL_DIR_MASK | I3C_MCTRL_RDTERM_MASK)) |
1651                       I3C_MCTRL_REQUEST(kI3C_RequestEmitStop);
1652     }
1653 
1654     /* Set back initial baud rate after DAA is over. */
1655     if (daaBaudRate != NULL)
1656     {
1657         base->MCONFIG = masterConfig;
1658     }
1659 
1660     /* Clear all flags. */
1661     I3C_MasterClearErrorStatusFlags(base, (uint32_t)kMasterErrorFlags);
1662     I3C_MasterClearStatusFlags(base, (uint32_t)kMasterClearFlags);
1663 
1664     /* Enable I3C IRQ sources while we configure stuff. */
1665     I3C_MasterEnableInterrupts(base, enabledInts);
1666 
1667     return result;
1668 }
1669 
1670 /*!
1671  * brief Get device information list after DAA process is done.
1672  *
1673  * param base The I3C peripheral base address.
1674  * param[out] count The pointer to store the available device count.
1675  * return Pointer to the i3c_device_info_t array.
1676  */
I3C_MasterGetDeviceListAfterDAA(I3C_Type * base,uint8_t * count)1677 i3c_device_info_t *I3C_MasterGetDeviceListAfterDAA(I3C_Type *base, uint8_t *count)
1678 {
1679     assert(NULL != count);
1680 
1681     *count = usedDevCount;
1682 
1683     return devList;
1684 }
1685 
1686 /*!
1687  * @brief introduce function I3C_MasterClearFlagsAndEnableIRQ.
1688  *
1689  * This function was used of Clear all flags and Enable I3C IRQ sources for @param *base.
1690  *
1691  * @param base The I3C peripheral base address.
1692  */
I3C_MasterClearFlagsAndEnableIRQ(I3C_Type * base)1693 static void I3C_MasterClearFlagsAndEnableIRQ(I3C_Type *base)
1694 {
1695     /* Clear all flags. */
1696     I3C_MasterClearStatusFlags(base, (uint32_t)kMasterClearFlags);
1697     /* Enable I3C IRQ sources. */
1698     I3C_MasterEnableInterrupts(base, (uint32_t)kMasterIrqFlags);
1699 }
1700 
1701 /*!
1702  * @brief introduce function I3C_MasterTransferNoStartFlag.
1703  *
1704  * This function was used of Check if device request wins arbitration.
1705  *
1706  * @param base The I3C peripheral base address.
1707  * @param transfer Pointer to the transfer structure.
1708  * @retval #true if the device wins arbitration.
1709  * @retval #false if the device not wins arbitration.
1710  */
I3C_MasterTransferNoStartFlag(I3C_Type * base,i3c_master_transfer_t * transfer)1711 static bool I3C_MasterTransferNoStartFlag(I3C_Type *base, i3c_master_transfer_t *transfer)
1712 {
1713     /* Wait tx fifo empty. */
1714     size_t txCount = 0xFFUL;
1715 
1716     while (txCount != 0U)
1717     {
1718         I3C_MasterGetFifoCounts(base, NULL, &txCount);
1719     }
1720 
1721     /* Check if device request wins arbitration. */
1722     if (0UL != (I3C_MasterGetStatusFlags(base) & (uint32_t)kI3C_MasterArbitrationWonFlag))
1723     {
1724         I3C_MasterClearFlagsAndEnableIRQ(base);
1725         return true;
1726     }
1727     return false;
1728 }
1729 
1730 /*!
1731  * brief Performs a master polling transfer on the I2C/I3C bus.
1732  *
1733  * note The API does not return until the transfer succeeds or fails due
1734  * to error happens during transfer.
1735  *
1736  * param base The I3C peripheral base address.
1737  * param transfer Pointer to the transfer structure.
1738  * retval #kStatus_Success Data was received successfully.
1739  * retval #kStatus_I3C_Busy Another master is currently utilizing the bus.
1740  * retval #kStatus_I3C_Nak The slave device sent a NAK in response to a byte.
1741  * retval #kStatus_I3C_FifoError FIFO under run or overrun.
1742  * retval #kStatus_I3C_ArbitrationLost Arbitration lost error.
1743  * retval #kStatus_I3C_PinLowTimeout SCL or SDA were held low longer than the timeout.
1744  */
I3C_MasterTransferBlocking(I3C_Type * base,i3c_master_transfer_t * transfer)1745 status_t I3C_MasterTransferBlocking(I3C_Type *base, i3c_master_transfer_t *transfer)
1746 {
1747     assert(NULL != transfer);
1748     assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
1749 
1750     status_t result                = kStatus_Success;
1751     i3c_direction_t direction      = transfer->direction;
1752     i3c_master_state_t masterState = I3C_MasterGetState(base);
1753     bool checkDdrState             = false;
1754     i3c_rx_term_ops_t rxTermOps;
1755 
1756     /* Return an error if the bus is already in use not by us. */
1757     checkDdrState = (transfer->busType == kI3C_TypeI3CDdr) ? (masterState != kI3C_MasterStateDdr) : true;
1758 
1759     if ((masterState != kI3C_MasterStateIdle) && (masterState != kI3C_MasterStateNormAct) && checkDdrState)
1760     {
1761         return kStatus_I3C_Busy;
1762     }
1763 
1764     /* Clear all flags. */
1765     I3C_MasterClearStatusFlags(base, (uint32_t)kMasterClearFlags);
1766     /* Reset fifos. These flags clear automatically. */
1767     base->MDATACTRL |= I3C_MDATACTRL_FLUSHTB_MASK | I3C_MDATACTRL_FLUSHFB_MASK;
1768 
1769     /* Disable I3C IRQ sources while we configure stuff. */
1770     I3C_MasterDisableInterrupts(base, (uint32_t)kMasterIrqFlags);
1771 
1772     if (transfer->busType != kI3C_TypeI3CDdr)
1773     {
1774         direction = (0UL != transfer->subaddressSize) ? kI3C_Write : transfer->direction;
1775     }
1776 
1777     /* True: Set Rx termination bytes at start point, False: Set Rx termination one bytes in advance. */
1778     if ((transfer->flags & (uint32_t)kI3C_TransferDisableRxTermFlag) != 0U)
1779     {
1780         rxTermOps = kI3C_RxTermDisable;
1781     }
1782     else if (transfer->dataSize <= 255U)
1783     {
1784         rxTermOps = kI3C_RxAutoTerm;
1785     }
1786     else
1787     {
1788         rxTermOps = kI3C_RxTermLastByte;
1789     }
1790 
1791     if (0UL != (transfer->flags & (uint32_t)kI3C_TransferStartWithBroadcastAddr))
1792     {
1793         if (0UL != (transfer->flags & (uint32_t)kI3C_TransferNoStartFlag))
1794         {
1795             return kStatus_InvalidArgument;
1796         }
1797 
1798         if (0UL != (transfer->flags & (uint32_t)kI3C_TransferRepeatedStartFlag))
1799         {
1800             return kStatus_InvalidArgument;
1801         }
1802 
1803         /* Issue 0x7E as start. */
1804         result = I3C_MasterStart(base, transfer->busType, 0x7E, kI3C_Write);
1805         if (result != kStatus_Success)
1806         {
1807             return result;
1808         }
1809 
1810         result = I3C_MasterWaitForCtrlDone(base, false);
1811         if (result != kStatus_Success)
1812         {
1813             return result;
1814         }
1815     }
1816 
1817     if (0UL == (transfer->flags & (uint32_t)kI3C_TransferNoStartFlag))
1818     {
1819         if ((direction == kI3C_Read) && (rxTermOps == kI3C_RxAutoTerm))
1820         {
1821             result = I3C_MasterStartWithRxSize(base, transfer->busType, transfer->slaveAddress, direction,
1822                                                (uint8_t)transfer->dataSize);
1823         }
1824         else
1825         {
1826             result = I3C_MasterStart(base, transfer->busType, transfer->slaveAddress, direction);
1827         }
1828         if (result != kStatus_Success)
1829         {
1830             return result;
1831         }
1832 
1833         result = I3C_MasterWaitForCtrlDone(base, false);
1834         if (result != kStatus_Success)
1835         {
1836             return result;
1837         }
1838 
1839         if (true == I3C_MasterTransferNoStartFlag(base, transfer))
1840         {
1841             return kStatus_I3C_IBIWon;
1842         }
1843     }
1844     else
1845     {
1846         if ((direction == kI3C_Read) && (rxTermOps != kI3C_RxTermDisable))
1847         {
1848             /* Can't set Rx termination more than one bytes in advance without START. */
1849             rxTermOps = kI3C_RxTermLastByte;
1850         }
1851     }
1852 
1853     /* Subaddress, MSB first. */
1854     if (0U != transfer->subaddressSize)
1855     {
1856         uint32_t subaddressRemaining = transfer->subaddressSize;
1857         while (0UL != subaddressRemaining--)
1858         {
1859             uint8_t subaddressByte = (uint8_t)((transfer->subaddress >> (8UL * subaddressRemaining)) & 0xFFUL);
1860 
1861             result = I3C_MasterWaitForTxReady(base, 1U);
1862 
1863             if ((0UL == subaddressRemaining) && ((transfer->direction == kI3C_Read) || (0UL == transfer->dataSize)) &&
1864                 (transfer->busType != kI3C_TypeI3CDdr))
1865             {
1866                 base->MWDATABE = subaddressByte;
1867                 result         = I3C_MasterWaitForComplete(base, false);
1868                 if (kStatus_Success != result)
1869                 {
1870                     if (result == kStatus_I3C_Nak)
1871                     {
1872                         (void)I3C_MasterEmitStop(base, true);
1873                     }
1874                     I3C_MasterClearFlagsAndEnableIRQ(base);
1875                     return result;
1876                 }
1877             }
1878             else
1879             {
1880                 base->MWDATAB = subaddressByte;
1881             }
1882         }
1883         /* Need to send repeated start if switching directions to read. */
1884         if ((transfer->busType != kI3C_TypeI3CDdr) && (0UL != transfer->dataSize) && (transfer->direction == kI3C_Read))
1885         {
1886             if (rxTermOps == kI3C_RxAutoTerm)
1887             {
1888                 result = I3C_MasterRepeatedStartWithRxSize(base, transfer->busType, transfer->slaveAddress, kI3C_Read,
1889                                                            (uint8_t)transfer->dataSize);
1890             }
1891             else
1892             {
1893                 result = I3C_MasterRepeatedStart(base, transfer->busType, transfer->slaveAddress, kI3C_Read);
1894             }
1895 
1896             if (kStatus_Success != result)
1897             {
1898                 I3C_MasterClearFlagsAndEnableIRQ(base);
1899                 return result;
1900             }
1901 
1902             result = I3C_MasterWaitForCtrlDone(base, false);
1903             if (result != kStatus_Success)
1904             {
1905                 return result;
1906             }
1907         }
1908     }
1909 
1910     if (rxTermOps == kI3C_RxAutoTerm)
1911     {
1912         transfer->flags |= (uint32_t)kI3C_TransferRxAutoTermFlag;
1913     }
1914     else
1915     {
1916         transfer->flags &= ~(uint32_t)kI3C_TransferRxAutoTermFlag;
1917     }
1918 
1919     /* Transmit data. */
1920     if ((transfer->direction == kI3C_Write) && (transfer->dataSize > 0UL))
1921     {
1922         /* Send Data. */
1923         result = I3C_MasterSend(base, transfer->data, transfer->dataSize, transfer->flags);
1924     }
1925     /* Receive Data. */
1926     else if ((transfer->direction == kI3C_Read) && (transfer->dataSize > 0UL))
1927     {
1928         result = I3C_MasterReceive(base, transfer->data, transfer->dataSize, transfer->flags);
1929     }
1930     else
1931     {
1932         if ((transfer->flags & (uint32_t)kI3C_TransferNoStopFlag) == 0UL)
1933         {
1934             result = I3C_MasterEmitStop(base, true);
1935         }
1936     }
1937 
1938     if (result == kStatus_I3C_Nak)
1939     {
1940         (void)I3C_MasterEmitStop(base, true);
1941     }
1942 
1943     I3C_MasterClearFlagsAndEnableIRQ(base);
1944 
1945     return result;
1946 }
1947 
1948 /*!
1949  * brief Creates a new handle for the I3C master non-blocking APIs.
1950  *
1951  * The creation of a handle is for use with the non-blocking APIs. Once a handle
1952  * is created, there is not a corresponding destroy handle. If the user wants to
1953  * terminate a transfer, the I3C_MasterTransferAbort() API shall be called.
1954  *
1955  *
1956  * note The function also enables the NVIC IRQ for the input I3C. Need to notice
1957  * that on some SoCs the I3C IRQ is connected to INTMUX, in this case user needs to
1958  * enable the associated INTMUX IRQ in application.
1959  *
1960  * param base The I3C peripheral base address.
1961  * param[out] handle Pointer to the I3C master driver handle.
1962  * param callback User provided pointer to the asynchronous callback function.
1963  * param userData User provided pointer to the application callback data.
1964  */
I3C_MasterTransferCreateHandle(I3C_Type * base,i3c_master_handle_t * handle,const i3c_master_transfer_callback_t * callback,void * userData)1965 void I3C_MasterTransferCreateHandle(I3C_Type *base,
1966                                     i3c_master_handle_t *handle,
1967                                     const i3c_master_transfer_callback_t *callback,
1968                                     void *userData)
1969 {
1970     uint32_t instance;
1971 
1972     assert(NULL != handle);
1973 
1974     /* Clear out the handle. */
1975     (void)memset(handle, 0, sizeof(*handle));
1976 
1977     /* Look up instance number */
1978     instance = I3C_GetInstance(base);
1979 
1980     /* Save base and instance. */
1981     handle->callback = *callback;
1982     handle->userData = userData;
1983 
1984     /* Save this handle for IRQ use. */
1985     s_i3cMasterHandle[instance] = handle;
1986 
1987     /* Set irq handler. */
1988     s_i3cMasterIsr = I3C_MasterTransferHandleIRQ;
1989 
1990     /* Clear all flags. */
1991     I3C_MasterClearErrorStatusFlags(base, (uint32_t)kMasterErrorFlags);
1992     I3C_MasterClearStatusFlags(base, (uint32_t)kMasterClearFlags);
1993     /* Reset fifos. These flags clear automatically. */
1994     base->MDATACTRL |= I3C_MDATACTRL_FLUSHTB_MASK | I3C_MDATACTRL_FLUSHFB_MASK;
1995 
1996     /* Enable NVIC IRQ, this only enables the IRQ directly connected to the NVIC.
1997      In some cases the I3C IRQ is configured through INTMUX, user needs to enable
1998      INTMUX IRQ in application code. */
1999     (void)EnableIRQ(kI3cIrqs[instance]);
2000 
2001     /* Clear internal IRQ enables and enable NVIC IRQ. */
2002     I3C_MasterEnableInterrupts(base, (uint32_t)kMasterIrqFlags);
2003 }
2004 
I3C_TransferStateMachineIBIWonState(I3C_Type * base,i3c_master_handle_t * handle,i3c_master_state_machine_param_t * stateParams)2005 static void I3C_TransferStateMachineIBIWonState(I3C_Type *base,
2006                                                 i3c_master_handle_t *handle,
2007                                                 i3c_master_state_machine_param_t *stateParams)
2008 {
2009     assert(NULL != base && NULL != handle && NULL != stateParams);
2010     if (stateParams->masterState == kI3C_MasterStateIbiAck)
2011     {
2012         handle->ibiType = I3C_GetIBIType(base);
2013         if (handle->callback.ibiCallback != NULL)
2014         {
2015             handle->callback.ibiCallback(base, handle, handle->ibiType, kI3C_IbiAckNackPending);
2016         }
2017         else
2018         {
2019             I3C_MasterEmitIBIResponse(base, kI3C_IbiRespNack);
2020         }
2021     }
2022 
2023     /* Make sure there is data in the rx fifo. */
2024     if (0UL != stateParams->rxCount)
2025     {
2026         if ((handle->ibiBuff == NULL) && (handle->callback.ibiCallback != NULL))
2027         {
2028             handle->callback.ibiCallback(base, handle, kI3C_IbiNormal, kI3C_IbiDataBuffNeed);
2029         }
2030         uint8_t tempData = (uint8_t)base->MRDATAB;
2031         if (handle->ibiBuff != NULL)
2032         {
2033             handle->ibiBuff[handle->ibiPayloadSize++] = tempData;
2034         }
2035         (stateParams->rxCount)--;
2036         return;
2037     }
2038     else if (0UL != (stateParams->status & (uint32_t)kI3C_MasterCompleteFlag))
2039     {
2040         handle->ibiType             = I3C_GetIBIType(base);
2041         handle->ibiAddress          = I3C_GetIBIAddress(base);
2042         stateParams->state_complete = true;
2043         stateParams->result         = kStatus_I3C_IBIWon;
2044     }
2045     else
2046     {
2047         stateParams->state_complete = true;
2048     }
2049 }
2050 
I3C_TransferStateMachineSendCommandState(I3C_Type * base,i3c_master_handle_t * handle,i3c_master_state_machine_param_t * stateParams)2051 static void I3C_TransferStateMachineSendCommandState(I3C_Type *base,
2052                                                      i3c_master_handle_t *handle,
2053                                                      i3c_master_state_machine_param_t *stateParams)
2054 {
2055     assert(NULL != base && NULL != handle && NULL != stateParams);
2056     I3C_MasterEnableInterrupts(base, (uint32_t)kI3C_MasterTxReadyFlag);
2057     /* Make sure there is room in the tx fifo for the next command. */
2058     if (0UL == (stateParams->txCount)--)
2059     {
2060         stateParams->state_complete = true;
2061         return;
2062     }
2063     if (handle->transfer.subaddressSize > 1U)
2064     {
2065         handle->transfer.subaddressSize--;
2066         base->MWDATAB = (uint8_t)((handle->transfer.subaddress) >> (8U * handle->transfer.subaddressSize));
2067     }
2068     else if (handle->transfer.subaddressSize == 1U)
2069     {
2070         handle->transfer.subaddressSize--;
2071 
2072         if ((handle->transfer.direction == kI3C_Read) || (0UL == handle->transfer.dataSize))
2073         {
2074             base->MWDATABE = (uint8_t)((handle->transfer.subaddress) >> (8U * handle->transfer.subaddressSize));
2075 
2076             if (handle->transfer.busType != kI3C_TypeI3CDdr)
2077             {
2078                 if (0UL == handle->transfer.dataSize)
2079                 {
2080                     handle->state = (uint8_t)kWaitForCompletionState;
2081                 }
2082                 else
2083                 {
2084                     /* xfer->dataSize != 0U, xfer->direction = kI3C_Read */
2085                     handle->state = (uint8_t)kWaitRepeatedStartCompleteState;
2086                 }
2087             }
2088             else
2089             {
2090                 handle->state = (uint8_t)kTransferDataState;
2091             }
2092         }
2093         else
2094         {
2095             /* Next state, transfer data. */
2096             handle->state = (uint8_t)kTransferDataState;
2097             base->MWDATAB = (uint8_t)((handle->transfer.subaddress) >> (8U * handle->transfer.subaddressSize));
2098         }
2099     }
2100     else
2101     {
2102         /* Eliminate misra 15.7*/
2103     }
2104 }
2105 
I3C_TransferStateMachineWaitRepeatedStartCompleteState(I3C_Type * base,i3c_master_handle_t * handle,i3c_master_state_machine_param_t * stateParams)2106 static void I3C_TransferStateMachineWaitRepeatedStartCompleteState(I3C_Type *base,
2107                                                                    i3c_master_handle_t *handle,
2108                                                                    i3c_master_state_machine_param_t *stateParams)
2109 {
2110     assert(NULL != base && NULL != handle && NULL != stateParams);
2111     /* We stay in this state until the master complete. */
2112     if (0UL != (stateParams->status & (uint32_t)kI3C_MasterCompleteFlag))
2113     {
2114         handle->state = (uint8_t)kTransferDataState;
2115         I3C_MasterDisableInterrupts(base, (uint32_t)kI3C_MasterTxReadyFlag);
2116 
2117         if (handle->remainingBytes < 256U)
2118         {
2119             handle->rxTermOps = (handle->rxTermOps == kI3C_RxTermDisable) ? handle->rxTermOps : kI3C_RxAutoTerm;
2120             stateParams->result =
2121                 I3C_MasterRepeatedStartWithRxSize(base, handle->transfer.busType, handle->transfer.slaveAddress,
2122                                                   kI3C_Read, (uint8_t)handle->remainingBytes);
2123         }
2124         else
2125         {
2126             stateParams->result =
2127                 I3C_MasterRepeatedStart(base, handle->transfer.busType, handle->transfer.slaveAddress, kI3C_Read);
2128         }
2129     }
2130 
2131     stateParams->state_complete = true;
2132 }
2133 
I3C_TransferStateMachineTransferDataState(I3C_Type * base,i3c_master_handle_t * handle,i3c_master_state_machine_param_t * stateParams)2134 static void I3C_TransferStateMachineTransferDataState(I3C_Type *base,
2135                                                       i3c_master_handle_t *handle,
2136                                                       i3c_master_state_machine_param_t *stateParams)
2137 {
2138     assert(NULL != base && NULL != handle && NULL != stateParams);
2139 
2140     i3c_puint8_to_u32_t dataBuff;
2141     if (handle->transfer.direction == kI3C_Write)
2142     {
2143         /* Make sure there is room in the tx fifo. */
2144         if (0UL == (stateParams->txCount)--)
2145         {
2146             stateParams->state_complete = true;
2147             return;
2148         }
2149 
2150         /* Put byte to send in fifo. */
2151         dataBuff.puint8 = (uint8_t *)handle->transfer.data;
2152         if (handle->transfer.dataSize > 1U)
2153         {
2154             base->MWDATAB = *dataBuff.puint8;
2155         }
2156         else
2157         {
2158             base->MWDATABE = *dataBuff.puint8;
2159         }
2160         dataBuff.u32 = dataBuff.u32 + 1U;
2161         (handle->transfer.dataSize)--;
2162         handle->transfer.data = (void *)(dataBuff.puint8);
2163 
2164         /* Move to stop when the transfer is done. */
2165         if (--handle->remainingBytes == 0UL)
2166         {
2167             handle->state = (uint8_t)kWaitForCompletionState;
2168         }
2169     }
2170     else
2171     {
2172         /* Make sure there is data in the rx fifo. */
2173         if (0UL == (stateParams->rxCount)--)
2174         {
2175             stateParams->state_complete = true;
2176             return;
2177         }
2178 
2179         /* Read byte from fifo. */
2180         dataBuff.puint8       = (uint8_t *)handle->transfer.data;
2181         *dataBuff.puint8      = (uint8_t)base->MRDATAB;
2182         dataBuff.u32          = dataBuff.u32 + 1U;
2183         handle->transfer.data = (void *)(dataBuff.puint8);
2184 
2185         /* Move to stop when the transfer is done. */
2186         if (--handle->remainingBytes == 0UL)
2187         {
2188             handle->state = (uint8_t)kWaitForCompletionState;
2189         }
2190 
2191         if ((handle->rxTermOps == kI3C_RxTermLastByte) && (handle->remainingBytes == 1UL))
2192         {
2193             base->MCTRL |= I3C_MCTRL_RDTERM(1UL);
2194         }
2195     }
2196 }
2197 
I3C_TransferStateMachineWaitForCompletionState(i3c_master_handle_t * handle,i3c_master_state_machine_param_t * stateParams)2198 static void I3C_TransferStateMachineWaitForCompletionState(i3c_master_handle_t *handle,
2199                                                            i3c_master_state_machine_param_t *stateParams)
2200 {
2201     /* We stay in this state until the maste complete. */
2202     if (0UL != (stateParams->status & (uint32_t)kI3C_MasterCompleteFlag))
2203     {
2204         handle->state = (uint8_t)kStopState;
2205     }
2206     else
2207     {
2208         stateParams->state_complete = true;
2209     }
2210 }
2211 
I3C_TransferStateMachineStopState(I3C_Type * base,i3c_master_handle_t * handle,i3c_master_state_machine_param_t * stateParams)2212 static void I3C_TransferStateMachineStopState(I3C_Type *base,
2213                                               i3c_master_handle_t *handle,
2214                                               i3c_master_state_machine_param_t *stateParams)
2215 {
2216     /* Only issue a stop transition if the caller requested it. */
2217     if (0UL == (handle->transfer.flags & (uint32_t)kI3C_TransferNoStopFlag))
2218     {
2219         /* Make sure there is room in the tx fifo for the stop command. */
2220         if (0UL == (stateParams->txCount)--)
2221         {
2222             stateParams->state_complete = true;
2223             return;
2224         }
2225         if (handle->transfer.busType == kI3C_TypeI3CDdr)
2226         {
2227             I3C_MasterEmitRequest(base, kI3C_RequestForceExit);
2228         }
2229         else
2230         {
2231             (void)I3C_MasterEmitStop(base, false);
2232         }
2233     }
2234     stateParams->state_complete = true;
2235 }
2236 
I3C_RunTransferStateMachine(I3C_Type * base,i3c_master_handle_t * handle,bool * isDone)2237 static status_t I3C_RunTransferStateMachine(I3C_Type *base, i3c_master_handle_t *handle, bool *isDone)
2238 {
2239     i3c_master_state_machine_param_t stateParams;
2240     (void)memset(&stateParams, 0, sizeof(stateParams));
2241 
2242     stateParams.result         = kStatus_Success;
2243     stateParams.state_complete = false;
2244 
2245     /* Set default isDone return value. */
2246     *isDone = false;
2247 
2248     uint32_t errStatus;
2249     size_t txFifoSize =
2250         2UL << ((base->SCAPABILITIES & I3C_SCAPABILITIES_FIFOTX_MASK) >> I3C_SCAPABILITIES_FIFOTX_SHIFT);
2251 
2252     /* Check for errors. */
2253     stateParams.status = (uint32_t)I3C_MasterGetPendingInterrupts(base);
2254     I3C_MasterClearStatusFlags(base, stateParams.status);
2255 
2256     stateParams.masterState = I3C_MasterGetState(base);
2257     errStatus               = I3C_MasterGetErrorStatusFlags(base);
2258     stateParams.result      = I3C_MasterCheckAndClearError(base, errStatus);
2259     if (kStatus_Success != stateParams.result)
2260     {
2261         return stateParams.result;
2262     }
2263 
2264     if (0UL != (stateParams.status & (uint32_t)kI3C_MasterSlave2MasterFlag))
2265     {
2266         if (handle->callback.slave2Master != NULL)
2267         {
2268             handle->callback.slave2Master(base, handle->userData);
2269         }
2270     }
2271 
2272     if ((0UL != (stateParams.status & (uint32_t)kI3C_MasterSlaveStartFlag)) &&
2273         (handle->transfer.busType != kI3C_TypeI2C))
2274     {
2275         handle->state = (uint8_t)kSlaveStartState;
2276     }
2277 
2278     if ((stateParams.masterState == kI3C_MasterStateIbiRcv) || (stateParams.masterState == kI3C_MasterStateIbiAck))
2279     {
2280         handle->state = (uint8_t)kIBIWonState;
2281     }
2282 
2283     if (handle->state == (uint8_t)kIdleState)
2284     {
2285         return stateParams.result;
2286     }
2287 
2288     /* Get fifo counts and compute room in tx fifo. */
2289     I3C_MasterGetFifoCounts(base, &stateParams.rxCount, &stateParams.txCount);
2290     stateParams.txCount = txFifoSize - stateParams.txCount;
2291 
2292     while (!stateParams.state_complete)
2293     {
2294         /* Execute the state. */
2295         switch (handle->state)
2296         {
2297             case (uint8_t)kSlaveStartState:
2298                 /* Emit start + 0x7E */
2299                 I3C_MasterEmitRequest(base, kI3C_RequestAutoIbi);
2300                 handle->state              = (uint8_t)kIBIWonState;
2301                 stateParams.state_complete = true;
2302                 break;
2303 
2304             case (uint8_t)kIBIWonState:
2305                 I3C_TransferStateMachineIBIWonState(base, handle, &stateParams);
2306                 break;
2307 
2308             case (uint8_t)kSendCommandState:
2309                 I3C_TransferStateMachineSendCommandState(base, handle, &stateParams);
2310                 break;
2311 
2312             case (uint8_t)kWaitRepeatedStartCompleteState:
2313                 I3C_TransferStateMachineWaitRepeatedStartCompleteState(base, handle, &stateParams);
2314                 break;
2315 
2316             case (uint8_t)kTransferDataState:
2317                 I3C_TransferStateMachineTransferDataState(base, handle, &stateParams);
2318                 break;
2319 
2320             case (uint8_t)kWaitForCompletionState:
2321                 I3C_TransferStateMachineWaitForCompletionState(handle, &stateParams);
2322                 break;
2323 
2324             case (uint8_t)kStopState:
2325                 I3C_TransferStateMachineStopState(base, handle, &stateParams);
2326                 *isDone = true;
2327                 break;
2328 
2329             default:
2330                 assert(false);
2331                 break;
2332         }
2333     }
2334     return stateParams.result;
2335 }
2336 
I3C_InitTransferStateMachine(I3C_Type * base,i3c_master_handle_t * handle)2337 static status_t I3C_InitTransferStateMachine(I3C_Type *base, i3c_master_handle_t *handle)
2338 {
2339     i3c_master_transfer_t *xfer = &handle->transfer;
2340     status_t result             = kStatus_Success;
2341     i3c_direction_t direction   = xfer->direction;
2342 
2343     if (xfer->busType != kI3C_TypeI3CDdr)
2344     {
2345         direction = (0UL != xfer->subaddressSize) ? kI3C_Write : xfer->direction;
2346     }
2347 
2348     if (0UL != (xfer->flags & (uint32_t)kI3C_TransferStartWithBroadcastAddr))
2349     {
2350         if (0UL != (xfer->flags & (uint32_t)kI3C_TransferNoStartFlag))
2351         {
2352             return kStatus_InvalidArgument;
2353         }
2354 
2355         if (0UL != (xfer->flags & (uint32_t)kI3C_TransferRepeatedStartFlag))
2356         {
2357             return kStatus_InvalidArgument;
2358         }
2359 
2360         /* Issue 0x7E as start. */
2361         result = I3C_MasterStart(base, xfer->busType, 0x7E, kI3C_Write);
2362         if (result != kStatus_Success)
2363         {
2364             return result;
2365         }
2366 
2367         result = I3C_MasterWaitForCtrlDone(base, false);
2368         if (result != kStatus_Success)
2369         {
2370             return result;
2371         }
2372     }
2373 
2374     /* Handle no start option. */
2375     if (0U != (xfer->flags & (uint32_t)kI3C_TransferNoStartFlag))
2376     {
2377         /* No need to send start flag, directly go to send command or data */
2378         if (xfer->subaddressSize > 0UL)
2379         {
2380             handle->state = (uint8_t)kSendCommandState;
2381         }
2382         else
2383         {
2384             if (direction == kI3C_Write)
2385             {
2386                 /* Next state, send data. */
2387                 handle->state = (uint8_t)kTransferDataState;
2388             }
2389             else
2390             {
2391                 /* Only support write with no stop signal. */
2392                 return kStatus_InvalidArgument;
2393             }
2394         }
2395         I3C_MasterTransferHandleIRQ(base, handle);
2396         return result;
2397     }
2398     /* If repeated start is requested, send repeated start. */
2399     else if (0U != (xfer->flags & (uint32_t)kI3C_TransferRepeatedStartFlag))
2400     {
2401         result = I3C_MasterRepeatedStart(base, xfer->busType, xfer->slaveAddress, direction);
2402     }
2403     else /* For normal transfer, send start. */
2404     {
2405         result = I3C_MasterStart(base, xfer->busType, xfer->slaveAddress, direction);
2406     }
2407 
2408     if (xfer->subaddressSize > 0U)
2409     {
2410         handle->state = (uint8_t)kSendCommandState;
2411     }
2412     else
2413     {
2414         handle->state = (uint8_t)kTransferDataState;
2415     }
2416 
2417     if ((handle->remainingBytes < 256U) && (direction == kI3C_Read))
2418     {
2419         handle->rxTermOps = (handle->rxTermOps == kI3C_RxTermDisable) ? handle->rxTermOps : kI3C_RxAutoTerm;
2420         base->MCTRL |= I3C_MCTRL_RDTERM(handle->remainingBytes);
2421     }
2422 
2423     return result;
2424 }
2425 
2426 /*!
2427  * brief Performs a non-blocking transaction on the I2C/I3C bus.
2428  *
2429  * param base The I3C peripheral base address.
2430  * param handle Pointer to the I3C master driver handle.
2431  * param transfer The pointer to the transfer descriptor.
2432  * retval #kStatus_Success The transaction was started successfully.
2433  * retval #kStatus_I3C_Busy Either another master is currently utilizing the bus, or a non-blocking
2434  *      transaction is already in progress.
2435  */
I3C_MasterTransferNonBlocking(I3C_Type * base,i3c_master_handle_t * handle,i3c_master_transfer_t * transfer)2436 status_t I3C_MasterTransferNonBlocking(I3C_Type *base, i3c_master_handle_t *handle, i3c_master_transfer_t *transfer)
2437 {
2438     assert(NULL != handle);
2439     assert(NULL != transfer);
2440     assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
2441     i3c_master_state_t masterState = I3C_MasterGetState(base);
2442     bool checkDdrState             = false;
2443 
2444     /* Return busy if another transaction is in progress. */
2445     if (handle->state != (uint8_t)kIdleState)
2446     {
2447         return kStatus_I3C_Busy;
2448     }
2449 
2450     /* Return an error if the bus is already in use not by us. */
2451     checkDdrState = (transfer->busType == kI3C_TypeI3CDdr) ? (masterState != kI3C_MasterStateDdr) : true;
2452     if ((masterState != kI3C_MasterStateIdle) && (masterState != kI3C_MasterStateNormAct) && checkDdrState)
2453     {
2454         return kStatus_I3C_Busy;
2455     }
2456 
2457     /* Disable I3C IRQ sources while we configure stuff. */
2458     I3C_MasterDisableInterrupts(base, (uint32_t)kMasterIrqFlags);
2459 
2460     /* Save transfer into handle. */
2461     handle->transfer       = *transfer;
2462     handle->remainingBytes = transfer->dataSize;
2463 
2464     /* Configure IBI response type. */
2465     base->MCTRL &= ~I3C_MCTRL_IBIRESP_MASK;
2466     base->MCTRL |= I3C_MCTRL_IBIRESP(transfer->ibiResponse);
2467 
2468     /* Clear all flags. */
2469     I3C_MasterClearErrorStatusFlags(base, (uint32_t)kMasterErrorFlags);
2470     I3C_MasterClearStatusFlags(base, (uint32_t)kMasterClearFlags);
2471     /* Reset fifos. These flags clear automatically. */
2472     base->MDATACTRL |= I3C_MDATACTRL_FLUSHTB_MASK | I3C_MDATACTRL_FLUSHFB_MASK;
2473 
2474     if ((transfer->flags & (uint32_t)kI3C_TransferDisableRxTermFlag) != 0U)
2475     {
2476         handle->rxTermOps = kI3C_RxTermDisable;
2477     }
2478     else if (transfer->dataSize <= 255U)
2479     {
2480         handle->rxTermOps = kI3C_RxAutoTerm;
2481     }
2482     else
2483     {
2484         handle->rxTermOps = kI3C_RxTermLastByte;
2485     }
2486 
2487     /* Generate commands to send. */
2488     (void)I3C_InitTransferStateMachine(base, handle);
2489 
2490     /* Enable I3C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
2491     I3C_MasterEnableInterrupts(base, (uint32_t)kMasterIrqFlags);
2492 
2493     if (transfer->direction == kI3C_Write)
2494     {
2495         I3C_MasterEnableInterrupts(base, (uint32_t)kI3C_MasterTxReadyFlag);
2496     }
2497 
2498     return kStatus_Success;
2499 }
2500 
2501 /*!
2502  * brief Returns number of bytes transferred so far.
2503  * param base The I3C peripheral base address.
2504  * param handle Pointer to the I3C master driver handle.
2505  * param[out] count Number of bytes transferred so far by the non-blocking transaction.
2506  * retval #kStatus_Success
2507  * retval #kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
2508  */
I3C_MasterTransferGetCount(I3C_Type * base,i3c_master_handle_t * handle,size_t * count)2509 status_t I3C_MasterTransferGetCount(I3C_Type *base, i3c_master_handle_t *handle, size_t *count)
2510 {
2511     assert(NULL != handle);
2512 
2513     if (NULL == count)
2514     {
2515         return kStatus_InvalidArgument;
2516     }
2517 
2518     /* Catch when there is not an active transfer. */
2519     if (handle->state == (uint8_t)kIdleState)
2520     {
2521         *count = 0;
2522         return kStatus_NoTransferInProgress;
2523     }
2524 
2525     uint8_t state;
2526     uint32_t remainingBytes;
2527     uint32_t dataSize;
2528 
2529     /* Cache some fields with IRQs disabled. This ensures all field values */
2530     /* are synchronized with each other during an ongoing transfer. */
2531     uint32_t irqs = I3C_MasterGetEnabledInterrupts(base);
2532     I3C_MasterDisableInterrupts(base, irqs);
2533     state          = handle->state;
2534     remainingBytes = handle->remainingBytes;
2535     dataSize       = handle->transfer.dataSize;
2536     I3C_MasterEnableInterrupts(base, irqs);
2537 
2538     /* Get transfer count based on current transfer state. */
2539     switch (state)
2540     {
2541         case (uint8_t)kIdleState:
2542         case (uint8_t)kSendCommandState:
2543             *count = 0;
2544             break;
2545 
2546         case (uint8_t)kTransferDataState:
2547             *count = dataSize - remainingBytes;
2548             break;
2549 
2550         case (uint8_t)kStopState:
2551         case (uint8_t)kWaitForCompletionState:
2552         default:
2553             *count = dataSize;
2554             break;
2555     }
2556 
2557     return kStatus_Success;
2558 }
2559 
2560 /*!
2561  * brief Terminates a non-blocking I3C master transmission early.
2562  *
2563  * note It is not safe to call this function from an IRQ handler that has a higher priority than the
2564  *      I3C peripheral's IRQ priority.
2565  *
2566  * param base The I3C peripheral base address.
2567  * param handle Pointer to the I3C master driver handle.
2568  * retval #kStatus_Success A transaction was successfully aborted.
2569  * retval #kStatus_I3C_Idle There is not a non-blocking transaction currently in progress.
2570  */
I3C_MasterTransferAbort(I3C_Type * base,i3c_master_handle_t * handle)2571 void I3C_MasterTransferAbort(I3C_Type *base, i3c_master_handle_t *handle)
2572 {
2573     if (handle->state != (uint8_t)kIdleState)
2574     {
2575         /* Disable internal IRQ enables. */
2576         I3C_MasterDisableInterrupts(base, (uint32_t)kMasterIrqFlags);
2577 
2578         /* Reset fifos. These flags clear automatically. */
2579         base->MDATACTRL |= I3C_MDATACTRL_FLUSHTB_MASK | I3C_MDATACTRL_FLUSHFB_MASK;
2580 
2581         /* Send a stop command to finalize the transfer. */
2582         (void)I3C_MasterStop(base);
2583 
2584         /* Reset handle. */
2585         handle->state = (uint8_t)kIdleState;
2586     }
2587 }
2588 
2589 /*!
2590  * brief Reusable routine to handle master interrupts.
2591  * note This function does not need to be called unless you are reimplementing the
2592  *  nonblocking API's interrupt handler routines to add special functionality.
2593  * param base The I3C peripheral base address.
2594  * param handle Pointer to the I3C master driver handle.
2595  */
I3C_MasterTransferHandleIRQ(I3C_Type * base,void * intHandle)2596 void I3C_MasterTransferHandleIRQ(I3C_Type *base, void *intHandle)
2597 {
2598     bool isDone;
2599     status_t result;
2600 
2601     i3c_master_handle_t *handle = (i3c_master_handle_t *)intHandle;
2602     /* Don't do anything if we don't have a valid handle. */
2603     if (NULL == handle)
2604     {
2605         return;
2606     }
2607 
2608     result = I3C_RunTransferStateMachine(base, handle, &isDone);
2609 
2610     if (handle->state == (uint8_t)kIdleState)
2611     {
2612         I3C_MasterDisableInterrupts(base, (uint32_t)kI3C_MasterTxReadyFlag);
2613         return;
2614     }
2615 
2616     if (isDone || (result != kStatus_Success))
2617     {
2618         /* XXX need to handle data that may be in rx fifo below watermark level? */
2619 
2620         /* XXX handle error, terminate xfer */
2621         if ((result == kStatus_I3C_Nak) || (result == kStatus_I3C_IBIWon))
2622         {
2623             (void)I3C_MasterEmitStop(base, false);
2624         }
2625 
2626         /* Disable internal IRQ enables. */
2627         I3C_MasterDisableInterrupts(base, (uint32_t)kI3C_MasterTxReadyFlag);
2628 
2629         /* Set handle to idle state. */
2630         handle->state = (uint8_t)kIdleState;
2631 
2632         /* Invoke IBI user callback. */
2633         if ((result == kStatus_I3C_IBIWon) && (handle->callback.ibiCallback != NULL))
2634         {
2635             handle->callback.ibiCallback(base, handle, handle->ibiType, kI3C_IbiReady);
2636             handle->ibiPayloadSize = 0;
2637         }
2638 
2639         /* Invoke callback. */
2640         if (NULL != handle->callback.transferComplete)
2641         {
2642             handle->callback.transferComplete(base, handle, result, handle->userData);
2643         }
2644     }
2645 }
2646 
2647 /*!
2648  * brief Provides a default configuration for the I3C slave peripheral.
2649  *
2650  * This function provides the following default configuration for the I3C slave peripheral:
2651  * code
2652  *  slaveConfig->enableslave             = true;
2653  * endcode
2654  *
2655  * After calling this function, you can override any settings in order to customize the configuration,
2656  * prior to initializing the slave driver with I3C_SlaveInit().
2657  *
2658  * param[out] slaveConfig User provided configuration structure for default values. Refer to #i3c_slave_config_t.
2659  */
I3C_SlaveGetDefaultConfig(i3c_slave_config_t * slaveConfig)2660 void I3C_SlaveGetDefaultConfig(i3c_slave_config_t *slaveConfig)
2661 {
2662     assert(NULL != slaveConfig);
2663 
2664     (void)memset(slaveConfig, 0, sizeof(*slaveConfig));
2665 
2666     slaveConfig->enableSlave = true;
2667 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SLAVE_IBI_MR_HJ) && FSL_FEATURE_I3C_HAS_NO_SLAVE_IBI_MR_HJ)
2668     slaveConfig->isHotJoin   = false;
2669 #endif
2670     slaveConfig->vendorID    = 0x11BU;
2671 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND)
2672     slaveConfig->enableRandomPart = false;
2673 #endif
2674     slaveConfig->partNumber = 0;
2675     slaveConfig->dcr        = 0; /* Generic device. */
2676     slaveConfig->bcr =
2677         0; /* BCR[7:6]: device role, I3C slave(2b'00), BCR[5]: SDR Only / SDR and HDR Capable,  SDR and HDR
2678               Capable(1b'1), BCR[4]: Bridge Identifier, Not a bridge device(1b'0), BCR[3]: Offline Capable, device is
2679               offline capable(1b'1), BCR[2]: IBI Payload, No data byte following(1b'0), BCR[1]: IBI Request Capable,
2680               capable(1b'1), BCR[0]: Max Data Speed Limitation, has limitation(1b'1). */
2681     slaveConfig->hdrMode             = (uint8_t)kI3C_HDRModeDDR;
2682     slaveConfig->nakAllRequest       = false;
2683     slaveConfig->ignoreS0S1Error     = true;
2684     slaveConfig->offline             = false;
2685     slaveConfig->matchSlaveStartStop = false;
2686     slaveConfig->maxWriteLength      = 256U;
2687     slaveConfig->maxReadLength       = 256U;
2688 }
2689 
2690 /*!
2691  * brief Initializes the I3C slave peripheral.
2692  *
2693  * This function enables the peripheral clock and initializes the I3C slave peripheral as described by the user
2694  * provided configuration.
2695  *
2696  * param base The I3C peripheral base address.
2697  * param slaveConfig User provided peripheral configuration. Use I3C_SlaveGetDefaultConfig() to get a set of
2698  * defaults that you can override.
2699  * param slowClock_Hz Frequency in Hertz of the I3C slow clock. Used to calculate the bus match condition values.
2700  */
I3C_SlaveInit(I3C_Type * base,const i3c_slave_config_t * slaveConfig,uint32_t slowClock_Hz)2701 void I3C_SlaveInit(I3C_Type *base, const i3c_slave_config_t *slaveConfig, uint32_t slowClock_Hz)
2702 {
2703     assert(NULL != slaveConfig);
2704     assert(0UL != slowClock_Hz);
2705 
2706     uint32_t configValue;
2707     uint32_t instance = I3C_GetInstance(base);
2708 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
2709     /* Ungate the clock. */
2710     CLOCK_EnableClock(kI3cClocks[instance]);
2711 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
2712 
2713 #if !(defined(FSL_FEATURE_I3C_HAS_NO_RESET) && FSL_FEATURE_I3C_HAS_NO_RESET)
2714     /* Reset the I3C module */
2715     RESET_PeripheralReset(kI3cResets[instance]);
2716 #endif
2717 
2718 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH)
2719     uint8_t matchCount;
2720     /* Caculate bus available condition match value for current slow clock, count value provides 1us.*/
2721     matchCount = (uint8_t)(slowClock_Hz / 1000000UL);
2722 #endif
2723 
2724     configValue = base->SCONFIG;
2725     configValue &=
2726         ~(I3C_SCONFIG_SADDR_MASK |
2727 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH)
2728           I3C_SCONFIG_BAMATCH_MASK |
2729 #endif
2730           I3C_SCONFIG_OFFLINE_MASK |
2731 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND)
2732           I3C_SCONFIG_IDRAND_MASK |
2733 #endif
2734 #if defined(FSL_FEATURE_I3C_HAS_HDROK) && FSL_FEATURE_I3C_HAS_HDROK
2735           I3C_SCONFIG_HDROK_MASK |
2736 #else
2737           I3C_SCONFIG_DDROK_MASK |
2738 #endif
2739           I3C_SCONFIG_S0IGNORE_MASK | I3C_SCONFIG_MATCHSS_MASK | I3C_SCONFIG_NACK_MASK | I3C_SCONFIG_SLVENA_MASK);
2740     configValue |= I3C_SCONFIG_SADDR(slaveConfig->staticAddr) |
2741 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH)
2742                    I3C_SCONFIG_BAMATCH(matchCount) |
2743 #endif
2744                    I3C_SCONFIG_OFFLINE(slaveConfig->offline) |
2745 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND)
2746                    I3C_SCONFIG_IDRAND(slaveConfig->enableRandomPart) |
2747 #endif
2748 #if defined(FSL_FEATURE_I3C_HAS_HDROK) && FSL_FEATURE_I3C_HAS_HDROK
2749                    I3C_SCONFIG_HDROK((0U != (slaveConfig->hdrMode & (uint8_t)kI3C_HDRModeDDR)) ? 1U : 0U) |
2750 #else
2751                    I3C_SCONFIG_DDROK((0U != (slaveConfig->hdrMode & (uint8_t)kI3C_HDRModeDDR)) ? 1U : 0U) |
2752 #endif
2753                    I3C_SCONFIG_S0IGNORE(slaveConfig->ignoreS0S1Error) |
2754                    I3C_SCONFIG_MATCHSS(slaveConfig->matchSlaveStartStop) |
2755                    I3C_SCONFIG_NACK(slaveConfig->nakAllRequest) | I3C_SCONFIG_SLVENA(slaveConfig->enableSlave);
2756 
2757     base->SVENDORID &= ~I3C_SVENDORID_VID_MASK;
2758     base->SVENDORID |= I3C_SVENDORID_VID(slaveConfig->vendorID);
2759 
2760 #if defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND
2761     base->SIDPARTNO = slaveConfig->partNumber;
2762 #else
2763     if (!slaveConfig->enableRandomPart)
2764     {
2765         base->SIDPARTNO = slaveConfig->partNumber;
2766     }
2767 #endif
2768 
2769     base->SIDEXT &= ~(I3C_SIDEXT_BCR_MASK | I3C_SIDEXT_DCR_MASK);
2770     base->SIDEXT |= I3C_SIDEXT_BCR(slaveConfig->bcr) | I3C_SIDEXT_DCR(slaveConfig->dcr);
2771 
2772     base->SMAXLIMITS &= ~(I3C_SMAXLIMITS_MAXRD_MASK | I3C_SMAXLIMITS_MAXWR_MASK);
2773     base->SMAXLIMITS |=
2774         (I3C_SMAXLIMITS_MAXRD(slaveConfig->maxReadLength) | I3C_SMAXLIMITS_MAXWR(slaveConfig->maxWriteLength));
2775 
2776 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SLAVE_IBI_MR_HJ) && FSL_FEATURE_I3C_HAS_NO_SLAVE_IBI_MR_HJ)
2777     if (slaveConfig->isHotJoin)
2778     {
2779         I3C_SlaveRequestEvent(base, kI3C_SlaveEventHotJoinReq);
2780     }
2781 #endif
2782     base->SCONFIG = configValue;
2783 }
2784 
2785 /*!
2786  * brief Deinitializes the I3C master peripheral.
2787  *
2788  * This function disables the I3C master peripheral and gates the clock. It also performs a software
2789  * reset to restore the peripheral to reset conditions.
2790  *
2791  * param base The I3C peripheral base address.
2792  */
I3C_SlaveDeinit(I3C_Type * base)2793 void I3C_SlaveDeinit(I3C_Type *base)
2794 {
2795     uint32_t idx = I3C_GetInstance(base);
2796 
2797 #if !(defined(FSL_FEATURE_I3C_HAS_NO_RESET) && FSL_FEATURE_I3C_HAS_NO_RESET)
2798     /* Reset the I3C module */
2799     RESET_PeripheralReset(kI3cResets[idx]);
2800 #endif
2801 
2802 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
2803     /* Gate clock. */
2804     CLOCK_DisableClock(kI3cClocks[idx]);
2805 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
2806 
2807     /* Reset handle pointer */
2808     s_i3cSlaveHandle[idx] = NULL;
2809 }
2810 
2811 /*!
2812  * @brief Gets the I3C slave state.
2813  *
2814  * @param base The I3C peripheral base address.
2815  * @return I3C slave activity state, refer #i3c_slave_activity_state_t.
2816  */
I3C_SlaveGetActivityState(I3C_Type * base)2817 i3c_slave_activity_state_t I3C_SlaveGetActivityState(I3C_Type *base)
2818 {
2819     uint8_t activeState = (uint8_t)((base->SSTATUS & I3C_SSTATUS_ACTSTATE_MASK) >> I3C_SSTATUS_ACTSTATE_SHIFT);
2820     i3c_slave_activity_state_t returnCode;
2821     switch (activeState)
2822     {
2823         case (uint8_t)kI3C_SlaveNoLatency:
2824             returnCode = kI3C_SlaveNoLatency;
2825             break;
2826         case (uint8_t)kI3C_SlaveLatency1Ms:
2827             returnCode = kI3C_SlaveLatency1Ms;
2828             break;
2829         case (uint8_t)kI3C_SlaveLatency100Ms:
2830             returnCode = kI3C_SlaveLatency100Ms;
2831             break;
2832         case (uint8_t)kI3C_SlaveLatency10S:
2833             returnCode = kI3C_SlaveLatency10S;
2834             break;
2835         default:
2836             returnCode = kI3C_SlaveNoLatency;
2837             break;
2838     }
2839 
2840     return returnCode;
2841 }
2842 
2843 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SLAVE_IBI_MR_HJ) && FSL_FEATURE_I3C_HAS_NO_SLAVE_IBI_MR_HJ)
2844 /*!
2845  * brief I3C slave request event.
2846  *
2847  * param base The I3C peripheral base address.
2848  * param event I3C slave event of type #i3c_slave_event_t
2849  * param data IBI data if In-band interrupt has data, only applicable for event type #kI3C_SlaveEventIBI
2850  */
I3C_SlaveRequestEvent(I3C_Type * base,i3c_slave_event_t event)2851 void I3C_SlaveRequestEvent(I3C_Type *base, i3c_slave_event_t event)
2852 {
2853     uint32_t ctrlValue = base->SCTRL;
2854 
2855     ctrlValue &= ~I3C_SCTRL_EVENT_MASK;
2856     ctrlValue |= I3C_SCTRL_EVENT(event);
2857 
2858     base->SCTRL = ctrlValue;
2859 }
2860 
2861 /*!
2862  * brief I3C slave request event.
2863  * deprecated Do not use this function. It has been superseded by @ref I3C_SlaveRequestIBIWithData.
2864  *
2865  * param base The I3C peripheral base address.
2866  * param data IBI data
2867  * param dataSize IBI data size.
2868  */
I3C_SlaveRequestIBIWithSingleData(I3C_Type * base,uint8_t data,size_t dataSize)2869 void I3C_SlaveRequestIBIWithSingleData(I3C_Type *base, uint8_t data, size_t dataSize)
2870 {
2871     uint32_t ctrlValue = base->SCTRL;
2872 
2873     ctrlValue &= ~(I3C_SCTRL_EVENT_MASK | I3C_SCTRL_IBIDATA_MASK);
2874     ctrlValue |= I3C_SCTRL_EVENT(1U) | I3C_SCTRL_IBIDATA(data);
2875 
2876     base->SCTRL = ctrlValue;
2877 }
2878 
2879 /*!
2880  * brief I3C slave request IBI event with data payload(mandatory and extended).
2881  *
2882  * param base The I3C peripheral base address.
2883  * param data Pointer to IBI data to be sent in the request.
2884  * param dataSize IBI data size.
2885  */
I3C_SlaveRequestIBIWithData(I3C_Type * base,uint8_t * data,size_t dataSize)2886 void I3C_SlaveRequestIBIWithData(I3C_Type *base, uint8_t *data, size_t dataSize)
2887 {
2888     assert((dataSize > 0U) && (dataSize <= 8U));
2889 
2890     uint32_t ctrlValue;
2891 
2892 #if (defined(I3C_IBIEXT1_MAX_MASK) && I3C_IBIEXT1_MAX_MASK)
2893     if (dataSize > 1U)
2894     {
2895         ctrlValue = I3C_IBIEXT1_EXT1(data[1]);
2896         if (dataSize > 2U)
2897         {
2898             ctrlValue |= I3C_IBIEXT1_EXT2(data[2]);
2899         }
2900         if (dataSize > 3U)
2901         {
2902             ctrlValue |= I3C_IBIEXT1_EXT3(data[3]);
2903         }
2904         ctrlValue |= I3C_IBIEXT1_CNT(dataSize - 1U);
2905         base->IBIEXT1 = ctrlValue;
2906     }
2907 
2908     if (dataSize > 4U)
2909     {
2910         ctrlValue = I3C_IBIEXT2_EXT4(data[4]);
2911         if (dataSize > 5U)
2912         {
2913             ctrlValue |= I3C_IBIEXT2_EXT5(data[5]);
2914         }
2915         if (dataSize > 6U)
2916         {
2917             ctrlValue |= I3C_IBIEXT2_EXT6(data[6]);
2918         }
2919         if (dataSize > 7U)
2920         {
2921             ctrlValue |= I3C_IBIEXT2_EXT7(data[7]);
2922         }
2923         base->IBIEXT2 = ctrlValue;
2924     }
2925 #endif
2926 
2927     ctrlValue = base->SCTRL;
2928 #if (defined(I3C_IBIEXT1_MAX_MASK) && I3C_IBIEXT1_MAX_MASK)
2929     ctrlValue &= ~(I3C_SCTRL_EVENT_MASK | I3C_SCTRL_IBIDATA_MASK | I3C_SCTRL_EXTDATA_MASK);
2930     ctrlValue |= I3C_SCTRL_EVENT(1U) | I3C_SCTRL_IBIDATA(data[0]) | I3C_SCTRL_EXTDATA(dataSize > 1U);
2931 #else
2932     ctrlValue &= ~(I3C_SCTRL_EVENT_MASK | I3C_SCTRL_IBIDATA_MASK);
2933     ctrlValue |= I3C_SCTRL_EVENT(1U) | I3C_SCTRL_IBIDATA(data[0]);
2934 #endif
2935     base->SCTRL = ctrlValue;
2936 }
2937 #endif /* !(defined(FSL_FEATURE_I3C_HAS_NO_SLAVE_IBI_MR_HJ) && FSL_FEATURE_I3C_HAS_NO_SLAVE_IBI_MR_HJ) */
2938 
2939 /*!
2940  * brief Performs a polling send transfer on the I3C bus.
2941  *
2942  * param base  The I3C peripheral base address.
2943  * param txBuff The pointer to the data to be transferred.
2944  * param txSize The length in bytes of the data to be transferred.
2945  * return Error or success status returned by API.
2946  */
I3C_SlaveSend(I3C_Type * base,const void * txBuff,size_t txSize)2947 status_t I3C_SlaveSend(I3C_Type *base, const void *txBuff, size_t txSize)
2948 {
2949     const uint8_t *buf = (const uint8_t *)((const void *)txBuff);
2950     status_t result    = kStatus_Success;
2951 
2952     assert(NULL != txBuff);
2953 
2954     /* Send data buffer */
2955     while (0UL != txSize--)
2956     {
2957         /* Wait until there is room in the fifo. This also checks for errors. */
2958         result = I3C_SlaveWaitForTxReady(base);
2959         if (kStatus_Success != result)
2960         {
2961             return result;
2962         }
2963 
2964         /* Write byte into I3C slave data register. */
2965         if (0UL != txSize)
2966         {
2967             base->SWDATAB = *buf++;
2968         }
2969         else
2970         {
2971             base->SWDATABE = *buf++;
2972         }
2973     }
2974 
2975     return result;
2976 }
2977 
2978 /*!
2979  * brief Performs a polling receive transfer on the I3C bus.
2980  *
2981  * param base  The I3C peripheral base address.
2982  * param rxBuff The pointer to the data to be transferred.
2983  * param rxSize The length in bytes of the data to be transferred.
2984  * return Error or success status returned by API.
2985  */
I3C_SlaveReceive(I3C_Type * base,void * rxBuff,size_t rxSize)2986 status_t I3C_SlaveReceive(I3C_Type *base, void *rxBuff, size_t rxSize)
2987 {
2988     status_t result = kStatus_Success;
2989     uint8_t *buf;
2990 
2991     assert(NULL != rxBuff);
2992 
2993     /* Handle empty read. */
2994     if (0UL == rxSize)
2995     {
2996         return kStatus_Success;
2997     }
2998 
2999 #if I3C_RETRY_TIMES
3000     uint32_t waitTimes = I3C_RETRY_TIMES;
3001 #endif
3002 
3003     /* Receive data */
3004     buf = (uint8_t *)rxBuff;
3005     while (0UL != rxSize)
3006     {
3007 #if I3C_RETRY_TIMES
3008         if (--waitTimes == 0)
3009         {
3010             return kStatus_I3C_Timeout;
3011         }
3012 #endif
3013         /* Check for errors. */
3014         result = I3C_SlaveCheckAndClearError(base, I3C_SlaveGetErrorStatusFlags(base));
3015         if (kStatus_Success != result)
3016         {
3017             return result;
3018         }
3019 
3020         /* Check RX data */
3021         if (0UL != (base->SDATACTRL & I3C_SDATACTRL_RXCOUNT_MASK))
3022         {
3023             *buf++ = (uint8_t)(base->SRDATAB & I3C_SRDATAB_DATA0_MASK);
3024             rxSize--;
3025         }
3026     }
3027 
3028     return result;
3029 }
3030 
3031 /*!
3032  * brief Creates a new handle for the I3C slave non-blocking APIs.
3033  *
3034  * The creation of a handle is for use with the non-blocking APIs. Once a handle
3035  * is created, there is not a corresponding destroy handle. If the user wants to
3036  * terminate a transfer, the I3C_SlaveTransferAbort() API shall be called.
3037  *
3038  * note The function also enables the NVIC IRQ for the input I3C. Need to notice
3039  * that on some SoCs the I3C IRQ is connected to INTMUX, in this case user needs to
3040  * enable the associated INTMUX IRQ in application.
3041 
3042  * param base The I3C peripheral base address.
3043  * param[out] handle Pointer to the I3C slave driver handle.
3044  * param callback User provided pointer to the asynchronous callback function.
3045  * param userData User provided pointer to the application callback data.
3046  */
I3C_SlaveTransferCreateHandle(I3C_Type * base,i3c_slave_handle_t * handle,i3c_slave_transfer_callback_t callback,void * userData)3047 void I3C_SlaveTransferCreateHandle(I3C_Type *base,
3048                                    i3c_slave_handle_t *handle,
3049                                    i3c_slave_transfer_callback_t callback,
3050                                    void *userData)
3051 {
3052     uint32_t instance;
3053 
3054     assert(NULL != handle);
3055 
3056     /* Clear out the handle. */
3057     (void)memset(handle, 0, sizeof(*handle));
3058 
3059     /* Look up instance number */
3060     instance = I3C_GetInstance(base);
3061 
3062     /* Save base and instance. */
3063     handle->callback = callback;
3064     handle->userData = userData;
3065 
3066     /* Save Tx FIFO Size. */
3067     handle->txFifoSize =
3068         2U << ((base->SCAPABILITIES & I3C_SCAPABILITIES_FIFOTX_MASK) >> I3C_SCAPABILITIES_FIFOTX_SHIFT);
3069 
3070     /* Save this handle for IRQ use. */
3071     s_i3cSlaveHandle[instance] = handle;
3072 
3073     /* Set irq handler. */
3074     s_i3cSlaveIsr = I3C_SlaveTransferHandleIRQ;
3075 
3076     /* Clear internal IRQ enables and enable NVIC IRQ. */
3077     I3C_SlaveDisableInterrupts(base, (uint32_t)kSlaveIrqFlags);
3078     (void)EnableIRQ(kI3cIrqs[instance]);
3079 }
3080 
3081 /*!
3082  * brief Starts accepting slave transfers.
3083  *
3084  * Call this API after calling I2C_SlaveInit() and I3C_SlaveTransferCreateHandle() to start processing
3085  * transactions driven by an I2C master. The slave monitors the I2C bus and pass events to the
3086  * callback that was passed into the call to I3C_SlaveTransferCreateHandle(). The callback is always invoked
3087  * from the interrupt context.
3088  *
3089  * The set of events received by the callback is customizable. To do so, set the a eventMask parameter to
3090  * the OR'd combination of #i3c_slave_transfer_event_t enumerators for the events you wish to receive.
3091  * The #kI3C_SlaveTransmitEvent and #kI3C_SlaveReceiveEvent events are always enabled and do not need
3092  * to be included in the mask. Alternatively, you can pass 0 to get a default set of only the transmit and
3093  * receive events that are always enabled. In addition, the #kI3C_SlaveAllEvents constant is provided as
3094  * a convenient way to enable all events.
3095  *
3096  * param base The I3C peripheral base address.
3097  * param handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
3098  * param eventMask Bit mask formed by OR'ing together #i3c_slave_transfer_event_t enumerators to specify
3099  *      which events to send to the callback. Other accepted values are 0 to get a default set of
3100  *      only the transmit and receive events, and #kI3C_SlaveAllEvents to enable all events.
3101  *
3102  * retval #kStatus_Success Slave transfers were successfully started.
3103  * retval #kStatus_I3C_Busy Slave transfers have already been started on this handle.
3104  */
I3C_SlaveTransferNonBlocking(I3C_Type * base,i3c_slave_handle_t * handle,uint32_t eventMask)3105 status_t I3C_SlaveTransferNonBlocking(I3C_Type *base, i3c_slave_handle_t *handle, uint32_t eventMask)
3106 {
3107     assert(NULL != handle);
3108 
3109     /* Return busy if another transaction is in progress. */
3110     if (handle->isBusy)
3111     {
3112         return kStatus_I3C_Busy;
3113     }
3114 
3115     /* Disable I3C IRQ sources while we configure stuff. */
3116     I3C_SlaveDisableInterrupts(base, (uint32_t)kSlaveIrqFlags);
3117 
3118     /* Clear transfer in handle. */
3119     (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
3120 
3121     /* Set up event mask. tx and rx are always enabled. */
3122     handle->eventMask = eventMask | (uint32_t)kI3C_SlaveTransmitEvent | (uint32_t)kI3C_SlaveReceiveEvent;
3123 
3124     /* Clear all flags. */
3125     I3C_SlaveClearStatusFlags(base, (uint32_t)kSlaveClearFlags);
3126 
3127     /* Enable I3C internal IRQ sources. NVIC IRQ was enabled in CreateHandle() */
3128     I3C_SlaveEnableInterrupts(base, (uint32_t)kSlaveIrqFlags);
3129 
3130     return kStatus_Success;
3131 }
3132 
3133 /*!
3134  * brief Gets the slave transfer status during a non-blocking transfer.
3135  * param base The I3C peripheral base address.
3136  * param handle Pointer to i2c_slave_handle_t structure.
3137  * param[out] count Pointer to a value to hold the number of bytes transferred. May be NULL if the count is not
3138  *      required.
3139  * retval #kStatus_Success
3140  * retval #kStatus_NoTransferInProgress
3141  */
I3C_SlaveTransferGetCount(I3C_Type * base,i3c_slave_handle_t * handle,size_t * count)3142 status_t I3C_SlaveTransferGetCount(I3C_Type *base, i3c_slave_handle_t *handle, size_t *count)
3143 {
3144     assert(NULL != handle);
3145 
3146     if (NULL == count)
3147     {
3148         return kStatus_InvalidArgument;
3149     }
3150 
3151     /* Catch when there is not an active transfer. */
3152     if (!handle->isBusy)
3153     {
3154         *count = 0;
3155         return kStatus_NoTransferInProgress;
3156     }
3157 
3158     /* For an active transfer, just return the count from the handle. */
3159     *count = handle->transferredCount;
3160 
3161     return kStatus_Success;
3162 }
3163 
3164 /*!
3165  * brief Aborts the slave non-blocking transfers.
3166  * note This API could be called at any time to stop slave for handling the bus events.
3167  * param base The I3C peripheral base address.
3168  * param handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
3169  * retval #kStatus_Success
3170  * retval #kStatus_I3C_Idle
3171  */
I3C_SlaveTransferAbort(I3C_Type * base,i3c_slave_handle_t * handle)3172 void I3C_SlaveTransferAbort(I3C_Type *base, i3c_slave_handle_t *handle)
3173 {
3174     assert(NULL != handle);
3175 
3176     /* Return idle if no transaction is in progress. */
3177     if (handle->isBusy)
3178     {
3179         /* Disable I3C IRQ sources. */
3180         I3C_SlaveDisableInterrupts(base, (uint32_t)kSlaveIrqFlags);
3181 
3182         /* Reset transfer info. */
3183         (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
3184 
3185         /* We're no longer busy. */
3186         handle->isBusy = false;
3187     }
3188 }
3189 
I3C_SlaveTransferHandleGetStatusFlags(I3C_Type * base,i3c_slave_handle_t * handle,i3c_slave_handleIrq_param_t * stateParams)3190 static bool I3C_SlaveTransferHandleGetStatusFlags(I3C_Type *base,
3191                                                   i3c_slave_handle_t *handle,
3192                                                   i3c_slave_handleIrq_param_t *stateParams)
3193 {
3194     assert(NULL != base && NULL != handle && NULL != stateParams);
3195     /* Check for a valid handle in case of a spurious interrupt. */
3196     uint32_t errFlags;
3197     stateParams->flags = I3C_SlaveGetStatusFlags(base);
3198     errFlags           = I3C_SlaveGetErrorStatusFlags(base);
3199 
3200     stateParams->pendingInts = I3C_SlaveGetPendingInterrupts(base);
3201     stateParams->enabledInts = I3C_SlaveGetEnabledInterrupts(base);
3202 
3203     if (0UL != (errFlags & (uint32_t)kSlaveErrorFlags))
3204     {
3205         handle->transfer.event            = (uint32_t)kI3C_SlaveCompletionEvent;
3206         handle->transfer.completionStatus = I3C_SlaveCheckAndClearError(base, errFlags);
3207 
3208         if ((0UL != (handle->eventMask & (uint32_t)kI3C_SlaveCompletionEvent)) && (NULL != handle->callback))
3209         {
3210             handle->callback(base, &handle->transfer, handle->userData);
3211         }
3212         return false;
3213     }
3214     return true;
3215 }
3216 
I3C_SlaveTransferHandleBusStart(I3C_Type * base,i3c_slave_transfer_t * xfer,uint32_t * pendingInts)3217 static void I3C_SlaveTransferHandleBusStart(I3C_Type *base, i3c_slave_transfer_t *xfer, uint32_t *pendingInts)
3218 {
3219     base->SDATACTRL |= I3C_SDATACTRL_FLUSHTB_MASK;
3220     xfer->txDataSize = 0;
3221     I3C_SlaveEnableInterrupts(base, (uint32_t)kI3C_SlaveTxReadyFlag);
3222     (*pendingInts) |= (uint32_t)kI3C_SlaveTxReadyFlag;
3223 }
3224 
I3C_SlaveTransferHandleEventSent(I3C_Type * base,i3c_slave_handle_t * handle,i3c_slave_transfer_t * xfer)3225 static void I3C_SlaveTransferHandleEventSent(I3C_Type *base, i3c_slave_handle_t *handle, i3c_slave_transfer_t *xfer)
3226 {
3227     xfer->event = (uint32_t)kI3C_SlaveRequestSentEvent;
3228     if ((0UL != (handle->eventMask & xfer->event)) && (NULL != handle->callback))
3229     {
3230         handle->callback(base, xfer, handle->userData);
3231     }
3232 }
3233 
I3C_SlaveTransferHandleReceivedCCC(I3C_Type * base,i3c_slave_handle_t * handle,i3c_slave_transfer_t * xfer)3234 static void I3C_SlaveTransferHandleReceivedCCC(I3C_Type *base, i3c_slave_handle_t *handle, i3c_slave_transfer_t *xfer)
3235 {
3236     handle->isBusy = true;
3237     xfer->event    = (uint32_t)kI3C_SlaveReceivedCCCEvent;
3238     if ((0UL != (handle->eventMask & xfer->event)) && (NULL != handle->callback))
3239     {
3240         handle->callback(base, xfer, handle->userData);
3241     }
3242 }
3243 
I3C_SlaveTransferHandleBusStop(I3C_Type * base,i3c_slave_handle_t * handle,i3c_slave_handleIrq_param_t * stateParams)3244 static void I3C_SlaveTransferHandleBusStop(I3C_Type *base,
3245                                            i3c_slave_handle_t *handle,
3246                                            i3c_slave_handleIrq_param_t *stateParams)
3247 {
3248     assert(NULL != base && NULL != handle && NULL != stateParams);
3249     I3C_SlaveDisableInterrupts(base, (uint32_t)kI3C_SlaveTxReadyFlag);
3250     stateParams->pendingInts &= ~(uint32_t)kI3C_SlaveTxReadyFlag;
3251     base->SDATACTRL |= I3C_SDATACTRL_FLUSHTB_MASK | I3C_SDATACTRL_FLUSHFB_MASK;
3252     if (handle->isBusy)
3253     {
3254         handle->transfer.event            = (uint32_t)kI3C_SlaveCompletionEvent;
3255         handle->transfer.completionStatus = kStatus_Success;
3256         handle->transfer.transferredCount = handle->transferredCount;
3257         handle->isBusy                    = false;
3258 
3259         if (handle->wasTransmit)
3260         {
3261             /* Subtract one from the transmit count to offset the fact that I3C asserts the */
3262             /* tx flag before it sees the nack from the master-receiver, thus causing one more */
3263             /* count that the master actually receives. */
3264             --handle->transfer.transferredCount;
3265             handle->wasTransmit = false;
3266         }
3267 
3268         if ((0UL != (handle->eventMask & handle->transfer.event)) && (NULL != handle->callback))
3269         {
3270             handle->callback(base, &handle->transfer, handle->userData);
3271         }
3272 
3273         /* Clean up transfer info on completion, after the callback has been invoked. */
3274         (void)memset(&handle->transfer, 0, sizeof(handle->transfer));
3275     }
3276 }
3277 
I3C_SlaveTransferHandleMatched(I3C_Type * base,i3c_slave_handle_t * handle,i3c_slave_transfer_t * xfer)3278 static void I3C_SlaveTransferHandleMatched(I3C_Type *base, i3c_slave_handle_t *handle, i3c_slave_transfer_t *xfer)
3279 {
3280     assert(NULL != base && NULL != handle && NULL != xfer);
3281     xfer->event    = (uint32_t)kI3C_SlaveAddressMatchEvent;
3282     handle->isBusy = true;
3283     if ((0UL != (handle->eventMask & (uint32_t)kI3C_SlaveAddressMatchEvent)) && (NULL != handle->callback))
3284     {
3285         handle->callback(base, xfer, handle->userData);
3286     }
3287 }
3288 
I3C_SlaveTransferHandleTxReady(I3C_Type * base,i3c_slave_handle_t * handle,i3c_slave_handleIrq_param_t * stateParams)3289 static void I3C_SlaveTransferHandleTxReady(I3C_Type *base,
3290                                            i3c_slave_handle_t *handle,
3291                                            i3c_slave_handleIrq_param_t *stateParams)
3292 {
3293     assert(NULL != base && NULL != handle && NULL != stateParams);
3294     handle->wasTransmit = true;
3295 
3296     /* If we're out of data, invoke callback to get more. */
3297     if ((NULL == handle->transfer.txData) || (0UL == handle->transfer.txDataSize))
3298     {
3299         handle->transfer.event = (uint32_t)kI3C_SlaveTransmitEvent;
3300         if (0UL != (stateParams->flags & (uint32_t)kI3C_SlaveBusHDRModeFlag))
3301         {
3302             handle->transfer.event |= (uint32_t)kI3C_SlaveHDRCommandMatchEvent;
3303             handle->isBusy = true;
3304         }
3305         if (NULL != handle->callback)
3306         {
3307             handle->callback(base, &handle->transfer, handle->userData);
3308         }
3309 
3310         /* Clear the transferred count now that we have a new buffer. */
3311         handle->transferredCount = 0;
3312     }
3313 
3314     if ((NULL == handle->transfer.txData) || (0UL == handle->transfer.txDataSize))
3315     {
3316         I3C_SlaveDisableInterrupts(base, (uint32_t)kI3C_SlaveTxReadyFlag);
3317         (stateParams->pendingInts) &= ~(uint32_t)kI3C_SlaveTxReadyFlag;
3318     }
3319 
3320     /* Transmit a byte. */
3321     while ((handle->transfer.txDataSize != 0UL) && ((stateParams->txCount) != 0U))
3322     {
3323         if (handle->transfer.txDataSize > 1UL)
3324         {
3325             base->SWDATAB = *handle->transfer.txData++;
3326         }
3327         else
3328         {
3329             base->SWDATABE = *handle->transfer.txData++;
3330             I3C_SlaveDisableInterrupts(base, (uint32_t)kI3C_SlaveTxReadyFlag);
3331         }
3332         --(handle->transfer.txDataSize);
3333         ++(handle->transferredCount);
3334         (stateParams->txCount)--;
3335     }
3336 }
3337 
I3C_SlaveTransferHandleRxReady(I3C_Type * base,i3c_slave_handle_t * handle,i3c_slave_handleIrq_param_t * stateParams)3338 static void I3C_SlaveTransferHandleRxReady(I3C_Type *base,
3339                                            i3c_slave_handle_t *handle,
3340                                            i3c_slave_handleIrq_param_t *stateParams)
3341 {
3342     assert(NULL != base && NULL != handle && NULL != stateParams);
3343     /* If we're out of room in the buffer, invoke callback to get another. */
3344     if ((NULL == handle->transfer.rxData) || (0UL == handle->transfer.rxDataSize))
3345     {
3346         handle->transfer.event = (uint32_t)kI3C_SlaveReceiveEvent;
3347         if (0UL != (stateParams->flags & (uint32_t)kI3C_SlaveBusHDRModeFlag))
3348         {
3349             handle->transfer.event |= (uint32_t)kI3C_SlaveHDRCommandMatchEvent;
3350             handle->isBusy = true;
3351         }
3352         if (NULL != handle->callback)
3353         {
3354             handle->callback(base, &handle->transfer, handle->userData);
3355         }
3356         handle->transferredCount = 0;
3357     }
3358     /* Receive a byte. */
3359     while ((stateParams->rxCount != 0U) && ((handle->transfer.rxData != NULL) && (handle->transfer.rxDataSize != 0UL)))
3360     {
3361         *(handle->transfer.rxData++) = (uint8_t)base->SRDATAB;
3362         --(handle->transfer.rxDataSize);
3363         ++(handle->transferredCount);
3364         (stateParams->rxCount)--;
3365     }
3366 }
3367 
3368 /*!
3369  * brief Reusable routine to handle slave interrupts.
3370  * note This function does not need to be called unless you are reimplementing the
3371  *  non blocking API's interrupt handler routines to add special functionality.
3372  * param base The I3C peripheral base address.
3373  * param handle Pointer to #i3c_slave_handle_t structure which stores the transfer state.
3374  */
I3C_SlaveTransferHandleIRQ(I3C_Type * base,void * intHandle)3375 void I3C_SlaveTransferHandleIRQ(I3C_Type *base, void *intHandle)
3376 {
3377     i3c_slave_handleIrq_param_t stateParams;
3378 
3379     (void)memset(&stateParams, 0, sizeof(stateParams));
3380     i3c_slave_handle_t *handle = (i3c_slave_handle_t *)intHandle;
3381 
3382     /* Check for a valid handle in case of a spurious interrupt. */
3383     if (NULL == handle)
3384     {
3385         return;
3386     }
3387 
3388     /* Get status flags. */
3389     if (false == I3C_SlaveTransferHandleGetStatusFlags(base, handle, &stateParams))
3390     {
3391         return;
3392     }
3393 
3394     /* Clear status flags. */
3395     I3C_SlaveClearStatusFlags(base, stateParams.flags);
3396 
3397     if (0UL != (stateParams.flags & (uint32_t)kI3C_SlaveBusStartFlag))
3398     {
3399         I3C_SlaveTransferHandleBusStart(base, &handle->transfer, &stateParams.pendingInts);
3400     }
3401 
3402     if (0UL != (stateParams.flags & (uint32_t)kI3C_SlaveEventSentFlag))
3403     {
3404         I3C_SlaveTransferHandleEventSent(base, handle, &handle->transfer);
3405     }
3406 
3407     if (0UL != (stateParams.flags & (uint32_t)kI3C_SlaveReceivedCCCFlag))
3408     {
3409         I3C_SlaveTransferHandleReceivedCCC(base, handle, &handle->transfer);
3410     }
3411 
3412     if (0UL != (stateParams.flags & (uint32_t)kI3C_SlaveMatchedFlag))
3413     {
3414         I3C_SlaveTransferHandleMatched(base, handle, &handle->transfer);
3415     }
3416 
3417     /* Get fifo counts and compute room in tx fifo. */
3418     I3C_SlaveGetFifoCounts(base, &stateParams.rxCount, &stateParams.txCount);
3419     stateParams.txCount = handle->txFifoSize - stateParams.txCount;
3420 
3421     /* Handle transmit and receive. */
3422     if ((0UL != (stateParams.flags & (uint32_t)kI3C_SlaveTxReadyFlag)) &&
3423         (0UL != (stateParams.pendingInts & (uint32_t)kI3C_SlaveTxReadyFlag)))
3424     {
3425         I3C_SlaveTransferHandleTxReady(base, handle, &stateParams);
3426     }
3427 
3428     if ((0UL != (stateParams.flags & (uint32_t)kI3C_SlaveRxReadyFlag)) &&
3429         (0UL != (stateParams.enabledInts & (uint32_t)kI3C_SlaveRxReadyFlag)))
3430     {
3431         I3C_SlaveTransferHandleRxReady(base, handle, &stateParams);
3432     }
3433 
3434     /* Handle stop event. */
3435     if (0UL != (stateParams.flags & (uint32_t)kI3C_SlaveBusStopFlag))
3436     {
3437         I3C_SlaveTransferHandleBusStop(base, handle, &stateParams);
3438     }
3439 }
3440 
I3C_CommonIRQHandler(I3C_Type * base,uint32_t instance)3441 static void I3C_CommonIRQHandler(I3C_Type *base, uint32_t instance)
3442 {
3443     /* Check for master IRQ. */
3444     if (((uint32_t)kI3C_MasterOn == (base->MCONFIG & I3C_MCONFIG_MSTENA_MASK)) && (NULL != s_i3cMasterIsr))
3445     {
3446         /* Master mode. */
3447         s_i3cMasterIsr(base, s_i3cMasterHandle[instance]);
3448     }
3449 
3450     /* Check for slave IRQ. */
3451     if ((I3C_SCONFIG_SLVENA_MASK == (base->SCONFIG & I3C_SCONFIG_SLVENA_MASK)) && (NULL != s_i3cSlaveIsr))
3452     {
3453         /* Slave mode. */
3454         s_i3cSlaveIsr(base, s_i3cSlaveHandle[instance]);
3455     }
3456     SDK_ISR_EXIT_BARRIER;
3457 }
3458 
3459 #if defined(I3C)
3460 /* Implementation of I3C handler named in startup code. */
3461 void I3C0_DriverIRQHandler(void);
I3C0_DriverIRQHandler(void)3462 void I3C0_DriverIRQHandler(void)
3463 {
3464     I3C_CommonIRQHandler(I3C, 0);
3465 }
3466 #endif
3467 
3468 #if defined(I3C0)
3469 /* Implementation of I3C0 handler named in startup code. */
3470 void I3C0_DriverIRQHandler(void);
I3C0_DriverIRQHandler(void)3471 void I3C0_DriverIRQHandler(void)
3472 {
3473     I3C_CommonIRQHandler(I3C0, 0);
3474 }
3475 #endif
3476 
3477 #if defined(I3C1)
3478 /* Implementation of I3C1 handler named in startup code. */
3479 void I3C1_DriverIRQHandler(void);
I3C1_DriverIRQHandler(void)3480 void I3C1_DriverIRQHandler(void)
3481 {
3482     I3C_CommonIRQHandler(I3C1, 1);
3483 }
3484 #endif
3485 
3486 #if defined(I3C2)
3487 /* Implementation of I3C2 handler named in startup code. */
3488 void I3C2_DriverIRQHandler(void);
I3C2_DriverIRQHandler(void)3489 void I3C2_DriverIRQHandler(void)
3490 {
3491     I3C_CommonIRQHandler(I3C2, 2);
3492 }
3493 #endif
3494