1 /*
2  * Copyright 2020, 2022-2024 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "fsl_component_i3c_adapter.h"
8 #include "fsl_i3c.h"
9 
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 #define I3C_TIME_OUT_INDEX 100000000U
14 
15 /* I3C master adapter internal resource*/
16 typedef struct _i3c_master_adapter_private
17 {
18     uint8_t devCount;
19     i3c_ccc_dev_t *devList;
20 } i3c_master_adapter_private_t;
21 
22 /*******************************************************************************
23  * Prototypes
24  ******************************************************************************/
25 static status_t I3C_MasterAdapterInit(i3c_device_t *master);
26 static status_t I3C_MasterAdapterProcessDAA(i3c_device_t *master);
27 static status_t I3C_MasterAdapterTransmitCCC(i3c_device_t *master, i3c_ccc_cmd_t *cmd);
28 static status_t I3C_MasterAdapterDoI3CTransfer(i3c_device_t *device, i3c_bus_transfer_t *xfer);
29 static status_t I3C_MasterAdapterDoI2CTransfer(i2c_device_t *device, i3c_bus_transfer_t *xfer);
30 static void I3C_SlaveAdapterRequestMastership(i3c_device_t *dev);
31 static void I3C_SlaveAdapterRequestHotJoin(i3c_device_t *dev);
32 static status_t I3C_SlaveAdapterInit(i3c_device_t *dev);
33 static status_t I3C_MasterAdapterHandOffMasterShip(i3c_device_t *master, uint8_t slaveAddr);
34 static void I3C_MasterAdapterTakeOverMasterShip(i3c_device_t *master);
35 static void I3C_SlaveAdapterRequestIBI(i3c_device_t *dev, void *data, size_t dataSize);
36 static void I3C_MasterAdapterRegisterIBI(i3c_device_t *master, uint8_t ibiAddress);
37 static void i3c_master_ibi_callback(I3C_Type *base,
38                                     i3c_master_handle_t *handle,
39                                     i3c_ibi_type_t ibiType,
40                                     i3c_ibi_state_t ibiState);
41 static void i3c_master_callback(I3C_Type *base, i3c_master_handle_t *handle, status_t status, void *userData);
42 static void i3c_slave2master_callback(I3C_Type *base, void *userData);
43 /*******************************************************************************
44  * Variables
45  ******************************************************************************/
46 
47 static volatile bool g_masterCompletionFlag = false;
48 static volatile bool g_ibiWonFlag           = false;
49 static volatile status_t g_completionStatus = kStatus_Success;
50 static volatile bool g_transferPolling      = false;
51 
52 const i3c_device_hw_ops_t master_ops = {.Init              = I3C_MasterAdapterInit,
53                                         .Deinit            = NULL,
54                                         .ProceedDAA        = I3C_MasterAdapterProcessDAA,
55                                         .CheckSupportCCC   = NULL,
56                                         .TransmitCCC       = I3C_MasterAdapterTransmitCCC,
57                                         .DoI3CTransfer     = I3C_MasterAdapterDoI3CTransfer,
58                                         .DoI2CTransfer     = I3C_MasterAdapterDoI2CTransfer,
59                                         .HotJoin           = I3C_SlaveAdapterRequestHotJoin,
60                                         .RequestMastership = I3C_SlaveAdapterRequestMastership,
61                                         .RegisterIBI       = I3C_MasterAdapterRegisterIBI,
62                                         .RequestIBI        = I3C_SlaveAdapterRequestIBI};
63 
64 const i3c_device_hw_ops_t slave_ops                        = {.Init              = I3C_SlaveAdapterInit,
65                                                               .Deinit            = NULL,
66                                                               .ProceedDAA        = NULL,
67                                                               .CheckSupportCCC   = NULL,
68                                                               .TransmitCCC       = NULL,
69                                                               .DoI3CTransfer     = NULL,
70                                                               .DoI2CTransfer     = NULL,
71                                                               .RegisterIBI       = NULL,
72                                                               .HotJoin           = I3C_SlaveAdapterRequestHotJoin,
73                                                               .RequestMastership = I3C_SlaveAdapterRequestMastership,
74                                                               .RequestIBI        = I3C_SlaveAdapterRequestIBI};
75 static const i3c_master_transfer_callback_t masterCallback = {.slave2Master     = i3c_slave2master_callback,
76                                                               .ibiCallback      = i3c_master_ibi_callback,
77                                                               .transferComplete = i3c_master_callback};
78 
79 /*******************************************************************************
80  * Code
81  ******************************************************************************/
82 #define I3C_SLAVELIST_MAX_LEN    50U
83 #define I3C_MASTER_IBI_BUFF_SIZE 50U
84 
i3c_secondarymaster_callback(I3C_Type * base,i3c_slave_transfer_t * xfer,void * userData)85 static void i3c_secondarymaster_callback(I3C_Type *base, i3c_slave_transfer_t *xfer, void *userData)
86 {
87     i3c_device_t *dev                           = (i3c_device_t *)userData;
88     i3c_device_control_info_t *devControlInfo   = dev->devControlInfo;
89     i3c_master_adapter_private_t *masterPrivate = (i3c_master_adapter_private_t *)devControlInfo->privateData;
90     switch ((uint32_t)xfer->event)
91     {
92         case (uint32_t)kI3C_SlaveReceivedCCCEvent:
93             if (0UL != (base->SDATACTRL & I3C_SDATACTRL_RXCOUNT_MASK))
94             {
95                 uint8_t cmdID = (uint8_t)(base->SRDATAB & I3C_SRDATAB_DATA0_MASK);
96                 /* DEFSLVLIST command */
97                 if (cmdID == 0x08U)
98                 {
99                     xfer->rxData     = (uint8_t *)masterPrivate->devList;
100                     xfer->rxDataSize = I3C_SLAVELIST_MAX_LEN;
101                 }
102             }
103             break;
104 
105         case (uint32_t)kI3C_SlaveCompletionEvent:
106             if (xfer->rxData != NULL)
107             {
108                 uint8_t *pDevList       = (uint8_t *)masterPrivate->devList;
109                 masterPrivate->devCount = pDevList[0];
110                 masterPrivate->devList  = (i3c_ccc_dev_t *)(void *)&pDevList[1];
111             }
112             break;
113 
114         case (uint32_t)kI3C_SlaveTransmitEvent:
115         case (uint32_t)kI3C_SlaveReceiveEvent:
116         case (uint32_t)kI3C_SlaveRequestSentEvent:
117             break;
118 
119         default:
120             assert(false);
121             break;
122     }
123 }
124 
i3c_master_ibi_callback(I3C_Type * base,i3c_master_handle_t * handle,i3c_ibi_type_t ibiType,i3c_ibi_state_t ibiState)125 static void i3c_master_ibi_callback(I3C_Type *base,
126                                     i3c_master_handle_t *handle,
127                                     i3c_ibi_type_t ibiType,
128                                     i3c_ibi_state_t ibiState)
129 {
130     g_transferPolling    = true;
131     i3c_device_t *master = (i3c_device_t *)handle->userData;
132     switch (ibiType)
133     {
134         case kI3C_IbiNormal:
135             if (ibiState == kI3C_IbiDataBuffNeed)
136             {
137                 handle->ibiBuff = malloc(I3C_MASTER_IBI_BUFF_SIZE);
138             }
139             else
140             {
141                 /* Handle ibi data*/
142                 void *ibiData = malloc(handle->ibiPayloadSize);
143                 (void)memcpy(ibiData, (void *)handle->ibiBuff, handle->ibiPayloadSize);
144                 (void)I3C_BusMasterHandleIBI(master, handle->ibiAddress, ibiData, handle->ibiPayloadSize);
145                 free(ibiData);
146             }
147             break;
148 
149         case kI3C_IbiMasterRequest:
150             if (ibiState == kI3C_IbiAckNackPending)
151             {
152                 I3C_MasterEmitIBIResponse(base, kI3C_IbiRespAck);
153             }
154             else
155             {
156                 (void)I3C_MasterAdapterHandOffMasterShip(master, handle->ibiAddress);
157             }
158             break;
159 
160         case kI3C_IbiHotJoin:
161             (void)I3C_BusMasterDoDAA(master);
162             break;
163 
164         default:
165             assert(false);
166             break;
167     }
168     g_transferPolling = false;
169 }
170 
i3c_slave2master_callback(I3C_Type * base,void * userData)171 static void i3c_slave2master_callback(I3C_Type *base, void *userData)
172 {
173     i3c_device_t *master = (i3c_device_t *)userData;
174     I3C_MasterAdapterTakeOverMasterShip(master);
175 }
176 
i3c_master_callback(I3C_Type * base,i3c_master_handle_t * handle,status_t status,void * userData)177 static void i3c_master_callback(I3C_Type *base, i3c_master_handle_t *handle, status_t status, void *userData)
178 {
179     /* Signal transfer success when received success status. */
180     if (status == kStatus_Success)
181     {
182         g_masterCompletionFlag = true;
183     }
184 
185     if (status == kStatus_I3C_IBIWon)
186     {
187         g_ibiWonFlag = true;
188     }
189 
190     g_completionStatus = status;
191 }
192 
I3C_MasterAdapterInit(i3c_device_t * master)193 static status_t I3C_MasterAdapterInit(i3c_device_t *master)
194 {
195     assert(master != NULL);
196     i3c_device_control_info_t *masterControlInfo  = master->devControlInfo;
197     i3c_bus_t *bus                                = master->bus;
198     i3c_master_adapter_resource_t *masterResource = (i3c_master_adapter_resource_t *)masterControlInfo->resource;
199 
200     I3C_Type *base                       = masterResource->base;
201     i3c_master_transfer_mode_t transMode = masterResource->transMode;
202     i3c_master_adapter_private_t *masterPrivate;
203 
204     i3c_config_t masterConfig;
205     I3C_GetDefaultConfig(&masterConfig);
206     masterConfig.baudRate_Hz.i2cBaud          = bus->i2cBaudRate;
207     masterConfig.baudRate_Hz.i3cPushPullBaud  = bus->i3cPushPullBaudRate;
208     masterConfig.baudRate_Hz.i3cOpenDrainBaud = bus->i3cOpenDrainBaudRate;
209     masterConfig.enableOpenDrainStop          = false;
210     masterConfig.masterDynamicAddress         = master->info.dynamicAddr;
211     masterConfig.maxWriteLength               = master->info.maxWriteLength;
212     masterConfig.maxReadLength                = master->info.maxReadLength;
213     masterConfig.staticAddr                   = master->info.staticAddr;
214     masterConfig.vendorID                     = master->info.vendorID;
215     masterConfig.partNumber                   = master->info.partNumber;
216     masterConfig.dcr                          = master->info.dcr;
217     masterConfig.bcr                          = master->info.bcr;
218     masterConfig.hdrMode                      = master->info.hdrMode;
219 #if !(defined(FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH) && FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH)
220     masterConfig.slowClock_Hz                 = masterResource->slowClockInHz;
221 #endif
222 
223     masterPrivate                  = malloc(sizeof(i3c_master_adapter_private_t));
224     masterControlInfo->privateData = masterPrivate;
225 
226     /* Master is capable of working as master but work as slave for now */
227     if (masterControlInfo->isSecondary)
228     {
229         masterConfig.enableMaster = kI3C_MasterCapable;
230         masterConfig.enableSlave  = true;
231         masterPrivate->devList    = malloc(I3C_SLAVELIST_MAX_LEN);
232         masterPrivate->devCount   = 0U;
233         (void)memset((void *)masterPrivate->devList, 0, I3C_SLAVELIST_MAX_LEN);
234     }
235     else
236     {
237         masterConfig.enableMaster = kI3C_MasterOn;
238         masterConfig.enableSlave  = false;
239     }
240 
241     I3C_Init(base, &masterConfig, masterResource->clockInHz);
242 
243     if (transMode == kI3C_MasterTransferInterruptMode)
244     {
245         i3c_master_handle_t *g_i3c_m_handle = malloc(sizeof(i3c_master_handle_t));
246         I3C_MasterTransferCreateHandle(base, g_i3c_m_handle, &masterCallback, master);
247     }
248 
249     status_t result = kStatus_Success;
250 
251     if (masterControlInfo->isSecondary)
252     {
253         /* Create slave handle. */
254         i3c_slave_handle_t *g_i3c_s_handle = malloc(sizeof(*g_i3c_s_handle));
255         I3C_SlaveTransferCreateHandle(base, g_i3c_s_handle, i3c_secondarymaster_callback, master);
256 
257         /* Start slave non-blocking transfer. */
258         result =
259             I3C_SlaveTransferNonBlocking(base, g_i3c_s_handle,
260                                          ((uint32_t)kI3C_SlaveCompletionEvent | (uint32_t)kI3C_SlaveReceivedCCCEvent |
261                                           (uint32_t)kI3C_SlaveRequestSentEvent));
262         I3C_SlaveDisableInterrupts(base, (uint32_t)kI3C_SlaveTxReadyFlag);
263     }
264     return result;
265 }
266 
I3C_MasterAdapterProcessDAA(i3c_device_t * master)267 static status_t I3C_MasterAdapterProcessDAA(i3c_device_t *master)
268 {
269     assert(master != NULL);
270     status_t result                               = kStatus_Success;
271     i3c_device_control_info_t *masterControlInfo  = master->devControlInfo;
272     i3c_master_adapter_resource_t *masterResource = (i3c_master_adapter_resource_t *)masterControlInfo->resource;
273     I3C_Type *base                                = masterResource->base;
274     uint8_t rxBuffer[8] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};
275     i3c_bus_t *i3cBus   = master->bus;
276     bool mctrlDone      = false;
277     uint8_t rxSize      = 0;
278     uint32_t errStatus;
279     uint32_t status;
280     size_t rxCount;
281 
282     /* Return an error if the bus is already in use not by us. */
283     result = I3C_CheckForBusyBus(base);
284     if (kStatus_Success != result)
285     {
286         return result;
287     }
288 
289     /* Clear all flags. */
290     I3C_MasterClearErrorStatusFlags(base, (uint32_t)kI3C_MasterAllErrorFlags);
291     I3C_MasterClearStatusFlags(base, (uint32_t)kI3C_MasterClearFlags);
292 
293     /* Disable I3C IRQ sources while we configure stuff. */
294     uint32_t enabledInts = I3C_MasterGetEnabledInterrupts(base);
295     I3C_MasterDisableInterrupts(base, enabledInts);
296 
297     /* Emit process DAA */
298     I3C_MasterEmitRequest(base, kI3C_RequestProcessDAA);
299 
300     do
301     {
302         status = I3C_MasterGetStatusFlags(base);
303 
304         /* Check for error flags. */
305         errStatus = I3C_MasterGetErrorStatusFlags(base);
306         result    = I3C_MasterCheckAndClearError(base, errStatus);
307         if (kStatus_Success != result)
308         {
309             return result;
310         }
311 
312         if ((!mctrlDone) || (rxSize < 8U))
313         {
314             I3C_MasterGetFifoCounts(base, &rxCount, NULL);
315             while (rxCount-- != 0U)
316             {
317                 rxBuffer[rxSize++] = (uint8_t)(base->MRDATAB & I3C_MRDATAB_VALUE_MASK);
318             }
319 
320             if ((status & (uint32_t)kI3C_MasterControlDoneFlag) != 0U)
321             {
322                 I3C_MasterClearStatusFlags(base, (uint32_t)kI3C_MasterControlDoneFlag);
323                 mctrlDone = true;
324             }
325         }
326         else if ((I3C_MasterGetState(base) == kI3C_MasterStateDaa) &&
327             (0UL != (I3C_MasterGetStatusFlags(base) & (uint32_t)kI3C_MasterBetweenFlag)))
328         {
329             uint8_t validAddr = I3C_BusGetValidAddrSlot(i3cBus, 0x0);
330             if (validAddr < I3C_BUS_MAX_ADDR)
331             {
332                 /* Assign the dynamic address. */
333                 base->MWDATAB = validAddr;
334                 /* Emit process DAA again. */
335                 I3C_MasterEmitRequest(base, kI3C_RequestProcessDAA);
336 
337                 i3c_device_t *newI3CDev = malloc(sizeof(i3c_device_t));
338                 (void)memset(newI3CDev, 0, sizeof(i3c_device_t));
339                 newI3CDev->info.dynamicAddr = validAddr;
340                 newI3CDev->info.vendorID    = (((uint16_t)rxBuffer[0] << 8U | (uint16_t)rxBuffer[1]) & 0xFFFEU) >> 1U;
341                 newI3CDev->info.partNumber  = ((uint32_t)rxBuffer[2] << 24U | (uint32_t)rxBuffer[3] << 16U |
342                                               (uint32_t)rxBuffer[4] << 8U | (uint32_t)rxBuffer[5]);
343                 newI3CDev->info.bcr         = rxBuffer[6];
344                 newI3CDev->info.dcr         = rxBuffer[7];
345                 I3C_BusAddI3CDev(i3cBus, newI3CDev);
346 
347                 /* Ready to handle next device. */
348                 mctrlDone = false;
349                 rxSize    = 0;
350             }
351             else
352             {
353                 return kStatus_I3CBus_AddrSlotInvalid;
354             }
355         }
356         else
357         {
358             /* Intentional empty */
359         }
360     } while ((status & (uint32_t)kI3C_MasterCompleteFlag) != (uint32_t)kI3C_MasterCompleteFlag);
361 
362     I3C_MasterClearStatusFlags(base, (uint32_t)kI3C_MasterCompleteFlag);
363 
364     /* Enable I3C IRQ sources while we configure stuff. */
365     I3C_MasterEnableInterrupts(base, enabledInts);
366 
367     return kStatus_Success;
368 }
369 
I3CMasterAdapterTransfer(I3C_Type * base,i3c_master_transfer_t * xfer,i3c_master_transfer_mode_t transMode)370 static status_t I3CMasterAdapterTransfer(I3C_Type *base,
371                                          i3c_master_transfer_t *xfer,
372                                          i3c_master_transfer_mode_t transMode)
373 {
374     g_ibiWonFlag           = false;
375     g_masterCompletionFlag = false;
376     uint32_t timeout       = 0U;
377     status_t result        = kStatus_Success;
378     g_completionStatus     = kStatus_Success;
379 
380     /*TODO: wait for module idle */
381     if (g_transferPolling == true)
382     {
383         result = I3C_MasterTransferBlocking(base, xfer);
384     }
385     else
386     {
387         void *handle = s_i3cMasterHandle[I3C_GetInstance(base)];
388 
389         if (transMode == kI3C_MasterTransferInterruptMode)
390         {
391             result = I3C_MasterTransferNonBlocking(base, handle, xfer);
392             if (kStatus_Success != result)
393             {
394                 return result;
395             }
396 
397             /* Wait for transfer completed. */
398             while (!g_masterCompletionFlag)
399             {
400                 timeout++;
401                 __NOP();
402                 if (g_ibiWonFlag)
403                 {
404                     break;
405                 }
406                 else if ((g_completionStatus != kStatus_Success) || (timeout > I3C_TIME_OUT_INDEX))
407                 {
408                     break;
409                 }
410                 else
411                 {
412                     /* Add this to fix MISRA C2012 rule15.7 issue: Empty else without comment. */
413                 }
414             }
415 
416             result = g_completionStatus;
417         }
418 
419         if (timeout == I3C_TIME_OUT_INDEX)
420         {
421             result = kStatus_I3CBus_MasterTransTimeout;
422         }
423     }
424 
425     return result;
426 }
I3C_MasterAdapterTransmitCCC(i3c_device_t * master,i3c_ccc_cmd_t * cmd)427 static status_t I3C_MasterAdapterTransmitCCC(i3c_device_t *master, i3c_ccc_cmd_t *cmd)
428 {
429     assert(master != NULL);
430     i3c_device_control_info_t *masterControlInfo  = master->devControlInfo;
431     i3c_master_adapter_resource_t *masterResource = (i3c_master_adapter_resource_t *)masterControlInfo->resource;
432     I3C_Type *base                                = masterResource->base;
433     i3c_master_transfer_mode_t transMode          = masterResource->transMode;
434     status_t result                               = kStatus_Success;
435 
436     i3c_master_transfer_t xfer;
437     (void)memset(&xfer, 0, sizeof(xfer));
438 
439     if (cmd->destAddr == I3C_BUS_BROADCAST_ADDR)
440     {
441         xfer.slaveAddress   = I3C_BUS_BROADCAST_ADDR;
442         xfer.subaddress     = cmd->cmdId;
443         xfer.subaddressSize = 1U;
444         xfer.data           = cmd->data;
445         xfer.dataSize       = cmd->dataSize;
446         xfer.direction      = cmd->isRead ? kI3C_Read : kI3C_Write;
447         xfer.busType        = kI3C_TypeI3CSdr;
448         xfer.flags          = (uint32_t)kI3C_TransferDisableRxTermFlag;
449         result              = I3CMasterAdapterTransfer(base, &xfer, transMode);
450         if (result != kStatus_Success)
451         {
452             return result;
453         }
454     }
455     else
456     {
457         xfer.slaveAddress = I3C_BUS_BROADCAST_ADDR;
458         xfer.data         = &cmd->cmdId;
459         xfer.dataSize     = 1U;
460         xfer.direction    = kI3C_Write;
461         xfer.busType      = kI3C_TypeI3CSdr;
462         xfer.flags        = (uint32_t)kI3C_TransferNoStopFlag;
463         result            = I3CMasterAdapterTransfer(base, &xfer, transMode);
464         if (result != kStatus_Success)
465         {
466             return result;
467         }
468 
469         xfer.slaveAddress = cmd->destAddr;
470         xfer.data         = cmd->data;
471         xfer.dataSize     = cmd->dataSize;
472         xfer.direction    = cmd->isRead ? kI3C_Read : kI3C_Write;
473         xfer.busType      = kI3C_TypeI3CSdr;
474         xfer.flags        = (uint32_t)kI3C_TransferRepeatedStartFlag | (uint32_t)kI3C_TransferDisableRxTermFlag;
475         result            = I3CMasterAdapterTransfer(base, &xfer, transMode);
476         if (result != kStatus_Success)
477         {
478             return result;
479         }
480     }
481 
482     return result;
483 }
484 
I3C_MasterAdapterDoI3CTransfer(i3c_device_t * device,i3c_bus_transfer_t * xfer)485 static status_t I3C_MasterAdapterDoI3CTransfer(i3c_device_t *device, i3c_bus_transfer_t *xfer)
486 {
487     assert(device != NULL);
488     i3c_bus_t *bus       = device->bus;
489     i3c_device_t *master = (i3c_device_t *)bus->currentMaster;
490     assert(master != NULL);
491 
492     i3c_device_control_info_t *masterControlInfo  = master->devControlInfo;
493     i3c_master_adapter_resource_t *masterResource = (i3c_master_adapter_resource_t *)masterControlInfo->resource;
494     I3C_Type *base                                = masterResource->base;
495     i3c_master_transfer_mode_t transMode          = masterResource->transMode;
496 
497     i3c_master_transfer_t masterXfer;
498     (void)memset(&masterXfer, 0, sizeof(masterXfer));
499 
500     masterXfer.slaveAddress   = device->info.dynamicAddr;
501     masterXfer.subaddress     = xfer->regAddr;
502     masterXfer.subaddressSize = xfer->regAddrSize;
503     masterXfer.data           = xfer->data;
504     masterXfer.dataSize       = xfer->dataSize;
505     masterXfer.direction      = xfer->isRead ? kI3C_Read : kI3C_Write;
506     masterXfer.busType        = kI3C_TypeI3CSdr;
507     masterXfer.flags          = (uint32_t)kI3C_TransferDefaultFlag;
508 
509     return I3CMasterAdapterTransfer(base, &masterXfer, transMode);
510 }
511 
I3C_MasterAdapterDoI2CTransfer(i2c_device_t * device,i3c_bus_transfer_t * xfer)512 static status_t I3C_MasterAdapterDoI2CTransfer(i2c_device_t *device, i3c_bus_transfer_t *xfer)
513 {
514     assert(device != NULL);
515     i3c_bus_t *bus       = device->bus;
516     i3c_device_t *master = (i3c_device_t *)bus->currentMaster;
517     assert(master != NULL);
518 
519     i3c_device_control_info_t *masterControlInfo  = master->devControlInfo;
520     i3c_master_adapter_resource_t *masterResource = (i3c_master_adapter_resource_t *)masterControlInfo->resource;
521     I3C_Type *base                                = masterResource->base;
522     i3c_master_transfer_mode_t transMode          = masterResource->transMode;
523 
524     i3c_master_transfer_t masterXfer;
525     (void)memset(&masterXfer, 0, sizeof(masterXfer));
526 
527     masterXfer.slaveAddress   = device->staticAddr;
528     masterXfer.subaddress     = xfer->regAddr;
529     masterXfer.subaddressSize = xfer->regAddrSize;
530     masterXfer.data           = xfer->data;
531     masterXfer.dataSize       = xfer->dataSize;
532     masterXfer.direction      = xfer->isRead ? kI3C_Read : kI3C_Write;
533     masterXfer.busType        = kI3C_TypeI2C;
534     masterXfer.flags          = (uint32_t)kI3C_TransferDefaultFlag;
535 
536     return I3CMasterAdapterTransfer(base, &masterXfer, transMode);
537 }
538 
I3C_MasterAdapterTakeOverMasterShip(i3c_device_t * master)539 static void I3C_MasterAdapterTakeOverMasterShip(i3c_device_t *master)
540 {
541     i3c_device_control_info_t *masterControlInfo  = master->devControlInfo;
542     i3c_master_adapter_resource_t *masterResource = (i3c_master_adapter_resource_t *)masterControlInfo->resource;
543     I3C_Type *base                                = masterResource->base;
544     i3c_bus_t *i3cBus                             = master->bus;
545     i3c_master_adapter_private_t *masterPrivate   = (i3c_master_adapter_private_t *)masterControlInfo->privateData;
546 
547     uint8_t devCount       = masterPrivate->devCount;
548     i3c_ccc_dev_t *devList = masterPrivate->devList;
549 
550     /* Register bus devices detected from SLAVE */
551     if ((devCount != 0U) && (devList != NULL))
552     {
553         for (uint8_t i = 0U; i < devCount; i++)
554         {
555             i3c_ccc_dev_t *cccDev = &devList[i];
556 #if defined(I3C_SDYNADDR_DADDR_MASK)
557             if (cccDev->dynamicAddr != (base->SDYNADDR & I3C_SDYNADDR_DADDR_MASK))
558 #else
559             if (cccDev->dynamicAddr != (base->SMAPCTRL0 & I3C_SMAPCTRL0_DA_MASK))
560 #endif
561             {
562                 if (cccDev->dynamicAddr != 0U)
563                 {
564                     i3c_device_t *newI3CDev = malloc(sizeof(i3c_device_t));
565                     (void)memset(newI3CDev, 0, sizeof(i3c_device_t));
566 
567                     newI3CDev->info.dynamicAddr = cccDev->dynamicAddr >> 1U;
568                     newI3CDev->info.bcr         = cccDev->dcr;
569                     newI3CDev->info.dcr         = cccDev->dcr;
570                     newI3CDev->info.staticAddr  = cccDev->staticAddr >> 1U;
571 
572                     I3C_BusAddI3CDev(i3cBus, newI3CDev);
573                 }
574                 else
575                 {
576                     i2c_device_t *newI2CDev = malloc(sizeof(i2c_device_t));
577                     (void)memset(newI2CDev, 0, sizeof(i2c_device_t));
578 
579                     newI2CDev->lvr        = cccDev->lvr;
580                     newI2CDev->staticAddr = cccDev->staticAddr >> 1U;
581 
582                     I3C_BusAddI2CDev(i3cBus, newI2CDev);
583                 }
584             }
585             else
586             {
587                 master->info.dynamicAddr = cccDev->dynamicAddr >> 1U;
588             }
589         }
590     }
591 
592     i3cBus->currentMaster          = master;
593     masterControlInfo->isSecondary = false;
594 
595     /* Clear all flags. */
596     I3C_SlaveClearStatusFlags(base, (uint32_t)kI3C_SlaveClearFlags);
597 
598     /* Disable I3C slave IRQ resources */
599     I3C_SlaveDisableInterrupts(base, (uint32_t)kI3C_SlaveAllIrqFlags);
600 
601     I3C_MasterEnable(base, kI3C_MasterOn);
602     I3C_SlaveEnable(base, false);
603 }
604 
I3C_MasterAdapterHandOffMasterShip(i3c_device_t * master,uint8_t slaveAddr)605 static status_t I3C_MasterAdapterHandOffMasterShip(i3c_device_t *master, uint8_t slaveAddr)
606 {
607     status_t result                               = kStatus_Success;
608     i3c_device_control_info_t *masterControlInfo  = master->devControlInfo;
609     i3c_master_adapter_resource_t *masterResource = (i3c_master_adapter_resource_t *)masterControlInfo->resource;
610     I3C_Type *base                                = masterResource->base;
611     i3c_bus_t *bus                                = master->bus;
612 
613     /* Disable MR and hotjoin events */
614     result =
615         I3C_BusMasterDisableEvents(master, I3C_BUS_BROADCAST_ADDR, ((uint8_t)kI3C_EventMR | (uint8_t)kI3C_EventHJ));
616     if (result != kStatus_Success)
617     {
618         return result;
619     }
620 
621     /* Send device list on bus */
622     result = I3C_BusMasterSendSlavesList(master);
623     if (result != kStatus_Success)
624     {
625         return result;
626     }
627 
628     uint8_t accData;
629     i3c_ccc_cmd_t getAccMstCmd = {0};
630 
631     getAccMstCmd.isRead   = true;
632     getAccMstCmd.cmdId    = I3C_BUS_CCC_GETACCMST;
633     getAccMstCmd.destAddr = slaveAddr;
634     getAccMstCmd.data     = &accData;
635     getAccMstCmd.dataSize = 1;
636 
637     result = I3C_MasterAdapterTransmitCCC(master, &getAccMstCmd);
638 
639     /* Change current master to secondary master */
640     bus->currentMaster             = NULL;
641     masterControlInfo->isSecondary = true;
642 
643     /* Clear all flags. */
644     I3C_MasterClearStatusFlags(base, (uint32_t)kI3C_MasterClearFlags);
645     I3C_MasterEnable(base, kI3C_MasterCapable);
646     I3C_SlaveEnable(base, true);
647 
648     /* Create slave handle. */
649     i3c_slave_handle_t *g_i3c_s_handle = malloc(sizeof(*g_i3c_s_handle));
650     I3C_SlaveTransferCreateHandle(base, g_i3c_s_handle, i3c_secondarymaster_callback, master);
651 
652     /* Start slave non-blocking transfer. */
653     result = I3C_SlaveTransferNonBlocking(base, g_i3c_s_handle,
654                                           ((uint32_t)kI3C_SlaveCompletionEvent | (uint32_t)kI3C_SlaveReceivedCCCEvent));
655     I3C_SlaveDisableInterrupts(base, (uint32_t)kI3C_SlaveTxReadyFlag);
656 
657     return result;
658 }
659 
I3C_MasterAdapterRegisterIBI(i3c_device_t * master,uint8_t ibiAddress)660 static void I3C_MasterAdapterRegisterIBI(i3c_device_t *master, uint8_t ibiAddress)
661 {
662     i3c_device_control_info_t *masterControlInfo  = master->devControlInfo;
663     i3c_master_adapter_resource_t *masterResource = (i3c_master_adapter_resource_t *)masterControlInfo->resource;
664     I3C_Type *base                                = masterResource->base;
665 
666     i3c_register_ibi_addr_t ibiRule;
667     I3C_MasterGetIBIRules(base, &ibiRule);
668     if (ibiRule.ibiHasPayload)
669     {
670         ibiRule.ibiHasPayload = true;
671     }
672 
673     for (uint32_t count = 0; count < ARRAY_SIZE(ibiRule.address); count++)
674     {
675         if (0U == ibiRule.address[count])
676         {
677             ibiRule.address[count] = ibiAddress;
678             break;
679         }
680     }
681 
682     I3C_MasterRegisterIBI(base, &ibiRule);
683 }
684 
I3C_SlaveAdapterInit(i3c_device_t * dev)685 static status_t I3C_SlaveAdapterInit(i3c_device_t *dev)
686 {
687     assert(dev != NULL);
688 
689     i3c_device_control_info_t *devControlInfo  = dev->devControlInfo;
690     i3c_device_information_t *devInfo          = &dev->info;
691     i3c_device_adapter_resource_t *devResource = (i3c_device_adapter_resource_t *)devControlInfo->resource;
692 
693     I3C_Type *base = devResource->base;
694 
695     i3c_slave_config_t slaveConfig;
696     I3C_SlaveGetDefaultConfig(&slaveConfig);
697     slaveConfig.staticAddr = devInfo->staticAddr;
698     slaveConfig.dcr        = devInfo->dcr;
699     slaveConfig.bcr        = devInfo->bcr;
700     slaveConfig.partNumber = devInfo->partNumber;
701     slaveConfig.vendorID   = devInfo->vendorID;
702     slaveConfig.offline    = false;
703 
704     I3C_SlaveInit(base, &slaveConfig, devResource->clockInHz);
705 
706     /* Create slave handle. */
707     i3c_slave_handle_t *g_i3c_s_handle = malloc(sizeof(*g_i3c_s_handle));
708     I3C_SlaveTransferCreateHandle(base, g_i3c_s_handle, devResource->callback, dev);
709 
710     /* Start slave non-blocking transfer. */
711     status_t result = kStatus_Success;
712     result          = I3C_SlaveTransferNonBlocking(base, g_i3c_s_handle, (uint32_t)kI3C_SlaveCompletionEvent);
713 
714     return result;
715 }
716 
I3C_SlaveAdapterRequestHotJoin(i3c_device_t * dev)717 static void I3C_SlaveAdapterRequestHotJoin(i3c_device_t *dev)
718 {
719     assert(dev != NULL);
720 
721     i3c_device_control_info_t *devControlInfo  = dev->devControlInfo;
722     i3c_device_adapter_resource_t *devResource = (i3c_device_adapter_resource_t *)devControlInfo->resource;
723 
724     I3C_Type *base = devResource->base;
725 
726     I3C_SlaveRequestEvent(base, kI3C_SlaveEventHotJoinReq);
727 }
728 
I3C_SlaveAdapterRequestMastership(i3c_device_t * dev)729 static void I3C_SlaveAdapterRequestMastership(i3c_device_t *dev)
730 {
731     assert(dev != NULL);
732 
733     i3c_device_control_info_t *devControlInfo  = dev->devControlInfo;
734     i3c_device_adapter_resource_t *devResource = (i3c_device_adapter_resource_t *)devControlInfo->resource;
735 
736     I3C_Type *base = devResource->base;
737 
738     I3C_SlaveRequestEvent(base, kI3C_SlaveEventMasterReq);
739 }
740 
I3C_SlaveAdapterRequestIBI(i3c_device_t * dev,void * data,size_t dataSize)741 static void I3C_SlaveAdapterRequestIBI(i3c_device_t *dev, void *data, size_t dataSize)
742 {
743     assert(dev != NULL);
744 
745     i3c_device_control_info_t *devControlInfo  = dev->devControlInfo;
746     i3c_device_adapter_resource_t *devResource = (i3c_device_adapter_resource_t *)devControlInfo->resource;
747 
748     I3C_Type *base = devResource->base;
749 
750     if (data != NULL)
751     {
752         I3C_SlaveRequestIBIWithData(base, (uint8_t *)data, dataSize);
753     }
754     else
755     {
756         I3C_SlaveRequestEvent(base, kI3C_SlaveEventIBI);
757     }
758 }
759