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