1 /*
2  * Copyright 2020, 2022-2023 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "fsl_component_i3c.h"
8 
9 /*******************************************************************************
10  * Definitions
11  ******************************************************************************/
12 
13 /*******************************************************************************
14  * Prototypes
15  ******************************************************************************/
16 
17 /*******************************************************************************
18  * Variables
19  ******************************************************************************/
20 
21 /*******************************************************************************
22  * Code
23  ******************************************************************************/
I3C_BusSetAddrSlot(i3c_bus_t * bus,uint8_t addr,i3c_addr_slot_status_t status)24 void I3C_BusSetAddrSlot(i3c_bus_t *bus, uint8_t addr, i3c_addr_slot_status_t status)
25 {
26     uint16_t bitPos = (uint16_t)addr * I3C_BUS_ADDR_SLOTWIDTH;
27     uint32_t *slotPtr;
28 
29     if (addr > I3C_BUS_MAX_ADDR)
30     {
31         return;
32     }
33 
34     slotPtr = &bus->addrSlots[bitPos / I3C_BUS_ADDR_SLOTDEPTH];
35     *slotPtr &= ~((uint32_t)I3C_BUS_ADDR_SLOTMASK << (bitPos % I3C_BUS_ADDR_SLOTDEPTH));
36     *slotPtr |= (uint32_t)status << (bitPos % I3C_BUS_ADDR_SLOTDEPTH);
37 }
38 
I3C_BusInitAddrSlots(i3c_bus_t * bus)39 static void I3C_BusInitAddrSlots(i3c_bus_t *bus)
40 {
41     uint8_t i;
42 
43     /* Reserve address 0x0 to 0x7. */
44     for (i = 0; i < 8U; i++)
45     {
46         I3C_BusSetAddrSlot(bus, i, kI3C_Bus_AddrSlot_Reserved);
47     }
48 
49     /* Reserve the conditional restriction I3C address. */
50     I3C_BusSetAddrSlot(bus, 0x78U, kI3C_Bus_AddrSlot_Reserved);
51     I3C_BusSetAddrSlot(bus, 0x79U, kI3C_Bus_AddrSlot_Reserved);
52     I3C_BusSetAddrSlot(bus, 0x7BU, kI3C_Bus_AddrSlot_Reserved);
53     I3C_BusSetAddrSlot(bus, 0x7DU, kI3C_Bus_AddrSlot_Reserved);
54 
55     /* All are prohibited since I3C targets will interpret an I3C address header with any of these addresses as a
56      * broadcast address with a single-bit error. */
57     I3C_BusSetAddrSlot(bus, I3C_BOARDCAST_SINGLE_BIT_ERR_DETECT_ADDR1, kI3C_Bus_AddrSlot_Reserved);
58     I3C_BusSetAddrSlot(bus, I3C_BOARDCAST_SINGLE_BIT_ERR_DETECT_ADDR2, kI3C_Bus_AddrSlot_Reserved);
59     I3C_BusSetAddrSlot(bus, I3C_BOARDCAST_SINGLE_BIT_ERR_DETECT_ADDR3, kI3C_Bus_AddrSlot_Reserved);
60     I3C_BusSetAddrSlot(bus, I3C_BOARDCAST_SINGLE_BIT_ERR_DETECT_ADDR4, kI3C_Bus_AddrSlot_Reserved);
61     I3C_BusSetAddrSlot(bus, I3C_BOARDCAST_SINGLE_BIT_ERR_DETECT_ADDR5, kI3C_Bus_AddrSlot_Reserved);
62     I3C_BusSetAddrSlot(bus, I3C_BOARDCAST_SINGLE_BIT_ERR_DETECT_ADDR6, kI3C_Bus_AddrSlot_Reserved);
63     I3C_BusSetAddrSlot(bus, I3C_BOARDCAST_SINGLE_BIT_ERR_DETECT_ADDR7, kI3C_Bus_AddrSlot_Reserved);
64 
65     /* Reserve I3C broadcast address. */
66     I3C_BusSetAddrSlot(bus, I3C_BUS_BROADCAST_ADDR, kI3C_Bus_AddrSlot_Reserved);
67 }
68 
I3C_BusGetAddrSlotStatus(i3c_bus_t * bus,uint8_t checkAddr)69 static uint8_t I3C_BusGetAddrSlotStatus(i3c_bus_t *bus, uint8_t checkAddr)
70 {
71     uint16_t bitPos    = (uint16_t)checkAddr * 2U;
72     uint32_t useStatus = 0;
73 
74     if (checkAddr > I3C_BUS_MAX_ADDR)
75     {
76         return (uint8_t)kI3C_Bus_AddrSlot_Reserved;
77     }
78 
79     useStatus = bus->addrSlots[bitPos / I3C_BUS_ADDR_SLOTDEPTH];
80     useStatus >>= bitPos % I3C_BUS_ADDR_SLOTDEPTH;
81 
82     return (uint8_t)(useStatus & (uint8_t)I3C_BUS_ADDR_SLOTMASK);
83 }
84 
I3C_CheckBusMasterOps(i3c_device_hw_ops_t * ops)85 static status_t I3C_CheckBusMasterOps(i3c_device_hw_ops_t *ops)
86 {
87     if ((ops == NULL) || (ops->Init == NULL) || (ops->DoI3CTransfer == NULL) || (ops->DoI2CTransfer == NULL) ||
88         (ops->TransmitCCC == NULL) || (ops->ProceedDAA == NULL))
89     {
90         return kStatus_I3CBus_MasterOpsMissing;
91     }
92 
93     return kStatus_Success;
94 }
95 
I3C_BusMasterGetMaxReadLength(i3c_device_t * master,i3c_device_information_t * info)96 static status_t I3C_BusMasterGetMaxReadLength(i3c_device_t *master, i3c_device_information_t *info)
97 {
98     i3c_ccc_cmd_t getMRLCmd = {0};
99     status_t result         = kStatus_Success;
100 
101     getMRLCmd.isRead   = true;
102     getMRLCmd.cmdId    = I3C_BUS_CCC_GETMRL;
103     getMRLCmd.destAddr = info->dynamicAddr;
104     getMRLCmd.data     = malloc(3U);
105     getMRLCmd.dataSize = 3U;
106 
107     /*
108      * When the device does not have IBI payload GETMRL only returns 2
109      * bytes of data.
110      */
111     if ((info->bcr & I3C_BUS_DEV_BCR_IBI_PAYLOAD_MASK) == 0U)
112     {
113         getMRLCmd.dataSize -= 1U;
114     }
115 
116     result = I3C_BusMasterSendCCC(master, &getMRLCmd);
117 
118     uint8_t *pData = getMRLCmd.data;
119     if ((info->bcr & I3C_BUS_DEV_BCR_IBI_PAYLOAD_MASK) != 0U)
120     {
121         info->maxIBILength = pData[2];
122     }
123 
124     info->maxReadLength = (uint16_t)pData[0] << 8UL | (uint16_t)pData[1];
125 
126     free(getMRLCmd.data);
127 
128     return result;
129 }
130 
I3C_BusMasterGetMaxWriteLength(i3c_device_t * master,i3c_device_information_t * info)131 static status_t I3C_BusMasterGetMaxWriteLength(i3c_device_t *master, i3c_device_information_t *info)
132 {
133     i3c_ccc_cmd_t getMWLCmd = {0};
134     status_t result         = kStatus_Success;
135 
136     uint16_t writelen;
137     getMWLCmd.isRead   = true;
138     getMWLCmd.cmdId    = I3C_BUS_CCC_GETMWL;
139     getMWLCmd.destAddr = info->dynamicAddr;
140     getMWLCmd.data     = &writelen;
141     getMWLCmd.dataSize = 2U;
142 
143     result = I3C_BusMasterSendCCC(master, &getMWLCmd);
144 
145     info->maxWriteLength = writelen;
146 
147     return result;
148 }
149 
I3C_BusMasterGetHDRCapability(i3c_device_t * master,i3c_device_information_t * info)150 static status_t I3C_BusMasterGetHDRCapability(i3c_device_t *master, i3c_device_information_t *info)
151 {
152     i3c_ccc_cmd_t getHDRCapCmd = {0};
153     status_t result            = kStatus_Success;
154 
155     uint8_t hdrMode;
156     getHDRCapCmd.isRead   = true;
157     getHDRCapCmd.cmdId    = I3C_BUS_CCC_GETHDRCAP;
158     getHDRCapCmd.destAddr = info->dynamicAddr;
159     getHDRCapCmd.data     = &hdrMode;
160     getHDRCapCmd.dataSize = 1U;
161 
162     result = I3C_BusMasterSendCCC(master, &getHDRCapCmd);
163 
164     info->hdrMode = hdrMode;
165 
166     return result;
167 }
168 
I3C_BusMasterGetPID(i3c_device_t * master,i3c_device_information_t * info)169 static status_t I3C_BusMasterGetPID(i3c_device_t *master, i3c_device_information_t *info)
170 {
171     uint8_t pid[6];
172     i3c_ccc_cmd_t getPidCmd = {0};
173     status_t result         = kStatus_Success;
174 
175     getPidCmd.isRead   = true;
176     getPidCmd.cmdId    = I3C_BUS_CCC_GETPID;
177     getPidCmd.destAddr = info->dynamicAddr;
178     getPidCmd.data     = pid;
179     getPidCmd.dataSize = 6U;
180 
181     result = I3C_BusMasterSendCCC(master, &getPidCmd);
182 
183     info->vendorID   = (((uint16_t)pid[0] << 8U | (uint16_t)pid[1]) & 0xFFFEU) >> 1U;
184     info->partNumber = ((uint32_t)pid[2] << 24U | (uint32_t)pid[3] << 16U | (uint32_t)pid[4] << 8U | (uint32_t)pid[5]);
185 
186     return result;
187 }
188 
I3C_BusMasterGetBCR(i3c_device_t * master,i3c_device_information_t * info)189 static status_t I3C_BusMasterGetBCR(i3c_device_t *master, i3c_device_information_t *info)
190 {
191     uint8_t bcr;
192     i3c_ccc_cmd_t getBCRCmd = {0};
193     status_t result         = kStatus_Success;
194 
195     getBCRCmd.isRead   = true;
196     getBCRCmd.cmdId    = I3C_BUS_CCC_GETBCR;
197     getBCRCmd.destAddr = info->dynamicAddr;
198     getBCRCmd.data     = &bcr;
199     getBCRCmd.dataSize = 1U;
200 
201     result = I3C_BusMasterSendCCC(master, &getBCRCmd);
202 
203     info->bcr = bcr;
204 
205     return result;
206 }
207 
I3C_BusMasterGetDCR(i3c_device_t * master,i3c_device_information_t * info)208 static status_t I3C_BusMasterGetDCR(i3c_device_t *master, i3c_device_information_t *info)
209 {
210     uint8_t dcr;
211     i3c_ccc_cmd_t getDCRCmd = {0};
212     status_t result         = kStatus_Success;
213 
214     getDCRCmd.isRead   = true;
215     getDCRCmd.cmdId    = I3C_BUS_CCC_GETDCR;
216     getDCRCmd.destAddr = info->dynamicAddr;
217     getDCRCmd.data     = &dcr;
218     getDCRCmd.dataSize = 1U;
219 
220     result = I3C_BusMasterSendCCC(master, &getDCRCmd);
221 
222     info->dcr = dcr;
223 
224     return result;
225 }
226 
I3C_BusMasterAssignDevDynamicAddr(i3c_device_t * masterDev)227 static status_t I3C_BusMasterAssignDevDynamicAddr(i3c_device_t *masterDev)
228 {
229     i3c_bus_t *i3cBus = masterDev->bus;
230     status_t result   = kStatus_Success;
231 
232     list_handle_t i3cDevList = &(i3cBus->i3cDevList);
233 
234     for (list_element_handle_t listItem = i3cDevList->head; listItem != NULL; listItem = listItem->next)
235     {
236         i3c_device_t *tmpDev = (i3c_device_t *)(void *)listItem;
237         if (tmpDev == masterDev)
238         {
239             continue;
240         }
241         else if ((tmpDev->initDynamicAddr != 0U) && (tmpDev->info.staticAddr != 0U) && (tmpDev->info.dynamicAddr == 0U))
242         {
243             result =
244                 I3C_BusMasterSetDynamicAddrFromStaticAddr(masterDev, tmpDev->info.staticAddr, tmpDev->initDynamicAddr);
245 
246             if (result != kStatus_Success)
247             {
248                 return result;
249             }
250 
251             tmpDev->info.dynamicAddr = tmpDev->initDynamicAddr;
252             I3C_BusSetAddrSlot(i3cBus, tmpDev->info.dynamicAddr, kI3C_Bus_AddrSlot_I3CDev);
253 
254             /* Retrieve device information. */
255             result = I3C_BusMasterGetDeviceInfo(masterDev, tmpDev->info.dynamicAddr, &tmpDev->info);
256             if (result != kStatus_Success)
257             {
258                 return result;
259             }
260         }
261         else
262         {
263             /*Empty else to eliminate MISRA 15.7*/
264         }
265     }
266 
267     return result;
268 }
269 
I3C_BusMasterAddExistingI3CDevs(i3c_device_t * masterDev)270 static status_t I3C_BusMasterAddExistingI3CDevs(i3c_device_t *masterDev)
271 {
272     i3c_bus_t *i3cBus = masterDev->bus;
273     status_t result   = kStatus_Success;
274 
275     list_handle_t i3cDevList = &(i3cBus->i3cDevList);
276 
277     for (list_element_handle_t listItem = i3cDevList->head; listItem != NULL; listItem = listItem->next)
278     {
279         i3c_device_t *tmpDev = (i3c_device_t *)(void *)listItem;
280         if (tmpDev == masterDev)
281         {
282             continue;
283         }
284         else if (tmpDev->ibiInfo != NULL)
285         {
286             result = I3C_BusMasterRegisterDevIBI(masterDev, tmpDev, tmpDev->ibiInfo);
287             if (result != kStatus_Success)
288             {
289                 return result;
290             }
291         }
292         else
293         {
294             /*Fix MISRA violation 15.7*/
295         }
296     }
297 
298     return result;
299 }
300 
301 /*!
302  * brief Add exist I3C device in bus to the bus device list.
303  *
304  * This function will simply add the device to the bus device list and set the related address slot.
305  *
306  * param bus Pointer to bus structure.
307  * param dev Pointer to I3C device.
308  */
I3C_BusAddI3CDev(i3c_bus_t * bus,i3c_device_t * dev)309 void I3C_BusAddI3CDev(i3c_bus_t *bus, i3c_device_t *dev)
310 {
311     /* Chain device into i3c_device_list */
312     list_handle_t i3cDevList = &bus->i3cDevList;
313     (void)LIST_AddTail(i3cDevList, &dev->listNode);
314 
315     if (dev->info.dynamicAddr != 0U)
316     {
317         /* Set slot status I3C device */
318         I3C_BusSetAddrSlot(bus, dev->info.dynamicAddr, kI3C_Bus_AddrSlot_I3CDev);
319     }
320 
321     if (dev->info.staticAddr != 0U)
322     {
323         /* Set slot status I2C device */
324         I3C_BusSetAddrSlot(bus, dev->info.staticAddr, kI3C_Bus_AddrSlot_I2CDev);
325     }
326 
327     dev->bus = bus;
328 }
329 
330 /*!
331  * brief Add exist I2C device in bus to the bus device list.
332  *
333  * This function will simply add the device to the bus device list and set the related address slot.
334  *
335  * param bus Pointer to bus structure.
336  * param dev Pointer to I2C device.
337  */
I3C_BusAddI2CDev(i3c_bus_t * bus,i2c_device_t * dev)338 void I3C_BusAddI2CDev(i3c_bus_t *bus, i2c_device_t *dev)
339 {
340     /* Chain device into i2c_device_list */
341     dev->bus                 = bus;
342     list_handle_t i2cDevList = &bus->i2cDevList;
343     (void)LIST_AddTail(i2cDevList, &dev->listNode);
344     /* Set slot status I2C device */
345     I3C_BusSetAddrSlot(bus, dev->staticAddr, kI3C_Bus_AddrSlot_I2CDev);
346     dev->bus = bus;
347 }
348 
349 /*!
350  * brief Get valid address slot in the I3C bus.
351  *
352  * This function will search for available address lot in the I3C bus address pool, the search starts from
353  * the startAddr specified by user input, to end address defined in @ref I3C_BUS_MAX_ADDR. Will return the
354  * available address if the related address slot is valid.
355  *
356  * param bus Pointer to bus structure.
357  * param startAddr Start address for address slot searching, end address is defined in @ref I3C_BUS_MAX_ADDR.
358  * return Available address in the bus address pool.
359  */
I3C_BusGetValidAddrSlot(i3c_bus_t * bus,uint8_t startAddr)360 uint8_t I3C_BusGetValidAddrSlot(i3c_bus_t *bus, uint8_t startAddr)
361 {
362     uint8_t validAddr = 0xFF;
363 
364     for (validAddr = startAddr; validAddr < I3C_BUS_MAX_ADDR; validAddr++)
365     {
366         if (I3C_BusGetAddrSlotStatus(bus, validAddr) == (uint8_t)kI3C_Bus_AddrSlot_Free)
367         {
368             return validAddr;
369         }
370     }
371 
372     return validAddr;
373 }
374 
375 /*!
376  * brief Gets the default configuration structure.
377  *
378  * This function initializes the bus configuration structure to a default value. The default
379  * values are:
380  *   busConfig->busMode = kI3C_Bus_PureMode;
381  *   busConfig->i2cBaudRate = 400000U;
382  *   busConfig->i3cOpenDrainBaudRate = 1500000U;
383  *   busConfig->i3cPushPullBaudRate = 4000000U;
384  *
385  * param config Pointer to a configuration structure.
386  */
I3C_BusGetDefaultBusConfig(i3c_bus_config_t * busConfig)387 void I3C_BusGetDefaultBusConfig(i3c_bus_config_t *busConfig)
388 {
389     busConfig->busMode              = kI3C_Bus_PureMode;
390     busConfig->i2cBaudRate          = 400000U;
391     busConfig->i3cOpenDrainBaudRate = 1500000U;
392     busConfig->i3cPushPullBaudRate  = 4000000U;
393 }
394 
395 /*!
396  * brief Creates I3C bus structure.
397  *
398  * This function creates the bus structure with input bus configuration. Address pool set up and device
399  * list initialize process will be also done in this function call.
400  *
401  * param bus Pointer to bus structure.
402  * param busConfig Pointer to the bus configuration structure.
403  */
I3C_BusCreate(i3c_bus_t * bus,const i3c_bus_config_t * busConfig)404 void I3C_BusCreate(i3c_bus_t *bus, const i3c_bus_config_t *busConfig)
405 {
406     assert(bus != NULL);
407 
408     (void)memset(bus, 0, sizeof(*bus));
409 
410     LIST_Init(&bus->i2cDevList, 0);
411     LIST_Init(&bus->i3cDevList, 0);
412     I3C_BusInitAddrSlots(bus);
413     bus->busMode              = busConfig->busMode;
414     bus->i2cBaudRate          = busConfig->i2cBaudRate;
415     bus->i3cOpenDrainBaudRate = busConfig->i3cOpenDrainBaudRate;
416     bus->i3cPushPullBaudRate  = busConfig->i3cPushPullBaudRate;
417 }
418 
419 /*!
420  * brief Create I3C master structure on bus.
421  *
422  * This function will create I3C master bus structure, initialize the master according to bus characteristics, install
423  * device information and device control information.
424  *
425  * param masterDev Pointer to device structure creating as master.
426  * param bus Pointer to bus structure.
427  * param devInfo Pointer to device information structure.
428  * param masterControlInfo Pointer to master control information structure.
429  */
I3C_BusMasterCreate(i3c_device_t * masterDev,i3c_bus_t * bus,i3c_device_information_t * devInfo,i3c_device_control_info_t * masterControlInfo)430 status_t I3C_BusMasterCreate(i3c_device_t *masterDev,
431                              i3c_bus_t *bus,
432                              i3c_device_information_t *devInfo,
433                              i3c_device_control_info_t *masterControlInfo)
434 {
435     status_t result = kStatus_Success;
436 
437     (void)memset(masterDev, 0, sizeof(*masterDev));
438 
439     masterDev->info = *devInfo;
440     result          = I3C_CheckBusMasterOps(masterControlInfo->funcs);
441 
442     if (result != kStatus_Success)
443     {
444         return result;
445     }
446 
447     masterDev->devControlInfo = masterControlInfo;
448     masterDev->bus            = bus;
449 
450     /* call master init to initialize master */
451     result = masterControlInfo->funcs->Init(masterDev);
452 
453     if (result != kStatus_Success)
454     {
455         return result;
456     }
457 
458     if (!masterControlInfo->isSecondary)
459     {
460         bus->currentMaster = masterDev;
461         /* Add masterDev to bus i3c device list */
462         I3C_BusAddI3CDev(bus, masterDev);
463 
464         /* Execute reset DAA CCC command to reset all i3c device dynamic address */
465         result = I3C_BusMasterResetDAA(masterDev, I3C_BUS_BROADCAST_ADDR);
466         if (result != kStatus_Success)
467         {
468             return result;
469         }
470 
471         /* Master assign slave with init dynamic address. */
472         result = I3C_BusMasterAssignDevDynamicAddr(masterDev);
473         if (result != kStatus_Success)
474         {
475             return result;
476         }
477 
478         result = I3C_BusMasterAddExistingI3CDevs(masterDev);
479         if (result != kStatus_Success)
480         {
481             return result;
482         }
483 
484         /* Disable all events before start doing DAA. */
485         result = I3C_BusMasterDisableEvents(masterDev, I3C_BUS_BROADCAST_ADDR,
486                                             ((uint8_t)kI3C_EventMR | (uint8_t)kI3C_EventHJ | (uint8_t)kI3C_EventIBI));
487         if (result != kStatus_Success)
488         {
489             return result;
490         }
491 
492         /* Start to do DAA */
493         result = I3C_BusMasterDoDAA(masterDev);
494         if (result != kStatus_Success)
495         {
496             return result;
497         }
498 
499         /* Enable all events before start doing DAA. */
500         result = I3C_BusMasterEnableEvents(masterDev, I3C_BUS_BROADCAST_ADDR,
501                                            ((uint8_t)kI3C_EventMR | (uint8_t)kI3C_EventHJ | (uint8_t)kI3C_EventIBI));
502         if (result != kStatus_Success)
503         {
504             return result;
505         }
506     }
507 
508     return result;
509 }
510 
511 /*!
512  * brief Bus master transfer CCC frame.
513  *
514  * Bus master call this function to transfer CCC frame, CCC frame command and data is prepared in @ref i3c_ccc_cmd_t
515  * structure.
516  *
517  * param masterDev Pointer to I3C master device.
518  * param command Pointer to ccc frame.
519  */
I3C_BusMasterSendCCC(i3c_device_t * masterDev,i3c_ccc_cmd_t * command)520 status_t I3C_BusMasterSendCCC(i3c_device_t *masterDev, i3c_ccc_cmd_t *command)
521 {
522     i3c_device_control_info_t *masterControlInfo = masterDev->devControlInfo;
523 
524     if (masterDev != masterDev->bus->currentMaster)
525     {
526         return kStatus_I3CBus_NotCurrentMaster;
527     }
528 
529     if (masterControlInfo->isSecondary)
530     {
531         return kStatus_I3CBus_Success;
532     }
533 
534     if (NULL == masterControlInfo->funcs->TransmitCCC)
535     {
536         return kStatus_I3CBus_MasterOpsUnsupport;
537     }
538 
539     return masterControlInfo->funcs->TransmitCCC(masterDev, command);
540 }
541 
542 /*!
543  * brief Bus master reset dynamic assigned address.
544  *
545  * Bus master call this function to reset dynamic assigned address, the operation could be done to all connected I3C
546  * devices by using slave address I3C_BUS_BROADCAST_ADDR or to a specific connected device by using the device's dynamic
547  * address.
548  *
549  * param masterDev Pointer to I3C master device.
550  * param slaveAddr Slave address, use I3C_BUS_BROADCAST_ADDR as broadcast address.
551  */
I3C_BusMasterResetDAA(i3c_device_t * masterDev,uint8_t slaveAddr)552 status_t I3C_BusMasterResetDAA(i3c_device_t *masterDev, uint8_t slaveAddr)
553 {
554     i3c_bus_t *i3cBus = masterDev->bus;
555     uint8_t addrStat;
556     status_t result;
557 
558     if (masterDev != masterDev->bus->currentMaster)
559     {
560         return kStatus_I3CBus_NotCurrentMaster;
561     }
562 
563     addrStat = I3C_BusGetAddrSlotStatus(i3cBus, slaveAddr);
564     if ((slaveAddr != I3C_BUS_BROADCAST_ADDR) && (addrStat != (uint8_t)kI3C_Bus_AddrSlot_I3CDev))
565     {
566         return kStatus_I3CBus_MasterOpsFailure;
567     }
568 
569     i3c_ccc_cmd_t rstDaaCmd = {0};
570 
571     rstDaaCmd.isRead   = false;
572     rstDaaCmd.destAddr = slaveAddr;
573     rstDaaCmd.cmdId    = I3C_BUS_CCC_RSTDAA((slaveAddr != I3C_BUS_BROADCAST_ADDR));
574 
575     result = I3C_BusMasterSendCCC(masterDev, &rstDaaCmd);
576     if (result == kStatus_Success)
577     {
578         if (slaveAddr != I3C_BUS_BROADCAST_ADDR)
579         {
580             /* Do not free current Controller's dynamic address. */
581             if (masterDev->info.dynamicAddr != slaveAddr)
582             {
583                 I3C_BusSetAddrSlot(i3cBus, slaveAddr, kI3C_Bus_AddrSlot_Free);
584             }
585         }
586         else
587         {
588             for (uint8_t i = 0; i <= I3C_BUS_MAX_ADDR; i++)
589             {
590                 addrStat = I3C_BusGetAddrSlotStatus(i3cBus, i);
591                 if ((addrStat == (uint8_t)kI3C_Bus_AddrSlot_I3CDev) && (masterDev->info.dynamicAddr != i))
592                 {
593                     I3C_BusSetAddrSlot(i3cBus, i, kI3C_Bus_AddrSlot_Free);
594                 }
595             }
596         }
597     }
598 
599     return result;
600 }
601 
602 /*!
603  * brief Bus master do dynamic address assignment.
604  *
605  * Bus master call this function to do dynamic address assignment to the I3C devices connected on bus.
606  *
607  * param masterDev Pointer to I3C master device.
608  */
I3C_BusMasterDoDAA(i3c_device_t * masterDev)609 status_t I3C_BusMasterDoDAA(i3c_device_t *masterDev)
610 {
611     i3c_device_control_info_t *masterControlInfo = masterDev->devControlInfo;
612     i3c_bus_t *i3cBus                            = masterDev->bus;
613     status_t result                              = kStatus_Success;
614 
615     if (masterDev != i3cBus->currentMaster)
616     {
617         return kStatus_I3CBus_NotCurrentMaster;
618     }
619 
620     result = masterControlInfo->funcs->ProceedDAA(masterDev);
621     if (result != kStatus_Success)
622     {
623         return result;
624     }
625 
626     /* Send defslvs command on bus if there's secondary master */
627     bool isSend              = false;
628     list_handle_t i3cDevList = &(i3cBus->i3cDevList);
629 
630     for (list_element_handle_t listItem = i3cDevList->head; listItem != NULL; listItem = listItem->next)
631     {
632         i3c_device_t *tmpDev = (i3c_device_t *)(void *)listItem;
633         if (tmpDev == masterDev)
634         {
635             continue;
636         }
637         else if ((tmpDev->info.bcr & I3C_BUS_DEV_BCR_DEV_ROLE_MASK) ==
638                  I3C_BUS_DEV_BCR_DEV_ROLE(I3C_BUS_DEV_BCR_DEV_MASTER))
639         {
640             isSend = true;
641             break;
642         }
643         else
644         {
645             /*Empty else to eliminate MISRA 15.7*/
646         }
647     }
648 
649     if (isSend)
650     {
651         result = I3C_BusMasterSendSlavesList(masterDev);
652     }
653 
654     return result;
655 }
656 
657 /*!
658  * brief Bus master set device dynamic address from static address.
659  *
660  * Bus master call this function to execute SETDASA CCC command to set device dynamic address from static address.
661  *
662  * param masterDev Pointer to I3C master device.
663  * param staticAddr Device static address.
664  * param initDynamicAddr Device initialized dynamic address.
665  */
I3C_BusMasterSetDynamicAddrFromStaticAddr(i3c_device_t * master,uint8_t staticAddr,uint8_t initDynamicAddr)666 status_t I3C_BusMasterSetDynamicAddrFromStaticAddr(i3c_device_t *master, uint8_t staticAddr, uint8_t initDynamicAddr)
667 {
668     i3c_ccc_cmd_t setdasaCCC = {0};
669     status_t result          = kStatus_Success;
670     uint8_t dynamicAddr      = initDynamicAddr << 1;
671 
672     setdasaCCC.cmdId    = I3C_BUS_CCC_SETDASA;
673     setdasaCCC.destAddr = staticAddr;
674     setdasaCCC.data     = &dynamicAddr;
675     setdasaCCC.dataSize = 1U;
676     setdasaCCC.isRead   = false;
677 
678     result = I3C_BusMasterSendCCC(master, &setdasaCCC);
679 
680     return result;
681 }
682 
683 /*!
684  * brief Bus master send slave list on bus.
685  *
686  * Bus master call this function to send slave list on bus to notify the secondary master.
687  *
688  * param masterDev Pointer to I3C master device.
689  */
I3C_BusMasterSendSlavesList(i3c_device_t * masterDev)690 status_t I3C_BusMasterSendSlavesList(i3c_device_t *masterDev)
691 {
692     i3c_bus_t *i3cBus = masterDev->bus;
693 
694     if (masterDev != i3cBus->currentMaster)
695     {
696         return kStatus_I3CBus_NotCurrentMaster;
697     }
698 
699     list_element_handle_t listItem;
700     list_handle_t i2cDevList = &(i3cBus->i2cDevList);
701     list_handle_t i3cDevList = &(i3cBus->i3cDevList);
702 
703     i3c_ccc_cmd_t defSlavesCmd = {0};
704     defSlavesCmd.isRead        = false;
705     defSlavesCmd.destAddr      = I3C_BUS_BROADCAST_ADDR;
706     defSlavesCmd.cmdId         = I3C_BUS_CCC_DEFSLVS;
707     uint8_t devCount           = 1;
708     status_t result            = kStatus_Success;
709 
710     for (listItem = i2cDevList->head; listItem != NULL; listItem = listItem->next)
711     {
712         devCount++;
713     }
714 
715     for (listItem = i3cDevList->head; listItem != NULL; listItem = listItem->next)
716     {
717         i3c_device_t *i3cDev = (i3c_device_t *)(void *)listItem;
718         if (i3cDev == masterDev)
719         {
720             continue;
721         }
722         else
723         {
724             devCount++;
725         }
726     }
727 
728     defSlavesCmd.dataSize = (uint16_t)sizeof(i3c_ccc_dev_t) * (uint16_t)devCount + 1U;
729     defSlavesCmd.data     = malloc(defSlavesCmd.dataSize);
730 
731     uint8_t *pData = defSlavesCmd.data;
732 
733     *pData                    = devCount;
734     i3c_ccc_dev_t *masterInfo = (i3c_ccc_dev_t *)(void *)&pData[1];
735     masterInfo->bcr           = masterDev->info.bcr;
736     masterInfo->dcr           = masterDev->info.dcr;
737     masterInfo->dynamicAddr   = masterDev->info.dynamicAddr << 1U;
738     masterInfo->staticAddr    = (I3C_BUS_BROADCAST_ADDR << 1U);
739 
740     i3c_ccc_dev_t *slaveInfo = (i3c_ccc_dev_t *)((uint32_t)&pData[1] + sizeof(i3c_ccc_dev_t));
741     for (listItem = i2cDevList->head; listItem != NULL; listItem = listItem->next)
742     {
743         slaveInfo->lvr        = ((i2c_device_t *)(void *)listItem)->lvr;
744         slaveInfo->staticAddr = (((i2c_device_t *)(void *)listItem)->staticAddr << 1U);
745         slaveInfo++;
746     }
747 
748     for (listItem = i3cDevList->head; listItem != NULL; listItem = listItem->next)
749     {
750         i3c_device_t *i3cDev = (i3c_device_t *)(void *)listItem;
751         if (i3cDev == masterDev)
752         {
753             continue;
754         }
755 
756         slaveInfo->dcr         = i3cDev->info.dcr;
757         slaveInfo->dynamicAddr = i3cDev->info.dynamicAddr << 1U;
758         slaveInfo->bcr         = i3cDev->info.bcr;
759         slaveInfo->staticAddr  = i3cDev->info.staticAddr << 1U;
760         slaveInfo++;
761     }
762 
763     result = I3C_BusMasterSendCCC(masterDev, &defSlavesCmd);
764 
765     free(defSlavesCmd.data);
766 
767     return result;
768 }
769 
770 /*!
771  * brief Bus master enable events.
772  *
773  * Bus master call this function to enable events on bus.
774  *
775  * param masterDev Pointer to I3C master device.
776  * param slaveAddr Slave address, use I3C_BUS_BROADCAST_ADDR as broadcast address.
777  * param busEvents Logic OR or member in @ref _i3c_bus_events.
778  */
I3C_BusMasterEnableEvents(i3c_device_t * masterDev,uint8_t slaveAddr,uint8_t busEvents)779 status_t I3C_BusMasterEnableEvents(i3c_device_t *masterDev, uint8_t slaveAddr, uint8_t busEvents)
780 {
781     i3c_ccc_cmd_t enEventsCmd = {0};
782     status_t result           = kStatus_Success;
783 
784     enEventsCmd.isRead   = false;
785     enEventsCmd.cmdId    = I3C_BUS_CCC_ENEC((slaveAddr != I3C_BUS_BROADCAST_ADDR));
786     enEventsCmd.destAddr = slaveAddr;
787     enEventsCmd.data     = &busEvents;
788     enEventsCmd.dataSize = 1U;
789 
790     result = I3C_BusMasterSendCCC(masterDev, &enEventsCmd);
791 
792     return result;
793 }
794 
795 /*!
796  * brief Bus master disable events.
797  *
798  * Bus master call this function to disable events on bus.
799  *
800  * param masterDev Pointer to I3C master device.
801  * param slaveAddr Slave address, use I3C_BUS_BROADCAST_ADDR as broadcast address.
802  * param busEvents Logic OR or member in @ref _i3c_bus_events.
803  */
I3C_BusMasterDisableEvents(i3c_device_t * masterDev,uint8_t slaveAddr,uint8_t busEvents)804 status_t I3C_BusMasterDisableEvents(i3c_device_t *masterDev, uint8_t slaveAddr, uint8_t busEvents)
805 {
806     i3c_ccc_cmd_t disEventsCmd = {0};
807     status_t result            = kStatus_Success;
808 
809     disEventsCmd.isRead   = false;
810     disEventsCmd.cmdId    = I3C_BUS_CCC_DISEC((slaveAddr != I3C_BUS_BROADCAST_ADDR));
811     disEventsCmd.destAddr = slaveAddr;
812     disEventsCmd.data     = &busEvents;
813     disEventsCmd.dataSize = 1U;
814 
815     result = I3C_BusMasterSendCCC(masterDev, &disEventsCmd);
816 
817     return result;
818 }
819 
820 /*!
821  * brief Bus master get device information for a specific I3C device.
822  *
823  * Bus master call this function to get device information for a specific I3C device.
824  *
825  * param masterDev Pointer to I3C master device.
826  * param slaveAddr Slave address, dynamic assigned address for a device.
827  * param devInfo Input pointer to structure i3c_device_information_t to store the read out device information.
828  */
I3C_BusMasterGetDeviceInfo(i3c_device_t * masterDev,uint8_t slaveAddr,i3c_device_information_t * devInfo)829 status_t I3C_BusMasterGetDeviceInfo(i3c_device_t *masterDev, uint8_t slaveAddr, i3c_device_information_t *devInfo)
830 {
831     status_t result = kStatus_Success;
832 
833     devInfo->dynamicAddr = slaveAddr;
834 
835     result = I3C_BusMasterGetPID(masterDev, devInfo);
836     if (result != kStatus_Success)
837     {
838         return result;
839     }
840 
841     result = I3C_BusMasterGetBCR(masterDev, devInfo);
842     if (result != kStatus_Success)
843     {
844         return result;
845     }
846 
847     result = I3C_BusMasterGetDCR(masterDev, devInfo);
848     if (result != kStatus_Success)
849     {
850         return result;
851     }
852 
853     result = I3C_BusMasterGetMaxReadLength(masterDev, devInfo);
854     if (result != kStatus_Success)
855     {
856         return result;
857     }
858     result = I3C_BusMasterGetMaxWriteLength(masterDev, devInfo);
859     if (result != kStatus_Success)
860     {
861         return result;
862     }
863 
864     if ((devInfo->bcr & I3C_BUS_DEV_BCR_MODE_MASK) != 0U)
865     {
866         result = I3C_BusMasterGetHDRCapability(masterDev, devInfo);
867         if (result != kStatus_Success)
868         {
869             return result;
870         }
871     }
872 
873     return result;
874 }
875 
I3C_BusMasterRegisterDevIBI(i3c_device_t * masterDev,i3c_device_t * i3cDev,i3c_device_ibi_info_t * devIbiInfo)876 status_t I3C_BusMasterRegisterDevIBI(i3c_device_t *masterDev, i3c_device_t *i3cDev, i3c_device_ibi_info_t *devIbiInfo)
877 {
878     i3c_bus_t *i3cBus = masterDev->bus;
879 
880     if (masterDev != i3cBus->currentMaster)
881     {
882         return kStatus_I3CBus_NotCurrentMaster;
883     }
884 
885     i3c_device_control_info_t *masterControlInfo = masterDev->devControlInfo;
886     i3cDev->ibiInfo                              = devIbiInfo;
887 
888     if (I3C_BusGetAddrSlotStatus(i3cBus, i3cDev->info.dynamicAddr) == (uint8_t)kI3C_Bus_AddrSlot_I3CDev)
889     {
890         masterControlInfo->funcs->RegisterIBI(masterDev, i3cDev->info.dynamicAddr);
891     }
892     else
893     {
894         return kStatus_I3CBus_InvalidOps;
895     }
896 
897     return kStatus_Success;
898 }
899 /*!
900  * brief Bus master handle in-band-interrupt event.
901  *
902  * Bus master call this function to handle in-band-interrupt event.
903  *
904  * param masterDev Pointer to I3C master device.
905  * param ibiAddress slave address which requests the IBI.
906  * param ibiData Pointer to the ibi data buffer.
907  * param payloadSize ibi data buffer size.
908  */
I3C_BusMasterHandleIBI(i3c_device_t * masterDev,uint8_t ibiAddress,void * ibiData,uint32_t payloadSize)909 status_t I3C_BusMasterHandleIBI(i3c_device_t *masterDev, uint8_t ibiAddress, void *ibiData, uint32_t payloadSize)
910 {
911     i3c_bus_t *i3cBus = masterDev->bus;
912 
913     if (masterDev != i3cBus->currentMaster)
914     {
915         return kStatus_I3CBus_NotCurrentMaster;
916     }
917 
918     list_element_handle_t listItem;
919     list_handle_t i3cDevList = &(i3cBus->i3cDevList);
920     i3c_device_t *i3cDev     = NULL;
921 
922     for (listItem = i3cDevList->head; listItem != NULL; listItem = listItem->next)
923     {
924         i3cDev = (i3c_device_t *)(void *)listItem;
925         if (i3cDev == masterDev)
926         {
927             continue;
928         }
929 
930         if (i3cDev->info.dynamicAddr == ibiAddress)
931         {
932             break;
933         }
934     }
935 
936     if (i3cDev != NULL)
937     {
938         assert(i3cDev->ibiInfo != NULL);
939         assert(i3cDev->ibiInfo->maxPayloadLength >= payloadSize);
940         assert(i3cDev->ibiInfo->ibiHandler != NULL);
941 
942         i3cDev->ibiInfo->ibiHandler(i3cDev, ibiData, payloadSize);
943     }
944 
945     return kStatus_Success;
946 }
947 
948 /*!
949  * brief Bus master do data transfer to I2C device.
950  *
951  * Bus master call this function to transfer data to connected I2C device.
952  *
953  * param masterDev Pointer to I3C master device.
954  * param i2cDev Pointer to the I2C device master do transfer.
955  * param xfer Pointer to bus transfer.
956  */
I3C_BusMasterDoTransferToI2CDev(i3c_device_t * masterDev,i2c_device_t * i2cDev,i3c_bus_transfer_t * xfer)957 status_t I3C_BusMasterDoTransferToI2CDev(i3c_device_t *masterDev, i2c_device_t *i2cDev, i3c_bus_transfer_t *xfer)
958 {
959     i3c_bus_t *i3cBus = masterDev->bus;
960 
961     if (masterDev != i3cBus->currentMaster)
962     {
963         return kStatus_I3CBus_NotCurrentMaster;
964     }
965 
966     status_t result                              = kStatus_Success;
967     i3c_device_control_info_t *masterControlInfo = masterDev->devControlInfo;
968 
969     if (I3C_BusGetAddrSlotStatus(i3cBus, i2cDev->staticAddr) == (uint8_t)kI3C_Bus_AddrSlot_I2CDev)
970     {
971         result = masterControlInfo->funcs->DoI2CTransfer(i2cDev, xfer);
972     }
973     else
974     {
975         result = kStatus_I3CBus_InvalidOps;
976     }
977 
978     return result;
979 }
980 
981 /*!
982  * brief Bus master do data transfer to I3C device.
983  *
984  * Bus master call this function to transfer data to connected I3C device.
985  *
986  * param masterDev Pointer to I3C master device.
987  * param i3cDev Pointer to the I3C device master do transfer.
988  * param xfer Pointer to bus transfer.
989  */
I3C_BusMasterDoTransferToI3CDev(i3c_device_t * masterDev,i3c_device_t * i3cDev,i3c_bus_transfer_t * xfer)990 status_t I3C_BusMasterDoTransferToI3CDev(i3c_device_t *masterDev, i3c_device_t *i3cDev, i3c_bus_transfer_t *xfer)
991 {
992     i3c_bus_t *i3cBus = masterDev->bus;
993 
994     if (masterDev != i3cBus->currentMaster)
995     {
996         return kStatus_I3CBus_NotCurrentMaster;
997     }
998 
999     status_t result                              = kStatus_Success;
1000     i3c_device_control_info_t *masterControlInfo = masterDev->devControlInfo;
1001 
1002     if (I3C_BusGetAddrSlotStatus(i3cBus, i3cDev->info.dynamicAddr) == (uint8_t)kI3C_Bus_AddrSlot_I3CDev)
1003     {
1004         result = masterControlInfo->funcs->DoI3CTransfer(i3cDev, xfer);
1005     }
1006     else
1007     {
1008         result = kStatus_I3CBus_InvalidOps;
1009     }
1010 
1011     return result;
1012 }
1013 
1014 /*!
1015  * brief Create I2C slave structure on bus.
1016  *
1017  * This function will create I2C device bus structure, initialize the slave according to bus characteristics, install
1018  * device information including static address, lvr and device control information.
1019  *
1020  * param i2cDev Pointer to device structure creating as I2C device.
1021  * param bus Pointer to bus structure.
1022  * param staticAddr Static address of the I2C device
1023  * param lvr legacy virtual register value of the device.
1024  * param devControlInfo Pointer to device control information structure.
1025  */
I3C_BusI2CSlaveCreate(i2c_device_t * i2cDev,i3c_bus_t * bus,uint8_t staticAddr,uint8_t lvr,i2c_device_control_info_t * devControlInfo)1026 status_t I3C_BusI2CSlaveCreate(
1027     i2c_device_t *i2cDev, i3c_bus_t *bus, uint8_t staticAddr, uint8_t lvr, i2c_device_control_info_t *devControlInfo)
1028 {
1029     (void)memset(i2cDev, 0, sizeof(*i2cDev));
1030 
1031     i2cDev->bus            = bus;
1032     i2cDev->staticAddr     = staticAddr;
1033     i2cDev->lvr            = lvr;
1034     i2cDev->devControlInfo = devControlInfo;
1035 
1036     i3c_device_t *masterDev = NULL;
1037     status_t result         = kStatus_Success;
1038 
1039     if (bus != NULL)
1040     {
1041         masterDev = (i3c_device_t *)bus->currentMaster;
1042     }
1043 
1044     if (masterDev != NULL)
1045     {
1046         /*Add device to bus i2c device list */
1047         I3C_BusAddI2CDev(bus, i2cDev);
1048     }
1049 
1050     if ((devControlInfo != NULL) && (devControlInfo->funcs != NULL) && (devControlInfo->funcs->Init != NULL))
1051     {
1052         result = devControlInfo->funcs->Init(i2cDev);
1053     }
1054 
1055     return result;
1056 }
1057 
1058 /*!
1059  * brief Create I3C slave structure on bus.
1060  *
1061  * This function will create I3C device bus structure, initialize the slave according to bus characteristics, install
1062  * device information and device control information.
1063  *
1064  * param i3cDev Pointer to device structure creating as I3C device.
1065  * param bus Pointer to bus structure.
1066  * param devInfo Pointer to device information structure
1067  * param devControlInfo Pointer to device control information structure.
1068  */
I3C_BusI3CSlaveCreate(i3c_device_t * i3cDev,i3c_bus_t * bus,i3c_device_information_t * devInfo,i3c_device_ibi_info_t * ibiInfo,i3c_device_control_info_t * devControlInfo)1069 status_t I3C_BusI3CSlaveCreate(i3c_device_t *i3cDev,
1070                                i3c_bus_t *bus,
1071                                i3c_device_information_t *devInfo,
1072                                i3c_device_ibi_info_t *ibiInfo,
1073                                i3c_device_control_info_t *devControlInfo)
1074 {
1075     (void)memset(i3cDev, 0, sizeof(*i3cDev));
1076 
1077     i3cDev->bus            = bus;
1078     i3cDev->ibiInfo        = ibiInfo;
1079     i3cDev->info           = *devInfo;
1080     i3cDev->devControlInfo = devControlInfo;
1081     status_t result        = kStatus_Success;
1082 
1083     i3c_device_t *masterDev = NULL;
1084 
1085     if (bus != NULL)
1086     {
1087         masterDev = (i3c_device_t *)bus->currentMaster;
1088     }
1089 
1090     if (masterDev != NULL)
1091     {
1092         /*Add device to bus i3c device list */
1093         I3C_BusAddI3CDev(bus, i3cDev);
1094     }
1095 
1096     if ((devControlInfo != NULL) && (devControlInfo->funcs != NULL) && (devControlInfo->funcs->Init != NULL))
1097     {
1098         result = devControlInfo->funcs->Init(i3cDev);
1099     }
1100 
1101     return result;
1102 }
1103 
1104 /*!
1105  * brief I3C slave device request Hot Join on bus.
1106  *
1107  * param i3cDev Pointer to device structure creating as I3C device.
1108  */
I3C_BusSlaveRequestHotJoin(i3c_device_t * i3cDev)1109 status_t I3C_BusSlaveRequestHotJoin(i3c_device_t *i3cDev)
1110 {
1111     status_t result = kStatus_Success;
1112 
1113     if ((i3cDev->devControlInfo != NULL) && (i3cDev->devControlInfo->funcs != NULL) &&
1114         (i3cDev->devControlInfo->funcs->HotJoin != NULL))
1115     {
1116         i3cDev->devControlInfo->funcs->HotJoin(i3cDev);
1117     }
1118     else
1119     {
1120         result = kStatus_I3CBus_SlaveOpsNotSupported;
1121     }
1122 
1123     return result;
1124 }
1125 
1126 /*!
1127  * brief I3C slave device request mastership on bus.
1128  *
1129  * param i3cDev Pointer to device structure creating as I3C device.
1130  */
I3C_BusSlaveRequestMasterShip(i3c_device_t * i3cDev)1131 status_t I3C_BusSlaveRequestMasterShip(i3c_device_t *i3cDev)
1132 {
1133     status_t result = kStatus_Success;
1134 
1135     if ((i3cDev->devControlInfo != NULL) && (i3cDev->devControlInfo->funcs != NULL) &&
1136         (i3cDev->devControlInfo->funcs->RequestMastership != NULL))
1137     {
1138         i3cDev->devControlInfo->funcs->RequestMastership(i3cDev);
1139     }
1140     else
1141     {
1142         result = kStatus_I3CBus_SlaveOpsNotSupported;
1143     }
1144 
1145     return result;
1146 }
1147 
1148 /*!
1149  * brief I3C slave request IBI events.
1150  *
1151  * param i3cDev Pointer to device structure creating as I3C device.
1152  * param data Pointer to data buffer to be sent in IBI event.
1153  * param dataSize data size of IBI data.
1154  */
I3C_BusSlaveRequestIBI(i3c_device_t * i3cDev,void * data,size_t dataSize)1155 status_t I3C_BusSlaveRequestIBI(i3c_device_t *i3cDev, void *data, size_t dataSize)
1156 {
1157     status_t result = kStatus_Success;
1158 
1159     if ((i3cDev->devControlInfo != NULL) && (i3cDev->devControlInfo->funcs != NULL) &&
1160         (i3cDev->devControlInfo->funcs->RequestMastership != NULL))
1161     {
1162         i3cDev->devControlInfo->funcs->RequestIBI(i3cDev, data, dataSize);
1163     }
1164     else
1165     {
1166         result = kStatus_I3CBus_SlaveOpsNotSupported;
1167     }
1168 
1169     return result;
1170 }
1171