openmv/lib/alif/Alif_CMSIS/Include/Driver_I3C.h
iabdalkader daf2bb30da misc: Restructure repo.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-04-13 08:28:34 +02:00

364 lines
21 KiB
C

/* Copyright (C) 2023 Alif Semiconductor - All Rights Reserved.
* Use, distribution and modification of this code is permitted under the
* terms stated in the Alif Semiconductor Software License Agreement
*
* You should have received a copy of the Alif Semiconductor Software
* License Agreement with this file. If not, please write to:
* contact@alifsemi.com, or visit: https://alifsemi.com/license
*/
#ifndef DRIVER_I3C_H_
#define DRIVER_I3C_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include "Driver_Common.h"
#define ARM_I3C_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(7,2) /* API version */
/****** I3C Control Codes *****/
/* I3C Control Codes: Bus mode */
#define I3C_MASTER_SET_BUS_MODE (1UL << 0) ///< Set bus mode to pure i3c, mixed i3c + i2c fast etc.
#define I3C_SLAVE_SET_ADDR (1UL << 1) ///< Set slave addr and initialize slave; arg: slave address
#define I3C_MASTER_SET_SLAVE_NACK_RETRY_COUNT (1UL << 2) ///< Set retry count to communicate to the slave that nacked the comm. Ref: Slave Nack retry count Control arguments
#define I3C_SET_SDA_TX_HOLD_TIME (1UL << 3) ///< Set SDA Hold time(in terms of the CORE_CLK periods) for FM, FM+, SDR and DDR mode of operations; arg:<1-7>
#define I3C_MASTER_ABORT_MESSAGE_TRANSFER (1UL << 4) ///< Abort the current Message transfer
#define I3C_MASTER_SETUP_HOT_JOIN_ACCEPTANCE (1UL << 5) ///< Accept/Reject the Hot Join request from slaves; arg: 1-Accept, 0-Reject
#define I3C_MASTER_SETUP_MR_ACCEPTANCE (1UL << 6) ///< Accept/Reject the Master request from slaves; arg: 1-Accept, 0-Reject
#define I3C_SLAVE_REQUEST_IBI_BUS_MASTERSHIP (1UL << 7) ///< Request for Bus Mastership
#define I3C_SET_DEVICE_CHARACTERISTICS (1UL << 8) ///< Set Device Characteristics (DCR) value; arg: 0-255
#define I3C_MASTER_INIT (1UL << 9) ///< Initialises the device as master
#define I3C_MASTER_SETUP_SIR_ACCEPTANCE (1UL << 10) ///< Accept/Reject the SIR from slaves; arg: 1-Accept, 0-Reject
#define I3C_SLAVE_SET_IBI_SIR (1UL << 11) ///< Set IBI Slave interrupt Request
#define I3C_SLAVE_SET_PID (1UL << 12) ///< Set MIPI I3C Slave's 48-bit Provisional ID
/* I3C Control Codes: Bus mode arguments */
#define I3C_BUS_SLOW_MODE (0x00UL) ///< Slow bus mode for pure i3c devices - For slave addressing
#define I3C_BUS_MODE_MIXED_FAST_I2C_FMP_SPEED_1_MBPS (0x01UL) ///< Mixed i3c + i2c device, Speed: Fast Mode Plus 1 MBPS
#define I3C_BUS_MODE_MIXED_FAST_I2C_FM_SPEED_400_KBPS (0x02UL) ///< Mixed i3c + i2c device, Speed: Fast Mode 400 KBPS
#define I3C_BUS_MODE_MIXED_SLOW_I2C_SS_SPEED_100_KBPS (0x03UL) ///< Mixed i3c + i2c device, Speed: Standard Mode 100 KBPS
#define I3C_BUS_MODE_MIXED_LIMITED (0x04UL)
#define I3C_BUS_NORMAL_MODE (0x05UL) ///< Normal bus mode for pure i3c devices - For actual data comm
/* I3C Control arguments: For Slave Nack retry count */
#define I3C_SLAVE_NACK_RETRY_COUNT_Pos 8U
#define I3C_SLAVE_NACK_RETRY_COUNT_Msk (3U << I3C_SLAVE_NACK_RETRY_COUNT_Pos)
#define I3C_SLAVE_NACK_RETRY_COUNT(x) ((x << I3C_SLAVE_NACK_RETRY_COUNT_Pos) & I3C_SLAVE_NACK_RETRY_COUNT_Msk) ///< x: 0-3
#define I3C_SLAVE_ADDR(x) (x & (0x7FU))
#define I3C_BUS_MAX_DEVS 0x8
/****** I3C Event *****/
#define ARM_I3C_EVENT_TRANSFER_DONE (1UL << 0) ///< Event Success
#define ARM_I3C_EVENT_TRANSFER_ERROR (1UL << 1) ///< Master and slave Transmit/Receive Error
#define ARM_I3C_EVENT_SLV_DYN_ADDR_ASSGN (1UL << 2) ///< Slave Dynamic Address Assigned(only for Slave mode)
#define ARM_I3C_EVENT_MESSAGE_TRANSFER_ABORT (1UL << 3) ///< Message transfer is aborted
#define ARM_I3C_EVENT_IBI_HOT_JOIN_REQ (1UL << 4) ///< Hot-Join request received from new slave
#define ARM_I3C_EVENT_IBI_MASTERSHIP_REQ (1UL << 5) ///< Slave requested to become bus Master
#define ARM_I3C_EVENT_BUSOWNER_UPDATED (1UL << 6) ///< Bus Owner (Master) updated
#define ARM_I3C_EVENT_SLAVE_CCC_UPDATED (1UL << 7) ///< Slave CCC updated by master
#define ARM_I3C_EVENT_IBI_SLV_INTR_REQ (1UL << 8) ///< Slave requested through SIR
#define ARM_I3C_EVENT_SLAVE_LIST (1UL << 9) ///< Targets info rcvd through DEFSLVS CCC. Applicable only for secondary masters
/****** I3C Error Status codes *****/
#define ARM_I3C_LEC_NO_ERROR (0U) ///< Last error code: No error
#define ARM_I3C_LEC_CRC_ERROR (1U) ///< Last error code: CRC error
#define ARM_I3C_LEC_PARITY_ERROR (2U) ///< Last error code: Parity error
#define ARM_I3C_LEC_FRAME_ERROR (3U) ///< Last error code: Frame error
#define ARM_I3C_LEC_IBA_NACK_ERROR (4U) ///< Last error code: Nack for I3C broadcast address error
#define ARM_I3C_LEC_ADDR_NACK_ERROR (5U) ///< Last error code: Nack for I3C slave address error
#define ARM_I3C_LEC_BUF_UNDER_OVERFLOW_ERROR (6U) ///< Last error code: Buffer Overflow/underflow error
#define ARM_I3C_LEC_TRANSFER_ABORT_ERROR (7U) ///< Last error code: Transfer abort error
#define ARM_I3C_LEC_I2C_SLAVE_NACK_ERROR (8U) ///< Last error code: I2C slave NACK for current write transfer error
#define ARM_I3C_LEC_PEC_BYTE_ERROR (9U) ///< Last error code: PEC byte check error
#define ARM_I3C_LEC_EARLY_TERMINATION_ERROR (10U) ///< Last error code: Master early termination error
/* I3C CCC (Common Command Codes) related definitions */
#define I3C_CCC_DIRECT BIT(7)
#define I3C_CCC_ID(id, broadcast) ((id) | ((broadcast) ? 0 : I3C_CCC_DIRECT))
/* Commands valid in both broadcast and unicast modes */
#define I3C_CCC_ENEC(broadcast) I3C_CCC_ID(0x0, broadcast)
#define I3C_CCC_DISEC(broadcast) I3C_CCC_ID(0x1, broadcast)
#define I3C_CCC_ENTAS(as, broadcast) I3C_CCC_ID(0x2 + (as), broadcast)
#define I3C_CCC_RSTDAA(broadcast) I3C_CCC_ID(0x6, broadcast)
#define I3C_CCC_SETMWL(broadcast) I3C_CCC_ID(0x9, broadcast)
#define I3C_CCC_SETMRL(broadcast) I3C_CCC_ID(0xa, broadcast)
#define I3C_CCC_SETXTIME(broadcast) ((broadcast) ? 0x28 : 0x98)
#define I3C_CCC_VENDOR(id, broadcast) ((id) + ((broadcast) ? 0x61 : 0xe0))
/* Broadcast-only commands */
#define I3C_CCC_ENTDAA I3C_CCC_ID(0x7, true)
#define I3C_CCC_DEFSLVS I3C_CCC_ID(0x8, true)
#define I3C_CCC_ENTTM I3C_CCC_ID(0xb, true)
#define I3C_CCC_ENTHDR(x) I3C_CCC_ID(0x20 + (x), true)
#define I3C_CCC_SETAASA I3C_CCC_ID(0x29, true)
/* Unicast-only commands */
#define I3C_CCC_SETDASA I3C_CCC_ID(0x7, false)
#define I3C_CCC_SETNEWDA I3C_CCC_ID(0x8, false)
#define I3C_CCC_GETMWL I3C_CCC_ID(0xb, false)
#define I3C_CCC_GETMRL I3C_CCC_ID(0xc, false)
#define I3C_CCC_GETPID I3C_CCC_ID(0xd, false)
#define I3C_CCC_GETBCR I3C_CCC_ID(0xe, false)
#define I3C_CCC_GETDCR I3C_CCC_ID(0xf, false)
#define I3C_CCC_GETSTATUS I3C_CCC_ID(0x10, false)
#define I3C_CCC_GETACCMST I3C_CCC_ID(0x11, false)
#define I3C_CCC_SETBRGTGT I3C_CCC_ID(0x13, false)
#define I3C_CCC_GETMXDS I3C_CCC_ID(0x14, false)
#define I3C_CCC_GETHDRCAP I3C_CCC_ID(0x15, false)
#define I3C_CCC_GETXTIME I3C_CCC_ID(0x19, false)
/* List of some Defining byte values */
#define I3C_CCC_DEF_BYTE_SYNC_TICK 0x7F
#define I3C_CCC_DEF_BYTE_DELAY_TIME 0xBF
#define I3C_CCC_DEF_BYTE_ASYNC_MODE0 0xDF
#define I3C_CCC_DEF_BYTE_ASYNC_MODE1 0xEF
#define I3C_CCC_DEF_BYTE_ASYNC_MODE2 0xF7
#define I3C_CCC_DEF_BYTE_ASYNC_MODE3 0xFB
#define I3C_CCC_DEF_BYTE_ASYNC_TRIG 0xFD
#define I3C_CCC_DEF_BYTE_TPH 0x3F
#define I3C_CCC_DEF_BYTE_TU 0x9F
#define I3C_CCC_DEF_BYTE_ODR 0x8F
/**
\brief I3C Command
*/
typedef struct _ARM_I3C_CMD {
uint8_t rw;
uint8_t cmd_id;
uint8_t def_byte;
uint16_t len;
uint8_t *data;
uint8_t addr;
} ARM_I3C_CMD;
/**
\brief I3C Status
*/
typedef struct _ARM_I3C_STATUS {
uint32_t busy :1; ///< Busy flag
uint32_t mode :1; ///< Mode: 0=Slave, 1=Master
uint32_t ibi_slv_addr :8; ///< Address of last IBI slave
uint32_t last_error_code :4; ///< Last occurred error
uint32_t defslv_cnt :8; ///< Slave count from last DEFSLVS (Applicable for Sec masters only)
uint32_t reserved :10;
} ARM_I3C_STATUS;
/**
\brief I3C device characteristics
*/
typedef struct _ARM_I3C_DEV_CHAR {
uint8_t static_addr; ///< Static address
uint8_t bcr; ///< Bus characteristics
uint8_t dcr; ///< Device characteristics
uint8_t dynamic_addr; ///< Dynamic address
} ARM_I3C_DEV_CHAR;
/**
\brief I3C Device Provisional ID info
\ The data is as per the MIPI SPEC
*/
typedef struct _ARM_I3C_SLV_PID {
uint32_t dcr :12; ///< Slave DCR
uint32_t inst_id :4; ///< Slave Instance ID
uint32_t part_id :16; ///< Slave Part ID
uint32_t pid_sel :1; ///< Slave PID selection; 0:Vendor fixed, 1: Random
uint32_t mipi_mfg_id :15; ///< Slave MIPI Manufacturer ID
uint32_t reserved :16;
} ARM_I3C_SLV_PID;
/**
\brief I3C Device Primary information
*/
typedef struct _ARM_I3C_DEV_PRIME_INFO {
ARM_I3C_DEV_CHAR dev_char; ///< Device characteristics
ARM_I3C_SLV_PID pid; ///< Device PID
} ARM_I3C_DEV_PRIME_INFO;
/**
\brief I3C Device information
\ The data is as per the MIPI SPEC
*/
typedef struct _ARM_I3C_DEVICE_INFO {
ARM_I3C_DEV_PRIME_INFO prime_info; ///< Device Primary info
uint16_t max_read_len; ///< Maximum Read length
uint16_t max_write_len; ///< Maximum Write length
uint32_t max_read_turnaround; ///< Maximum Read turnaround time
uint8_t max_read_speed; ///< Maximum Read speed
uint8_t max_write_speed; ///< Maximum write speed
uint16_t reserved;
} ARM_I3C_DEVICE_INFO;
/**
\brief I3C Device type
*/
typedef enum _ARM_I3C_DEVICE_TYPE {
ARM_I3C_DEVICE_TYPE_I3C, ///< i3c device
ARM_I3C_DEVICE_TYPE_I2C ///< legacy i2c device
} ARM_I3C_DEVICE_TYPE;
// Function documentation
/**
\fn ARM_DRIVER_VERSION GetVersion (void)
\brief Get i3c driver version.
\return \ref ARM_DRIVER_VERSION
\fn ARM_I3C_CAPABILITIES GetCapabilities (void)
\brief Get i3c driver capabilities.
\return \ref ARM_I3C_CAPABILITIES
\fn ARM_I3C_STATUS GetStatus (void)
\brief Get i3c driver status.
\return \ref ARM_I3C_STATUS
\fn ARM_I3C_DEVICE_INFO GetDeviceInfo (void)
\brief Get i3c device information.
\return \ref ARM_I3C_DEVICE_INFO
\fn int32_t Initialize (ARM_I3C_SignalEvent_t cb_event)
\brief Initialize I3C Interface.
\param[in] cb_event Pointer to \ref ARM_I3C_SignalEvent
\return \ref execution_status
\fn int32_t Uninitialize (void)
\brief De-initialize I3C Interface.
\return \ref execution_status
\fn int32_t PowerControl (ARM_POWER_STATE state)
\brief Control I3C Interface Power.
\param[in] state Power state
\return \ref execution_status
\fn int32_t MasterTransmit (uint8_t addr, const uint8_t *data, uint16_t len)
\brief Start transmitting data as I3C Master.
\param[in] addr Assigned Slave Address;
Dynamic Address for i3c, Static Address for i2c slave device
\param[in] data Pointer to buffer with data to transmit to I3C Slave
\param[in] len Number of data bytes to transmit
\return \ref execution_status
\fn int32_t MasterReceive (uint8_t addr, uint8_t *data, uint16_t len)
\brief Start receiving data as I3C Master.
\param[in] addr Assigned Slave Address;
Dynamic Address for i3c, Static Address for i2c slave device
\param[out] data Pointer to buffer for data to receive from I3C Slave
\param[in] len Number of data bytes to receive
\return \ref execution_status
\fn int32_t SlaveTransmit(struct i3c_dev *dev, const uint8_t *data, uint16_t len)
\brief Start transmitting data as I3C Slave.
\param[in] data Pointer to buffer with data to transmit to I3C master
\param[in] len Number of data bytes to transmit
\return \ref execution_status
\fn int32_t SlaveReceive(struct i3c_dev *dev, uint8_t *data, uint32_t len)
\brief Start receiving data as I3C Master.
\param[out] data Pointer to buffer for data to receive from I3C master
\param[in] len Number of data bytes to receive
\return \ref execution_status
\fn int32_t Control (uint32_t control, uint32_t arg)
\brief Control I3C mastaer and slave Interface.
\param[in] control Operation
\param[in] arg Argument of operation (optional)
\return \ref execution_status
\fn int32_t MasterSendCommand (ARM_I3C_CMD *cmd)
\brief Send a I3C Command
\param[in] cmd The I3C_CMD to be sent
\return \ref execution status
\fn int32_t MasterAssignDA (ARM_I3C_CMD *addr_cmd)
\brief Assign dynamic address to the i3c slave using SETDASA and ENTDAA
Note: Only required for i3c slave devices;
i2c slave device uses static address for communication \ref I3Cx_AttachSlvDev.
\param[in] addr_cmd Command for addressing
\return \ref execution status
\fn int32_t AttachSlvDev (const ARM_I3C_DEVICE_TYPE dev_type,
const uint8_t addr)
\brief Attach i3c/i2c device to the i3c bus.
\param[in] dev_type Device type - i3c/i2c
\param[in] addr dynamic addr of i3c device/static addr of i2c device
\return \ref execution_status
\fn int32_t Detachdev (uint8_t addr)
\brief Detach already attached i2c/i3c device from the i3c bus.
\param[in] addr static address of already attached i2c device
OR
dynamic address of already attached i3c device
\return \ref execution_status
\fn int32_t GetSlaveList (uint8_t *addr_list, uint8_t *count)
\brief Gets list of slaves already attached
\param[in] addr_list Address list of i3c slavesus
\param[in] count Count of i3c slaves
\return \ref execution_status
\fn int32_t GetSlaveDynAddr (const uint8_t static_addr, uint8_t *dynamic_addr)
\brief Detach already attached i2c/i3c device from the i3c bus.
\param[in] static_addr static address of already attached i3c device
\param[in] dynamic_addr dynamic address of already attached i3c device
\return \ref execution_status
\fn int32_t GetSlvsInfo (void* data, const uint8_t value)
\brief Gets the received Slaves information
\param[in] data ARM_I3C_DEV_CHAR/ARM_I3C_DEV_PRIME_INFO information store
\param[in] value Either Slaves count or Slave address
\return \ref execution_status
*/
typedef void (*ARM_I3C_SignalEvent_t) (uint32_t event); ///< Pointer to \ref I3C_SignalEvent : Signal I3C Event.
/**
\brief I3C Driver Capabilities.
*/
typedef struct _ARM_I3C_CAPABILITIES {
uint32_t legacy_i2c_dev : 1; ///< legacy i2c device support
uint32_t adaptive_mode : 1; ///< Slave I2C/I3C Adaptive mode support during boot up phase
uint32_t ibi : 1; ///< In-Band Interrupts support
uint32_t ibi_payload : 1; ///< In-Band Interrupt with Payload support
uint32_t sec_master : 1; ///< Secondary Master Configuration support
uint32_t hdr_ddr0 : 1; ///< HDR DDR0 mode support
uint32_t hdr_tsp : 1; ///< HDR Ternary Symbol Pure-Bus mode support
uint32_t hdr_tsl : 1; ///< HDR Ternary Symbol Legacy-Inclusive-Bus mode support
uint32_t reserved : 24; ///< Reserved (must be zero)
} ARM_I3C_CAPABILITIES;
/**
\brief Access structure of the I3C Driver.
*/
typedef struct _ARM_DRIVER_I3C {
ARM_DRIVER_VERSION (*GetVersion) (void); ///< Pointer to \ref GetVersion : Get I3C driver version.
ARM_I3C_CAPABILITIES (*GetCapabilities) (void); ///< Pointer to \ref GetCapabilities : Get I3C driver capabilities.
ARM_I3C_STATUS (*GetStatus) (void); ///< Pointer to \ref GetStatus : Get I3C driver status.
ARM_I3C_DEVICE_INFO (*GetDeviceInfo) (void); ///< Pointer to \ref GetDeviceInfo : Get I3C device information.
int32_t (*Initialize) (ARM_I3C_SignalEvent_t cb_event); ///< Pointer to \ref Initialize : Initialize I3C Interface.
int32_t (*Uninitialize) (void); ///< Pointer to \ref Uninitialize : De-initialize I3C Interface.
int32_t (*PowerControl) (ARM_POWER_STATE state); ///< Pointer to \ref PowerControl : Control I3C Interface Power.
int32_t (*MasterTransmit) (uint8_t addr, const uint8_t *data, uint16_t len); ///< Pointer to \ref MasterTransmit : Start transmitting data as I3C Master.
int32_t (*MasterReceive) (uint8_t addr, uint8_t *data, uint16_t len); ///< Pointer to \ref MasterReceive : Start receiving data as I3C Master.
int32_t (*SlaveTransmit) (const uint8_t *data, uint16_t len); ///< Pointer to \ref MasterTransmit : Start transmitting data as I3C Slave.
int32_t (*SlaveReceive) (uint8_t *data, uint16_t len); ///< Pointer to \ref SlaveReceive : Start receiving data as I3C Slave.
int32_t (*Control) (uint32_t control, uint32_t arg); ///< Pointer to \ref Control : Control I3C Master and slave Interface.
int32_t (*MasterSendCommand) (ARM_I3C_CMD *cmd); ///< Pointer to \ref MasterSendCommand : Send I3C CCC
int32_t (*MasterAssignDA) (ARM_I3C_CMD *addr_cmd); ///< Pointer to \ref MasterAssignDA : Assign I3C Dynamic Address
int32_t (*AttachSlvDev) (ARM_I3C_DEVICE_TYPE dev_type, const uint8_t addr); ///< Pointer to \ref AttachSlvDev : Attach i3c/i2c slave device to the i3c bus.
int32_t (*Detachdev) (uint8_t addr); ///< Pointer to \ref Detachdev : Detach already attached i2c/i3c device from the i3c bus.
int32_t (*GetSlaveList) (uint8_t *addr_list, uint8_t *count); ///< Pointer to \ref GetSlaveList : Fetch list of slaves attached to the bus.
int32_t (*GetSlaveDynAddr) (const uint8_t static_addr, uint8_t *dynamic_addr); ///< Pointer to \ref GetSlaveDynAddr : Fetch dynamic address of slave given with static address.
int32_t (*GetSlvsInfo) (void* data, const uint8_t value); ///< Pointer to \ref GetSlvsInfo : Fetches slave's characteristics.
} const ARM_DRIVER_I3C;
#ifdef __cplusplus
}
#endif
#endif /* DRIVER_I3C_H_ */