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