diff --git a/Libraries/CMSIS/Device/Maxim/MAX32657/Include/i3c_regs.h b/Libraries/CMSIS/Device/Maxim/MAX32657/Include/i3c_regs.h index 6e624a98c9a..8aba8f5c292 100644 --- a/Libraries/CMSIS/Device/Maxim/MAX32657/Include/i3c_regs.h +++ b/Libraries/CMSIS/Device/Maxim/MAX32657/Include/i3c_regs.h @@ -1042,9 +1042,27 @@ typedef struct { #define MXC_F_I3C_CAPABILITIES_CCCHANDLE_POS 12 /**< CAPABILITIES_CCCHANDLE Position */ #define MXC_F_I3C_CAPABILITIES_CCCHANDLE ((uint32_t)(0xFUL << MXC_F_I3C_CAPABILITIES_CCCHANDLE_POS)) /**< CAPABILITIES_CCCHANDLE Mask */ +#define MXC_V_I3C_CAPABILITIES_CCCHANDLE_BASIC ((uint32_t)0x1UL) /**< CAPABILITIES_CCCHANDLE_BASIC Mask */ +#define MXC_S_I3C_CAPABILITIES_CCCHANDLE_BASIC (MXC_V_I3C_CAPABILITIES_CCCHANDLE_BASIC << MXC_F_I3C_CAPABILITIES_CCCHANDLE_POS) /**< CAPABILITIES_CCCHANDLE_BASIC Setting */ +#define MXC_V_I3C_CAPABILITIES_CCCHANDLE_LIMITS ((uint32_t)0x2UL) /**< CAPABILITIES_CCCHANDLE_LIMITS Mask */ +#define MXC_S_I3C_CAPABILITIES_CCCHANDLE_LIMITS (MXC_V_I3C_CAPABILITIES_CCCHANDLE_LIMITS << MXC_F_I3C_CAPABILITIES_CCCHANDLE_POS) /**< CAPABILITIES_CCCHANDLE_LIMITS Setting */ +#define MXC_V_I3C_CAPABILITIES_CCCHANDLE_INTACT ((uint32_t)0x4UL) /**< CAPABILITIES_CCCHANDLE_INTACT Mask */ +#define MXC_S_I3C_CAPABILITIES_CCCHANDLE_INTACT (MXC_V_I3C_CAPABILITIES_CCCHANDLE_INTACT << MXC_F_I3C_CAPABILITIES_CCCHANDLE_POS) /**< CAPABILITIES_CCCHANDLE_INTACT Setting */ +#define MXC_V_I3C_CAPABILITIES_CCCHANDLE_VENDOR ((uint32_t)0x8UL) /**< CAPABILITIES_CCCHANDLE_VENDOR Mask */ +#define MXC_S_I3C_CAPABILITIES_CCCHANDLE_VENDOR (MXC_V_I3C_CAPABILITIES_CCCHANDLE_VENDOR << MXC_F_I3C_CAPABILITIES_CCCHANDLE_POS) /**< CAPABILITIES_CCCHANDLE_VENDOR Setting */ #define MXC_F_I3C_CAPABILITIES_IBI_MR_HJ_POS 16 /**< CAPABILITIES_IBI_MR_HJ Position */ #define MXC_F_I3C_CAPABILITIES_IBI_MR_HJ ((uint32_t)(0x1FUL << MXC_F_I3C_CAPABILITIES_IBI_MR_HJ_POS)) /**< CAPABILITIES_IBI_MR_HJ Mask */ +#define MXC_V_I3C_CAPABILITIES_IBI_MR_HJ_IBI ((uint32_t)0x1UL) /**< CAPABILITIES_IBI_MR_HJ_IBI Mask */ +#define MXC_S_I3C_CAPABILITIES_IBI_MR_HJ_IBI (MXC_V_I3C_CAPABILITIES_IBI_MR_HJ_IBI << MXC_F_I3C_CAPABILITIES_IBI_MR_HJ_POS) /**< CAPABILITIES_IBI_MR_HJ_IBI Setting */ +#define MXC_V_I3C_CAPABILITIES_IBI_MR_HJ_IBI_PAYLOAD ((uint32_t)0x2UL) /**< CAPABILITIES_IBI_MR_HJ_IBI_PAYLOAD Mask */ +#define MXC_S_I3C_CAPABILITIES_IBI_MR_HJ_IBI_PAYLOAD (MXC_V_I3C_CAPABILITIES_IBI_MR_HJ_IBI_PAYLOAD << MXC_F_I3C_CAPABILITIES_IBI_MR_HJ_POS) /**< CAPABILITIES_IBI_MR_HJ_IBI_PAYLOAD Setting */ +#define MXC_V_I3C_CAPABILITIES_IBI_MR_HJ_CREQ ((uint32_t)0x4UL) /**< CAPABILITIES_IBI_MR_HJ_CREQ Mask */ +#define MXC_S_I3C_CAPABILITIES_IBI_MR_HJ_CREQ (MXC_V_I3C_CAPABILITIES_IBI_MR_HJ_CREQ << MXC_F_I3C_CAPABILITIES_IBI_MR_HJ_POS) /**< CAPABILITIES_IBI_MR_HJ_CREQ Setting */ +#define MXC_V_I3C_CAPABILITIES_IBI_MR_HJ_HOTJOIN ((uint32_t)0x8UL) /**< CAPABILITIES_IBI_MR_HJ_HOTJOIN Mask */ +#define MXC_S_I3C_CAPABILITIES_IBI_MR_HJ_HOTJOIN (MXC_V_I3C_CAPABILITIES_IBI_MR_HJ_HOTJOIN << MXC_F_I3C_CAPABILITIES_IBI_MR_HJ_POS) /**< CAPABILITIES_IBI_MR_HJ_HOTJOIN Setting */ +#define MXC_V_I3C_CAPABILITIES_IBI_MR_HJ_BAMATCH ((uint32_t)0x10UL) /**< CAPABILITIES_IBI_MR_HJ_BAMATCH Mask */ +#define MXC_S_I3C_CAPABILITIES_IBI_MR_HJ_BAMATCH (MXC_V_I3C_CAPABILITIES_IBI_MR_HJ_BAMATCH << MXC_F_I3C_CAPABILITIES_IBI_MR_HJ_POS) /**< CAPABILITIES_IBI_MR_HJ_BAMATCH Setting */ #define MXC_F_I3C_CAPABILITIES_TIMECTRL_POS 21 /**< CAPABILITIES_TIMECTRL Position */ #define MXC_F_I3C_CAPABILITIES_TIMECTRL ((uint32_t)(0x1UL << MXC_F_I3C_CAPABILITIES_TIMECTRL_POS)) /**< CAPABILITIES_TIMECTRL Mask */ diff --git a/Libraries/CMSIS/Device/Maxim/MAX32657/Include/max32657.h b/Libraries/CMSIS/Device/Maxim/MAX32657/Include/max32657.h index ce758f9c72e..bf290ac3241 100644 --- a/Libraries/CMSIS/Device/Maxim/MAX32657/Include/max32657.h +++ b/Libraries/CMSIS/Device/Maxim/MAX32657/Include/max32657.h @@ -611,11 +611,11 @@ We may want to handle GET_IRQ better... #define MXC_I3C_FIFO_DEPTH (8) // TODO(ME30): Confirm this is correct. /* Non-secure Mapping */ -#define MXC_BASE_I3C_NS ((uint32_t)0x4001D000UL) +#define MXC_BASE_I3C_NS ((uint32_t)0x40018000UL) #define MXC_I3C_NS ((mxc_i3c_regs_t *)MXC_BASE_I3C_NS) /* Secure Mapping */ -#define MXC_BASE_I3C_S ((uint32_t)0x5001D000UL) +#define MXC_BASE_I3C_S ((uint32_t)0x50018000UL) #define MXC_I3C_S ((mxc_i3c_regs_t *)MXC_BASE_I3C_S) #if IS_SECURE_ENVIRONMENT @@ -629,7 +629,6 @@ We may want to handle GET_IRQ better... #define MXC_I3C_GET_BASE(i) ((i) == MXC_I3C ? 0 : -1) #define MXC_I3C_GET_IDX(p) ((p) == MXC_I3C ? 0 : -1) - /******************************************************************************/ /* DMA */ #define MXC_DMA_CHANNELS (4) diff --git a/Libraries/PeriphDrivers/Include/MAX32657/i3c.h b/Libraries/PeriphDrivers/Include/MAX32657/i3c.h index 825e461aff5..b0aed5390db 100644 --- a/Libraries/PeriphDrivers/Include/MAX32657/i3c.h +++ b/Libraries/PeriphDrivers/Include/MAX32657/i3c.h @@ -22,8 +22,8 @@ ******************************************************************************/ /* Define to prevent redundant inclusion */ -#ifndef LIBRARIES_PERIPHDRIVERS_INCLUDE_MAX32657_I2C_H_ -#define LIBRARIES_PERIPHDRIVERS_INCLUDE_MAX32657_I2C_H_ +#ifndef LIBRARIES_PERIPHDRIVERS_INCLUDE_MAX32657_I3C_H_ +#define LIBRARIES_PERIPHDRIVERS_INCLUDE_MAX32657_I3C_H_ #include #include @@ -42,7 +42,6 @@ extern "C" { */ /***** Definitions *****/ -typedef struct _i3c_controller_t mxc_i3c_controller_t; typedef struct _i3c_target_t mxc_i3c_target_t; typedef struct _i2c_target_t mxc_i3c_i2c_target_t; @@ -62,7 +61,7 @@ typedef enum { MXC_I3C_HIGH_KEEPER_ON_CHIP = MXC_S_I3C_MCONFIG_HKEEP_ONCHIP_SCL_SDA, ///< SCL and SDA pads ///< have weak pull-ups MXC_I3C_HIGH_KEEPER_EXT_SDA = MXC_S_I3C_MCONFIG_HKEEP_EXTERNAL_SDA, ///< External high-keeper - ///< support for SDA signal + ///< support for SDA signal MXC_I3C_HIGH_KEEPER_EXT_SCL_SDA = MXC_S_I3C_MCONFIG_HKEEP_EXTERNAL_SCL_SDA, ///< External high-keeper support for SCL and SDA signals } mxc_i3c_high_keeper_t; @@ -92,10 +91,10 @@ typedef enum { * */ typedef enum { - MXC_I3C_IBI_TYPE_NONE = MXC_V_I3C_MSTATUS_IBITYPE_NONE, ///< - MXC_I3C_IBI_TYPE_IBI = MXC_V_I3C_MSTATUS_IBITYPE_IBI, ///< - MXC_I3C_IBI_TYPE_CONTROLLER_REQ = MXC_V_I3C_MSTATUS_IBITYPE_CONTROLLER_REQ, ///< - MXC_I3C_IBI_TYPE_HOTJOIN_REQ = MXC_V_I3C_MSTATUS_IBITYPE_HOTJOIN_REQ, ///< + MXC_I3C_IBI_TYPE_NONE = MXC_V_I3C_MSTATUS_IBITYPE_NONE, ///< + MXC_I3C_IBI_TYPE_IBI = MXC_V_I3C_MSTATUS_IBITYPE_IBI, ///< + MXC_I3C_IBI_TYPE_CONTROLLER_REQ = MXC_V_I3C_MSTATUS_IBITYPE_CONTROLLER_REQ, ///< + MXC_I3C_IBI_TYPE_HOTJOIN_REQ = MXC_V_I3C_MSTATUS_IBITYPE_HOTJOIN_REQ, ///< } mxc_i3c_ibi_type_t; /** @@ -111,7 +110,8 @@ typedef enum { * @return 0 if the IBI should not be acknowledged (NACK), non-zero to * acknowledge the IBI. */ -typedef int (*mxc_i3c_ibi_ack_t)(mxc_i3c_regs_t *i3c, unsigned char dynAddr, mxc_i3c_ibi_type_t ibiType); +typedef int (*mxc_i3c_ibi_ack_t)(mxc_i3c_regs_t *i3c, unsigned char dynAddr, + mxc_i3c_ibi_type_t ibiType); /** * @brief IBI request callback. Called after an IBI is acknowledged by the application @@ -119,10 +119,26 @@ typedef int (*mxc_i3c_ibi_ack_t)(mxc_i3c_regs_t *i3c, unsigned char dynAddr, mxc * * @param i3c Pointer to I3C registers. * @param target Pointer to I3C target requesting an IBI. - * */ typedef void (*mxc_i3c_ibi_req_t)(mxc_i3c_regs_t *i3c, mxc_i3c_target_t *target); +/** + * @brief IBI payload request callback. Write additional byte to \a byte. + * + * This function will be called as long as non-zero is returned. + * + * @return Non-zero if a byte is written to \a byte, 0 to indicate no more additional + * bytes left to send. + */ +typedef int (*mxc_i3c_ibi_getbyte_t)(mxc_i3c_regs_t *i3c, unsigned char *byte); + +/** + * @brief CCC request callback. + * + * Called when the received CCC is not handled automatically. + */ +typedef void (*mxc_i3c_ccc_cb_t)(mxc_i3c_regs_t *i3c, unsigned char ccc); + /** * @brief The information required to perform a complete I2C transaction as * the bus master. @@ -146,16 +162,6 @@ struct _i2c_target_t { uint8_t staticAddr; ///< Target address of the I2C target. }; -struct _i3c_controller_t { - mxc_i3c_regs_t *regs; ///< Pointer to regs of this I3C instance. - mxc_i3c_target_t *i3cTargets; ///< List of I3C targets. - uint8_t numI3CTargets; ///< Number of I3C targets. - mxc_i3c_i2c_target_t *i2cTargets; ///< List of I2C targets. - uint8_t numI2CTargets; ///< Number of I2C targets. - mxc_i3c_ibi_ack_t ibiAckCB; ///< IBI acknowledge callback. - mxc_i3c_ibi_req_t ibiReqCB; ///< IBI request callback. -}; - /***** Function Prototypes *****/ /* ************************************************************************* */ @@ -172,17 +178,18 @@ struct _i3c_controller_t { * @param i3c Pointer to I3C registers (selects the I3C block used). * @param targetMode Whether to put the device in controller or target mode. Use * non-zero. + * @param staticAddr I2C-style static address. Has no effect if the address is hardwired. * * @return Success/Fail, see \ref MXC_Error_Codes for a list of return codes. */ -int MXC_I3C_Init(mxc_i3c_regs_t *i3c, int targetMode); +int MXC_I3C_Init(mxc_i3c_regs_t *i3c, int targetMode, uint8_t staticAddr); /** * @brief Set the I3C targets connected to this controller instance. * - * @param i3c Pointer to I3C registers. - * @param targets Pointer to I3C targets. - * @param numTargets Number of I3C targets. + * @param i3c Pointer to I3C registers. + * @param targets Pointer to I3C targets. + * @param numTargets Number of I3C targets. * * @return Success/Fail, see \ref MXC_Error_Codes for a list of return codes. */ @@ -191,14 +198,42 @@ int MXC_I3C_SetI3CTargets(mxc_i3c_regs_t *i3c, mxc_i3c_target_t *targets, uint8_ /** * @brief Set the I3C targets connected to this controller instance. * - * @param i3c Pointer to I3C registers. - * @param targets Pointer to I2C targets. - * @param numTargets Number of I2C targets. + * @param i3c Pointer to I3C registers. + * @param targets Pointer to I2C targets. + * @param numTargets Number of I2C targets. * * @return Success/Fail, see \ref MXC_Error_Codes for a list of return codes. */ int MXC_I3C_SetI2CTargets(mxc_i3c_regs_t *i3c, mxc_i3c_i2c_target_t *targets, uint8_t numTargets); +/** + * @brief Set IBI handlers. Only required for controller mode. + * + * @param i3c Pointer to I3C registers. + * @param ackCb Called when an IBI needs to be ACKed or NACKed. + * @param reqCb Called when mandatory and additional bytes are read. + */ +void MXC_I3C_SetIBICallback(mxc_i3c_regs_t *i3c, mxc_i3c_ibi_ack_t ackCb, mxc_i3c_ibi_req_t reqCb); + +/** + * @brief Set IBI payload callback. Only required for target mode. + * + * Application will write IBI payload using this callback. + * + * @param i3c Pointer to I3C registers. + * @param payloadCb Called when application needs provide data bytes to send with the + * IBI. + */ +void MXC_I3C_SetIBIPayloadCallback(mxc_i3c_regs_t *i3c, mxc_i3c_ibi_getbyte_t payloadCb); + +/** + * @brief Set CCC command callback. Only required for target mode. + * + * @param i3c Pointer to I3C registers. + * @param cccCb Called when application needs to handle a CCC command. + */ +void MXC_I3C_SetCCCCallback(mxc_i3c_regs_t *i3c, mxc_i3c_ccc_cb_t cccCb); + /** * @brief Broadcast a Common Command Code (CCC) to all I3C targets. * @@ -211,10 +246,11 @@ int MXC_I3C_SetI2CTargets(mxc_i3c_regs_t *i3c, mxc_i3c_i2c_target_t *targets, ui * * @return Success/Fail, see \ref MXC_Error_Codes for a list of return codes. */ -int MXC_I3C_BroadcastCCC(mxc_i3c_regs_t *i3c, unsigned char ccc, int defByte, unsigned char *data, int len); +int MXC_I3C_BroadcastCCC(mxc_i3c_regs_t *i3c, unsigned char ccc, int defByte, unsigned char *data, + int len); /** - * @brief Perform dynamic address assignment. + * @brief Perform dynamic address assignment. * * @param i3c Pointer to I3C registers. * @@ -223,7 +259,60 @@ int MXC_I3C_BroadcastCCC(mxc_i3c_regs_t *i3c, unsigned char ccc, int defByte, un int MXC_I3C_PerformDAA(mxc_i3c_regs_t *i3c); /** - * @brief Read multiple bytes from an I2C target in blocking mode. + * @brief Generate a hot-join request in target mode. + * + * Hot-Join will only be generated if the target is powered on after the bus is + * configured or physically connected to an already configured bus. If the active + * controller disables the Hot-Join events through DISEC CCCs, it will not be + * generated either. + * + * @param i3c Pointer to I3C registers. + * + * @return E_SUCCESS if request is submitted. E_BAD_STATE if operation is not allowed in + * the current state. E_NOT_SUPPORTED is returned in case HotJoin generation is not + * supported. Note that return value of E_SUCCESS does not guarantee a successful + * Hot-Join since the decision is up to the controller. + */ +int MXC_I3C_HotJoin(mxc_i3c_regs_t *i3c); + +/** + * @brief Generate an In-Band Interrupt in target mode. + * + * @param i3c Pointer to I3C registers. + * @param mdb Mandatory data byte to be sent if IBI is acknowledged. + * @param getByteCb Callback to get additional databytes from the application. Pass NULL + * if no additional data bytes except \a mdb will be sent with the IBI + * request. + * + * @return E_SUCCESS if request is submitted. E_BAD_STATE if operation is not allowed in + * the current state. E_NOT_SUPPORTED is returned in case IBI generation is not + * supported. Note that return value of E_SUCCESS does not guarantee that the + * request has been acknowledged. + */ +int MXC_I3C_RequestIBI(mxc_i3c_regs_t *i3c, unsigned char mdb, mxc_i3c_ibi_getbyte_t getByteCb); + +/** + * @brief Enter offline mode and stop participating on the bus. + * + * Offline mode is only allowed if the target has already been assigned a dynamic address. + * + * @param i3c Pointer to I3C registers. + * + * @return E_SUCCESS if device switches to offline mode, E_BAD_STATE otherwise. + */ +int MXC_I3C_Standby(mxc_i3c_regs_t *i3c); + +/** + * @brief Exit offline mode using previously assigned dynamic address. + * + * @param i3c Pointer to I3C registers. + * + * @return E_SUCCESS if device comes out of offline mode, E_BAD_STATE otherwise. + */ +int MXC_I3C_Wakeup(mxc_i3c_regs_t *i3c); + +/** + * @brief Read multiple bytes from an I2C target in blocking mode. * * @param i3c Pointer to I3C registers. * @param staticAddr 7-bit target address to read from. @@ -233,10 +322,11 @@ int MXC_I3C_PerformDAA(mxc_i3c_regs_t *i3c); * * @return Success/Fail, see \ref MXC_Error_Codes for a list of return codes. */ -int MXC_I3C_ReadI2CBlocking(mxc_i3c_regs_t *i3c, unsigned char staticAddr, unsigned char *bytes, unsigned int *len); +int MXC_I3C_ReadI2CBlocking(mxc_i3c_regs_t *i3c, unsigned char staticAddr, unsigned char *bytes, + unsigned int *len); /** - * @brief Write multiple bytes to an I2C target in blocking mode. + * @brief Write multiple bytes to an I2C target in blocking mode. * * @param i3c Pointer to I3C registers. * @param staticAddr 7-bit target address to read from. @@ -246,18 +336,66 @@ int MXC_I3C_ReadI2CBlocking(mxc_i3c_regs_t *i3c, unsigned char staticAddr, unsig * * @return Success/Fail, see \ref MXC_Error_Codes for a list of return codes. */ -int MXC_I3C_WriteI2CBlocking(mxc_i3c_regs_t *i3c, unsigned char staticAddr, unsigned char *bytes, unsigned int *len); +int MXC_I3C_WriteI2CBlocking(mxc_i3c_regs_t *i3c, unsigned char staticAddr, unsigned char *bytes, + unsigned int *len); + +/** + * @brief Read multiple bytes from an I3C target in blocking mode. + * + * @param i3c Pointer to I3C registers. + * @param dynAddr 7-bit target dynamic address to read from. + * @param len The number of bytes to read. On return from this function, + * this will be set to the number of bytes actually received. + * + * @return Success/Fail, see \ref MXC_Error_Codes for a list of return codes. + */ +int MXC_I3C_ReadSDRBlocking(mxc_i3c_regs_t *i3c, unsigned char dynAddr, unsigned char *bytes, + unsigned int *len); /** - * @brief Emit an I2C STOP. + * @brief Write multiple bytes to an I3C target in blocking mode. + * + * @param i3c Pointer to I3C registers. + * @param dynAddr 7-bit target dynamic address to write to. + * @param len The number of bytes to write. On return from this function, + * this will be set to the number of bytes actually sent. + * + * @return Success/Fail, see \ref MXC_Error_Codes for a list of return codes. + */ +int MXC_I3C_WriteSDRBlocking(mxc_i3c_regs_t *i3c, unsigned char dynAddr, unsigned char *bytes, + unsigned int *len); + +/** + * @brief Unloads bytes from the receive FIFO. + * + * @param i3c Pointer to I3C registers. + * @param bytes The buffer to read the data into. + * @param len The number of bytes to read. + * + * @return The number of bytes actually read. + */ +int MXC_I3C_ReadRXFIFO(mxc_i3c_regs_t *i3c, volatile unsigned char *bytes, unsigned int len); + +/** + * @brief Loads bytes into the transmit FIFO. + * + * @param i2c Pointer to I3C registers. + * @param bytes The buffer containing the bytes to write. + * @param len The number of bytes to write. + * + * @return The number of bytes actually written. + */ +int MXC_I3C_WriteTXFIFO(mxc_i3c_regs_t *i3c, volatile unsigned char *bytes, unsigned int len); + +/** + * @brief Emit an I2C STOP. * * @param i3c Pointer to I3C registers. */ static inline void MXC_I3C_I2CStop(mxc_i3c_regs_t *i3c) { /* Configure MCTRL register for STOP */ - i3c->mctrl = MXC_S_I3C_MCTRL_REQUEST_EMIT_STOP | - (1 << MXC_F_I3C_MCTRL_TYPE_POS); + i3c->mctrl = MXC_S_I3C_MCTRL_REQUEST_EMIT_STOP | (1 << MXC_F_I3C_MCTRL_TYPE_POS); /* Wait for MCTRL_DONE */ while (!(i3c->mstatus & MXC_F_I3C_MSTATUS_MCTRLDONE)) {} } @@ -275,30 +413,6 @@ static inline void MXC_I3C_Stop(mxc_i3c_regs_t *i3c) while (!(i3c->mstatus & MXC_F_I3C_MSTATUS_MCTRLDONE)) {} } -/** - * @brief Read multiple bytes from an I3C target in blocking mode. - * - * @param i3c Pointer to I3C registers. - * @param dynAddr 7-bit target dynamic address to read from. - * @param len The number of bytes to read. On return from this function, - * this will be set to the number of bytes actually received. - * - * @return Success/Fail, see \ref MXC_Error_Codes for a list of return codes. - */ -int MXC_I3C_ReadSDRBlocking(mxc_i3c_regs_t *i3c, unsigned char dynAddr, unsigned char *bytes, unsigned int *len); - -/** - * @brief Write multiple bytes to an I3C target in blocking mode. - * - * @param i3c Pointer to I3C registers. - * @param dynAddr 7-bit target dynamic address to write to. - * @param len The number of bytes to write. On return from this function, - * this will be set to the number of bytes actually sent. - * - * @return Success/Fail, see \ref MXC_Error_Codes for a list of return codes. - */ -int MXC_I3C_WriteSDRBlocking(mxc_i3c_regs_t *i3c, unsigned char dynAddr, unsigned char *bytes, unsigned int *len); - /** * @brief Sets the SCL frequency for I3C push-pull operation. * @@ -407,36 +521,25 @@ int MXC_I3C_SetHighKeeperMode(mxc_i3c_regs_t *i3c, mxc_i3c_high_keeper_t hkeep); * * @return Success/Fail, see \ref MXC_Error_Codes for a list of return codes. */ -int MXC_I3C_SetRXTXThreshold(mxc_i3c_regs_t *i3c, mxc_i3c_rx_threshold_t rxth, mxc_i3c_tx_threshold_t txth); +int MXC_I3C_SetRXTXThreshold(mxc_i3c_regs_t *i3c, mxc_i3c_rx_threshold_t rxth, + mxc_i3c_tx_threshold_t txth); /** - * @brief Unloads bytes from the receive FIFO. - * + * @brief Returns the dynamic address in target mode. + * * @param i3c Pointer to I3C registers. - * @param bytes The buffer to read the data into. - * @param len The number of bytes to read. - * - * @return The number of bytes actually read. - */ -int MXC_I3C_ReadRXFIFO(mxc_i3c_regs_t *i3c, volatile unsigned char *bytes, unsigned int len); - -/** - * @brief Loads bytes into the transmit FIFO. - * - * @param i2c Pointer to I3C registers. - * @param bytes The buffer containing the bytes to write. - * @param len The number of bytes to write. - * - * @return The number of bytes actually written. + * + * @return Dynamic address set by bus controller. If the address is invalid or + * device is not running in target mode, then 0 is returned. */ -int MXC_I3C_WriteTXFIFO(mxc_i3c_regs_t *i3c, volatile unsigned char *bytes, unsigned int len); +uint8_t MXC_I3C_GetDynamicAddress(mxc_i3c_regs_t *i3c); /** * @brief Interrupt handler. * * @param i3c Pointer to I3C registers. */ -void MXC_I3C_IRQHandler(mxc_i3c_regs_t *i3c); +void MXC_I3C_AsyncHandler(mxc_i3c_regs_t *i3c); /** * @brief Removes and discards all bytes currently in the receive FIFO. @@ -513,7 +616,7 @@ static inline void MXC_I3C_ControllerDisableInt(mxc_i3c_regs_t *i3c, uint32_t ma */ static inline unsigned int MXC_I3C_ControllerGetFlags(mxc_i3c_regs_t *i3c) { - return i3c->mstatus; + return i3c->mintmasked; } /** @@ -530,10 +633,58 @@ static inline void MXC_I3C_ControllerClearFlags(mxc_i3c_regs_t *i3c, uint32_t ma i3c->mstatus |= mask; } +/** + * @brief Enable target interrupts. + * + * @param i3c Pointer to I3C registers. + * @param mask Interrupt mask to set. + */ +static inline void MXC_I3C_TargetEnableInt(mxc_i3c_regs_t *i3c, uint32_t mask) +{ + i3c->intset |= mask; +} + +/** + * @brief Disable target interrupts. + * + * @param i3c Pointer to I3C registers. + * @param mask Interrupt mask to set. + */ +static inline void MXC_I3C_TargetDisableInt(mxc_i3c_regs_t *i3c, uint32_t mask) +{ + i3c->intclr |= mask; +} + +/** + * @brief Get the presently set interrupt flags. + * + * @param i3c Pointer to I3C registers. + * + * @return See \ref MXC_Error_Codes for a list of return values. + */ +static inline unsigned int MXC_I3C_TargetGetFlags(mxc_i3c_regs_t *i3c) +{ + return i3c->intmasked; +} + +/** + * @brief Clear target interrupts. + * + * Note that some bits cannot be cleared manually and self-clear only when their + * respective condition occurs. + * + * @param i3c Pointer to I3C registers. + * @param mask Interrupt mask to clear. + */ +static inline void MXC_I3C_TargetClearFlags(mxc_i3c_regs_t *i3c, uint32_t mask) +{ + i3c->status |= mask; +} + /**@} end of group i3c */ #ifdef __cplusplus } #endif -#endif // LIBRARIES_PERIPHDRIVERS_INCLUDE_MAX32657_I2C_H_ +#endif // LIBRARIES_PERIPHDRIVERS_INCLUDE_MAX32657_I3C_H_ diff --git a/Libraries/PeriphDrivers/Source/I3C/i3c_me30.c b/Libraries/PeriphDrivers/Source/I3C/i3c_me30.c index 029b7c4ca28..aa325041a11 100644 --- a/Libraries/PeriphDrivers/Source/I3C/i3c_me30.c +++ b/Libraries/PeriphDrivers/Source/I3C/i3c_me30.c @@ -24,14 +24,18 @@ #include "i3c_ccc.h" /* **** Definitions **** */ -#define MXC_I3C_PUSH_PULL_FREQ 12500000U -#define MXC_I3C_OPEN_DRAIN_FREQ 2500000U +#define MXC_I3C_PUSH_PULL_FREQ 2500000U +#define MXC_I3C_OPEN_DRAIN_FREQ 1000000U #define MXC_I3C_I2C_FREQ 100000U #define MXC_I3C_MAX_FIFO_TRANSACTION 255U -#define GET_FIELD(reg, name, field) \ - ((i3c->reg & MXC_F_I3C_##name##_##field) >> MXC_F_I3C_##name##_##field##_POS) +#define GET_FIELD(reg, field) ((i3c->reg & MXC_F_I3C_##field) >> MXC_F_I3C_##field##_POS) +#define SET_FIELD(reg, field, value) \ + do { \ + i3c->reg &= ~MXC_F_I3C_##field; \ + i3c->reg |= value << MXC_F_I3C_##field##_POS; \ + } while (0); #define POLL_REG(reg, name, field) \ while ((i3c->reg & MXC_F_I3C_##name##_##field) != MXC_F_I3C_##name##_##field) {} @@ -107,6 +111,18 @@ typedef struct { ///< bytes will be stored in this buffer. } mxc_i3c_ccc_req_t; +typedef struct { + mxc_i3c_regs_t *regs; ///< Pointer to regs of this I3C instance. + mxc_i3c_target_t *i3cTargets; ///< List of I3C targets. + uint8_t numI3CTargets; ///< Number of I3C targets. + mxc_i3c_i2c_target_t *i2cTargets; ///< List of I2C targets. + uint8_t numI2CTargets; ///< Number of I2C targets. + mxc_i3c_ibi_ack_t ibiAckCB; ///< IBI acknowledge callback. + mxc_i3c_ibi_req_t ibiReqCB; ///< IBI request callback. + mxc_i3c_ibi_getbyte_t ibiGetByteCB; ///< IBI additional data callback. + mxc_i3c_ccc_cb_t cccCB; ///< CCC callback. +} mxc_i3c_controller_t; + #define MXC_I3C_ADDR_INVALID 0x00U /* **** Globals **** */ @@ -117,10 +133,11 @@ typedef struct { mxc_i3c_controller_t controller[MXC_I3C_INSTANCES]; /* **** Functions **** */ -int MXC_I3C_Init(mxc_i3c_regs_t *i3c, int targetMode) +int MXC_I3C_Init(mxc_i3c_regs_t *i3c, int targetMode, uint8_t staticAddr) { int ret = E_NO_ERROR; int idx; + uint8_t val; idx = MXC_I3C_GET_IDX(i3c); if (idx < 0) { @@ -165,14 +182,49 @@ int MXC_I3C_Init(mxc_i3c_regs_t *i3c, int targetMode) /* 3. Optionally write IBIRULES reg to optimize response to incoming IBIs */ /* 4. Enable controller mode */ - i3c->mconfig &= ~MXC_F_I3C_MCONFIG_CTARENA; - i3c->mconfig |= MXC_S_I3C_MCONFIG_CTARENA_ON; + SET_FIELD(mconfig, MCONFIG_CTARENA, MXC_V_I3C_MCONFIG_CTARENA_ON); } else { /* Target mode initialization */ - /* 1. */ - /* After reset, write setup registers needed for optional features */ - /* 2. */ - /* Write 1 to CONFIG.TGTENA */ + /* 1. After reset, write setup registers needed for optional features */ + if (staticAddr != MXC_I3C_ADDR_INVALID) { + if (GET_FIELD(capabilities, CAPABILITIES_SADDR) == + MXC_V_I3C_CAPABILITIES_SADDR_CONFIG) { + SET_FIELD(config, CONFIG_SADDR, staticAddr); + } + } + + if (i3c->capabilities & MXC_F_I3C_CAPABILITIES_FIFORX) { + MXC_I3C_SetRXTXThreshold(i3c, MXC_I3C_RX_TH_NOT_EMPTY, MXC_I3C_TX_TH_ALMOST_FULL); + } + + /* Set BCR, DCR */ + val = 0 << 6; /* Device role: target */ + if (i3c->capabilities & MXC_S_I3C_CAPABILITIES_CCCHANDLE_LIMITS) { + val |= 1 << 0; /* Max data speed limitation */ + } + if (i3c->capabilities & MXC_S_I3C_CAPABILITIES_CCCHANDLE_BASIC) { + val |= 1 << 5; /* Supports advanced capabiliries */ + } + if (i3c->capabilities & MXC_S_I3C_CAPABILITIES_IBI_MR_HJ_IBI) { + val |= 1 << 1; /* Supports IBI generation */ + } + if (i3c->capabilities & MXC_S_I3C_CAPABILITIES_IBI_MR_HJ_IBI_PAYLOAD) { + val |= 1 << 2; /* MDB and additional data bytes may follow the IBI */ + } + val |= 1 << 3; /* Offline capable */ + SET_FIELD(idext, IDEXT_BCR, val); + + /* Set DCR to generic device */ + SET_FIELD(idext, IDEXT_DCR, 0); + + /* Enable CCC handling */ + MXC_I3C_TargetEnableInt(i3c, MXC_F_I3C_INTSET_CCC); + + /* 2. Write 1 to CONFIG.TGTENA */ + SET_FIELD(config, CONFIG_TGTENA, 1); + + /* Clear STOP bit */ + SET_FIELD(status, STATUS_STOP, 0); } controller[idx].regs = i3c; @@ -216,6 +268,37 @@ int MXC_I3C_SetI2CTargets(mxc_i3c_regs_t *i3c, mxc_i3c_i2c_target_t *targets, ui return E_SUCCESS; } +void MXC_I3C_SetIBICallback(mxc_i3c_regs_t *i3c, mxc_i3c_ibi_ack_t ackCb, mxc_i3c_ibi_req_t reqCb) +{ + int idx; + + idx = MXC_I3C_GET_IDX(i3c); + if (idx >= 0) { + controller[idx].ibiAckCB = ackCb; + controller[idx].ibiReqCB = reqCb; + } +} + +void MXC_I3C_SetIBIPayloadCallback(mxc_i3c_regs_t *i3c, mxc_i3c_ibi_getbyte_t payloadCb) +{ + int idx; + + idx = MXC_I3C_GET_IDX(i3c); + if (idx >= 0) { + controller[idx].ibiGetByteCB = payloadCb; + } +} + +void MXC_I3C_SetCCCCallback(mxc_i3c_regs_t *i3c, mxc_i3c_ccc_cb_t cccCb) +{ + int idx; + + idx = MXC_I3C_GET_IDX(i3c); + if (idx >= 0) { + controller[idx].cccCB = cccCb; + } +} + static int MXC_I3C_GetError(mxc_i3c_regs_t *i3c) { uint32_t errFlags = i3c->merrwarn & MXC_I3C_MERRWARN_MASK; @@ -305,7 +388,7 @@ static int MXC_I3C_IBIAckNack(mxc_i3c_regs_t *i3c, int ack, int mdb, unsigned ch while ((i3c->mstatus & MXC_F_I3C_MSTATUS_COMPLETE) == 0 && rdbytes < (1 + MXC_I3C_MAX_IBI_BYTES)) { if (i3c->mstatus & MXC_F_I3C_MSTATUS_RXPEND) { - *data++ = GET_FIELD(mrdatab, MRDATAB, DATA); + *data++ = GET_FIELD(mrdatab, MRDATAB_DATA); rdbytes++; } } @@ -329,12 +412,12 @@ static int MXC_I3C_ProcessIBI(mxc_i3c_regs_t *i3c) return E_BAD_PARAM; } - if (GET_FIELD(mstatus, MSTATUS, STATE) != MXC_V_I3C_MSTATUS_STATE_IBIACK) { + if (GET_FIELD(mstatus, MSTATUS_STATE) != MXC_V_I3C_MSTATUS_STATE_IBIACK) { return E_BAD_STATE; } - ibiAddr = GET_FIELD(mstatus, MSTATUS, IBIADDR); - ibiType = GET_FIELD(mstatus, MSTATUS, IBITYPE); + ibiAddr = GET_FIELD(mstatus, MSTATUS_IBIADDR); + ibiType = GET_FIELD(mstatus, MSTATUS_IBITYPE); mdb = 0; buf = NULL; numBytes = NULL; @@ -698,7 +781,7 @@ int MXC_I3C_PerformDAA(mxc_i3c_regs_t *i3c) MXC_I3C_ControllerClearFlags(i3c, MXC_F_I3C_MSTATUS_IBIWON); } - if (GET_FIELD(mstatus, MSTATUS, STATE) != MXC_V_I3C_MSTATUS_STATE_IDLE) { + if (GET_FIELD(mstatus, MSTATUS_STATE) != MXC_V_I3C_MSTATUS_STATE_IDLE) { return E_BAD_STATE; } @@ -738,7 +821,7 @@ int MXC_I3C_PerformDAA(mxc_i3c_regs_t *i3c) } } else if (ret == E_NO_RESPONSE) { /* No more devices waiting for dynamic address assignment */ - if ((GET_FIELD(mstatus, MSTATUS, STATE) == MXC_V_I3C_MSTATUS_STATE_IDLE) && + if ((GET_FIELD(mstatus, MSTATUS_STATE) == MXC_V_I3C_MSTATUS_STATE_IDLE) && (i3c->mstatus & MXC_F_I3C_MSTATUS_COMPLETE)) { /* DAA is complete */ ret = E_SUCCESS; @@ -766,7 +849,7 @@ int MXC_I3C_PerformDAA(mxc_i3c_regs_t *i3c) pid = ((uint64_t)vendor_id << 32) | part_id; /* Find device with received PID */ - if ((GET_FIELD(mstatus, MSTATUS, STATE) == MXC_V_I3C_MSTATUS_STATE_DAA) && + if ((GET_FIELD(mstatus, MSTATUS_STATE) == MXC_V_I3C_MSTATUS_STATE_DAA) && (i3c->mstatus & MXC_F_I3C_MSTATUS_BETWEEN)) { target = MXC_I3C_FindTarget(&controller[idx], pid); if (target) { @@ -797,6 +880,95 @@ int MXC_I3C_PerformDAA(mxc_i3c_regs_t *i3c) return ret; } +int MXC_I3C_HotJoin(mxc_i3c_regs_t *i3c) +{ + if (!(i3c->capabilities & MXC_S_I3C_CAPABILITIES_IBI_MR_HJ_HOTJOIN)) { + return E_NOT_SUPPORTED; + } + + if ((MXC_I3C_GetDynamicAddress(i3c) != MXC_I3C_ADDR_INVALID) || + (i3c->status & MXC_F_I3C_STATUS_HJDIS)) { + return E_BAD_STATE; + } + + SET_FIELD(config, CONFIG_TGTENA, 0); + SET_FIELD(ctrl, CTRL_EVENT, MXC_V_I3C_CTRL_EVENT_HOTJOIN); + SET_FIELD(config, CONFIG_TGTENA, 1); + + return E_SUCCESS; +} + +int MXC_I3C_RequestIBI(mxc_i3c_regs_t *i3c, unsigned char mdb, mxc_i3c_ibi_getbyte_t getByteCb) +{ + int ret, idx; + unsigned char byte; + + idx = MXC_I3C_GET_IDX(i3c); + if (idx < 0) { + return E_BAD_PARAM; + } + + if (!(i3c->capabilities & MXC_S_I3C_CAPABILITIES_IBI_MR_HJ_IBI)) { + return E_NOT_SUPPORTED; + } + + if ((MXC_I3C_GetDynamicAddress(i3c) == MXC_I3C_ADDR_INVALID) || + (i3c->status & MXC_F_I3C_STATUS_IBIDIS)) { + return E_BAD_STATE; + } + + if (i3c->status & MXC_F_I3C_STATUS_EVENT) { + return E_BUSY; + } + + /* Write MDB and additional data bytes to TX FIFO */ + controller[idx].ibiGetByteCB = getByteCb; + if (i3c->capabilities & MXC_S_I3C_CAPABILITIES_IBI_MR_HJ_IBI_PAYLOAD) { + if (getByteCb) { + while ((i3c->status & MXC_F_I3C_STATUS_TXNOTFULL)) { + ret = getByteCb(i3c, &byte); + if (ret) { + i3c->wdatab1 = byte; + } else { + break; + } + } + } + SET_FIELD(ctrl, CTRL_IBIDATA, mdb); + SET_FIELD(ctrl, CTRL_EXTDATA, !!(i3c->datactrl & MXC_F_I3C_DATACTRL_TXCOUNT)); + } + + MXC_I3C_TargetEnableInt(i3c, MXC_F_I3C_INTSET_EVENT | MXC_F_I3C_INTSET_TXNOTFULL | + MXC_F_I3C_INTSET_STOP); + + SET_FIELD(ctrl, CTRL_EVENT, MXC_V_I3C_CTRL_EVENT_IBI); + + return E_SUCCESS; +} + +int MXC_I3C_Standby(mxc_i3c_regs_t *i3c) +{ + if (MXC_I3C_GetDynamicAddress(i3c) == MXC_I3C_ADDR_INVALID) { + return E_BAD_STATE; + } + + SET_FIELD(config, CONFIG_TGTENA, 0); + + return E_SUCCESS; +} + +int MXC_I3C_Wakeup(mxc_i3c_regs_t *i3c) +{ + if ((MXC_I3C_GetDynamicAddress(i3c) == MXC_I3C_ADDR_INVALID) || + (GET_FIELD(config, CONFIG_TGTENA) == 1)) { + return E_BAD_STATE; + } + + i3c->config |= (MXC_F_I3C_CONFIG_TGTENA | MXC_F_I3C_CONFIG_OFFLINE); + + return E_SUCCESS; +} + int MXC_I3C_ReadI2CBlocking(mxc_i3c_regs_t *i3c, uint8_t staticAddr, unsigned char *bytes, unsigned int *len) { @@ -901,7 +1073,7 @@ int MXC_I3C_ReadSDRBlocking(mxc_i3c_regs_t *i3c, unsigned char dynAddr, unsigned int ret; unsigned int remaining, chunkSize; - if (GET_FIELD(mstatus, MSTATUS, STATE) != MXC_V_I3C_MSTATUS_STATE_IDLE) { + if (GET_FIELD(mstatus, MSTATUS_STATE) != MXC_V_I3C_MSTATUS_STATE_IDLE) { return E_BAD_STATE; } @@ -938,7 +1110,7 @@ int MXC_I3C_WriteSDRBlocking(mxc_i3c_regs_t *i3c, unsigned char dynAddr, unsigne int ret; unsigned int remaining; - if (GET_FIELD(mstatus, MSTATUS, STATE) != MXC_V_I3C_MSTATUS_STATE_IDLE) { + if (GET_FIELD(mstatus, MSTATUS_STATE) != MXC_V_I3C_MSTATUS_STATE_IDLE) { return E_BAD_STATE; } @@ -963,6 +1135,41 @@ int MXC_I3C_WriteSDRBlocking(mxc_i3c_regs_t *i3c, unsigned char dynAddr, unsigne return ret; } +int MXC_I3C_ReadRXFIFO(mxc_i3c_regs_t *i3c, volatile unsigned char *bytes, unsigned int len) +{ + unsigned int readb = 0; + + while ((len > readb) && !(i3c->mstatus & MXC_F_I3C_MSTATUS_ERRWARN) && + (i3c->mstatus & MXC_F_I3C_MSTATUS_RXPEND)) { + bytes[readb++] = i3c->mrdatab; + } + + return readb; +} + +int MXC_I3C_WriteTXFIFO(mxc_i3c_regs_t *i3c, volatile unsigned char *bytes, unsigned int len) +{ + unsigned int written = 0; + + if (len == 0) { + return 0; + } + + while ((len - 1 > written) && !(i3c->mstatus & MXC_F_I3C_MSTATUS_ERRWARN) && + (i3c->mstatus & MXC_F_I3C_MSTATUS_TXNOTFULL)) { + i3c->mwdatab1 = bytes[written++]; + } + + if ((len == written + 1) && (i3c->mstatus & MXC_F_I3C_MSTATUS_TXNOTFULL)) { + i3c->mwdatabe = bytes[written++]; + if (i3c->mstatus & MXC_F_I3C_MSTATUS_ERRWARN) { + return written; + } + } + + return written; +} + int MXC_I3C_SetPPFrequency(mxc_i3c_regs_t *i3c, unsigned int frequency) { uint32_t ticks, highPeriod, lowPeriod; @@ -1059,7 +1266,6 @@ int MXC_I3C_SetI2CFrequency(mxc_i3c_regs_t *i3c, unsigned int frequency) if (lowPeriod > 0xF) { lowPeriod = 0xF; } - i3c->mconfig &= ~MXC_F_I3C_MCONFIG_I2CBAUD; i3c->mconfig |= lowPeriod << MXC_F_I3C_MCONFIG_I2CBAUD_POS; @@ -1092,9 +1298,11 @@ int MXC_I3C_SetSkew(mxc_i3c_regs_t *i3c, uint8_t skew) return E_BAD_PARAM; } - ppFreq = MXC_I3C_GetPPFrequency(i3c); - if ((PeripheralClock / ppFreq) < 4) { - return E_BAD_STATE; + if (skew > 0) { + ppFreq = MXC_I3C_GetPPFrequency(i3c); + if ((PeripheralClock / ppFreq) < 4) { + return E_BAD_STATE; + } } i3c->mconfig &= ~MXC_F_I3C_MCONFIG_SKEW; @@ -1128,45 +1336,71 @@ int MXC_I3C_SetRXTXThreshold(mxc_i3c_regs_t *i3c, mxc_i3c_rx_threshold_t rxth, return E_SUCCESS; } -int MXC_I3C_ReadRXFIFO(mxc_i3c_regs_t *i3c, volatile unsigned char *bytes, unsigned int len) +uint8_t MXC_I3C_GetDynamicAddress(mxc_i3c_regs_t *i3c) { - unsigned int readb = 0; - - while ((len > readb) && !(i3c->mstatus & MXC_F_I3C_MSTATUS_ERRWARN) && - (i3c->mstatus & MXC_F_I3C_MSTATUS_RXPEND)) { - bytes[readb++] = i3c->mrdatab; + if (GET_FIELD(config, CONFIG_TGTENA) == 1 && GET_FIELD(dynaddr, DYNADDR_DAVALID) == 1) { + return GET_FIELD(dynaddr, DYNADDR_DADDR); } - return readb; + return MXC_I3C_ADDR_INVALID; } -int MXC_I3C_WriteTXFIFO(mxc_i3c_regs_t *i3c, volatile unsigned char *bytes, unsigned int len) +void MXC_I3C_AsyncHandler(mxc_i3c_regs_t *i3c) { - unsigned int written = 0; - - if (len == 0) { - return 0; - } + int idx, ret; + uint8_t flags, byte; - while ((len - 1 > written) && !(i3c->mstatus & MXC_F_I3C_MSTATUS_ERRWARN) && - (i3c->mstatus & MXC_F_I3C_MSTATUS_TXNOTFULL)) { - i3c->mwdatab1 = bytes[written++]; + idx = MXC_I3C_GET_IDX(i3c); + if (idx < 0) { + return; } - if ((len == written + 1) && (i3c->mstatus & MXC_F_I3C_MSTATUS_TXNOTFULL)) { - i3c->mwdatabe = bytes[written++]; - if (i3c->mstatus & MXC_F_I3C_MSTATUS_ERRWARN) { - return written; + if (i3c->mconfig & MXC_F_I3C_MCONFIG_CTARENA) { + /* Controller mode */ + if (i3c->mintmasked & MXC_F_I3C_MINTMASKED_TGTSTART) { + MXC_I3C_ControllerClearFlags(i3c, MXC_F_I3C_MINTMASKED_TGTSTART); + MXC_I3C_ProcessIBI(i3c); + } + } else { + /* Target mode */ + flags = MXC_I3C_TargetGetFlags(i3c); + + if (flags & MXC_F_I3C_INTMASKED_CCC) { + MXC_I3C_TargetClearFlags(i3c, MXC_F_I3C_STATUS_CCC); + /* First byte is CCC command */ + byte = i3c->rdatab; + if (controller[idx].cccCB) { + controller[idx].cccCB(i3c, byte); + } } - } - return written; -} + if (flags & MXC_F_I3C_INTMASKED_EVENT) { + /* IBI acked */ + if (GET_FIELD(status, STATUS_EVDET) == MXC_V_I3C_STATUS_EVDET_REQ_ACKED) { + MXC_I3C_TargetClearFlags(i3c, MXC_F_I3C_STATUS_EVENT); + MXC_I3C_TargetDisableInt(i3c, MXC_F_I3C_INTCLR_EVENT); + if (GET_FIELD(ctrl, CTRL_EVENT) == MXC_V_I3C_CTRL_EVENT_IBI) { + /* Enable TX interrupts to transmit additional payload */ + MXC_I3C_TargetEnableInt(i3c, MXC_F_I3C_INTSET_TXNOTFULL); + } + } + } -void MXC_I3C_IRQHandler(mxc_i3c_regs_t *i3c) -{ - if (i3c->mintmasked & MXC_F_I3C_MINTMASKED_TGTSTART) { - MXC_I3C_ControllerClearFlags(i3c, MXC_F_I3C_MINTMASKED_TGTSTART); - MXC_I3C_ProcessIBI(i3c); + flags = MXC_I3C_TargetGetFlags(i3c); + if (flags & MXC_F_I3C_INTMASKED_TXNOTFULL) { + if (controller[idx].ibiGetByteCB) { + while ((i3c->status & MXC_F_I3C_STATUS_TXNOTFULL)) { + ret = controller[idx].ibiGetByteCB(i3c, &byte); + if (ret) { + i3c->wdatab1 = byte; + } else { + /* No more data */ + MXC_I3C_TargetDisableInt(i3c, MXC_F_I3C_INTCLR_TXNOTFULL); + controller[idx].ibiGetByteCB = NULL; + break; + } + } + } + } } }