diff --git a/components/hal/esp32p4/include/hal/i3c_master_ll.h b/components/hal/esp32p4/include/hal/i3c_master_ll.h index 43bab471ea..d42b0d756d 100644 --- a/components/hal/esp32p4/include/hal/i3c_master_ll.h +++ b/components/hal/esp32p4/include/hal/i3c_master_ll.h @@ -27,9 +27,257 @@ extern "C" { #define I3C_LL_GET_HW(num) (((num) == 0) ? (&I3C_MST) : NULL) #define I3C_LL_MASTER_EVENT_INTR (I3C_MST_TRANSFER_COMPLETE_INT_ENA_M | I3C_MST_COMMAND_DONE_INT_ENA_M | I3C_MST_TX_DATA_BUF_THLD_INT_ENA_M | I3C_MST_RX_DATA_BUF_THLD_INT_ENA_M) -#define I3C_LL_MASTER_FIFO_LENGTH (128) +#define I3C_LL_MASTER_DATA_BUFFER_SIZE (128) // The TX Data Buffer and the RX Data Buffer can store up to 128 bytes at a time #define I3C_LL_MASTER_TRANSMIT_EVENT_INTR (I3C_MST_TX_DATA_BUF_THLD_INT_ENA_M | I3C_MST_TRANSFER_COMPLETE_INT_ENA_M | I3C_MST_COMMAND_DONE_INT_ENA_M) #define I3C_LL_MASTER_RECEIVE_EVENT_INTR (I3C_MST_RX_DATA_BUF_THLD_INT_ENA_M | I3C_MST_TRANSFER_COMPLETE_INT_ENA_M | I3C_MST_COMMAND_DONE_INT_ENA_M) +#define I3C_MASTER_LL_DEFAULT_SETUP_TIME (600) + +/** + * @brief I3C master command types + * + * This enumeration defines the types of commands that the I3C master can issue. + * Each command type corresponds to a specific purpose in the I3C communication protocol. + */ +typedef enum { + I3C_MASTER_LL_COMMAND_REGULAR = 0, ///< I3C master sends regular command + I3C_MASTER_LL_COMMAND_IMMEDIATE = 1, ///< I3C master sends immediate command + I3C_MASTER_LL_COMMAND_ADDRESS_ASSIGNMENT = 2, ///< I3C master assigns address command +} i3c_master_ll_command_type_t; + +/** + * @brief I3C master transfer directions + * + * This enumeration defines the direction of data transfer for I3C master operations. + * The transfer direction specifies whether the master sends data to or receives data from the target device. + */ +typedef enum { + I3C_MASTER_LL_TRANSFER_DIR_WRITE = 0, ///< I3C master write direction + I3C_MASTER_LL_TRANSFER_DIR_READ = 1, ///< I3C master read direction +} i3c_master_ll_transfer_direction_t; + +/** + * @brief I3C Master Command Descriptor + * + * This structure represents a command entry for the I3C master. It is used + * to define and execute different types of I3C commands, including address + * assignment, immediate commands, and regular transfers. Each entry consists + * of two parts: the low part (`cmd_l`) and the high part (`cmd_h`). + */ +typedef struct { + /** + * @brief Command Low Part (cmd_l) + * + * This union defines the command attributes for different types of I3C commands. + */ + union { + /** + * @brief Address Assignment Command + * + * Used for dynamically assigning addresses to devices on the I3C bus. + */ + struct { + uint32_t cmd_attr : 3; ///< Command type (0: regular, 1: immediate, 2: address assignment). See `i3c_master_ll_command_type_t`. + uint32_t tid : 4; ///< Transaction ID, used as an identification tag for this command. The same value shall be reflected in the Response Descriptor. + uint32_t cmd : 8; ///< Transfer Command CCC value, specifies CCC code. + uint32_t reserved15 : 1; ///< Reserved bit. + uint32_t dev_indx : 5; ///< Indicates the DAT table index for the slave device being addressed with the transfer. Static and Device addressing related information will be stored to this index in the DAT. This field is reserved in Broadcast CCC transfer. + uint32_t reserved21 : 5; ///< Reserved bits. + uint32_t dev_cnt : 4; ///< Indicates the number of devices to which Dynamic Address shall be assigned. + uint32_t roc : 1; ///< Response on Completion, controls whether the response status is sent after the successful completion of the transfer command. (0: Respond status is not required, 1: Respond status is required). + uint32_t toc : 1; ///< Terminate on Completion, controls what bus condition to issue after the transfer command completes. (0: Issue repeated start (Sr) at the end of transfer. 1: Issue Stop (P) at the end of transfer Note: This field must be set to 1 for ENTDAA. It is meaningful for SETDASA transfer) + } addr; ///< Address assignment command format. + + /** + * @brief Immediate Command + * + * It is suitable for situations where a small amount of data needs to be transferred quickly, + * and the data is directly included in the command. + */ + struct { + uint32_t cmd_attr : 3; ///< Command type (0: regular, 1: immediate, 2: address assignment). See `i3c_master_ll_command_type_t`. + uint32_t tid : 4; ///< Transaction ID, used as an identification tag for this command. The same value shall be reflected in the Response Descriptor. + uint32_t cmd : 8; ///< Transfer Command CCC value, specifies CCC code. + uint32_t cp : 1; ///< Command Present, indicates whether the CMD field is valid for CCC transfer + uint32_t dev_indx : 5; ///< Indicates the DAT table index for the slave device being addressed with the transfer. Static and Device addressing related information will be stored to this index in the DAT. This field is reserved in Broadcast CCC transfer. + uint32_t reserved21 : 2; ///< Reserved bits. + uint32_t bc : 3; ///< Byte count (number of bytes transferred in command_h). + uint32_t mode : 3; ///< Data Transfer Speed and Mode. Set the mode and speed for the I3C or I2C transfer. Interpretation of this field depends on whether the Device is in I3C Mode vs. I2C Mode (see the DEVICE field in the DAT Table entry indexed by field DEV_INDEX). + uint32_t rnw : 1; ///< Identifies the direction of this transfer (1: read, 0: write). See `i3c_master_ll_transfer_direction_t`. + uint32_t roc : 1; ///< Response on Completion, controls whether the response status is sent after the successful completion of the transfer command. (0: Respond status is not required, 1: Respond status is required). + uint32_t toc : 1; ///< Terminate on Completion, controls what bus condition to issue after the transfer command completes. (0: Issue repeated start at the end of transfer. 1: Issue Stop (P) at the end of transfer Note: This field must be set to 1 for ENTDAA. It is meaningful for SETDASA transfer) + } immediate; ///< Immediate command format. + + /** + * @brief Regular Transfer Command + * + * Used for general CCC transfer and private data transfer + */ + struct { + uint32_t cmd_attr : 3; ///< Command type (0: regular, 1: immediate, 2: address assignment). See `i3c_master_ll_command_type_t`. + uint32_t tid : 4; ///< Transaction ID, used as an identification tag for this command. The same value shall be reflected in the Response Descriptor. + uint32_t cmd : 8; ///< Transfer Command CCC value, specifies CCC code. + uint32_t cp : 1; ///< Command Present, indicates whether the CMD field is valid for CCC transfer + uint32_t dev_indx : 5; ///< Indicates the DAT table index for the slave device being addressed with the transfer. Static and Device addressing related information will be stored to this index in the DAT. This field is reserved in Broadcast CCC transfer. + uint32_t reserved21 : 5; ///< Reserved bits. + uint32_t mode : 3; ///< Data Transfer Speed and Mode. Set the mode and speed for the I3C or I2C transfer. Interpretation of this field depends on whether the Device is in I3C Mode vs. I2C Mode (see the DEVICE field in the DAT Table entry indexed by field DEV_INDEX). + uint32_t rnw : 1; ///< Identifies the direction of this transfer (1: read, 0: write). See `i3c_master_ll_transfer_direction_t`. + uint32_t roc : 1; ///< Response on Completion, controls whether the response status is sent after the successful completion of the transfer command. (0: Respond status is not required, 1: Respond status is required). + uint32_t toc : 1; ///< Terminate on Completion, controls what bus condition to issue after the transfer command completes. (0: Issue repeated start at the end of transfer. 1: Issue Stop (P) at the end of transfer Note: This field must be set to 1 for ENTDAA. It is meaningful for SETDASA transfer) + } regular; ///< Regular transfer command format. + + /** + * @brief Raw Value Access + * + * Provides direct access to the 32-bit value of the command. + */ + uint32_t val; ///< Raw 32-bit value of the command. + } cmd_l; ///< Low part of the command. + + /** + * @brief Command High Part (cmd_h) + * + * This union defines additional attributes for different types of I3C commands. + */ + union { + /** + * @brief Address Assignment Command High Part + * + * No additional data for address assignment commands. + */ + struct { + uint32_t reserved0 : 32; ///< Reserved bits. + } addr; + + /** + * @brief Immediate Command High Part + * + * Provides up to four bytes of data for the immediate command. + */ + struct { + uint32_t byte1 : 8; ///< First byte of data. + uint32_t byte2 : 8; ///< Second byte of data. + uint32_t byte3 : 8; ///< Third byte of data. + uint32_t byte4 : 8; ///< Fourth byte of data. + } immediate; + + /** + * @brief Regular Transfer Command High Part + * + * Defines the data length for regular transfer commands. + */ + struct { + uint32_t reserved0 : 16; ///< Reserved bits. + uint32_t dl : 16; ///< Data length (number of bytes to transfer). + } regular; + + /** + * @brief Raw Value Access + * + * Provides direct access to the 32-bit value of the high part of the command. + */ + uint32_t val; ///< Raw 32-bit value of the high part of the command. + } cmd_h; ///< High part of the command. +} i3c_master_ll_command_descriptor_t; + +/** + * @brief I3C Master Error State Enumeration + */ +typedef enum { + I3C_MASTER_LL_NO_ERROR = 0, ///< Indicates that the I3C master encountered no errors. + I3C_MASTER_LL_READ_LENGTH_MISMATCH = 3, ///< The length of data read from the slave device does not match the expected or requested length. + I3C_MASTER_LL_BROADCAST_ADDRESS_NACK_ERROR = 4, ///< Broadcast Address NACK Error. + I3C_MASTER_LL_ADDRESS_NACK_OR_DYNAMIC_ADDRESS_NACK = 5, ///< Address NACK or Dynamic Address NACK. + I3C_MASTER_LL_BUFFER_RX_OVERFLOW_TX_UNDERFLOW = 6, ///< Buffer RX Overflow or TX Underflow. + I3C_MASTER_LL_I2C_SLAVE_WRITE_DATA_NACK_ERROR = 9, ///< I2C Slave Write Data NACK Error. +} i3c_master_ll_error_state_t; + +/** + * @brief I3C master response data + * + * This union represents the response data structure used by the I3C master. + * It includes fields for data length, transaction ID, and error status. + */ +typedef union { + struct { + uint32_t dl : 16; ///< Data Length. For Write Transfer: Remaining data length (in bytes). + ///< For Read Transfer: Received data length (in bytes). + ///< For Address Assignment: Remaining Devices count. + uint32_t reserved16 : 8; + uint32_t tid : 4; ///< Identification tag for the command. This value shall match one of commands sent on the bus. + uint32_t err_sts : 4; ///< Error state: A 4-bit field indicating the error state of the transaction. See `i3c_master_ll_error_state_t` + }; + uint32_t val; +} i3c_master_ll_response_descriptor_t; + +/** + * @brief I3C master operating mode + * + * This enumeration defines the operating modes for an I3C master. + * It can either operate in the I3C protocol mode or be backward-compatible with I2C devices. + */ +typedef enum { + I3C_MASTER_LL_MODE_I3C = 0, ///< I3C works under I3C mode + I3C_MASTER_LL_MODE_I2C = 1, ///< I3C works under I2C mode +} i3c_master_ll_mode_t; + +/** + * @brief I3C Device address descriptor + * + * This structure represents a single entry in the I3C master address table. + * It is used to store and manage the static and dynamic addresses of devices + * on the I3C bus in different modes. + */ +typedef union { + /** + * @brief I3C device with static address + * + * Use SETDASA (Set Dynamic Address from Static Address) command to assign a dynamic address to a device based on its static address. + */ + struct { + uint32_t static_addr : 7; ///< Static Address of the I3C Target. + uint32_t reserved7 : 9; ///< Reserved bits. + uint32_t dynamic_addr : 7; ///< For SETDASA command, it is the Dynamic Address to be assigned to the I3C device with Static Address. + ///< For other transfer, it is the Dynamic Address used as the targets’ address. + uint32_t reserved24 : 6; ///< Reserved bits. + uint32_t dnrc : 2; ///< Device NACK Retry Counter. It decides the number of retry when current transfer nacked. + uint32_t mode : 1; ///< Mode indicator, must be I3C mode (0). See `i3c_master_ll_mode_t`. + } i3c_static; + + /** + * @brief I3C device with dynamic address + * + * Use ENTDAA (Enter Dynamic Address Assignment) command is used to dynamically assign addresses to devices without requiring a static address. + */ + struct { + uint32_t reserved0 : 16; ///< Reserved bits. + uint32_t dynamic_addr : 7; ///< For ENTDAA command, it is the Dynamic Address to be assigned to the I3C device without Static Address. + ///< For other transfer, it is the Dynamic Address used as the targets’ address. + uint32_t par : 1; ///< Parity Bit of 7-bit Dynamic Address. + uint32_t reserved24 : 5; ///< Reserved bits. + uint32_t dnrc : 2; ///< Device NACK Retry Counter. It decides the number of retry when current transfer nacked. + uint32_t mode : 1; ///< Mode indicator, must be I3C mode (0). See `i3c_master_ll_mode_t`. + } dynamic; + + /** + * @brief I2C devices with static address + * + * This mode is used to represent devices operating in I2C mode. + */ + struct { + uint32_t static_addr : 7; ///< Static address of the I2C device (7-bit). + uint32_t reserved7 : 22; ///< Reserved bits. + uint32_t dnrc : 2; ///< Device NACK Retry Counter. It decides the number of retry when the current transfer is nacked. + uint32_t mode : 1; ///< Mode indicator, must be I2C mode (1). See `i3c_master_ll_mode_t`. + } i2c_static; + + /** + * @brief Raw Value + * + * This provides direct access to the raw 32-bit value of the entry, + * allowing for low-level manipulation or initialization. + */ + uint32_t val; ///< Raw 32-bit value of the address table entry. +} i3c_master_ll_device_address_descriptor_t; typedef enum { I3C_MASTER_LL_FIFO_WM_LENGTH_2 = 0x0, @@ -37,7 +285,7 @@ typedef enum { I3C_MASTER_LL_FIFO_WM_LENGTH_8 = 0x2, I3C_MASTER_LL_FIFO_WM_LENGTH_16 = 0x3, I3C_MASTER_LL_FIFO_WM_LENGTH_31 = 0x4, -} i3c_master_ll_fifo_wm_enum_t; +} i3c_master_ll_fifo_wm_t; /** * @brief Set the clock source for the I3C master @@ -47,12 +295,9 @@ typedef enum { */ static inline void i3c_master_ll_set_source_clk(i3c_mst_dev_t *hw, i3c_master_clock_source_t src_clk) { + (void)hw; // Suppress unused parameter warning // src_clk : (1) for PLL_F160M, (0) for XTAL - if (hw == &I3C_MST) { - HP_SYS_CLKRST.peri_clk_ctrl119.reg_i3c_mst_clk_src_sel = (src_clk == I3C_MASTER_CLK_SRC_PLL_F160M) ? 1 : 0; - } else { - HAL_ASSERT(false); - } + HP_SYS_CLKRST.peri_clk_ctrl119.reg_i3c_mst_clk_src_sel = (src_clk == I3C_MASTER_CLK_SRC_PLL_F160M) ? 1 : 0; } /// use a macro to wrap the function, force the caller to use it in a critical section @@ -66,10 +311,11 @@ static inline void i3c_master_ll_set_source_clk(i3c_mst_dev_t *hw, i3c_master_cl * @param addr_table Device address table * @param device_number Number of devices */ -static inline void i3c_master_ll_set_address_device_table(i3c_mst_dev_t *hw, i3c_master_address_table_t *addr_table, size_t device_number) +__attribute__((always_inline)) +static inline void i3c_master_ll_set_device_address_table(i3c_mst_dev_t *hw, i3c_master_ll_device_address_descriptor_t *addr_table, size_t device_number) { for (int i = 0; i < device_number; i++) { - I3C_MST_MEM.dev_addr_table[i].val = addr_table[i].dat.val; + I3C_MST_MEM.dev_addr_table[i].val = addr_table[i].val; } } @@ -81,11 +327,8 @@ static inline void i3c_master_ll_set_address_device_table(i3c_mst_dev_t *hw, i3c */ static inline void i3c_master_ll_enable_bus_clock(i3c_mst_dev_t *hw, bool enable) { - if (hw == &I3C_MST) { - HP_SYS_CLKRST.soc_clk_ctrl2.reg_i3c_mst_apb_clk_en = enable; - } else { - HAL_ASSERT(false); - } + (void)hw; // Suppress unused parameter warning + HP_SYS_CLKRST.soc_clk_ctrl2.reg_i3c_mst_apb_clk_en = enable; } /// use a macro to wrap the function, force the caller to use it in a critical section @@ -100,11 +343,8 @@ static inline void i3c_master_ll_enable_bus_clock(i3c_mst_dev_t *hw, bool enable */ static inline void i3c_master_ll_enable_controller_clock(i3c_mst_dev_t *hw, bool enable) { - if (hw == &I3C_MST) { - HP_SYS_CLKRST.peri_clk_ctrl119.reg_i3c_mst_clk_en = enable; - } else { - HAL_ASSERT(false); - } + (void)hw; // Suppress unused parameter warning + HP_SYS_CLKRST.peri_clk_ctrl119.reg_i3c_mst_clk_en = enable; } /// use a macro to wrap the function, force the caller to use it in a critical section @@ -118,12 +358,9 @@ static inline void i3c_master_ll_enable_controller_clock(i3c_mst_dev_t *hw, bool */ static inline void i3c_master_ll_reset_register(i3c_mst_dev_t *hw) { - if (hw == &I3C_MST) { - HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_i3cmst = 1; - HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_i3cmst = 0; - } else { - HAL_ASSERT(false); - } + (void)hw; // Suppress unused parameter warning + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_i3cmst = 1; + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_i3cmst = 0; } /// use a macro to wrap the function, force the caller to use it in a critical section @@ -137,7 +374,8 @@ static inline void i3c_master_ll_reset_register(i3c_mst_dev_t *hw) * @param command_buf Command buffer * @param command_num Number of commands */ -static inline void i3c_master_ll_set_command(i3c_mst_dev_t *hw, i3c_master_command_table_t *command_buf, size_t command_num) +__attribute__((always_inline)) +static inline void i3c_master_ll_set_command(i3c_mst_dev_t *hw, i3c_master_ll_command_descriptor_t *command_buf, size_t command_num) { for (int i = 0; i < command_num; i++) { I3C_MST_MEM.command_buf_port.reg_command = command_buf[i].cmd_l.val; @@ -150,12 +388,26 @@ static inline void i3c_master_ll_set_command(i3c_mst_dev_t *hw, i3c_master_comma * * @param hw I3C master hardware instance */ +__attribute__((always_inline)) static inline void i3c_master_ll_start_transaction(i3c_mst_dev_t *hw) { hw->device_ctrl.reg_trans_start = 1; hw->device_ctrl.reg_trans_start = 0; } +/** + * @brief Inject the broadcast address in private transfer and legacy I2C transfer + * + * @note In-Band Interrupts driven from slaves may not win address arbitration if the broadcast address is not injected. + * + * @param hw I3C master hardware instance + * @param enable Whether to enable or disable the broadcast address injection + */ +static inline void i3c_master_ll_inject_broadcast_address_head(i3c_mst_dev_t *hw, bool enable) +{ + hw->device_ctrl.reg_ba_include = enable ? 1 : 0; +} + /** * @brief Set the open-drain timing for I3C master * @@ -177,6 +429,7 @@ static inline void i3c_master_ll_set_i3c_open_drain_timing(i3c_mst_dev_t *hw, ui * @param clock_source_freq Clock source frequency * @param scl_freq SCL frequency */ +__attribute__((always_inline)) static inline void i3c_master_ll_set_i2c_fast_mode_timing(i3c_mst_dev_t *hw, uint32_t clock_source_freq, uint32_t scl_freq) { uint32_t period_cnt = clock_source_freq / scl_freq / 2; @@ -185,12 +438,26 @@ static inline void i3c_master_ll_set_i2c_fast_mode_timing(i3c_mst_dev_t *hw, uin } /** - * @brief Set the push-pull timing for I3C master - * + * @brief Set the fast+ mode timing for I2C master * @param hw I3C master hardware instance * @param clock_source_freq Clock source frequency * @param scl_freq SCL frequency */ +__attribute__((always_inline)) +static inline void i3c_master_ll_set_i2c_fast_plus_mode_timing(i3c_mst_dev_t *hw, uint32_t clock_source_freq, uint32_t scl_freq) +{ + uint32_t period_cnt = clock_source_freq / scl_freq / 2; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->scl_i2c_fmp_time, reg_i2c_fmp_high_period, (period_cnt - 1)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->scl_i2c_fmp_time, reg_i2c_fmp_low_period, (period_cnt - 1)); +} + +/** +* @brief Set the push-pull timing for I3C master +* +* @param hw I3C master hardware instance +* @param clock_source_freq Clock source frequency +* @param scl_freq SCL frequency +*/ static inline void i3c_master_ll_set_i3c_push_pull_timing(i3c_mst_dev_t *hw, uint32_t clock_source_freq, uint32_t scl_freq) { uint32_t period_cnt = clock_source_freq / scl_freq / 2; @@ -250,11 +517,11 @@ static inline void i3c_master_ll_set_stop_setup_time(i3c_mst_dev_t *hw, uint32_t * @brief Get the data byte count from the I3C master * * @param hw I3C master hardware instance - * @param count Pointer to store the data byte count + * @return Number of data bytes, meaning differently according to different transfer */ -static inline void i3c_master_ll_get_data_byte_count(i3c_mst_dev_t *hw, uint32_t *count) +static inline uint32_t i3c_master_ll_get_data_byte_count(i3c_mst_dev_t *hw) { - *count = I3C_MST.present_state1.data_byte_cnt; + return hw->present_state1.data_byte_cnt; } /** @@ -264,6 +531,7 @@ static inline void i3c_master_ll_get_data_byte_count(i3c_mst_dev_t *hw, uint32_t * @param data Pointer to store the read data * @param length Length of data to read */ +__attribute__((always_inline)) static inline void i3c_master_ll_read_rx_port(i3c_mst_dev_t *hw, uint8_t *data, size_t length) { uint32_t data_word = 0; @@ -281,7 +549,7 @@ static inline void i3c_master_ll_read_rx_port(i3c_mst_dev_t *hw, uint8_t *data, } /** - * @brief Write data to the TX port of the I3C master + * @brief Write data to the TX buffer via FIFO port * * @param hw I3C master hardware instance * @param data Pointer to the data to write @@ -371,6 +639,7 @@ static inline void i3c_master_ll_get_intr_mask(i3c_mst_dev_t *dev, uint32_t *int * @param dev I3C master hardware instance * @return TX FIFO empty count */ +__attribute__((always_inline)) static inline uint8_t i3c_master_ll_get_tx_fifo_empty_count(i3c_mst_dev_t *dev) { return dev->data_buffer_status_level.tx_data_buf_empty_cnt; @@ -382,6 +651,7 @@ static inline uint8_t i3c_master_ll_get_tx_fifo_empty_count(i3c_mst_dev_t *dev) * @param dev I3C master hardware instance * @return RX FIFO full count */ +__attribute__((always_inline)) static inline uint8_t i3c_master_ll_get_rx_fifo_full_count(i3c_mst_dev_t *dev) { return dev->data_buffer_status_level.rx_data_buf_cnt; @@ -393,7 +663,7 @@ static inline uint8_t i3c_master_ll_get_rx_fifo_full_count(i3c_mst_dev_t *dev) * @param dev I3C master hardware instance * @param fifo_wm FIFO watermark threshold */ -static inline void i3c_master_ll_set_tx_data_fifo_wm_threshold(i3c_mst_dev_t *dev, i3c_master_ll_fifo_wm_enum_t fifo_wm) +static inline void i3c_master_ll_set_tx_data_fifo_wm_threshold(i3c_mst_dev_t *dev, i3c_master_ll_fifo_wm_t fifo_wm) { dev->data_buffer_thld_ctrl.reg_tx_data_buf_thld = fifo_wm; } @@ -404,7 +674,7 @@ static inline void i3c_master_ll_set_tx_data_fifo_wm_threshold(i3c_mst_dev_t *de * @param dev I3C master hardware instance * @param fifo_wm FIFO watermark threshold */ -static inline void i3c_master_ll_set_rx_data_fifo_wm_threshold(i3c_mst_dev_t *dev, i3c_master_ll_fifo_wm_enum_t fifo_wm) +static inline void i3c_master_ll_set_rx_data_fifo_wm_threshold(i3c_mst_dev_t *dev, i3c_master_ll_fifo_wm_t fifo_wm) { dev->data_buffer_thld_ctrl.reg_rx_data_buf_thld = fifo_wm; } @@ -435,11 +705,56 @@ static inline void i3c_master_ll_enable_rx_by_dma(i3c_mst_dev_t *dev, bool enabl * @brief Get the response buffer value from the I3C master * * @param dev I3C master hardware instance - * @return Response buffer value + * @return Response data */ -static inline uint32_t i3c_master_ll_get_response_buffer_value(i3c_mst_dev_t *dev) +__attribute__((always_inline)) +static inline i3c_master_ll_response_descriptor_t i3c_master_ll_get_response_data(i3c_mst_dev_t *dev) { - return I3C_MST_MEM.response_buf_port.response; + return (i3c_master_ll_response_descriptor_t)(I3C_MST_MEM.response_buf_port.val); +} + +/** + * @brief Set the init value of dct_index, which points to the entry in the DCT table + * + * @param dev I3C master hardware instance + * @param index DCT index value + */ +static inline void i3c_master_ll_set_init_dct_index(i3c_mst_dev_t *dev, uint32_t index) +{ + dev->device_table.reg_dct_daa_init_index = index; +} + +/** + * @brief Set the init value of dat_index, which points to the entry in the DAT table + * + * @param dev I3C master hardware instance + * @param index DAT index value + */ +static inline void i3c_master_ll_set_init_dat_index(i3c_mst_dev_t *dev, uint32_t index) +{ + dev->device_table.reg_dat_daa_init_index = index; +} + +/** + * @brief Get the current DCT index + * + * @param dev I3C master hardware instance + * @return Current DCT index + */ +static inline uint32_t i3c_master_ll_get_current_dct_index(i3c_mst_dev_t *dev) +{ + return dev->device_table.present_dct_index; +} + +/** + * @brief Get the current DAT index + * + * @param dev I3C master hardware instance + * @return Current DAT index + */ +static inline uint32_t i3c_master_ll_get_current_dat_index(i3c_mst_dev_t *dev) +{ + return dev->device_table.present_dat_index; } #ifdef __cplusplus diff --git a/components/hal/include/hal/i3c_master_types.h b/components/hal/include/hal/i3c_master_types.h index a6a208e400..3e267b9557 100644 --- a/components/hal/include/hal/i3c_master_types.h +++ b/components/hal/include/hal/i3c_master_types.h @@ -6,239 +6,14 @@ #pragma once -#ifdef __cplusplus -extern "C" { -#endif - #include #include #include "soc/soc_caps.h" #include "soc/clk_tree_defs.h" -#include "hal/hal_utils.h" -/** - * @brief I3C Master Command Table Entry - * - * This structure represents a command entry for the I3C master. It is used - * to define and execute different types of I3C commands, including address - * assignment, immediate commands, and regular transfers. Each entry consists - * of two parts: the low part (`cmd_l`) and the high part (`cmd_h`). - */ -typedef struct { - /** - * @brief Command Low Part (cmd_l) - * - * This union defines the command attributes for different types of I3C commands. - */ - union { - /** - * @brief Address Assignment Command - * - * Used for dynamically assigning addresses to devices on the I3C bus. - */ - struct { - uint32_t cmd_attr : 3; ///< Command type (0: regular, 1: immediate, 2: address assignment). - uint32_t tid : 4; ///< Transaction ID, used as an identification tag for this command. The same value shall be reflected in the Response Descriptor - uint32_t cmd : 8; ///< Transfer Command CCC value, specifies CCC code. - uint32_t reserved15 : 1; ///< Reserved bit. - uint32_t dev_indx : 5; ///< Indicates the DAT table index for the slave device being addressed with the transfer. Static and Device addressing related information will be stored to this index in the DAT. This field is reserved in Broadcast CCC transfer. - uint32_t reserved21 : 5; ///< Reserved bits. - uint32_t dev_cnt : 4; ///< Indicates the number of devices to which Dynamic Address shall be assigned. - uint32_t roc : 1; ///< Response on Completion, controls whether the response status is sent after the successful completion of the transfer command. (0: Respond status is not required, 1: Respond status is required). - uint32_t toc : 1; ///< Terminate on Completion, controls what bus condition to issue after the transfer command completes. (0: Issue repeated start at the end of transfer. 1: Issue Stop (P) at the end of transfer Note: This field must be set to 1 for ENTDAA. It is meaningful for SETDASA transfer) - } addr; ///< Address assignment command format. - - /** - * @brief Immediate Command - * - * Executes a command with immediate effect, typically for control or configuration purposes. - */ - struct { - uint32_t cmd_attr : 3; ///< Command type (0: regular, 1: immediate, 2: address assignment). - uint32_t tid : 4; ///< Transaction ID, used as an identification tag for this command. The same value shall be reflected in the Response Descriptor - uint32_t cmd : 8; ///< Transfer Command CCC value, specifies CCC code. - uint32_t cp : 1; ///< Command Present, indicates whether the CMD field is valid for CCC transfer - uint32_t dev_indx : 5; ///< Indicates the DAT table index for the slave device being addressed with the transfer. Static and Device addressing related information will be stored to this index in the DAT. This field is reserved in Broadcast CCC transfer. - uint32_t reserved21 : 2; ///< Reserved bits. - uint32_t bc : 3; ///< Byte count (number of bytes transferred in command_h). - uint32_t mode : 3; ///< Data Transfer Speed and Mode. Set the mode and speed for the I3C or I2C transfer. Interpretation of this field depends on whether the Device is in I3C Mode vs. I2C Mode (see the DEVICE field in the DAT Table entry indexed by field DEV_INDEX). - uint32_t rnw : 1; ///< Identifies the direction of this transfer (1: read, 0: write). - uint32_t roc : 1; ///< Response on Completion, controls whether the response status is sent after the successful completion of the transfer command. (0: Respond status is not required, 1: Respond status is required). - uint32_t toc : 1; ///< Terminate on Completion, controls what bus condition to issue after the transfer command completes. (0: Issue repeated start at the end of transfer. 1: Issue Stop (P) at the end of transfer Note: This field must be set to 1 for ENTDAA. It is meaningful for SETDASA transfer) - } immediate; ///< Immediate command format. - - /** - * @brief Regular Transfer Command - * - * Used for standard data transfers on the I3C bus. - */ - struct { - uint32_t cmd_attr : 3; ///< Command type (0: regular, 1: immediate, 2: address assignment). - uint32_t tid : 4; ///< Transaction ID, used as an identification tag for this command. The same value shall be reflected in the Response Descriptor - uint32_t cmd : 8; ///< Transfer Command CCC value, specifies CCC code. - uint32_t cp : 1; ///< Command Present, indicates whether the CMD field is valid for CCC transfer - uint32_t dev_indx : 5; ///< Indicates the DAT table index for the slave device being addressed with the transfer. Static and Device addressing related information will be stored to this index in the DAT. This field is reserved in Broadcast CCC transfer. - uint32_t reserved21 : 5; ///< Reserved bits. - uint32_t mode : 3; ///< Data Transfer Speed and Mode. Set the mode and speed for the I3C or I2C transfer. Interpretation of this field depends on whether the Device is in I3C Mode vs. I2C Mode (see the DEVICE field in the DAT Table entry indexed by field DEV_INDEX). - uint32_t rnw : 1; ///< Identifies the direction of this transfer (1: read, 0: write). - uint32_t roc : 1; ///< Response on Completion, controls whether the response status is sent after the successful completion of the transfer command. (0: Respond status is not required, 1: Respond status is required). - uint32_t toc : 1; ///< Terminate on Completion, controls what bus condition to issue after the transfer command completes. (0: Issue repeated start at the end of transfer. 1: Issue Stop (P) at the end of transfer Note: This field must be set to 1 for ENTDAA. It is meaningful for SETDASA transfer) - } regular; ///< Regular transfer command format. - - /** - * @brief Raw Value Access - * - * Provides direct access to the 32-bit value of the command. - */ - uint32_t val; ///< Raw 32-bit value of the command. - } cmd_l; ///< Low part of the command. - - /** - * @brief Command High Part (cmd_h) - * - * This union defines additional attributes for different types of I3C commands. - */ - union { - /** - * @brief Address Assignment Command High Part - * - * No additional data for address assignment commands. - */ - struct { - uint32_t reserved0 : 32; ///< Reserved bits. - } addr; - - /** - * @brief Immediate Command High Part - * - * Provides up to four bytes of data for the immediate command. - */ - struct { - uint32_t byte1 : 8; ///< First byte of data. - uint32_t byte2 : 8; ///< Second byte of data. - uint32_t byte3 : 8; ///< Third byte of data. - uint32_t byte4 : 8; ///< Fourth byte of data. - } immediate; - - /** - * @brief Regular Transfer Command High Part - * - * Defines the data length for regular transfer commands. - */ - struct { - uint32_t reserved0 : 16; ///< Reserved bits. - uint32_t dl : 16; ///< Data length (number of bytes to transfer). - } regular; - - /** - * @brief Raw Value Access - * - * Provides direct access to the 32-bit value of the high part of the command. - */ - uint32_t val; ///< Raw 32-bit value of the high part of the command. - } cmd_h; ///< High part of the command. -} i3c_master_command_table_t; - -/** - * @brief I3C Master Address Table Entry - * - * This structure represents a single entry in the I3C master address table. - * It is used to store and manage the static and dynamic addresses of devices - * on the I3C bus in different modes, such as SETDASA, ENTDAA, or I2C compatibility. - */ -typedef struct { - union { - /** - * @brief SETDASA Mode - * - * The SETDASA (Set Dynamic Address from Static Address) mode is used - * to assign a dynamic address to a device based on its static address. - */ - struct { - uint32_t static_addr : 7; ///< Static Address of the I3C Target. - uint32_t reserved7 : 9; ///< Reserved bits. - uint32_t dynamic_addr : 8; ///< If used for address assignment by SETDASA CCC, it is the Dynamic Address to be assigned to the I3C device with Static Address. For other transfer, the Dynamic Address is used as the targets’ address. - uint32_t reserved24 : 5; ///< Reserved bits. - uint32_t d : 2; ///< Device NACK Retry Counter. It decides the number of retry when current transfer nacked. - uint32_t mode : 1; ///< Mode indicator (I3C mode = 0). - } setdasa; - - /** - * @brief ENTDAA Mode - * - * The ENTDAA (Enter Dynamic Address Assignment) mode is used for - * dynamically assigning addresses to devices without requiring a static address. - */ - struct { - uint32_t reserved0 : 16; ///< Reserved bits. - uint32_t dynamic_addr : 7; ///< If used for address assignment by ENTDAA CCC, it is the Dynamic Address to be assigned to the I3C device without Static Address. For other transfer, the Dynamic Address is used as the targets’ address. - uint32_t dyn : 1; ///< Parity Bit of 7-bit Dynamic Address. - uint32_t reserved24 : 5; ///< Reserved bits. - uint32_t d : 2; ///< Device NACK Retry Counter. It decides the number of retry when current transfer nacked. - uint32_t mode : 1; ///< Mode indicator (I3C mode = 0). - } entdaa; - - /** - * @brief I2C Compatibility Mode - * - * This mode is used to represent devices operating in I2C mode. - * Only the static address is relevant in this case. - */ - struct { - uint32_t static_addr : 7; ///< Static address of the I2C device (7-bit). - uint32_t reserved7 : 22; ///< Reserved bits. - uint32_t d : 2; ///< Device NACK Retry Counter. It decides the number of retry when the current transfer is nacked. - uint32_t mode : 1; ///< Mode indicator (I2C mode = 1). - } i2c; - - /** - * @brief Raw Value - * - * This provides direct access to the raw 32-bit value of the entry, - * allowing for low-level manipulation or initialization. - */ - uint32_t val; ///< Raw 32-bit value of the address table entry. - } dat; ///< Union of different mode representations. -} i3c_master_address_table_t; - -/** - * @brief I3C master command types - * - * This enumeration defines the types of commands that the I3C master can issue. - * Each command type corresponds to a specific purpose in the I3C communication protocol. - */ -typedef enum { - I3C_MASTER_REGULAR_COMMAND = 0, ///< I3C master sends regular command - I3C_MASTER_IMMEDIATE_COMMAND = 1, ///< I3C master sends immediate command - I3C_MASTER_ADDRESS_ASSIGNMENT_COMMAND = 2, ///< I3C master assigns address command -} i3c_master_command_type_t; - -/** - * @brief I3C master transfer directions - * - * This enumeration defines the direction of data transfer for I3C master operations. - * The transfer direction specifies whether the master sends data to or receives data from the target device. - */ -typedef enum { - I3C_MASTER_WRITE_TRANSFER = 0, ///< I3C master write direction - I3C_MASTER_READ_TRANSFER = 1, ///< I3C master read direction -} i3c_master_transfer_direction_t; - -/** - * @brief I3C master response data - * - * This union represents the response data structure used by the I3C master. - * It includes fields for data length, transaction ID, and error status. - */ -typedef union { - struct { - uint32_t dl : 16; ///< Data Length - uint32_t reserved16 : 8; - uint32_t tid : 4; ///< Transaction ID, used as an identification tag for this command. The same value shall be reflected in the Response Descriptor - uint32_t err_sts : 4; ///< Error state: A 4-bit field indicating the error state of the transaction. - }; - uint32_t val; -} i3c_master_response_data_t; +#ifdef __cplusplus +extern "C" { +#endif #if SOC_I3C_MASTER_SUPPORTED /** diff --git a/components/soc/esp32p4/register/soc/i3c_mst_mem_struct.h b/components/soc/esp32p4/register/soc/i3c_mst_mem_struct.h index 3f9a7fea3f..f972096e2f 100644 --- a/components/soc/esp32p4/register/soc/i3c_mst_mem_struct.h +++ b/components/soc/esp32p4/register/soc/i3c_mst_mem_struct.h @@ -135,39 +135,19 @@ typedef union { */ typedef union { struct { - /** reg_dat_devn_static_addr : R/W; bitpos: [6:0]; default: 0; + /** dat_data : WO; bitpos: [31:0]; default: 0; * NA */ - uint32_t reg_dat_devn_static_addr:7; - uint32_t reserved_7:9; - /** reg_dat_dev12_dynamic_addr : R/W; bitpos: [23:16]; default: 0; - * Device Dynamic Address with parity, The MSB,bit[23], should be programmed with - * parity of dynamic address. - */ - uint32_t reg_dat_devn_dynamic_addr:8; - uint32_t reserved_24:5; - /** reg_dat_dev12_nack_retry_cnt : R/W; bitpos: [30:29]; default: 0; - * This field is used to set the Device NACK Retry count for the particular device. If - * the Device NACK's for the device address, the controller automatically retries the - * same device until this count expires. If the Slave does not ACK for the mentioned - * number of retries, then controller generates an error response and move to the Halt - * state. - */ - uint32_t reg_dat_devn_nack_retry_cnt:2; - /** reg_dat_dev12_i2c : R/W; bitpos: [31]; default: 0; - * Legacy I2C device or not. This bit should be set to 1 if the device is a legacy I2C - * device. - */ - uint32_t reg_dat_devn_i2c:1; + uint32_t dat_data:32; }; uint32_t val; } i3c_mst_mem_dev_addr_tablen_loc_reg_t; typedef struct { + volatile uint32_t loc0; volatile uint32_t loc1; volatile uint32_t loc2; volatile uint32_t loc3; - volatile uint32_t loc4; } i3c_mst_mem_dev_char_tablen_reg_t; typedef struct {